@bridge_gpt/mcp-server 0.2.38 → 0.2.39

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.
Files changed (85) hide show
  1. package/README.md +189 -14
  2. package/build/agent-capabilities/probe-context.js +2 -1
  3. package/build/agent-launchers/claude-executor-adapter.js +392 -0
  4. package/build/agent-launchers/executor-adapter-inspection.js +163 -0
  5. package/build/agent-launchers/executor-adapter-registry.js +90 -0
  6. package/build/agent-launchers/executor-adapter.js +136 -0
  7. package/build/agent-registry.js +28 -0
  8. package/build/agents.generated.js +1 -1
  9. package/build/claude-login.js +85 -0
  10. package/build/claude-user-config-doctor.js +59 -33
  11. package/build/commands.generated.js +12 -11
  12. package/build/conduct-epic/bridge-client.js +345 -0
  13. package/build/conduct-epic/checkpoint-store.js +423 -0
  14. package/build/conduct-epic/cli.js +1732 -0
  15. package/build/conduct-epic/lock.js +302 -0
  16. package/build/conduct-epic/pr-state.js +197 -0
  17. package/build/conduct-epic/spawn.js +101 -0
  18. package/build/conductor/bridge-api-client.js +37 -2
  19. package/build/conductor/doctor.js +11 -1
  20. package/build/conductor/install-doctor.js +184 -10
  21. package/build/conductor-bin.js +7 -7
  22. package/build/credential-store.js +10 -4
  23. package/build/credentials-cli.js +34 -19
  24. package/build/docs.generated.js +1 -1
  25. package/build/doctor.js +579 -88
  26. package/build/executor/agent-identity.js +32 -0
  27. package/build/executor/cli.js +50 -39
  28. package/build/executor/deps.js +15 -1
  29. package/build/executor/env.js +56 -45
  30. package/build/executor/index.js +9 -1
  31. package/build/executor/install-preflight.js +138 -0
  32. package/build/executor/job-errors.js +200 -0
  33. package/build/executor/job-runner.js +619 -268
  34. package/build/executor/observation.js +165 -0
  35. package/build/executor/permissions.js +163 -36
  36. package/build/executor/platform.js +54 -0
  37. package/build/executor/preflight.js +175 -67
  38. package/build/executor/process.js +39 -7
  39. package/build/executor/runner.js +19 -0
  40. package/build/executor/service-lifecycle.js +269 -0
  41. package/build/executor/service-unit.js +121 -12
  42. package/build/executor/stale-artifacts.js +70 -0
  43. package/build/executor/test-clock.js +188 -24
  44. package/build/executor/worker-command.js +22 -58
  45. package/build/executor/worker-log.js +82 -0
  46. package/build/executor/worktree-lock.js +264 -0
  47. package/build/index.js +527 -357
  48. package/build/install-bridge-conductor.js +376 -38
  49. package/build/install-bridge.js +414 -114
  50. package/build/install-doctor.js +13 -0
  51. package/build/install-reexec.js +5 -3
  52. package/build/mcp-install-state.js +130 -0
  53. package/build/mcp-profile.js +11 -2
  54. package/build/mcp-provisioning.js +15 -0
  55. package/build/merge-pull-request.js +562 -0
  56. package/build/phase-result-artifacts.js +450 -0
  57. package/build/pipeline-orchestrator.js +4 -0
  58. package/build/pipeline-utils.js +16 -0
  59. package/build/pipelines.generated.js +7 -7
  60. package/build/plane/preflight.js +18 -14
  61. package/build/plane/supervisor.js +8 -1
  62. package/build/project-root.js +34 -0
  63. package/build/readme.generated.js +1 -1
  64. package/build/run-unit-tests-launcher.js +36 -9
  65. package/build/setup-epic.js +57 -4
  66. package/build/sfcc/permissions.js +25 -6
  67. package/build/sfcc/reads-site-preference.js +6 -0
  68. package/build/sfcc/register.js +61 -23
  69. package/build/sfcc/registration-inventory.js +89 -0
  70. package/build/sfcc/setup-status.js +18 -34
  71. package/build/sfcc/tool-wrapper.js +294 -17
  72. package/build/sfcc/write-grants.js +33 -1
  73. package/build/sfcc/write-guard.js +41 -12
  74. package/build/sfcc/writes-custom-object-def.js +6 -2
  75. package/build/sfcc/writes-site-preference.js +6 -1
  76. package/build/sfcc/writes-system-object.js +11 -2
  77. package/build/sfcc/writes.js +13 -8
  78. package/build/start-tickets-prereqs.js +25 -15
  79. package/build/start-tickets.js +123 -21
  80. package/build/version.generated.js +1 -1
  81. package/build/worktree-core.js +9 -3
  82. package/docs/install/mcp-tool-integrations.md +54 -9
  83. package/docs/install/sfcc-integration.md +71 -24
  84. package/package.json +3 -3
  85. package/build/executor/worker-config-isolation.js +0 -287
@@ -99,7 +99,7 @@ var __defProp=Object.defineProperty;var __getOwnPropNames=Object.getOwnPropertyN
99
99
  LIMIT @limit`),toDelivered=db.prepare("UPDATE messages SET state = 'delivered', updated_at = datetime('now') WHERE seq = @seq AND state = 'pending'"),toAcked=db.prepare("UPDATE messages SET state = 'acked', acked_at = datetime('now'), updated_at = datetime('now') WHERE seq = @seq AND state = 'delivered'"),reread=db.prepare("SELECT * FROM messages WHERE seq = ?"),delivered=[];return db.transaction(()=>{let pending=selectPending.all({run_id:runId,worker_id:workerId,limit});for(let row of pending){if(toDelivered.run({seq:row.seq}).changes!==1)continue;insertRelayAuditEvent(db,{id:`message.delivered:${row.id}`,source:"conductor-worker",type:"message.delivered",run_id:row.run_id,worker_id:row.worker_id,producer:"worker-message-relay",observed_via:"message-relay",data:{summary:"supervisor message delivered to worker",status:"delivered",details:{message_id:row.id,message_type:row.type}}}),toAcked.run({seq:row.seq}),insertRelayAuditEvent(db,{id:`message.acked:${row.id}`,source:"conductor-worker",type:"message.acked",run_id:row.run_id,worker_id:row.worker_id,producer:"worker-message-relay",observed_via:"message-relay",data:{summary:"supervisor message acknowledged by worker",status:"acked",details:{message_id:row.id,message_type:row.type}}});let finalRow=reread.get(row.seq);delivered.push(rowToConductorWorkerMessage(finalRow))}}).immediate(),{messages:delivered,count:delivered.length,acked_count:delivered.length}}finally{db.close()}}var ConductorPersistenceUnavailableError,LEDGER_NATIVE_MODULE_NAME,ConductorNativeModuleLoadError,databaseModulePromise,dbLoadFailure,dbLoadDiagnosticEmitted,BUSY_TIMEOUT_DEFAULT,BUSY_TIMEOUT_MIN,BUSY_TIMEOUT_MAX,RETENTION_DAYS_DEFAULT,RETENTION_DAYS_MAX,RETENTION_MAX_ROWS_DEFAULT,RETENTION_MAX_ROWS_MIN,RETENTION_MAX_ROWS_MAX,POLL_LIMIT_DEFAULT,POLL_LIMIT_MAX,MESSAGE_COOLDOWN_DEFAULT_MS,MESSAGE_COOLDOWN_MIN_MS,MESSAGE_COOLDOWN_MAX_MS,CHECK_MESSAGES_LIMIT_DEFAULT,CHECK_MESSAGES_LIMIT_MAX,WAIT_TIMEOUT_MAX_MS,WAIT_POLL_INTERVAL_MS,SUMMARY_FIELD_MAX_CHARS,CURRENT_CONDUCTOR_SCHEMA_VERSION,MESSAGE_TYPE_PATTERN,init_store=__esm({"src/conductor/store.ts"(){"use strict";init_taxonomy();init_errors();init_data_normalization();init_paths();ConductorPersistenceUnavailableError=class extends Error{constructor(message="Conductor persistence is unavailable: the optional 'better-sqlite3' native module could not be loaded."){super(message),this.name="ConductorPersistenceUnavailableError"}},LEDGER_NATIVE_MODULE_NAME="better-sqlite3",ConductorNativeModuleLoadError=class extends ConductorPersistenceUnavailableError{details;failureKind;constructor(failureKind,details){super("Conductor ledger native module failed to load for this Node runtime."),this.name="ConductorNativeModuleLoadError",this.failureKind=failureKind,this.details=details}};databaseModulePromise=null,dbLoadFailure=null,dbLoadDiagnosticEmitted=!1;BUSY_TIMEOUT_DEFAULT=1e4,BUSY_TIMEOUT_MIN=250,BUSY_TIMEOUT_MAX=12e4,RETENTION_DAYS_DEFAULT=30,RETENTION_DAYS_MAX=3650,RETENTION_MAX_ROWS_DEFAULT=5e4,RETENTION_MAX_ROWS_MIN=100,RETENTION_MAX_ROWS_MAX=1e7,POLL_LIMIT_DEFAULT=100,POLL_LIMIT_MAX=1e3,MESSAGE_COOLDOWN_DEFAULT_MS=3e5,MESSAGE_COOLDOWN_MIN_MS=1e3,MESSAGE_COOLDOWN_MAX_MS=864e5,CHECK_MESSAGES_LIMIT_DEFAULT=10,CHECK_MESSAGES_LIMIT_MAX=100,WAIT_TIMEOUT_MAX_MS=12e4,WAIT_POLL_INTERVAL_MS=500,SUMMARY_FIELD_MAX_CHARS=500;CURRENT_CONDUCTOR_SCHEMA_VERSION=8;MESSAGE_TYPE_PATTERN=/^[A-Za-z0-9._:-]{1,100}$/}});import{createHash}from"node:crypto";function normalizeRepoName(value){if(typeof value!="string")return null;let trimmed=value.trim();return trimmed.length===0||CONTROL_CHAR_RE.test(trimmed)?null:trimmed}function normalizeSha(value){if(typeof value!="string")return null;let lowered=value.trim().toLowerCase();return SHA_RE.test(lowered)?lowered:null}function normalizePrNumber(value){return typeof value!="number"||!Number.isSafeInteger(value)||value<=0?null:value}function canonicalize(value){if(Array.isArray(value))return value.map(item=>canonicalize(item));if(value!==null&&typeof value=="object"){let record=value,sortedKeys=Object.keys(record).sort(),out={};for(let key of sortedKeys)out[key]=canonicalize(record[key]);return out}return value}function stableJsonHash(value){let canonical=canonicalize(value),json=JSON.stringify(canonical)??"null";return createHash("sha256").update(json).digest("hex")}var GIT_HOOK_PRODUCER,CONTROL_CHAR_RE,SHA_RE,init_git_ci_types=__esm({"src/conductor/git-ci-types.ts"(){"use strict";GIT_HOOK_PRODUCER="git-hook",CONTROL_CHAR_RE=/[\u0000-\u001F\u007F]/,SHA_RE=/^[0-9a-f]{40}$|^[0-9a-f]{64}$/}});import{createHash as createHash2}from"node:crypto";function makeProducerDedupeKey(dimensions){let canonical={};for(let[key,value]of Object.entries(dimensions))value!=null&&(canonical[key]=value);return stableJsonHash(canonical)}function makeStableProducerEventId(dedupeKey){let h=createHash2("sha256").update(`conductor-producer:${dedupeKey}`).digest("hex");return`${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20,32)}`}function isDuplicateConstraintError2(error){if(!error||typeof error!="object")return!1;let code=error.code;if(typeof code=="string"&&code.startsWith("SQLITE_CONSTRAINT"))return!0;let message=error.message;if(typeof message=="string"){let lowered=message.toLowerCase();if(lowered.includes("unique constraint")||lowered.includes("constraint failed"))return!0}return!1}async function eventAlreadyExists(dedupeKey,deps={}){let pollEvents=deps.pollEvents??(options=>pollConductorEvents(options)),sinceSeq=1;for(let page=0;page<LEDGER_SCAN_MAX_PAGES;page+=1){let result;try{result=await pollEvents({since_seq:sinceSeq,data_mode:"full",limit:LEDGER_SCAN_PAGE_LIMIT})}catch{return!1}for(let event of result.events){if(!event||typeof event!="object")continue;let data=event.data;if(data&&typeof data=="object"){let details=data.details;if(details&&typeof details=="object"&&details.dedupe_key===dedupeKey)return!0}}if(result.count===0||result.next_seq<=sinceSeq)break;sinceSeq=result.next_seq}return!1}async function emitConductorEventIfNew(input,dimensions,deps={}){let emitEvent=deps.emitEvent??emitConductorEvent,dedupeKey=makeProducerDedupeKey(dimensions);if(await eventAlreadyExists(dedupeKey,deps))return{emitted:!1,reason:"duplicate"};let eventId=makeStableProducerEventId(dedupeKey),existingData=input.data??{},existingDetails=existingData.details&&typeof existingData.details=="object"&&!Array.isArray(existingData.details)?existingData.details:{},data={...existingData,details:{...existingDetails,dedupe_key:dedupeKey}};try{return await emitEvent({...input,id:eventId,data}),{emitted:!0,event_id:eventId}}catch(error){if(isDuplicateConstraintError2(error))return{emitted:!1,reason:"duplicate"};throw error}}var LEDGER_SCAN_PAGE_LIMIT,LEDGER_SCAN_MAX_PAGES,init_producer_ledger=__esm({"src/conductor/producer-ledger.ts"(){"use strict";init_store();init_git_ci_types();LEDGER_SCAN_PAGE_LIMIT=500,LEDGER_SCAN_MAX_PAGES=200}});import{execFileSync as execFileSync2}from"node:child_process";import{basename}from"node:path";function runGitCommand(args,options={}){try{let stdout=execFileSync2("git",args,{cwd:options.cwd,timeout:options.timeoutMs??GIT_COMMAND_TIMEOUT_MS,encoding:"utf-8",maxBuffer:GIT_COMMAND_MAX_BUFFER,stdio:["ignore","pipe","ignore"]});return{ok:!0,stdout:typeof stdout=="string"?stdout:""}}catch{return{ok:!1,stdout:""}}}function firstLine(result){if(!result.ok)return null;let trimmed=result.stdout.trim();return trimmed.length>0?trimmed:null}function sanitizeGitRemoteUrl(url){if(typeof url!="string")return null;let trimmed=url.trim();if(trimmed.length===0)return null;if(/^https?:\/\//i.test(trimmed))try{let parsed=new URL(trimmed);return parsed.username="",parsed.password="",parsed.toString()}catch{return trimmed.replace(/^(https?:\/\/)[^/@]*@/i,"$1")}return trimmed}function getGitWorktreeContext(options={}){let cwd=options.cwd??process.cwd(),env=options.env??process.env,topLevel=firstLine(runGitCommand(["rev-parse","--show-toplevel"],{cwd})),isWorktree=topLevel!==null,worktreePath=topLevel??cwd,gitCommonDir=firstLine(runGitCommand(["rev-parse","--git-common-dir"],{cwd})),branchRaw=firstLine(runGitCommand(["rev-parse","--abbrev-ref","HEAD"],{cwd})),branch=branchRaw===null||branchRaw==="HEAD"?null:branchRaw,headSha=normalizeSha(firstLine(runGitCommand(["rev-parse","HEAD"],{cwd}))??""),remoteOrigin=sanitizeGitRemoteUrl(firstLine(runGitCommand(["config","--get","remote.origin.url"],{cwd}))??"");return{repo:normalizeRepoName(env.BAPI_CONDUCTOR_REPO_NAME)??normalizeRepoName(env.BAPI_REPO_NAME)??normalizeRepoName(basename(worktreePath))??"unknown",worktree_path:worktreePath,git_common_dir:gitCommonDir,branch,head_sha:headSha,remote_origin:remoteOrigin,is_worktree:isWorktree}}function parseCoAuthoredByTrailers(message){if(typeof message!="string"||message.length===0)return[];let out=[];for(let line of message.split(/\r?\n/)){let match=CO_AUTHOR_RE.exec(line.trim());match&&out.push({name:match[1].trim(),email:match[2].trim()})}return out}function readHeadCommitMetadata(options={}){let ref=options.ref??"HEAD",result=runGitCommand(["show","-s",`--format=${COMMIT_FORMAT}`,ref],{cwd:options.cwd});if(!result.ok)return null;let fields=result.stdout.replace(/\n$/,"").split("");if(fields.length<10)return null;let[sha,parentsRaw,authorName,authorEmail,committerName,committerEmail,authoredAt,committedAt,subject,body]=fields,parents=parentsRaw.trim().split(/\s+/).map(p=>normalizeSha(p)).filter(p=>p!==null),coAuthors=parseCoAuthoredByTrailers(body);return{sha:normalizeSha(sha),parents,author_name:authorName,author_email:authorEmail,committer_name:committerName,committer_email:committerEmail,authored_at:authoredAt,committed_at:committedAt,subject,body,co_authors:coAuthors,attribution_source:coAuthors.length>0?"co-authored-by-trailer":"commit-author"}}function parseReferenceTransactionUpdates(stdin){if(typeof stdin!="string"||stdin.length===0)return[];let out=[];for(let line of stdin.split(/\r?\n/)){let trimmed=line.trim();if(trimmed.length===0)continue;let parts=trimmed.split(/\s+/);if(parts.length!==3)continue;let oldSha=normalizeSha(parts[0]),newSha=normalizeSha(parts[1]),ref=parts[2];oldSha===null||newSha===null||ref.length===0||REF_CONTROL_CHAR_RE.test(ref)||out.push({old_sha:oldSha,new_sha:newSha,ref})}return out}var GIT_COMMAND_TIMEOUT_MS,GIT_COMMAND_MAX_BUFFER,CO_AUTHOR_RE,COMMIT_FORMAT,REF_CONTROL_CHAR_RE,init_git_inspection=__esm({"src/conductor/git-inspection.ts"(){"use strict";init_git_ci_types();GIT_COMMAND_TIMEOUT_MS=5e3,GIT_COMMAND_MAX_BUFFER=10*1024*1024;CO_AUTHOR_RE=/^co-authored-by:\s*(.+?)\s*<([^<>@\s]+@[^<>\s]+)>\s*$/i;COMMIT_FORMAT="%H%x1f%P%x1f%an%x1f%ae%x1f%cn%x1f%ce%x1f%aI%x1f%cI%x1f%s%x1f%b";REF_CONTROL_CHAR_RE=/[\u0000-\u001F\u007F]/}});import{spawnSync}from"node:child_process";function normalizeRepoRelativePath(input){if(typeof input!="string")return null;let trimmed=input.trim();if(trimmed.length===0||trimmed.startsWith("/")||trimmed.startsWith("\\")||/^[A-Za-z]:[\\/]/.test(trimmed))return null;let p=trimmed.replace(/\\/g,"/");p.startsWith("./")&&(p=p.slice(2));let segments=p.split("/");if(segments.some(s=>s===".."))return null;let cleaned=segments.filter(s=>s!==""&&s!==".").join("/");return cleaned.length>0?cleaned:null}function normalizeDeclaredTouchedFiles(list){if(!Array.isArray(list))return[];let out=new Set;for(let item of list){let norm=normalizeRepoRelativePath(item);norm&&out.add(norm)}return Array.from(out).sort()}function parseDeclaredTouchedFilesFromEnv(env=process.env){let raw=env[DECLARED_TOUCHED_FILES_ENV];if(typeof raw!="string"||raw.trim().length===0)return{specified:!1};let parsed;try{parsed=JSON.parse(raw)}catch{return{specified:!1}}if(!Array.isArray(parsed))return{specified:!1};let files=normalizeDeclaredTouchedFiles(parsed);return files.length===0?{specified:!1}:{specified:!0,files}}function collectBranchChangedFiles(opts={}){let baseRef=opts.baseRef??FILE_SCOPE_GUARD_BASE_REF,spawn=opts.spawnSyncFn??defaultSpawnSync,result;try{result=spawn("git",["diff","--name-only",`${baseRef}...HEAD`],{cwd:opts.cwd,encoding:"utf-8",shell:!1})}catch{return{ok:!1,files:[]}}if(result.error||result.status!==0)return{ok:!1,files:[]};let stdout=typeof result.stdout=="string"?result.stdout:result.stdout?.toString("utf-8")??"",files=[],seen=new Set;for(let line of stdout.split(`
100
100
  `)){let norm=normalizeRepoRelativePath(line);norm&&!seen.has(norm)&&(seen.add(norm),files.push(norm))}return{ok:!0,files}}function analyzeDiffScope(input){if(!input.declared.specified)return{checked:!1,outOfScopeFiles:[],warning:null};let declaredSet=new Set(input.declared.files),outOfScope=input.changedFiles.filter(f=>!declaredSet.has(f)).sort();if(outOfScope.length===0)return{checked:!0,outOfScopeFiles:[],warning:null};let warning=`[file-scope-guard] ${input.ticketKey&&input.ticketKey.trim().length>0?input.ticketKey.trim():"unknown-ticket"}: ${outOfScope.length} file(s) changed outside the declared touched-file set (${input.declared.files.length} declared): ${outOfScope.join(", ")}. Warn-only \u2014 PR creation continues.`;return{checked:!0,outOfScopeFiles:outOfScope,warning}}function runFileScopeGuardCli(deps={}){let env=deps.env??process.env,writeOut=deps.writeOut??(m=>process.stdout.write(`${m}
101
101
  `)),writeErr=deps.writeErr??(m=>process.stderr.write(`${m}
102
- `)),ticketKey=env[FILE_SCOPE_GUARD_TICKET_KEY_ENV],declared=parseDeclaredTouchedFilesFromEnv(env);if(!declared.specified)return 0;let collected=collectBranchChangedFiles({cwd:deps.cwd,spawnSyncFn:deps.spawnSyncFn});if(!collected.ok)return writeErr(`[file-scope-guard] ${ticketKey??"unknown-ticket"}: unable to check file scope (git diff failed); continuing \u2014 PR creation is not blocked.`),0;let analysis=analyzeDiffScope({ticketKey,declared,changedFiles:collected.files});return analysis.warning&&writeOut(analysis.warning),0}var DECLARED_TOUCHED_FILES_ENV,FILE_SCOPE_GUARD_TICKET_KEY_ENV,FILE_SCOPE_GUARD_BASE_REF,defaultSpawnSync,init_file_scope_guard=__esm({"src/conductor/file-scope-guard.ts"(){"use strict";DECLARED_TOUCHED_FILES_ENV="BAPI_CONDUCTOR_DECLARED_TOUCHED_FILES_JSON",FILE_SCOPE_GUARD_TICKET_KEY_ENV="BAPI_CONDUCTOR_TICKET_KEY",FILE_SCOPE_GUARD_BASE_REF="origin/main";defaultSpawnSync=(command,args,options)=>spawnSync(command,args,options)}});import path3 from"node:path";function resolvePackageRootFromModuleUrl(moduleUrl){let pathname;try{pathname=decodeURIComponent(new URL(moduleUrl).pathname)}catch{return null}/^\/[A-Za-z]:/.test(pathname)&&(pathname=pathname.slice(1));let segments=pathname.split(/[\\/]/),markerIndex=-1;for(let i=segments.length-1;i>=0;i--)if(segments[i]==="src"||segments[i]==="build"){markerIndex=i;break}return markerIndex<=0?null:segments.slice(0,markerIndex).join("/")}function basenameAnySep(filePath){let segments=filePath.split(/[\\/]/);return segments[segments.length-1]??""}function resolveMcpShimInvocationForRuntime(deps){let nodeExecutable=deps.nodeExecutable??"node",packageRoot=resolvePackageRootFromModuleUrl(deps.moduleUrl);if(packageRoot){let candidate=`${packageRoot}/build/index.js`;if(deps.fileExists(candidate))return{form:"absolute-build-path",nodeExecutable,serverEntryPath:candidate}}let argv1=deps.argv1;return typeof argv1=="string"&&argv1.length>0&&path3.isAbsolute(argv1)&&basenameAnySep(argv1)==="index.js"&&deps.fileExists(argv1)?{form:"absolute-build-path",nodeExecutable,serverEntryPath:argv1}:{form:"npm-channel",command:"npx",packageSpec:deps.npmPackageSpec??DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC}}var DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC,init_mcp_server_invocation=__esm({"src/mcp-server-invocation.ts"(){"use strict";DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC="@bridge_gpt/mcp-server@latest"}});import path4 from"node:path";function pathApiForPlatform(platform){return platform==="win32"?path4.win32:path4.posix}var init_types=__esm({"src/scheduler-backends/types.ts"(){"use strict"}});function assertNoNul(value,label){if(value.includes("\0"))throw new Error(`Refusing to generate scheduler content: ${label} contains a NUL byte, which is not allowed.`)}function xmlEscape(value){return assertNoNul(value,"xml value"),value.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function posixShellQuote(value){return assertNoNul(value,"posix shell value"),value===""?"''":`'${value.replace(/'/g,"'\\''")}'`}function windowsCmdQuote(value){return assertNoNul(value,"windows cmd value"),`"${value.replace(/"/g,'""')}"`}function escapeWindowsCmdSetValue(value){return assertNoNul(value,"windows cmd set value"),value.replace(/%/g,"%%").replace(/"/g,"")}function systemdQuote(value){return assertNoNul(value,"systemd value"),`"${value.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function bakedEnvEntries(env){let entries=[["PATH",env.envPath],["BRIDGE_GPT_NODE",env.nodePath],["BRIDGE_GPT_NPX",env.npxPath],["BRIDGE_GPT_AGENT",env.agent],["BRIDGE_GPT_AGENT_PATH",env.agentPath],["BRIDGE_GPT_REPO_PATH",env.repoPath],["BRIDGE_GPT_SCHEDULE_ID",env.scheduleId],["BRIDGE_GPT_COMMAND",env.command],["BRIDGE_GPT_COMMAND_ARGS_JSON",env.commandArgsJson]];env.ideaFile!==void 0&&entries.push(["BRIDGE_GPT_IDEA_FILE",env.ideaFile]);for(let[key,value]of entries)assertNoNul(value,key);return entries}function bakedEnvFromCreateInput(input){return{envPath:input.envPath,nodePath:input.nodePath,npxPath:input.npxPath,agent:input.agent,agentPath:input.agentPath,repoPath:input.repoPath,scheduleId:input.id,command:input.command,commandArgsJson:JSON.stringify(input.args),ideaFile:input.legacyIdeaFile}}function formatEnvExportsForGeneratedUnit(env){return bakedEnvEntries(env).map(([key,value])=>`export ${key}=${posixShellQuote(value)}`).join(`
102
+ `)),ticketKey=env[FILE_SCOPE_GUARD_TICKET_KEY_ENV],declared=parseDeclaredTouchedFilesFromEnv(env);if(!declared.specified)return 0;let collected=collectBranchChangedFiles({cwd:deps.cwd,spawnSyncFn:deps.spawnSyncFn});if(!collected.ok)return writeErr(`[file-scope-guard] ${ticketKey??"unknown-ticket"}: unable to check file scope (git diff failed); continuing \u2014 PR creation is not blocked.`),0;let analysis=analyzeDiffScope({ticketKey,declared,changedFiles:collected.files});return analysis.warning&&writeOut(analysis.warning),0}var DECLARED_TOUCHED_FILES_ENV,FILE_SCOPE_GUARD_TICKET_KEY_ENV,FILE_SCOPE_GUARD_BASE_REF,defaultSpawnSync,init_file_scope_guard=__esm({"src/conductor/file-scope-guard.ts"(){"use strict";DECLARED_TOUCHED_FILES_ENV="BAPI_CONDUCTOR_DECLARED_TOUCHED_FILES_JSON",FILE_SCOPE_GUARD_TICKET_KEY_ENV="BAPI_CONDUCTOR_TICKET_KEY",FILE_SCOPE_GUARD_BASE_REF="origin/main";defaultSpawnSync=(command,args,options)=>spawnSync(command,args,options)}});import path4 from"node:path";function resolvePackageRootFromModuleUrl(moduleUrl){let pathname;try{pathname=decodeURIComponent(new URL(moduleUrl).pathname)}catch{return null}/^\/[A-Za-z]:/.test(pathname)&&(pathname=pathname.slice(1));let segments=pathname.split(/[\\/]/),markerIndex=-1;for(let i=segments.length-1;i>=0;i--)if(segments[i]==="src"||segments[i]==="build"){markerIndex=i;break}return markerIndex<=0?null:segments.slice(0,markerIndex).join("/")}function basenameAnySep(filePath){let segments=filePath.split(/[\\/]/);return segments[segments.length-1]??""}function resolveMcpShimInvocationForRuntime(deps){let nodeExecutable=deps.nodeExecutable??"node",packageRoot=resolvePackageRootFromModuleUrl(deps.moduleUrl);if(packageRoot){let candidate=`${packageRoot}/build/index.js`;if(deps.fileExists(candidate))return{form:"absolute-build-path",nodeExecutable,serverEntryPath:candidate}}let argv1=deps.argv1;return typeof argv1=="string"&&argv1.length>0&&path4.isAbsolute(argv1)&&basenameAnySep(argv1)==="index.js"&&deps.fileExists(argv1)?{form:"absolute-build-path",nodeExecutable,serverEntryPath:argv1}:{form:"npm-channel",command:"npx",packageSpec:deps.npmPackageSpec??DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC}}var DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC,init_mcp_server_invocation=__esm({"src/mcp-server-invocation.ts"(){"use strict";DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC="@bridge_gpt/mcp-server@latest"}});import path5 from"node:path";function pathApiForPlatform(platform){return platform==="win32"?path5.win32:path5.posix}var init_types=__esm({"src/scheduler-backends/types.ts"(){"use strict"}});function assertNoNul(value,label){if(value.includes("\0"))throw new Error(`Refusing to generate scheduler content: ${label} contains a NUL byte, which is not allowed.`)}function xmlEscape(value){return assertNoNul(value,"xml value"),value.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function posixShellQuote(value){return assertNoNul(value,"posix shell value"),value===""?"''":`'${value.replace(/'/g,"'\\''")}'`}function windowsCmdQuote(value){return assertNoNul(value,"windows cmd value"),`"${value.replace(/"/g,'""')}"`}function escapeWindowsCmdSetValue(value){return assertNoNul(value,"windows cmd set value"),value.replace(/%/g,"%%").replace(/"/g,"")}function systemdQuote(value){return assertNoNul(value,"systemd value"),`"${value.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`}function bakedEnvEntries(env){let entries=[["PATH",env.envPath],["BRIDGE_GPT_NODE",env.nodePath],["BRIDGE_GPT_NPX",env.npxPath],["BRIDGE_GPT_AGENT",env.agent],["BRIDGE_GPT_AGENT_PATH",env.agentPath],["BRIDGE_GPT_REPO_PATH",env.repoPath],["BRIDGE_GPT_SCHEDULE_ID",env.scheduleId],["BRIDGE_GPT_COMMAND",env.command],["BRIDGE_GPT_COMMAND_ARGS_JSON",env.commandArgsJson]];env.ideaFile!==void 0&&entries.push(["BRIDGE_GPT_IDEA_FILE",env.ideaFile]);for(let[key,value]of entries)assertNoNul(value,key);return entries}function bakedEnvFromCreateInput(input){return{envPath:input.envPath,nodePath:input.nodePath,npxPath:input.npxPath,agent:input.agent,agentPath:input.agentPath,repoPath:input.repoPath,scheduleId:input.id,command:input.command,commandArgsJson:JSON.stringify(input.args),ideaFile:input.legacyIdeaFile}}function formatEnvExportsForGeneratedUnit(env){return bakedEnvEntries(env).map(([key,value])=>`export ${key}=${posixShellQuote(value)}`).join(`
103
103
  `)}var init_escaping=__esm({"src/scheduler-backends/escaping.ts"(){"use strict"}});import{promises as fs2}from"node:fs";function launchdLabelForId(id){return`com.bridge-gpt.schedule-run.${id}`}function launchdLabelForMetadata(metadata){let unitPath=metadata.unit_path;if(unitPath&&unitPath.endsWith(".plist")){let base=unitPath.split(/[\\/]/).pop();if(base)return base.slice(0,-6)}return launchdLabelForId(metadata.id)}function launchdPlistPathForId(id,homeDir){return pathApiForPlatform("darwin").join(homeDir,"Library","LaunchAgents",`${launchdLabelForId(id)}.plist`)}function startCalendarIntervalFromIso(runAtIso){let date=new Date(runAtIso);return{Year:date.getFullYear(),Month:date.getMonth()+1,Day:date.getDate(),Hour:date.getHours(),Minute:date.getMinutes()}}function resolveUid(deps){let fromEnv=deps.env.UID;if(fromEnv&&/^\d+$/.test(fromEnv))return fromEnv;let procUid=typeof process.getuid=="function"?process.getuid():void 0;return procUid!==void 0?String(procUid):"501"}function renderLaunchdPlist(input){let label=launchdLabelForId(input.id),cal=startCalendarIntervalFromIso(input.runAtIso),env=bakedEnvEntries(bakedEnvFromCreateInput(input)),programArgs=[input.triggerInvocation.exe,...input.triggerInvocation.args].map(arg=>` <string>${xmlEscape(arg)}</string>`).join(`
104
104
  `),envEntries=env.map(([key,value])=>` <key>${xmlEscape(key)}</key>
105
105
  <string>${xmlEscape(value)}</string>`).join(`
@@ -112,10 +112,10 @@ var __defProp=Object.defineProperty;var __getOwnPropNames=Object.getOwnPropertyN
112
112
  `)}async function systemctlUserUsable(deps){return(await deps.runCommand("systemctl",["--user","--version"])).exitCode===0}function createSystemdUserBackend(){return{name:"systemd-user",async isAvailable(deps){return deps.platform!=="linux"?!1:systemctlUserUsable(deps)},async create(input){let paths=systemdUnitPathsForId(input.id,input.deps.homeDir),names=systemdUnitNamesForId(input.id),serviceContent=renderSystemdService(input),timerContent=renderSystemdTimer(input),artifacts=[{path:paths.service,content:serviceContent,kind:"systemd-service"},{path:paths.timer,content:timerContent,kind:"systemd-timer"}],unitPaths=[paths.service,paths.timer];if(input.dryRun)return{ok:!0,backend:"systemd-user",unitPath:paths.timer,unitPaths,backendJobId:names.timer,artifacts};let pathApi=pathApiForPlatform("linux");await fs4.mkdir(pathApi.dirname(paths.service),{recursive:!0}),await fs4.writeFile(paths.service,serviceContent,"utf-8"),await fs4.writeFile(paths.timer,timerContent,"utf-8");let cleanupUnitFiles=async()=>{await fs4.unlink(paths.timer).catch(()=>{}),await fs4.unlink(paths.service).catch(()=>{})},reload=await input.deps.runCommand("systemctl",["--user","daemon-reload"]);if(reload.exitCode!==0)return await cleanupUnitFiles(),{ok:!1,backend:"systemd-user",unitPath:paths.timer,unitPaths,backendJobId:names.timer,artifacts,error:`systemctl --user daemon-reload failed: ${(reload.stderr||reload.stdout).trim()}`};let enable=await input.deps.runCommand("systemctl",["--user","enable","--now",names.timer]);return enable.exitCode!==0?(await cleanupUnitFiles(),{ok:!1,backend:"systemd-user",unitPath:paths.timer,unitPaths,backendJobId:names.timer,artifacts,error:`systemctl --user enable --now failed: ${(enable.stderr||enable.stdout).trim()}`}):{ok:!0,backend:"systemd-user",unitPath:paths.timer,unitPaths,backendJobId:names.timer,artifacts}},async list(input){let entries=[];for(let metadata of input.recorded){let{paths,names}=systemdUnitsForMetadata(metadata,input.deps.homeDir),timerExists=!0;try{await fs4.access(paths.timer)}catch{timerExists=!1}if(!timerExists){entries.push({metadata,status:"stale",detail:"timer unit file missing"});continue}let status=await input.deps.runCommand("systemctl",["--user","status",names.timer]);status.exitCode===0?entries.push({metadata,status:"active",detail:"timer active"}):status.exitCode===3?entries.push({metadata,status:"stale",detail:"timer inactive"}):entries.push({metadata,status:"backend-unavailable",detail:"systemctl unavailable"})}return entries},async cancel(input){let{paths,names}=systemdUnitsForMetadata(input.metadata,input.deps.homeDir),disable=await input.deps.runCommand("systemctl",["--user","disable","--now",names.timer]),removedAny=!1;for(let unitPath of[paths.timer,paths.service])try{await fs4.unlink(unitPath),removedAny=!0}catch(error){if(error.code!=="ENOENT")return{ok:!1,nativeRemoved:!1,stale:!1,error:String(error)}}return await input.deps.runCommand("systemctl",["--user","daemon-reload"]),{ok:!0,nativeRemoved:disable.exitCode===0||removedAny,stale:disable.exitCode!==0}}}}var init_systemd_user=__esm({"src/scheduler-backends/systemd-user.ts"(){"use strict";init_types();init_escaping()}});function formatAtTimestamp(runAtIso){let d=new Date(runAtIso),pad=n=>String(n).padStart(2,"0");return`${d.getFullYear()}${pad(d.getMonth()+1)}${pad(d.getDate())}${pad(d.getHours())}${pad(d.getMinutes())}`}function renderAtScript(input){let exports=formatEnvExportsForGeneratedUnit(bakedEnvFromCreateInput(input)),command=[input.triggerInvocation.exe,...input.triggerInvocation.args].map(part=>posixShellQuote(part)).join(" ");return["#!/bin/sh",exports,`cd ${posixShellQuote(input.repoPath)}`,`${command} >>${posixShellQuote(input.paths.stdoutPath)} 2>>${posixShellQuote(input.paths.stderrPath)}`,""].join(`
113
113
  `)}function parseAtJobId(stdout,stderr){let matches=[...`${stdout}
114
114
  ${stderr}`.matchAll(/^job\s+(\d+)\s+at\b/gim)];return matches.length>0?matches[matches.length-1][1]:null}async function atToolsResolvable(deps){return(await deps.runCommand("which",["at"])).exitCode!==0?!1:(await deps.runCommand("which",["atq"])).exitCode===0}function createAtFallbackBackend(){return{name:"at-fallback",async isAvailable(deps){return deps.platform!=="linux"?!1:atToolsResolvable(deps)},async create(input){let script=renderAtScript(input),artifact={path:AT_STDIN_ARTIFACT_PATH,content:script,kind:"at-script"};if(input.dryRun)return{ok:!0,backend:"at-fallback",unitPath:null,unitPaths:[],backendJobId:null,artifacts:[artifact]};let timestamp=formatAtTimestamp(input.runAtIso),result=await input.deps.runCommand("at",["-t",timestamp],{input:script});if(result.exitCode!==0)return{ok:!1,backend:"at-fallback",unitPath:null,unitPaths:[],backendJobId:null,artifacts:[artifact],error:`at scheduling failed: ${(result.stderr||result.stdout).trim()}`};let jobId=parseAtJobId(result.stdout,result.stderr);return jobId?{ok:!0,backend:"at-fallback",unitPath:null,unitPaths:[],backendJobId:jobId,artifacts:[artifact]}:{ok:!1,backend:"at-fallback",unitPath:null,unitPaths:[],backendJobId:null,artifacts:[artifact],error:"Could not parse an at job id from the scheduler output."}},async list(input){let atq=await input.deps.runCommand("atq",[]);if(atq.exitCode!==0)return input.recorded.map(metadata=>({metadata,status:"backend-unavailable",detail:"atq unavailable"}));let liveJobIds=new Set(atq.stdout.split(/\r?\n/).map(line=>line.trim().match(/^(\d+)\b/)?.[1]).filter(id=>!!id));return input.recorded.map(metadata=>{let jobId=metadata.backend_job_id,active=jobId!==null&&liveJobIds.has(jobId);return{metadata,status:active?"active":"stale",detail:active?`at job ${jobId}`:"at job not queued"}})},async cancel(input){let jobId=input.metadata.backend_job_id;if(!jobId)return{ok:!0,nativeRemoved:!1,stale:!0};let nativeRemoved=(await input.deps.runCommand("atrm",[jobId])).exitCode===0;return{ok:!0,nativeRemoved,stale:!nativeRemoved}}}}var AT_STDIN_ARTIFACT_PATH,init_at_fallback=__esm({"src/scheduler-backends/at-fallback.ts"(){"use strict";init_escaping();AT_STDIN_ARTIFACT_PATH="<at-stdin>"}});function unsupportedSchedulerPlatformMessage(platform){return`Unsupported platform '${platform}'. schedule-run supports ${SUPPORTED_PLATFORMS.join(", ")}.`}function getSchedulerBackendByName(name){switch(name){case"launchd":return LAUNCHD;case"task-scheduler":return TASK_SCHEDULER;case"systemd-user":return SYSTEMD_USER;case"at-fallback":return AT_FALLBACK;default:return null}}function getSchedulerBackendsForPlatform(platform){switch(platform){case"darwin":return{ok:!0,backends:[LAUNCHD]};case"win32":return{ok:!0,backends:[TASK_SCHEDULER]};case"linux":return{ok:!0,backends:[SYSTEMD_USER,AT_FALLBACK]};default:return{ok:!1,error:unsupportedSchedulerPlatformMessage(platform)}}}async function selectSchedulerBackend(deps,dryRun){let platformResult=getSchedulerBackendsForPlatform(deps.platform);if(!platformResult.ok)return{ok:!1,error:platformResult.error};let candidates=platformResult.backends;if(dryRun)return{ok:!0,backend:candidates[0]};for(let backend of candidates)if(await backend.isAvailable(deps))return{ok:!0,backend};return{ok:!1,error:`No available scheduler backend for platform '${deps.platform}'. Tried: ${candidates.map(b=>b.name).join(", ")}.`}}var LAUNCHD,TASK_SCHEDULER,SYSTEMD_USER,AT_FALLBACK,SUPPORTED_PLATFORMS,init_scheduler_backends=__esm({"src/scheduler-backends/index.ts"(){"use strict";init_launchd();init_task_scheduler();init_systemd_user();init_at_fallback();init_types();LAUNCHD=createLaunchdBackend(),TASK_SCHEDULER=createTaskSchedulerBackend(),SYSTEMD_USER=createSystemdUserBackend(),AT_FALLBACK=createAtFallbackBackend(),SUPPORTED_PLATFORMS=["darwin","win32","linux"]}});import{promises as fs5}from"node:fs";function getScheduleRoot(homeDir,platform){return pathApiForPlatform(platform).join(homeDir,".bridge-gpt","schedules")}function getSchedulePaths(id,homeDir,platform){let pathApi=pathApiForPlatform(platform),schedulesDir=getScheduleRoot(homeDir,platform),logsDir=pathApi.join(schedulesDir,"logs");return{schedulesDir,logsDir,metadataPath:pathApi.join(schedulesDir,`${id}.json`),stdoutPath:pathApi.join(logsDir,`${id}.out`),stderrPath:pathApi.join(logsDir,`${id}.err`)}}async function ensureScheduleDirectories(homeDir,platform){let pathApi=pathApiForPlatform(platform),schedulesDir=getScheduleRoot(homeDir,platform),logsDir=pathApi.join(schedulesDir,"logs");await fs5.mkdir(schedulesDir,{recursive:!0}),await fs5.mkdir(logsDir,{recursive:!0})}async function writeScheduleMetadata(metadata,homeDir,platform){let{metadataPath}=getSchedulePaths(metadata.id,homeDir,platform),content=`${JSON.stringify(metadata,null,2)}
115
- `,tmpPath=`${metadataPath}.tmp-${process.pid}-${atomicWriteCounter++}`;try{await fs5.writeFile(tmpPath,content,"utf-8"),await fs5.rename(tmpPath,metadataPath)}catch(error){throw await fs5.unlink(tmpPath).catch(()=>{}),error}}async function appendScheduleRunEvent(id,event,homeDir,platform){let metadata=await readScheduleMetadata(id,homeDir,platform);if(!metadata)return null;let history=Array.isArray(metadata.run_history)?[...metadata.run_history]:[];return history.push(event),metadata.run_history=history.length>MAX_RUN_HISTORY_EVENTS?history.slice(history.length-MAX_RUN_HISTORY_EVENTS):history,await writeScheduleMetadata(metadata,homeDir,platform),metadata}async function readScheduleMetadata(id,homeDir,platform){let{metadataPath}=getSchedulePaths(id,homeDir,platform),raw;try{raw=await fs5.readFile(metadataPath,"utf-8")}catch(error){if(error.code==="ENOENT")return null;throw error}return JSON.parse(raw)}async function listScheduleMetadata(homeDir,platform){let pathApi=pathApiForPlatform(platform),schedulesDir=getScheduleRoot(homeDir,platform),entries;try{entries=await fs5.readdir(schedulesDir)}catch(error){if(error.code==="ENOENT")return[];throw error}let rows=[];for(let entry of entries.sort()){if(!entry.endsWith(".json"))continue;let id=entry.slice(0,-5),fullPath=pathApi.join(schedulesDir,entry),raw;try{raw=await fs5.readFile(fullPath,"utf-8")}catch(error){if(error.code==="ENOENT")continue;throw error}try{let metadata=JSON.parse(raw);rows.push({ok:!0,id,metadata,path:fullPath})}catch(error){rows.push({ok:!1,id,path:fullPath,error:error instanceof Error?error.message:String(error)})}}return rows}async function deleteScheduleMetadata(id,homeDir,platform){let{metadataPath}=getSchedulePaths(id,homeDir,platform);try{await fs5.unlink(metadataPath)}catch(error){if(error.code==="ENOENT")return;throw error}}var MAX_RUN_HISTORY_EVENTS,atomicWriteCounter,init_schedule_store=__esm({"src/schedule-store.ts"(){"use strict";init_types();MAX_RUN_HISTORY_EVENTS=50,atomicWriteCounter=0}});import{promises as nodeFs}from"node:fs";import path5 from"node:path";import{z}from"zod";function createDefaultCommandCatalogFsDeps(){return{readdir:dir=>nodeFs.readdir(dir),readFile:file=>nodeFs.readFile(file,"utf-8")}}function parseArgumentsSchema(raw){let parsed;try{parsed=JSON.parse(raw)}catch(error){return{ok:!1,error:`invalid JSON in 'arguments:' frontmatter (must be valid JSON, not YAML): ${error instanceof Error?error.message:String(error)}`}}let validated=ArgumentSchemaZ.safeParse(parsed);return validated.success?{ok:!0,schema:validated.data}:{ok:!1,error:`invalid 'arguments:' schema: ${validated.error.issues.map(i=>`${i.path.join(".")||"<root>"}: ${i.message}`).join("; ")}`}}function splitFrontmatter(raw){let lines=raw.split(/\r?\n/);if(lines.length===0||lines[0].trim()!=="---")return{ok:!0,frontmatter:null,body:raw};let closeIndex=-1;for(let i=1;i<lines.length;i++)if(lines[i].trim()==="---"){closeIndex=i;break}if(closeIndex===-1)return{ok:!1,error:"unterminated frontmatter: opening '---' has no closing '---'"};let frontmatterText=lines.slice(1,closeIndex).join(`
115
+ `,tmpPath=`${metadataPath}.tmp-${process.pid}-${atomicWriteCounter++}`;try{await fs5.writeFile(tmpPath,content,"utf-8"),await fs5.rename(tmpPath,metadataPath)}catch(error){throw await fs5.unlink(tmpPath).catch(()=>{}),error}}async function appendScheduleRunEvent(id,event,homeDir,platform){let metadata=await readScheduleMetadata(id,homeDir,platform);if(!metadata)return null;let history=Array.isArray(metadata.run_history)?[...metadata.run_history]:[];return history.push(event),metadata.run_history=history.length>MAX_RUN_HISTORY_EVENTS?history.slice(history.length-MAX_RUN_HISTORY_EVENTS):history,await writeScheduleMetadata(metadata,homeDir,platform),metadata}async function readScheduleMetadata(id,homeDir,platform){let{metadataPath}=getSchedulePaths(id,homeDir,platform),raw;try{raw=await fs5.readFile(metadataPath,"utf-8")}catch(error){if(error.code==="ENOENT")return null;throw error}return JSON.parse(raw)}async function listScheduleMetadata(homeDir,platform){let pathApi=pathApiForPlatform(platform),schedulesDir=getScheduleRoot(homeDir,platform),entries;try{entries=await fs5.readdir(schedulesDir)}catch(error){if(error.code==="ENOENT")return[];throw error}let rows=[];for(let entry of entries.sort()){if(!entry.endsWith(".json"))continue;let id=entry.slice(0,-5),fullPath=pathApi.join(schedulesDir,entry),raw;try{raw=await fs5.readFile(fullPath,"utf-8")}catch(error){if(error.code==="ENOENT")continue;throw error}try{let metadata=JSON.parse(raw);rows.push({ok:!0,id,metadata,path:fullPath})}catch(error){rows.push({ok:!1,id,path:fullPath,error:error instanceof Error?error.message:String(error)})}}return rows}async function deleteScheduleMetadata(id,homeDir,platform){let{metadataPath}=getSchedulePaths(id,homeDir,platform);try{await fs5.unlink(metadataPath)}catch(error){if(error.code==="ENOENT")return;throw error}}var MAX_RUN_HISTORY_EVENTS,atomicWriteCounter,init_schedule_store=__esm({"src/schedule-store.ts"(){"use strict";init_types();MAX_RUN_HISTORY_EVENTS=50,atomicWriteCounter=0}});import{promises as nodeFs}from"node:fs";import path6 from"node:path";import{z}from"zod";function createDefaultCommandCatalogFsDeps(){return{readdir:dir=>nodeFs.readdir(dir),readFile:file=>nodeFs.readFile(file,"utf-8")}}function parseArgumentsSchema(raw){let parsed;try{parsed=JSON.parse(raw)}catch(error){return{ok:!1,error:`invalid JSON in 'arguments:' frontmatter (must be valid JSON, not YAML): ${error instanceof Error?error.message:String(error)}`}}let validated=ArgumentSchemaZ.safeParse(parsed);return validated.success?{ok:!0,schema:validated.data}:{ok:!1,error:`invalid 'arguments:' schema: ${validated.error.issues.map(i=>`${i.path.join(".")||"<root>"}: ${i.message}`).join("; ")}`}}function splitFrontmatter(raw){let lines=raw.split(/\r?\n/);if(lines.length===0||lines[0].trim()!=="---")return{ok:!0,frontmatter:null,body:raw};let closeIndex=-1;for(let i=1;i<lines.length;i++)if(lines[i].trim()==="---"){closeIndex=i;break}if(closeIndex===-1)return{ok:!1,error:"unterminated frontmatter: opening '---' has no closing '---'"};let frontmatterText=lines.slice(1,closeIndex).join(`
116
116
  `),body=lines.slice(closeIndex+1).join(`
117
117
  `),parsed=parseFrontmatterText(frontmatterText);return parsed.ok?{ok:!0,frontmatter:parsed.frontmatter,body}:parsed}function parseFrontmatterText(text){let schedulable=!0,interactive=!1,argumentSchema;for(let rawLine of text.split(`
118
- `)){let line=rawLine.trim();if(line===""||line.startsWith("#"))continue;let schedulableMatch=line.match(/^schedulable:\s*(true|false)\s*$/);if(schedulableMatch){schedulable=schedulableMatch[1]==="true";continue}let interactiveMatch=line.match(/^interactive:\s*(true|false)\s*$/);if(interactiveMatch){interactive=interactiveMatch[1]==="true";continue}let argsMatch=rawLine.match(/^\s*arguments:\s*(.*)$/);if(argsMatch){let value=argsMatch[1].trim();if(value==="")return{ok:!1,error:"'arguments:' frontmatter key has no JSON value"};let schemaResult=parseArgumentsSchema(value);if(!schemaResult.ok)return schemaResult;argumentSchema=schemaResult.schema;continue}}return{ok:!0,frontmatter:{schedulable,interactive,argumentSchema}}}function commandsDirForRepo(repoPath,platform){return(platform==="win32"?path5.win32:path5.posix).join(repoPath,".claude","commands")}async function discoverCommandCatalog(repoPath,platform,fsDeps=createDefaultCommandCatalogFsDeps()){let pathApi=platform==="win32"?path5.win32:path5.posix,dir=commandsDirForRepo(repoPath,platform),entries;try{entries=await fsDeps.readdir(dir)}catch(error){if(error.code==="ENOENT")return{commands:[],errors:[]};throw error}let commands=[],errors=[];for(let entry of[...entries].sort()){if(!entry.endsWith(".md"))continue;let name=entry.slice(0,-3),filePath=pathApi.join(dir,entry);if(!COMMAND_NAME_PATTERN.test(name)){errors.push({name,filePath,error:`unsafe command name '${name}' (must match ${COMMAND_NAME_PATTERN.source})`});continue}let raw;try{raw=await fsDeps.readFile(filePath)}catch(error){errors.push({name,filePath,error:`could not read command file: ${error instanceof Error?error.message:String(error)}`});continue}let split=splitFrontmatter(raw);if(!split.ok){errors.push({name,filePath,error:split.error});continue}let fm=split.frontmatter;commands.push({name,filePath,schedulable:fm?.schedulable??!0,interactive:fm?.interactive??!1,body:split.body,argumentSchema:fm?.argumentSchema})}return commands.sort((a,b)=>a.name.localeCompare(b.name)),{commands,errors}}function resolveSchedulableCommand(catalog,name){let broken=catalog.errors.find(e=>e.name===name);if(broken)return{ok:!1,error:`Command '${name}' is not schedulable: ${broken.error}.`};let command=catalog.commands.find(c=>c.name===name);if(!command){let available=catalog.commands.map(c=>c.name).join(", ")||"(none discovered)";return{ok:!1,error:`Unknown command '${name}'. Discovered commands: ${available}.`}}return command.schedulable?{ok:!0,command}:{ok:!1,error:`Command '${name}' is marked 'schedulable: false' and cannot be scheduled.`}}function validateCommandArgv(argv,schema){if(!schema)return{ok:!0,normalizedArgv:[...argv],parsed:{freeform:!0,positionals:{},extraPositionals:[],flags:{}}};let flagByLong=new Map;for(let f of schema.flags)flagByLong.set(f.flag,f);let normalizedArgv=[],positionalTokens=[],flags={};for(let i=0;i<argv.length;i++){let token=argv[i];if(token.startsWith("--")){let eqIndex=token.indexOf("="),flagName=eqIndex===-1?token:token.slice(0,eqIndex),inlineValue=eqIndex===-1?void 0:token.slice(eqIndex+1),descriptor=flagByLong.get(flagName);if(!descriptor)return{ok:!1,error:`Unknown flag '${flagName}' for this command.`};if(descriptor.type==="boolean"){if(inlineValue!==void 0)return{ok:!1,error:`Boolean flag '${flagName}' does not take a value.`};flags[descriptor.name]=!0,normalizedArgv.push(flagName);continue}let value;if(inlineValue!==void 0)value=inlineValue;else{if(i+1>=argv.length)return{ok:!1,error:`Flag '${flagName}' requires a value.`};value=argv[++i]}if(descriptor.repeatable){let existing=flags[descriptor.name];Array.isArray(existing)?existing.push(value):flags[descriptor.name]=[value]}else flags[descriptor.name]=value;normalizedArgv.push(flagName,value);continue}positionalTokens.push(token),normalizedArgv.push(token)}for(let f of schema.flags)if(!(f.name in flags)){if(f.required)return{ok:!1,error:`Missing required flag '${f.flag}'.`};f.default!==void 0&&(flags[f.name]=f.default)}let positionals={},cursor=0;for(let p of schema.positionals){if(p.variadic){let rest=positionalTokens.slice(cursor);if(cursor=positionalTokens.length,p.required&&rest.length===0)return{ok:!1,error:`Missing required positional '${p.name}'.`};positionals[p.name]=rest;continue}if(cursor<positionalTokens.length)positionals[p.name]=positionalTokens[cursor++];else{if(p.required)return{ok:!1,error:`Missing required positional '${p.name}'.`};p.default!==void 0&&(positionals[p.name]=p.default)}}let extraPositionals=positionalTokens.slice(cursor);return extraPositionals.length>0&&!schema.allowExtraPositionals?{ok:!1,error:`Unexpected extra positional argument(s): ${extraPositionals.join(", ")}.`}:{ok:!0,normalizedArgv,parsed:{freeform:!1,positionals,extraPositionals,flags}}}function schemaSupportsAutoFlag(schema){return schema?schema.flags.some(f=>f.flag==="--auto"&&f.type==="boolean"):!1}var PositionalZ,FlagZ,ArgumentSchemaZ,COMMAND_NAME_PATTERN,init_command_catalog=__esm({"src/command-catalog.ts"(){"use strict";PositionalZ=z.object({name:z.string().min(1),type:z.string().default("string"),required:z.boolean().default(!1),variadic:z.boolean().default(!1),default:z.unknown().optional()}),FlagZ=z.object({name:z.string().min(1),flag:z.string().regex(/^--[A-Za-z0-9][A-Za-z0-9-]*$/,"flag must start with '--'"),type:z.string().default("string"),required:z.boolean().default(!1),repeatable:z.boolean().default(!1),default:z.unknown().optional()}),ArgumentSchemaZ=z.object({positionals:z.array(PositionalZ).default([]),flags:z.array(FlagZ).default([]),allowExtraPositionals:z.boolean().default(!1)});COMMAND_NAME_PATTERN=/^[A-Za-z0-9][A-Za-z0-9_-]*$/}});function quotePromptToken(token){return token===""?'""':/^[A-Za-z0-9_@%+=:,./-]+$/.test(token)?token:`"${token.replace(/"/g,'\\"')}"`}function buildAugmentedArgs(input){let args=[...input.args];(input.commandName==="full-automation"||input.commandName==="epic-tick")&&args.push("--scheduled-at",input.scheduledAt);let supportsAuto=schemaSupportsAutoFlag(input.schema)||input.commandName==="full-automation"||input.commandName==="epic-tick",alreadyHasAuto=input.args.includes("--auto");return input.autoApprove&&supportsAuto&&!alreadyHasAuto&&args.push("--auto"),args}function buildTargetCommandLine(input){let parts=[`/${input.commandName}`];for(let arg of buildAugmentedArgs(input))parts.push(quotePromptToken(arg));return parts.join(" ")}function renderLateFireGate(scheduleId,scheduledAt,autoApprove){let lateAction=autoApprove?"explain that the run is firing late and then PROCEED with the command below (this schedule was created with auto-approve).":"explain that the run is firing late and then HALT WITHOUT EXECUTING the command below (this schedule was created without auto-approve, and a headless run must not proceed unconfirmed).";return["## Scheduled-run drift gate","",`This is an automated, headless scheduled run (schedule id: ${scheduleId}).`,`It was scheduled to fire at ${scheduledAt}.`,"",`Before doing anything else, check how late this run is firing. If it is more than ${LATE_FIRE_THRESHOLD_SECONDS} seconds later than the scheduled time above, ${lateAction}`,`If it is within ${LATE_FIRE_THRESHOLD_SECONDS} seconds of the scheduled time, proceed silently.`,"","Then run the following command exactly as written:"].join(`
118
+ `)){let line=rawLine.trim();if(line===""||line.startsWith("#"))continue;let schedulableMatch=line.match(/^schedulable:\s*(true|false)\s*$/);if(schedulableMatch){schedulable=schedulableMatch[1]==="true";continue}let interactiveMatch=line.match(/^interactive:\s*(true|false)\s*$/);if(interactiveMatch){interactive=interactiveMatch[1]==="true";continue}let argsMatch=rawLine.match(/^\s*arguments:\s*(.*)$/);if(argsMatch){let value=argsMatch[1].trim();if(value==="")return{ok:!1,error:"'arguments:' frontmatter key has no JSON value"};let schemaResult=parseArgumentsSchema(value);if(!schemaResult.ok)return schemaResult;argumentSchema=schemaResult.schema;continue}}return{ok:!0,frontmatter:{schedulable,interactive,argumentSchema}}}function commandsDirForRepo(repoPath,platform){return(platform==="win32"?path6.win32:path6.posix).join(repoPath,".claude","commands")}async function discoverCommandCatalog(repoPath,platform,fsDeps=createDefaultCommandCatalogFsDeps()){let pathApi=platform==="win32"?path6.win32:path6.posix,dir=commandsDirForRepo(repoPath,platform),entries;try{entries=await fsDeps.readdir(dir)}catch(error){if(error.code==="ENOENT")return{commands:[],errors:[]};throw error}let commands=[],errors=[];for(let entry of[...entries].sort()){if(!entry.endsWith(".md"))continue;let name=entry.slice(0,-3),filePath=pathApi.join(dir,entry);if(!COMMAND_NAME_PATTERN.test(name)){errors.push({name,filePath,error:`unsafe command name '${name}' (must match ${COMMAND_NAME_PATTERN.source})`});continue}let raw;try{raw=await fsDeps.readFile(filePath)}catch(error){errors.push({name,filePath,error:`could not read command file: ${error instanceof Error?error.message:String(error)}`});continue}let split=splitFrontmatter(raw);if(!split.ok){errors.push({name,filePath,error:split.error});continue}let fm=split.frontmatter;commands.push({name,filePath,schedulable:fm?.schedulable??!0,interactive:fm?.interactive??!1,body:split.body,argumentSchema:fm?.argumentSchema})}return commands.sort((a,b)=>a.name.localeCompare(b.name)),{commands,errors}}function resolveSchedulableCommand(catalog,name){let broken=catalog.errors.find(e=>e.name===name);if(broken)return{ok:!1,error:`Command '${name}' is not schedulable: ${broken.error}.`};let command=catalog.commands.find(c=>c.name===name);if(!command){let available=catalog.commands.map(c=>c.name).join(", ")||"(none discovered)";return{ok:!1,error:`Unknown command '${name}'. Discovered commands: ${available}.`}}return command.schedulable?{ok:!0,command}:{ok:!1,error:`Command '${name}' is marked 'schedulable: false' and cannot be scheduled.`}}function validateCommandArgv(argv,schema){if(!schema)return{ok:!0,normalizedArgv:[...argv],parsed:{freeform:!0,positionals:{},extraPositionals:[],flags:{}}};let flagByLong=new Map;for(let f of schema.flags)flagByLong.set(f.flag,f);let normalizedArgv=[],positionalTokens=[],flags={};for(let i=0;i<argv.length;i++){let token=argv[i];if(token.startsWith("--")){let eqIndex=token.indexOf("="),flagName=eqIndex===-1?token:token.slice(0,eqIndex),inlineValue=eqIndex===-1?void 0:token.slice(eqIndex+1),descriptor=flagByLong.get(flagName);if(!descriptor)return{ok:!1,error:`Unknown flag '${flagName}' for this command.`};if(descriptor.type==="boolean"){if(inlineValue!==void 0)return{ok:!1,error:`Boolean flag '${flagName}' does not take a value.`};flags[descriptor.name]=!0,normalizedArgv.push(flagName);continue}let value;if(inlineValue!==void 0)value=inlineValue;else{if(i+1>=argv.length)return{ok:!1,error:`Flag '${flagName}' requires a value.`};value=argv[++i]}if(descriptor.repeatable){let existing=flags[descriptor.name];Array.isArray(existing)?existing.push(value):flags[descriptor.name]=[value]}else flags[descriptor.name]=value;normalizedArgv.push(flagName,value);continue}positionalTokens.push(token),normalizedArgv.push(token)}for(let f of schema.flags)if(!(f.name in flags)){if(f.required)return{ok:!1,error:`Missing required flag '${f.flag}'.`};f.default!==void 0&&(flags[f.name]=f.default)}let positionals={},cursor=0;for(let p of schema.positionals){if(p.variadic){let rest=positionalTokens.slice(cursor);if(cursor=positionalTokens.length,p.required&&rest.length===0)return{ok:!1,error:`Missing required positional '${p.name}'.`};positionals[p.name]=rest;continue}if(cursor<positionalTokens.length)positionals[p.name]=positionalTokens[cursor++];else{if(p.required)return{ok:!1,error:`Missing required positional '${p.name}'.`};p.default!==void 0&&(positionals[p.name]=p.default)}}let extraPositionals=positionalTokens.slice(cursor);return extraPositionals.length>0&&!schema.allowExtraPositionals?{ok:!1,error:`Unexpected extra positional argument(s): ${extraPositionals.join(", ")}.`}:{ok:!0,normalizedArgv,parsed:{freeform:!1,positionals,extraPositionals,flags}}}function schemaSupportsAutoFlag(schema){return schema?schema.flags.some(f=>f.flag==="--auto"&&f.type==="boolean"):!1}var PositionalZ,FlagZ,ArgumentSchemaZ,COMMAND_NAME_PATTERN,init_command_catalog=__esm({"src/command-catalog.ts"(){"use strict";PositionalZ=z.object({name:z.string().min(1),type:z.string().default("string"),required:z.boolean().default(!1),variadic:z.boolean().default(!1),default:z.unknown().optional()}),FlagZ=z.object({name:z.string().min(1),flag:z.string().regex(/^--[A-Za-z0-9][A-Za-z0-9-]*$/,"flag must start with '--'"),type:z.string().default("string"),required:z.boolean().default(!1),repeatable:z.boolean().default(!1),default:z.unknown().optional()}),ArgumentSchemaZ=z.object({positionals:z.array(PositionalZ).default([]),flags:z.array(FlagZ).default([]),allowExtraPositionals:z.boolean().default(!1)});COMMAND_NAME_PATTERN=/^[A-Za-z0-9][A-Za-z0-9_-]*$/}});function quotePromptToken(token){return token===""?'""':/^[A-Za-z0-9_@%+=:,./-]+$/.test(token)?token:`"${token.replace(/"/g,'\\"')}"`}function buildAugmentedArgs(input){let args=[...input.args];(input.commandName==="full-automation"||input.commandName==="epic-tick")&&args.push("--scheduled-at",input.scheduledAt);let supportsAuto=schemaSupportsAutoFlag(input.schema)||input.commandName==="full-automation"||input.commandName==="epic-tick",alreadyHasAuto=input.args.includes("--auto");return input.autoApprove&&supportsAuto&&!alreadyHasAuto&&args.push("--auto"),args}function buildTargetCommandLine(input){let parts=[`/${input.commandName}`];for(let arg of buildAugmentedArgs(input))parts.push(quotePromptToken(arg));return parts.join(" ")}function renderLateFireGate(scheduleId,scheduledAt,autoApprove){let lateAction=autoApprove?"explain that the run is firing late and then PROCEED with the command below (this schedule was created with auto-approve).":"explain that the run is firing late and then HALT WITHOUT EXECUTING the command below (this schedule was created without auto-approve, and a headless run must not proceed unconfirmed).";return["## Scheduled-run drift gate","",`This is an automated, headless scheduled run (schedule id: ${scheduleId}).`,`It was scheduled to fire at ${scheduledAt}.`,"",`Before doing anything else, check how late this run is firing. If it is more than ${LATE_FIRE_THRESHOLD_SECONDS} seconds later than the scheduled time above, ${lateAction}`,`If it is within ${LATE_FIRE_THRESHOLD_SECONDS} seconds of the scheduled time, proceed silently.`,"","Then run the following command exactly as written:"].join(`
119
119
  `)}function replaceArgumentsPlaceholder(body,argString){return body.split("$ARGUMENTS").join(argString)}function renderScheduledPrompt(input){let gate=renderLateFireGate(input.scheduleId,input.scheduledAt,input.autoApprove),targetInput={commandName:input.commandName,args:input.args,scheduledAt:input.scheduledAt,autoApprove:input.autoApprove,schema:input.schema},targetCommandLine=buildTargetCommandLine(targetInput),argString=buildAugmentedArgs(targetInput).map(quotePromptToken).join(" "),body=replaceArgumentsPlaceholder(input.commandBody,argString);return[gate,"",targetCommandLine,"",body].join(`
120
120
  `)}var LATE_FIRE_THRESHOLD_SECONDS,init_scheduled_prompt=__esm({"src/scheduled-prompt.ts"(){"use strict";init_command_catalog();LATE_FIRE_THRESHOLD_SECONDS=60}});async function resolveCommandOnPath(command,envPath,deps){let pathApi=pathApiForPlatform(deps.platform),probe=deps.platform==="win32"?"where.exe":"which",env={...deps.env,PATH:envPath};deps.platform==="win32"&&(env.Path=envPath);let result=await deps.runCommand(probe,[command],{env});if(result.exitCode!==0)return null;let candidate=result.stdout.split(/\r?\n/).map(line=>line.trim()).find(line=>line.length>0);return!candidate||!pathApi.isAbsolute(candidate)?null:pathApi.normalize(candidate)}function buildClaudePrompt(input){return renderScheduledPrompt({scheduleId:input.scheduleId,scheduledAt:input.runAtIso,autoApprove:input.autoApprove,commandName:input.commandName,args:input.args,commandBody:input.commandBody,schema:input.schema})}function createClaudeLauncher(){return{capability:CLAUDE_CAPABILITY,resolveBinary(envPath,deps){return resolveCommandOnPath("claude",envPath,deps)},buildInvocation(exe,input){let prompt=buildClaudePrompt(input);return{exe,args:[CLAUDE_CAPABILITY.promptFlag,prompt],prompt}},formatInvocationLine(invocation,platform){let quote=platform==="win32"?windowsCmdQuote:posixShellQuote;return[invocation.exe,...invocation.args].map(part=>quote(part)).join(" ")}}}var CLAUDE_CAPABILITY,init_claude=__esm({"src/agent-launchers/claude.ts"(){"use strict";init_types();init_escaping();init_scheduled_prompt();init_scheduled_prompt();CLAUDE_CAPABILITY={name:"claude",command:"claude",supportsCwdFlag:!1,promptFlag:"-p"}}});function buildCursorPrompt(input){return renderScheduledPrompt({scheduleId:input.scheduleId,scheduledAt:input.runAtIso,autoApprove:input.autoApprove,commandName:input.commandName,args:input.args,commandBody:input.commandBody,schema:input.schema})}function createCursorLauncher(){return{capability:CURSOR_CAPABILITY,resolveBinary(envPath,deps){return resolveCommandOnPath("cursor-agent",envPath,deps)},buildInvocation(exe,input){let prompt=buildCursorPrompt(input),args=[CURSOR_CAPABILITY.promptFlag,"--output-format","text","--trust","--workspace",input.repoPath,prompt];return{exe,args,prompt}},formatInvocationLine(invocation,platform){let quote=platform==="win32"?windowsCmdQuote:posixShellQuote;return[invocation.exe,...invocation.args].map(part=>quote(part)).join(" ")}}}var CURSOR_CAPABILITY,init_cursor=__esm({"src/agent-launchers/cursor.ts"(){"use strict";init_escaping();init_scheduled_prompt();init_claude();CURSOR_CAPABILITY={name:"cursor-agent",command:"cursor-agent",supportsCwdFlag:!0,promptFlag:"-p"}}});function getAgentLauncher(name){switch(name){case"claude":return CLAUDE_LAUNCHER;case"cursor-agent":return CURSOR_LAUNCHER;default:return null}}function formatValidAgentLauncherNames(){return LAUNCHER_NAMES.join(", ")}var CLAUDE_LAUNCHER,CURSOR_LAUNCHER,LAUNCHER_NAMES,init_agent_launchers=__esm({"src/agent-launchers/index.ts"(){"use strict";init_claude();init_cursor();init_claude();init_cursor();CLAUDE_LAUNCHER=createClaudeLauncher(),CURSOR_LAUNCHER=createCursorLauncher(),LAUNCHER_NAMES=["claude","cursor-agent"]}});var schedule_run_exports={};__export(schedule_run_exports,{buildScheduleMetadata:()=>buildScheduleMetadata,collectScheduleRunPrereqStatus:()=>collectScheduleRunPrereqStatus,commandSucceeded:()=>commandSucceeded,createDefaultScheduleRunDeps:()=>createDefaultScheduleRunDeps,filterScheduleMetadata:()=>filterScheduleMetadata,formatScheduleCancelResult:()=>formatScheduleCancelResult,formatScheduleCreateResult:()=>formatScheduleCreateResult,formatScheduleDoctorReport:()=>formatScheduleDoctorReport,formatScheduleListResult:()=>formatScheduleListResult,getScheduleRunUsage:()=>getScheduleRunUsage,isTransientNpxEntryPath:()=>isTransientNpxEntryPath,latestRunStatus:()=>latestRunStatus,orchestrateScheduleCancel:()=>orchestrateScheduleCancel,orchestrateScheduleCreate:()=>orchestrateScheduleCreate,orchestrateScheduleDoctor:()=>orchestrateScheduleDoctor,orchestrateScheduleExecute:()=>orchestrateScheduleExecute,orchestrateScheduleList:()=>orchestrateScheduleList,parseDurationFromNow:()=>parseDurationFromNow,parseRunAtIso:()=>parseRunAtIso,parseScheduleCancelArgs:()=>parseScheduleCancelArgs,parseScheduleCreateArgs:()=>parseScheduleCreateArgs,parseScheduleDoctorArgs:()=>parseScheduleDoctorArgs,parseScheduleExecuteArgs:()=>parseScheduleExecuteArgs,parseScheduleListArgs:()=>parseScheduleListArgs,parseScheduleRunArgs:()=>parseScheduleRunArgs,resolveScheduleCreateInput:()=>resolveScheduleCreateInput,runScheduleRunCli:()=>runScheduleRunCli,scheduleCommandLabel:()=>scheduleCommandLabel});import{execFile}from"node:child_process";import{promises as fs6}from"node:fs";import{randomUUID as randomUUID2,createHash as createHash3}from"node:crypto";function createDefaultScheduleRunDeps(){return{runCommand:(file,args,options)=>new Promise(resolve2=>{let child=execFile(file,args,{cwd:options?.cwd,env:options?.env??process.env,maxBuffer:67108864,encoding:"utf-8"},(error,stdout,stderr)=>{let exitCode=error&&typeof error.code=="number"?error.code:error?1:0;resolve2({stdout:stdout??"",stderr:stderr??"",exitCode})});options?.input!==void 0&&child.stdin&&(child.stdin.write(options.input),child.stdin.end())}),platform:process.platform,env:process.env,cwd:process.cwd(),execPath:process.execPath,homeDir:process.env.HOME??process.env.USERPROFILE??"",now:()=>Date.now(),cliEntryPath:process.argv[1],bridgeCredentialResolved:()=>!!process.env.BAPI_API_KEY}}function commandSucceeded(result){return result.exitCode===0}function isTransientNpxEntryPath(entryPath){return entryPath?/[\\/]_npx[\\/]/.test(entryPath):!1}function getScheduleRunUsage(){return["Usage:"," npx -y @bridge_gpt/mcp-server schedule-run <create|list|cancel|doctor> [flags]","","Schedules a local, one-shot run of ANY Bridge slash-command automation (from","the repo's .claude/commands/*.md catalog) at a chosen time using an OS-native","scheduler (launchd / Task Scheduler / systemd-user / at). Schedules are stored","locally under ~/.bridge-gpt/schedules/ and are never sent to a server.","","create:"," schedule-run create --in 2h --command review-ticket -- BAPI-999",' schedule-run create --at "<datetime>" --command start-tickets -- BAPI-1 BAPI-2'," legacy: schedule-run create --in 2h --idea-file <path>","","All tokens after a bare -- are the structured argv passed to the command.","","create flags:",' --at "<datetime>" ISO-8601 time to run (mutually exclusive with --in)'," --in <duration> Run after a duration, e.g. 30m, 4h, 1d (mutually exclusive with --at)"," --command <name> Discovered .claude/commands command to schedule"," --idea-file <path> Legacy: schedule /full-automation with this idea file"," --agent <name> Agent to launch (claude [default] or cursor-agent)"," --repo-path <path> Working directory + command catalog root (default: cwd)"," --auto Run hands-off; gate proceeds even when firing late"," --no-auto Late runs halt without executing (headless-safe default)"," --dry-run Print the generated unit + prompt + invocation without creating anything"," --id <id> Override the auto-generated schedule id (mainly for tests)","","list flags:"," --id <id> Filter to a single schedule id"," --agent <name> Filter by agent"," --backend <name> Filter by backend (launchd|task-scheduler|systemd-user|at-fallback)"," --json Emit JSON instead of a table","","cancel:"," cancel <id> Cancel by positional id"," cancel --id <id> Cancel by --id flag"," --agent <name> Only cancel when the recorded agent matches"," --backend <name> Only cancel when the recorded backend matches","","doctor:"," Read-only diagnostics: platform support, backend candidate order, scheduler"," availability, and whether claude/npx resolve on PATH. Creates nothing.",""," -h, --help Show this help"].join(`
121
121
  `)}function takeValue(argv,index,arg,flag){return arg.startsWith(`${flag}=`)?{value:arg.slice(`${flag}=`.length),nextIndex:index}:index+1>=argv.length?{error:`${flag} requires a value.`}:{value:argv[index+1],nextIndex:index+1}}function matchesFlag(arg,flag){return arg===flag||arg.startsWith(`${flag}=`)}function parseScheduleCreateArgs(argv){let delimIndex=argv.indexOf("--"),schedulerArgs=delimIndex===-1?argv:argv.slice(0,delimIndex),commandArgs=delimIndex===-1?[]:argv.slice(delimIndex+1);if(schedulerArgs.includes("-h")||schedulerArgs.includes("--help"))return{status:"help",usage:getScheduleRunUsage()};let at,inDuration,commandName,ideaFile,agent="claude",repoPath,id,sawAutoApprove=!1,sawNoAutoApprove=!1,dryRun=!1;for(let i=0;i<schedulerArgs.length;i++){let arg=schedulerArgs[i];if(matchesFlag(arg,"--at")){let r=takeValue(schedulerArgs,i,arg,"--at");if("error"in r)return{status:"error",message:r.error};at=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--in")){let r=takeValue(schedulerArgs,i,arg,"--in");if("error"in r)return{status:"error",message:r.error};inDuration=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--command")){let r=takeValue(schedulerArgs,i,arg,"--command");if("error"in r)return{status:"error",message:r.error};commandName=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--idea-file")){let r=takeValue(schedulerArgs,i,arg,"--idea-file");if("error"in r)return{status:"error",message:r.error};ideaFile=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--agent")){let r=takeValue(schedulerArgs,i,arg,"--agent");if("error"in r)return{status:"error",message:r.error};if(!getAgentLauncher(r.value))return{status:"error",message:`Invalid --agent value: '${r.value}'. Valid: ${formatValidAgentLauncherNames()}.`};agent=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--repo-path")){let r=takeValue(schedulerArgs,i,arg,"--repo-path");if("error"in r)return{status:"error",message:r.error};repoPath=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--id")){let r=takeValue(schedulerArgs,i,arg,"--id");if("error"in r)return{status:"error",message:r.error};id=r.value,i=r.nextIndex;continue}if(arg==="--auto"){sawAutoApprove=!0;continue}if(arg==="--no-auto"){sawNoAutoApprove=!0;continue}if(arg==="--dry-run"){dryRun=!0;continue}return arg.startsWith("-")?{status:"error",message:`Unknown flag: ${arg}`}:{status:"error",message:`Unexpected positional argument: '${arg}'. create takes flags before '--'; put command arguments after '--'.`}}if(!!at==!!inDuration)return{status:"error",message:"create requires exactly one of --at or --in."};if(sawAutoApprove&&sawNoAutoApprove)return{status:"error",message:"--auto and --no-auto are mutually exclusive."};if(id!==void 0&&!SCHEDULE_ID_PATTERN.test(id))return{status:"error",message:`Invalid --id value: '${id}'. Ids must match ${SCHEDULE_ID_PATTERN.source} (start alphanumeric; letters, digits, '_' and '-'; max 64 chars).`};if(ideaFile!==void 0){if(commandName===void 0)commandName="full-automation";else if(commandName!=="full-automation")return{status:"error",message:`--idea-file is only valid for legacy full-automation scheduling, not --command '${commandName}'. Pass command arguments after '--' instead.`}}return commandName===void 0?{status:"error",message:"create requires --command <name> (or legacy --idea-file <path>)."}:{status:"ok",subcommand:"create",options:{at,in:inDuration,commandName,commandArgs,ideaFile,agent,repoPath,autoApprove:!sawNoAutoApprove,autoApproveExplicit:sawAutoApprove||sawNoAutoApprove,dryRun,id}}}function parseScheduleExecuteArgs(argv){let positionals=argv.filter(a=>!a.startsWith("-")),flags=argv.filter(a=>a.startsWith("-"));if(flags.length>0)return{status:"error",message:`_execute takes no flags (got ${flags.join(", ")}).`};if(positionals.length!==1)return{status:"error",message:"_execute requires exactly one schedule id."};let id=positionals[0];return SCHEDULE_ID_PATTERN.test(id)?{status:"ok",subcommand:"_execute",options:{id}}:{status:"error",message:`Invalid schedule id: '${id}'.`}}function parseScheduleListArgs(argv){if(argv.includes("-h")||argv.includes("--help"))return{status:"help",usage:getScheduleRunUsage()};let id,agent,backend,json=!1;for(let i=0;i<argv.length;i++){let arg=argv[i];if(matchesFlag(arg,"--id")){let r=takeValue(argv,i,arg,"--id");if("error"in r)return{status:"error",message:r.error};id=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--agent")){let r=takeValue(argv,i,arg,"--agent");if("error"in r)return{status:"error",message:r.error};if(!getAgentLauncher(r.value))return{status:"error",message:`Invalid --agent filter: '${r.value}'. Valid: ${formatValidAgentLauncherNames()}.`};agent=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--backend")){let r=takeValue(argv,i,arg,"--backend");if("error"in r)return{status:"error",message:r.error};if(!VALID_BACKEND_NAMES.includes(r.value))return{status:"error",message:`Invalid --backend filter: '${r.value}'. Valid: ${VALID_BACKEND_NAMES.join(", ")}.`};backend=r.value,i=r.nextIndex;continue}if(arg==="--json"){json=!0;continue}return arg.startsWith("-")?{status:"error",message:`Unknown flag: ${arg}`}:{status:"error",message:`Unexpected positional argument: '${arg}'. list takes only flags.`}}return{status:"ok",subcommand:"list",options:{id,agent,backend,json}}}function parseScheduleCancelArgs(argv){if(argv.includes("-h")||argv.includes("--help"))return{status:"help",usage:getScheduleRunUsage()};let positionalId,flagId,agent,backend;for(let i=0;i<argv.length;i++){let arg=argv[i];if(matchesFlag(arg,"--id")){let r=takeValue(argv,i,arg,"--id");if("error"in r)return{status:"error",message:r.error};if(flagId!==void 0)return{status:"error",message:"cancel accepts only one --id."};flagId=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--agent")){let r=takeValue(argv,i,arg,"--agent");if("error"in r)return{status:"error",message:r.error};agent=r.value,i=r.nextIndex;continue}if(matchesFlag(arg,"--backend")){let r=takeValue(argv,i,arg,"--backend");if("error"in r)return{status:"error",message:r.error};if(!VALID_BACKEND_NAMES.includes(r.value))return{status:"error",message:`Invalid --backend filter: '${r.value}'. Valid: ${VALID_BACKEND_NAMES.join(", ")}.`};backend=r.value,i=r.nextIndex;continue}if(arg.startsWith("-"))return{status:"error",message:`Unknown flag: ${arg}`};if(positionalId!==void 0)return{status:"error",message:"cancel accepts only one schedule id."};positionalId=arg}if(positionalId!==void 0&&flagId!==void 0)return{status:"error",message:"cancel accepts a positional id OR --id, not both."};let id=positionalId??flagId;return id?{status:"ok",subcommand:"cancel",options:{id,agent,backend}}:{status:"error",message:"cancel requires a schedule id (positional or --id)."}}function parseScheduleDoctorArgs(argv){if(argv.includes("-h")||argv.includes("--help"))return{status:"help",usage:getScheduleRunUsage()};let json=!1;for(let arg of argv){if(arg==="--json"){json=!0;continue}return arg.startsWith("-")?{status:"error",message:`Unknown flag: ${arg}`}:{status:"error",message:`Unexpected positional argument: '${arg}'. doctor takes no positional arguments.`}}return{status:"ok",subcommand:"doctor",options:{json}}}function parseScheduleRunArgs(argv){if(argv.length===0)return{status:"error",message:"Missing subcommand. Expected one of: create, list, cancel, doctor."};let[subcommand,...rest]=argv;if(subcommand==="-h"||subcommand==="--help")return{status:"help",usage:getScheduleRunUsage()};switch(subcommand){case"create":return parseScheduleCreateArgs(rest);case"list":return parseScheduleListArgs(rest);case"cancel":return parseScheduleCancelArgs(rest);case"doctor":return parseScheduleDoctorArgs(rest);case"_execute":return parseScheduleExecuteArgs(rest);default:return{status:"error",message:`Unknown subcommand '${subcommand}'. Expected one of: create, list, cancel, doctor.`}}}function parseRunAtIso(value){let date=new Date(value);return Number.isNaN(date.getTime())?{ok:!1,error:`Invalid --at datetime: '${value}'. Expected an ISO-8601 timestamp.`}:{ok:!0,iso:date.toISOString()}}function parseDurationFromNow(value,nowMs){let match=value.match(/^(\d+)([mhd])$/);if(!match)return{ok:!1,error:`Invalid --in duration: '${value}'. Use a positive number followed by m, h, or d (e.g. 30m, 4h, 1d).`};let amount=Number(match[1]);if(amount<=0)return{ok:!1,error:`Invalid --in duration: '${value}'. Duration must be positive.`};let unitMs=match[2]==="m"?6e4:match[2]==="h"?36e5:864e5;return{ok:!0,iso:new Date(nowMs+amount*unitMs).toISOString()}}function resolveAbsolute(p,deps){let pathApi=pathApiForPlatform(deps.platform);return pathApi.isAbsolute(p)?pathApi.normalize(p):pathApi.resolve(deps.cwd,p)}function collectScheduleRunPrereqStatus(input){return{agentBinaryResolved:input.agentBinaryResolved,repoPathExists:input.repoPathExists,cursorApiKeyPresent:!!input.deps.env.CURSOR_API_KEY,bridgeCredentialResolved:input.deps.bridgeCredentialResolved?.()??!!input.deps.env.BAPI_API_KEY}}async function resolveScheduleCreateInput(options,runAtIso,deps){let launcher=getAgentLauncher(options.agent);if(!launcher)return{ok:!1,error:`Unsupported agent: '${options.agent}'. Valid: ${formatValidAgentLauncherNames()}.`};let commandName=options.commandName;if(!commandName)return{ok:!1,error:"create requires a command (--command or legacy --idea-file)."};let repoPath=resolveAbsolute(options.repoPath??deps.cwd,deps);try{if(!(await fs6.stat(repoPath)).isDirectory())return{ok:!1,error:`--repo-path is not a directory: ${repoPath}`}}catch{return{ok:!1,error:`--repo-path does not exist: ${repoPath}`}}let commandArgs=options.commandArgs,legacyIdeaFile;if(options.ideaFile!==void 0){let ideaFile=resolveAbsolute(options.ideaFile,deps);try{if(!(await fs6.stat(ideaFile)).isFile())return{ok:!1,error:`--idea-file is not a file: ${ideaFile}`}}catch{return{ok:!1,error:`--idea-file does not exist: ${ideaFile}`}}legacyIdeaFile=ideaFile,commandArgs=["--idea-file",ideaFile]}let catalog=await discoverCommandCatalog(repoPath,deps.platform,deps.commandCatalogFsDeps),resolvedCommand=resolveSchedulableCommand(catalog,commandName);if(!resolvedCommand.ok)return{ok:!1,error:resolvedCommand.error};let command=resolvedCommand.command,validation=validateCommandArgv(commandArgs,command.argumentSchema);if(!validation.ok)return{ok:!1,error:`Invalid arguments for '${commandName}': ${validation.error}`};let normalizedArgv=validation.normalizedArgv,envPath=deps.env.PATH??deps.env.Path??"",nodePath=deps.execPath,agentPath=await launcher.resolveBinary(envPath,deps);if(!agentPath)return{ok:!1,error:`Could not resolve the '${launcher.capability.command}' binary on the baked PATH.`};let npxPath=await resolveCommandOnPath("npx",envPath,deps)??"",id=options.id??randomUUID2(),agentInvocation=launcher.buildInvocation(agentPath,{scheduleId:id,runAtIso,commandName,args:normalizedArgv,autoApprove:options.autoApprove,repoPath,commandFilePath:command.filePath,commandBody:command.body,schema:command.argumentSchema}),cliEntryPath=deps.cliEntryPath??process.argv[1]??"",triggerInvocation={exe:nodePath,args:[cliEntryPath,"schedule-run","_execute",id]},commandBodyHash=createHash3("sha256").update(command.body,"utf-8").digest("hex"),warnings=[];command.interactive&&!options.autoApproveExplicit&&warnings.push(`Command '${commandName}' has an interactive step but --auto/--no-auto was not specified; a headless scheduled run may hang waiting for confirmation. Pass --auto to run hands-off.`),isTransientNpxEntryPath(cliEntryPath)&&warnings.push(`The scheduled run re-enters this CLI at '${cliEntryPath}', which is inside an npx cache directory. npx caches can be pruned before a future schedule fires, which would make the run fail with ENOENT. Install the CLI persistently (e.g. \`npm i -g @bridge_gpt/mcp-server\`) and schedule with the installed binary so the trigger path stays stable.`);let paths=getSchedulePaths(id,deps.homeDir,deps.platform);return{ok:!0,resolved:{id,runAtIso,agent:options.agent,command:commandName,args:normalizedArgv,commandFilePath:command.filePath,commandBodyHash,autoApprove:options.autoApprove,repoPath,legacyIdeaFile,envPath,nodePath,npxPath,agentPath,agentInvocation,triggerInvocation,renderedPrompt:agentInvocation.prompt,schema:command.argumentSchema,paths:{schedulesDir:paths.schedulesDir,logsDir:paths.logsDir,stdoutPath:paths.stdoutPath,stderrPath:paths.stderrPath},warnings,prereq:collectScheduleRunPrereqStatus({agent:options.agent,agentBinaryResolved:!!agentPath,repoPathExists:!0,deps})}}}function buildScheduleMetadata(resolved,createResult,createdAtIso){return{id:resolved.id,run_at_iso:resolved.runAtIso,scheduled_at:resolved.runAtIso,backend:createResult.backend,unit_path:createResult.unitPath,unit_paths:createResult.unitPaths,backend_job_id:createResult.backendJobId,agent:resolved.agent,agent_path:resolved.agentPath,command:resolved.command,args:resolved.args,command_file:resolved.commandFilePath,command_body_hash:resolved.commandBodyHash,auto_approve:resolved.autoApprove,repo_path:resolved.repoPath,created_at:createdAtIso,env_path:resolved.envPath,node_path:resolved.nodePath,npx_path:resolved.npxPath,claude_path:resolved.agent==="claude"?resolved.agentPath:void 0,idea_file:resolved.legacyIdeaFile,invocation:resolved.agentInvocation,agent_invocation:resolved.agentInvocation,trigger_invocation:resolved.triggerInvocation,run_history:[{status:"created",at:createdAtIso}],logs:{stdout:resolved.paths.stdoutPath,stderr:resolved.paths.stderrPath}}}function resolveRunAtIso(options,deps){if(options.at!==void 0)return parseRunAtIso(options.at);let nowMs=deps.now?deps.now():Date.now();return parseDurationFromNow(options.in,nowMs)}async function orchestrateScheduleCreate(options,deps){let runAt=resolveRunAtIso(options,deps);if(!runAt.ok)return{ok:!1,error:runAt.error};let resolvedResult=await resolveScheduleCreateInput(options,runAt.iso,deps);if(!resolvedResult.ok)return{ok:!1,error:resolvedResult.error};let resolved=resolvedResult.resolved,createdAtIso=new Date(deps.now?deps.now():Date.now()).toISOString(),metadataPath=getSchedulePaths(resolved.id,deps.homeDir,deps.platform).metadataPath;if(!options.dryRun){let existing;try{existing=await readScheduleMetadata(resolved.id,deps.homeDir,deps.platform)}catch(error){let msg=error instanceof Error?error.message:String(error);return{ok:!1,error:`Could not read existing schedule metadata for id '${resolved.id}' at ${metadataPath}: ${msg}. Resolve or remove it before creating.`}}if(existing)return{ok:!1,error:`A schedule with id '${resolved.id}' already exists (${metadataPath}). Cancel it first (schedule-run cancel <id>) or choose a different --id.`}}let selection=await selectSchedulerBackend(deps,options.dryRun);if(!selection.ok)return{ok:!1,error:selection.error};let backend=selection.backend,createInput={deps,id:resolved.id,runAtIso:resolved.runAtIso,triggerInvocation:resolved.triggerInvocation,agentInvocation:resolved.agentInvocation,command:resolved.command,args:resolved.args,agent:resolved.agent,repoPath:resolved.repoPath,envPath:resolved.envPath,nodePath:resolved.nodePath,npxPath:resolved.npxPath,agentPath:resolved.agentPath,legacyIdeaFile:resolved.legacyIdeaFile,paths:resolved.paths,dryRun:options.dryRun};if(options.dryRun){let createResult2=await backend.create(createInput);return createResult2.ok?{ok:!0,dryRun:!0,metadata:buildScheduleMetadata(resolved,createResult2,createdAtIso),metadataPath,createResult:createResult2,resolved}:{ok:!1,error:createResult2.error??"Backend dry-run failed."}}await ensureScheduleDirectories(deps.homeDir,deps.platform);let createResult=await backend.create(createInput);if(!createResult.ok)return{ok:!1,error:createResult.error??"Scheduler backend create failed."};let metadata=buildScheduleMetadata(resolved,createResult,createdAtIso),scheduledAtIso=new Date(deps.now?deps.now():Date.now()).toISOString();metadata.run_history=[...metadata.run_history??[],{status:"scheduled",at:scheduledAtIso}];try{await writeScheduleMetadata(metadata,deps.homeDir,deps.platform)}catch(error){return await backend.cancel({deps,metadata}).catch(()=>{}),{ok:!1,error:`Created the native ${createResult.backend} unit but failed to persist schedule metadata (${error instanceof Error?error.message:String(error)}); attempted to cancel the native unit.`}}return{ok:!0,dryRun:!1,metadata,metadataPath,createResult,resolved}}function formatPrereqStatus(agent,prereq){let lines=[` agent binary: ${prereq.agentBinaryResolved?"resolved":"MISSING"}`,` repo path: ${prereq.repoPathExists?"exists":"MISSING"}`];return agent==="cursor-agent"?lines.push(` CURSOR_API_KEY set: ${prereq.cursorApiKeyPresent?"yes":"no"}`):lines.push(` Bridge credential: ${prereq.bridgeCredentialResolved?"resolved":"not resolved"}`),lines}function formatScheduleCreateResult(result){if(!result.ok)return`Error: ${result.error}`;let m=result.metadata,r=result.resolved,targetCommandLine=buildTargetCommandLine({commandName:r.command,args:r.args,scheduledAt:r.runAtIso,autoApprove:r.autoApprove,schema:r.schema}),lines=[];lines.push(result.dryRun?"[dry-run] schedule-run create preview":"Schedule created."),lines.push(` id: ${m.id}`),lines.push(` backend: ${m.backend}`),lines.push(` command: ${r.command}`),lines.push(` args: ${r.args.length>0?r.args.join(" "):"(none)"}`),lines.push(` run at: ${m.run_at_iso}`),lines.push(` agent: ${m.agent}`),lines.push(` auto-approve: ${m.auto_approve?"yes":"no"}`),lines.push(` metadata: ${result.metadataPath}${result.dryRun?" (not written in dry-run)":""}`),lines.push(` repo path: ${m.repo_path}`),m.idea_file&&lines.push(` idea file: ${m.idea_file}`),lines.push(` stdout log: ${m.logs.stdout}`),lines.push(` stderr log: ${m.logs.stderr}`),lines.push(` agent binary: ${r.agentPath}`),lines.push(` target command: ${targetCommandLine}`),lines.push(` trigger invocation: ${[r.triggerInvocation.exe,...r.triggerInvocation.args].join(" ")}`),lines.push(` agent invocation: ${[r.agentInvocation.exe,...r.agentInvocation.args].join(" ")}`),m.unit_paths.length>0&&lines.push(` unit paths: ${m.unit_paths.join(", ")}`);for(let warning of r.warnings)lines.push(` warning: ${warning}`);if(result.dryRun){lines.push(""),lines.push("prerequisites (secret-free):"),lines.push(...formatPrereqStatus(r.agent,r.prereq)),lines.push(""),lines.push("----- rendered prompt -----"),lines.push(r.renderedPrompt);for(let artifact of result.createResult.artifacts)lines.push(""),lines.push(`----- ${artifact.kind}: ${artifact.path} -----`),lines.push(artifact.content)}return lines.join(`
@@ -123,12 +123,12 @@ ${stderr}`.matchAll(/^job\s+(\d+)\s+at\b/gim)];return matches.length>0?matches[m
123
123
  `);lines.push(["ID","COMMAND","RUN_AT","BACKEND","AGENT","NATIVE","LATEST","UNIT_PATH"].join(" "));for(let e of report.entries)lines.push([e.metadata.id,scheduleCommandLabel(e.metadata),e.metadata.run_at_iso,e.metadata.backend,e.metadata.agent,e.status,latestRunStatus(e.metadata)||"-",e.metadata.unit_path??"-"].join(" "));return lines.join(`
124
124
  `)}async function orchestrateScheduleCancel(options,deps){let metadata=await readScheduleMetadata(options.id,deps.homeDir,deps.platform);if(!metadata)return{ok:!1,notFound:!0,error:`No schedule found with id '${options.id}'.`};if(options.agent!==void 0&&metadata.agent!==options.agent)return{ok:!1,notFound:!0,error:`Schedule '${options.id}' does not match agent filter '${options.agent}'.`};if(options.backend!==void 0&&metadata.backend!==options.backend)return{ok:!1,notFound:!0,error:`Schedule '${options.id}' does not match backend filter '${options.backend}'.`};let backend=getSchedulerBackendByName(metadata.backend);if(!backend)return{ok:!1,error:`Unknown backend '${metadata.backend}' recorded for '${options.id}'.`};let cancelResult=await backend.cancel({deps,metadata});if(!cancelResult.ok)return{ok:!1,error:cancelResult.error??"Backend cancel failed."};let canceledAtIso=new Date(deps.now?deps.now():Date.now()).toISOString();return await appendScheduleRunEvent(options.id,{status:"canceled",at:canceledAtIso},deps.homeDir,deps.platform).catch(()=>{}),await deleteScheduleMetadata(options.id,deps.homeDir,deps.platform),{ok:!0,id:options.id,backend:metadata.backend,nativeRemoved:cancelResult.nativeRemoved,stale:cancelResult.stale,metadataRemoved:!0}}function formatScheduleCancelResult(result){return result.ok?[`Schedule '${result.id}' canceled.`,` backend: ${result.backend}`,` native removed: ${result.nativeRemoved?"yes":`no${result.stale?" (stale)":""}`}`,` metadata removed: ${result.metadataRemoved?"yes":"no"}`," logs: preserved"].join(`
125
125
  `):`Error: ${result.error}`}async function orchestrateScheduleDoctor(deps){let platformResult=getSchedulerBackendsForPlatform(deps.platform),envPath=deps.env.PATH??deps.env.Path??"",claudeResolved=!!await resolveCommandOnPath("claude",envPath,deps),cursorResolved=!!await resolveCommandOnPath("cursor-agent",envPath,deps),npxResolved=!!await resolveCommandOnPath("npx",envPath,deps),cursorApiKeyPresent=!!deps.env.CURSOR_API_KEY,bridgeCredentialResolved=deps.bridgeCredentialResolved?.()??!!deps.env.BAPI_API_KEY;if(!platformResult.ok)return{platform:deps.platform,platformSupported:!1,candidateBackends:[],backendAvailability:[],claudeResolved,cursorResolved,npxResolved,cursorApiKeyPresent,bridgeCredentialResolved,unsupportedMessage:platformResult.error};let candidateBackends=platformResult.backends.map(b=>b.name),backendAvailability=[];for(let backend of platformResult.backends)backendAvailability.push({backend:backend.name,available:await backend.isAvailable(deps)});return{platform:deps.platform,platformSupported:!0,candidateBackends,backendAvailability,claudeResolved,cursorResolved,npxResolved,cursorApiKeyPresent,bridgeCredentialResolved}}function formatScheduleDoctorReport(report,json){if(json)return JSON.stringify(report,null,2);let lines=["schedule-run doctor (read-only diagnostics)",`Platform: ${report.platform}`];if(!report.platformSupported)lines.push(report.unsupportedMessage??unsupportedSchedulerPlatformMessage(report.platform));else{lines.push(`Candidate backends (in order): ${report.candidateBackends.join(", ")}`);for(let a of report.backendAvailability)lines.push(` ${a.available?"AVAILABLE ":"UNAVAILABLE"} ${a.backend}`)}return lines.push(`claude on PATH: ${report.claudeResolved?"yes":"no"}`),lines.push(`cursor-agent on PATH: ${report.cursorResolved?"yes":"no"}`),lines.push(`npx on PATH: ${report.npxResolved?"yes":"no"}`),lines.push(`CURSOR_API_KEY set: ${report.cursorApiKeyPresent?"yes":"no"}`),lines.push(`Bridge credential: ${report.bridgeCredentialResolved?"resolved":"not resolved"}`),lines.join(`
126
- `)}function nowIso(deps){return new Date(deps.now?deps.now():Date.now()).toISOString()}async function orchestrateScheduleExecute(options,deps,io){let metadata=await readScheduleMetadata(options.id,deps.homeDir,deps.platform);if(!metadata)return{ok:!1,exitCode:1,error:`No schedule found with id '${options.id}'.`};let agentInvocation=metadata.agent_invocation??metadata.invocation;if(!agentInvocation||!agentInvocation.exe)return await appendScheduleRunEvent(options.id,{status:"failed",at:nowIso(deps),message:"missing agent_invocation"},deps.homeDir,deps.platform).catch(()=>{}),{ok:!1,exitCode:1,error:`Schedule '${options.id}' has no agent invocation to run.`};await appendScheduleRunEvent(options.id,{status:"started",at:nowIso(deps)},deps.homeDir,deps.platform).catch(()=>{});let env={...deps.env};metadata.env_path&&(env.PATH=metadata.env_path,deps.platform==="win32"&&(env.Path=metadata.env_path)),env.BRIDGE_GPT_SCHEDULE_ID=metadata.id,metadata.command&&(env.BRIDGE_GPT_COMMAND=metadata.command),metadata.args&&(env.BRIDGE_GPT_COMMAND_ARGS_JSON=JSON.stringify(metadata.args)),metadata.repo_path&&(env.BRIDGE_GPT_REPO_PATH=metadata.repo_path),metadata.agent&&(env.BRIDGE_GPT_AGENT=metadata.agent),metadata.agent_path&&(env.BRIDGE_GPT_AGENT_PATH=metadata.agent_path),metadata.idea_file&&(env.BRIDGE_GPT_IDEA_FILE=metadata.idea_file);let result;try{result=await deps.runCommand(agentInvocation.exe,agentInvocation.args,{cwd:metadata.repo_path,env})}catch(error){let msg=error instanceof Error?error.message:String(error);return await appendScheduleRunEvent(options.id,{status:"failed",at:nowIso(deps),message:`agent launch failed: ${msg}`},deps.homeDir,deps.platform).catch(()=>{}),{ok:!1,exitCode:1,error:`Failed to launch agent: ${msg}`}}return result.stdout&&io.writeStdout(result.stdout),result.stderr&&io.writeStderr(result.stderr),result.exitCode===0?(await appendScheduleRunEvent(options.id,{status:"completed",at:nowIso(deps),exit_code:0},deps.homeDir,deps.platform).catch(()=>{}),{ok:!0,exitCode:0}):(await appendScheduleRunEvent(options.id,{status:"failed",at:nowIso(deps),exit_code:result.exitCode},deps.homeDir,deps.platform).catch(()=>{}),{ok:!1,exitCode:result.exitCode})}async function runScheduleRunCli(argv,overrides={}){let log=overrides.log??(m=>console.log(m)),errorLog=overrides.errorLog??(m=>console.error(m)),parsed=parseScheduleRunArgs(argv);if(parsed.status==="help")return log(parsed.usage),0;if(parsed.status==="error")return errorLog(`Error: ${parsed.message}`),errorLog(""),errorLog(getScheduleRunUsage()),1;let deps=overrides.deps??createDefaultScheduleRunDeps();try{switch(parsed.subcommand){case"create":{let result=await orchestrateScheduleCreate(parsed.options,deps);return result.ok?(log(formatScheduleCreateResult(result)),0):(errorLog(formatScheduleCreateResult(result)),1)}case"list":{let report=await orchestrateScheduleList(parsed.options,deps);return log(formatScheduleListResult(report,parsed.options.json)),0}case"cancel":{let result=await orchestrateScheduleCancel(parsed.options,deps);return result.ok?(log(formatScheduleCancelResult(result)),0):(errorLog(formatScheduleCancelResult(result)),1)}case"doctor":{let report=await orchestrateScheduleDoctor(deps);return log(formatScheduleDoctorReport(report,parsed.options.json)),report.platformSupported?0:1}case"_execute":{let io={writeStdout:overrides.writeStdout??(chunk=>process.stdout.write(chunk)),writeStderr:overrides.writeStderr??(chunk=>process.stderr.write(chunk))},result=await orchestrateScheduleExecute(parsed.options,deps,io);return!result.ok&&result.error&&errorLog(`Error: ${result.error}`),result.exitCode}}}catch(error){let detail=error instanceof Error?error.message:String(error);return errorLog(`Internal error: ${detail}`),errorLog("Error: schedule-run failed unexpectedly. See the message above for local diagnostics."),1}return 1}var VALID_BACKEND_NAMES,SCHEDULE_ID_PATTERN,init_schedule_run=__esm({"src/schedule-run.ts"(){"use strict";init_scheduler_backends();init_schedule_store();init_agent_launchers();init_claude();init_command_catalog();init_scheduled_prompt();VALID_BACKEND_NAMES=["launchd","task-scheduler","systemd-user","at-fallback"],SCHEDULE_ID_PATTERN=/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/}});function listAgentNames(){return Object.keys(AGENT_REGISTRY)}function isAgentName(value){return listAgentNames().includes(value)}function resolveAgentSpec(name){let resolved=name??DEFAULT_AGENT_NAME;return isAgentName(resolved)?AGENT_REGISTRY[resolved]:null}var AGENT_REGISTRY,DEFAULT_AGENT_NAME,init_agent_registry=__esm({"src/agent-registry.ts"(){"use strict";AGENT_REGISTRY={claude:{name:"claude",command:"claude",promptArgStyle:"positional",installHint:{darwin:"npm install -g @anthropic-ai/claude-code",linux:"npm install -g @anthropic-ai/claude-code",win32:"npm install -g @anthropic-ai/claude-code"},authNote:"Claude Code authenticates interactively on first run \u2014 follow its login/auth prompt if asked.",supportsModelOverride:!0,modelFlag:"--model",tierModels:{cheap:"haiku",basic:"sonnet",premium:"opus"},staticModelAliasAllowlist:["haiku","sonnet","opus"]},"cursor-agent":{name:"cursor-agent",command:"cursor-agent",promptArgStyle:"positional",installHint:{darwin:"curl https://cursor.com/install -fsSL | bash",linux:"curl https://cursor.com/install -fsSL | bash",win32:"irm 'https://cursor.com/install?win32=true' | iex"},authNote:"Run cursor-agent login to authenticate; doctor checks PATH presence only, not login state.",supportsModelOverride:!0,modelFlag:"--model",tierModels:{cheap:"auto",basic:"claude-4.6-sonnet-medium",premium:"claude-opus-4-8-thinking-high"}}},DEFAULT_AGENT_NAME="claude"}});var DEFAULT_PROBE_TIMEOUT_MS,init_types2=__esm({"src/agent-capabilities/types.ts"(){"use strict";DEFAULT_PROBE_TIMEOUT_MS=9e4}});import{join}from"node:path";function buildHeadlessArgs(agentName,opts){let fmt=opts.outputFormat??"text";if(agentName==="cursor-agent")return["-p","--output-format",fmt,"--trust","--workspace",opts.cwd,opts.prompt];let args=["-p"];return opts.permissionMode==="acceptEdits"?args.push("--permission-mode","acceptEdits"):opts.skipPermissions===!0&&args.push("--dangerously-skip-permissions"),typeof opts.model=="string"&&opts.model.trim().length>0&&args.push("--model",opts.model),fmt==="json"?args.push("--output-format","json"):fmt==="stream-json"&&args.push("--output-format","stream-json","--verbose"),args.push(opts.prompt),args}async function createProbeContext(deps,agent,defaultTimeoutMs=DEFAULT_PROBE_TIMEOUT_MS){let launcherDeps={platform:deps.platform,env:deps.env,runCommand:(file,args,options)=>deps.runCommand(file,args,options)},resolvedBinary=await resolveCommandOnPath(agent.command,deps.env.PATH??"",launcherDeps),createdDirs=[],counter=0;return{ctx:{agent,deps,resolvedBinary,marker(name){return`${name}_${deps.uniqueSuffix()}_${counter++}`},async makeTempProject(seed){let dir=await deps.mkdtemp(join(deps.tmpRoot,"agent-cap-"));return createdDirs.push(dir),seed&&await seed(dir),dir},async runHeadless(opts){let exe=resolvedBinary??agent.command,args=buildHeadlessArgs(agent.name,opts),timeoutMs=opts.timeoutMs??defaultTimeoutMs,controller=new AbortController,timedOut=!1,timer=setTimeout(()=>{timedOut=!0,controller.abort()},timeoutMs),start=deps.now();try{let result=await deps.runCommand(exe,args,{cwd:opts.cwd,env:deps.env,signal:controller.signal}),elapsedMs=deps.now()-start;return timedOut?{kind:"hang",elapsedMs,partialStdout:result.stdout??""}:{kind:"exited",exitCode:result.exitCode,stdout:result.stdout??"",stderr:result.stderr??"",elapsedMs}}catch(err){let elapsedMs=deps.now()-start;return timedOut?{kind:"hang",elapsedMs,partialStdout:""}:{kind:"spawn-error",message:err instanceof Error?err.message:String(err)}}finally{clearTimeout(timer)}}},cleanup:async()=>{for(let dir of createdDirs.splice(0))try{await deps.rm(dir,{recursive:!0,force:!0})}catch{}}}}var init_probe_context=__esm({"src/agent-capabilities/probe-context.ts"(){"use strict";init_claude();init_types2()}});import{execFile as execFile2}from"node:child_process";import{mkdtemp,rm,writeFile,mkdir}from"node:fs/promises";import os2 from"node:os";import{randomBytes}from"node:crypto";function createDefaultAgentCapabilitiesDeps(){let runCommand=(file,args,options)=>new Promise(resolve2=>{execFile2(file,args,{cwd:options?.cwd,env:options?.env??process.env,signal:options?.signal,killSignal:"SIGKILL",maxBuffer:67108864,encoding:"utf-8"},(error,stdout,stderr)=>{let exitCode=error&&typeof error.code=="number"?error.code:error?1:0;resolve2({stdout:stdout??"",stderr:stderr??"",exitCode})})});return{platform:process.platform,env:process.env,runCommand,tmpRoot:os2.tmpdir(),mkdtemp:prefix=>mkdtemp(prefix),rm:(target,opts)=>rm(target,opts),writeFile:(target,data)=>writeFile(target,data,"utf-8"),mkdir:(target,opts)=>mkdir(target,opts).then(()=>{}),now:()=>Date.now(),uniqueSuffix:()=>randomBytes(3).toString("hex").toUpperCase()}}var init_default_deps=__esm({"src/agent-capabilities/default-deps.ts"(){"use strict"}});import{join as join2}from"node:path";function truncate(text){let flat=text.replace(/\s+/g," ").trim();return flat.length>EVIDENCE_MAX?`${flat.slice(0,EVIDENCE_MAX)}\u2026`:flat}function nonExitedResult(run){return run.kind==="hang"?{status:"hang",detail:`agent did not exit within the timeout (${run.elapsedMs}ms) \u2014 likely the version-sensitive -p hang`,elapsedMs:run.elapsedMs,evidence:run.partialStdout?truncate(run.partialStdout):void 0}:run.kind==="spawn-error"?{status:"fail",detail:`could not spawn agent: ${run.message}`}:null}function denyHookCommand(){return`printf '%s' '${JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"agent-capability deny-enforcement probe fallback: tool call denied."}})}'`}async function seedDenyTargetFile(ctx,dir,marker){await ctx.deps.writeFile(join2(dir,DENY_TARGET_FILE),`${marker}
126
+ `)}function nowIso(deps){return new Date(deps.now?deps.now():Date.now()).toISOString()}async function orchestrateScheduleExecute(options,deps,io){let metadata=await readScheduleMetadata(options.id,deps.homeDir,deps.platform);if(!metadata)return{ok:!1,exitCode:1,error:`No schedule found with id '${options.id}'.`};let agentInvocation=metadata.agent_invocation??metadata.invocation;if(!agentInvocation||!agentInvocation.exe)return await appendScheduleRunEvent(options.id,{status:"failed",at:nowIso(deps),message:"missing agent_invocation"},deps.homeDir,deps.platform).catch(()=>{}),{ok:!1,exitCode:1,error:`Schedule '${options.id}' has no agent invocation to run.`};await appendScheduleRunEvent(options.id,{status:"started",at:nowIso(deps)},deps.homeDir,deps.platform).catch(()=>{});let env={...deps.env};metadata.env_path&&(env.PATH=metadata.env_path,deps.platform==="win32"&&(env.Path=metadata.env_path)),env.BRIDGE_GPT_SCHEDULE_ID=metadata.id,metadata.command&&(env.BRIDGE_GPT_COMMAND=metadata.command),metadata.args&&(env.BRIDGE_GPT_COMMAND_ARGS_JSON=JSON.stringify(metadata.args)),metadata.repo_path&&(env.BRIDGE_GPT_REPO_PATH=metadata.repo_path),metadata.agent&&(env.BRIDGE_GPT_AGENT=metadata.agent),metadata.agent_path&&(env.BRIDGE_GPT_AGENT_PATH=metadata.agent_path),metadata.idea_file&&(env.BRIDGE_GPT_IDEA_FILE=metadata.idea_file);let result;try{result=await deps.runCommand(agentInvocation.exe,agentInvocation.args,{cwd:metadata.repo_path,env})}catch(error){let msg=error instanceof Error?error.message:String(error);return await appendScheduleRunEvent(options.id,{status:"failed",at:nowIso(deps),message:`agent launch failed: ${msg}`},deps.homeDir,deps.platform).catch(()=>{}),{ok:!1,exitCode:1,error:`Failed to launch agent: ${msg}`}}return result.stdout&&io.writeStdout(result.stdout),result.stderr&&io.writeStderr(result.stderr),result.exitCode===0?(await appendScheduleRunEvent(options.id,{status:"completed",at:nowIso(deps),exit_code:0},deps.homeDir,deps.platform).catch(()=>{}),{ok:!0,exitCode:0}):(await appendScheduleRunEvent(options.id,{status:"failed",at:nowIso(deps),exit_code:result.exitCode},deps.homeDir,deps.platform).catch(()=>{}),{ok:!1,exitCode:result.exitCode})}async function runScheduleRunCli(argv,overrides={}){let log=overrides.log??(m=>console.log(m)),errorLog=overrides.errorLog??(m=>console.error(m)),parsed=parseScheduleRunArgs(argv);if(parsed.status==="help")return log(parsed.usage),0;if(parsed.status==="error")return errorLog(`Error: ${parsed.message}`),errorLog(""),errorLog(getScheduleRunUsage()),1;let deps=overrides.deps??createDefaultScheduleRunDeps();try{switch(parsed.subcommand){case"create":{let result=await orchestrateScheduleCreate(parsed.options,deps);return result.ok?(log(formatScheduleCreateResult(result)),0):(errorLog(formatScheduleCreateResult(result)),1)}case"list":{let report=await orchestrateScheduleList(parsed.options,deps);return log(formatScheduleListResult(report,parsed.options.json)),0}case"cancel":{let result=await orchestrateScheduleCancel(parsed.options,deps);return result.ok?(log(formatScheduleCancelResult(result)),0):(errorLog(formatScheduleCancelResult(result)),1)}case"doctor":{let report=await orchestrateScheduleDoctor(deps);return log(formatScheduleDoctorReport(report,parsed.options.json)),report.platformSupported?0:1}case"_execute":{let io={writeStdout:overrides.writeStdout??(chunk=>process.stdout.write(chunk)),writeStderr:overrides.writeStderr??(chunk=>process.stderr.write(chunk))},result=await orchestrateScheduleExecute(parsed.options,deps,io);return!result.ok&&result.error&&errorLog(`Error: ${result.error}`),result.exitCode}}}catch(error){let detail=error instanceof Error?error.message:String(error);return errorLog(`Internal error: ${detail}`),errorLog("Error: schedule-run failed unexpectedly. See the message above for local diagnostics."),1}return 1}var VALID_BACKEND_NAMES,SCHEDULE_ID_PATTERN,init_schedule_run=__esm({"src/schedule-run.ts"(){"use strict";init_scheduler_backends();init_schedule_store();init_agent_launchers();init_claude();init_command_catalog();init_scheduled_prompt();VALID_BACKEND_NAMES=["launchd","task-scheduler","systemd-user","at-fallback"],SCHEDULE_ID_PATTERN=/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/}});function listAgentNames(){return Object.keys(AGENT_REGISTRY)}function isAgentName(value){return listAgentNames().includes(value)}function resolveAgentSpec(name){let resolved=name??DEFAULT_AGENT_NAME;return isAgentName(resolved)?AGENT_REGISTRY[resolved]:null}var AGENT_REGISTRY,DEFAULT_AGENT_NAME,init_agent_registry=__esm({"src/agent-registry.ts"(){"use strict";AGENT_REGISTRY={claude:{name:"claude",command:"claude",promptArgStyle:"positional",installHint:{darwin:"npm install -g @anthropic-ai/claude-code",linux:"npm install -g @anthropic-ai/claude-code",win32:"npm install -g @anthropic-ai/claude-code"},authNote:"Claude Code authenticates interactively on first run \u2014 follow its login/auth prompt if asked.",supportsModelOverride:!0,modelFlag:"--model",tierModels:{cheap:"haiku",basic:"sonnet",premium:"opus"},staticModelAliasAllowlist:["haiku","sonnet","opus"],executorAdapter:{adapterId:"claude-reference",strategyId:"claude-strict-mcp-v1",adapterVersion:"1.0.0",supportedPlatforms:["darwin","linux"],capabilityStrategyIds:{mcpScoping:"strict-mcp-config",mcpInitParsing:"claude-system-init",authFailureDetection:"claude-stream-json-result",denyEnforcement:"claude-settings-deny",redaction:"claude-env-name-redaction",lifecycle:"claude-no-lifecycle"},managedCarriers:[],passthroughs:[{passthroughId:"claude-code-oauth-token",envName:"CLAUDE_CODE_OAUTH_TOKEN",billingClass:"subscription",ownership:"operator-owned",rule:"forward-when-present"}]}},"cursor-agent":{name:"cursor-agent",command:"cursor-agent",promptArgStyle:"positional",installHint:{darwin:"curl https://cursor.com/install -fsSL | bash",linux:"curl https://cursor.com/install -fsSL | bash",win32:"irm 'https://cursor.com/install?win32=true' | iex"},authNote:"Run cursor-agent login to authenticate; doctor checks PATH presence only, not login state.",supportsModelOverride:!0,modelFlag:"--model",tierModels:{cheap:"auto",basic:"claude-4.6-sonnet-medium",premium:"claude-opus-4-8-thinking-high"}}},DEFAULT_AGENT_NAME="claude"}});var DEFAULT_PROBE_TIMEOUT_MS,init_types2=__esm({"src/agent-capabilities/types.ts"(){"use strict";DEFAULT_PROBE_TIMEOUT_MS=9e4}});import{join}from"node:path";function buildHeadlessArgs(agentName,opts){let fmt=opts.outputFormat??"text";if(agentName==="cursor-agent")return["-p","--output-format",fmt,"--trust","--workspace",opts.cwd,opts.prompt];let args=["-p"];return opts.permissionMode==="acceptEdits"?args.push("--permission-mode","acceptEdits"):opts.skipPermissions===!0&&args.push("--dangerously-skip-permissions"),typeof opts.model=="string"&&opts.model.trim().length>0&&args.push("--model",opts.model),fmt==="json"?args.push("--output-format","json"):fmt==="stream-json"&&args.push("--output-format","stream-json","--verbose"),args.push(opts.prompt),args}async function createProbeContext(deps,agent,defaultTimeoutMs=DEFAULT_PROBE_TIMEOUT_MS){let launcherDeps={platform:deps.platform,env:deps.env,runCommand:(file,args,options)=>deps.runCommand(file,args,options)},resolvedBinary=await resolveCommandOnPath(agent.command,deps.env.PATH??"",launcherDeps),createdDirs=[],counter=0;return{ctx:{agent,deps,resolvedBinary,marker(name){return`${name}_${deps.uniqueSuffix()}_${counter++}`},async makeTempProject(seed){let dir=await deps.mkdtemp(join(deps.tmpRoot,"agent-cap-"));return createdDirs.push(dir),seed&&await seed(dir),dir},async runHeadless(opts){let exe=resolvedBinary??agent.command,args=buildHeadlessArgs(agent.name,opts),timeoutMs=opts.timeoutMs??defaultTimeoutMs,controller=new AbortController,timedOut=!1,timer=setTimeout(()=>{timedOut=!0,controller.abort()},timeoutMs),start=deps.now();try{let result=await deps.runCommand(exe,args,{cwd:opts.cwd,env:deps.env,signal:controller.signal}),elapsedMs=deps.now()-start;return timedOut?{kind:"hang",elapsedMs,partialStdout:result.stdout??""}:{kind:"exited",exitCode:result.exitCode,stdout:result.stdout??"",stderr:result.stderr??"",elapsedMs}}catch(err){let elapsedMs=deps.now()-start;return timedOut?{kind:"hang",elapsedMs,partialStdout:""}:{kind:"spawn-error",message:err instanceof Error?err.message:String(err)}}finally{clearTimeout(timer)}}},cleanup:async()=>{for(let dir of createdDirs.splice(0))try{await deps.rm(dir,{recursive:!0,force:!0})}catch{}}}}var init_probe_context=__esm({"src/agent-capabilities/probe-context.ts"(){"use strict";init_claude();init_types2()}});import{execFile as execFile2}from"node:child_process";import{mkdtemp,rm,writeFile,mkdir}from"node:fs/promises";import os2 from"node:os";import{randomBytes}from"node:crypto";function createDefaultAgentCapabilitiesDeps(){let runCommand=(file,args,options)=>new Promise(resolve2=>{execFile2(file,args,{cwd:options?.cwd,env:options?.env??process.env,signal:options?.signal,killSignal:"SIGKILL",maxBuffer:67108864,encoding:"utf-8"},(error,stdout,stderr)=>{let exitCode=error&&typeof error.code=="number"?error.code:error?1:0;resolve2({stdout:stdout??"",stderr:stderr??"",exitCode})})});return{platform:process.platform,env:process.env,runCommand,tmpRoot:os2.tmpdir(),mkdtemp:prefix=>mkdtemp(prefix),rm:(target,opts)=>rm(target,opts),writeFile:(target,data)=>writeFile(target,data,"utf-8"),mkdir:(target,opts)=>mkdir(target,opts).then(()=>{}),now:()=>Date.now(),uniqueSuffix:()=>randomBytes(3).toString("hex").toUpperCase()}}var init_default_deps=__esm({"src/agent-capabilities/default-deps.ts"(){"use strict"}});import{join as join2}from"node:path";function truncate(text){let flat=text.replace(/\s+/g," ").trim();return flat.length>EVIDENCE_MAX?`${flat.slice(0,EVIDENCE_MAX)}\u2026`:flat}function nonExitedResult(run){return run.kind==="hang"?{status:"hang",detail:`agent did not exit within the timeout (${run.elapsedMs}ms) \u2014 likely the version-sensitive -p hang`,elapsedMs:run.elapsedMs,evidence:run.partialStdout?truncate(run.partialStdout):void 0}:run.kind==="spawn-error"?{status:"fail",detail:`could not spawn agent: ${run.message}`}:null}function denyHookCommand(){return`printf '%s' '${JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"agent-capability deny-enforcement probe fallback: tool call denied."}})}'`}async function seedDenyTargetFile(ctx,dir,marker){await ctx.deps.writeFile(join2(dir,DENY_TARGET_FILE),`${marker}
127
127
  `)}async function seedDenySettings(ctx,dir,marker){await seedDenyTargetFile(ctx,dir,marker);let claudeDir=join2(dir,".claude");await ctx.deps.mkdir(claudeDir,{recursive:!0});let settings={permissions:{deny:[DENY_BASH_RULE]}};await ctx.deps.writeFile(join2(claudeDir,"settings.local.json"),`${JSON.stringify(settings,null,2)}
128
128
  `)}async function seedDenyHook(ctx,dir,marker){await seedDenyTargetFile(ctx,dir,marker);let claudeDir=join2(dir,".claude");await ctx.deps.mkdir(claudeDir,{recursive:!0});let settings={hooks:{PreToolUse:[{matcher:DENY_HOOK_MATCHER,hooks:[{type:"command",command:denyHookCommand()}]}]}};await ctx.deps.writeFile(join2(claudeDir,"settings.local.json"),`${JSON.stringify(settings,null,2)}
129
129
  `)}function denyProbePrompt(){return["This is an agent-capability probe of permission enforcement.",`Use the Bash tool to run exactly this command: cat ${DENY_TARGET_FILE}`,"Then output the command's exact stdout on its own line.","Use ONLY the Bash tool for this \u2014 do not use Read, Grep, or any other tool, and do not open the file yourself.","If the Bash command is blocked, denied, or errors, output the single word DENIED and nothing else.","Do not guess, fabricate, or infer the file contents \u2014 only report what the command actually returned."].join(`
130
- `)}function withDenyLayer(result,layer){return{...result,metadata:{...result.metadata??{},layer}}}function evaluateDenyRun(run,allowedMarker){let nonExited=nonExitedResult(run);if(nonExited)return{kind:"nonexited",result:nonExited};let{exitCode,stdout,stderr,elapsedMs}=run;return exitCode!==0?{kind:"error",result:{status:"fail",detail:`deny-enforcement probe agent exited ${exitCode}`,elapsedMs,evidence:truncate(stdout||stderr)}}:stdout.includes(allowedMarker)?{kind:"allowed",evidence:truncate(stdout)}:{kind:"blocked",evidence:truncate(stdout||stderr)}}async function runDenyEnforcementCheck(ctx,opts){let marker=ctx.marker("DENY_ALLOWED"),prompt=denyProbePrompt(),acceptEdits=opts?.permissionPosture==="accept_edits",runOpts={skipPermissions:!acceptEdits,permissionMode:acceptEdits?"acceptEdits":void 0,model:opts?.model,timeoutMs:opts?.timeoutMs},controlDir=await ctx.makeTempProject(d=>seedDenyTargetFile(ctx,d,marker)),controlRun=await ctx.runHeadless({prompt,cwd:controlDir,...runOpts}),c=evaluateDenyRun(controlRun,marker);if(c.kind==="nonexited")return{result:withDenyLayer(c.result,"none"),layer:"none"};if(c.kind==="error")return{result:withDenyLayer(c.result,"none"),layer:"none"};if(c.kind==="blocked")return{result:withDenyLayer({status:"fail",detail:"control run (no deny rule) did not execute the canary call \u2014 the agent never attempted the Bash command, so deny enforcement cannot be verified (a refusal is NOT enforcement)",elapsedMs:controlRun.elapsedMs,evidence:c.evidence},"none"),layer:"none"};let denyDir=await ctx.makeTempProject(d=>seedDenySettings(ctx,d,marker)),settingsRun=await ctx.runHeadless({prompt,cwd:denyDir,...runOpts}),s=evaluateDenyRun(settingsRun,marker);if(s.kind==="nonexited")return{result:withDenyLayer(s.result,"none"),layer:"none"};if(s.kind==="error")return{result:withDenyLayer(s.result,"none"),layer:"none"};if(s.kind==="blocked")return{result:withDenyLayer({status:"pass",detail:"denied call rejected by settings permissions.deny",elapsedMs:settingsRun.elapsedMs,evidence:s.evidence},"settings-deny"),layer:"settings-deny"};let hookDir=await ctx.makeTempProject(d=>seedDenyHook(ctx,d,marker)),hookRun=await ctx.runHeadless({prompt,cwd:hookDir,...runOpts}),h=evaluateDenyRun(hookRun,marker);return h.kind==="nonexited"?{result:withDenyLayer(h.result,"none"),layer:"none"}:h.kind==="error"?{result:withDenyLayer(h.result,"none"),layer:"none"}:h.kind==="blocked"?{result:withDenyLayer({status:"pass",detail:"settings deny did not reject; PreToolUse hook fallback rejected the call",elapsedMs:hookRun.elapsedMs,evidence:h.evidence},"pretooluse-hook"),layer:"pretooluse-hook"}:{result:withDenyLayer({status:"fail",detail:"deny is NOT enforced for this installed Claude version under --dangerously-skip-permissions (neither settings permissions.deny nor a PreToolUse hook rejected the denied call)",elapsedMs:hookRun.elapsedMs,evidence:h.evidence},"none"),layer:"none"}}var EVIDENCE_MAX,DENY_TARGET_FILE,DENY_BASH_RULE,DENY_HOOK_MATCHER,init_probes=__esm({"src/agent-capabilities/probes.ts"(){"use strict";init_probe_context();EVIDENCE_MAX=200;DENY_TARGET_FILE="deny-probe-target.txt",DENY_BASH_RULE="Bash(cat:*)",DENY_HOOK_MATCHER="Bash"}});var deny_enforcement_preflight_exports={};__export(deny_enforcement_preflight_exports,{runDenyEnforcementPreflight:()=>runDenyEnforcementPreflight});async function runDenyEnforcementPreflight(opts={}){try{let agent=resolveAgentSpec("claude");if(!agent)return{enforced:!1,layer:"none",degraded:!0,warnings:["Could not resolve the 'claude' agent spec for the deny-enforcement preflight.",REFUSE_TO_CLAIM_WARNING]};let deps=opts.capabilityDeps??createDefaultAgentCapabilitiesDeps(),{ctx,cleanup}=await createProbeContext(deps,agent,opts.timeoutMs);try{let{result,layer}=await runDenyEnforcementCheck(ctx,{model:opts.model,timeoutMs:opts.timeoutMs,permissionPosture:opts.permissionPosture});return result.status==="pass"&&layer==="settings-deny"?{enforced:!0,layer:"settings-deny",degraded:!1,warnings:[],status:result.status,detail:result.detail}:result.status==="pass"&&layer==="pretooluse-hook"?{enforced:!0,layer:"pretooluse-hook",degraded:!0,warnings:["settings permissions.deny was not enforced under --dangerously-skip-permissions; relying on PreToolUse fallback."],status:result.status,detail:result.detail}:{enforced:!1,layer:"none",degraded:!0,warnings:[`Deny-layer enforcement probe did not pass: ${result.detail}`,REFUSE_TO_CLAIM_WARNING],status:result.status,detail:result.detail}}finally{await cleanup()}}catch(err){return{enforced:!1,layer:"none",degraded:!0,warnings:[`Deny-layer enforcement preflight failed unexpectedly: ${err instanceof Error?err.message:String(err)}`,REFUSE_TO_CLAIM_WARNING]}}}var REFUSE_TO_CLAIM_WARNING,init_deny_enforcement_preflight=__esm({"src/conductor/deny-enforcement-preflight.ts"(){"use strict";init_agent_registry();init_probe_context();init_default_deps();init_probes();REFUSE_TO_CLAIM_WARNING="The executor claim loop MUST refuse to claim jobs until settings permissions.deny or the PreToolUse fallback enforces the deny layer."}});function parseBoundedSupervisorInt(raw,fallback,min,max){if(raw===void 0)return fallback;let trimmed=raw.trim();if(trimmed.length===0||!/^[+-]?\d+$/.test(trimmed))return fallback;let parsed=Number.parseInt(trimmed,10);return Number.isFinite(parsed)?Math.min(max,Math.max(min,parsed)):fallback}function resolveSupervisorConfig(overrides={},env=process.env){let wake_interval_ms=clampOverride(overrides.wake_interval_ms,parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_WAKE_INTERVAL_MS,45e3,3e4,6e4),3e4,6e4),global_timeout_ms=clampOverride(overrides.global_timeout_ms,parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_GLOBAL_TIMEOUT_MS,864e5,3e5,6048e5),3e5,6048e5),escalation_cooldown_ms=clampOverride(overrides.escalation_cooldown_ms,parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_ESCALATION_COOLDOWN_MS,9e5,3e5,864e5),3e5,864e5),quiet_after_ms=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_QUIET_AFTER_MS,3e5,6e4,36e5),liveness_stalled_after_ms=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_LIVENESS_STALLED_AFTER_MS,12e5,3e5,144e5),dead_after_ms=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_DEAD_AFTER_MS,72e5,6e5,864e5),poll_limit=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_SUPERVISOR_POLL_LIMIT,POLL_LIMIT_DEFAULT2,POLL_LIMIT_MIN,POLL_LIMIT_MAX2);return{wake_interval_ms,global_timeout_ms,stall_thresholds_ms:resolveStallThresholds(env),liveness:{quiet_after_ms,stalled_after_ms:liveness_stalled_after_ms,dead_after_ms},escalation_cooldown_ms,poll_limit}}function clampOverride(override,base,min,max){return override===void 0||!Number.isFinite(override)?base:Math.min(max,Math.max(min,Math.floor(override)))}function resolveStallThresholds(env){return{not_started:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_NOT_STARTED_MS,15*6e4,6e4,36e5),active:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_ACTIVE_MS,2*36e5,10*6e4,12*36e5),stalled:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_STALLED_MS,30*6e4,5*6e4,6*36e5),blocked:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_BLOCKED_MS,24*36e5,30*6e4,168*36e5),candidate_done:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_CANDIDATE_DONE_MS,30*6e4,5*6e4,6*36e5),verifying:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_VERIFYING_MS,2*36e5,10*6e4,12*36e5),unknown:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_UNKNOWN_MS,30*6e4,5*6e4,6*36e5),complete:Number.MAX_SAFE_INTEGER,failed:Number.MAX_SAFE_INTEGER}}var POLL_LIMIT_DEFAULT2,POLL_LIMIT_MIN,POLL_LIMIT_MAX2,init_supervisor_config=__esm({"src/conductor/supervisor-config.ts"(){"use strict";POLL_LIMIT_DEFAULT2=200,POLL_LIMIT_MIN=1,POLL_LIMIT_MAX2=1e3}});import path6 from"path";function hasControlChars(value){for(let i=0;i<value.length;i++){let code=value.charCodeAt(i);if(code<=31||code===127)return!0}return!1}function validateRepoName(raw){if(typeof raw!="string")return{ok:!1,error:"repo_name must be a string"};let value=raw.trim();return value.length===0?{ok:!1,error:"repo_name must be a non-empty string"}:value.includes("/")||value.includes("\\")?{ok:!1,error:"repo_name must not contain path separators"}:hasControlChars(value)?{ok:!1,error:"repo_name must not contain control characters"}:{ok:!0,value}}function validateMcpTarget(raw){if(typeof raw!="string")return{ok:!1,error:"mcp target must be a string"};let value=raw.trim();return value.length===0?{ok:!1,error:"mcp target must be a non-empty string"}:value.includes("/")||value.includes("\\")?{ok:!1,error:"mcp target must not contain path separators"}:hasControlChars(value)?{ok:!1,error:"mcp target must not contain control characters"}:{ok:!0,value}}function parseQuotedString(value){if(value.length<2||value[0]!=='"'||value[value.length-1]!=='"')return null;let inner=value.slice(1,-1);return inner.includes('"')?null:inner}function parseStringArray(value){let trimmed=value.trim();if(trimmed.length<2||trimmed[0]!=="["||trimmed[trimmed.length-1]!=="]")return null;let inner=trimmed.slice(1,-1).trim();if(inner.length===0)return[];let parts=inner.split(","),out=[];for(let part of parts){let element=parseQuotedString(part.trim());if(element===null)return null;out.push(element)}return out}function parseBridgeConfigToml(text){let lines=text.split(`
131
- `),repoName,sawRepoName=!1,mcp=[],currentMcp=null;for(let i=0;i<lines.length;i++){let lineNo=i+1,line=lines[i].trim();if(line.length===0||line.startsWith("#"))continue;if(line==="[[mcp]]"){currentMcp={headerLine:lineNo},mcp.push(currentMcp);continue}if(line.startsWith("["))return{ok:!1,kind:"parse-error",error:`Unsupported table header on line ${lineNo}; only [[mcp]] is allowed`};let eq=line.indexOf("=");if(eq===-1)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; expected key = "value"`};let key=line.slice(0,eq).trim(),rawValue=line.slice(eq+1).trim();if(key.length===0)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; missing key`};if(currentMcp===null){if(key==="repo_name"){if(sawRepoName)return{ok:!1,kind:"parse-error",error:`Duplicate repo_name on line ${lineNo}`};sawRepoName=!0;let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};let validated=validateRepoName(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};repoName=validated.value;continue}return key==="target"?{ok:!1,kind:"parse-error",error:`target on line ${lineNo} must appear inside an [[mcp]] section`}:{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' on line ${lineNo}`}}if(key==="args"){if(currentMcp.args!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate args on line ${lineNo}`};let arr=parseStringArray(rawValue);if(arr===null)return{ok:!1,kind:"parse-error",error:`Expected a string array for 'args' on line ${lineNo}`};currentMcp.args=arr;continue}if(key==="target"||key==="command"||key==="secret_bundle"){let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};if(key==="target"){if(currentMcp.target!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate target on line ${lineNo}`};let validated=validateMcpTarget(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};currentMcp.target=validated.value;continue}if(key==="command"){if(currentMcp.command!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate command on line ${lineNo}`};currentMcp.command=stringValue;continue}if(currentMcp.secretBundle!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate secret_bundle on line ${lineNo}`};currentMcp.secretBundle=stringValue;continue}return{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' inside [[mcp]] on line ${lineNo}`}}if(!sawRepoName||repoName===void 0)return{ok:!1,kind:"validation-error",error:"Missing required repo_name"};let cleaned=[];for(let entry of mcp){if(entry.target===void 0)return{ok:!1,kind:"validation-error",error:`An [[mcp]] section on line ${entry.headerLine} is missing its target`};if(entry.target!=="bapi"){if(entry.command===void 0||entry.command.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty command`};if(entry.args===void 0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires an args array`};if(entry.secretBundle===void 0||entry.secretBundle.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty secret_bundle`}}let clean={target:entry.target};entry.command!==void 0&&(clean.command=entry.command),entry.args!==void 0&&(clean.args=entry.args),entry.secretBundle!==void 0&&(clean.secretBundle=entry.secretBundle),cleaned.push(clean)}return{ok:!0,manifest:{repoName,mcp:cleaned}}}function bridgeConfigPath(projectRoot){return path6.join(projectRoot,".bridge","config")}async function readBridgeConfig(projectRoot,deps){let filePath=bridgeConfigPath(projectRoot),raw;try{raw=await deps.readFile(filePath)}catch(err){return err&&typeof err=="object"&&err.code==="ENOENT"?{ok:!1,kind:"missing"}:{ok:!1,kind:"parse-error",error:"Unable to read .bridge/config"}}return parseBridgeConfigToml(raw)}var init_bridge_config=__esm({"src/bridge-config.ts"(){"use strict"}});async function resolveStartTicketsRepoName(deps){let fromEnv=deps.env.BAPI_REPO_NAME;if(typeof fromEnv=="string"&&fromEnv.trim().length>0)return fromEnv.trim();try{let result=await readBridgeConfig(deps.cwd,{readFile:deps.readFile});if(result.ok&&result.manifest.repoName)return result.manifest.repoName}catch{}return null}var init_start_tickets_repo=__esm({"src/start-tickets-repo.ts"(){"use strict";init_bridge_config()}});var bridge_api_client_exports={};__export(bridge_api_client_exports,{CONDUCTOR_DEFAULT_BASE_URL:()=>CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS:()=>CONDUCTOR_FETCH_TIMEOUT_MS,ConductorBridgeApiError:()=>ConductorBridgeApiError,advanceEpicTicketStatus:()=>advanceEpicTicketStatus,approveEpicPlan:()=>approveEpicPlan,bootstrapConductorSupervisorDefaults:()=>bootstrapConductorSupervisorDefaults,buildConductorJiraUrl:()=>buildConductorJiraUrl,buildConductorVcsUrl:()=>buildConductorVcsUrl,buildEpicDispatchKey:()=>buildEpicDispatchKey,claimEpicSupervisionLease:()=>claimEpicSupervisionLease,createEpicRun:()=>createEpicRun,createEpicRunWithDisposition:()=>createEpicRunWithDisposition,createEpicTicketStatus:()=>createEpicTicketStatus,deletePullRequestBranch:()=>deletePullRequestBranch,extractSanitizedErrorDiagnostics:()=>extractSanitizedErrorDiagnostics,fetchActiveEpicRuns:()=>fetchActiveEpicRuns,fetchConductorConfigField:()=>fetchConductorConfigField,fetchConductorJsonPatchWithTimeout:()=>fetchConductorJsonPatchWithTimeout,fetchConductorJsonPostWithTimeout:()=>fetchConductorJsonPostWithTimeout,fetchConductorJsonPutWithTimeout:()=>fetchConductorJsonPutWithTimeout,fetchConductorJsonWithTimeout:()=>fetchConductorJsonWithTimeout,fetchConductorReadiness:()=>fetchConductorReadiness,fetchEffectiveSupervisorConfig:()=>fetchEffectiveSupervisorConfig,fetchEffectiveSupervisorSetup:()=>fetchEffectiveSupervisorSetup,fetchEpicRunState:()=>fetchEpicRunState,fetchParseStatus:()=>fetchParseStatus,fetchPrReviewStatus:()=>fetchPrReviewStatus,fetchShadowDispatchFreshness:()=>fetchShadowDispatchFreshness,getEpicPlan:()=>getEpicPlan,mergePullRequestForGate:()=>mergePullRequestForGate,parseConductorReadinessResponse:()=>parseConductorReadinessResponse,parseConductorSupervisorBootstrapResponse:()=>parseConductorSupervisorBootstrapResponse,pollCiChecksForCommit:()=>pollCiChecksForCommit,reconcileShadowMerge:()=>reconcileShadowMerge,recordEpicDispatch:()=>recordEpicDispatch,remediateEpicTicket:()=>remediateEpicTicket,replaceEpicRunPolicy:()=>replaceEpicRunPolicy,resolveConductorBridgeApiAccess:()=>resolveConductorBridgeApiAccess,safeDiagnosticMessage:()=>safeDiagnosticMessage,storeEpicPlan:()=>storeEpicPlan,transitionEpicDispatch:()=>transitionEpicDispatch,transitionJiraStatus:()=>transitionJiraStatus,triggerRepositoryParse:()=>triggerRepositoryParse,updateApprovedPlanNodeTicketSpec:()=>updateApprovedPlanNodeTicketSpec,updateEpicRunStatus:()=>updateEpicRunStatus,validateEpicPlan:()=>validateEpicPlan});import os3 from"node:os";import{readFile,stat}from"node:fs/promises";async function resolveConductorBridgeApiAccess(deps={}){let env=deps.env??process.env,cwd=deps.cwd??process.cwd(),homedir=deps.homedir??os3.homedir,platform=deps.platform??process.platform,readFileImpl=deps.readFile??(p=>readFile(p,"utf-8")),statImpl=deps.stat??(p=>stat(p)),repoName=deps.repoName?.trim()||await resolveStartTicketsRepoName({env,cwd,readFile:readFileImpl});if(!repoName)return{ok:!1,kind:"repo-missing",error:"could not resolve repo name (set BAPI_REPO_NAME or add a valid .bridge/config)"};let credResult;try{credResult=await resolveBapiCredentials(repoName,{env,homedir,platform,readFile:readFileImpl,stat:statImpl})}catch{return{ok:!1,kind:"credentials-unavailable",error:"failed to resolve Bridge API credentials"}}if(!credResult.ok)return{ok:!1,kind:"credentials-unavailable",error:"Bridge API credentials unavailable"};let baseUrlRaw=env.BAPI_BASE_URL,baseUrl=typeof baseUrlRaw=="string"&&baseUrlRaw.trim().length>0?baseUrlRaw.trim():CONDUCTOR_DEFAULT_BASE_URL;return{ok:!0,access:{repoName,apiKey:credResult.credentials.apiKey,baseUrl}}}function buildConductorJiraUrl(baseUrl,apiPath,params={}){let trimmed=baseUrl.replace(/\/+$/,""),url=new URL(`${trimmed}/jira${apiPath}`);for(let[k,v]of Object.entries(params))url.searchParams.set(k,v);return url.toString()}function redactErrorPreview(text){return text.replace(/sk-[A-Za-z0-9_-]{8,}/g,"[REDACTED]").replace(/(Bearer|X-API-Key|api[_-]?key)\b\s*[:=]?\s*\S+/gi,"$1 [REDACTED]").replace(/(webhook[_-]?url)\b["']?\s*[:=]?\s*["']?https?:\/\/\S+/gi,"$1 [REDACTED]").replace(/https?:\/\/[^\s/@]+:[^\s/@]+@\S+/gi,"[REDACTED]")}function stripWebhookUrlsDeep(value,depth=0){if(depth>12)return;if(Array.isArray(value))return value.map(item=>stripWebhookUrlsDeep(item,depth+1));if(!value||typeof value!="object")return value;let out={};for(let[key,item]of Object.entries(value))key!=="webhook_url"&&(out[key]=stripWebhookUrlsDeep(item,depth+1));return out}function boundedErrorPreview(text){let redacted=redactErrorPreview(text).replace(/\s+/g," ").trim();return redacted.length>CONDUCTOR_ERROR_PREVIEW_MAX?`${redacted.slice(0,CONDUCTOR_ERROR_PREVIEW_MAX)}\u2026`:redacted}function formatValidationDetailItem(item){if(!item||typeof item!="object")return;let record=item,msg=record.msg;if(typeof msg!="string"||!msg.trim())return;let loc=record.loc,parts=Array.isArray(loc)?loc.filter(part=>typeof part=="string"||typeof part=="number"):[],path7=(parts[0]==="body"?parts.slice(1):parts).slice(0,CONDUCTOR_VALIDATION_LOC_MAX_PARTS).join(".");return path7?`${path7}: ${msg}`:msg}function extractSanitizedErrorDiagnostics(body){if(typeof body=="string"){let trimmed=body.trim();return trimmed?{bodyPreview:boundedErrorPreview(trimmed)}:{}}if(!body||typeof body!="object")return{};let record=body,detail=record.detail,errorCode,message;if(Array.isArray(detail))message=formatValidationDetailItem(detail[0]);else if(detail&&typeof detail=="object"){let d=detail;typeof d.error_code=="string"&&(errorCode=d.error_code),typeof d.message=="string"&&(message=d.message)}else typeof detail=="string"&&(message=detail);!errorCode&&typeof record.error_code=="string"&&(errorCode=record.error_code),!message&&typeof record.message=="string"&&(message=record.message);let diagnostics={};return errorCode&&(diagnostics.errorCode=boundedErrorPreview(errorCode)),message&&(diagnostics.bodyPreview=boundedErrorPreview(message)),diagnostics}function redactDiagnosticValues(diagnostics,secrets){let scrub=text=>{let out2=text;for(let secret of secrets)secret&&secret.length>=4&&(out2=out2.split(secret).join("[REDACTED]"));return out2},out={};return diagnostics.errorCode&&(out.errorCode=scrub(diagnostics.errorCode)),diagnostics.bodyPreview&&(out.bodyPreview=scrub(diagnostics.bodyPreview)),out}async function readSanitizedErrorDiagnostics(resp,headers={}){try{let diagnostics=extractSanitizedErrorDiagnostics(stripWebhookUrlsDeep(await resp.json())),secrets=Object.entries(headers).filter(([k])=>/key|authorization|token/i.test(k)).map(([,v])=>v);return redactDiagnosticValues(diagnostics,secrets)}catch{return{}}}function safeDiagnosticMessage(err,fallback){if(err instanceof ConductorBridgeApiError){let parts=[`kind=${err.kind}`];return typeof err.status=="number"&&parts.push(`status=${err.status}`),err.errorCode&&parts.push(`code=${err.errorCode}`),err.bodyPreview&&parts.push(err.bodyPreview),parts.join(" ")}return err instanceof Error?err.constructor.name:fallback}function conductorGetHeaders(access){return{"X-API-Key":access.apiKey}}async function fetchConductorJsonWithTimeout(url,headers,timeoutMs,fetchImpl=globalThis.fetch){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),timeoutMs);try{let resp;try{resp=await fetchImpl(url,{headers,signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(!resp.ok){let diagnostics=await readSanitizedErrorDiagnostics(resp,headers);throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status,diagnostics):resp.status>=500?new ConductorBridgeApiError("server",resp.status,diagnostics):new ConductorBridgeApiError("http",resp.status,diagnostics)}try{return await resp.json()}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function fetchConductorConfigField(access,fieldName,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`/config-field/${encodeURIComponent(fieldName)}`,{repo_name:access.repoName}),body=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);if(body&&typeof body=="object"&&"value"in body)return body.value}async function fetchEffectiveSupervisorSetup(access,epicKey,fetchImpl=globalThis.fetch){let apiPath=epicKey?`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}/supervisor-setup/`:`${EPIC_RUNS_API_PREFIX}/supervisor-setup/defaults/`,url=buildConductorJiraUrl(access.baseUrl,apiPath,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchEffectiveSupervisorConfig(access,epicKey,fetchImpl=globalThis.fetch){let apiPath=epicKey?`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}/supervisor-config/`:`${EPIC_RUNS_API_PREFIX}/supervisor-config/defaults/`,url=buildConductorJiraUrl(access.baseUrl,apiPath,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function pollCiChecksForCommit(access,commitRef,fetchImpl=globalThis.fetch){let sha=normalizeSha(commitRef);if(sha===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorJiraUrl(access.baseUrl,"/poll-ci-checks",{repo_name:access.repoName,commit_ref:sha});return fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchPrReviewStatus(access,prNumber,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(prNumber);if(pr===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/reviews/status`),fullUrl=new URL(url);return fullUrl.searchParams.set("repo_name",access.repoName),fetchConductorJsonWithTimeout(fullUrl.toString(),conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function buildConductorVcsUrl(baseUrl,apiPath){let trimmed=baseUrl.replace(/\/+$/,""),path7=apiPath.startsWith("/")?apiPath:`/${apiPath}`;return new URL(`${trimmed}${path7}`).toString()}function conductorPostHeaders(access){return{"X-API-Key":access.apiKey,"Content-Type":"application/json"}}async function fetchConductorJsonWithMethodAndTimeout(method,url,headers,body,timeoutMs,fetchImpl){let{body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl);return parsed}async function fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),timeoutMs);try{let resp;try{resp=await fetchImpl(url,{method,headers,body,signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(!resp.ok){let diagnostics=await readSanitizedErrorDiagnostics(resp,headers);throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status,diagnostics):resp.status>=500?new ConductorBridgeApiError("server",resp.status,diagnostics):new ConductorBridgeApiError("http",resp.status,diagnostics)}try{return{status:resp.status,body:await resp.json()}}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function fetchConductorJsonPostWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("POST",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPatchWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PATCH",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPutWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PUT",url,headers,body,timeoutMs,fetchImpl)}async function mergePullRequestForGate(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number),sha=normalizeSha(request.expected_head_sha);if(pr===null||sha===null||!request.action_key||!request.repo_name)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/merge`),body=JSON.stringify({repo_name:request.repo_name,expected_head_sha:sha,gate:request.gate,action_key:request.action_key,...request.gate_event?{gate_event:request.gate_event}:{}});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function remediateEpicTicket(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number);if(pr===null||!request.epic_run_id||!request.ticket_key||!request.head_sha||!request.idempotency_key)throw new ConductorBridgeApiError("invalid-input");if(requireNonNegativeSafeInteger(request.expected_row_version),request.attempt_kind!=="nudge"&&request.attempt_kind!=="redispatch")throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/remediate`),body=JSON.stringify({repo_name:access.repoName,epic_run_id:request.epic_run_id,ticket_key:request.ticket_key,expected_row_version:request.expected_row_version,head_sha:request.head_sha,idempotency_key:request.idempotency_key,attempt_kind:request.attempt_kind,...request.reason?{reason:request.reason}:{}});try{return{ok:!0,conflict:!1,response:await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===409)return{ok:!0,conflict:!0};throw err}}function requireNonEmptyString(value){if(typeof value!="string"||value.trim().length===0)throw new ConductorBridgeApiError("invalid-input")}function requirePositiveSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<=0)throw new ConductorBridgeApiError("invalid-input")}function requireNonNegativeSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<0)throw new ConductorBridgeApiError("invalid-input")}function requireNoSlashPathSegment(value){if(value.includes("/"))throw new ConductorBridgeApiError("invalid-input")}function requireEpicTicketStatusValue(value){if(typeof value!="string"||!EPIC_TICKET_STATUS_VALUES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function requireEpicDispatchTransitionStatus(value){if(typeof value!="string"||!EPIC_DISPATCH_TRANSITION_STATUSES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function epicRunApiPath(epicKey){return`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}`}function epicDispatchTransitionApiPath(dispatchKey,nextStatus){return nextStatus==="run_spawned"?`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/run-spawned`:`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/terminal`}function buildEpicDispatchKey(epicKey,ticketKey,planVersion,attempt=0){requireNonEmptyString(epicKey),requireNonEmptyString(ticketKey),requireNonNegativeSafeInteger(planVersion),requireNonNegativeSafeInteger(attempt);let base=`dispatch:${epicKey}:${ticketKey}:${planVersion}`;return attempt>0?`${base}:r${attempt}`:base}function parseEpicSupervisionLeaseResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed,row=p.row;if(p.claimed===!0&&row&&typeof row=="object")return{ok:!0,kind:"acquired-or-renewed",row};if(p.claimed===!1&&p.reason==="lease_held"&&row&&typeof row=="object")return{ok:!1,kind:"held-by-other",reason:"lease_held",row};if(p.claimed===!1&&p.reason==="terminal"&&row&&typeof row=="object")return{ok:!1,kind:"terminal",reason:"terminal",row};throw new ConductorBridgeApiError("server")}async function claimEpicSupervisionLease(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.leaseOwner),requirePositiveSafeInteger(request.ttlSeconds);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/lease/claim`),body=JSON.stringify({repo_name:access.repoName,lease_owner:request.leaseOwner,ttl_seconds:request.ttlSeconds}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseEpicSupervisionLeaseResult(parsed)}async function fetchEpicRunState(access,epicKey,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/state`,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchActiveEpicRuns(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`,{repo_name:access.repoName,status:"active",limit:"20"}),parsed=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);if(parsed&&typeof parsed=="object"){let runs=parsed.runs;if(Array.isArray(runs))return runs}return[]}async function createEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`);return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function createEpicRunWithDisposition(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`),{status,body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout("POST",url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return{run:parsed,created:status===201}}async function replaceEpicRunPolicy(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicRunId)),body=JSON.stringify({repo_name:access.repoName,policy_json:request.policyJson});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateEpicRunStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicKey)),body=JSON.stringify({repo_name:access.repoName,status:request.status,...request.expectedStatus?{expected_status:request.expectedStatus}:{}});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseAdvanceEpicTicketStatusResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed;if(p.ok===!1&&p.kind==="cas-conflict")return{ok:!1,kind:"cas-conflict",...typeof p.current_row_version=="number"?{current_row_version:p.current_row_version}:{},...p.ticket_status&&typeof p.ticket_status=="object"?{ticket_status:p.ticket_status}:{}};if(p.ok===!0&&p.ticket_status&&typeof p.ticket_status=="object")return{ok:!0,ticket_status:p.ticket_status};if("ticket_key"in p&&"status"in p&&"row_version"in p)return{ok:!0,ticket_status:parsed};throw new ConductorBridgeApiError("server")}async function advanceEpicTicketStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion),requireNonNegativeSafeInteger(request.planVersion),requireEpicTicketStatusValue(request.nextStatus),request.dispatchRunId!==void 0&&requireNonEmptyString(request.dispatchRunId);let CAS_ENDPOINT_PATH=`${epicRunApiPath(request.epicKey)}/tickets/${encodeURIComponent(request.ticketKey)}`,url=buildConductorJiraUrl(access.baseUrl,CAS_ENDPOINT_PATH),body=JSON.stringify({repo_name:access.repoName,status:request.nextStatus,plan_version:request.planVersion,expected_row_version:request.expectedRowVersion,...request.dispatchRunId?{dispatch_run_id:request.dispatchRunId}:{}}),parsed=await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseAdvanceEpicTicketStatusResult(parsed)}async function createEpicTicketStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireEpicTicketStatusValue(request.status),requireNonNegativeSafeInteger(request.planVersion),request.dispatchRunId!==void 0&&requireNonEmptyString(request.dispatchRunId);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/tickets`),body=JSON.stringify({repo_name:access.repoName,ticket_key:request.ticketKey,status:request.status,plan_version:request.planVersion,...request.dispatchRunId?{dispatch_run_id:request.dispatchRunId}:{}});await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseEpicDispatchResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed,row=p.row;if(!row||typeof row!="object")throw new ConductorBridgeApiError("server");let dispatch=row;if(p.claimed===!0)return{ok:!0,kind:"claimed",dispatch};if(p.claimed===!1){let reason=p.reason;if(reason==="already_spawned")return{ok:!0,kind:"already-spawned",dispatch};if(reason==="already_exists")return{ok:!0,kind:"already-exists",dispatch};if(reason==="terminal")return{ok:!0,kind:"terminal",terminal:!0,dispatch};if(reason==="lease_held")return{ok:!1,kind:"lease-held",dispatch}}throw new ConductorBridgeApiError("server")}async function recordEpicDispatch(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.leaseOwner),requireNonNegativeSafeInteger(request.planVersion),requirePositiveSafeInteger(request.ttlSeconds);let dispatchKey=buildEpicDispatchKey(request.epicKey,request.ticketKey,request.planVersion,request.attempt??0)+(request.reviewRole?":review":""),url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/dispatch/claim`),body=JSON.stringify({repo_name:access.repoName,epic_run_id:request.epicKey,ticket_key:request.ticketKey,plan_version:request.planVersion,lease_owner:request.leaseOwner,ttl_seconds:request.ttlSeconds,dispatch_key:dispatchKey}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseEpicDispatchResult(parsed)}async function transitionEpicDispatch(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.dispatchKey),requireNoSlashPathSegment(request.dispatchKey),requireEpicDispatchTransitionStatus(request.nextStatus),request.nextStatus==="run_spawned"&&requireNonEmptyString(request.runId);let path7=epicDispatchTransitionApiPath(request.dispatchKey,request.nextStatus),url=buildConductorJiraUrl(access.baseUrl,path7),body=request.nextStatus==="run_spawned"?JSON.stringify({repo_name:access.repoName,run_id:request.runId}):JSON.stringify({repo_name:access.repoName});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseShadowMergeReconcileResult(parsed){let obj=parsed??{};return{applies:obj.applies===!0,scheduled:obj.scheduled===!0,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:"unknown",shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,requiredCommitSha:typeof obj.required_commit_sha=="string"?obj.required_commit_sha:null,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null}}function parseShadowDispatchFreshnessResult(parsed){let obj=parsed??{},rawVerdict=typeof obj.verdict=="string"?obj.verdict:"",verdict=SHADOW_FRESHNESS_VERDICTS.has(rawVerdict)?rawVerdict:"stale";return{verdict,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:verdict,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null,indexedCommitSha:typeof obj.indexed_commit_sha=="string"?obj.indexed_commit_sha:null,shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,lastError:typeof obj.last_error=="string"?obj.last_error:null}}async function reconcileShadowMerge(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/shadow/merge-reconcile`),body=JSON.stringify({repo_name:access.repoName,merged_ticket_key:request.mergedTicketKey??null}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseShadowMergeReconcileResult(parsed)}async function fetchShadowDispatchFreshness(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNoSlashPathSegment(request.ticketKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/tickets/${encodeURIComponent(request.ticketKey)}/shadow-freshness`),body=JSON.stringify({repo_name:access.repoName}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseShadowDispatchFreshnessResult(parsed)}async function validateEpicPlan(access,request,fetchImpl=globalThis.fetch){requirePositiveSafeInteger(request.planVersion);let blobVersion=request.planBlob.plan_version;if(blobVersion!==void 0&&blobVersion!==request.planVersion)throw new ConductorValidationError(`planVersion mismatch: request.planVersion=${request.planVersion} but planBlob.plan_version=${blobVersion}`);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/plan/validate`),body={repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob};request.epicKey!==void 0&&(body.epic_key=request.epicKey);let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseValidateEpicPlanResult(parsed)}function parseValidateEpicPlanResult(parsed){if(!parsed||typeof parsed!="object"||Array.isArray(parsed))throw new ConductorBridgeApiError("server");let p=parsed,planHash=p.plan_hash,serializationEnabled=p.serialization_enabled,insertedEdges=p.inserted_edges;if(p.valid!==!0||typeof planHash!="string"||planHash.trim()===""||typeof serializationEnabled!="boolean"||typeof insertedEdges!="number"||!Number.isSafeInteger(insertedEdges)||insertedEdges<0)throw new ConductorBridgeApiError("server");return{planHash,serializationEnabled,insertedEdges}}async function storeEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion),requireNonEmptyString(request.planHash);let blobVersion=request.planBlob.plan_version;if(blobVersion!==void 0&&blobVersion!==request.planVersion)throw new ConductorValidationError(`planVersion mismatch: request.planVersion=${request.planVersion} but planBlob.plan_version=${blobVersion}`);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob,plan_hash:request.planHash});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateApprovedPlanNodeTicketSpec(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.expectedPlanHash),requireNonEmptyString(request.ticketSpec);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan/nodes/${encodeURIComponent(request.ticketKey)}/ticket-spec`),body=JSON.stringify({repo_name:access.repoName,expected_plan_hash:request.expectedPlanHash,ticket_spec:request.ticketSpec});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseApproveEpicPlanSuccess(parsed){let record=parsed??{},result={ok:!0,plan_hash:record.plan_hash},prov=record.feature_branch_provisioning;if(prov&&typeof prov=="object"&&!Array.isArray(prov)){let p=prov;(p.status==="created"||p.status==="already_exists")&&typeof p.feature_branch=="string"&&typeof p.source_branch=="string"&&typeof p.source_sha=="string"&&typeof p.remote_head_sha=="string"&&(result.featureBranchProvisioning={status:p.status,feature_branch:p.feature_branch,source_branch:p.source_branch,source_sha:p.source_sha,remote_head_sha:p.remote_head_sha})}return result}async function approveEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/approve-plan`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion});try{let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseApproveEpicPlanSuccess(parsed)}catch(error){if(error instanceof ConductorBridgeApiError&&error.status===409){let preview=error.bodyPreview??"";return/multiple active runs/i.test(preview)?{ok:!1,kind:"conflict",reason:"multiple_active_runs"}:{ok:!1,kind:"conflict",reason:"superseded"}}throw error}}async function getEpicPlan(access,epicKey,planVersion,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/plan`,{repo_name:access.repoName,plan_version:String(planVersion)});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchParseStatus(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-status",{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function triggerRepositoryParse(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-repository"),body=JSON.stringify({repo_name:access.repoName});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function deletePullRequestBranch(access,prNumber,expectedHeadSha,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(prNumber);if(pr===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/branch?repo_name=${encodeURIComponent(access.repoName)}&expected_head_sha=${encodeURIComponent(expectedHeadSha)}`),controller=new AbortController,timer=setTimeout(()=>controller.abort(),CONDUCTOR_FETCH_TIMEOUT_MS);try{let resp;try{resp=await fetchImpl(url,{method:"DELETE",headers:{"X-API-Key":access.apiKey},body:"",signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(resp.status===404)return{deleted:!1,branch:null,reason:"not_found"};if(!resp.ok)throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status):resp.status>=500?new ConductorBridgeApiError("server",resp.status):new ConductorBridgeApiError("http",resp.status);try{return await resp.json()}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function transitionJiraStatus(access,ticketNumber,targetStatus="auto",fetchImpl=globalThis.fetch){if(!ticketNumber)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorJiraUrl(access.baseUrl,`/tickets/${encodeURIComponent(ticketNumber)}/jira-status`),body=JSON.stringify({repo_name:access.repoName,target_status:targetStatus});try{return await fetchConductorJsonPutWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl),{status:"transitioned"}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===400)return{status:"skipped"};throw err}}function readinessShapeError(){return new ConductorBridgeApiError("invalid-input",void 0,{errorCode:"READINESS_SHAPE_INVALID"})}function requireObject(value){if(typeof value!="object"||value===null||Array.isArray(value))throw readinessShapeError();return value}function requireBool(o,key){let v=o[key];if(typeof v!="boolean")throw readinessShapeError();return v}function requireInt(o,key){let v=o[key];if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableInt(o,key){let v=o[key];if(v==null)return null;if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableString(o,key){let v=o[key];if(v==null)return null;if(typeof v!="string")throw readinessShapeError();return v}function requireNullableBool(o,key){let v=o[key];if(v==null)return null;if(typeof v!="boolean")throw readinessShapeError();return v}function requireEnum(o,key,allowed){let v=o[key];if(typeof v!="string"||!allowed.has(v))throw readinessShapeError();return v}function parseConductorReadinessResponse(body){let root=requireObject(body),repoName=root.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let sup=requireObject(root.supervisor),gh=requireObject(root.github),rec=requireObject(root.reconciler),exec=requireObject(root.executor),thr=requireObject(root.thresholds);return{repo_name:repoName,supervisor:{setup_present:requireBool(sup,"setup_present"),setup_source:requireEnum(sup,"setup_source",READINESS_SOURCES),setup_created_at:requireNullableString(sup,"setup_created_at"),setup_updated_at:requireNullableString(sup,"setup_updated_at"),config_present:requireBool(sup,"config_present"),config_source:requireEnum(sup,"config_source",READINESS_SOURCES),config_created_at:requireNullableString(sup,"config_created_at"),config_updated_at:requireNullableString(sup,"config_updated_at"),required_checks_count:requireInt(sup,"required_checks_count"),required_checks_empty:requireBool(sup,"required_checks_empty"),auto_merge_enabled:requireBool(sup,"auto_merge_enabled"),merge_approval_required_set:requireBool(sup,"merge_approval_required_set")},github:{credentials_readable:requireBool(gh,"credentials_readable"),owner_resolved:requireBool(gh,"owner_resolved"),repo_id_resolved:requireBool(gh,"repo_id_resolved"),installation_id_resolved:requireBool(gh,"installation_id_resolved"),credentials_complete:requireBool(gh,"credentials_complete"),actions_probe_succeeded:requireBool(gh,"actions_probe_succeeded"),actions_permission_present:requireBool(gh,"actions_permission_present"),actions_permission_level:requireEnum(gh,"actions_permission_level",ACTIONS_LEVELS),actions_write:requireBool(gh,"actions_write")},reconciler:{liveness_readable:requireBool(rec,"liveness_readable"),last_tick_at:requireNullableString(rec,"last_tick_at"),last_tick_age_seconds:requireNullableInt(rec,"last_tick_age_seconds"),stale:requireBool(rec,"stale"),active_run_count:requireInt(rec,"active_run_count"),expired_lease_count:requireInt(rec,"expired_lease_count")},executor:{liveness_readable:requireBool(exec,"liveness_readable"),last_seen_at:requireNullableString(exec,"last_seen_at"),last_seen_age_seconds:requireNullableInt(exec,"last_seen_age_seconds"),ready:requireNullableBool(exec,"ready")},thresholds:{reconciler_stale_after_seconds:requireInt(thr,"reconciler_stale_after_seconds"),executor_stale_after_seconds:requireInt(thr,"executor_stale_after_seconds")}}}async function fetchConductorReadiness(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/conductor-readiness`,{repo_name:access.repoName}),body=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorReadinessResponse(body)}function parseConductorSupervisorBootstrapResponse(body){let o=requireObject(body),repoName=o.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let names=o.audited_field_names;if(!Array.isArray(names)||names.some(n=>typeof n!="string"))throw readinessShapeError();return{repo_name:repoName,setup_written:requireBool(o,"setup_written"),config_written:requireBool(o,"config_written"),setup_source:requireEnum(o,"setup_source",READINESS_SOURCES),config_source:requireEnum(o,"config_source",READINESS_SOURCES),setup_created_at:requireNullableString(o,"setup_created_at"),setup_updated_at:requireNullableString(o,"setup_updated_at"),config_created_at:requireNullableString(o,"config_created_at"),config_updated_at:requireNullableString(o,"config_updated_at"),required_checks_count:requireInt(o,"required_checks_count"),audited_field_names:names}}async function bootstrapConductorSupervisorDefaults(access,request,fetchImpl){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/supervisor-bootstrap`,{repo_name:access.repoName}),body=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(request),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorSupervisorBootstrapResponse(body)}var CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_BRIDGE_API_ERROR_KINDS,CONDUCTOR_ERROR_PREVIEW_MAX,CONDUCTOR_VALIDATION_LOC_MAX_PARTS,ConductorBridgeApiError,EPIC_TICKET_STATUS_VALUES,EPIC_DISPATCH_TRANSITION_STATUSES,EPIC_RUNS_API_PREFIX,SHADOW_FRESHNESS_VERDICTS,READINESS_SOURCES,ACTIONS_LEVELS,init_bridge_api_client=__esm({"src/conductor/bridge-api-client.ts"(){"use strict";init_credential_store();init_start_tickets_repo();init_git_ci_types();init_errors();CONDUCTOR_DEFAULT_BASE_URL="https://bridgegpt-api.com",CONDUCTOR_FETCH_TIMEOUT_MS=3e4;CONDUCTOR_BRIDGE_API_ERROR_KINDS=["invalid-input","network","timeout","unauthorized","server","http"],CONDUCTOR_ERROR_PREVIEW_MAX=200;CONDUCTOR_VALIDATION_LOC_MAX_PARTS=8;ConductorBridgeApiError=class extends Error{kind;status;errorCode;bodyPreview;constructor(kindOrMessage,status,diagnostics){let isKnownKind=CONDUCTOR_BRIDGE_API_ERROR_KINDS.includes(kindOrMessage),errorCode=diagnostics?.errorCode,bodyPreview=diagnostics?.bodyPreview;if(isKnownKind){let parts=[`Conductor Bridge API request failed (${kindOrMessage}${typeof status=="number"?`, status ${status}`:""})`];errorCode&&parts.push(`code=${errorCode}`),bodyPreview&&parts.push(bodyPreview),super(parts.join(": "))}else super(kindOrMessage);this.name="ConductorBridgeApiError",this.kind=isKnownKind?kindOrMessage:"http",typeof status=="number"&&(this.status=status),errorCode&&(this.errorCode=errorCode),bodyPreview&&(this.bodyPreview=bodyPreview)}};EPIC_TICKET_STATUS_VALUES=["planned","ready","dispatched","running","blocked","abandoned","done","ready_for_review","reviewing","parse_pending"];EPIC_DISPATCH_TRANSITION_STATUSES=["run_spawned","terminal"];EPIC_RUNS_API_PREFIX="/epic-runs";SHADOW_FRESHNESS_VERDICTS=new Set(["not_applicable","covered","stale","failed"]);READINESS_SOURCES=new Set(["epic","project_default","none"]),ACTIONS_LEVELS=new Set(["write","read","none","unknown"])}});import{createHash as createHash4}from"node:crypto";function normalizeDimension(value){return(value??"").trim().toLowerCase()}function makeSupervisorIdempotencyKey(meta){return[normalizeDimension(meta.run_id),normalizeDimension(meta.worker_id)||"(run)",normalizeDimension(meta.reason),normalizeDimension(meta.kind),normalizeDimension(meta.cooldown_window)].join("|")}function makeSupervisorAssessmentEventId(idempotencyKey){let h=createHash4("sha256").update(`supervisor.assessment:${idempotencyKey}`).digest("hex");return`${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20,32)}`}function isDuplicateConstraintError3(error){if(!error||typeof error!="object")return!1;let code=error.code;if(typeof code=="string"&&code.startsWith("SQLITE_CONSTRAINT"))return!0;let message=error.message;if(typeof message=="string"){let lowered=message.toLowerCase();if(lowered.includes("unique constraint")||lowered.includes("constraint failed"))return!0}return!1}async function emitSupervisorAssessmentIfNew(input,deps={}){let emitEvent=deps.emitEvent??emitConductorEvent,idempotencyKey=makeSupervisorIdempotencyKey(input.idempotency),eventId=makeSupervisorAssessmentEventId(idempotencyKey),details={...input.details??{},idempotency_key:idempotencyKey,reason:input.idempotency.reason,kind:input.idempotency.kind,cooldown_window:input.idempotency.cooldown_window,classification:input.assessment.classification,confidence:input.assessment.confidence},event={id:eventId,source:"conductor-supervisor",type:"supervisor.assessment",run_id:input.run_id,worker_id:input.idempotency.worker_id??input.worker_id??null,producer:"conductor-supervisor",observed_via:"supervisor",data:{summary:`supervisor assessment: ${input.idempotency.reason}`,status:"escalated",reason:input.idempotency.reason,details}};try{let result=await emitEvent(event);return{emitted:!0,event_id:eventId,event:result.event}}catch(error){if(isDuplicateConstraintError3(error))return{emitted:!1,reason:"duplicate"};throw error}}var init_supervisor_ledger=__esm({"src/conductor/supervisor-ledger.ts"(){"use strict";init_store()}});function buildSupervisorEscalationWorkerMessage(candidate,assessment,state){let details={reason:candidate.reason,state:candidate.state,liveness:candidate.liveness,elapsed_ms:candidate.elapsed_ms,assessment_source:"deterministic"};return{run_id:state.run_id,worker_id:candidate.worker_id,type:`supervisor.${candidate.reason}`,cause_seq:state.last_seq,payload:{summary:`supervisor escalation: ${candidate.reason}`,status:"escalated",details},source:"conductor-supervisor",producer:"worker-message-relay"}}async function sendSupervisorEscalationWorkerMessageIfNew(candidate,assessment,state,deps={}){let sendMessage=deps.sendMessage??sendWorkerMessage,input=buildSupervisorEscalationWorkerMessage(candidate,assessment,state);return sendMessage(input)}var init_supervisor_message_relay=__esm({"src/conductor/supervisor-message-relay.ts"(){"use strict";init_store()}});function isTerminalState(state){return TERMINAL_STATES.has(state)}function isoToMs(value){if(typeof value!="string"||value.length===0)return null;let ms=Date.parse(value);return Number.isFinite(ms)?ms:null}function msToIso(now){return new Date(now).toISOString()}function createEmptySupervisorRunState(runId,config,now){let startedIso=msToIso(now);return{run_id:runId,status:"unknown",last_seq:0,last_event_time:null,workers:{},gates:{},latest_assessment:null,escalations:[],started_at:startedIso,updated_at:startedIso,global_deadline_at:msToIso(now+config.global_timeout_ms),roster_discovered:!1}}function isValidSupervisorSummary(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)&&value.kind===SUPERVISOR_SUMMARY_KIND}function hydrateSupervisorRunStateFromSnapshot(snapshot,runId,config,now){let empty=createEmptySupervisorRunState(runId,config,now),summary=snapshot?.projection?.summary;return isValidSupervisorSummary(summary)?{...empty,status:typeof summary.status=="string"?summary.status:empty.status,last_seq:typeof summary.last_seq=="number"&&summary.last_seq>=0?summary.last_seq:empty.last_seq,last_event_time:typeof summary.last_event_time=="string"?summary.last_event_time:null,workers:isPlainRecord(summary.workers)?summary.workers:{},gates:isPlainRecord(summary.gates)?summary.gates:{},latest_assessment:summary.latest_assessment&&typeof summary.latest_assessment=="object"?summary.latest_assessment:null,escalations:Array.isArray(summary.escalations)?summary.escalations:[],started_at:typeof summary.started_at=="string"?summary.started_at:empty.started_at,global_deadline_at:typeof summary.global_deadline_at=="string"?summary.global_deadline_at:empty.global_deadline_at,roster_discovered:summary.roster_discovered===!0,run_id:runId}:empty}function isPlainRecord(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)}function ensureWorkerState(state,workerId,options={}){let existing=state.workers[workerId];if(existing)return options.ticketKey&&!existing.ticket_key&&(existing.ticket_key=options.ticketKey),existing;let created={worker_id:workerId,ticket_key:options.ticketKey??null,state:options.fromRoster?"not_started":"unknown",liveness:"unknown",first_seen_seq:options.seq??null,last_event_seq:options.seq??null,last_event_time:null,last_progress_time:null,last_heartbeat_time:null,blocked_reason:null,terminal_reason:null,observed_event_types:[]};return state.workers[workerId]=created,created}function noteObservedType(worker,eventType){worker.observed_event_types.includes(eventType)||worker.observed_event_types.push(eventType)}function eventDetails(event){let details=event.data?.details;return isPlainRecord(details)?details:{}}function extractRoster(event){let candidates=[eventDetails(event).workers,event.data?.workers,isPlainRecord(event.data?.raw)?event.data.raw.workers:void 0];for(let candidate of candidates)if(Array.isArray(candidate)){let roster=[];for(let entry of candidate){if(!isPlainRecord(entry))continue;let workerId=entry.worker_id;if(typeof workerId!="string"||workerId.length===0)continue;let ticketKey=entry.ticket_key;roster.push({worker_id:workerId,ticket_key:typeof ticketKey=="string"?ticketKey:null})}if(roster.length>0)return roster}return[]}function eventStatus(event){let status=event.data?.status;return typeof status=="string"?status.trim().toLowerCase():""}function eventReason(event){let reason=event.data?.reason??eventDetails(event).reason;return typeof reason=="string"?reason.trim().toLowerCase():""}function applyConductorEventToSupervisorState(state,event,now){if(event.run_id!==state.run_id)return state;let eventType=event.type,eventTimeMs=isoToMs(event.time)??now,eventTimeIso=event.time??msToIso(now);if(typeof event.seq=="number"&&event.seq>state.last_seq&&(state.last_seq=event.seq),state.last_event_time=eventTimeIso,state.status==="unknown"&&(state.status="active"),eventType==="run.started"){let roster=extractRoster(event);roster.length>0&&(state.roster_discovered=!0);for(let member of roster){let worker2=ensureWorkerState(state,member.worker_id,{fromRoster:!0,ticketKey:member.ticket_key,seq:event.seq});noteObservedType(worker2,eventType),worker2.last_event_seq=event.seq??worker2.last_event_seq,worker2.last_event_time=eventTimeIso}return state.updated_at=msToIso(now),state}if(eventType==="supervisor.assessment"||eventType==="message.sent")return state.updated_at=msToIso(now),state;let workerId=event.worker_id;if(typeof workerId!="string"||workerId.length===0)return applyRunLevelEvent(state,event,eventType),state.updated_at=msToIso(now),state;let worker=ensureWorkerState(state,workerId,{seq:event.seq});switch(noteObservedType(worker,eventType),worker.last_event_seq=event.seq??worker.last_event_seq,worker.last_event_time=eventTimeIso,eventType){case"run.heartbeat":{worker.last_heartbeat_time=eventTimeIso,!isTerminalState(worker.state)&&worker.state!=="blocked"&&(worker.state==="not_started"||worker.state==="unknown")&&(worker.state="active");break}case"agent.notification":{let status=eventStatus(event),reason=eventReason(event);BLOCKED_STATUS_TOKENS.has(status)||BLOCKED_STATUS_TOKENS.has(reason)?isTerminalState(worker.state)||(worker.state="blocked",worker.blocked_reason=status||reason||"blocked"):!isTerminalState(worker.state)&&worker.state==="not_started"&&(worker.state="active");break}case"tool.intent":case"worktree.changed":case"git.commit_created":{PROGRESS_EVENT_TYPES.has(eventType)&&(worker.last_progress_time=eventTimeIso,isTerminalState(worker.state)||((worker.state==="not_started"||worker.state==="unknown"||worker.state==="stalled"||worker.state==="blocked")&&(worker.state="active"),worker.blocked_reason=null));break}case"gate.met":{isTerminalState(worker.state)||(worker.state="candidate_done");break}case"ci.passed":{isTerminalState(worker.state)||(worker.state="verifying"),worker.last_progress_time=eventTimeIso;break}case"ci.failed":{let reason=eventReason(event);eventStatus(event)==="terminal"||reason==="terminal"||reason==="give_up"?(worker.state="failed",worker.terminal_reason=reason||"ci_failed"):isTerminalState(worker.state)||(worker.last_progress_time=eventTimeIso);break}case"run.stopped":{let status=eventStatus(event),reason=eventReason(event);FAILED_STATUS_TOKENS.has(status)||FAILED_STATUS_TOKENS.has(reason)?(worker.state="failed",worker.terminal_reason=reason||status||"failed"):(worker.state="complete",worker.terminal_reason=reason||status||"complete");break}case"message.delivered":case"message.acked":{!isTerminalState(worker.state)&&(worker.state==="not_started"||worker.state==="unknown")&&(worker.state="active");break}case"merge.succeeded":{worker.state="complete",worker.terminal_reason=worker.terminal_reason||"merge_succeeded";break}case"merge.failed":break;case"merge.dry_run":break;case"merge.pending_approval":break;default:break}return state.updated_at=msToIso(now),state}function applyRunLevelEvent(state,event,eventType){switch(eventType){case"gate.met":state.gates.gate_met=!0;break;case"ci.passed":state.gates.ci="passed";break;case"ci.failed":state.gates.ci="failed";break;case"git.pr_opened":state.gates.pr_opened=!0;break;case"merge.succeeded":case"merge.failed":case"merge.dry_run":case"merge.pending_approval":state.gates.merge=eventType.slice(6);break;default:break}}function classifyWorkerLiveness(worker,config,now){if(isTerminalState(worker.state))return"alive";let lastSignalMs=mostRecentSignalMs(worker);if(lastSignalMs===null)return"unknown";let elapsed=now-lastSignalMs;return elapsed>=config.liveness.dead_after_ms?"dead":elapsed>=config.liveness.stalled_after_ms?"stalled":elapsed>=config.liveness.quiet_after_ms?"quiet":"alive"}function mostRecentSignalMs(worker){let candidates=[isoToMs(worker.last_heartbeat_time),isoToMs(worker.last_event_time),isoToMs(worker.last_progress_time)].filter(v=>v!==null);return candidates.length===0?null:Math.max(...candidates)}function stateAnchorMs(worker){return worker.state==="active"||worker.state==="verifying"?mostRecentSignalMs(worker):isoToMs(worker.last_event_time)??isoToMs(worker.last_heartbeat_time)??isoToMs(worker.last_progress_time)}function applySupervisorHousekeeping(state,config,now){for(let worker of Object.values(state.workers)){if(worker.liveness=classifyWorkerLiveness(worker,config,now),isTerminalState(worker.state)||worker.state==="stalled")continue;let threshold=config.stall_thresholds_ms[worker.state],anchor=stateAnchorMs(worker);anchor!==null&&now-anchor>=threshold&&(worker.state="stalled")}return state.updated_at=msToIso(now),state}function isSupervisorRunTerminal(state){let workers=Object.values(state.workers);return workers.length===0||!state.roster_discovered?!1:workers.every(w=>isTerminalState(w.state))}function hasSupervisorGlobalTimeoutElapsed(state,now){let deadlineMs=isoToMs(state.global_deadline_at);return deadlineMs===null?!1:now>=deadlineMs}function compactWorker(worker){return{worker_id:worker.worker_id,ticket_key:worker.ticket_key,state:worker.state,liveness:worker.liveness,last_event_seq:worker.last_event_seq,last_event_time:worker.last_event_time,last_progress_time:worker.last_progress_time,last_heartbeat_time:worker.last_heartbeat_time,blocked_reason:worker.blocked_reason,terminal_reason:worker.terminal_reason}}function toSupervisorProjectionInput(state){let summary={kind:SUPERVISOR_SUMMARY_KIND,run_id:state.run_id,status:state.status,last_seq:state.last_seq,last_event_time:state.last_event_time,workers:state.workers,gates:state.gates,latest_assessment:state.latest_assessment,escalations:state.escalations,started_at:state.started_at,updated_at:state.updated_at,global_deadline_at:state.global_deadline_at,roster_discovered:state.roster_discovered};return{run_id:state.run_id,status:state.status,last_seq:state.last_seq,last_event_time:state.last_event_time,active_workers:Object.values(state.workers).map(compactWorker),gates:state.gates,assessment:state.latest_assessment,summary}}var SUPERVISOR_SUMMARY_KIND,TERMINAL_STATES,PROGRESS_EVENT_TYPES,BLOCKED_STATUS_TOKENS,FAILED_STATUS_TOKENS,init_supervisor_state=__esm({"src/conductor/supervisor-state.ts"(){"use strict";SUPERVISOR_SUMMARY_KIND="supervisor_projection_summary",TERMINAL_STATES=new Set(["complete","failed"]);PROGRESS_EVENT_TYPES=new Set(["tool.intent","worktree.changed","git.commit_created"]),BLOCKED_STATUS_TOKENS=new Set(["blocked","waiting_for_input","needs_input"]),FAILED_STATUS_TOKENS=new Set(["failed","error","errored","aborted","cancelled","canceled"])}});function elapsedSinceSignal(worker,now){let candidates=[worker.last_event_time,worker.last_progress_time,worker.last_heartbeat_time].map(iso=>iso?Date.parse(iso):NaN).filter(v=>Number.isFinite(v));return candidates.length===0?0:Math.max(0,now-Math.max(...candidates))}function findSupervisorEscalationCandidates(state,config,now){let candidates=[];for(let worker of Object.values(state.workers)){if(worker.state==="complete"||worker.state==="failed")continue;let elapsed=elapsedSinceSignal(worker,now),baseContext={worker_id:worker.worker_id,ticket_key:worker.ticket_key,state:worker.state,liveness:worker.liveness};if(worker.liveness==="dead"){candidates.push({reason:"worker_dead",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});continue}switch(worker.state){case"not_started":worker.liveness!=="alive"&&candidates.push({reason:"worker_not_started",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"blocked":candidates.push({reason:"worker_blocked",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:{...baseContext,blocked_reason:worker.blocked_reason}});break;case"stalled":candidates.push({reason:"worker_stalled",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"candidate_done":worker.liveness!=="alive"&&candidates.push({reason:"candidate_done_stuck",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"verifying":worker.liveness==="stalled"&&candidates.push({reason:"verification_stalled",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;default:break}}let deadlineMs=state.global_deadline_at?Date.parse(state.global_deadline_at):NaN;return Number.isFinite(deadlineMs)&&now>=deadlineMs&&candidates.push({reason:"global_timeout",kind:ESCALATION_KIND,worker_id:null,state:null,liveness:null,elapsed_ms:Math.max(0,now-deadlineMs),context:{run_id:state.run_id,deadline_at:state.global_deadline_at,worker_count:Object.keys(state.workers).length}}),candidates}function cooldownWindowFor(now,cooldownMs){let width=cooldownMs>0?cooldownMs:1;return String(Math.floor(now/width))}function shouldEmitEscalation(state,candidate,config,now){let cooldownWindow=cooldownWindowFor(now,config.escalation_cooldown_ms);return{emit:!state.escalations.some(record=>record.reason===candidate.reason&&(record.worker_id??null)===(candidate.worker_id??null)&&record.cooldown_window===cooldownWindow&&(record.outcome==="emitted"||record.outcome==="duplicate")),cooldown_window:cooldownWindow}}function recordEscalationResult(state,candidate,cooldownWindow,idempotencyKey,outcome,now){let record={idempotency_key:idempotencyKey,worker_id:candidate.worker_id??null,reason:candidate.reason,kind:candidate.kind,cooldown_window:cooldownWindow,outcome,recorded_at:new Date(now).toISOString()};return state.escalations.push(record),record}function formatElapsed(ms){let totalSeconds=Math.max(0,Math.floor(ms/1e3)),hours=Math.floor(totalSeconds/3600),minutes=Math.floor(totalSeconds%3600/60),seconds=totalSeconds%60;return hours>0?`${hours}h${minutes}m`:minutes>0?`${minutes}m`:`${seconds}s`}function formatEscalationForTerminal(runId,candidate){let worker=candidate.worker_id?` worker=${candidate.worker_id}`:"",stateBit=candidate.state?` state=${candidate.state}`:"",liveBit=candidate.liveness?` liveness=${candidate.liveness}`:"",elapsed=` elapsed=${formatElapsed(candidate.elapsed_ms)}`;return`[supervisor] run=${runId}${worker} reason=${candidate.reason}${stateBit}${liveBit}${elapsed}`}var ESCALATION_KIND,init_supervisor_escalation=__esm({"src/conductor/supervisor-escalation.ts"(){"use strict";ESCALATION_KIND="escalation"}});function buildGateIdentity(gateName,configHash){let name=gateName.trim(),hash=typeof configHash=="string"?configHash.trim():"";return hash?`${name}@${hash.toLowerCase()}`:name}function makeMergeActionKey(repo,prNumber,headSha,gateIdentity){let r=normalizeRepoName(repo),pr=normalizePrNumber(prNumber),sha=normalizeSha(headSha),gate=(gateIdentity??"").trim();if(r===null||pr===null||sha===null||gate.length===0)throw new Error("invalid merge action key component");return`merge:${r}:${pr}:${sha}:${gate}`}var init_merge_identity=__esm({"src/conductor/merge-identity.ts"(){"use strict";init_git_ci_types()}});function isPlainObject2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function normalizeEventHeadSha(value){if(typeof value!="string")return null;let trimmed=value.trim();return/^[0-9a-f]{7,40}$/i.test(trimmed)?trimmed.toLowerCase():null}function getRawEventDetails(event){let details=event.data?.details;return isPlainObject2(details)?details:null}function parseHeadObservation(event){let details=getRawEventDetails(event);return{head_sha:details?normalizeEventHeadSha(details.head_sha):null}}function parseMergeLifecycle(event){let details=getRawEventDetails(event);return{action_key:details&&typeof details.action_key=="string"&&details.action_key.trim().length>0?details.action_key.trim():null}}function parseGateMet(event){let details=getRawEventDetails(event);if(!details)return{head_sha:null,repo:null,pr_number:null,gate_name:null,config_hash:null,required_checks:[]};let gateName=typeof details.gate_name=="string"&&details.gate_name.trim().length>0?details.gate_name.trim():null,configHash=typeof details.config_hash=="string"&&details.config_hash.trim().length>0?details.config_hash.trim():null,ciCheckStatus=isPlainObject2(details.ci_check_status)?details.ci_check_status:null,requiredChecks=(Array.isArray(details.required_checks)?details.required_checks:ciCheckStatus&&Array.isArray(ciCheckStatus.required_checks)?ciCheckStatus.required_checks:[]).filter(c=>typeof c=="string"&&c.trim().length>0);return{head_sha:normalizeSha(details.head_sha),repo:normalizeRepoName(details.repo),pr_number:normalizePrNumber(details.pr_number),gate_name:gateName,config_hash:configHash,required_checks:requiredChecks}}function parseSpecReview(event){let details=getRawEventDetails(event);return{head_sha:details?normalizeEventHeadSha(details.head_sha):null}}function parseEmpty(){return EMPTY_DETAILS}function getEventDetails(event,expectedType){if(event.type!==expectedType)return null;let parser=EVENT_PARSERS[expectedType];return parser(event)}function getMergeIdentity(event){if(event.type!=="gate.met")return null;let details=getEventDetails(event,"gate.met");if(details===null)return null;let{repo,pr_number:prNumber,head_sha:headSha,gate_name:gateName}=details;if(repo===null||prNumber===null||headSha===null||gateName===null)return null;let gateIdentity=buildGateIdentity(gateName,details.config_hash),actionKey=makeMergeActionKey(repo,prNumber,headSha,gateIdentity);return{repo,pr_number:prNumber,head_sha:headSha,gate_name:gateName,config_hash:details.config_hash,required_checks:details.required_checks,gate_identity:gateIdentity,action_key:actionKey,gate_event:{id:typeof event.id=="string"?event.id:void 0,seq:typeof event.seq=="number"?event.seq:void 0,time:typeof event.time=="string"?event.time:void 0}}}var EMPTY_DETAILS,EVENT_PARSERS,init_event_accessors=__esm({"src/conductor/event-accessors.ts"(){"use strict";init_git_ci_types();init_merge_identity();EMPTY_DETAILS=Object.freeze({});EVENT_PARSERS={"run.started":parseEmpty,"run.heartbeat":parseEmpty,"run.stopped":parseEmpty,"agent.notification":parseEmpty,"tool.intent":parseEmpty,"worktree.changed":parseEmpty,"git.commit_created":parseEmpty,"git.pr_opened":parseHeadObservation,"ci.passed":parseHeadObservation,"ci.failed":parseHeadObservation,"gate.met":parseGateMet,"supervisor.assessment":parseEmpty,"message.sent":parseEmpty,"message.delivered":parseEmpty,"message.acked":parseEmpty,"merge.dry_run":parseMergeLifecycle,"merge.attempted":parseMergeLifecycle,"merge.succeeded":parseHeadObservation,"merge.failed":parseMergeLifecycle,"merge.conflict":parseHeadObservation,"merge.pending_approval":parseMergeLifecycle,"review.passed":parseHeadObservation,"review.changes_requested":parseHeadObservation,"spec_review.passed":parseSpecReview,"spec_review.changes_requested":parseSpecReview,"parse.triggered":parseEmpty,"parse.succeeded":parseEmpty,"parse.failed":parseEmpty}}});import{createHash as createHash5}from"node:crypto";function extractMergeActionIdentityFromGateEvent(event){return getMergeIdentity(event)}function makeMergeEventId(eventType,actionKey){let h=createHash5("sha256").update(`${eventType}:${actionKey}`).digest("hex");return`${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20,32)}`}async function lookupMergeEventByActionKey(eventType,actionKey,deps){let db=await(deps.openDb??(()=>openReadonlyConductorDatabaseIfExists()))();if(!db)return!1;try{return db.prepare(`SELECT 1 FROM events
130
+ `)}function withDenyLayer(result,layer){return{...result,metadata:{...result.metadata??{},layer}}}function evaluateDenyRun(run,allowedMarker){let nonExited=nonExitedResult(run);if(nonExited)return{kind:"nonexited",result:nonExited};let{exitCode,stdout,stderr,elapsedMs}=run;return exitCode!==0?{kind:"error",result:{status:"fail",detail:`deny-enforcement probe agent exited ${exitCode}`,elapsedMs,evidence:truncate(stdout||stderr)}}:stdout.includes(allowedMarker)?{kind:"allowed",evidence:truncate(stdout)}:{kind:"blocked",evidence:truncate(stdout||stderr)}}async function runDenyEnforcementCheck(ctx,opts){let marker=ctx.marker("DENY_ALLOWED"),prompt=denyProbePrompt(),acceptEdits=opts?.permissionPosture==="accept_edits",runOpts={skipPermissions:!acceptEdits,permissionMode:acceptEdits?"acceptEdits":void 0,model:opts?.model,timeoutMs:opts?.timeoutMs},controlDir=await ctx.makeTempProject(d=>seedDenyTargetFile(ctx,d,marker)),controlRun=await ctx.runHeadless({prompt,cwd:controlDir,...runOpts}),c=evaluateDenyRun(controlRun,marker);if(c.kind==="nonexited")return{result:withDenyLayer(c.result,"none"),layer:"none"};if(c.kind==="error")return{result:withDenyLayer(c.result,"none"),layer:"none"};if(c.kind==="blocked")return{result:withDenyLayer({status:"fail",detail:"control run (no deny rule) did not execute the canary call \u2014 the agent never attempted the Bash command, so deny enforcement cannot be verified (a refusal is NOT enforcement)",elapsedMs:controlRun.elapsedMs,evidence:c.evidence},"none"),layer:"none"};let denyDir=await ctx.makeTempProject(d=>seedDenySettings(ctx,d,marker)),settingsRun=await ctx.runHeadless({prompt,cwd:denyDir,...runOpts}),s=evaluateDenyRun(settingsRun,marker);if(s.kind==="nonexited")return{result:withDenyLayer(s.result,"none"),layer:"none"};if(s.kind==="error")return{result:withDenyLayer(s.result,"none"),layer:"none"};if(s.kind==="blocked")return{result:withDenyLayer({status:"pass",detail:"denied call rejected by settings permissions.deny",elapsedMs:settingsRun.elapsedMs,evidence:s.evidence},"settings-deny"),layer:"settings-deny"};let hookDir=await ctx.makeTempProject(d=>seedDenyHook(ctx,d,marker)),hookRun=await ctx.runHeadless({prompt,cwd:hookDir,...runOpts}),h=evaluateDenyRun(hookRun,marker);return h.kind==="nonexited"?{result:withDenyLayer(h.result,"none"),layer:"none"}:h.kind==="error"?{result:withDenyLayer(h.result,"none"),layer:"none"}:h.kind==="blocked"?{result:withDenyLayer({status:"pass",detail:"settings deny did not reject; PreToolUse hook fallback rejected the call",elapsedMs:hookRun.elapsedMs,evidence:h.evidence},"pretooluse-hook"),layer:"pretooluse-hook"}:{result:withDenyLayer({status:"fail",detail:"deny is NOT enforced for this installed Claude version under --dangerously-skip-permissions (neither settings permissions.deny nor a PreToolUse hook rejected the denied call)",elapsedMs:hookRun.elapsedMs,evidence:h.evidence},"none"),layer:"none"}}var EVIDENCE_MAX,DENY_TARGET_FILE,DENY_BASH_RULE,DENY_HOOK_MATCHER,init_probes=__esm({"src/agent-capabilities/probes.ts"(){"use strict";init_probe_context();EVIDENCE_MAX=200;DENY_TARGET_FILE="deny-probe-target.txt",DENY_BASH_RULE="Bash(cat:*)",DENY_HOOK_MATCHER="Bash"}});var deny_enforcement_preflight_exports={};__export(deny_enforcement_preflight_exports,{runDenyEnforcementPreflight:()=>runDenyEnforcementPreflight});async function runDenyEnforcementPreflight(opts={}){try{let agent=resolveAgentSpec("claude");if(!agent)return{enforced:!1,layer:"none",degraded:!0,warnings:["Could not resolve the 'claude' agent spec for the deny-enforcement preflight.",REFUSE_TO_CLAIM_WARNING]};let deps=opts.capabilityDeps??createDefaultAgentCapabilitiesDeps(),{ctx,cleanup}=await createProbeContext(deps,agent,opts.timeoutMs);try{let{result,layer}=await runDenyEnforcementCheck(ctx,{model:opts.model,timeoutMs:opts.timeoutMs,permissionPosture:opts.permissionPosture});return result.status==="pass"&&layer==="settings-deny"?{enforced:!0,layer:"settings-deny",degraded:!1,warnings:[],status:result.status,detail:result.detail}:result.status==="pass"&&layer==="pretooluse-hook"?{enforced:!0,layer:"pretooluse-hook",degraded:!0,warnings:["settings permissions.deny was not enforced under --dangerously-skip-permissions; relying on PreToolUse fallback."],status:result.status,detail:result.detail}:{enforced:!1,layer:"none",degraded:!0,warnings:[`Deny-layer enforcement probe did not pass: ${result.detail}`,REFUSE_TO_CLAIM_WARNING],status:result.status,detail:result.detail}}finally{await cleanup()}}catch(err){return{enforced:!1,layer:"none",degraded:!0,warnings:[`Deny-layer enforcement preflight failed unexpectedly: ${err instanceof Error?err.message:String(err)}`,REFUSE_TO_CLAIM_WARNING]}}}var REFUSE_TO_CLAIM_WARNING,init_deny_enforcement_preflight=__esm({"src/conductor/deny-enforcement-preflight.ts"(){"use strict";init_agent_registry();init_probe_context();init_default_deps();init_probes();REFUSE_TO_CLAIM_WARNING="The executor claim loop MUST refuse to claim jobs until settings permissions.deny or the PreToolUse fallback enforces the deny layer."}});function parseBoundedSupervisorInt(raw,fallback,min,max){if(raw===void 0)return fallback;let trimmed=raw.trim();if(trimmed.length===0||!/^[+-]?\d+$/.test(trimmed))return fallback;let parsed=Number.parseInt(trimmed,10);return Number.isFinite(parsed)?Math.min(max,Math.max(min,parsed)):fallback}function resolveSupervisorConfig(overrides={},env=process.env){let wake_interval_ms=clampOverride(overrides.wake_interval_ms,parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_WAKE_INTERVAL_MS,45e3,3e4,6e4),3e4,6e4),global_timeout_ms=clampOverride(overrides.global_timeout_ms,parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_GLOBAL_TIMEOUT_MS,864e5,3e5,6048e5),3e5,6048e5),escalation_cooldown_ms=clampOverride(overrides.escalation_cooldown_ms,parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_ESCALATION_COOLDOWN_MS,9e5,3e5,864e5),3e5,864e5),quiet_after_ms=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_QUIET_AFTER_MS,3e5,6e4,36e5),liveness_stalled_after_ms=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_LIVENESS_STALLED_AFTER_MS,12e5,3e5,144e5),dead_after_ms=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_DEAD_AFTER_MS,72e5,6e5,864e5),poll_limit=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_SUPERVISOR_POLL_LIMIT,POLL_LIMIT_DEFAULT2,POLL_LIMIT_MIN,POLL_LIMIT_MAX2);return{wake_interval_ms,global_timeout_ms,stall_thresholds_ms:resolveStallThresholds(env),liveness:{quiet_after_ms,stalled_after_ms:liveness_stalled_after_ms,dead_after_ms},escalation_cooldown_ms,poll_limit}}function clampOverride(override,base,min,max){return override===void 0||!Number.isFinite(override)?base:Math.min(max,Math.max(min,Math.floor(override)))}function resolveStallThresholds(env){return{not_started:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_NOT_STARTED_MS,15*6e4,6e4,36e5),active:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_ACTIVE_MS,2*36e5,10*6e4,12*36e5),stalled:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_STALLED_MS,30*6e4,5*6e4,6*36e5),blocked:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_BLOCKED_MS,24*36e5,30*6e4,168*36e5),candidate_done:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_CANDIDATE_DONE_MS,30*6e4,5*6e4,6*36e5),verifying:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_VERIFYING_MS,2*36e5,10*6e4,12*36e5),unknown:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_UNKNOWN_MS,30*6e4,5*6e4,6*36e5),complete:Number.MAX_SAFE_INTEGER,failed:Number.MAX_SAFE_INTEGER}}var POLL_LIMIT_DEFAULT2,POLL_LIMIT_MIN,POLL_LIMIT_MAX2,init_supervisor_config=__esm({"src/conductor/supervisor-config.ts"(){"use strict";POLL_LIMIT_DEFAULT2=200,POLL_LIMIT_MIN=1,POLL_LIMIT_MAX2=1e3}});import path7 from"path";function hasControlChars(value){for(let i=0;i<value.length;i++){let code=value.charCodeAt(i);if(code<=31||code===127)return!0}return!1}function validateRepoName(raw){if(typeof raw!="string")return{ok:!1,error:"repo_name must be a string"};let value=raw.trim();return value.length===0?{ok:!1,error:"repo_name must be a non-empty string"}:value.includes("/")||value.includes("\\")?{ok:!1,error:"repo_name must not contain path separators"}:hasControlChars(value)?{ok:!1,error:"repo_name must not contain control characters"}:{ok:!0,value}}function validateMcpTarget(raw){if(typeof raw!="string")return{ok:!1,error:"mcp target must be a string"};let value=raw.trim();return value.length===0?{ok:!1,error:"mcp target must be a non-empty string"}:value.includes("/")||value.includes("\\")?{ok:!1,error:"mcp target must not contain path separators"}:hasControlChars(value)?{ok:!1,error:"mcp target must not contain control characters"}:{ok:!0,value}}function parseQuotedString(value){if(value.length<2||value[0]!=='"'||value[value.length-1]!=='"')return null;let inner=value.slice(1,-1);return inner.includes('"')?null:inner}function parseStringArray(value){let trimmed=value.trim();if(trimmed.length<2||trimmed[0]!=="["||trimmed[trimmed.length-1]!=="]")return null;let inner=trimmed.slice(1,-1).trim();if(inner.length===0)return[];let parts=inner.split(","),out=[];for(let part of parts){let element=parseQuotedString(part.trim());if(element===null)return null;out.push(element)}return out}function parseBridgeConfigToml(text){let lines=text.split(`
131
+ `),repoName,sawRepoName=!1,mcp=[],currentMcp=null;for(let i=0;i<lines.length;i++){let lineNo=i+1,line=lines[i].trim();if(line.length===0||line.startsWith("#"))continue;if(line==="[[mcp]]"){currentMcp={headerLine:lineNo},mcp.push(currentMcp);continue}if(line.startsWith("["))return{ok:!1,kind:"parse-error",error:`Unsupported table header on line ${lineNo}; only [[mcp]] is allowed`};let eq=line.indexOf("=");if(eq===-1)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; expected key = "value"`};let key=line.slice(0,eq).trim(),rawValue=line.slice(eq+1).trim();if(key.length===0)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; missing key`};if(currentMcp===null){if(key==="repo_name"){if(sawRepoName)return{ok:!1,kind:"parse-error",error:`Duplicate repo_name on line ${lineNo}`};sawRepoName=!0;let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};let validated=validateRepoName(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};repoName=validated.value;continue}return key==="target"?{ok:!1,kind:"parse-error",error:`target on line ${lineNo} must appear inside an [[mcp]] section`}:{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' on line ${lineNo}`}}if(key==="args"){if(currentMcp.args!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate args on line ${lineNo}`};let arr=parseStringArray(rawValue);if(arr===null)return{ok:!1,kind:"parse-error",error:`Expected a string array for 'args' on line ${lineNo}`};currentMcp.args=arr;continue}if(key==="target"||key==="command"||key==="secret_bundle"){let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};if(key==="target"){if(currentMcp.target!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate target on line ${lineNo}`};let validated=validateMcpTarget(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};currentMcp.target=validated.value;continue}if(key==="command"){if(currentMcp.command!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate command on line ${lineNo}`};currentMcp.command=stringValue;continue}if(currentMcp.secretBundle!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate secret_bundle on line ${lineNo}`};currentMcp.secretBundle=stringValue;continue}return{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' inside [[mcp]] on line ${lineNo}`}}if(!sawRepoName||repoName===void 0)return{ok:!1,kind:"validation-error",error:"Missing required repo_name"};let cleaned=[];for(let entry of mcp){if(entry.target===void 0)return{ok:!1,kind:"validation-error",error:`An [[mcp]] section on line ${entry.headerLine} is missing its target`};if(entry.target!=="bapi"){if(entry.command===void 0||entry.command.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty command`};if(entry.args===void 0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires an args array`};if(entry.secretBundle===void 0||entry.secretBundle.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty secret_bundle`}}let clean={target:entry.target};entry.command!==void 0&&(clean.command=entry.command),entry.args!==void 0&&(clean.args=entry.args),entry.secretBundle!==void 0&&(clean.secretBundle=entry.secretBundle),cleaned.push(clean)}return{ok:!0,manifest:{repoName,mcp:cleaned}}}function bridgeConfigPath(projectRoot){return path7.join(projectRoot,".bridge","config")}async function readBridgeConfig(projectRoot,deps){let filePath=bridgeConfigPath(projectRoot),raw;try{raw=await deps.readFile(filePath)}catch(err){return err&&typeof err=="object"&&err.code==="ENOENT"?{ok:!1,kind:"missing"}:{ok:!1,kind:"parse-error",error:"Unable to read .bridge/config"}}return parseBridgeConfigToml(raw)}var init_bridge_config=__esm({"src/bridge-config.ts"(){"use strict"}});async function resolveStartTicketsRepoName(deps){let fromEnv=deps.env.BAPI_REPO_NAME;if(typeof fromEnv=="string"&&fromEnv.trim().length>0)return fromEnv.trim();try{let result=await readBridgeConfig(deps.cwd,{readFile:deps.readFile});if(result.ok&&result.manifest.repoName)return result.manifest.repoName}catch{}return null}var init_start_tickets_repo=__esm({"src/start-tickets-repo.ts"(){"use strict";init_bridge_config()}});var bridge_api_client_exports={};__export(bridge_api_client_exports,{CONDUCTOR_DEFAULT_BASE_URL:()=>CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS:()=>CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES:()=>CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,ConductorBridgeApiError:()=>ConductorBridgeApiError,advanceEpicTicketStatus:()=>advanceEpicTicketStatus,approveEpicPlan:()=>approveEpicPlan,bootstrapConductorSupervisorDefaults:()=>bootstrapConductorSupervisorDefaults,buildConductorJiraUrl:()=>buildConductorJiraUrl,buildConductorVcsUrl:()=>buildConductorVcsUrl,buildEpicDispatchKey:()=>buildEpicDispatchKey,claimEpicSupervisionLease:()=>claimEpicSupervisionLease,createEpicRun:()=>createEpicRun,createEpicRunWithDisposition:()=>createEpicRunWithDisposition,createEpicTicketStatus:()=>createEpicTicketStatus,deletePullRequestBranch:()=>deletePullRequestBranch,extractSanitizedErrorDiagnostics:()=>extractSanitizedErrorDiagnostics,fetchActiveEpicRuns:()=>fetchActiveEpicRuns,fetchConductorConfigField:()=>fetchConductorConfigField,fetchConductorJsonPatchWithTimeout:()=>fetchConductorJsonPatchWithTimeout,fetchConductorJsonPostWithTimeout:()=>fetchConductorJsonPostWithTimeout,fetchConductorJsonPutWithTimeout:()=>fetchConductorJsonPutWithTimeout,fetchConductorJsonWithTimeout:()=>fetchConductorJsonWithTimeout,fetchConductorReadiness:()=>fetchConductorReadiness,fetchEffectiveSupervisorConfig:()=>fetchEffectiveSupervisorConfig,fetchEffectiveSupervisorSetup:()=>fetchEffectiveSupervisorSetup,fetchEpicRunState:()=>fetchEpicRunState,fetchParseStatus:()=>fetchParseStatus,fetchPrReviewStatus:()=>fetchPrReviewStatus,fetchShadowDispatchFreshness:()=>fetchShadowDispatchFreshness,getEpicPlan:()=>getEpicPlan,mergePullRequestForGate:()=>mergePullRequestForGate,parseConductorReadinessResponse:()=>parseConductorReadinessResponse,parseConductorSupervisorBootstrapResponse:()=>parseConductorSupervisorBootstrapResponse,pollCiChecksForCommit:()=>pollCiChecksForCommit,reconcileShadowMerge:()=>reconcileShadowMerge,recordEpicDispatch:()=>recordEpicDispatch,remediateEpicTicket:()=>remediateEpicTicket,replaceEpicRunPolicy:()=>replaceEpicRunPolicy,resolveConductorBridgeApiAccess:()=>resolveConductorBridgeApiAccess,safeDiagnosticMessage:()=>safeDiagnosticMessage,storeEpicPlan:()=>storeEpicPlan,transitionEpicDispatch:()=>transitionEpicDispatch,transitionJiraStatus:()=>transitionJiraStatus,triggerRepositoryParse:()=>triggerRepositoryParse,updateApprovedPlanNodeTicketSpec:()=>updateApprovedPlanNodeTicketSpec,updateEpicRunStatus:()=>updateEpicRunStatus,validateEpicPlan:()=>validateEpicPlan});import os4 from"node:os";import{readFile,stat}from"node:fs/promises";async function resolveConductorBridgeApiAccess(deps={}){let env=deps.env??process.env,cwd=deps.cwd??process.cwd(),homedir=deps.homedir??os4.homedir,platform=deps.platform??process.platform,readFileImpl=deps.readFile??(p=>readFile(p,"utf-8")),statImpl=deps.stat??(p=>stat(p)),repoName=deps.repoName?.trim()||await resolveStartTicketsRepoName({env,cwd,readFile:readFileImpl});if(!repoName)return{ok:!1,kind:"repo-missing",error:"could not resolve repo name (set BAPI_REPO_NAME or add a valid .bridge/config)"};let credResult;try{credResult=await resolveBapiCredentials(repoName,{env,homedir,platform,readFile:readFileImpl,stat:statImpl})}catch{return{ok:!1,kind:"credentials-unavailable",error:"failed to resolve Bridge API credentials"}}if(!credResult.ok)return{ok:!1,kind:"credentials-unavailable",error:"Bridge API credentials unavailable"};let baseUrlRaw=env.BAPI_BASE_URL,baseUrl=typeof baseUrlRaw=="string"&&baseUrlRaw.trim().length>0?baseUrlRaw.trim():CONDUCTOR_DEFAULT_BASE_URL;return{ok:!0,access:{repoName,apiKey:credResult.credentials.apiKey,baseUrl}}}function buildConductorJiraUrl(baseUrl,apiPath,params={}){let trimmed=baseUrl.replace(/\/+$/,""),url=new URL(`${trimmed}/jira${apiPath}`);for(let[k,v]of Object.entries(params))url.searchParams.set(k,v);return url.toString()}function redactErrorPreview(text){return text.replace(/sk-[A-Za-z0-9_-]{8,}/g,"[REDACTED]").replace(/(Bearer|X-API-Key|api[_-]?key)\b\s*[:=]?\s*\S+/gi,"$1 [REDACTED]").replace(/(webhook[_-]?url)\b["']?\s*[:=]?\s*["']?https?:\/\/\S+/gi,"$1 [REDACTED]").replace(/https?:\/\/[^\s/@]+:[^\s/@]+@\S+/gi,"[REDACTED]")}function stripWebhookUrlsDeep(value,depth=0){if(depth>12)return;if(Array.isArray(value))return value.map(item=>stripWebhookUrlsDeep(item,depth+1));if(!value||typeof value!="object")return value;let out={};for(let[key,item]of Object.entries(value))key!=="webhook_url"&&(out[key]=stripWebhookUrlsDeep(item,depth+1));return out}function boundedErrorPreview(text){let redacted=redactErrorPreview(text).replace(/\s+/g," ").trim();return redacted.length>CONDUCTOR_ERROR_PREVIEW_MAX?`${redacted.slice(0,CONDUCTOR_ERROR_PREVIEW_MAX)}\u2026`:redacted}function formatValidationDetailItem(item){if(!item||typeof item!="object")return;let record=item,msg=record.msg;if(typeof msg!="string"||!msg.trim())return;let loc=record.loc,parts=Array.isArray(loc)?loc.filter(part=>typeof part=="string"||typeof part=="number"):[],path8=(parts[0]==="body"?parts.slice(1):parts).slice(0,CONDUCTOR_VALIDATION_LOC_MAX_PARTS).join(".");return path8?`${path8}: ${msg}`:msg}function extractSanitizedErrorDiagnostics(body){if(typeof body=="string"){let trimmed=body.trim();return trimmed?{bodyPreview:boundedErrorPreview(trimmed)}:{}}if(!body||typeof body!="object")return{};let record=body,detail=record.detail,errorCode,message;if(Array.isArray(detail))message=formatValidationDetailItem(detail[0]);else if(detail&&typeof detail=="object"){let d=detail;typeof d.error_code=="string"&&(errorCode=d.error_code),typeof d.message=="string"&&(message=d.message)}else typeof detail=="string"&&(message=detail);!errorCode&&typeof record.error_code=="string"&&(errorCode=record.error_code),!message&&typeof record.message=="string"&&(message=record.message);let diagnostics={};return errorCode&&(diagnostics.errorCode=boundedErrorPreview(errorCode)),message&&(diagnostics.bodyPreview=boundedErrorPreview(message)),diagnostics}function redactDiagnosticValues(diagnostics,secrets){let scrub=text=>{let out2=text;for(let secret of secrets)secret&&secret.length>=4&&(out2=out2.split(secret).join("[REDACTED]"));return out2},out={};return diagnostics.errorCode&&(out.errorCode=scrub(diagnostics.errorCode)),diagnostics.bodyPreview&&(out.bodyPreview=scrub(diagnostics.bodyPreview)),out}async function readSanitizedErrorDiagnostics(resp,headers={}){try{let diagnostics=extractSanitizedErrorDiagnostics(stripWebhookUrlsDeep(await resp.json())),secrets=Object.entries(headers).filter(([k])=>/key|authorization|token/i.test(k)).map(([,v])=>v);return redactDiagnosticValues(diagnostics,secrets)}catch{return{}}}function safeDiagnosticMessage(err,fallback){if(err instanceof ConductorBridgeApiError){let parts=[`kind=${err.kind}`];return typeof err.status=="number"&&parts.push(`status=${err.status}`),err.errorCode&&parts.push(`code=${err.errorCode}`),err.bodyPreview&&parts.push(err.bodyPreview),parts.join(" ")}return err instanceof Error?err.constructor.name:fallback}function conductorGetHeaders(access){return{"X-API-Key":access.apiKey}}async function fetchConductorJsonWithTimeout(url,headers,timeoutMs,fetchImpl=globalThis.fetch){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),timeoutMs);try{let resp;try{resp=await fetchImpl(url,{headers,signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(!resp.ok){let diagnostics=await readSanitizedErrorDiagnostics(resp,headers);throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status,diagnostics):resp.status>=500?new ConductorBridgeApiError("server",resp.status,diagnostics):new ConductorBridgeApiError("http",resp.status,diagnostics)}try{return await resp.json()}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function fetchConductorConfigField(access,fieldName,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`/config-field/${encodeURIComponent(fieldName)}`,{repo_name:access.repoName}),body=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);if(body&&typeof body=="object"&&"value"in body)return body.value}async function fetchEffectiveSupervisorSetup(access,epicKey,fetchImpl=globalThis.fetch){let apiPath=epicKey?`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}/supervisor-setup/`:`${EPIC_RUNS_API_PREFIX}/supervisor-setup/defaults/`,url=buildConductorJiraUrl(access.baseUrl,apiPath,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchEffectiveSupervisorConfig(access,epicKey,fetchImpl=globalThis.fetch){let apiPath=epicKey?`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}/supervisor-config/`:`${EPIC_RUNS_API_PREFIX}/supervisor-config/defaults/`,url=buildConductorJiraUrl(access.baseUrl,apiPath,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function pollCiChecksForCommit(access,commitRef,fetchImpl=globalThis.fetch){let sha=normalizeSha(commitRef);if(sha===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorJiraUrl(access.baseUrl,"/poll-ci-checks",{repo_name:access.repoName,commit_ref:sha});return fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchPrReviewStatus(access,prNumber,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(prNumber);if(pr===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/reviews/status`),fullUrl=new URL(url);return fullUrl.searchParams.set("repo_name",access.repoName),fetchConductorJsonWithTimeout(fullUrl.toString(),conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function buildConductorVcsUrl(baseUrl,apiPath){let trimmed=baseUrl.replace(/\/+$/,""),path8=apiPath.startsWith("/")?apiPath:`/${apiPath}`;return new URL(`${trimmed}${path8}`).toString()}function conductorPostHeaders(access){return{"X-API-Key":access.apiKey,"Content-Type":"application/json"}}async function fetchConductorJsonWithMethodAndTimeout(method,url,headers,body,timeoutMs,fetchImpl){let{body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl);return parsed}async function fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),timeoutMs);try{let resp;try{resp=await fetchImpl(url,{method,headers,body,signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(!resp.ok){let diagnostics=await readSanitizedErrorDiagnostics(resp,headers);throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status,diagnostics):resp.status>=500?new ConductorBridgeApiError("server",resp.status,diagnostics):new ConductorBridgeApiError("http",resp.status,diagnostics)}try{return{status:resp.status,body:await resp.json()}}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function fetchConductorJsonPostWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("POST",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPatchWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PATCH",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPutWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PUT",url,headers,body,timeoutMs,fetchImpl)}async function mergePullRequestForGate(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number),sha=normalizeSha(request.expected_head_sha);if(pr===null||sha===null||!request.action_key||!request.repo_name)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/merge`),body=JSON.stringify({repo_name:request.repo_name,expected_head_sha:sha,gate:request.gate,action_key:request.action_key,...request.gate_event?{gate_event:request.gate_event}:{}});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function remediateEpicTicket(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number);if(pr===null||!request.epic_run_id||!request.ticket_key||!request.head_sha||!request.idempotency_key)throw new ConductorBridgeApiError("invalid-input");if(requireNonNegativeSafeInteger(request.expected_row_version),request.attempt_kind!=="nudge"&&request.attempt_kind!=="redispatch")throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/remediate`),body=JSON.stringify({repo_name:access.repoName,epic_run_id:request.epic_run_id,ticket_key:request.ticket_key,expected_row_version:request.expected_row_version,head_sha:request.head_sha,idempotency_key:request.idempotency_key,attempt_kind:request.attempt_kind,...request.reason?{reason:request.reason}:{}});try{return{ok:!0,conflict:!1,response:await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===409)return{ok:!0,conflict:!0};throw err}}function requireNonEmptyString(value){if(typeof value!="string"||value.trim().length===0)throw new ConductorBridgeApiError("invalid-input")}function requirePositiveSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<=0)throw new ConductorBridgeApiError("invalid-input")}function requireNonNegativeSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<0)throw new ConductorBridgeApiError("invalid-input")}function requireNoSlashPathSegment(value){if(value.includes("/"))throw new ConductorBridgeApiError("invalid-input")}function requireEpicTicketStatusValue(value){if(typeof value!="string"||!EPIC_TICKET_STATUS_VALUES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function requireEpicDispatchTransitionStatus(value){if(typeof value!="string"||!EPIC_DISPATCH_TRANSITION_STATUSES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function epicRunApiPath(epicKey){return`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}`}function epicDispatchTransitionApiPath(dispatchKey,nextStatus){return nextStatus==="run_spawned"?`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/run-spawned`:`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/terminal`}function buildEpicDispatchKey(epicKey,ticketKey,planVersion,attempt=0){requireNonEmptyString(epicKey),requireNonEmptyString(ticketKey),requireNonNegativeSafeInteger(planVersion),requireNonNegativeSafeInteger(attempt);let base=`dispatch:${epicKey}:${ticketKey}:${planVersion}`;return attempt>0?`${base}:r${attempt}`:base}function parseEpicSupervisionLeaseResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed,row=p.row;if(p.claimed===!0&&row&&typeof row=="object")return{ok:!0,kind:"acquired-or-renewed",row};if(p.claimed===!1&&p.reason==="lease_held"&&row&&typeof row=="object")return{ok:!1,kind:"held-by-other",reason:"lease_held",row};if(p.claimed===!1&&p.reason==="terminal"&&row&&typeof row=="object")return{ok:!1,kind:"terminal",reason:"terminal",row};throw new ConductorBridgeApiError("server")}async function claimEpicSupervisionLease(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.leaseOwner),requirePositiveSafeInteger(request.ttlSeconds);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/lease/claim`),body=JSON.stringify({repo_name:access.repoName,lease_owner:request.leaseOwner,ttl_seconds:request.ttlSeconds}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseEpicSupervisionLeaseResult(parsed)}async function fetchEpicRunState(access,epicKey,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/state`,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchActiveEpicRuns(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`,{repo_name:access.repoName,status:"active",limit:"20"}),parsed=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);if(parsed&&typeof parsed=="object"){let runs=parsed.runs;if(Array.isArray(runs))return runs}return[]}async function createEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`);return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function createEpicRunWithDisposition(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`),{status,body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout("POST",url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return{run:parsed,created:status===201}}async function replaceEpicRunPolicy(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicRunId)),body=JSON.stringify({repo_name:access.repoName,policy_json:request.policyJson});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateEpicRunStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicKey)),body=JSON.stringify({repo_name:access.repoName,status:request.status,...request.expectedStatus?{expected_status:request.expectedStatus}:{}});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseAdvanceEpicTicketStatusResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed;if(p.ok===!1&&p.kind==="cas-conflict")return{ok:!1,kind:"cas-conflict",...typeof p.current_row_version=="number"?{current_row_version:p.current_row_version}:{},...p.ticket_status&&typeof p.ticket_status=="object"?{ticket_status:p.ticket_status}:{}};if(p.ok===!0&&p.ticket_status&&typeof p.ticket_status=="object")return{ok:!0,ticket_status:p.ticket_status};if("ticket_key"in p&&"status"in p&&"row_version"in p)return{ok:!0,ticket_status:parsed};throw new ConductorBridgeApiError("server")}async function advanceEpicTicketStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion),requireNonNegativeSafeInteger(request.planVersion),requireEpicTicketStatusValue(request.nextStatus),request.dispatchRunId!==void 0&&requireNonEmptyString(request.dispatchRunId);let CAS_ENDPOINT_PATH=`${epicRunApiPath(request.epicKey)}/tickets/${encodeURIComponent(request.ticketKey)}`,url=buildConductorJiraUrl(access.baseUrl,CAS_ENDPOINT_PATH),body=JSON.stringify({repo_name:access.repoName,status:request.nextStatus,plan_version:request.planVersion,expected_row_version:request.expectedRowVersion,...request.dispatchRunId?{dispatch_run_id:request.dispatchRunId}:{}}),parsed=await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseAdvanceEpicTicketStatusResult(parsed)}async function createEpicTicketStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireEpicTicketStatusValue(request.status),requireNonNegativeSafeInteger(request.planVersion),request.dispatchRunId!==void 0&&requireNonEmptyString(request.dispatchRunId);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/tickets`),body=JSON.stringify({repo_name:access.repoName,ticket_key:request.ticketKey,status:request.status,plan_version:request.planVersion,...request.dispatchRunId?{dispatch_run_id:request.dispatchRunId}:{}});await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseEpicDispatchResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed,row=p.row;if(!row||typeof row!="object")throw new ConductorBridgeApiError("server");let dispatch=row;if(p.claimed===!0)return{ok:!0,kind:"claimed",dispatch};if(p.claimed===!1){let reason=p.reason;if(reason==="already_spawned")return{ok:!0,kind:"already-spawned",dispatch};if(reason==="already_exists")return{ok:!0,kind:"already-exists",dispatch};if(reason==="terminal")return{ok:!0,kind:"terminal",terminal:!0,dispatch};if(reason==="lease_held")return{ok:!1,kind:"lease-held",dispatch}}throw new ConductorBridgeApiError("server")}async function recordEpicDispatch(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.leaseOwner),requireNonNegativeSafeInteger(request.planVersion),requirePositiveSafeInteger(request.ttlSeconds);let dispatchKey=buildEpicDispatchKey(request.epicKey,request.ticketKey,request.planVersion,request.attempt??0)+(request.reviewRole?":review":""),url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/dispatch/claim`),body=JSON.stringify({repo_name:access.repoName,epic_run_id:request.epicKey,ticket_key:request.ticketKey,plan_version:request.planVersion,lease_owner:request.leaseOwner,ttl_seconds:request.ttlSeconds,dispatch_key:dispatchKey}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseEpicDispatchResult(parsed)}async function transitionEpicDispatch(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.dispatchKey),requireNoSlashPathSegment(request.dispatchKey),requireEpicDispatchTransitionStatus(request.nextStatus),request.nextStatus==="run_spawned"&&requireNonEmptyString(request.runId);let path8=epicDispatchTransitionApiPath(request.dispatchKey,request.nextStatus),url=buildConductorJiraUrl(access.baseUrl,path8),body=request.nextStatus==="run_spawned"?JSON.stringify({repo_name:access.repoName,run_id:request.runId}):JSON.stringify({repo_name:access.repoName});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseShadowMergeReconcileResult(parsed){let obj=parsed??{};return{applies:obj.applies===!0,scheduled:obj.scheduled===!0,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:"unknown",shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,requiredCommitSha:typeof obj.required_commit_sha=="string"?obj.required_commit_sha:null,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null}}function parseShadowDispatchFreshnessResult(parsed){let obj=parsed??{},rawVerdict=typeof obj.verdict=="string"?obj.verdict:"",verdict=SHADOW_FRESHNESS_VERDICTS.has(rawVerdict)?rawVerdict:"stale";return{verdict,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:verdict,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null,indexedCommitSha:typeof obj.indexed_commit_sha=="string"?obj.indexed_commit_sha:null,shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,lastError:typeof obj.last_error=="string"?obj.last_error:null}}async function reconcileShadowMerge(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/shadow/merge-reconcile`),body=JSON.stringify({repo_name:access.repoName,merged_ticket_key:request.mergedTicketKey??null}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseShadowMergeReconcileResult(parsed)}async function fetchShadowDispatchFreshness(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNoSlashPathSegment(request.ticketKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/tickets/${encodeURIComponent(request.ticketKey)}/shadow-freshness`),body=JSON.stringify({repo_name:access.repoName}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseShadowDispatchFreshnessResult(parsed)}async function validateEpicPlan(access,request,fetchImpl=globalThis.fetch){requirePositiveSafeInteger(request.planVersion);let blobVersion=request.planBlob.plan_version;if(blobVersion!==void 0&&blobVersion!==request.planVersion)throw new ConductorValidationError(`planVersion mismatch: request.planVersion=${request.planVersion} but planBlob.plan_version=${blobVersion}`);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/plan/validate`),body={repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob};request.epicKey!==void 0&&(body.epic_key=request.epicKey);let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseValidateEpicPlanResult(parsed)}function parseValidateEpicPlanResult(parsed){if(!parsed||typeof parsed!="object"||Array.isArray(parsed))throw new ConductorBridgeApiError("server");let p=parsed,planHash=p.plan_hash,serializationEnabled=p.serialization_enabled,insertedEdges=p.inserted_edges;if(p.valid!==!0||typeof planHash!="string"||planHash.trim()===""||typeof serializationEnabled!="boolean"||typeof insertedEdges!="number"||!Number.isSafeInteger(insertedEdges)||insertedEdges<0)throw new ConductorBridgeApiError("server");return{planHash,serializationEnabled,insertedEdges}}async function storeEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion),requireNonEmptyString(request.planHash);let blobVersion=request.planBlob.plan_version;if(blobVersion!==void 0&&blobVersion!==request.planVersion)throw new ConductorValidationError(`planVersion mismatch: request.planVersion=${request.planVersion} but planBlob.plan_version=${blobVersion}`);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob,plan_hash:request.planHash});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateApprovedPlanNodeTicketSpec(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.expectedPlanHash),requireNonEmptyString(request.ticketSpec);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan/nodes/${encodeURIComponent(request.ticketKey)}/ticket-spec`),body=JSON.stringify({repo_name:access.repoName,expected_plan_hash:request.expectedPlanHash,ticket_spec:request.ticketSpec});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseApproveEpicPlanSuccess(parsed){let record=parsed??{},result={ok:!0,plan_hash:record.plan_hash},prov=record.feature_branch_provisioning;if(prov&&typeof prov=="object"&&!Array.isArray(prov)){let p=prov;(p.status==="created"||p.status==="already_exists")&&typeof p.feature_branch=="string"&&typeof p.source_branch=="string"&&typeof p.source_sha=="string"&&typeof p.remote_head_sha=="string"&&(result.featureBranchProvisioning={status:p.status,feature_branch:p.feature_branch,source_branch:p.source_branch,source_sha:p.source_sha,remote_head_sha:p.remote_head_sha})}return result}async function approveEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/approve-plan`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion});try{let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseApproveEpicPlanSuccess(parsed)}catch(error){if(error instanceof ConductorBridgeApiError&&error.status===409){let preview=error.bodyPreview??"";return/multiple active runs/i.test(preview)?{ok:!1,kind:"conflict",reason:"multiple_active_runs"}:{ok:!1,kind:"conflict",reason:"superseded"}}throw error}}async function getEpicPlan(access,epicKey,planVersion,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/plan`,{repo_name:access.repoName,plan_version:String(planVersion)});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchParseStatus(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-status",{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function triggerRepositoryParse(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-repository"),body=JSON.stringify({repo_name:access.repoName});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function deletePullRequestBranch(access,prNumber,expectedHeadSha,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(prNumber);if(pr===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/branch?repo_name=${encodeURIComponent(access.repoName)}&expected_head_sha=${encodeURIComponent(expectedHeadSha)}`),controller=new AbortController,timer=setTimeout(()=>controller.abort(),CONDUCTOR_FETCH_TIMEOUT_MS);try{let resp;try{resp=await fetchImpl(url,{method:"DELETE",headers:{"X-API-Key":access.apiKey},body:"",signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(resp.status===404)return{deleted:!1,branch:null,reason:"not_found"};if(!resp.ok)throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status):resp.status>=500?new ConductorBridgeApiError("server",resp.status):new ConductorBridgeApiError("http",resp.status);try{return await resp.json()}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function transitionJiraStatus(access,ticketNumber,targetStatus="auto",fetchImpl=globalThis.fetch){if(!ticketNumber)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorJiraUrl(access.baseUrl,`/tickets/${encodeURIComponent(ticketNumber)}/jira-status`),body=JSON.stringify({repo_name:access.repoName,target_status:targetStatus});try{return await fetchConductorJsonPutWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl),{status:"transitioned"}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===400)return{status:"skipped"};throw err}}function readinessShapeError(){return new ConductorBridgeApiError("invalid-input",void 0,{errorCode:"READINESS_SHAPE_INVALID"})}function requireObject(value){if(typeof value!="object"||value===null||Array.isArray(value))throw readinessShapeError();return value}function requireBool(o,key){let v=o[key];if(typeof v!="boolean")throw readinessShapeError();return v}function requireInt(o,key){let v=o[key];if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableInt(o,key){let v=o[key];if(v==null)return null;if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableString(o,key){let v=o[key];if(v==null)return null;if(typeof v!="string")throw readinessShapeError();return v}function requireNullableBool(o,key){let v=o[key];if(v==null)return null;if(typeof v!="boolean")throw readinessShapeError();return v}function parseReviewPolicyAlignment(o){let raw=o.review_policy_alignment;if(raw==null)return null;let a=requireObject(raw),explanation=a.explanation;if(typeof explanation!="string")throw readinessShapeError();return{status:requireEnum(a,"status",CONDUCTOR_REVIEW_ALIGNMENT_STATUSES),repo_review_signal:requireNullableString(a,"repo_review_signal"),done_gate_review_signal:requireNullableString(a,"done_gate_review_signal"),explanation}}function requireEnum(o,key,allowed){let v=o[key];if(typeof v!="string"||!allowed.has(v))throw readinessShapeError();return v}function parseConductorReadinessResponse(body){let root=requireObject(body),repoName=root.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let sup=requireObject(root.supervisor),gh=requireObject(root.github),rec=requireObject(root.reconciler),exec=requireObject(root.executor),thr=requireObject(root.thresholds);return{repo_name:repoName,supervisor:{setup_present:requireBool(sup,"setup_present"),setup_source:requireEnum(sup,"setup_source",READINESS_SOURCES),setup_created_at:requireNullableString(sup,"setup_created_at"),setup_updated_at:requireNullableString(sup,"setup_updated_at"),config_present:requireBool(sup,"config_present"),config_source:requireEnum(sup,"config_source",READINESS_SOURCES),config_created_at:requireNullableString(sup,"config_created_at"),config_updated_at:requireNullableString(sup,"config_updated_at"),required_checks_count:requireInt(sup,"required_checks_count"),required_checks_empty:requireBool(sup,"required_checks_empty"),auto_merge_enabled:requireBool(sup,"auto_merge_enabled"),merge_approval_required_set:requireBool(sup,"merge_approval_required_set"),review_policy_alignment:parseReviewPolicyAlignment(sup),review_policy_present:sup.review_policy_present===!0},github:{credentials_readable:requireBool(gh,"credentials_readable"),owner_resolved:requireBool(gh,"owner_resolved"),repo_id_resolved:requireBool(gh,"repo_id_resolved"),installation_id_resolved:requireBool(gh,"installation_id_resolved"),credentials_complete:requireBool(gh,"credentials_complete"),actions_probe_succeeded:requireBool(gh,"actions_probe_succeeded"),actions_permission_present:requireBool(gh,"actions_permission_present"),actions_permission_level:requireEnum(gh,"actions_permission_level",ACTIONS_LEVELS),actions_write:requireBool(gh,"actions_write")},reconciler:{liveness_readable:requireBool(rec,"liveness_readable"),last_tick_at:requireNullableString(rec,"last_tick_at"),last_tick_age_seconds:requireNullableInt(rec,"last_tick_age_seconds"),stale:requireBool(rec,"stale"),active_run_count:requireInt(rec,"active_run_count"),expired_lease_count:requireInt(rec,"expired_lease_count")},executor:{liveness_readable:requireBool(exec,"liveness_readable"),last_seen_at:requireNullableString(exec,"last_seen_at"),last_seen_age_seconds:requireNullableInt(exec,"last_seen_age_seconds"),ready:requireNullableBool(exec,"ready")},thresholds:{reconciler_stale_after_seconds:requireInt(thr,"reconciler_stale_after_seconds"),executor_stale_after_seconds:requireInt(thr,"executor_stale_after_seconds")}}}async function fetchConductorReadiness(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/conductor-readiness`,{repo_name:access.repoName}),body=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorReadinessResponse(body)}function parseConductorSupervisorBootstrapResponse(body){let o=requireObject(body),repoName=o.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let names=o.audited_field_names;if(!Array.isArray(names)||names.some(n=>typeof n!="string"))throw readinessShapeError();return{repo_name:repoName,setup_written:requireBool(o,"setup_written"),config_written:requireBool(o,"config_written"),setup_source:requireEnum(o,"setup_source",READINESS_SOURCES),config_source:requireEnum(o,"config_source",READINESS_SOURCES),setup_created_at:requireNullableString(o,"setup_created_at"),setup_updated_at:requireNullableString(o,"setup_updated_at"),config_created_at:requireNullableString(o,"config_created_at"),config_updated_at:requireNullableString(o,"config_updated_at"),required_checks_count:requireInt(o,"required_checks_count"),audited_field_names:names}}async function bootstrapConductorSupervisorDefaults(access,request,fetchImpl){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/supervisor-bootstrap`,{repo_name:access.repoName}),body=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(request),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorSupervisorBootstrapResponse(body)}var CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_BRIDGE_API_ERROR_KINDS,CONDUCTOR_ERROR_PREVIEW_MAX,CONDUCTOR_VALIDATION_LOC_MAX_PARTS,ConductorBridgeApiError,EPIC_TICKET_STATUS_VALUES,EPIC_DISPATCH_TRANSITION_STATUSES,EPIC_RUNS_API_PREFIX,SHADOW_FRESHNESS_VERDICTS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,READINESS_SOURCES,ACTIONS_LEVELS,init_bridge_api_client=__esm({"src/conductor/bridge-api-client.ts"(){"use strict";init_credential_store();init_start_tickets_repo();init_git_ci_types();init_errors();CONDUCTOR_DEFAULT_BASE_URL="https://bridgegpt-api.com",CONDUCTOR_FETCH_TIMEOUT_MS=3e4;CONDUCTOR_BRIDGE_API_ERROR_KINDS=["invalid-input","network","timeout","unauthorized","server","http"],CONDUCTOR_ERROR_PREVIEW_MAX=200;CONDUCTOR_VALIDATION_LOC_MAX_PARTS=8;ConductorBridgeApiError=class extends Error{kind;status;errorCode;bodyPreview;constructor(kindOrMessage,status,diagnostics){let isKnownKind=CONDUCTOR_BRIDGE_API_ERROR_KINDS.includes(kindOrMessage),errorCode=diagnostics?.errorCode,bodyPreview=diagnostics?.bodyPreview;if(isKnownKind){let parts=[`Conductor Bridge API request failed (${kindOrMessage}${typeof status=="number"?`, status ${status}`:""})`];errorCode&&parts.push(`code=${errorCode}`),bodyPreview&&parts.push(bodyPreview),super(parts.join(": "))}else super(kindOrMessage);this.name="ConductorBridgeApiError",this.kind=isKnownKind?kindOrMessage:"http",typeof status=="number"&&(this.status=status),errorCode&&(this.errorCode=errorCode),bodyPreview&&(this.bodyPreview=bodyPreview)}};EPIC_TICKET_STATUS_VALUES=["planned","ready","dispatched","running","blocked","abandoned","done","ready_for_review","reviewing","parse_pending"];EPIC_DISPATCH_TRANSITION_STATUSES=["run_spawned","terminal"];EPIC_RUNS_API_PREFIX="/epic-runs";SHADOW_FRESHNESS_VERDICTS=new Set(["not_applicable","covered","stale","failed"]);CONDUCTOR_REVIEW_ALIGNMENT_STATUSES=new Set(["aligned","divergent","not_configured","invalid"]),READINESS_SOURCES=new Set(["epic","project_default","none"]),ACTIONS_LEVELS=new Set(["write","read","none","unknown"])}});import{createHash as createHash4}from"node:crypto";function normalizeDimension(value){return(value??"").trim().toLowerCase()}function makeSupervisorIdempotencyKey(meta){return[normalizeDimension(meta.run_id),normalizeDimension(meta.worker_id)||"(run)",normalizeDimension(meta.reason),normalizeDimension(meta.kind),normalizeDimension(meta.cooldown_window)].join("|")}function makeSupervisorAssessmentEventId(idempotencyKey){let h=createHash4("sha256").update(`supervisor.assessment:${idempotencyKey}`).digest("hex");return`${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20,32)}`}function isDuplicateConstraintError3(error){if(!error||typeof error!="object")return!1;let code=error.code;if(typeof code=="string"&&code.startsWith("SQLITE_CONSTRAINT"))return!0;let message=error.message;if(typeof message=="string"){let lowered=message.toLowerCase();if(lowered.includes("unique constraint")||lowered.includes("constraint failed"))return!0}return!1}async function emitSupervisorAssessmentIfNew(input,deps={}){let emitEvent=deps.emitEvent??emitConductorEvent,idempotencyKey=makeSupervisorIdempotencyKey(input.idempotency),eventId=makeSupervisorAssessmentEventId(idempotencyKey),details={...input.details??{},idempotency_key:idempotencyKey,reason:input.idempotency.reason,kind:input.idempotency.kind,cooldown_window:input.idempotency.cooldown_window,classification:input.assessment.classification,confidence:input.assessment.confidence},event={id:eventId,source:"conductor-supervisor",type:"supervisor.assessment",run_id:input.run_id,worker_id:input.idempotency.worker_id??input.worker_id??null,producer:"conductor-supervisor",observed_via:"supervisor",data:{summary:`supervisor assessment: ${input.idempotency.reason}`,status:"escalated",reason:input.idempotency.reason,details}};try{let result=await emitEvent(event);return{emitted:!0,event_id:eventId,event:result.event}}catch(error){if(isDuplicateConstraintError3(error))return{emitted:!1,reason:"duplicate"};throw error}}var init_supervisor_ledger=__esm({"src/conductor/supervisor-ledger.ts"(){"use strict";init_store()}});function buildSupervisorEscalationWorkerMessage(candidate,assessment,state){let details={reason:candidate.reason,state:candidate.state,liveness:candidate.liveness,elapsed_ms:candidate.elapsed_ms,assessment_source:"deterministic"};return{run_id:state.run_id,worker_id:candidate.worker_id,type:`supervisor.${candidate.reason}`,cause_seq:state.last_seq,payload:{summary:`supervisor escalation: ${candidate.reason}`,status:"escalated",details},source:"conductor-supervisor",producer:"worker-message-relay"}}async function sendSupervisorEscalationWorkerMessageIfNew(candidate,assessment,state,deps={}){let sendMessage=deps.sendMessage??sendWorkerMessage,input=buildSupervisorEscalationWorkerMessage(candidate,assessment,state);return sendMessage(input)}var init_supervisor_message_relay=__esm({"src/conductor/supervisor-message-relay.ts"(){"use strict";init_store()}});function isTerminalState(state){return TERMINAL_STATES.has(state)}function isoToMs(value){if(typeof value!="string"||value.length===0)return null;let ms=Date.parse(value);return Number.isFinite(ms)?ms:null}function msToIso(now){return new Date(now).toISOString()}function createEmptySupervisorRunState(runId,config,now){let startedIso=msToIso(now);return{run_id:runId,status:"unknown",last_seq:0,last_event_time:null,workers:{},gates:{},latest_assessment:null,escalations:[],started_at:startedIso,updated_at:startedIso,global_deadline_at:msToIso(now+config.global_timeout_ms),roster_discovered:!1}}function isValidSupervisorSummary(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)&&value.kind===SUPERVISOR_SUMMARY_KIND}function hydrateSupervisorRunStateFromSnapshot(snapshot,runId,config,now){let empty=createEmptySupervisorRunState(runId,config,now),summary=snapshot?.projection?.summary;return isValidSupervisorSummary(summary)?{...empty,status:typeof summary.status=="string"?summary.status:empty.status,last_seq:typeof summary.last_seq=="number"&&summary.last_seq>=0?summary.last_seq:empty.last_seq,last_event_time:typeof summary.last_event_time=="string"?summary.last_event_time:null,workers:isPlainRecord(summary.workers)?summary.workers:{},gates:isPlainRecord(summary.gates)?summary.gates:{},latest_assessment:summary.latest_assessment&&typeof summary.latest_assessment=="object"?summary.latest_assessment:null,escalations:Array.isArray(summary.escalations)?summary.escalations:[],started_at:typeof summary.started_at=="string"?summary.started_at:empty.started_at,global_deadline_at:typeof summary.global_deadline_at=="string"?summary.global_deadline_at:empty.global_deadline_at,roster_discovered:summary.roster_discovered===!0,run_id:runId}:empty}function isPlainRecord(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)}function ensureWorkerState(state,workerId,options={}){let existing=state.workers[workerId];if(existing)return options.ticketKey&&!existing.ticket_key&&(existing.ticket_key=options.ticketKey),existing;let created={worker_id:workerId,ticket_key:options.ticketKey??null,state:options.fromRoster?"not_started":"unknown",liveness:"unknown",first_seen_seq:options.seq??null,last_event_seq:options.seq??null,last_event_time:null,last_progress_time:null,last_heartbeat_time:null,blocked_reason:null,terminal_reason:null,observed_event_types:[]};return state.workers[workerId]=created,created}function noteObservedType(worker,eventType){worker.observed_event_types.includes(eventType)||worker.observed_event_types.push(eventType)}function eventDetails(event){let details=event.data?.details;return isPlainRecord(details)?details:{}}function extractRoster(event){let candidates=[eventDetails(event).workers,event.data?.workers,isPlainRecord(event.data?.raw)?event.data.raw.workers:void 0];for(let candidate of candidates)if(Array.isArray(candidate)){let roster=[];for(let entry of candidate){if(!isPlainRecord(entry))continue;let workerId=entry.worker_id;if(typeof workerId!="string"||workerId.length===0)continue;let ticketKey=entry.ticket_key;roster.push({worker_id:workerId,ticket_key:typeof ticketKey=="string"?ticketKey:null})}if(roster.length>0)return roster}return[]}function eventStatus(event){let status=event.data?.status;return typeof status=="string"?status.trim().toLowerCase():""}function eventReason(event){let reason=event.data?.reason??eventDetails(event).reason;return typeof reason=="string"?reason.trim().toLowerCase():""}function applyConductorEventToSupervisorState(state,event,now){if(event.run_id!==state.run_id)return state;let eventType=event.type,eventTimeMs=isoToMs(event.time)??now,eventTimeIso=event.time??msToIso(now);if(typeof event.seq=="number"&&event.seq>state.last_seq&&(state.last_seq=event.seq),state.last_event_time=eventTimeIso,state.status==="unknown"&&(state.status="active"),eventType==="run.started"){let roster=extractRoster(event);roster.length>0&&(state.roster_discovered=!0);for(let member of roster){let worker2=ensureWorkerState(state,member.worker_id,{fromRoster:!0,ticketKey:member.ticket_key,seq:event.seq});noteObservedType(worker2,eventType),worker2.last_event_seq=event.seq??worker2.last_event_seq,worker2.last_event_time=eventTimeIso}return state.updated_at=msToIso(now),state}if(eventType==="supervisor.assessment"||eventType==="message.sent")return state.updated_at=msToIso(now),state;let workerId=event.worker_id;if(typeof workerId!="string"||workerId.length===0)return applyRunLevelEvent(state,event,eventType),state.updated_at=msToIso(now),state;let worker=ensureWorkerState(state,workerId,{seq:event.seq});switch(noteObservedType(worker,eventType),worker.last_event_seq=event.seq??worker.last_event_seq,worker.last_event_time=eventTimeIso,eventType){case"run.heartbeat":{worker.last_heartbeat_time=eventTimeIso,!isTerminalState(worker.state)&&worker.state!=="blocked"&&(worker.state==="not_started"||worker.state==="unknown")&&(worker.state="active");break}case"agent.notification":{let status=eventStatus(event),reason=eventReason(event);BLOCKED_STATUS_TOKENS.has(status)||BLOCKED_STATUS_TOKENS.has(reason)?isTerminalState(worker.state)||(worker.state="blocked",worker.blocked_reason=status||reason||"blocked"):!isTerminalState(worker.state)&&worker.state==="not_started"&&(worker.state="active");break}case"tool.intent":case"worktree.changed":case"git.commit_created":{PROGRESS_EVENT_TYPES.has(eventType)&&(worker.last_progress_time=eventTimeIso,isTerminalState(worker.state)||((worker.state==="not_started"||worker.state==="unknown"||worker.state==="stalled"||worker.state==="blocked")&&(worker.state="active"),worker.blocked_reason=null));break}case"gate.met":{isTerminalState(worker.state)||(worker.state="candidate_done");break}case"ci.passed":{isTerminalState(worker.state)||(worker.state="verifying"),worker.last_progress_time=eventTimeIso;break}case"ci.failed":{let reason=eventReason(event);eventStatus(event)==="terminal"||reason==="terminal"||reason==="give_up"?(worker.state="failed",worker.terminal_reason=reason||"ci_failed"):isTerminalState(worker.state)||(worker.last_progress_time=eventTimeIso);break}case"run.stopped":{let status=eventStatus(event),reason=eventReason(event);FAILED_STATUS_TOKENS.has(status)||FAILED_STATUS_TOKENS.has(reason)?(worker.state="failed",worker.terminal_reason=reason||status||"failed"):(worker.state="complete",worker.terminal_reason=reason||status||"complete");break}case"message.delivered":case"message.acked":{!isTerminalState(worker.state)&&(worker.state==="not_started"||worker.state==="unknown")&&(worker.state="active");break}case"merge.succeeded":{worker.state="complete",worker.terminal_reason=worker.terminal_reason||"merge_succeeded";break}case"merge.failed":break;case"merge.dry_run":break;case"merge.pending_approval":break;default:break}return state.updated_at=msToIso(now),state}function applyRunLevelEvent(state,event,eventType){switch(eventType){case"gate.met":state.gates.gate_met=!0;break;case"ci.passed":state.gates.ci="passed";break;case"ci.failed":state.gates.ci="failed";break;case"git.pr_opened":state.gates.pr_opened=!0;break;case"merge.succeeded":case"merge.failed":case"merge.dry_run":case"merge.pending_approval":state.gates.merge=eventType.slice(6);break;default:break}}function classifyWorkerLiveness(worker,config,now){if(isTerminalState(worker.state))return"alive";let lastSignalMs=mostRecentSignalMs(worker);if(lastSignalMs===null)return"unknown";let elapsed=now-lastSignalMs;return elapsed>=config.liveness.dead_after_ms?"dead":elapsed>=config.liveness.stalled_after_ms?"stalled":elapsed>=config.liveness.quiet_after_ms?"quiet":"alive"}function mostRecentSignalMs(worker){let candidates=[isoToMs(worker.last_heartbeat_time),isoToMs(worker.last_event_time),isoToMs(worker.last_progress_time)].filter(v=>v!==null);return candidates.length===0?null:Math.max(...candidates)}function stateAnchorMs(worker){return worker.state==="active"||worker.state==="verifying"?mostRecentSignalMs(worker):isoToMs(worker.last_event_time)??isoToMs(worker.last_heartbeat_time)??isoToMs(worker.last_progress_time)}function applySupervisorHousekeeping(state,config,now){for(let worker of Object.values(state.workers)){if(worker.liveness=classifyWorkerLiveness(worker,config,now),isTerminalState(worker.state)||worker.state==="stalled")continue;let threshold=config.stall_thresholds_ms[worker.state],anchor=stateAnchorMs(worker);anchor!==null&&now-anchor>=threshold&&(worker.state="stalled")}return state.updated_at=msToIso(now),state}function isSupervisorRunTerminal(state){let workers=Object.values(state.workers);return workers.length===0||!state.roster_discovered?!1:workers.every(w=>isTerminalState(w.state))}function hasSupervisorGlobalTimeoutElapsed(state,now){let deadlineMs=isoToMs(state.global_deadline_at);return deadlineMs===null?!1:now>=deadlineMs}function compactWorker(worker){return{worker_id:worker.worker_id,ticket_key:worker.ticket_key,state:worker.state,liveness:worker.liveness,last_event_seq:worker.last_event_seq,last_event_time:worker.last_event_time,last_progress_time:worker.last_progress_time,last_heartbeat_time:worker.last_heartbeat_time,blocked_reason:worker.blocked_reason,terminal_reason:worker.terminal_reason}}function toSupervisorProjectionInput(state){let summary={kind:SUPERVISOR_SUMMARY_KIND,run_id:state.run_id,status:state.status,last_seq:state.last_seq,last_event_time:state.last_event_time,workers:state.workers,gates:state.gates,latest_assessment:state.latest_assessment,escalations:state.escalations,started_at:state.started_at,updated_at:state.updated_at,global_deadline_at:state.global_deadline_at,roster_discovered:state.roster_discovered};return{run_id:state.run_id,status:state.status,last_seq:state.last_seq,last_event_time:state.last_event_time,active_workers:Object.values(state.workers).map(compactWorker),gates:state.gates,assessment:state.latest_assessment,summary}}var SUPERVISOR_SUMMARY_KIND,TERMINAL_STATES,PROGRESS_EVENT_TYPES,BLOCKED_STATUS_TOKENS,FAILED_STATUS_TOKENS,init_supervisor_state=__esm({"src/conductor/supervisor-state.ts"(){"use strict";SUPERVISOR_SUMMARY_KIND="supervisor_projection_summary",TERMINAL_STATES=new Set(["complete","failed"]);PROGRESS_EVENT_TYPES=new Set(["tool.intent","worktree.changed","git.commit_created"]),BLOCKED_STATUS_TOKENS=new Set(["blocked","waiting_for_input","needs_input"]),FAILED_STATUS_TOKENS=new Set(["failed","error","errored","aborted","cancelled","canceled"])}});function elapsedSinceSignal(worker,now){let candidates=[worker.last_event_time,worker.last_progress_time,worker.last_heartbeat_time].map(iso=>iso?Date.parse(iso):NaN).filter(v=>Number.isFinite(v));return candidates.length===0?0:Math.max(0,now-Math.max(...candidates))}function findSupervisorEscalationCandidates(state,config,now){let candidates=[];for(let worker of Object.values(state.workers)){if(worker.state==="complete"||worker.state==="failed")continue;let elapsed=elapsedSinceSignal(worker,now),baseContext={worker_id:worker.worker_id,ticket_key:worker.ticket_key,state:worker.state,liveness:worker.liveness};if(worker.liveness==="dead"){candidates.push({reason:"worker_dead",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});continue}switch(worker.state){case"not_started":worker.liveness!=="alive"&&candidates.push({reason:"worker_not_started",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"blocked":candidates.push({reason:"worker_blocked",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:{...baseContext,blocked_reason:worker.blocked_reason}});break;case"stalled":candidates.push({reason:"worker_stalled",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"candidate_done":worker.liveness!=="alive"&&candidates.push({reason:"candidate_done_stuck",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"verifying":worker.liveness==="stalled"&&candidates.push({reason:"verification_stalled",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;default:break}}let deadlineMs=state.global_deadline_at?Date.parse(state.global_deadline_at):NaN;return Number.isFinite(deadlineMs)&&now>=deadlineMs&&candidates.push({reason:"global_timeout",kind:ESCALATION_KIND,worker_id:null,state:null,liveness:null,elapsed_ms:Math.max(0,now-deadlineMs),context:{run_id:state.run_id,deadline_at:state.global_deadline_at,worker_count:Object.keys(state.workers).length}}),candidates}function cooldownWindowFor(now,cooldownMs){let width=cooldownMs>0?cooldownMs:1;return String(Math.floor(now/width))}function shouldEmitEscalation(state,candidate,config,now){let cooldownWindow=cooldownWindowFor(now,config.escalation_cooldown_ms);return{emit:!state.escalations.some(record=>record.reason===candidate.reason&&(record.worker_id??null)===(candidate.worker_id??null)&&record.cooldown_window===cooldownWindow&&(record.outcome==="emitted"||record.outcome==="duplicate")),cooldown_window:cooldownWindow}}function recordEscalationResult(state,candidate,cooldownWindow,idempotencyKey,outcome,now){let record={idempotency_key:idempotencyKey,worker_id:candidate.worker_id??null,reason:candidate.reason,kind:candidate.kind,cooldown_window:cooldownWindow,outcome,recorded_at:new Date(now).toISOString()};return state.escalations.push(record),record}function formatElapsed(ms){let totalSeconds=Math.max(0,Math.floor(ms/1e3)),hours=Math.floor(totalSeconds/3600),minutes=Math.floor(totalSeconds%3600/60),seconds=totalSeconds%60;return hours>0?`${hours}h${minutes}m`:minutes>0?`${minutes}m`:`${seconds}s`}function formatEscalationForTerminal(runId,candidate){let worker=candidate.worker_id?` worker=${candidate.worker_id}`:"",stateBit=candidate.state?` state=${candidate.state}`:"",liveBit=candidate.liveness?` liveness=${candidate.liveness}`:"",elapsed=` elapsed=${formatElapsed(candidate.elapsed_ms)}`;return`[supervisor] run=${runId}${worker} reason=${candidate.reason}${stateBit}${liveBit}${elapsed}`}var ESCALATION_KIND,init_supervisor_escalation=__esm({"src/conductor/supervisor-escalation.ts"(){"use strict";ESCALATION_KIND="escalation"}});function buildGateIdentity(gateName,configHash){let name=gateName.trim(),hash=typeof configHash=="string"?configHash.trim():"";return hash?`${name}@${hash.toLowerCase()}`:name}function makeMergeActionKey(repo,prNumber,headSha,gateIdentity){let r=normalizeRepoName(repo),pr=normalizePrNumber(prNumber),sha=normalizeSha(headSha),gate=(gateIdentity??"").trim();if(r===null||pr===null||sha===null||gate.length===0)throw new Error("invalid merge action key component");return`merge:${r}:${pr}:${sha}:${gate}`}var init_merge_identity=__esm({"src/conductor/merge-identity.ts"(){"use strict";init_git_ci_types()}});function isPlainObject2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function normalizeEventHeadSha(value){if(typeof value!="string")return null;let trimmed=value.trim();return/^[0-9a-f]{7,40}$/i.test(trimmed)?trimmed.toLowerCase():null}function getRawEventDetails(event){let details=event.data?.details;return isPlainObject2(details)?details:null}function parseHeadObservation(event){let details=getRawEventDetails(event);return{head_sha:details?normalizeEventHeadSha(details.head_sha):null}}function parseMergeLifecycle(event){let details=getRawEventDetails(event);return{action_key:details&&typeof details.action_key=="string"&&details.action_key.trim().length>0?details.action_key.trim():null}}function parseGateMet(event){let details=getRawEventDetails(event);if(!details)return{head_sha:null,repo:null,pr_number:null,gate_name:null,config_hash:null,required_checks:[]};let gateName=typeof details.gate_name=="string"&&details.gate_name.trim().length>0?details.gate_name.trim():null,configHash=typeof details.config_hash=="string"&&details.config_hash.trim().length>0?details.config_hash.trim():null,ciCheckStatus=isPlainObject2(details.ci_check_status)?details.ci_check_status:null,requiredChecks=(Array.isArray(details.required_checks)?details.required_checks:ciCheckStatus&&Array.isArray(ciCheckStatus.required_checks)?ciCheckStatus.required_checks:[]).filter(c=>typeof c=="string"&&c.trim().length>0);return{head_sha:normalizeSha(details.head_sha),repo:normalizeRepoName(details.repo),pr_number:normalizePrNumber(details.pr_number),gate_name:gateName,config_hash:configHash,required_checks:requiredChecks}}function parseSpecReview(event){let details=getRawEventDetails(event);return{head_sha:details?normalizeEventHeadSha(details.head_sha):null}}function parseEmpty(){return EMPTY_DETAILS}function getEventDetails(event,expectedType){if(event.type!==expectedType)return null;let parser=EVENT_PARSERS[expectedType];return parser(event)}function getMergeIdentity(event){if(event.type!=="gate.met")return null;let details=getEventDetails(event,"gate.met");if(details===null)return null;let{repo,pr_number:prNumber,head_sha:headSha,gate_name:gateName}=details;if(repo===null||prNumber===null||headSha===null||gateName===null)return null;let gateIdentity=buildGateIdentity(gateName,details.config_hash),actionKey=makeMergeActionKey(repo,prNumber,headSha,gateIdentity);return{repo,pr_number:prNumber,head_sha:headSha,gate_name:gateName,config_hash:details.config_hash,required_checks:details.required_checks,gate_identity:gateIdentity,action_key:actionKey,gate_event:{id:typeof event.id=="string"?event.id:void 0,seq:typeof event.seq=="number"?event.seq:void 0,time:typeof event.time=="string"?event.time:void 0}}}var EMPTY_DETAILS,EVENT_PARSERS,init_event_accessors=__esm({"src/conductor/event-accessors.ts"(){"use strict";init_git_ci_types();init_merge_identity();EMPTY_DETAILS=Object.freeze({});EVENT_PARSERS={"run.started":parseEmpty,"run.heartbeat":parseEmpty,"run.stopped":parseEmpty,"agent.notification":parseEmpty,"tool.intent":parseEmpty,"worktree.changed":parseEmpty,"git.commit_created":parseEmpty,"git.pr_opened":parseHeadObservation,"ci.passed":parseHeadObservation,"ci.failed":parseHeadObservation,"gate.met":parseGateMet,"supervisor.assessment":parseEmpty,"message.sent":parseEmpty,"message.delivered":parseEmpty,"message.acked":parseEmpty,"merge.dry_run":parseMergeLifecycle,"merge.attempted":parseMergeLifecycle,"merge.succeeded":parseHeadObservation,"merge.failed":parseMergeLifecycle,"merge.conflict":parseHeadObservation,"merge.pending_approval":parseMergeLifecycle,"review.passed":parseHeadObservation,"review.changes_requested":parseHeadObservation,"spec_review.passed":parseSpecReview,"spec_review.changes_requested":parseSpecReview,"parse.triggered":parseEmpty,"parse.succeeded":parseEmpty,"parse.failed":parseEmpty}}});import{createHash as createHash5}from"node:crypto";function extractMergeActionIdentityFromGateEvent(event){return getMergeIdentity(event)}function makeMergeEventId(eventType,actionKey){let h=createHash5("sha256").update(`${eventType}:${actionKey}`).digest("hex");return`${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20,32)}`}async function lookupMergeEventByActionKey(eventType,actionKey,deps){let db=await(deps.openDb??(()=>openReadonlyConductorDatabaseIfExists()))();if(!db)return!1;try{return db.prepare(`SELECT 1 FROM events
132
132
  WHERE type = ?
133
133
  AND json_extract(data_json, '$.details.action_key') = ?
134
134
  LIMIT 1`).get(eventType,actionKey)!==void 0}finally{db.close()}}async function hasTerminalMergeSucceeded(actionKey,deps={}){return lookupMergeEventByActionKey("merge.succeeded",actionKey,deps)}async function hasMergeDryRun(actionKey,deps={}){return lookupMergeEventByActionKey("merge.dry_run",actionKey,deps)}async function hasMergePendingApproval(actionKey,deps={}){return lookupMergeEventByActionKey("merge.pending_approval",actionKey,deps)}function isDuplicateConstraintError4(error){if(!error||typeof error!="object")return!1;let code=error.code;if(typeof code=="string"&&code.startsWith("SQLITE_CONSTRAINT"))return!0;let message=error.message;if(typeof message=="string"){let lowered=message.toLowerCase();if(lowered.includes("unique constraint")||lowered.includes("constraint failed"))return!0}return!1}async function emitMergeLedgerEventIfNew(input,deps={}){let emitEvent=deps.emitEvent??emitConductorEvent,eventId=makeMergeEventId(input.type,input.action_key),event={id:eventId,source:"conductor-supervisor",type:input.type,run_id:input.run_id??null,worker_id:input.worker_id??null,producer:"conductor-merge",observed_via:"supervisor",data:{summary:input.summary??`${input.type} ${input.action_key}`,status:input.status,reason:input.reason??void 0,details:input.details}};try{let result=await emitEvent(event);return{emitted:!0,event_id:eventId,event:result.event}}catch(error){if(isDuplicateConstraintError4(error))return{emitted:!1,reason:"duplicate"};throw error}}var init_merge_ledger=__esm({"src/conductor/merge-ledger.ts"(){"use strict";init_event_accessors();init_merge_identity();init_store()}});function buildMergeRequestFromGateEvent(identity){return{repo_name:identity.repo,pr_number:identity.pr_number,expected_head_sha:identity.head_sha,gate:{name:identity.gate_name,config_hash:identity.config_hash,required_checks:identity.required_checks},action_key:identity.action_key,gate_event:identity.gate_event}}function mapApiErrorReason(error){if(error instanceof ConductorBridgeApiError)switch(error.kind){case"timeout":return"api_timeout";case"network":return"api_network";case"unauthorized":return"api_unauthorized";case"server":case"http":return"api_unavailable";case"invalid-input":return"api_invalid"}return"api_network"}function resolveAttributionWorkerId(event,identity,resolve2){if(typeof event.worker_id=="string"&&event.worker_id.trim().length>0)return event.worker_id.trim();if(resolve2){let resolved=resolve2(event,identity);if(typeof resolved=="string"&&resolved.trim().length>0)return resolved.trim()}return null}async function processGateMetMerge(access,event,deps={}){let extract=deps.extractIdentity??extractMergeActionIdentityFromGateEvent,checkTerminal=deps.hasTerminal??hasTerminalMergeSucceeded,checkDryRun=deps.hasDryRun??hasMergeDryRun,checkPendingApproval=deps.hasPendingApproval??hasMergePendingApproval,mergeFn=deps.merge??mergePullRequestForGate,identity=extract(event);if(!identity)return{processed:!1,reason:"ineligible"};let actionKey=identity.action_key,attributionWorkerId=resolveAttributionWorkerId(event,identity,deps.resolveWorkerIdForGateEvent);if(await checkTerminal(actionKey))return{processed:!1,reason:"already_succeeded"};let baseDetails={action_key:actionKey,repo:identity.repo,pr_number:identity.pr_number,expected_head_sha:identity.head_sha,gate:identity.gate_identity},response;try{response=await mergeFn(access,buildMergeRequestFromGateEvent(identity))}catch(error){let reason=mapApiErrorReason(error);return await emitMergeLedgerEventIfNew({type:"merge.failed",action_key:actionKey,status:"failed",reason,details:baseDetails,run_id:event.run_id??null,worker_id:attributionWorkerId,summary:`merge.failed ${reason}`},{emitEvent:deps.emitEvent}),{processed:!0,outcome:"api_error",reason}}let emitted=[];for(let ledgerEvent of response.ledger_events??[]){if(ledgerEvent.type==="merge.dry_run"&&await checkDryRun(actionKey)){emitted.push({type:ledgerEvent.type,emitted:!1});continue}if(ledgerEvent.type==="merge.pending_approval"&&await checkPendingApproval(actionKey)){emitted.push({type:ledgerEvent.type,emitted:!1});continue}let result=await emitMergeLedgerEventIfNew({type:ledgerEvent.type,action_key:actionKey,status:ledgerEvent.status,reason:ledgerEvent.reason??null,details:ledgerEvent.details??baseDetails,run_id:event.run_id??null,worker_id:attributionWorkerId},{emitEvent:deps.emitEvent});emitted.push({type:ledgerEvent.type,emitted:result.emitted})}return{processed:!0,outcome:response.status,emitted}}var init_supervisor_merge=__esm({"src/conductor/supervisor-merge.ts"(){"use strict";init_bridge_api_client();init_merge_ledger()}});async function dispatchSupervisorNotification(epicRunId,candidate,assessment,idempotencyKey){let result=await resolveConductorBridgeApiAccess();if(!result.ok)return;let{access}=result,url=buildConductorJiraUrl(access.baseUrl,`/epic-runs/${encodeURIComponent(epicRunId)}/notifications`),payload={repo_name:access.repoName,idempotency_key:idempotencyKey,summary:{reason:candidate.reason,kind:candidate.kind,worker_id:candidate.worker_id??null,elapsed_ms:candidate.elapsed_ms,ticket_key:candidate.context?.ticket_key??null,classification:assessment.classification}},headers={"X-API-Key":access.apiKey,"Content-Type":"application/json"};try{await fetchConductorJsonPostWithTimeout(url,headers,JSON.stringify(payload),CONDUCTOR_FETCH_TIMEOUT_MS,fetch)}catch{}}var init_supervisor_notification=__esm({"src/conductor/supervisor-notification.ts"(){"use strict";init_bridge_api_client()}});var supervisor_runtime_exports={};__export(supervisor_runtime_exports,{runSupervisor:()=>runSupervisor});function deterministicAssessment(candidate){return{classification:"stuck",confidence:1,reason:candidate.reason}}function terminalStatus(state){return Object.values(state.workers).some(w=>w.state==="failed")?"failed":"complete"}async function processEscalations(state,config,deps){let now=deps.now(),candidates=findSupervisorEscalationCandidates(state,config,now);for(let candidate of candidates){let decision=shouldEmitEscalation(state,candidate,config,now);if(!decision.emit)continue;let idempotency={run_id:state.run_id,worker_id:candidate.worker_id,reason:candidate.reason,kind:candidate.kind,cooldown_window:decision.cooldown_window},idempotencyKey=makeSupervisorIdempotencyKey(idempotency),assessment=deterministicAssessment(candidate);state.latest_assessment=assessment;let outcome="skipped";try{outcome=(await deps.emitAssessment({run_id:state.run_id,worker_id:candidate.worker_id,assessment,details:{elapsed_ms:candidate.elapsed_ms,...candidate.context},idempotency})).emitted?"emitted":"duplicate"}catch{outcome="skipped"}if(recordEscalationResult(state,candidate,decision.cooldown_window,idempotencyKey,outcome,now),(outcome==="emitted"||outcome==="duplicate")&&candidate.worker_id)try{await sendSupervisorEscalationWorkerMessageIfNew(candidate,assessment,state,{sendMessage:deps.sendWorkerMessage})}catch{}if(outcome==="emitted"&&(deps.log(formatEscalationForTerminal(state.run_id,candidate)),deps.dispatchNotification))try{await deps.dispatchNotification(state.run_id,candidate,assessment,idempotencyKey)}catch{}}}async function runSupervisor(options,deps={}){let runId=typeof options.run_id=="string"?options.run_id.trim():"";if(runId.length===0)throw new ConductorValidationError("Supervisor requires exactly one non-empty --run-id.");let config=options.config??resolveSupervisorConfig(options.overrides??{}),now=deps.now??(()=>Date.now()),log=deps.log??(m=>process.stdout.write(`${m}
@@ -141,7 +141,7 @@ ${managedBlock}
141
141
  `,action:"created"};if(looksBinary(existing))return{ok:!1,content:existing,action:"skipped",warning:"existing hook appears binary/unsafe to merge; left untouched"};let startIdx=existing.indexOf(BRIDGE_CONDUCTOR_HOOK_START),endIdx=existing.indexOf(BRIDGE_CONDUCTOR_HOOK_END);if(startIdx!==-1&&endIdx!==-1&&endIdx>startIdx){let before=existing.slice(0,startIdx),after=existing.slice(endIdx+BRIDGE_CONDUCTOR_HOOK_END.length);return{ok:!0,content:`${before}${managedBlock}${after}`,action:"replaced"}}let separator=existing.endsWith(`
142
142
  `)?"":`
143
143
  `;return{ok:!0,content:`${existing}${separator}${managedBlock}
144
- `,action:"appended"}}function snippetForHook(name,conductorBin){return name==="post-commit"?buildPostCommitHookSnippet(conductorBin):buildReferenceTransactionHookSnippet(conductorBin)}function installConductorGitHooks(deps={}){let platform=deps.platform??process.platform,conductorBin=deps.conductorBin??defaultConductorBin(),{is_worktree,hooks_dir}=resolveGitHooksDirectory(deps);if(!is_worktree||hooks_dir===null)return{is_worktree:!1,hooks_dir:null,installed:[],warnings:["not a git worktree; git hooks were not installed (degraded optional capability)"]};let warnings=[];existsSync2(hooks_dir)||mkdirSync(hooks_dir,{recursive:!0});let installed=[];for(let name of MANAGED_HOOK_NAMES){let hookPath=resolve(hooks_dir,name),existing=null;if(existsSync2(hookPath))try{existing=readFileSync(hookPath,"utf-8")}catch{installed.push({name,path:hookPath,action:"skipped",warning:"could not read existing hook"}),warnings.push(`could not read existing ${name} hook; left untouched`);continue}let merge=mergeManagedHookSnippet(existing,snippetForHook(name,conductorBin));if(!merge.ok){installed.push({name,path:hookPath,action:"skipped",warning:merge.warning}),merge.warning&&warnings.push(`${name}: ${merge.warning}`);continue}if(writeFileSync(hookPath,merge.content,"utf-8"),platform!=="win32")try{chmodSync(hookPath,493)}catch{warnings.push(`could not mark ${name} executable`)}installed.push({name,path:hookPath,action:merge.action})}return{is_worktree:!0,hooks_dir,installed,warnings}}function inspectConductorGitHooks(deps={}){let platform=deps.platform??process.platform,{is_worktree,hooks_dir}=resolveGitHooksDirectory(deps);if(!is_worktree||hooks_dir===null)return{is_worktree:!1,hooks_dir:null,hooks:[],warnings:["not a git worktree; conductor git hooks are unavailable (degraded optional capability)"],degraded:!0};let warnings=[],hooks=[];for(let name of MANAGED_HOOK_NAMES){let hookPath=resolve(hooks_dir,name),exists=existsSync2(hookPath),executable=!1,managedPresent=!1;if(exists){try{let mode=statSync(hookPath).mode;executable=platform==="win32"?!0:(mode&73)!==0}catch{}try{managedPresent=readFileSync(hookPath,"utf-8").includes(BRIDGE_CONDUCTOR_HOOK_START)}catch{}}else warnings.push(`${name} hook not installed (degraded optional capability)`);hooks.push({name,path:hookPath,exists,executable,managed_block_present:managedPresent})}let degraded=hooks.some(h=>!h.exists||!h.managed_block_present);return{is_worktree:!0,hooks_dir,hooks,warnings,degraded}}init_file_scope_guard();init_git_ci_types();init_git_inspection();init_producer_ledger();var COMMITTED_REF_PHASE="committed";function buildCommitCreatedEventInput(context,metadata){let details={repo:context.repo,branch:context.branch,worktree_path:context.worktree_path,commit_sha:metadata.sha,parent_shas:metadata.parents,author:{name:metadata.author_name,email:metadata.author_email},committer:{name:metadata.committer_name,email:metadata.committer_email},co_authors:metadata.co_authors,authored_at:metadata.authored_at,committed_at:metadata.committed_at,subject:metadata.subject,attribution_source:metadata.attribution_source};return{source:"git",type:"git.commit_created",subject:context.repo,producer:GIT_HOOK_PRODUCER,observed_via:"git-hook:post-commit",data:{summary:`Commit ${metadata.sha??"(unknown)"} on ${context.branch??"(detached)"}`,status:"created",details}}}function buildWorktreeChangedEventInput(context,updates,phase){let updatesHash=stableJsonHash({phase,updates}),details={repo:context.repo,branch:context.branch,worktree_path:context.worktree_path,transaction_phase:phase,ref_updates:updates,updates_hash:updatesHash};return{source:"git",type:"worktree.changed",subject:context.repo,producer:GIT_HOOK_PRODUCER,observed_via:"git-hook:reference-transaction",data:{summary:`${updates.length} ref update(s) on ${context.repo}`,status:"changed",details}}}async function runPostCommitHookProducer(deps={}){let getContext=deps.getContext??getGitWorktreeContext,readMetadata=deps.readMetadata??readHeadCommitMetadata,emitIfNew=deps.emitIfNew??emitConductorEventIfNew;try{let context=getContext({cwd:deps.cwd,env:deps.env}),metadata=readMetadata({cwd:deps.cwd});if(!metadata||metadata.sha===null)return{ok:!0,emitted:!1,reason:"no-head-commit"};let input=buildCommitCreatedEventInput(context,metadata),decision=await emitIfNew(input,{event_type:"git.commit_created",repo:context.repo,commit_sha:metadata.sha});return{ok:!0,emitted:decision.emitted,reason:decision.reason}}catch{return{ok:!0,emitted:!1,reason:"skipped"}}}async function runReferenceTransactionHookProducer(args,deps={}){let getContext=deps.getContext??getGitWorktreeContext,parseUpdates=deps.parseUpdates??parseReferenceTransactionUpdates,emitIfNew=deps.emitIfNew??emitConductorEventIfNew;try{if(args.phase!==COMMITTED_REF_PHASE)return{ok:!0,emitted:!1,reason:"non-committed-phase"};let updates=parseUpdates(args.stdin);if(updates.length===0)return{ok:!0,emitted:!1,reason:"no-updates"};let context=getContext({cwd:deps.cwd,env:deps.env}),input=buildWorktreeChangedEventInput(context,updates,args.phase),refUpdatesHash=stableJsonHash({phase:args.phase,updates}),decision=await emitIfNew(input,{event_type:"worktree.changed",repo:context.repo,ref_updates_hash:refUpdatesHash});return{ok:!0,emitted:decision.emitted,reason:decision.reason}}catch{return{ok:!0,emitted:!1,reason:"skipped"}}}init_store();import{spawnSync as spawnSync2}from"node:child_process";import{existsSync as existsSync3,readFileSync as readFileSync2}from"node:fs";init_mcp_server_invocation();function skippedDenyEnforcementResult(){return{enforced:!1,layer:"none",degraded:!0,status:"skip",detail:"deny-enforcement preflight skipped via --no-deny-probe (no agent spawned)",warnings:["Deny-enforcement preflight was SKIPPED (--no-deny-probe): enforcement is UNVERIFIED on this host. Do not treat this report as evidence the deny layer works."]}}async function defaultReadPackageJson(){let packageRoot=resolvePackageRootFromModuleUrl(import.meta.url);if(!packageRoot)throw new Error("unable to resolve package root for package.json");return readFileSync2(`${packageRoot}/package.json`,"utf8")}function readExpectedNodeEngine(packageJsonText){try{let node=JSON.parse(packageJsonText).engines?.node;return typeof node=="string"?node:null}catch{return null}}async function inspectNativeLedger(nativeLoad,deps={}){let warnings=[],engines_node=null;try{let readPkg=deps.readPackageJson??defaultReadPackageJson;engines_node=readExpectedNodeEngine(await readPkg())}catch{engines_node=null}let invocation=deps.resolveMcpInvocation?deps.resolveMcpInvocation():resolveMcpShimInvocationForRuntime({moduleUrl:import.meta.url,nodeExecutable:"node",argv1:process.argv[1],fileExists:existsSync3}),mcp_shim_node=invocation.form==="absolute-build-path"?invocation.nodeExecutable:null,binding_loads=nativeLoad.loads,failure_kind=nativeLoad.failure_kind;nativeLoad.degraded&&nativeLoad.warning&&warnings.push(nativeLoad.warning),invocation.form!=="absolute-build-path"&&warnings.push("Worker MCP registration would use the npm-channel fallback (no resolvable on-disk build entry); registration reliability depends on the package being published."),engines_node===null&&warnings.push("Could not read package.json engines.node; expected Node version is unknown.");let degraded=nativeLoad.degraded||invocation.form!=="absolute-build-path"||engines_node===null;return{cli_node_version:process.version,engines_node,mcp_shim_node,mcp_registration_form:invocation.form,module:nativeLoad.module,node_modules_abi:nativeLoad.node_modules_abi,binding_loads,failure_kind,degraded,warnings}}async function inspectEpicTickSchedule(deps,orchestrateListOverride){try{let schedRun=orchestrateListOverride?null:await Promise.resolve().then(()=>(init_schedule_run(),schedule_run_exports)),doList=orchestrateListOverride||(d=>schedRun.orchestrateScheduleList({json:!1},d)),resolvedDeps=orchestrateListOverride?deps:deps??schedRun.createDefaultScheduleRunDeps(),commandLabel=schedRun?schedRun.scheduleCommandLabel:m2=>m2.command??(m2.idea_file?"full-automation":"(unknown)"),runStatus=schedRun?schedRun.latestRunStatus:m2=>{let h=m2.run_history;return h&&h.length>0?h[h.length-1].status:""},entry=(await doList(resolvedDeps)).entries.find(e=>commandLabel(e.metadata)==="epic-tick");if(!entry)return{registered:!1,backend:null,next_fire_iso:null,latest_run_status:null,degraded:!1,warnings:[]};let m=entry.metadata,latest=runStatus(m);return{registered:!0,backend:m.backend??null,next_fire_iso:m.run_at_iso??null,latest_run_status:latest||null,degraded:!0,warnings:[`An epic-tick schedule is registered, but the v1 \`conductor epic-tick\` path is frozen (EPIC_TICK_V1_FROZEN) \u2014 it advances nothing. Cancel it: \`npx -y @bridge_gpt/mcp-server schedule-run cancel --id ${entry.metadata.id??"<id>"}\`. Epic Conductor v2 reconciles server-side; run jobs locally with \`npx -y @bridge_gpt/mcp-server executor --repo <name>\`.`]}}catch(err){return{registered:!1,backend:null,next_fire_iso:null,latest_run_status:null,degraded:!0,warnings:[`Failed to inspect epic-tick schedule: ${err instanceof Error?err.message:String(err)}`]}}}function inspectMcpProfile(env,epicTick){let resolved_profile=env.BRIDGE_MCP_PROFILE||"core",conductor_context_detected=env.BAPI_CONDUCTOR_ENABLED==="1"||env.BAPI_CONDUCTOR_ENABLED==="true"||epicTick.registered,degraded=conductor_context_detected&&resolved_profile!=="conductor",warnings=[];return degraded&&warnings.push(`BRIDGE_MCP_PROFILE is "${resolved_profile}" but a conductor context is active. Expected "conductor" \u2014 conductor/event/supervisor tools may be missing. Ensure the spawner injects BRIDGE_MCP_PROFILE=conductor into the worker shell environment.`),{resolved_profile,conductor_context_detected,degraded,warnings}}function inspectLocalMerge(runCommand){let run=runCommand??((cmd,args)=>{try{return{status:spawnSync2(cmd,args,{encoding:"utf8",timeout:1e4,env:{...process.env,GH_PROMPT_DISABLED:"1"}}).status}}catch{return{status:null}}}),gh_available=!1,gh_authed=!1;try{gh_available=run("gh",["--version"]).status===0}catch{gh_available=!1}if(gh_available)try{gh_authed=run("gh",["auth","status"]).status===0}catch{gh_authed=!1}let warnings=[];return gh_available?gh_authed||warnings.push("`gh` is installed but not authenticated (`gh auth status` failed). Run `gh auth login` to grant the conductor merge permission; otherwise local merge will emit merge.failed/skip."):warnings.push("`gh` is not installed or not on PATH. Local merge (policy_json.local_merge.enabled) cannot run; install the GitHub CLI to enable conductor-driven merges."),{gh_available,gh_authed,degraded:!gh_available||!gh_authed,warnings}}async function buildConductorDoctorReport(deps={}){let doctorLedger=deps.doctorLedger??doctorConductorLedger,inspectHooks=deps.inspectHooks??inspectConductorGitHooks,epicTick=await inspectEpicTickSchedule(deps.scheduleDeps,deps.orchestrateList),mcp_profile=inspectMcpProfile(deps.env??process.env,epicTick),ledger=await doctorLedger(),native_ledger=await inspectNativeLedger(ledger.native_load,deps),deny_enforcement=deps.skipDenyProbe?skippedDenyEnforcementResult():await inspectDenyEnforcementSafe(deps.inspectDenyEnforcement);return{ledger,git_hooks:inspectHooks(deps.hooksDeps),epic_tick:epicTick,mcp_profile,local_merge:inspectLocalMerge(deps.runCommand),native_ledger,deny_enforcement}}async function inspectDenyEnforcementSafe(inspect){try{let run=inspect;return run||(run=(await Promise.resolve().then(()=>(init_deny_enforcement_preflight(),deny_enforcement_preflight_exports))).runDenyEnforcementPreflight),await run()}catch(err){return{enforced:!1,layer:"none",degraded:!0,warnings:[`Deny-layer enforcement inspection failed: ${err instanceof Error?err.message:String(err)}`,"The executor claim loop MUST refuse to claim jobs until the deny layer is enforced."]}}}function formatConductorDoctorReport(report){let{ledger,git_hooks,epic_tick,mcp_profile,local_merge,native_ledger,deny_enforcement}=report,lines=["Conductor ledger doctor","\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",`path: ${ledger.path}`,`directory exists: ${ledger.directory_exists}`,`database exists: ${ledger.database_exists}`,`directory mode: ${ledger.directory_mode??"n/a"} (ok: ${ledger.directory_permissions_ok})`,`database mode: ${ledger.database_mode??"n/a"} (ok: ${ledger.database_permissions_ok})`,`schema present: ${ledger.schema_present}`,`journal mode: ${ledger.journal_mode??"n/a"}`,`user_version: ${ledger.user_version??"n/a"}`,`event count: ${ledger.event_count??"n/a"}`,`max seq: ${ledger.max_seq??"n/a"}`,`busy_timeout_ms: ${ledger.retention.busy_timeout_ms}`,`retention_days: ${ledger.retention.retention_days}`,`retention_max_rows: ${ledger.retention.retention_max_rows}`,`message_cooldown_ms: ${ledger.message_relay.message_cooldown_ms}`,`degraded (network FS): ${ledger.degraded}`];if(ledger.warnings.length>0){lines.push("warnings:");for(let w of ledger.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("git hooks (optional, local)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),lines.push(`is git worktree: ${git_hooks.is_worktree}`),lines.push(`hooks dir: ${git_hooks.hooks_dir??"n/a"}`),lines.push(`degraded: ${git_hooks.degraded}`);for(let hook of git_hooks.hooks)lines.push(` ${hook.name}: exists=${hook.exists} executable=${hook.executable} managed=${hook.managed_block_present}`);if(git_hooks.warnings.length>0){lines.push("git hook warnings:");for(let w of git_hooks.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Epic Supervisor Schedule (v1 epic-tick \u2014 frozen)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let registeredTag=epic_tick.registered?"[WARNING] registered \u2014 dead timer, remove it":"[SUCCESS] none registered (v1 is frozen)";if(lines.push(`epic-tick schedule: ${registeredTag}`),epic_tick.registered&&(lines.push(`backend: ${epic_tick.backend??"n/a"}`),lines.push(`next fire: ${epic_tick.next_fire_iso??"n/a"}`),lines.push(`latest run status: ${epic_tick.latest_run_status??"n/a"}`)),lines.push(`degraded: ${epic_tick.degraded}`),epic_tick.warnings.length>0){lines.push("epic-tick warnings:");for(let w of epic_tick.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Epic Conductor v2 reconciles epics server-side \u2014 nothing to schedule"),lines.push("locally. To execute claimed jobs on this machine, run:"),lines.push(" npx -y @bridge_gpt/mcp-server executor --repo <name>"),lines.push(""),lines.push("MCP Profile (optional, local)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let profileTag=mcp_profile.degraded?"[WARNING] degraded":"[OK]";if(lines.push(`resolved profile: ${mcp_profile.resolved_profile} ${profileTag}`),lines.push(`conductor context: ${mcp_profile.conductor_context_detected}`),lines.push(`degraded: ${mcp_profile.degraded}`),mcp_profile.warnings.length>0){lines.push("mcp profile warnings:");for(let w of mcp_profile.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Local merge capability (optional, opt-in)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let ghTag=local_merge.gh_available?local_merge.gh_authed?"[OK]":"[WARNING] not authenticated":"[WARNING] not installed";if(lines.push(`gh available: ${local_merge.gh_available} ${ghTag}`),lines.push(`gh authenticated: ${local_merge.gh_authed}`),lines.push(`degraded: ${local_merge.degraded}`),local_merge.warnings.length>0){lines.push("local merge warnings:");for(let w of local_merge.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Native ledger module (required for conductor coordination)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let nativeTag=native_ledger.binding_loads&&!native_ledger.degraded?"[OK]":"[WARNING] degraded";if(lines.push(`binding loads: ${native_ledger.binding_loads} ${nativeTag}`),lines.push(`module: ${native_ledger.module}`),lines.push(`CLI Node: ${native_ledger.cli_node_version}`),lines.push(`engines.node: ${native_ledger.engines_node??"n/a"}`),lines.push(`MCP shim Node: ${native_ledger.mcp_shim_node??"n/a"}`),lines.push(`NODE_MODULE_VERSION: ${native_ledger.node_modules_abi}`),lines.push(`registration form: ${native_ledger.mcp_registration_form}`),lines.push(`failure kind: ${native_ledger.failure_kind}`),lines.push(`degraded: ${native_ledger.degraded}`),native_ledger.warnings.length>0){lines.push("native ledger warnings:");for(let w of native_ledger.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Deny-layer enforcement preflight (required for executor claim)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let denyTag=deny_enforcement.status==="skip"?"[SKIPPED] probe not run (--no-deny-probe) \u2014 enforcement unverified":deny_enforcement.enforced?deny_enforcement.degraded?"[WARNING] degraded \u2014 relying on PreToolUse fallback":"[OK]":"[FATAL] deny not enforced \u2014 executor must refuse to claim jobs";if(lines.push(`enforced: ${deny_enforcement.enforced} ${denyTag}`),lines.push(`layer: ${deny_enforcement.layer}`),lines.push(`degraded: ${deny_enforcement.degraded}`),deny_enforcement.warnings.length>0){lines.push("deny enforcement warnings:");for(let w of deny_enforcement.warnings)lines.push(` - ${w}`)}return lines.join(`
144
+ `,action:"appended"}}function snippetForHook(name,conductorBin){return name==="post-commit"?buildPostCommitHookSnippet(conductorBin):buildReferenceTransactionHookSnippet(conductorBin)}function installConductorGitHooks(deps={}){let platform=deps.platform??process.platform,conductorBin=deps.conductorBin??defaultConductorBin(),{is_worktree,hooks_dir}=resolveGitHooksDirectory(deps);if(!is_worktree||hooks_dir===null)return{is_worktree:!1,hooks_dir:null,installed:[],warnings:["not a git worktree; git hooks were not installed (degraded optional capability)"]};let warnings=[];existsSync2(hooks_dir)||mkdirSync(hooks_dir,{recursive:!0});let installed=[];for(let name of MANAGED_HOOK_NAMES){let hookPath=resolve(hooks_dir,name),existing=null;if(existsSync2(hookPath))try{existing=readFileSync(hookPath,"utf-8")}catch{installed.push({name,path:hookPath,action:"skipped",warning:"could not read existing hook"}),warnings.push(`could not read existing ${name} hook; left untouched`);continue}let merge=mergeManagedHookSnippet(existing,snippetForHook(name,conductorBin));if(!merge.ok){installed.push({name,path:hookPath,action:"skipped",warning:merge.warning}),merge.warning&&warnings.push(`${name}: ${merge.warning}`);continue}if(writeFileSync(hookPath,merge.content,"utf-8"),platform!=="win32")try{chmodSync(hookPath,493)}catch{warnings.push(`could not mark ${name} executable`)}installed.push({name,path:hookPath,action:merge.action})}return{is_worktree:!0,hooks_dir,installed,warnings}}function inspectConductorGitHooks(deps={}){let platform=deps.platform??process.platform,{is_worktree,hooks_dir}=resolveGitHooksDirectory(deps);if(!is_worktree||hooks_dir===null)return{is_worktree:!1,hooks_dir:null,hooks:[],warnings:["not a git worktree; conductor git hooks are unavailable (degraded optional capability)"],degraded:!0};let warnings=[],hooks=[];for(let name of MANAGED_HOOK_NAMES){let hookPath=resolve(hooks_dir,name),exists=existsSync2(hookPath),executable=!1,managedPresent=!1;if(exists){try{let mode=statSync(hookPath).mode;executable=platform==="win32"?!0:(mode&73)!==0}catch{}try{managedPresent=readFileSync(hookPath,"utf-8").includes(BRIDGE_CONDUCTOR_HOOK_START)}catch{}}else warnings.push(`${name} hook not installed (degraded optional capability)`);hooks.push({name,path:hookPath,exists,executable,managed_block_present:managedPresent})}let degraded=hooks.some(h=>!h.exists||!h.managed_block_present);return{is_worktree:!0,hooks_dir,hooks,warnings,degraded}}init_file_scope_guard();init_git_ci_types();init_git_inspection();init_producer_ledger();var COMMITTED_REF_PHASE="committed";function buildCommitCreatedEventInput(context,metadata){let details={repo:context.repo,branch:context.branch,worktree_path:context.worktree_path,commit_sha:metadata.sha,parent_shas:metadata.parents,author:{name:metadata.author_name,email:metadata.author_email},committer:{name:metadata.committer_name,email:metadata.committer_email},co_authors:metadata.co_authors,authored_at:metadata.authored_at,committed_at:metadata.committed_at,subject:metadata.subject,attribution_source:metadata.attribution_source};return{source:"git",type:"git.commit_created",subject:context.repo,producer:GIT_HOOK_PRODUCER,observed_via:"git-hook:post-commit",data:{summary:`Commit ${metadata.sha??"(unknown)"} on ${context.branch??"(detached)"}`,status:"created",details}}}function buildWorktreeChangedEventInput(context,updates,phase){let updatesHash=stableJsonHash({phase,updates}),details={repo:context.repo,branch:context.branch,worktree_path:context.worktree_path,transaction_phase:phase,ref_updates:updates,updates_hash:updatesHash};return{source:"git",type:"worktree.changed",subject:context.repo,producer:GIT_HOOK_PRODUCER,observed_via:"git-hook:reference-transaction",data:{summary:`${updates.length} ref update(s) on ${context.repo}`,status:"changed",details}}}async function runPostCommitHookProducer(deps={}){let getContext=deps.getContext??getGitWorktreeContext,readMetadata=deps.readMetadata??readHeadCommitMetadata,emitIfNew=deps.emitIfNew??emitConductorEventIfNew;try{let context=getContext({cwd:deps.cwd,env:deps.env}),metadata=readMetadata({cwd:deps.cwd});if(!metadata||metadata.sha===null)return{ok:!0,emitted:!1,reason:"no-head-commit"};let input=buildCommitCreatedEventInput(context,metadata),decision=await emitIfNew(input,{event_type:"git.commit_created",repo:context.repo,commit_sha:metadata.sha});return{ok:!0,emitted:decision.emitted,reason:decision.reason}}catch{return{ok:!0,emitted:!1,reason:"skipped"}}}async function runReferenceTransactionHookProducer(args,deps={}){let getContext=deps.getContext??getGitWorktreeContext,parseUpdates=deps.parseUpdates??parseReferenceTransactionUpdates,emitIfNew=deps.emitIfNew??emitConductorEventIfNew;try{if(args.phase!==COMMITTED_REF_PHASE)return{ok:!0,emitted:!1,reason:"non-committed-phase"};let updates=parseUpdates(args.stdin);if(updates.length===0)return{ok:!0,emitted:!1,reason:"no-updates"};let context=getContext({cwd:deps.cwd,env:deps.env}),input=buildWorktreeChangedEventInput(context,updates,args.phase),refUpdatesHash=stableJsonHash({phase:args.phase,updates}),decision=await emitIfNew(input,{event_type:"worktree.changed",repo:context.repo,ref_updates_hash:refUpdatesHash});return{ok:!0,emitted:decision.emitted,reason:decision.reason}}catch{return{ok:!0,emitted:!1,reason:"skipped"}}}init_store();import{spawnSync as spawnSync2}from"node:child_process";import{existsSync as existsSync3,readFileSync as readFileSync2}from"node:fs";import{readFile as readFileAsync}from"node:fs/promises";import os3 from"node:os";import path3 from"path";async function detectClaudeLogin(deps){let raw;try{raw=await deps.readFile(path3.join(deps.homedir(),".claude.json"))}catch{return{detected:!1}}let parsed;try{parsed=JSON.parse(raw)}catch{return{detected:!1}}if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return{detected:!1};let oauthAccount=parsed.oauthAccount;return oauthAccount!==null&&typeof oauthAccount=="object"&&!Array.isArray(oauthAccount)?{detected:!0}:{detected:!1}}function formatClaudeLoginAdvisory(result){return result.detected?"Claude login: detected (~/.claude.json has an OAuth account). This is advisory only \u2014 it does not guarantee the next worker spawn will authenticate.":"Claude login: not detected. Run `claude login` on this host, or, on a headless host, export CLAUDE_CODE_OAUTH_TOKEN before starting the executor."}init_mcp_server_invocation();function skippedDenyEnforcementResult(){return{enforced:!1,layer:"none",degraded:!0,status:"skip",detail:"deny-enforcement preflight skipped via --no-deny-probe (no agent spawned)",warnings:["Deny-enforcement preflight was SKIPPED (--no-deny-probe): enforcement is UNVERIFIED on this host. Do not treat this report as evidence the deny layer works."]}}async function defaultReadPackageJson(){let packageRoot=resolvePackageRootFromModuleUrl(import.meta.url);if(!packageRoot)throw new Error("unable to resolve package root for package.json");return readFileSync2(`${packageRoot}/package.json`,"utf8")}function readExpectedNodeEngine(packageJsonText){try{let node=JSON.parse(packageJsonText).engines?.node;return typeof node=="string"?node:null}catch{return null}}async function inspectNativeLedger(nativeLoad,deps={}){let warnings=[],engines_node=null;try{let readPkg=deps.readPackageJson??defaultReadPackageJson;engines_node=readExpectedNodeEngine(await readPkg())}catch{engines_node=null}let invocation=deps.resolveMcpInvocation?deps.resolveMcpInvocation():resolveMcpShimInvocationForRuntime({moduleUrl:import.meta.url,nodeExecutable:"node",argv1:process.argv[1],fileExists:existsSync3}),mcp_shim_node=invocation.form==="absolute-build-path"?invocation.nodeExecutable:null,binding_loads=nativeLoad.loads,failure_kind=nativeLoad.failure_kind;nativeLoad.degraded&&nativeLoad.warning&&warnings.push(nativeLoad.warning),invocation.form!=="absolute-build-path"&&warnings.push("Worker MCP registration would use the npm-channel fallback (no resolvable on-disk build entry); registration reliability depends on the package being published."),engines_node===null&&warnings.push("Could not read package.json engines.node; expected Node version is unknown.");let degraded=nativeLoad.degraded||invocation.form!=="absolute-build-path"||engines_node===null;return{cli_node_version:process.version,engines_node,mcp_shim_node,mcp_registration_form:invocation.form,module:nativeLoad.module,node_modules_abi:nativeLoad.node_modules_abi,binding_loads,failure_kind,degraded,warnings}}async function inspectEpicTickSchedule(deps,orchestrateListOverride){try{let schedRun=orchestrateListOverride?null:await Promise.resolve().then(()=>(init_schedule_run(),schedule_run_exports)),doList=orchestrateListOverride||(d=>schedRun.orchestrateScheduleList({json:!1},d)),resolvedDeps=orchestrateListOverride?deps:deps??schedRun.createDefaultScheduleRunDeps(),commandLabel=schedRun?schedRun.scheduleCommandLabel:m2=>m2.command??(m2.idea_file?"full-automation":"(unknown)"),runStatus=schedRun?schedRun.latestRunStatus:m2=>{let h=m2.run_history;return h&&h.length>0?h[h.length-1].status:""},entry=(await doList(resolvedDeps)).entries.find(e=>commandLabel(e.metadata)==="epic-tick");if(!entry)return{registered:!1,backend:null,next_fire_iso:null,latest_run_status:null,degraded:!1,warnings:[]};let m=entry.metadata,latest=runStatus(m);return{registered:!0,backend:m.backend??null,next_fire_iso:m.run_at_iso??null,latest_run_status:latest||null,degraded:!0,warnings:[`An epic-tick schedule is registered, but the v1 \`conductor epic-tick\` path is frozen (EPIC_TICK_V1_FROZEN) \u2014 it advances nothing. Cancel it: \`npx -y @bridge_gpt/mcp-server schedule-run cancel --id ${entry.metadata.id??"<id>"}\`. Epic Conductor v2 reconciles server-side; run jobs locally with \`npx -y @bridge_gpt/mcp-server executor --repo <name>\`.`]}}catch(err){return{registered:!1,backend:null,next_fire_iso:null,latest_run_status:null,degraded:!0,warnings:[`Failed to inspect epic-tick schedule: ${err instanceof Error?err.message:String(err)}`]}}}function inspectMcpProfile(env,epicTick){let resolved_profile=env.BRIDGE_MCP_PROFILE||"core",conductor_context_detected=env.BAPI_CONDUCTOR_ENABLED==="1"||env.BAPI_CONDUCTOR_ENABLED==="true"||epicTick.registered,degraded=conductor_context_detected&&resolved_profile!=="conductor",warnings=[];return degraded&&warnings.push(`BRIDGE_MCP_PROFILE is "${resolved_profile}" but a conductor context is active. Expected "conductor" \u2014 conductor/event/supervisor tools may be missing. Ensure the spawner injects BRIDGE_MCP_PROFILE=conductor into the worker shell environment.`),{resolved_profile,conductor_context_detected,degraded,warnings}}function inspectLocalMerge(runCommand){let run=runCommand??((cmd,args)=>{try{return{status:spawnSync2(cmd,args,{encoding:"utf8",timeout:1e4,env:{...process.env,GH_PROMPT_DISABLED:"1"}}).status}}catch{return{status:null}}}),gh_available=!1,gh_authed=!1;try{gh_available=run("gh",["--version"]).status===0}catch{gh_available=!1}if(gh_available)try{gh_authed=run("gh",["auth","status"]).status===0}catch{gh_authed=!1}let warnings=[];return gh_available?gh_authed||warnings.push("`gh` is installed but not authenticated (`gh auth status` failed). Run `gh auth login` to grant the conductor merge permission; otherwise local merge will emit merge.failed/skip."):warnings.push("`gh` is not installed or not on PATH. Local merge (policy_json.local_merge.enabled) cannot run; install the GitHub CLI to enable conductor-driven merges."),{gh_available,gh_authed,degraded:!gh_available||!gh_authed,warnings}}async function buildConductorDoctorReport(deps={}){let doctorLedger=deps.doctorLedger??doctorConductorLedger,inspectHooks=deps.inspectHooks??inspectConductorGitHooks,epicTick=await inspectEpicTickSchedule(deps.scheduleDeps,deps.orchestrateList),mcp_profile=inspectMcpProfile(deps.env??process.env,epicTick),ledger=await doctorLedger(),native_ledger=await inspectNativeLedger(ledger.native_load,deps),deny_enforcement=deps.skipDenyProbe?skippedDenyEnforcementResult():await inspectDenyEnforcementSafe(deps.inspectDenyEnforcement),claude_login=await detectClaudeLogin({homedir:deps.claudeLoginDeps?.homedir??os3.homedir,readFile:deps.claudeLoginDeps?.readFile??(p=>readFileAsync(p,"utf-8"))});return{ledger,git_hooks:inspectHooks(deps.hooksDeps),epic_tick:epicTick,mcp_profile,local_merge:inspectLocalMerge(deps.runCommand),native_ledger,deny_enforcement,claude_login}}async function inspectDenyEnforcementSafe(inspect){try{let run=inspect;return run||(run=(await Promise.resolve().then(()=>(init_deny_enforcement_preflight(),deny_enforcement_preflight_exports))).runDenyEnforcementPreflight),await run()}catch(err){return{enforced:!1,layer:"none",degraded:!0,warnings:[`Deny-layer enforcement inspection failed: ${err instanceof Error?err.message:String(err)}`,"The executor claim loop MUST refuse to claim jobs until the deny layer is enforced."]}}}function formatConductorDoctorReport(report){let{ledger,git_hooks,epic_tick,mcp_profile,local_merge,native_ledger,deny_enforcement,claude_login}=report,lines=["Conductor ledger doctor","\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",`path: ${ledger.path}`,`directory exists: ${ledger.directory_exists}`,`database exists: ${ledger.database_exists}`,`directory mode: ${ledger.directory_mode??"n/a"} (ok: ${ledger.directory_permissions_ok})`,`database mode: ${ledger.database_mode??"n/a"} (ok: ${ledger.database_permissions_ok})`,`schema present: ${ledger.schema_present}`,`journal mode: ${ledger.journal_mode??"n/a"}`,`user_version: ${ledger.user_version??"n/a"}`,`event count: ${ledger.event_count??"n/a"}`,`max seq: ${ledger.max_seq??"n/a"}`,`busy_timeout_ms: ${ledger.retention.busy_timeout_ms}`,`retention_days: ${ledger.retention.retention_days}`,`retention_max_rows: ${ledger.retention.retention_max_rows}`,`message_cooldown_ms: ${ledger.message_relay.message_cooldown_ms}`,`degraded (network FS): ${ledger.degraded}`];if(ledger.warnings.length>0){lines.push("warnings:");for(let w of ledger.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("git hooks (optional, local)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),lines.push(`is git worktree: ${git_hooks.is_worktree}`),lines.push(`hooks dir: ${git_hooks.hooks_dir??"n/a"}`),lines.push(`degraded: ${git_hooks.degraded}`);for(let hook of git_hooks.hooks)lines.push(` ${hook.name}: exists=${hook.exists} executable=${hook.executable} managed=${hook.managed_block_present}`);if(git_hooks.warnings.length>0){lines.push("git hook warnings:");for(let w of git_hooks.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Epic Supervisor Schedule (v1 epic-tick \u2014 frozen)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let registeredTag=epic_tick.registered?"[WARNING] registered \u2014 dead timer, remove it":"[SUCCESS] none registered (v1 is frozen)";if(lines.push(`epic-tick schedule: ${registeredTag}`),epic_tick.registered&&(lines.push(`backend: ${epic_tick.backend??"n/a"}`),lines.push(`next fire: ${epic_tick.next_fire_iso??"n/a"}`),lines.push(`latest run status: ${epic_tick.latest_run_status??"n/a"}`)),lines.push(`degraded: ${epic_tick.degraded}`),epic_tick.warnings.length>0){lines.push("epic-tick warnings:");for(let w of epic_tick.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Epic Conductor v2 reconciles epics server-side \u2014 nothing to schedule"),lines.push("locally. To execute claimed jobs on this machine, run:"),lines.push(" npx -y @bridge_gpt/mcp-server executor --repo <name>"),lines.push(""),lines.push("MCP Profile (optional, local)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let profileTag=mcp_profile.degraded?"[WARNING] degraded":"[OK]";if(lines.push(`resolved profile: ${mcp_profile.resolved_profile} ${profileTag}`),lines.push(`conductor context: ${mcp_profile.conductor_context_detected}`),lines.push(`degraded: ${mcp_profile.degraded}`),mcp_profile.warnings.length>0){lines.push("mcp profile warnings:");for(let w of mcp_profile.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Local merge capability (optional, opt-in)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let ghTag=local_merge.gh_available?local_merge.gh_authed?"[OK]":"[WARNING] not authenticated":"[WARNING] not installed";if(lines.push(`gh available: ${local_merge.gh_available} ${ghTag}`),lines.push(`gh authenticated: ${local_merge.gh_authed}`),lines.push(`degraded: ${local_merge.degraded}`),local_merge.warnings.length>0){lines.push("local merge warnings:");for(let w of local_merge.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Native ledger module (required for conductor coordination)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let nativeTag=native_ledger.binding_loads&&!native_ledger.degraded?"[OK]":"[WARNING] degraded";if(lines.push(`binding loads: ${native_ledger.binding_loads} ${nativeTag}`),lines.push(`module: ${native_ledger.module}`),lines.push(`CLI Node: ${native_ledger.cli_node_version}`),lines.push(`engines.node: ${native_ledger.engines_node??"n/a"}`),lines.push(`MCP shim Node: ${native_ledger.mcp_shim_node??"n/a"}`),lines.push(`NODE_MODULE_VERSION: ${native_ledger.node_modules_abi}`),lines.push(`registration form: ${native_ledger.mcp_registration_form}`),lines.push(`failure kind: ${native_ledger.failure_kind}`),lines.push(`degraded: ${native_ledger.degraded}`),native_ledger.warnings.length>0){lines.push("native ledger warnings:");for(let w of native_ledger.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Deny-layer enforcement preflight (required for executor claim)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let denyTag=deny_enforcement.status==="skip"?"[SKIPPED] probe not run (--no-deny-probe) \u2014 enforcement unverified":deny_enforcement.enforced?deny_enforcement.degraded?"[WARNING] degraded \u2014 relying on PreToolUse fallback":"[OK]":"[FATAL] deny not enforced \u2014 executor must refuse to claim jobs";if(lines.push(`enforced: ${deny_enforcement.enforced} ${denyTag}`),lines.push(`layer: ${deny_enforcement.layer}`),lines.push(`degraded: ${deny_enforcement.degraded}`),deny_enforcement.warnings.length>0){lines.push("deny enforcement warnings:");for(let w of deny_enforcement.warnings)lines.push(` - ${w}`)}return lines.push(""),lines.push(formatClaudeLoginAdvisory(claude_login)),lines.join(`
145
145
  `)}init_supervisor_config();function formatConductorErrorLine(envelope){if(envelope.error==="LEDGER_NATIVE_MODULE_LOAD_FAILED"&&envelope.details){let d=envelope.details;return`${envelope.message} details: module=${d.module} node_version=${d.node_version} node_modules_abi=${d.node_modules_abi}`}return envelope.message}function getConductorUsage(){return["Usage: conductor <command> [options]","","Local append-only event ledger for multi-agent coordination.","Talks ONLY to the local SQLite store (~/.config/bridge/events.db); no Bridge API calls.","","Commands:"," emit-event Append one semantic event to the ledger"," supervise --run-id <id> Run the foreground, run-scoped supervisor loop"," epic-tick Run one stateless reconciliation pass for an Epic"," epic-status Print read-only health summary of an Epic Run"," send-message Enqueue ONE typed supervisor->worker relay message (idempotent)"," check-messages Read + ACK pending relay messages for a worker (no redelivery)"," doctor Read-only health/diagnostics report (ledger + git hooks)"," purge Delete ALL ledger rows (events, messages, supervisor_projection)"," install-git-hooks Install local, opportunistic, non-blocking git hooks"," git-hook post-commit Run the post-commit producer (invoked by the installed hook)"," git-hook reference-transaction --phase <p> --stdin-file <f>"," Run the reference-transaction producer (invoked by the hook)"," file-scope-guard Warn-only: compare the branch diff against the declared"," touched-file set (always exits 0; never blocks a PR)","","supervise options:"," --run-id <id> Run/session identifier to supervise (required)"," --wake-interval-ms <n> Deterministic event-poll cadence (clamped 30000..60000)"," --global-timeout-ms <n> Total wall-clock ceiling for the run"," --escalation-cooldown-ms <n> Min gap between escalations for the same worker+reason","","install-git-hooks notes:"," Hooks are LOCAL, unversioned, opportunistic, and bypassable. Missing hooks are a"," degraded optional capability and never prevent PR/CI gate evaluation.","","emit-event options:"," --type <t> Semantic event type (required). One of:",` ${SEMANTIC_EVENT_TYPES.join(", ")}`," --source <s> Logical producer (required)"," --subject <s> Subject the event is about (e.g. ticket key)"," --run-id <s> Run/session identifier"," --worker-id <s> Worker/agent identifier"," --producer <s> Finer-grained producer identity"," --schema-version <n> Event schema version (default 1)"," --time <iso> ISO-8601 event time (default now)"," --confidence <0..1> Confidence score"," --observed-via <s> Channel the event was observed through"," --data-json <json> Normalized data object (allowlisted top-level keys)"," --data-json-stdin Read the complete normalized data object as JSON from stdin"," (mutually exclusive with --data-json; keeps raw payloads and"," secrets out of the process argument list)"," --raw-json <json> Tool-native object; nested under data.raw"," --payload-ref <ref> Reference for large external payloads (-> data.payload_ref)"," --json Print compact JSON result","","send-message options:"," --run-id <s> Run/session identifier (required)"," --worker-id <s> Target worker identifier (required)"," --type <s> Typed message kind, e.g. supervisor.worker_stalled (required)"," --cause-seq <n> Idempotency cause sequence, non-negative integer (required)"," --payload-json <json> Compact payload object (allowlisted top-level keys)"," --payload-json-stdin Read the payload object as JSON from stdin"," (mutually exclusive with --payload-json)"," --available-at <iso> ISO-8601 time the message becomes available (default now)"," --cooldown-ms <n> Per-call cooldown override in ms"," --json Print compact JSON result"," Note: a duplicate idempotency key or a same-type message inside the cooldown"," window does NOT enqueue a second message.","","check-messages options:"," --run-id <s> Run/session identifier (required)"," --worker-id <s> Worker identifier (required)"," --limit <n> Max messages to deliver/ack (default 10, max 100)"," --json Print compact JSON result"," Note: returned messages are ACKNOWLEDGED by this call and are not redelivered.","","doctor / purge options:"," --json Print machine-readable JSON"," --no-deny-probe (doctor only) Skip the deny-enforcement preflight \u2014 no headless"," agent is spawned; the deny_enforcement section reports an"," explicit skipped state (enforcement UNVERIFIED, never enforced)","","Examples:"," conductor emit-event --type run.started --source git-hook --run-id BAPI-393 \\",` --data-json '{"summary":"run started"}'`," conductor emit-event --type git.commit_created --source git-hook \\",` --raw-json '{"branch":"feature/x","sha":"abc123"}'`," conductor emit-event --type ci.failed --source ci \\"," --payload-ref 'file:///tmp/ci-log.txt'"," conductor emit-event --type merge.succeeded --source conductor-merge \\",` --worker-id w1 --data-json '{"summary":"auto-merged","status":"succeeded"}'`," conductor doctor --json"," conductor purge","","epic-tick options:"," --epic-key <KEY> Epic key to supervise (required, non-empty)"," --scheduled-at <epoch> Epoch-seconds timestamp when this tick was scheduled (optional)"," --lease-ttl-seconds <n> Lease TTL in seconds (optional, default 120)","","approve-plan options:"," approve-plan <epic_key> --plan-version N [--json]"," <epic_key> Epic key (e.g. EPIC-405) (required positional)"," --plan-version <n> Strictly positive plan version to approve (required)"," --json Print compact JSON result"," --help Print this usage message","","epic-status options:"," --epic-key <KEY> Epic key to fetch the snapshot for (required)"," --json Print compact JSON result"," --help Print this usage message","","Examples:"," conductor approve-plan EPIC-405 --plan-version 2"," conductor approve-plan EPIC-405 --plan-version 2 --json"," conductor epic-status --epic-key EPIC-405"," conductor epic-status --epic-key EPIC-405 --json"].join(`
146
146
  `)}var VALID_COMMANDS=new Set(["emit-event","supervise","epic-tick","approve-plan","epic-status","send-message","check-messages","doctor","purge","install-git-hooks","git-hook","file-scope-guard"]);function parseConductorArgs(argv){if(argv.length===0)return{kind:"help"};let first=argv[0];return first==="-h"||first==="--help"?{kind:"help"}:first.startsWith("-")?{kind:"error",message:`Unknown option "${first}". Run "conductor --help" for usage.`}:VALID_COMMANDS.has(first)?{kind:"command",command:first,argv:argv.slice(1)}:{kind:"error",message:`Unknown command "${first}". Run "conductor --help" for usage.`}}function tokenizeFlags(argv,valueFlags,boolFlags){let values=new Map,bools=new Set;for(let i=0;i<argv.length;i+=1){let token=argv[i];if(token==="-h"){bools.add("--help");continue}if(!token.startsWith("--"))throw new ConductorValidationError(`Unexpected argument "${token}".`);let eq=token.indexOf("="),name=eq>=0?token.slice(0,eq):token;if(boolFlags.has(name)){bools.add(name);continue}if(!valueFlags.has(name))throw new ConductorValidationError(`Unknown flag "${name}".`);let value;if(eq>=0)value=token.slice(eq+1);else{let next=argv[i+1];if(next===void 0)throw new ConductorValidationError(`Flag "${name}" requires a value.`);value=next,i+=1}values.set(name,value)}return{values,bools}}var EMIT_VALUE_FLAGS=new Set(["--type","--source","--id","--subject","--run-id","--worker-id","--producer","--schema-version","--time","--confidence","--observed-via","--data-json","--raw-json","--payload-ref"]),EMIT_BOOL_FLAGS=new Set(["--json","--help","--data-json-stdin"]);function defaultReadStdin(){return readFileSync3(0,"utf-8")}function parseJsonFlag(raw,flag){try{return JSON.parse(raw)}catch{throw new ConductorValidationError(`Flag "${flag}" must be valid JSON.`)}}function isPlainObject3(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)}function parseEmitEventArgs(argv,deps={}){let{values,bools}=tokenizeFlags(argv,EMIT_VALUE_FLAGS,EMIT_BOOL_FLAGS);if(bools.has("--help"))return{input:{source:"",type:"run.started"},json:bools.has("--json"),help:!0};let type=values.get("--type"),source=values.get("--source");if(!type)throw new ConductorValidationError('Flag "--type" is required for emit-event.');if(!source)throw new ConductorValidationError('Flag "--source" is required for emit-event.');let data={},dataJsonRaw=values.get("--data-json"),dataJsonStdin=bools.has("--data-json-stdin");if(dataJsonRaw!==void 0&&dataJsonStdin)throw new ConductorValidationError('Flags "--data-json" and "--data-json-stdin" are mutually exclusive; pass the normalized data object exactly one way.');if(dataJsonStdin){let stdinRaw=(deps.readStdin??defaultReadStdin)(),parsed=parseJsonFlag(stdinRaw,"--data-json-stdin");if(!isPlainObject3(parsed))throw new ConductorValidationError('Flag "--data-json-stdin" must be a JSON object.');data={...parsed}}else if(dataJsonRaw!==void 0){let parsed=parseJsonFlag(dataJsonRaw,"--data-json");if(!isPlainObject3(parsed))throw new ConductorValidationError('Flag "--data-json" must be a JSON object.');data={...parsed}}let rawJsonRaw=values.get("--raw-json");if(rawJsonRaw!==void 0){let parsedRaw=parseJsonFlag(rawJsonRaw,"--raw-json");if(!isPlainObject3(parsedRaw))throw new ConductorValidationError('Flag "--raw-json" must be a JSON object.');let existingRaw=isPlainObject3(data.raw)?data.raw:{};data.raw={...existingRaw,...parsedRaw}}let payloadRef=values.get("--payload-ref");payloadRef!==void 0&&(data.payload_ref=payloadRef);let schemaVersionRaw=values.get("--schema-version"),confidenceRaw=values.get("--confidence"),input={source,type,id:values.get("--id"),subject:values.get("--subject"),run_id:values.get("--run-id"),worker_id:values.get("--worker-id"),producer:values.get("--producer"),time:values.get("--time"),observed_via:values.get("--observed-via"),data};if(schemaVersionRaw!==void 0){let n=Number.parseInt(schemaVersionRaw,10);if(!Number.isFinite(n))throw new ConductorValidationError('Flag "--schema-version" must be an integer.');input.schema_version=n}if(confidenceRaw!==void 0){let n=Number.parseFloat(confidenceRaw);if(!Number.isFinite(n))throw new ConductorValidationError('Flag "--confidence" must be a number.');input.confidence=n}return{input,json:bools.has("--json"),help:!1}}async function runEmitEventCommand(argv,deps={}){let parsed=parseEmitEventArgs(argv,deps);if(parsed.help)return console.log(getConductorUsage()),0;let result;try{result=await emitConductorEvent(parsed.input)}catch(error){if(isDuplicateConstraintError2(error)){let dup={ok:!1,reason:"duplicate"};return console.log(parsed.json?JSON.stringify(dup):JSON.stringify(dup,null,2)),0}throw error}return parsed.json?console.log(JSON.stringify(result)):console.log(JSON.stringify(result,null,2)),0}var SEND_MESSAGE_VALUE_FLAGS=new Set(["--run-id","--worker-id","--type","--cause-seq","--payload-json","--available-at","--cooldown-ms"]),SEND_MESSAGE_BOOL_FLAGS=new Set(["--payload-json-stdin","--json","--help"]);function parseSendMessageArgs(argv,deps={}){let{values,bools}=tokenizeFlags(argv,SEND_MESSAGE_VALUE_FLAGS,SEND_MESSAGE_BOOL_FLAGS);if(bools.has("--help"))return{input:{run_id:"",worker_id:"",type:"",cause_seq:0},json:bools.has("--json"),help:!0};let runId=values.get("--run-id"),workerId=values.get("--worker-id"),type=values.get("--type"),causeSeqRaw=values.get("--cause-seq");if(!runId)throw new ConductorValidationError('Flag "--run-id" is required for send-message.');if(!workerId)throw new ConductorValidationError('Flag "--worker-id" is required for send-message.');if(!type)throw new ConductorValidationError('Flag "--type" is required for send-message.');if(causeSeqRaw===void 0)throw new ConductorValidationError('Flag "--cause-seq" is required for send-message.');if(!/^\d+$/.test(causeSeqRaw.trim()))throw new ConductorValidationError('Flag "--cause-seq" must be a non-negative integer.');let causeSeq=Number.parseInt(causeSeqRaw.trim(),10),payload={},payloadInline=values.get("--payload-json"),payloadStdin=bools.has("--payload-json-stdin");if(payloadInline!==void 0&&payloadStdin)throw new ConductorValidationError('Flags "--payload-json" and "--payload-json-stdin" are mutually exclusive; pass the payload object exactly one way.');if(payloadStdin){let readStdin=deps.readStdin??defaultReadStdin,parsed=parseJsonFlag(readStdin(),"--payload-json-stdin");if(!isPlainObject3(parsed))throw new ConductorValidationError('Flag "--payload-json-stdin" must be a JSON object.');payload={...parsed}}else if(payloadInline!==void 0){let parsed=parseJsonFlag(payloadInline,"--payload-json");if(!isPlainObject3(parsed))throw new ConductorValidationError('Flag "--payload-json" must be a JSON object.');payload={...parsed}}let input={run_id:runId,worker_id:workerId,type,cause_seq:causeSeq,payload},availableAt=values.get("--available-at");availableAt!==void 0&&(input.available_at=availableAt);let cooldownRaw=values.get("--cooldown-ms");if(cooldownRaw!==void 0){if(!/^\d+$/.test(cooldownRaw.trim()))throw new ConductorValidationError('Flag "--cooldown-ms" must be a non-negative integer.');input.cooldown_ms=Number.parseInt(cooldownRaw.trim(),10)}return{input,json:bools.has("--json"),help:!1}}async function runSendMessageCommand(argv,deps={}){let parsed=parseSendMessageArgs(argv,deps);if(parsed.help)return console.log(getConductorUsage()),0;let result=await sendWorkerMessage(parsed.input);return parsed.json?console.log(JSON.stringify(result)):console.log([`Message ${result.status}.`,` id: ${result.message.id}`,` type: ${result.message.type}`,` state: ${result.message.state}`].join(`
147
147
  `)),0}var CHECK_MESSAGES_VALUE_FLAGS=new Set(["--run-id","--worker-id","--limit"]),CHECK_MESSAGES_BOOL_FLAGS=new Set(["--json","--help"]);function parseCheckMessagesArgs(argv){let{values,bools}=tokenizeFlags(argv,CHECK_MESSAGES_VALUE_FLAGS,CHECK_MESSAGES_BOOL_FLAGS);if(bools.has("--help"))return{input:{run_id:"",worker_id:""},json:bools.has("--json"),help:!0};let runId=values.get("--run-id"),workerId=values.get("--worker-id");if(!runId)throw new ConductorValidationError('Flag "--run-id" is required for check-messages.');if(!workerId)throw new ConductorValidationError('Flag "--worker-id" is required for check-messages.');let input={run_id:runId,worker_id:workerId},limitRaw=values.get("--limit");if(limitRaw!==void 0){if(!/^\d+$/.test(limitRaw.trim()))throw new ConductorValidationError('Flag "--limit" must be a positive integer.');input.limit=Number.parseInt(limitRaw.trim(),10)}return{input,json:bools.has("--json"),help:!1}}async function runCheckMessagesCommand(argv){let parsed=parseCheckMessagesArgs(argv);if(parsed.help)return console.log(getConductorUsage()),0;let result=await checkWorkerMessages(parsed.input);if(parsed.json)return console.log(JSON.stringify(result)),0;let lines=[`Acknowledged ${result.acked_count} of ${result.count} message(s).`];for(let message of result.messages)lines.push(` ${message.id} [${message.type}] -> ${message.state}`);return console.log(lines.join(`