@bridge_gpt/mcp-server 0.2.52 → 0.2.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -12
- package/build/commands.generated.js +6 -4
- package/build/conductor/bridge-api-client.js +61 -0
- package/build/conductor/cli.js +23 -0
- package/build/conductor/doctor.js +428 -5
- package/build/conductor/install-doctor.js +65 -656
- package/build/conductor/readiness-cli.js +152 -0
- package/build/conductor/readiness-sections.js +666 -0
- package/build/conductor/readiness.js +710 -0
- package/build/conductor/tools.js +56 -3
- package/build/conductor-bin.js +21 -17
- package/build/index.js +4651 -4580
- package/build/install-doctor.js +154 -2
- package/build/pipelines.generated.js +3 -3
- package/build/plane/alembic-head.js +40 -11
- package/build/plane/build-freshness.js +22 -11
- package/build/plane/preflight.js +363 -48
- package/build/plane/types.js +36 -0
- package/build/readiness-check.js +412 -0
- package/build/readme.generated.js +1 -1
- package/build/version.generated.js +3 -3
- package/package.json +2 -2
- package/pipelines/{full-automation.json → idea-to-pr.json} +1 -1
package/build/conductor-bin.js
CHANGED
|
@@ -96,34 +96,38 @@ var __defProp=Object.defineProperty;var __getOwnPropNames=Object.getOwnPropertyN
|
|
|
96
96
|
WHERE run_id = @run_id AND worker_id = @worker_id AND state = 'pending'
|
|
97
97
|
AND julianday(available_at) <= julianday('now')
|
|
98
98
|
ORDER BY seq ASC
|
|
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(`
|
|
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{chmodSync,existsSync as existsSync2,mkdirSync,readFileSync,realpathSync,statSync,writeFileSync}from"node:fs";import{basename as basename2,dirname,isAbsolute,join,resolve}from"node:path";import{fileURLToPath}from"node:url";function resolveGitHooksDirectory(deps={}){let runGit=deps.runGit??runGitCommand,cwd=deps.cwd??process.cwd(),result=runGit(["rev-parse","--git-common-dir"],{cwd});if(!result.ok)return{is_worktree:!1,hooks_dir:null};let commonDir=result.stdout.trim();if(commonDir.length===0)return{is_worktree:!1,hooks_dir:null};let absoluteCommonDir=isAbsolute(commonDir)?commonDir:resolve(cwd,commonDir);return{is_worktree:!0,hooks_dir:resolve(absoluteCommonDir,"hooks")}}function resolveConductorHookBin(overrides={}){let deps={moduleUrl:overrides.moduleUrl??import.meta.url,argv1:overrides.argv1??process.argv[1],realpath:overrides.realpath??defaultRealpath,isFile:overrides.isFile??defaultIsFile},moduleFile=moduleFilePath(deps.moduleUrl),candidates=[];if(moduleFile!==null){let dir=dirname(moduleFile);candidates.push(join(dir,CONDUCTOR_BIN_FILENAME)),candidates.push(join(dir,"..",CONDUCTOR_BIN_FILENAME))}typeof deps.argv1=="string"&&deps.argv1.length>0&&basename2(deps.argv1)===CONDUCTOR_BIN_FILENAME&&candidates.push(deps.argv1);let seen=new Set;for(let candidate of candidates){let canonical;try{canonical=deps.realpath(candidate)}catch{continue}if(canonical!==null&&!seen.has(canonical)){seen.add(canonical);try{if(deps.isFile(canonical))return{ok:!0,path:canonical}}catch{continue}}}return{ok:!1,reason:CONDUCTOR_HOOK_BIN_UNRESOLVED_REASON}}function moduleFilePath(moduleUrl){try{return fileURLToPath(moduleUrl)}catch{return null}}function defaultRealpath(filePath){try{return realpathSync(filePath)}catch{return null}}function defaultIsFile(filePath){try{return statSync(filePath).isFile()}catch{return!1}}function wrapManagedBlock(body){return[BRIDGE_CONDUCTOR_HOOK_START,body,BRIDGE_CONDUCTOR_HOOK_END].join(`
|
|
100
|
+
`)}function buildPostCommitHookSnippet(conductorBin){let body=["# Managed by Bridge conductor (BAPI-395). Local, unversioned, opportunistic, bypassable.",`( node ${JSON.stringify(conductorBin)} git-hook post-commit >/dev/null 2>&1 & ) || true`].join(`
|
|
101
|
+
`);return wrapManagedBlock(body)}function buildReferenceTransactionHookSnippet(conductorBin){let body=["# Managed by Bridge conductor (BAPI-395). Local, unversioned, opportunistic, bypassable.",'__bridge_tmp="$(mktemp 2>/dev/null || echo "/tmp/bridge-conductor-refs.$$")"','cat > "$__bridge_tmp"',`( node ${JSON.stringify(conductorBin)} git-hook reference-transaction --phase "$1" --stdin-file "$__bridge_tmp" >/dev/null 2>&1 & ) || true`].join(`
|
|
102
|
+
`);return wrapManagedBlock(body)}function looksBinary(content){return content.includes("\0")}function mergeManagedHookSnippet(existing,managedBlock){if(existing===null||existing.length===0)return{ok:!0,content:`#!/bin/sh
|
|
103
|
+
${managedBlock}
|
|
104
|
+
`,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(`
|
|
105
|
+
`)?"":`
|
|
106
|
+
`;return{ok:!0,content:`${existing}${separator}${managedBlock}
|
|
107
|
+
`,action:"appended"}}function snippetForHook(name,conductorBin){return name==="post-commit"?buildPostCommitHookSnippet(conductorBin):buildReferenceTransactionHookSnippet(conductorBin)}function validateResolvedBin(resolution){if(!resolution.ok)return resolution;let canonical=defaultRealpath(resolution.path);return canonical===null||!defaultIsFile(canonical)?{ok:!1,reason:CONDUCTOR_HOOK_BIN_UNRESOLVED_REASON}:{ok:!0,path:canonical}}function installConductorGitHooks(deps={}){let platform=deps.platform??process.platform,resolution=validateResolvedBin(deps.resolveBin?deps.resolveBin():resolveConductorHookBin());if(!resolution.ok)return{ok:!1,error:CONDUCTOR_BIN_UNRESOLVED_ERROR,reason:resolution.reason};let conductorBin=resolution.path,{is_worktree,hooks_dir}=resolveGitHooksDirectory(deps);if(!is_worktree||hooks_dir===null)return{ok:!0,is_worktree:!1,hooks_dir:null,installed:[],warnings:["not a git worktree; git hooks were not installed (degraded optional capability)"],conductor_bin:conductorBin};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{ok:!0,is_worktree:!0,hooks_dir,installed,warnings,conductor_bin:conductorBin}}function extractManagedHookBinPath(content){let startIdx=content.indexOf(BRIDGE_CONDUCTOR_HOOK_START),endIdx=content.indexOf(BRIDGE_CONDUCTOR_HOOK_END);if(startIdx===-1||endIdx===-1||endIdx<=startIdx)return null;let block=content.slice(startIdx,endIdx),match=/\bnode\s+("(?:[^"\\]|\\.)*")\s+git-hook\b/.exec(block);if(match===null)return null;try{let parsed=JSON.parse(match[1]);return typeof parsed=="string"&&parsed.length>0?parsed:null}catch{return null}}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,embeddedBinPath=null,embeddedBinIsFile=!1;if(exists){try{let mode=statSync(hookPath).mode;executable=platform==="win32"?!0:(mode&73)!==0}catch{}try{let content=readFileSync(hookPath,"utf-8");managedPresent=content.includes(BRIDGE_CONDUCTOR_HOOK_START),managedPresent&&(embeddedBinPath=extractManagedHookBinPath(content),embeddedBinIsFile=embeddedBinPath!==null&&defaultIsFile(embeddedBinPath),embeddedBinPath===null?warnings.push(`${name} hook has a managed block with no recognizable conductor command; reinstall with \`conductor install-git-hooks\``):embeddedBinIsFile||warnings.push(`${name} hook points at a missing or invalid conductor binary (${embeddedBinPath}); the hook is dead \u2014 reinstall with \`conductor install-git-hooks\``))}catch{}}else warnings.push(`${name} hook not installed (degraded optional capability)`);hooks.push({name,path:hookPath,exists,executable,managed_block_present:managedPresent,embedded_bin_path:embeddedBinPath,embedded_bin_is_file:embeddedBinIsFile})}let degraded=hooks.some(h=>!h.exists||!h.managed_block_present||!h.embedded_bin_is_file);return{is_worktree:!0,hooks_dir,hooks,warnings,degraded}}var BRIDGE_CONDUCTOR_HOOK_START,BRIDGE_CONDUCTOR_HOOK_END,MANAGED_HOOK_NAMES,CONDUCTOR_BIN_FILENAME,CONDUCTOR_HOOK_BIN_UNRESOLVED_REASON,CONDUCTOR_BIN_UNRESOLVED_ERROR,init_git_hooks=__esm({"src/conductor/git-hooks.ts"(){"use strict";init_git_inspection();BRIDGE_CONDUCTOR_HOOK_START="# >>> BRIDGE_CONDUCTOR_HOOK_START >>>",BRIDGE_CONDUCTOR_HOOK_END="# <<< BRIDGE_CONDUCTOR_HOOK_END <<<",MANAGED_HOOK_NAMES=["post-commit","reference-transaction"];CONDUCTOR_BIN_FILENAME="conductor-bin.js",CONDUCTOR_HOOK_BIN_UNRESOLVED_REASON=`no usable ${CONDUCTOR_BIN_FILENAME} was found for the executing artifact (searched: the sibling bundle layout, the parent TypeScript-emit layout, and the invocation target when it is named ${CONDUCTOR_BIN_FILENAME}). Reinstall or rebuild the package so a conductor binary ships beside the executing module.`;CONDUCTOR_BIN_UNRESOLVED_ERROR="CONDUCTOR_BIN_UNRESOLVED"}});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,spawn2=opts.spawnSyncFn??defaultSpawnSync,result;try{result=spawn2("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
108
|
`)){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
109
|
`)),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)}});var MCP_SERVER_NAME,MCP_PACKAGE_NAME,MCP_README_URI,LEGACY_SERVER_NAMES,RECOGNIZED_SERVER_NAMES,init_mcp_identity=__esm({"src/mcp-identity.ts"(){"use strict";MCP_SERVER_NAME="bridge",MCP_PACKAGE_NAME="@bridge_gpt/mcp-server",MCP_README_URI=`${MCP_SERVER_NAME}://readme`,LEGACY_SERVER_NAMES=["bridge-api"],RECOGNIZED_SERVER_NAMES=[MCP_SERVER_NAME,...LEGACY_SERVER_NAMES]}});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";init_mcp_identity();DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC=`${MCP_PACKAGE_NAME}@latest`}});function resolveProfiles(raw){let baseline=new Set(["core"]);if(raw===void 0)return baseline;let trimmed=raw.trim();if(trimmed==="")return baseline;let tokens=trimmed.split(",").map(t=>t.trim().toLowerCase());if(tokens.some(t=>t==="full"))return new Set(["core","conductor","estimation","pipeline-authoring","sfcc","sfcc-write"]);for(let token of tokens)VALID_GROUPS.has(token)&&baseline.add(token);return baseline}var VALID_GROUPS,init_mcp_profile=__esm({"src/mcp-profile.ts"(){"use strict";VALID_GROUPS=new Set(["core","conductor","estimation","pipeline-authoring","sfcc","sfcc-write"])}});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"}});import path5 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(`
|
|
103
|
-
`),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 path5.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()}});function joinPath(base,rel){let trimmedBase=base.endsWith("/")?base.slice(0,-1):base,trimmedRel=rel.startsWith("/")?rel.slice(1):rel;return`${trimmedBase}/${trimmedRel}`}function hostAdapterForTarget(target){return HOST_ADAPTERS[target.hostKind]}function allHostTargets(){return HOST_PLATFORM_ORDER.map(id=>MCP_HOST_TARGETS[id])}function getProjectJsonTargets(){return allHostTargets().filter(t=>t.scope==="project"&&hostAdapterForTarget(t).format==="json")}var HOST_ADAPTERS,MCP_HOST_TARGETS,HOST_PLATFORM_ORDER,init_mcp_host_targets=__esm({"src/mcp-host-targets.ts"(){"use strict";HOST_ADAPTERS={"claude-code-json":{format:"json",topLevelKey:"mcpServers",transportType:void 0},"cursor-json":{format:"json",topLevelKey:"mcpServers",transportType:"stdio"},"vscode-json":{format:"json",topLevelKey:"servers",transportType:"stdio"},"codex-toml":{format:"toml",topLevelKey:"mcp_servers",transportType:void 0},"copilot-cli":{format:"json",topLevelKey:"mcpServers",transportType:"local",extraEntryKeys:{tools:["*"]}}};MCP_HOST_TARGETS={"claude-code":{id:"claude-code",label:"Claude Code",scope:"project",relPath:".mcp.json",displayPath:".mcp.json",hostKind:"claude-code-json",vendorCli:{bin:"claude",kind:"claude-add-json"},launchAgent:"claude",worktreeSupported:!0,writeStrategy:"vendor-first",detect:()=>!0},cursor:{id:"cursor",label:"Cursor",scope:"project",relPath:".cursor/mcp.json",displayPath:".cursor/mcp.json",hostKind:"cursor-json",launchAgent:"cursor-agent",worktreeSupported:!0,writeStrategy:"direct",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".cursor"))||typeof ctx.env.CURSOR_TRACE_DIR=="string"&&ctx.env.CURSOR_TRACE_DIR.length>0},"copilot-vscode":{id:"copilot-vscode",label:"GitHub Copilot (VS Code)",scope:"project",relPath:".vscode/mcp.json",displayPath:".vscode/mcp.json",hostKind:"vscode-json",worktreeSupported:!1,writeStrategy:"direct",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".vscode"))},"copilot-cli":{id:"copilot-cli",label:"GitHub Copilot CLI",scope:"global",absPathResolver:homedir=>joinPath(homedir,".copilot/mcp-config.json"),displayPath:"~/.copilot/mcp-config.json",hostKind:"copilot-cli",vendorCli:{bin:"copilot",kind:"copilot-add"},worktreeSupported:!1,writeStrategy:"vendor-first",detect:()=>!1},codex:{id:"codex",label:"OpenAI Codex",scope:"global",absPathResolver:homedir=>joinPath(homedir,".codex/config.toml"),displayPath:"~/.codex/config.toml",hostKind:"codex-toml",vendorCli:{bin:"codex",kind:"codex-add"},worktreeSupported:!1,writeStrategy:"vendor-first",detect:ctx=>ctx.exists(joinPath(ctx.homedir,".codex"))},windsurf:{id:"windsurf",label:"Windsurf",scope:"global",absPathResolver:homedir=>joinPath(homedir,".codeium/windsurf/mcp_config.json"),displayPath:"~/.codeium/windsurf/mcp_config.json",hostKind:"claude-code-json",worktreeSupported:!1,writeStrategy:"manual-instructions",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".windsurf"))||ctx.exists(joinPath(ctx.cwd,".windsurfrules"))}},HOST_PLATFORM_ORDER=["claude-code","cursor","copilot-vscode","copilot-cli","codex","windsurf"]}});var LAUNCHER_CONFIG_TARGETS,DUPLICATE_REGISTRATION_GUIDANCE,REASON_TEXT,init_launcher_config_inspection=__esm({"src/launcher-config-inspection.ts"(){"use strict";init_mcp_host_targets();init_mcp_identity();LAUNCHER_CONFIG_TARGETS=getProjectJsonTargets().map(target=>({relPath:target.relPath,topLevelKey:hostAdapterForTarget(target).topLevelKey})),DUPLICATE_REGISTRATION_GUIDANCE=`duplicate Bridge registrations: this config carries both \`${MCP_SERVER_NAME}\` and \`${LEGACY_SERVER_NAMES.join("`, `")}\`. Confirm which registration you want to keep, then remove the unintended entry manually. Bridge will not choose for you.`,REASON_TEXT={"file-unreadable":"the file exists but could not be read","invalid-json":"the file is not valid JSON","root-not-object":"the JSON root is not an object","servers-not-object":"the servers section is not an object","entry-not-object":"the Bridge entry is not an object","no-package-token":`the Bridge launcher has no recognizable ${MCP_PACKAGE_NAME} token`,"version-range":"the launcher pin is a version range, which an automated repin must not rewrite","non-release-specifier":"the launcher pin is a dist-tag or channel, not an exact release","malformed-version":"the launcher pin is not a valid MAJOR.MINOR.PATCH release","pinned-ahead-of-target":"the launcher pin is newer than the target version and must not be downgraded","duplicate-registration":DUPLICATE_REGISTRATION_GUIDANCE}}});var init_mcp_registration_doctor=__esm({"src/mcp-registration-doctor.ts"(){"use strict";init_mcp_host_targets();init_mcp_identity();init_launcher_config_inspection()}});var init_commands_generated=__esm({"src/commands.generated.ts"(){"use strict"}});var init_command_assets_doctor=__esm({"src/command-assets-doctor.ts"(){"use strict";init_commands_generated()}});var CLAUDE_REVIEW_WORKFLOW_RELPATH,CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION,init_claude_review_workflow_drift=__esm({"src/claude-review-workflow-drift.ts"(){"use strict";CLAUDE_REVIEW_WORKFLOW_RELPATH=".github/workflows/claude-review.yml",CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION=`Reconcile the base branch with the repository default branch \u2014 merge the default branch in, or sync ${CLAUDE_REVIEW_WORKFLOW_RELPATH} together with tests/pytest/commands/test_claude_review_workflow_prompt.py. See docs/claude/runbooks/claude-review-base-branch-drift.md.`}});var init_claude_review_workflow_drift_probe=__esm({"src/claude-review-workflow-drift-probe.ts"(){"use strict";init_claude_review_workflow_drift()}});var init_third_party_mcp_targets=__esm({"src/third-party-mcp-targets.ts"(){"use strict";init_credential_store()}});var init_mcp_provisioning=__esm({"src/mcp-provisioning.ts"(){"use strict";init_bridge_config();init_third_party_mcp_targets();init_mcp_server_invocation();init_mcp_host_targets();init_mcp_identity()}});function claudeMcpShadowingRemediationCommand(registrationKey){return`claude mcp remove ${registrationKey} -s local`}var CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV,CLAUDE_MCP_SHADOWING_OVERRIDE_WARNING,CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND,init_claude_user_config_doctor=__esm({"src/claude-user-config-doctor.ts"(){"use strict";init_mcp_registration_doctor();init_mcp_provisioning();init_mcp_identity();init_launcher_config_inspection();CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV="BAPI_CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING",CLAUDE_MCP_SHADOWING_OVERRIDE_WARNING=`Proceeding anyway because ${CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV} is set`;CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND=claudeMcpShadowingRemediationCommand(MCP_SERVER_NAME)}});var START_TICKETS_DOCTOR_COMMAND,CONDUCTOR_LIVE_SOURCE_PATH_ENV,CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV,GIT_INSTALL_HINTS,REVIEW_TICKETS_GIT_INSTALL_HINTS,RIPGREP_SHELL_FUNCTION_CAVEAT,RIPGREP_INSTALL_HINTS,CREDENTIAL_RESOLUTION_HINT,CLAUDE_MCP_SHADOWING_HINT,LIVE_SOURCE_GUARD_HINT,init_start_tickets_prereqs=__esm({"src/start-tickets-prereqs.ts"(){"use strict";init_credential_store();init_start_tickets_repo();init_mcp_registration_doctor();init_command_assets_doctor();init_mcp_identity();init_claude_review_workflow_drift();init_claude_review_workflow_drift_probe();init_claude_user_config_doctor();START_TICKETS_DOCTOR_COMMAND=`npx -y ${MCP_PACKAGE_NAME} doctor`,CONDUCTOR_LIVE_SOURCE_PATH_ENV="BAPI_CONDUCTOR_LIVE_SOURCE_PATH",CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV="BAPI_CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH",GIT_INSTALL_HINTS={darwin:"xcode-select --install (or brew install git)",linux:"Install git with your distro package manager, e.g. apt install git",win32:"Install Git for Windows: https://git-scm.com/download/win"},REVIEW_TICKETS_GIT_INSTALL_HINTS={darwin:`${GIT_INSTALL_HINTS.darwin} (or rerun review-tickets with --no-refresh-base to skip the fetch)`,linux:`${GIT_INSTALL_HINTS.linux} (or rerun review-tickets with --no-refresh-base to skip the fetch)`,win32:`${GIT_INSTALL_HINTS.win32} (or rerun review-tickets with --no-refresh-base to skip the fetch)`},RIPGREP_SHELL_FUNCTION_CAVEAT="a shell function/alias will not satisfy this check \u2014 ripgrep must be installed as a real PATH binary.",RIPGREP_INSTALL_HINTS={darwin:`brew install ripgrep (${RIPGREP_SHELL_FUNCTION_CAVEAT})`,linux:`Install ripgrep with your distro package manager, e.g. apt install ripgrep (${RIPGREP_SHELL_FUNCTION_CAVEAT})`,win32:`winget install BurntSushi.ripgrep.MSVC (${RIPGREP_SHELL_FUNCTION_CAVEAT})`},CREDENTIAL_RESOLUTION_HINT=`Rerun /install-bridge to persist the routing credential, set BAPI_API_KEY in the environment, or add it under "bapi:<repo_name>" in ~/.config/bridge/credentials.json. To migrate a key that only lives in .mcp.json / .cursor/mcp.json, run: npx -y ${MCP_PACKAGE_NAME} credentials migrate-agent-config --write-credentials.`,CLAUDE_MCP_SHADOWING_HINT=`Run \`${CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND}\` to clear the '${MCP_SERVER_NAME}' MCP registration in ~/.claude.json (use the matching scope if it is registered at user scope, or under the projects entry for this repository/worktree). This is ADVISORY: workers load MCP servers with --strict-mcp-config from their own worktree registration, so this entry does not reach a worker and does not block a conductor run.`,LIVE_SOURCE_GUARD_HINT=`Point ${CONDUCTOR_LIVE_SOURCE_PATH_ENV} at your live dev server's checkout ONLY when it differs from this conductor base checkout, or dispatch the conductor from a separate clone. To override the guard and dispatch anyway (not recommended), set ${CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV}=1.`}});import path6 from"path";function pathApiForPlatform(platform){return platform==="win32"?path6.win32:path6.posix}var init_worktree_core=__esm({"src/worktree-core.ts"(){"use strict";init_start_tickets_prereqs()}});var init_platform_escaping=__esm({"src/platform-escaping.ts"(){"use strict"}});var init_prompt=__esm({"src/agent-launchers/prompt.ts"(){"use strict"}});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)}var init_claude=__esm({"src/agent-launchers/claude.ts"(){"use strict";init_worktree_core();init_platform_escaping();init_prompt()}});var DEFAULT_PROBE_TIMEOUT_MS,init_types=__esm({"src/agent-capabilities/types.ts"(){"use strict";DEFAULT_PROBE_TIMEOUT_MS=9e4}});import{join as join2}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==="auto"?args.push("--permission-mode","auto"):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(join2(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_types()}});import{execFile}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=>{execFile(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 join3}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(join3(dir,DENY_TARGET_FILE),`${marker}
|
|
110
|
+
`)),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"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."}var init_claude_login=__esm({"src/claude-login.ts"(){"use strict"}});function resolveRegistrationKey(servers){let absent={state:"absent",writeKey:MCP_SERVER_NAME};if(typeof servers!="object"||servers===null||Array.isArray(servers))return absent;let present=RECOGNIZED_SERVER_NAMES.filter(name=>Object.prototype.hasOwnProperty.call(servers,name));if(present.length===0)return absent;if(present.length>1)return{state:"conflict",keys:present};let[only]=present;return only===MCP_SERVER_NAME?{state:"canonical",key:MCP_SERVER_NAME}:{state:"legacy",key:only}}function existingRegistrationKey(servers){let resolution=resolveRegistrationKey(servers);return resolution.state==="canonical"||resolution.state==="legacy"?resolution.key:null}var MCP_SERVER_NAME,MCP_PACKAGE_NAME,MCP_README_URI,LEGACY_SERVER_NAMES,RECOGNIZED_SERVER_NAMES,init_mcp_identity=__esm({"src/mcp-identity.ts"(){"use strict";MCP_SERVER_NAME="bridge",MCP_PACKAGE_NAME="@bridge_gpt/mcp-server",MCP_README_URI=`${MCP_SERVER_NAME}://readme`,LEGACY_SERVER_NAMES=["bridge-api"],RECOGNIZED_SERVER_NAMES=[MCP_SERVER_NAME,...LEGACY_SERVER_NAMES]}});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";init_mcp_identity();DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC=`${MCP_PACKAGE_NAME}@latest`}});function resolveProfiles(raw){let baseline=new Set(["core"]);if(raw===void 0)return baseline;let trimmed=raw.trim();if(trimmed==="")return baseline;let tokens=trimmed.split(",").map(t=>t.trim().toLowerCase());if(tokens.some(t=>t==="full"))return new Set(["core","conductor","estimation","pipeline-authoring","sfcc","sfcc-write"]);for(let token of tokens)VALID_GROUPS.has(token)&&baseline.add(token);return baseline}var VALID_GROUPS,init_mcp_profile=__esm({"src/mcp-profile.ts"(){"use strict";VALID_GROUPS=new Set(["core","conductor","estimation","pipeline-authoring","sfcc","sfcc-write"])}});function containsAbsolutePath(value){return ABSOLUTE_PATH_PATTERN.test(value)}function containsTransportArtifact(value){return TRANSPORT_ARTIFACT_PATTERN.test(value)}function normalizeProse(value,field,maxLength){if(typeof value!="string")throw new ReadinessCheckValidationError(Array.isArray(value)?`${field} must be a single string, not an array`:`${field} must be a string`);let collapsed=value.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s{2,}/g," ").trim();if(collapsed.length===0)throw new ReadinessCheckValidationError(`${field} must not be blank`);if(containsAbsolutePath(collapsed))throw new ReadinessCheckValidationError(`${field} must not contain an absolute path`);if(containsTransportArtifact(collapsed))throw new ReadinessCheckValidationError(`${field} must not contain a request header or a response body`);return collapsed.length>maxLength?`${collapsed.slice(0,maxLength-1).trimEnd()}\u2026`:collapsed}function normalizeReadinessDetail(value){return normalizeProse(value,"detail",READINESS_DETAIL_MAX_LENGTH)}function normalizeReadinessRemediation(value){return normalizeProse(value,"remediation",READINESS_REMEDIATION_MAX_LENGTH)}function createReadinessCheck(input){if(input===null||typeof input!="object")throw new ReadinessCheckValidationError("check must be an object");if(!READINESS_CHECK_SOURCES.includes(input.source))throw new ReadinessCheckValidationError("source is not a supported readiness source");if(!READINESS_CHECK_STATUSES.includes(input.status))throw new ReadinessCheckValidationError("status is not a supported readiness status");if(typeof input.id!="string"||!READINESS_ID_PATTERN.test(input.id))throw new ReadinessCheckValidationError("id is not a stable dotted lowercase identifier");if(!input.id.startsWith(`${input.source}.`))throw new ReadinessCheckValidationError("id namespace does not match its source");let label=normalizeProse(input.label,"label",READINESS_DETAIL_MAX_LENGTH),detail=input.detail===void 0?void 0:normalizeReadinessDetail(input.detail);if(input.status==="pass"){if(input.remediation!==void 0)throw new ReadinessCheckValidationError("a passing check must not carry a remediation");return{id:input.id,source:input.source,label,status:"pass",...detail?{detail}:{}}}if(input.status==="fail"){if(input.remediation===void 0)throw new ReadinessCheckValidationError("a failing check must carry exactly one remediation");return{id:input.id,source:input.source,label,status:"fail",...detail?{detail}:{},remediation:normalizeReadinessRemediation(input.remediation)}}let remediation=input.remediation===void 0?void 0:normalizeReadinessRemediation(input.remediation);return{id:input.id,source:input.source,label,status:input.status,...detail?{detail}:{},...remediation?{remediation}:{}}}function validateReadinessChecks(checks,fallbackSource="conductor"){let validated=[],malformedIndex=0;for(let candidate of checks)try{validated.push(createReadinessCheck(candidate))}catch{let raw=candidate??{},source=READINESS_CHECK_SOURCES.includes(raw.source)?raw.source:fallbackSource;malformedIndex+=1,validated.push(createReadinessCheck({id:`${source}.unreadable-check-${malformedIndex}`,source,label:READINESS_MALFORMED_CHECK_LABEL,status:"fail",detail:READINESS_MALFORMED_CHECK_DETAIL,remediation:READINESS_MALFORMED_CHECK_REMEDIATION}))}return validated}function summarizeReadinessChecks(checks){let counts={pass:0,warn:0,fail:0,skip:0};for(let check of checks)counts[check.status]+=1;return counts}function createReadinessCheckSafely(input){let safeRemediation=()=>input?.status==="pass"?{remediation:void 0}:{remediation:READINESS_UNSAFE_REMEDIATION_REPLACEMENT};try{return createReadinessCheck(input)}catch{}try{return createReadinessCheck({...input,detail:READINESS_UNSAFE_DETAIL_REPLACEMENT})}catch{}try{return createReadinessCheck({...input,...safeRemediation()})}catch{}try{return createReadinessCheck({...input,detail:READINESS_UNSAFE_DETAIL_REPLACEMENT,...safeRemediation()})}catch{}let source=READINESS_CHECK_SOURCES.includes(input?.source)?input.source:"conductor";return createReadinessCheck({id:`${source}.unreadable-check`,source,label:READINESS_MALFORMED_CHECK_LABEL,status:"fail",detail:READINESS_MALFORMED_CHECK_DETAIL,remediation:READINESS_MALFORMED_CHECK_REMEDIATION})}var READINESS_CHECK_STATUSES,READINESS_CHECK_SOURCES,ReadinessCheckValidationError,READINESS_DETAIL_MAX_LENGTH,READINESS_REMEDIATION_MAX_LENGTH,ID_SEGMENT,READINESS_ID_PATTERN,POSIX_PATH_ROOTS,ABSOLUTE_PATH_PATTERN,TRANSPORT_ARTIFACT_PATTERN,READINESS_MALFORMED_CHECK_DETAIL,READINESS_MALFORMED_CHECK_REMEDIATION,READINESS_MALFORMED_CHECK_LABEL,READINESS_UNSAFE_DETAIL_REPLACEMENT,READINESS_UNSAFE_REMEDIATION_REPLACEMENT,init_readiness_check=__esm({"src/readiness-check.ts"(){"use strict";READINESS_CHECK_STATUSES=["pass","warn","fail","skip"],READINESS_CHECK_SOURCES=["install","conductor","plane","server"],ReadinessCheckValidationError=class extends Error{constructor(reason){super(`invalid readiness check: ${reason}`),this.name="ReadinessCheckValidationError"}},READINESS_DETAIL_MAX_LENGTH=400,READINESS_REMEDIATION_MAX_LENGTH=400,ID_SEGMENT="[a-z0-9]+(?:-[a-z0-9]+)*",READINESS_ID_PATTERN=new RegExp(`^${ID_SEGMENT}(?:\\.${ID_SEGMENT})+$`),POSIX_PATH_ROOTS=["Users","home","root","var","tmp","private","opt","usr","etc","srv","mnt","media","Applications","Library","System","Volumes","node_modules"],ABSOLUTE_PATH_PATTERN=new RegExp(`(^|[\\s"'\`(<])(?:\\/(?:${POSIX_PATH_ROOTS.join("|")})\\/|[A-Za-z]:[\\\\/]|file:\\/\\/)`);TRANSPORT_ARTIFACT_PATTERN=/(^|[\s"'`(<])(?:authorization\s*:|x-api-key\s*:|bearer\s+\S|\{\s*"[A-Za-z_$][\w$]*"\s*:)/i;READINESS_MALFORMED_CHECK_DETAIL="this prerequisite reported a result that failed the readiness contract, so its real state is unknown",READINESS_MALFORMED_CHECK_REMEDIATION="re-run `conductor readiness`; if it persists, run `conductor doctor` and `install conductor` to re-collect this locus.",READINESS_MALFORMED_CHECK_LABEL="Unreadable prerequisite";READINESS_UNSAFE_DETAIL_REPLACEMENT="detail withheld \u2014 the source reported it in a form this report may not carry",READINESS_UNSAFE_REMEDIATION_REPLACEMENT="re-run `conductor readiness`; this prerequisite's own fix text could not be carried into this report safely."}});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"}});import path5 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(`
|
|
111
|
+
`),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 path5.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}async function resolveRequiredStartTicketsRepoName(deps){let repoName=await resolveStartTicketsRepoName(deps);return repoName?{ok:!0,repoName}:{ok:!1,kind:"repo-missing",error:"could not resolve repo name (set BAPI_REPO_NAME or add a valid .bridge/config)"}}var init_start_tickets_repo=__esm({"src/start-tickets-repo.ts"(){"use strict";init_bridge_config()}});function joinPath(base,rel){let trimmedBase=base.endsWith("/")?base.slice(0,-1):base,trimmedRel=rel.startsWith("/")?rel.slice(1):rel;return`${trimmedBase}/${trimmedRel}`}function hostAdapterForTarget(target){return HOST_ADAPTERS[target.hostKind]}function allHostTargets(){return HOST_PLATFORM_ORDER.map(id=>MCP_HOST_TARGETS[id])}function getProjectJsonTargets(){return allHostTargets().filter(t=>t.scope==="project"&&hostAdapterForTarget(t).format==="json")}var HOST_ADAPTERS,MCP_HOST_TARGETS,HOST_PLATFORM_ORDER,init_mcp_host_targets=__esm({"src/mcp-host-targets.ts"(){"use strict";HOST_ADAPTERS={"claude-code-json":{format:"json",topLevelKey:"mcpServers",transportType:void 0},"cursor-json":{format:"json",topLevelKey:"mcpServers",transportType:"stdio"},"vscode-json":{format:"json",topLevelKey:"servers",transportType:"stdio"},"codex-toml":{format:"toml",topLevelKey:"mcp_servers",transportType:void 0},"copilot-cli":{format:"json",topLevelKey:"mcpServers",transportType:"local",extraEntryKeys:{tools:["*"]}}};MCP_HOST_TARGETS={"claude-code":{id:"claude-code",label:"Claude Code",scope:"project",relPath:".mcp.json",displayPath:".mcp.json",hostKind:"claude-code-json",vendorCli:{bin:"claude",kind:"claude-add-json"},launchAgent:"claude",worktreeSupported:!0,writeStrategy:"vendor-first",detect:()=>!0},cursor:{id:"cursor",label:"Cursor",scope:"project",relPath:".cursor/mcp.json",displayPath:".cursor/mcp.json",hostKind:"cursor-json",launchAgent:"cursor-agent",worktreeSupported:!0,writeStrategy:"direct",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".cursor"))||typeof ctx.env.CURSOR_TRACE_DIR=="string"&&ctx.env.CURSOR_TRACE_DIR.length>0},"copilot-vscode":{id:"copilot-vscode",label:"GitHub Copilot (VS Code)",scope:"project",relPath:".vscode/mcp.json",displayPath:".vscode/mcp.json",hostKind:"vscode-json",worktreeSupported:!1,writeStrategy:"direct",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".vscode"))},"copilot-cli":{id:"copilot-cli",label:"GitHub Copilot CLI",scope:"global",absPathResolver:homedir=>joinPath(homedir,".copilot/mcp-config.json"),displayPath:"~/.copilot/mcp-config.json",hostKind:"copilot-cli",vendorCli:{bin:"copilot",kind:"copilot-add"},worktreeSupported:!1,writeStrategy:"vendor-first",detect:()=>!1},codex:{id:"codex",label:"OpenAI Codex",scope:"global",absPathResolver:homedir=>joinPath(homedir,".codex/config.toml"),displayPath:"~/.codex/config.toml",hostKind:"codex-toml",vendorCli:{bin:"codex",kind:"codex-add"},worktreeSupported:!1,writeStrategy:"vendor-first",detect:ctx=>ctx.exists(joinPath(ctx.homedir,".codex"))},windsurf:{id:"windsurf",label:"Windsurf",scope:"global",absPathResolver:homedir=>joinPath(homedir,".codeium/windsurf/mcp_config.json"),displayPath:"~/.codeium/windsurf/mcp_config.json",hostKind:"claude-code-json",worktreeSupported:!1,writeStrategy:"manual-instructions",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".windsurf"))||ctx.exists(joinPath(ctx.cwd,".windsurfrules"))}},HOST_PLATFORM_ORDER=["claude-code","cursor","copilot-vscode","copilot-cli","codex","windsurf"]}});var LAUNCHER_CONFIG_TARGETS,DUPLICATE_REGISTRATION_GUIDANCE,REASON_TEXT,init_launcher_config_inspection=__esm({"src/launcher-config-inspection.ts"(){"use strict";init_mcp_host_targets();init_mcp_identity();LAUNCHER_CONFIG_TARGETS=getProjectJsonTargets().map(target=>({relPath:target.relPath,topLevelKey:hostAdapterForTarget(target).topLevelKey})),DUPLICATE_REGISTRATION_GUIDANCE=`duplicate Bridge registrations: this config carries both \`${MCP_SERVER_NAME}\` and \`${LEGACY_SERVER_NAMES.join("`, `")}\`. Confirm which registration you want to keep, then remove the unintended entry manually. Bridge will not choose for you.`,REASON_TEXT={"file-unreadable":"the file exists but could not be read","invalid-json":"the file is not valid JSON","root-not-object":"the JSON root is not an object","servers-not-object":"the servers section is not an object","entry-not-object":"the Bridge entry is not an object","no-package-token":`the Bridge launcher has no recognizable ${MCP_PACKAGE_NAME} token`,"version-range":"the launcher pin is a version range, which an automated repin must not rewrite","non-release-specifier":"the launcher pin is a dist-tag or channel, not an exact release","malformed-version":"the launcher pin is not a valid MAJOR.MINOR.PATCH release","pinned-ahead-of-target":"the launcher pin is newer than the target version and must not be downgraded","duplicate-registration":DUPLICATE_REGISTRATION_GUIDANCE}}});var init_mcp_registration_doctor=__esm({"src/mcp-registration-doctor.ts"(){"use strict";init_mcp_host_targets();init_mcp_identity();init_launcher_config_inspection()}});var init_commands_generated=__esm({"src/commands.generated.ts"(){"use strict"}});var init_command_assets_doctor=__esm({"src/command-assets-doctor.ts"(){"use strict";init_commands_generated()}});function summarizeClaudeReviewWorkflowDrift(classification){let{baseRef,defaultRef,workflowPath}=classification;return classification.state==="aligned"?`'${baseRef}' matches '${defaultRef}' for ${workflowPath}`:classification.state==="unverified"?`comparison unavailable (${classification.reason}) \u2014 advisory check failed open, ${workflowPath} lineage unknown`:`WARNING: '${baseRef}' carries a stale ${workflowPath} (differs from '${defaultRef}') \u2014 Claude review cannot run for pull requests based on it; reconcile '${baseRef}' with '${defaultRef}'`}var CLAUDE_REVIEW_WORKFLOW_RELPATH,CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION,init_claude_review_workflow_drift=__esm({"src/claude-review-workflow-drift.ts"(){"use strict";CLAUDE_REVIEW_WORKFLOW_RELPATH=".github/workflows/claude-review.yml";CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION=`Reconcile the base branch with the repository default branch \u2014 merge the default branch in, or sync ${CLAUDE_REVIEW_WORKFLOW_RELPATH} together with tests/pytest/commands/test_claude_review_workflow_prompt.py. See docs/claude/runbooks/claude-review-base-branch-drift.md.`}});var init_claude_review_workflow_drift_probe=__esm({"src/claude-review-workflow-drift-probe.ts"(){"use strict";init_claude_review_workflow_drift()}});var init_third_party_mcp_targets=__esm({"src/third-party-mcp-targets.ts"(){"use strict";init_credential_store()}});var init_mcp_provisioning=__esm({"src/mcp-provisioning.ts"(){"use strict";init_bridge_config();init_third_party_mcp_targets();init_mcp_server_invocation();init_mcp_host_targets();init_mcp_identity()}});function claudeMcpShadowingRemediationCommand(registrationKey){return`claude mcp remove ${registrationKey} -s local`}var CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV,CLAUDE_MCP_SHADOWING_OVERRIDE_WARNING,CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND,init_claude_user_config_doctor=__esm({"src/claude-user-config-doctor.ts"(){"use strict";init_mcp_registration_doctor();init_mcp_provisioning();init_mcp_identity();init_launcher_config_inspection();CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV="BAPI_CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING",CLAUDE_MCP_SHADOWING_OVERRIDE_WARNING=`Proceeding anyway because ${CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV} is set`;CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND=claudeMcpShadowingRemediationCommand(MCP_SERVER_NAME)}});var START_TICKETS_DOCTOR_COMMAND,CONDUCTOR_LIVE_SOURCE_PATH_ENV,CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV,GIT_INSTALL_HINTS,REVIEW_TICKETS_GIT_INSTALL_HINTS,RIPGREP_SHELL_FUNCTION_CAVEAT,RIPGREP_INSTALL_HINTS,CREDENTIAL_RESOLUTION_HINT,CLAUDE_MCP_SHADOWING_HINT,LIVE_SOURCE_GUARD_HINT,init_start_tickets_prereqs=__esm({"src/start-tickets-prereqs.ts"(){"use strict";init_credential_store();init_start_tickets_repo();init_mcp_registration_doctor();init_command_assets_doctor();init_mcp_identity();init_claude_review_workflow_drift();init_claude_review_workflow_drift_probe();init_claude_user_config_doctor();START_TICKETS_DOCTOR_COMMAND=`npx -y ${MCP_PACKAGE_NAME} doctor`,CONDUCTOR_LIVE_SOURCE_PATH_ENV="BAPI_CONDUCTOR_LIVE_SOURCE_PATH",CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV="BAPI_CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH",GIT_INSTALL_HINTS={darwin:"xcode-select --install (or brew install git)",linux:"Install git with your distro package manager, e.g. apt install git",win32:"Install Git for Windows: https://git-scm.com/download/win"},REVIEW_TICKETS_GIT_INSTALL_HINTS={darwin:`${GIT_INSTALL_HINTS.darwin} (or rerun review-tickets with --no-refresh-base to skip the fetch)`,linux:`${GIT_INSTALL_HINTS.linux} (or rerun review-tickets with --no-refresh-base to skip the fetch)`,win32:`${GIT_INSTALL_HINTS.win32} (or rerun review-tickets with --no-refresh-base to skip the fetch)`},RIPGREP_SHELL_FUNCTION_CAVEAT="a shell function/alias will not satisfy this check \u2014 ripgrep must be installed as a real PATH binary.",RIPGREP_INSTALL_HINTS={darwin:`brew install ripgrep (${RIPGREP_SHELL_FUNCTION_CAVEAT})`,linux:`Install ripgrep with your distro package manager, e.g. apt install ripgrep (${RIPGREP_SHELL_FUNCTION_CAVEAT})`,win32:`winget install BurntSushi.ripgrep.MSVC (${RIPGREP_SHELL_FUNCTION_CAVEAT})`},CREDENTIAL_RESOLUTION_HINT=`Rerun /install-bridge to persist the routing credential, set BAPI_API_KEY in the environment, or add it under "bapi:<repo_name>" in ~/.config/bridge/credentials.json. To migrate a key that only lives in .mcp.json / .cursor/mcp.json, run: npx -y ${MCP_PACKAGE_NAME} credentials migrate-agent-config --write-credentials.`,CLAUDE_MCP_SHADOWING_HINT=`Run \`${CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND}\` to clear the '${MCP_SERVER_NAME}' MCP registration in ~/.claude.json (use the matching scope if it is registered at user scope, or under the projects entry for this repository/worktree). This is ADVISORY: workers load MCP servers with --strict-mcp-config from their own worktree registration, so this entry does not reach a worker and does not block a conductor run.`,LIVE_SOURCE_GUARD_HINT=`Point ${CONDUCTOR_LIVE_SOURCE_PATH_ENV} at your live dev server's checkout ONLY when it differs from this conductor base checkout, or dispatch the conductor from a separate clone. To override the guard and dispatch anyway (not recommended), set ${CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV}=1.`}});import path6 from"path";function pathApiForPlatform(platform){return platform==="win32"?path6.win32:path6.posix}var init_worktree_core=__esm({"src/worktree-core.ts"(){"use strict";init_start_tickets_prereqs()}});var init_platform_escaping=__esm({"src/platform-escaping.ts"(){"use strict"}});var init_prompt=__esm({"src/agent-launchers/prompt.ts"(){"use strict"}});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)}var init_claude=__esm({"src/agent-launchers/claude.ts"(){"use strict";init_worktree_core();init_platform_escaping();init_prompt()}});var DEFAULT_PROBE_TIMEOUT_MS,init_types=__esm({"src/agent-capabilities/types.ts"(){"use strict";DEFAULT_PROBE_TIMEOUT_MS=9e4}});import{join as join2}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==="auto"?args.push("--permission-mode","auto"):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(join2(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_types()}});import{execFile}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=>{execFile(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 join3}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(join3(dir,DENY_TARGET_FILE),`${marker}
|
|
104
112
|
`)}async function seedDenySettings(ctx,dir,marker){await seedDenyTargetFile(ctx,dir,marker);let claudeDir=join3(dir,".claude");await ctx.deps.mkdir(claudeDir,{recursive:!0});let settings={permissions:{deny:[DENY_BASH_RULE]}};await ctx.deps.writeFile(join3(claudeDir,"settings.local.json"),`${JSON.stringify(settings,null,2)}
|
|
105
113
|
`)}async function seedDenyHook(ctx,dir,marker){await seedDenyTargetFile(ctx,dir,marker);let claudeDir=join3(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(join3(claudeDir,"settings.local.json"),`${JSON.stringify(settings,null,2)}
|
|
106
114
|
`)}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(`
|
|
107
|
-
`)}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(),permissionMode=opts?.permissionPosture==="auto"?"auto":opts?.permissionPosture==="accept_edits"?"acceptEdits":void 0,runOpts={skipPermissions:permissionMode===void 0,permissionMode,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 the probed permission posture (${opts?.permissionPosture??"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,{REQUIRED_DENY_ENFORCEMENT_POSTURES:()=>REQUIRED_DENY_ENFORCEMENT_POSTURES,runDenyEnforcementPreflight:()=>runDenyEnforcementPreflight});async function runDenyEnforcementPreflightForPosture(posture,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:posture});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 the ${posture??"skip_permissions"} posture; 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]}}}async function runDenyEnforcementPreflight(opts={}){if(opts.permissionPosture!==void 0)return runDenyEnforcementPreflightForPosture(opts.permissionPosture,opts);let postures=[],warnings=[],combined,degraded=!1;for(let posture of REQUIRED_DENY_ENFORCEMENT_POSTURES){let result=await runDenyEnforcementPreflightForPosture(posture,opts);postures.push({posture,enforced:result.enforced,layer:result.layer,...result.status===void 0?{}:{status:result.status},...result.detail===void 0?{}:{detail:result.detail}});for(let warning of result.warnings)warnings.includes(warning)||warnings.push(warning);if(result.degraded&&(degraded=!0),combined===void 0&&(combined=result),!result.enforced)return{enforced:!1,layer:result.layer,degraded:!0,warnings:[`Deny-layer enforcement is not verified for the '${posture}' permission posture.`,...warnings],...result.status===void 0?{}:{status:result.status},...result.detail===void 0?{}:{detail:result.detail},postures}}let primary=combined;return{enforced:!0,layer:primary.layer,degraded,warnings,...primary.status===void 0?{}:{status:primary.status},...primary.detail===void 0?{}:{detail:primary.detail},postures}}var REQUIRED_DENY_ENFORCEMENT_POSTURES,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();REQUIRED_DENY_ENFORCEMENT_POSTURES=["auto","skip_permissions"],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}});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,EPIC_RUN_STATUS_VALUES:()=>EPIC_RUN_STATUS_VALUES,adoptCurrentHeadAndUnparkTicket:()=>adoptCurrentHeadAndUnparkTicket,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,readEpicRunCompletionState:()=>readEpicRunCompletionState,reconcileShadowMerge:()=>reconcileShadowMerge,recordEpicDispatch:()=>recordEpicDispatch,remediateEpicTicket:()=>remediateEpicTicket,replaceEpicRunPolicy:()=>replaceEpicRunPolicy,resolveConductorBridgeApiAccess:()=>resolveConductorBridgeApiAccess,safeDiagnosticMessage:()=>safeDiagnosticMessage,stopEpicRun:()=>stopEpicRun,storeEpicPlan:()=>storeEpicPlan,transitionEpicDispatch:()=>transitionEpicDispatch,transitionJiraStatus:()=>transitionJiraStatus,triggerRepositoryParse:()=>triggerRepositoryParse,unparkEpicTicket:()=>unparkEpicTicket,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"):[],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={};errorCode&&(diagnostics.errorCode=boundedErrorPreview(errorCode)),message&&(diagnostics.bodyPreview=boundedErrorPreview(message));let rawCurrentRowVersion=detail&&typeof detail=="object"&&!Array.isArray(detail)?detail.current_row_version:record.current_row_version;return typeof rawCurrentRowVersion=="number"&&Number.isSafeInteger(rawCurrentRowVersion)&&rawCurrentRowVersion>=0&&(diagnostics.currentRowVersion=rawCurrentRowVersion),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)),typeof diagnostics.currentRowVersion=="number"&&(out.currentRowVersion=diagnostics.currentRowVersion),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)}function isEpicRunStatus(value){return typeof value=="string"&&EPIC_RUN_STATUS_VALUES.includes(value)}async function readEpicRunCompletionState(access,epicRunId,fetchImpl=globalThis.fetch){if(typeof epicRunId!="string"||epicRunId.trim().length===0)return{ok:!1,reason:"invalid-input"};let parsed;try{parsed=await fetchEpicRunState(access,epicRunId,fetchImpl)}catch(err){return err instanceof ConductorBridgeApiError?err.kind==="http"&&err.status===404?{ok:!1,reason:"not-found"}:err.kind==="unauthorized"?{ok:!1,reason:"unauthorized"}:err.kind==="timeout"?{ok:!1,reason:"timeout"}:err.kind==="server"?{ok:!1,reason:"server"}:err.kind==="network"?{ok:!1,reason:"network"}:err.kind==="invalid-input"?{ok:!1,reason:"invalid-input"}:{ok:!1,reason:"malformed"}:{ok:!1,reason:"network"}}if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return{ok:!1,reason:"malformed"};let epicRun=parsed.epic_run;if(!epicRun||typeof epicRun!="object"||Array.isArray(epicRun))return{ok:!1,reason:"malformed"};let status=epicRun.status;if(!isEpicRunStatus(status))return{ok:!1,reason:"malformed"};let policyJson=epicRun.policy_json,featureBranch;if(policyJson&&typeof policyJson=="object"&&!Array.isArray(policyJson)){let baseBranch=policyJson.base_branch;typeof baseBranch=="string"&&baseBranch.trim().length>0&&(featureBranch=baseBranch)}return{ok:!0,state:featureBranch?{status,featureBranch}:{status}}}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)}async function stopEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/stop`),body=JSON.stringify({repo_name:access.repoName,...request.reason!==void 0?{reason:request.reason}:{},...request.expectedGeneration!==void 0?{expected_generation:request.expectedGeneration}:{}});return await fetchConductorJsonPostWithTimeout(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 postUnparkLikeRequest(url,headers,body,fetchImpl){try{let parsed=await fetchConductorJsonPostWithTimeout(url,headers,body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseAdvanceEpicTicketStatusResult(parsed)}catch(err){if(err instanceof ConductorBridgeApiError&&err.status===400&&typeof err.currentRowVersion=="number")return parseAdvanceEpicTicketStatusResult({ok:!1,kind:"cas-conflict",current_row_version:err.currentRowVersion});throw err}}async function unparkEpicTicket(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/unpark`),body=JSON.stringify({repo_name:access.repoName,expected_row_version:request.expectedRowVersion,...request.idempotencyKey!==void 0?{idempotency_key:request.idempotencyKey}:{},...request.reason!==void 0?{reason:request.reason}:{}});return postUnparkLikeRequest(url,conductorPostHeaders(access),body,fetchImpl)}async function adoptCurrentHeadAndUnparkTicket(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/adopt-current-head-and-unpark`),body=JSON.stringify({repo_name:access.repoName,expected_row_version:request.expectedRowVersion,...request.idempotencyKey!==void 0?{idempotency_key:request.idempotencyKey}:{},...request.reason!==void 0?{reason:request.reason}:{}});return postUnparkLikeRequest(url,conductorPostHeaders(access),body,fetchImpl)}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,deadlineExpired:obj.deadline_expired===!0,blockedAdvanceReason:typeof obj.blocked_advance_reason=="string"&&obj.blocked_advance_reason.length>0?obj.blocked_advance_reason: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),request.trackedPaths!==void 0&&(body.tracked_paths=request.trackedPaths);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,valid=p.valid;if(typeof valid!="boolean"||typeof planHash!="string"||planHash.trim()===""||typeof serializationEnabled!="boolean"||typeof insertedEdges!="number"||!Number.isSafeInteger(insertedEdges)||insertedEdges<0)throw new ConductorBridgeApiError("server");let rejections=parsePlanLintRejections(p.rejections),notices=parsePlanLintNotices(p.notices);if(!valid&&rejections.length===0)throw new ConductorBridgeApiError("server");return{valid,rejections,notices,evaluationComplete:typeof p.evaluation_complete=="boolean"?p.evaluation_complete:!0,planHash,serializationEnabled,insertedEdges,overlappingPairsFound:safeCount(p.overlapping_pairs_found),undeclaredNodes:safeCount(p.undeclared_nodes),undeclaredPairsSkipped:safeCount(p.undeclared_pairs_skipped),coverageScope:typeof p.coverage_scope=="string"&&p.coverage_scope.trim()!==""?p.coverage_scope:"unreported"}}function parsePlanLintRejections(value){if(!Array.isArray(value))return[];let out=[];for(let raw of value){if(!raw||typeof raw!="object"||Array.isArray(raw))continue;let entry=raw,reasonCode=entry.reason_code,explanation=entry.explanation;if(typeof reasonCode!="string"||reasonCode.trim()===""||typeof explanation!="string"||explanation.trim()==="")continue;let rejection={reasonCode,explanation,ticketKeys:safeStringArray(entry.ticket_keys)};typeof entry.path=="string"&&entry.path!==""&&(rejection.path=entry.path),typeof entry.migration_id=="string"&&entry.migration_id!==""&&(rejection.migrationId=entry.migration_id),out.push(rejection)}return out}function parsePlanLintNotices(value){if(!Array.isArray(value))return[];let out=[];for(let raw of value){if(!raw||typeof raw!="object"||Array.isArray(raw))continue;let entry=raw,noticeCode=entry.notice_code,explanation=entry.explanation;typeof noticeCode!="string"||noticeCode.trim()===""||typeof explanation!="string"||explanation.trim()===""||out.push({noticeCode,explanation,ticketKeys:safeStringArray(entry.ticket_keys),paths:safeStringArray(entry.paths)})}return out}function safeStringArray(value){return Array.isArray(value)?value.filter(v=>typeof v=="string"&&v!==""):[]}function safeCount(value){return typeof value=="number"&&Number.isSafeInteger(value)&&value>=0?value:0}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`),storeBody={repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob,plan_hash:request.planHash};request.trackedPaths!==void 0&&(storeBody.tracked_paths=request.trackedPaths);let body=JSON.stringify(storeBody);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,EPIC_RUN_STATUS_VALUES,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;currentRowVersion;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),typeof diagnostics?.currentRowVersion=="number"&&(this.currentRowVersion=diagnostics.currentRowVersion)}};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";EPIC_RUN_STATUS_VALUES=["planning","pending_approval","active","blocked","abandoned","done"];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 createHash3}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=createHash3("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 createHash4}from"node:crypto";function extractMergeActionIdentityFromGateEvent(event){return getMergeIdentity(event)}function makeMergeEventId(eventType,actionKey){let h=createHash4("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
|
|
115
|
+
`)}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(),permissionMode=opts?.permissionPosture==="auto"?"auto":opts?.permissionPosture==="accept_edits"?"acceptEdits":void 0,runOpts={skipPermissions:permissionMode===void 0,permissionMode,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 the probed permission posture (${opts?.permissionPosture??"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,{REQUIRED_DENY_ENFORCEMENT_POSTURES:()=>REQUIRED_DENY_ENFORCEMENT_POSTURES,runDenyEnforcementPreflight:()=>runDenyEnforcementPreflight});async function runDenyEnforcementPreflightForPosture(posture,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:posture});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 the ${posture??"skip_permissions"} posture; 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]}}}async function runDenyEnforcementPreflight(opts={}){if(opts.permissionPosture!==void 0)return runDenyEnforcementPreflightForPosture(opts.permissionPosture,opts);let postures=[],warnings=[],combined,degraded=!1;for(let posture of REQUIRED_DENY_ENFORCEMENT_POSTURES){let result=await runDenyEnforcementPreflightForPosture(posture,opts);postures.push({posture,enforced:result.enforced,layer:result.layer,...result.status===void 0?{}:{status:result.status},...result.detail===void 0?{}:{detail:result.detail}});for(let warning of result.warnings)warnings.includes(warning)||warnings.push(warning);if(result.degraded&&(degraded=!0),combined===void 0&&(combined=result),!result.enforced)return{enforced:!1,layer:result.layer,degraded:!0,warnings:[`Deny-layer enforcement is not verified for the '${posture}' permission posture.`,...warnings],...result.status===void 0?{}:{status:result.status},...result.detail===void 0?{}:{detail:result.detail},postures}}let primary=combined;return{enforced:!0,layer:primary.layer,degraded,warnings,...primary.status===void 0?{}:{status:primary.status},...primary.detail===void 0?{}:{detail:primary.detail},postures}}var REQUIRED_DENY_ENFORCEMENT_POSTURES,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();REQUIRED_DENY_ENFORCEMENT_POSTURES=["auto","skip_permissions"],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."}});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";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,outcomes=[binding_loads?{id:"native-ledger",label:"Native ledger binding",status:"pass",detail:`${nativeLoad.module} loads (NODE_MODULE_VERSION ${nativeLoad.node_modules_abi})`}:{id:"native-ledger",label:"Native ledger binding",status:"warn",detail:`${nativeLoad.module} did not load (NODE_MODULE_VERSION ${nativeLoad.node_modules_abi}, failure: ${failure_kind})`,remediation:NATIVE_LEDGER_REMEDIATION},invocation.form==="absolute-build-path"?{id:"mcp-registration-form",label:"Worker MCP registration form",status:"pass",detail:"resolves an on-disk build entry"}:{id:"mcp-registration-form",label:"Worker MCP registration form",status:"warn",detail:`registration form is \`${invocation.form}\` \u2014 the npm-channel fallback`,remediation:MCP_REGISTRATION_FORM_REMEDIATION},engines_node===null?{id:"node-engine",label:"Expected Node engine",status:"warn",detail:"package.json engines.node could not be read",remediation:NODE_ENGINE_REMEDIATION}:{id:"node-engine",label:"Expected Node engine",status:"pass",detail:`expected ${engines_node}; running ${process.version}`}];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,outcomes}}async function collectConductorNativeLedger(deps={}){let ledger=await(deps.doctorLedger??doctorConductorLedger)(),native_ledger=await inspectNativeLedger(ledger.native_load,deps);return{ledger,native_ledger}}function describeNativeLedgerAvailability(inspection){return inspection.binding_loads?{status:"available"}:{status:"degraded",module:inspection.module,nodeModulesAbi:inspection.node_modules_abi,failureKind:inspection.failure_kind}}function inspectMcpProfile(env){let raw=env.BRIDGE_MCP_PROFILE,raw_profile=raw===void 0?MCP_PROFILE_UNSET:raw,groups=resolveProfiles(raw),active_groups=Array.from(groups),conductor_context_detected=env.BAPI_CONDUCTOR_ENABLED==="1"||env.BAPI_CONDUCTOR_ENABLED==="true",degraded=conductor_context_detected&&!groups.has("conductor"),warnings=[];degraded&&warnings.push(`BRIDGE_MCP_PROFILE is ${raw_profile} (active groups: ${active_groups.join(", ")}) but a conductor context is active. ADD \`conductor\` to BRIDGE_MCP_PROFILE (e.g. \`${raw_profile===MCP_PROFILE_UNSET?"conductor":`${raw_profile},conductor`}\`) \u2014 do NOT replace the value, which would drop the worker's other groups. Without it the conductor/event/supervisor tools are not registered.`);let outcomes=[degraded?{id:"mcp-profile",label:"MCP conductor profile",status:"warn",detail:`a conductor context is active but the resolved groups omit \`conductor\` (active: ${active_groups.join(", ")})`,remediation:MCP_PROFILE_REMEDIATION}:{id:"mcp-profile",label:"MCP conductor profile",status:"pass",detail:conductor_context_detected?`conductor context active; resolved groups: ${active_groups.join(", ")}`:`no conductor context detected; resolved groups: ${active_groups.join(", ")}`}];return{raw_profile,active_groups,conductor_context_detected,degraded,warnings,outcomes}}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,outcomes:[gh_available?{id:"gh-cli",label:"GitHub CLI availability",status:"pass",detail:"`gh --version` succeeded"}:{id:"gh-cli",label:"GitHub CLI availability",status:"warn",detail:"`gh` is not installed or not on PATH",remediation:GH_CLI_REMEDIATION},gh_available?gh_authed?{id:"gh-auth",label:"GitHub CLI authentication",status:"pass",detail:"`gh auth status` reports an authenticated account"}:{id:"gh-auth",label:"GitHub CLI authentication",status:"warn",detail:"`gh` is installed but `gh auth status` failed",remediation:GH_AUTH_REMEDIATION}:{id:"gh-auth",label:"GitHub CLI authentication",status:"skip",detail:GH_AUTH_SKIPPED_DETAIL,remediation:GH_CLI_REMEDIATION}]}}async function buildConductorDoctorReport(deps={}){let inspectHooks=deps.inspectHooks??inspectConductorGitHooks,mcp_profile=inspectMcpProfile(deps.env??process.env),{ledger,native_ledger}=await collectConductorNativeLedger(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),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{return{enforced:!1,layer:"none",degraded:!0,warnings:["Deny-layer enforcement inspection failed: the probe could not be run.","The executor claim loop MUST refuse to claim jobs until the deny layer is enforced."]}}}function formatConductorDoctorReport(report){let{ledger,git_hooks,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} bin=${hook.embedded_bin_path??"n/a"} bin_is_file=${hook.embedded_bin_is_file}`);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 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 ${MCP_PACKAGE_NAME} 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(`raw profile: ${mcp_profile.raw_profile}`),lines.push(`active groups: ${mcp_profile.active_groups.join(", ")} ${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(`
|
|
116
|
+
`)}function outcomesOf(inspection){return Array.isArray(inspection?.outcomes)?inspection?.outcomes:[]}function ledgerOutcome(report){let ledger=report?.ledger;return ledger===void 0?null:ledger.degraded?{id:"ledger",label:"Conductor event ledger",status:"warn",detail:`local ledger degraded (schema present: ${ledger.schema_present}, permissions ok: ${ledger.directory_permissions_ok&&ledger.database_permissions_ok})`,remediation:CONDUCTOR_LEDGER_REMEDIATION}:{id:"ledger",label:"Conductor event ledger",status:"pass",detail:`local ledger healthy (schema version ${ledger.user_version??"unknown"})`}}function gitHooksOutcome(report){let hooks=report?.git_hooks;if(hooks===void 0)return null;if(!hooks.is_worktree)return{id:"git-hooks",label:"Conductor git hooks",status:"skip",detail:"not a git worktree, so no managed conductor hooks apply"};let rendered=hooks.hooks.map(hook=>`${hook.name}=${hook.exists&&hook.managed_block_present}`).join(", ");return hooks.degraded?{id:"git-hooks",label:"Conductor git hooks",status:"warn",detail:`managed hooks installed: ${rendered}`,remediation:CONDUCTOR_GIT_HOOKS_REMEDIATION}:{id:"git-hooks",label:"Conductor git hooks",status:"pass",detail:`managed hooks installed: ${rendered}`}}function denyEnforcementOutcome(report){let deny=report?.deny_enforcement;return deny===void 0?null:deny.layer==="none"&&!deny.enforced&&deny.status==="skip"?{id:"deny-enforcement",label:"Deny-layer enforcement",status:"skip",detail:"not probed \u2014 enforcement is UNVERIFIED, which is not the same as unenforced",remediation:DENY_ENFORCEMENT_SKIP_REMEDIATION}:deny.enforced&&!deny.degraded?{id:"deny-enforcement",label:"Deny-layer enforcement",status:"pass",detail:`enforced by the ${deny.layer} layer`}:{id:"deny-enforcement",label:"Deny-layer enforcement",status:"fail",detail:deny.enforced?`enforced by the ${deny.layer} layer, but degraded`:"the denied call was not rejected by any layer",remediation:"restore the settings-deny layer before running a conductor worker; the executor claim loop refuses to claim jobs while enforcement is missing."}}function claudeLoginOutcome(report){let login=report?.claude_login;return login===void 0?null:login.detected?{id:"claude-login",label:"Claude login",status:"pass",detail:"a local Claude login marker was detected"}:{id:"claude-login",label:"Claude login",status:"warn",detail:"no local Claude login marker was detected",remediation:CONDUCTOR_CLAUDE_LOGIN_REMEDIATION}}function mapConductorDoctorReportToReadinessChecks(report){let collected=new Map,record=outcome=>{outcome&&!collected.has(outcome.id)&&collected.set(outcome.id,outcome)};record(ledgerOutcome(report)),record(gitHooksOutcome(report));for(let outcome of outcomesOf(report?.mcp_profile))record(outcome);for(let outcome of outcomesOf(report?.local_merge))record(outcome);for(let outcome of outcomesOf(report?.native_ledger))record(outcome);return record(denyEnforcementOutcome(report)),record(claudeLoginOutcome(report)),CONDUCTOR_READINESS_DESCRIPTORS.map(({id,label})=>{let outcome=collected.get(id);return outcome?createReadinessCheckSafely({id:`conductor.${id}`,source:"conductor",label:outcome.label||label,status:outcome.status,...outcome.detail?{detail:outcome.detail}:{},...outcome.status==="fail"?{remediation:outcome.remediation??CONDUCTOR_UNCOLLECTED_REMEDIATION}:outcome.status!=="pass"&&outcome.remediation?{remediation:outcome.remediation}:{}}):createReadinessCheck({id:`conductor.${id}`,source:"conductor",label,status:"fail",detail:CONDUCTOR_UNCOLLECTED_DETAIL,remediation:CONDUCTOR_UNCOLLECTED_REMEDIATION})})}var MCP_PROFILE_REMEDIATION,GH_CLI_REMEDIATION,GH_AUTH_REMEDIATION,GH_AUTH_SKIPPED_DETAIL,NATIVE_LEDGER_REMEDIATION,MCP_REGISTRATION_FORM_REMEDIATION,NODE_ENGINE_REMEDIATION,DENY_ENFORCEMENT_SKIP_REMEDIATION,MCP_PROFILE_UNSET,CONDUCTOR_READINESS_DESCRIPTORS,CONDUCTOR_LEDGER_REMEDIATION,CONDUCTOR_GIT_HOOKS_REMEDIATION,CONDUCTOR_CLAUDE_LOGIN_REMEDIATION,CONDUCTOR_UNCOLLECTED_DETAIL,CONDUCTOR_UNCOLLECTED_REMEDIATION,init_doctor=__esm({"src/conductor/doctor.ts"(){"use strict";init_store();init_claude_login();init_git_hooks();init_mcp_server_invocation();init_mcp_identity();init_mcp_profile();init_readiness_check();MCP_PROFILE_REMEDIATION="ADD `conductor` to BRIDGE_MCP_PROFILE (comma-separated) \u2014 do NOT replace the existing value, which would drop the worker's other tool groups. Without it the conductor/event/supervisor tools are not registered.",GH_CLI_REMEDIATION="install the GitHub CLI (`gh`) and put it on PATH; conductor-driven merges run under this host's own `gh` auth because the GitHub App token is `contents: read` and cannot merge.",GH_AUTH_REMEDIATION="run `gh auth login` to grant the conductor merge permission; otherwise local merge emits merge.failed/skip rather than merging.",GH_AUTH_SKIPPED_DETAIL="not tested \u2014 `gh` is not installed, so `gh auth status` was never run",NATIVE_LEDGER_REMEDIATION="`better-sqlite3` is an optionalDependency npm silently skips on a build failure \u2014 reinstall it for this Node runtime to restore local conductor observability. Diagnostic only: nothing is installed or rebuilt for you.",MCP_REGISTRATION_FORM_REMEDIATION="build this package so an on-disk entry resolves (`npm run build` in mcp_server), or accept that worker MCP registration depends on the published package being reachable.",NODE_ENGINE_REMEDIATION="reinstall the package so its package.json is readable; until then the expected Node version is unknown and a Node/ABI skew cannot be diagnosed.",DENY_ENFORCEMENT_SKIP_REMEDIATION="run `conductor doctor` (without --no-deny-probe) to execute the owning deny-enforcement preflight; `conductor readiness` never spawns that probe itself.",MCP_PROFILE_UNSET="(unset)";CONDUCTOR_READINESS_DESCRIPTORS=[{id:"ledger",label:"Conductor event ledger"},{id:"git-hooks",label:"Conductor git hooks"},{id:"mcp-profile",label:"MCP conductor profile"},{id:"gh-cli",label:"GitHub CLI availability"},{id:"gh-auth",label:"GitHub CLI authentication"},{id:"native-ledger",label:"Native ledger binding"},{id:"mcp-registration-form",label:"Worker MCP registration form"},{id:"node-engine",label:"Expected Node engine"},{id:"deny-enforcement",label:"Deny-layer enforcement"},{id:"claude-login",label:"Claude login"}],CONDUCTOR_LEDGER_REMEDIATION="run `conductor doctor` for the ledger detail, then re-create the local ledger directory with owner-only permissions; the ledger is local observability and never blocks a run.",CONDUCTOR_GIT_HOOKS_REMEDIATION="run `conductor install-git-hooks` to install the managed post-commit and reference-transaction hooks; they are local, opportunistic, and bypassable.",CONDUCTOR_CLAUDE_LOGIN_REMEDIATION="run `claude login` on the host that will run conductor workers; Bridge stores no Anthropic credential and can only advise here.",CONDUCTOR_UNCOLLECTED_DETAIL="not collected \u2014 the conductor doctor did not report this inspection",CONDUCTOR_UNCOLLECTED_REMEDIATION="run `conductor doctor` directly to collect this inspection; its state is unknown, not healthy."}});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}});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,EPIC_RUN_STATUS_VALUES:()=>EPIC_RUN_STATUS_VALUES,adoptCurrentHeadAndUnparkTicket:()=>adoptCurrentHeadAndUnparkTicket,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,fetchExplainRun:()=>fetchExplainRun,fetchParseStatus:()=>fetchParseStatus,fetchPrReviewStatus:()=>fetchPrReviewStatus,fetchShadowDispatchFreshness:()=>fetchShadowDispatchFreshness,getEpicPlan:()=>getEpicPlan,mergePullRequestForGate:()=>mergePullRequestForGate,parseConductorReadinessResponse:()=>parseConductorReadinessResponse,parseConductorSupervisorBootstrapResponse:()=>parseConductorSupervisorBootstrapResponse,pollCiChecksForCommit:()=>pollCiChecksForCommit,readEpicRunCompletionState:()=>readEpicRunCompletionState,reconcileShadowMerge:()=>reconcileShadowMerge,recordEpicDispatch:()=>recordEpicDispatch,remediateEpicTicket:()=>remediateEpicTicket,replaceEpicRunPolicy:()=>replaceEpicRunPolicy,resolveConductorBridgeApiAccess:()=>resolveConductorBridgeApiAccess,safeDiagnosticMessage:()=>safeDiagnosticMessage,stopEpicRun:()=>stopEpicRun,storeEpicPlan:()=>storeEpicPlan,transitionEpicDispatch:()=>transitionEpicDispatch,transitionJiraStatus:()=>transitionJiraStatus,triggerRepositoryParse:()=>triggerRepositoryParse,unparkEpicTicket:()=>unparkEpicTicket,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"):[],path14=(parts[0]==="body"?parts.slice(1):parts).slice(0,CONDUCTOR_VALIDATION_LOC_MAX_PARTS).join(".");return path14?`${path14}: ${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={};errorCode&&(diagnostics.errorCode=boundedErrorPreview(errorCode)),message&&(diagnostics.bodyPreview=boundedErrorPreview(message));let rawCurrentRowVersion=detail&&typeof detail=="object"&&!Array.isArray(detail)?detail.current_row_version:record.current_row_version;return typeof rawCurrentRowVersion=="number"&&Number.isSafeInteger(rawCurrentRowVersion)&&rawCurrentRowVersion>=0&&(diagnostics.currentRowVersion=rawCurrentRowVersion),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)),typeof diagnostics.currentRowVersion=="number"&&(out.currentRowVersion=diagnostics.currentRowVersion),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(/\/+$/,""),path14=apiPath.startsWith("/")?apiPath:`/${apiPath}`;return new URL(`${trimmed}${path14}`).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 fetchExplainRun(access,epicRunId,ticketKey,fetchImpl=globalThis.fetch){requireNonEmptyString(epicRunId);let apiPath=`${epicRunApiPath(epicRunId)}/explain`;ticketKey!==void 0&&(requireNonEmptyString(ticketKey),requireNoSlashPathSegment(ticketKey),apiPath=`${epicRunApiPath(epicRunId)}/tickets/${encodeURIComponent(ticketKey)}/explain`);let url=buildConductorJiraUrl(access.baseUrl,apiPath,{repo_name:access.repoName});return fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function isEpicRunStatus(value){return typeof value=="string"&&EPIC_RUN_STATUS_VALUES.includes(value)}async function readEpicRunCompletionState(access,epicRunId,fetchImpl=globalThis.fetch){if(typeof epicRunId!="string"||epicRunId.trim().length===0)return{ok:!1,reason:"invalid-input"};let parsed;try{parsed=await fetchEpicRunState(access,epicRunId,fetchImpl)}catch(err){return err instanceof ConductorBridgeApiError?err.kind==="http"&&err.status===404?{ok:!1,reason:"not-found"}:err.kind==="unauthorized"?{ok:!1,reason:"unauthorized"}:err.kind==="timeout"?{ok:!1,reason:"timeout"}:err.kind==="server"?{ok:!1,reason:"server"}:err.kind==="network"?{ok:!1,reason:"network"}:err.kind==="invalid-input"?{ok:!1,reason:"invalid-input"}:{ok:!1,reason:"malformed"}:{ok:!1,reason:"network"}}if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return{ok:!1,reason:"malformed"};let epicRun=parsed.epic_run;if(!epicRun||typeof epicRun!="object"||Array.isArray(epicRun))return{ok:!1,reason:"malformed"};let status=epicRun.status;if(!isEpicRunStatus(status))return{ok:!1,reason:"malformed"};let policyJson=epicRun.policy_json,featureBranch;if(policyJson&&typeof policyJson=="object"&&!Array.isArray(policyJson)){let baseBranch=policyJson.base_branch;typeof baseBranch=="string"&&baseBranch.trim().length>0&&(featureBranch=baseBranch)}return{ok:!0,state:featureBranch?{status,featureBranch}:{status}}}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)}async function stopEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/stop`),body=JSON.stringify({repo_name:access.repoName,...request.reason!==void 0?{reason:request.reason}:{},...request.expectedGeneration!==void 0?{expected_generation:request.expectedGeneration}:{}});return await fetchConductorJsonPostWithTimeout(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 postUnparkLikeRequest(url,headers,body,fetchImpl){try{let parsed=await fetchConductorJsonPostWithTimeout(url,headers,body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseAdvanceEpicTicketStatusResult(parsed)}catch(err){if(err instanceof ConductorBridgeApiError&&err.status===400&&typeof err.currentRowVersion=="number")return parseAdvanceEpicTicketStatusResult({ok:!1,kind:"cas-conflict",current_row_version:err.currentRowVersion});throw err}}async function unparkEpicTicket(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/unpark`),body=JSON.stringify({repo_name:access.repoName,expected_row_version:request.expectedRowVersion,...request.idempotencyKey!==void 0?{idempotency_key:request.idempotencyKey}:{},...request.reason!==void 0?{reason:request.reason}:{}});return postUnparkLikeRequest(url,conductorPostHeaders(access),body,fetchImpl)}async function adoptCurrentHeadAndUnparkTicket(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/adopt-current-head-and-unpark`),body=JSON.stringify({repo_name:access.repoName,expected_row_version:request.expectedRowVersion,...request.idempotencyKey!==void 0?{idempotency_key:request.idempotencyKey}:{},...request.reason!==void 0?{reason:request.reason}:{}});return postUnparkLikeRequest(url,conductorPostHeaders(access),body,fetchImpl)}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 path14=epicDispatchTransitionApiPath(request.dispatchKey,request.nextStatus),url=buildConductorJiraUrl(access.baseUrl,path14),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,deadlineExpired:obj.deadline_expired===!0,blockedAdvanceReason:typeof obj.blocked_advance_reason=="string"&&obj.blocked_advance_reason.length>0?obj.blocked_advance_reason: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),request.trackedPaths!==void 0&&(body.tracked_paths=request.trackedPaths);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,valid=p.valid;if(typeof valid!="boolean"||typeof planHash!="string"||planHash.trim()===""||typeof serializationEnabled!="boolean"||typeof insertedEdges!="number"||!Number.isSafeInteger(insertedEdges)||insertedEdges<0)throw new ConductorBridgeApiError("server");let rejections=parsePlanLintRejections(p.rejections),notices=parsePlanLintNotices(p.notices);if(!valid&&rejections.length===0)throw new ConductorBridgeApiError("server");return{valid,rejections,notices,evaluationComplete:typeof p.evaluation_complete=="boolean"?p.evaluation_complete:!0,planHash,serializationEnabled,insertedEdges,overlappingPairsFound:safeCount(p.overlapping_pairs_found),undeclaredNodes:safeCount(p.undeclared_nodes),undeclaredPairsSkipped:safeCount(p.undeclared_pairs_skipped),coverageScope:typeof p.coverage_scope=="string"&&p.coverage_scope.trim()!==""?p.coverage_scope:"unreported"}}function parsePlanLintRejections(value){if(!Array.isArray(value))return[];let out=[];for(let raw of value){if(!raw||typeof raw!="object"||Array.isArray(raw))continue;let entry=raw,reasonCode=entry.reason_code,explanation=entry.explanation;if(typeof reasonCode!="string"||reasonCode.trim()===""||typeof explanation!="string"||explanation.trim()==="")continue;let rejection={reasonCode,explanation,ticketKeys:safeStringArray(entry.ticket_keys)};typeof entry.path=="string"&&entry.path!==""&&(rejection.path=entry.path),typeof entry.migration_id=="string"&&entry.migration_id!==""&&(rejection.migrationId=entry.migration_id),out.push(rejection)}return out}function parsePlanLintNotices(value){if(!Array.isArray(value))return[];let out=[];for(let raw of value){if(!raw||typeof raw!="object"||Array.isArray(raw))continue;let entry=raw,noticeCode=entry.notice_code,explanation=entry.explanation;typeof noticeCode!="string"||noticeCode.trim()===""||typeof explanation!="string"||explanation.trim()===""||out.push({noticeCode,explanation,ticketKeys:safeStringArray(entry.ticket_keys),paths:safeStringArray(entry.paths)})}return out}function safeStringArray(value){return Array.isArray(value)?value.filter(v=>typeof v=="string"&&v!==""):[]}function safeCount(value){return typeof value=="number"&&Number.isSafeInteger(value)&&value>=0?value:0}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`),storeBody={repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob,plan_hash:request.planHash};request.trackedPaths!==void 0&&(storeBody.tracked_paths=request.trackedPaths);let body=JSON.stringify(storeBody);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")},review_workflow:parseReviewWorkflow(root),conductor_ci_workflow:parseConductorCiWorkflow(root)}}function parseReviewWorkflow(body){let raw=body.review_workflow;if(raw==null)return null;let o=requireObject(raw);return{probe_succeeded:requireBool(o,"probe_succeeded"),workflow_present:requireBool(o,"workflow_present"),emits_run_id:requireBool(o,"emits_run_id"),emits_reviewed_sha:requireBool(o,"emits_reviewed_sha")}}function parseConductorCiWorkflow(body){let raw=body.conductor_ci_workflow;if(raw==null)return null;let o=requireObject(raw);return{probe_succeeded:requireBool(o,"probe_succeeded"),workflow_present:requireBool(o,"workflow_present"),migration_guard_present:requireBool(o,"migration_guard_present")}}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,EPIC_RUN_STATUS_VALUES,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;currentRowVersion;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),typeof diagnostics?.currentRowVersion=="number"&&(this.currentRowVersion=diagnostics.currentRowVersion)}};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";EPIC_RUN_STATUS_VALUES=["planning","pending_approval","active","blocked","abandoned","done"];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 createHash3}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=createHash3("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 createHash4}from"node:crypto";function extractMergeActionIdentityFromGateEvent(event){return getMergeIdentity(event)}function makeMergeEventId(eventType,actionKey){let h=createHash4("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
|
|
108
117
|
WHERE type = ?
|
|
109
118
|
AND json_extract(data_json, '$.details.action_key') = ?
|
|
110
119
|
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}
|
|
111
120
|
`)),errorLog=deps.errorLog??(m=>process.stderr.write(`${m}
|
|
112
|
-
`)),waitForEvent=deps.waitForEvent??waitForConductorEvent,getSnapshot=deps.getSnapshot??getSupervisorSnapshot,upsertProjection=deps.upsertProjection??upsertSupervisorProjection,emitAssessment=deps.emitAssessment??emitSupervisorAssessmentIfNew,sendMessage=deps.sendWorkerMessage??sendWorkerMessage,resolveBridgeAccess=deps.resolveBridgeAccess??(()=>resolveConductorBridgeApiAccess()),processMerge=deps.processMerge??processGateMetMerge,dispatchNotification=deps.dispatchNotification??dispatchSupervisorNotification,bridgeAccess=null,bridgeAccessResolved=!1,processGateMetMerges=async events=>{let eligible=events.filter(e=>extractMergeActionIdentityFromGateEvent(e)!==null);if(eligible.length!==0){if(!bridgeAccessResolved){bridgeAccessResolved=!0;try{let result=await resolveBridgeAccess();bridgeAccess=result.ok?result.access:null,result.ok||errorLog(`[supervisor] run=${runId} auto-merge disabled: ${result.kind}`)}catch{bridgeAccess=null}}if(bridgeAccess)for(let event of eligible)try{await processMerge(bridgeAccess,event)}catch{}}},persist=async state2=>{try{await upsertProjection(toSupervisorProjectionInput(state2))}catch{}},state;try{let snapshot=await getSnapshot(runId);state=hydrateSupervisorRunStateFromSnapshot(snapshot,runId,config,now())}catch{return{run_id:runId,status:"failed",exit_code:2,reason:"supervisor failed to load initial snapshot",last_seq:0,worker_count:0}}let sinceSeq=state.last_seq>0?state.last_seq+1:1,iterationCap=Math.max(1e3,Math.ceil(config.global_timeout_ms/Math.max(1,config.wake_interval_ms))+16);try{applySupervisorHousekeeping(state,config,now());for(let iteration=0;iteration<iterationCap;iteration+=1){if(isSupervisorRunTerminal(state))return state.status=terminalStatus(state),await persist(state),log(`[supervisor] run=${runId} complete status=${state.status} workers=${Object.keys(state.workers).length}`),{run_id:runId,status:state.status,exit_code:0,reason:"all workers terminal",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length};if(hasSupervisorGlobalTimeoutElapsed(state,now()))return state.status="timed_out",await persist(state),errorLog(`[supervisor] run=${runId} global timeout elapsed`),{run_id:runId,status:"timed_out",exit_code:2,reason:"global timeout elapsed",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length};let waitResult=await waitForEvent({since_seq:sinceSeq,filter:{run_id:runId},data_mode:"full",timeout_ms:config.wake_interval_ms,limit:config.poll_limit});if(waitResult.events.length>0){let sorted=[...waitResult.events].sort((a,b)=>a.seq-b.seq);for(let event of sorted)applyConductorEventToSupervisorState(state,event,now());sinceSeq=sorted[sorted.length-1].seq+1,await processGateMetMerges(sorted)}applySupervisorHousekeeping(state,config,now()),await processEscalations(state,config,{emitAssessment,sendWorkerMessage:sendMessage,log,now,dispatchNotification}),await persist(state)}return state.status="timed_out",await persist(state),{run_id:runId,status:"timed_out",exit_code:2,reason:"supervisor iteration cap reached",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length}}catch{state.status="failed";try{await upsertProjection(toSupervisorProjectionInput(state))}catch{}return errorLog(`[supervisor] run=${runId} failed unexpectedly`),{run_id:runId,status:"failed",exit_code:2,reason:"supervisor failed unexpectedly",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length}}}var init_supervisor_runtime=__esm({"src/conductor/supervisor-runtime.ts"(){"use strict";init_store();init_supervisor_ledger();init_supervisor_message_relay();init_supervisor_config();init_supervisor_state();init_supervisor_escalation();init_supervisor_ledger();init_bridge_api_client();init_merge_ledger();init_supervisor_merge();init_supervisor_notification();init_errors()}});var recovery_operations_exports={};__export(recovery_operations_exports,{RECOVERY_TICKET_RETRY_LIMIT:()=>RECOVERY_TICKET_RETRY_LIMIT,abandonEpicRunRecovery:()=>abandonEpicRunRecovery,adoptCurrentHeadAndUnparkWithRetry:()=>adoptCurrentHeadAndUnparkWithRetry,stopEpicRunRecovery:()=>stopEpicRunRecovery,unparkEpicTicketWithRetry:()=>unparkEpicTicketWithRetry});import{randomUUID as randomUUID2}from"crypto";async function stopEpicRunRecovery(access,options){try{return(await stopEpicRun(access,{epicRunId:options.epicRunId,reason:options.reason})).committed?{ok:!0,kind:"committed",epicRunId:options.epicRunId}:{ok:!0,kind:"already-stopped",epicRunId:options.epicRunId}}catch(err){if(err instanceof ConductorBridgeApiError&&err.status===409&&err.errorCode==="RUN_TERMINAL"){let status=await readTerminalRunStatus(access,options.epicRunId);return{ok:!1,kind:"terminal",epicRunId:options.epicRunId,status}}return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,message:safeDiagnosticMessage(err,"stop request failed")}}}async function readTerminalRunStatus(access,epicRunId){try{return(await fetchEpicRunState(access,epicRunId)).epic_run.status}catch{return"terminal"}}async function abandonEpicRunRecovery(access,options){let state;try{state=await fetchEpicRunState(access,options.epicRunId)}catch(err){return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,message:safeDiagnosticMessage(err,"could not read run state")}}let currentStatus=state.epic_run.status;if(currentStatus==="abandoned")return{ok:!0,kind:"already-abandoned",epicRunId:options.epicRunId};try{return await updateEpicRunStatus(access,{epicKey:options.epicRunId,status:"abandoned",expectedStatus:currentStatus}),{ok:!0,kind:"abandoned",epicRunId:options.epicRunId}}catch(err){return err instanceof ConductorBridgeApiError&&err.status===400?{ok:!1,kind:"concurrent-change",epicRunId:options.epicRunId,message:"the run's status changed concurrently; re-check its state and retry"}:{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,message:safeDiagnosticMessage(err,"abandon request failed")}}}async function ticketRecoveryWithRetry(access,options,mutate){let idempotencyKey=randomUUID2();for(let attempt=0;attempt<RECOVERY_TICKET_RETRY_LIMIT;attempt+=1){let state;try{state=await fetchEpicRunState(access,options.epicRunId)}catch(err){return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,ticketKey:options.ticketKey,message:safeDiagnosticMessage(err,"could not read run state")}}let ticket=state.ticket_statuses.find(t=>t.ticket_key===options.ticketKey);if(!ticket)return{ok:!1,kind:"ticket-not-found",epicRunId:options.epicRunId,ticketKey:options.ticketKey};let result;try{result=await mutate(access,{epicRunId:options.epicRunId,ticketKey:options.ticketKey,expectedRowVersion:ticket.row_version,idempotencyKey,reason:options.reason})}catch(err){return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,ticketKey:options.ticketKey,message:safeDiagnosticMessage(err,"recovery request failed")}}if(result.ok)return{ok:!0,kind:"unparked",epicRunId:options.epicRunId,ticketKey:options.ticketKey,status:result.ticket_status.status}}return{ok:!1,kind:"concurrent-change-exhausted",epicRunId:options.epicRunId,ticketKey:options.ticketKey}}async function unparkEpicTicketWithRetry(access,options){return ticketRecoveryWithRetry(access,options,(a,args)=>unparkEpicTicket(a,args))}async function adoptCurrentHeadAndUnparkWithRetry(access,options){return ticketRecoveryWithRetry(access,options,(a,args)=>adoptCurrentHeadAndUnparkTicket(a,args))}var RECOVERY_TICKET_RETRY_LIMIT,init_recovery_operations=__esm({"src/conductor/recovery-operations.ts"(){"use strict";init_bridge_api_client();RECOVERY_TICKET_RETRY_LIMIT=3}});var recovery_cli_exports={};__export(recovery_cli_exports,{runAbandonRunCommand:()=>runAbandonRunCommand,runAdoptCurrentHeadAndUnparkCommand:()=>runAdoptCurrentHeadAndUnparkCommand,runStopRunCommand:()=>runStopRunCommand,runUnparkCommand:()=>runUnparkCommand});function tokenizeRecoveryFlags(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(REJECTED_VERSION_FLAGS.has(name))throw new ConductorValidationError(`Flag "${name}" is not supported here \u2014 row-version handling is internal to recovery and cannot be supplied by the operator. Omit it; recovery reads the current version itself.`);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}}function parseRunRecoveryArgs(argv){let{values,bools}=tokenizeRecoveryFlags(argv,RUN_VALUE_FLAGS,RECOVERY_BOOL_FLAGS);if(bools.has("--help"))return{epicRunId:"",json:bools.has("--json"),help:!0};let epicRunId=values.get("--epic-run-id");if(epicRunId===void 0||epicRunId.trim().length===0)throw new ConductorValidationError('Flag "--epic-run-id" is required and must be non-empty.');return{epicRunId:epicRunId.trim(),json:bools.has("--json"),help:!1}}function parseTicketRecoveryArgs(argv){let{values,bools}=tokenizeRecoveryFlags(argv,TICKET_VALUE_FLAGS,RECOVERY_BOOL_FLAGS);if(bools.has("--help"))return{epicRunId:"",ticketKey:"",json:bools.has("--json"),help:!0};let epicRunId=values.get("--epic-run-id");if(epicRunId===void 0||epicRunId.trim().length===0)throw new ConductorValidationError('Flag "--epic-run-id" is required and must be non-empty.');let ticketKey=values.get("--ticket-key");if(ticketKey===void 0||ticketKey.trim().length===0)throw new ConductorValidationError('Flag "--ticket-key" is required and must be non-empty.');return{epicRunId:epicRunId.trim(),ticketKey:ticketKey.trim(),json:bools.has("--json"),help:!1}}async function resolveRecoveryAccess(json){let{resolveConductorBridgeApiAccess:resolveConductorBridgeApiAccess2}=await Promise.resolve().then(()=>(init_bridge_api_client(),bridge_api_client_exports)),result=await resolveConductorBridgeApiAccess2();return result.ok?result.access:(json?console.log(JSON.stringify({ok:!1,kind:"unauthorized",error:result.error})):console.error(`Error: ${result.error}`),null)}function renderStopRunResult(result,json){return json?(console.log(JSON.stringify(result)),result.ok?0:1):result.ok&&result.kind==="committed"?(console.log(`Run ${result.epicRunId}: stopped. Its queued work was cancelled; the run record remains available for inspection.`),0):result.ok&&result.kind==="already-stopped"?(console.log(`Run ${result.epicRunId}: already stopped; no further action.`),0):!result.ok&&result.kind==="terminal"?(console.error(`Run ${result.epicRunId}: terminal (${result.status}) and cannot be stopped.`),1):(console.error(`Run ${result.epicRunId}: could not be stopped \u2014 ${result.message}.`),1)}async function runStopRunCommand(argv){try{let parsed=parseRunRecoveryArgs(argv);if(parsed.help)return console.log(STOP_RUN_USAGE),0;let access=await resolveRecoveryAccess(parsed.json);if(!access)return 1;let{stopEpicRunRecovery:stopEpicRunRecovery2}=await Promise.resolve().then(()=>(init_recovery_operations(),recovery_operations_exports)),result=await stopEpicRunRecovery2(access,{epicRunId:parsed.epicRunId});return renderStopRunResult(result,parsed.json)}catch(error){return console.error(`Error: ${toConductorErrorEnvelope(error).message}`),1}}function renderAbandonRunResult(result,json){return json?(console.log(JSON.stringify(result)),result.ok?0:1):result.ok&&result.kind==="abandoned"?(console.log(`Run ${result.epicRunId}: abandoned (terminal).`),0):result.ok&&result.kind==="already-abandoned"?(console.log(`Run ${result.epicRunId}: already abandoned (terminal); no further action.`),0):(console.error(`Run ${result.epicRunId}: could not be abandoned \u2014 ${result.message}.`),1)}async function runAbandonRunCommand(argv){try{let parsed=parseRunRecoveryArgs(argv);if(parsed.help)return console.log(ABANDON_RUN_USAGE),0;let access=await resolveRecoveryAccess(parsed.json);if(!access)return 1;let{abandonEpicRunRecovery:abandonEpicRunRecovery2}=await Promise.resolve().then(()=>(init_recovery_operations(),recovery_operations_exports)),result=await abandonEpicRunRecovery2(access,{epicRunId:parsed.epicRunId});return renderAbandonRunResult(result,parsed.json)}catch(error){return console.error(`Error: ${toConductorErrorEnvelope(error).message}`),1}}function renderTicketRecoveryResult(result,json){return json?(console.log(JSON.stringify(result)),result.ok?0:1):result.ok?(console.log(`Ticket ${result.ticketKey} (run ${result.epicRunId}): unparked \u2014 status: ${result.status}.`),0):result.kind==="ticket-not-found"?(console.error(`Ticket ${result.ticketKey}: not found in run ${result.epicRunId}.`),1):result.kind==="concurrent-change-exhausted"?(console.error(`Ticket ${result.ticketKey} (run ${result.epicRunId}): could not recover \u2014 it kept changing concurrently. Re-check the run/ticket status and try again.`),1):(console.error(`Ticket ${result.ticketKey} (run ${result.epicRunId}): could not recover \u2014 ${result.message}.`),1)}async function runUnparkCommand(argv){try{let parsed=parseTicketRecoveryArgs(argv);if(parsed.help)return console.log(UNPARK_USAGE),0;let access=await resolveRecoveryAccess(parsed.json);if(!access)return 1;let{unparkEpicTicketWithRetry:unparkEpicTicketWithRetry2}=await Promise.resolve().then(()=>(init_recovery_operations(),recovery_operations_exports)),result=await unparkEpicTicketWithRetry2(access,{epicRunId:parsed.epicRunId,ticketKey:parsed.ticketKey});return renderTicketRecoveryResult(result,parsed.json)}catch(error){return console.error(`Error: ${toConductorErrorEnvelope(error).message}`),1}}async function runAdoptCurrentHeadAndUnparkCommand(argv){try{let parsed=parseTicketRecoveryArgs(argv);if(parsed.help)return console.log(ADOPT_CURRENT_HEAD_USAGE),0;let access=await resolveRecoveryAccess(parsed.json);if(!access)return 1;let{adoptCurrentHeadAndUnparkWithRetry:adoptCurrentHeadAndUnparkWithRetry2}=await Promise.resolve().then(()=>(init_recovery_operations(),recovery_operations_exports)),result=await adoptCurrentHeadAndUnparkWithRetry2(access,{epicRunId:parsed.epicRunId,ticketKey:parsed.ticketKey});return renderTicketRecoveryResult(result,parsed.json)}catch(error){return console.error(`Error: ${toConductorErrorEnvelope(error).message}`),1}}var RUN_VALUE_FLAGS,TICKET_VALUE_FLAGS,RECOVERY_BOOL_FLAGS,REJECTED_VERSION_FLAGS,STOP_RUN_USAGE,ABANDON_RUN_USAGE,UNPARK_USAGE,ADOPT_CURRENT_HEAD_USAGE,init_recovery_cli=__esm({"src/conductor/recovery-cli.ts"(){"use strict";init_errors();RUN_VALUE_FLAGS=new Set(["--epic-run-id"]),TICKET_VALUE_FLAGS=new Set(["--epic-run-id","--ticket-key"]),RECOVERY_BOOL_FLAGS=new Set(["--json","--help"]),REJECTED_VERSION_FLAGS=new Set(["--row-version","--expected-row-version","--row_version","--expected_row_version"]);STOP_RUN_USAGE=["Usage: conductor stop-run --epic-run-id <id> [--json]","","Stop an epic run: block new dispatch and cancel its queued work. The run","record is preserved (never deleted) so its history stays inspectable.","Idempotent \u2014 repeating it once stopped is a safe no-op."].join(`
|
|
121
|
+
`)),waitForEvent=deps.waitForEvent??waitForConductorEvent,getSnapshot=deps.getSnapshot??getSupervisorSnapshot,upsertProjection=deps.upsertProjection??upsertSupervisorProjection,emitAssessment=deps.emitAssessment??emitSupervisorAssessmentIfNew,sendMessage=deps.sendWorkerMessage??sendWorkerMessage,resolveBridgeAccess=deps.resolveBridgeAccess??(()=>resolveConductorBridgeApiAccess()),processMerge=deps.processMerge??processGateMetMerge,dispatchNotification=deps.dispatchNotification??dispatchSupervisorNotification,bridgeAccess=null,bridgeAccessResolved=!1,processGateMetMerges=async events=>{let eligible=events.filter(e=>extractMergeActionIdentityFromGateEvent(e)!==null);if(eligible.length!==0){if(!bridgeAccessResolved){bridgeAccessResolved=!0;try{let result=await resolveBridgeAccess();bridgeAccess=result.ok?result.access:null,result.ok||errorLog(`[supervisor] run=${runId} auto-merge disabled: ${result.kind}`)}catch{bridgeAccess=null}}if(bridgeAccess)for(let event of eligible)try{await processMerge(bridgeAccess,event)}catch{}}},persist=async state2=>{try{await upsertProjection(toSupervisorProjectionInput(state2))}catch{}},state;try{let snapshot=await getSnapshot(runId);state=hydrateSupervisorRunStateFromSnapshot(snapshot,runId,config,now())}catch{return{run_id:runId,status:"failed",exit_code:2,reason:"supervisor failed to load initial snapshot",last_seq:0,worker_count:0}}let sinceSeq=state.last_seq>0?state.last_seq+1:1,iterationCap=Math.max(1e3,Math.ceil(config.global_timeout_ms/Math.max(1,config.wake_interval_ms))+16);try{applySupervisorHousekeeping(state,config,now());for(let iteration=0;iteration<iterationCap;iteration+=1){if(isSupervisorRunTerminal(state))return state.status=terminalStatus(state),await persist(state),log(`[supervisor] run=${runId} complete status=${state.status} workers=${Object.keys(state.workers).length}`),{run_id:runId,status:state.status,exit_code:0,reason:"all workers terminal",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length};if(hasSupervisorGlobalTimeoutElapsed(state,now()))return state.status="timed_out",await persist(state),errorLog(`[supervisor] run=${runId} global timeout elapsed`),{run_id:runId,status:"timed_out",exit_code:2,reason:"global timeout elapsed",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length};let waitResult=await waitForEvent({since_seq:sinceSeq,filter:{run_id:runId},data_mode:"full",timeout_ms:config.wake_interval_ms,limit:config.poll_limit});if(waitResult.events.length>0){let sorted=[...waitResult.events].sort((a,b)=>a.seq-b.seq);for(let event of sorted)applyConductorEventToSupervisorState(state,event,now());sinceSeq=sorted[sorted.length-1].seq+1,await processGateMetMerges(sorted)}applySupervisorHousekeeping(state,config,now()),await processEscalations(state,config,{emitAssessment,sendWorkerMessage:sendMessage,log,now,dispatchNotification}),await persist(state)}return state.status="timed_out",await persist(state),{run_id:runId,status:"timed_out",exit_code:2,reason:"supervisor iteration cap reached",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length}}catch{state.status="failed";try{await upsertProjection(toSupervisorProjectionInput(state))}catch{}return errorLog(`[supervisor] run=${runId} failed unexpectedly`),{run_id:runId,status:"failed",exit_code:2,reason:"supervisor failed unexpectedly",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length}}}var init_supervisor_runtime=__esm({"src/conductor/supervisor-runtime.ts"(){"use strict";init_store();init_supervisor_ledger();init_supervisor_message_relay();init_supervisor_config();init_supervisor_state();init_supervisor_escalation();init_supervisor_ledger();init_bridge_api_client();init_merge_ledger();init_supervisor_merge();init_supervisor_notification();init_errors()}});import path7 from"path";function buildSetupUrl(baseUrl){return`${baseUrl.replace(/\/+$/,"")}/setup`}async function resolveInstallDoctorTarget(deps){let envRepo=deps.env.BAPI_REPO_NAME?.trim(),envBase=deps.env.BAPI_BASE_URL?.trim(),repoName=envRepo&&envRepo.length>0?envRepo:null,repoSource=repoName?"env":null,baseUrl=envBase&&envBase.length>0?envBase:null;if(!repoName||!baseUrl)for(let{relPath,topLevelKey}of MCP_CONFIG_ENV_TARGETS){let raw;try{raw=await deps.readFile(path7.join(deps.cwd,relPath))}catch{continue}let parsed;try{parsed=JSON.parse(raw)}catch{continue}let servers=parsed&&typeof parsed=="object"?parsed[topLevelKey]:void 0,registrationKey=existingRegistrationKey(servers),envBlock=registrationKey!==null?servers[registrationKey]?.env:void 0;if(envBlock&&(!repoName&&typeof envBlock.BAPI_REPO_NAME=="string"&&envBlock.BAPI_REPO_NAME.trim()&&(repoName=envBlock.BAPI_REPO_NAME.trim(),repoSource="config"),!baseUrl&&typeof envBlock.BAPI_BASE_URL=="string"&&envBlock.BAPI_BASE_URL.trim()&&(baseUrl=envBlock.BAPI_BASE_URL.trim()),repoName&&baseUrl))break}return{repoName,repoSource,baseUrl:baseUrl??DEFAULT_BASE_URL}}function classifyProbeFailure(error){let name=error?.name;return name==="TimeoutError"||name==="AbortError"?"request timed out":"request unavailable"}async function probeGet(deps,url,apiKey){try{let resp=await deps.fetch(url,{headers:{"X-API-Key":apiKey},signal:AbortSignal.timeout(PROBE_TIMEOUT_MS)}),body=null;try{body=await resp.json()}catch{}return{ok:!0,status:resp.status,body}}catch(e){return{ok:!1,error:classifyProbeFailure(e)}}}function summarizeManifestGroups(body){if(!body||typeof body!="object")return null;let groups=body.groups;if(!Array.isArray(groups))return null;let total=0,unset=[];for(let group of groups){let fields=group?.fields;if(Array.isArray(fields))for(let field of fields){let name=field?.field_name;typeof name=="string"&&(total+=1,field.is_set||unset.push(name))}}return{total,unset}}function summarizeIntegrations(body){if(!body||typeof body!="object")return null;let integrations=body.integrations;if(!Array.isArray(integrations))return null;let total=0,unconfigured=[];for(let item of integrations){let label=item?.label;typeof label=="string"&&(total+=1,item.is_configured||unconfigured.push(label))}return{total,unconfigured}}function readGithubConfiguredFlag(body){if(!body||typeof body!="object")return null;let integrations=body.integrations;if(!Array.isArray(integrations))return null;for(let item of integrations){if(item?.id!=="github_app")continue;let configured=item.is_configured;return typeof configured=="boolean"?configured:null}return null}async function collectInstallStatusChecks(deps){let checks=[],loginResult=await detectClaudeLogin({homedir:deps.homedir,readFile:deps.readFile});checks.push({id:"claude-login",label:"Claude login",status:loginResult.detected?"PASS":"INFO",detail:formatClaudeLoginAdvisory(loginResult)});let target=await resolveInstallDoctorTarget(deps);if(!target.repoName)return checks.push({id:"identity",label:"Repository identity",status:"SKIP",detail:"no BAPI_REPO_NAME in the environment or project-local MCP configs",remediation:"run install-bridge (or set BAPI_REPO_NAME) to configure this project."}),checks;checks.push({id:"identity",label:"Repository identity",status:"PASS",detail:`${target.repoName} (from ${target.repoSource}), base URL ${target.baseUrl}`});let setupUrl=buildSetupUrl(target.baseUrl),credDeps={env:deps.env,homedir:deps.homedir,platform:deps.platform,readFile:deps.readFile,stat:deps.stat,stderr:()=>{}},cred=await resolveBapiCredentials(target.repoName,credDeps);if(!cred.ok){checks.push({id:"credential",label:"Bridge API credential",status:"WARN",detail:`not resolved (${cred.kind})`,remediation:"set BAPI_API_KEY or persist it via /install-bridge / the credentials subcommand; until then the remaining install checks are skipped."});for(let[id,label]of[["connectivity","Server connectivity"],["bootstrap","Bootstrap config fields"],["indexing","Repository indexing"]])checks.push({id,label,status:"SKIP",detail:"no credential resolved"});return checks}checks.push({id:"credential",label:"Bridge API credential",status:"PASS",detail:`resolved from ${cred.credentials.source} (value never read into the report)`});let apiKey=cred.credentials.apiKey,repoQuery=`repo_name=${encodeURIComponent(target.repoName)}`,ping=await probeGet(deps,`${target.baseUrl}/jira/ping?${repoQuery}`,apiKey);ping.ok?ping.status===200?checks.push({id:"connectivity",label:"Server connectivity",status:"PASS",detail:"ping OK"}):ping.status===401||ping.status===403?checks.push({id:"connectivity",label:"Server connectivity",status:"WARN",detail:`the server rejected the resolved key (HTTP ${ping.status})`,remediation:"the key may have been rotated \u2014 re-run install-bridge with a current key."}):ping.status===404?checks.push({id:"connectivity",label:"Server connectivity",status:"WARN",detail:`the server does not know repo '${target.repoName}' (HTTP 404)`,remediation:`create the project at ${setupUrl} (setup UI), or check BAPI_REPO_NAME spelling.`}):checks.push({id:"connectivity",label:"Server connectivity",status:"WARN",detail:`unexpected HTTP ${ping.status} from /jira/ping`,remediation:"the server answered but not with a status this check understands \u2014 re-run doctor; if it persists the Bridge API is unhealthy and no install fact below can be trusted."}):checks.push({id:"connectivity",label:"Server connectivity",status:"WARN",detail:`unreachable (${ping.error})`,remediation:`check ${target.baseUrl} and your network, then re-run doctor.`});let manifest=await probeGet(deps,`${target.baseUrl}/jira/config/install-manifest?${repoQuery}`,apiKey);if(!manifest.ok)checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:`manifest unreachable (${manifest.error})`,remediation:`check ${target.baseUrl} and your network, then re-run doctor.`});else if(manifest.status===404)checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:"no configuration row found for this repository",remediation:`create the project at ${setupUrl} (setup UI), then run /install-bridge.`});else if(manifest.status===200){let summary=summarizeManifestGroups(manifest.body);summary?summary.unset.length===0?checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"PASS",detail:`${summary.total}/${summary.total} bootstrap fields set`}):checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:`${summary.total-summary.unset.length}/${summary.total} set; unset: ${summary.unset.join(", ")}`,remediation:"run /install-bridge to derive the unset fields (intentionally-unset fields are fine to leave)."}):checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:"manifest response had an unexpected shape",remediation:"the manifest could not be read, so no bootstrap field state is known \u2014 re-run doctor, then run /install-bridge to re-derive the project configuration."})}else checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:`unexpected HTTP ${manifest.status} from the install manifest`,remediation:"the manifest endpoint answered with an unrecognized status \u2014 re-run doctor; if it persists, re-run /install-bridge for this repository."});if(manifest.ok&&manifest.status===200){let integrations=summarizeIntegrations(manifest.body);integrations===null?checks.push({id:"integrations",label:"Integration credentials",status:"SKIP",detail:"the manifest response carried no integrations checklist"}):integrations.unconfigured.length===0?checks.push({id:"integrations",label:"Integration credentials",status:"PASS",detail:`${integrations.total}/${integrations.total} configured`}):checks.push({id:"integrations",label:"Integration credentials",status:"WARN",detail:`not configured: ${integrations.unconfigured.join(", ")}`,remediation:`a human configures these at ${setupUrl} (setup UI \u2192 project settings) \u2014 Bridge API never accepts integration secrets through an agent or MCP tool.`})}else checks.push({id:"integrations",label:"Integration credentials",status:"SKIP",detail:"manifest unavailable"});if(manifest.ok&&manifest.status===200){let github=readGithubConfiguredFlag(manifest.body);github===null?checks.push({id:"github",label:"GitHub connection",status:"SKIP",detail:"the manifest response carried no GitHub integration entry"}):github?checks.push({id:"github",label:"GitHub connection",status:"PASS",detail:"a GitHub repository is connected to this project"}):checks.push({id:"github",label:"GitHub connection",status:"WARN",detail:"no GitHub repository is connected to this project",remediation:`run 'npx -y ${MCP_PACKAGE_NAME}@latest connect-github --repo ${target.repoName}'.`})}else checks.push({id:"github",label:"GitHub connection",status:"SKIP",detail:"manifest unavailable"});let parse=await probeGet(deps,`${target.baseUrl}/jira/parse-status?${repoQuery}`,apiKey);if(!parse.ok||parse.status!==200)checks.push({id:"indexing",label:"Repository indexing",status:"SKIP",detail:parse.ok?`HTTP ${parse.status} from /jira/parse-status`:`unreachable (${parse.error})`});else if(parse.body?.status==="in_progress"){let startedAt=parse.body.started_at;checks.push({id:"indexing",label:"Repository indexing",status:"INFO",detail:`parse job in progress${typeof startedAt=="string"?` (started ${startedAt})`:""}`})}else checks.push({id:"indexing",label:"Repository indexing",status:"INFO",detail:'no parse job currently running \u2014 if this repository has never been indexed, queue one with /parse-repository (monitor with parse_repository action "status").'});return checks}function projectInstallStatus(check){return check.status==="PASS"?{status:"pass"}:check.status==="WARN"?{status:"warn",...check.remediation?{remediation:check.remediation}:{}}:check.status==="INFO"?check.id==="claude-login"?{status:"warn",remediation:INSTALL_CLAUDE_LOGIN_REMEDIATION}:{status:"pass"}:check.id==="identity"?{status:"fail",remediation:check.remediation??INSTALL_IDENTITY_REMEDIATION}:{status:"skip",...check.remediation?{remediation:check.remediation}:{}}}function mapInstallStatusChecksToReadinessChecks(checks,collectorUnavailable=!1){let byId=new Map;for(let check of checks??[])byId.has(check.id)||byId.set(check.id,check);return INSTALL_READINESS_DESCRIPTORS.map(({id,label})=>{let source=byId.get(id);if(!source)return collectorUnavailable?createReadinessCheck({id:`install.${id}`,source:"install",label,status:"fail",detail:INSTALL_UNAVAILABLE_DETAIL,remediation:INSTALL_UNAVAILABLE_REMEDIATION}):createReadinessCheck({id:`install.${id}`,source:"install",label,status:"skip",detail:INSTALL_NOT_COLLECTED_DETAIL});let projected=projectInstallStatus(source);return createReadinessCheckSafely({id:`install.${id}`,source:"install",label:source.label||label,status:projected.status,...source.detail?{detail:source.detail}:{},...projected.status==="pass"?{}:projected.remediation?{remediation:projected.remediation}:projected.status==="fail"?{remediation:INSTALL_IDENTITY_REMEDIATION}:{}})})}var DEFAULT_BASE_URL,MCP_CONFIG_ENV_TARGETS,PROBE_TIMEOUT_MS,INSTALL_READINESS_DESCRIPTORS,INSTALL_IDENTITY_REMEDIATION,INSTALL_CLAUDE_LOGIN_REMEDIATION,INSTALL_NOT_COLLECTED_DETAIL,INSTALL_UNAVAILABLE_DETAIL,INSTALL_UNAVAILABLE_REMEDIATION,init_install_doctor=__esm({"src/install-doctor.ts"(){"use strict";init_readiness_check();init_credential_store();init_claude_login();init_mcp_host_targets();init_mcp_identity();DEFAULT_BASE_URL="https://bridgegpt-api.com";MCP_CONFIG_ENV_TARGETS=getProjectJsonTargets().map(target=>({relPath:target.relPath,topLevelKey:hostAdapterForTarget(target).topLevelKey})),PROBE_TIMEOUT_MS=5e3;INSTALL_READINESS_DESCRIPTORS=[{id:"claude-login",label:"Claude login"},{id:"identity",label:"Repository identity"},{id:"credential",label:"Bridge API credential"},{id:"connectivity",label:"Server connectivity"},{id:"bootstrap",label:"Bootstrap config fields"},{id:"integrations",label:"Integration credentials"},{id:"github",label:"GitHub connection"},{id:"indexing",label:"Repository indexing"}],INSTALL_IDENTITY_REMEDIATION="run /install-bridge (or set BAPI_REPO_NAME) to configure this project; without a repository identity no server-side conductor fact can be resolved.",INSTALL_CLAUDE_LOGIN_REMEDIATION="run `claude login` on the host that will run conductor workers; Bridge stores no Anthropic credential and cannot confirm this for you.",INSTALL_NOT_COLLECTED_DETAIL="not collected \u2014 an earlier install prerequisite stopped the checklist",INSTALL_UNAVAILABLE_DETAIL="unknown \u2014 the install-status checklist could not be collected at all",INSTALL_UNAVAILABLE_REMEDIATION="run `doctor` to collect the advisory install-status checklist directly; this prerequisite's state is unknown, not healthy."}});function planeCheckPassed(check,label,detail){return{diagnostic:null,outcomes:[{check,id:check,label,status:"pass",...detail?{detail}:{}}]}}function planeCheckFinding(diagnostic,label,detail){return{diagnostic,outcomes:[{check:diagnostic.check,id:diagnostic.check,label,status:diagnostic.severity==="blocking"?"fail":"warn",detail,...diagnostic.remediation?{remediation:diagnostic.remediation}:{}}]}}var PLANE_MANIFEST_SUPPORTED_SCHEMA_VERSIONS,PLANE_RUNTIME_DIR,PLANE_MANIFEST_FILENAME,PLANE_RUNTIME_LOG_FILENAME,PLANE_RUNTIME_LOG_PATH,PLANE_SERVER_HOST,PLANE_SERVER_PORT,PLANE_SERVER_BASE_URL,PLANE_SERVER_PORT_ENV_VAR,init_types2=__esm({"src/plane/types.ts"(){"use strict";PLANE_MANIFEST_SUPPORTED_SCHEMA_VERSIONS=[1,2],PLANE_RUNTIME_DIR=".bridge/plane",PLANE_MANIFEST_FILENAME="plane.json",PLANE_RUNTIME_LOG_FILENAME="runtime.log",PLANE_RUNTIME_LOG_PATH=`${PLANE_RUNTIME_DIR}/${PLANE_RUNTIME_LOG_FILENAME}`,PLANE_SERVER_HOST="127.0.0.1",PLANE_SERVER_PORT=8e3,PLANE_SERVER_BASE_URL=`http://${PLANE_SERVER_HOST}:${PLANE_SERVER_PORT}`,PLANE_SERVER_PORT_ENV_VAR="BAPI_PLANE_PORT"}});import path8 from"path";function isRelevantSourceFile(name){return!(!name.endsWith(".ts")||name.endsWith(".generated.ts"))}async function findNewestSourceMtime(srcDir,deps){let newest=null,walk=async dir=>{let entries;try{entries=await deps.fs.readdir(dir)}catch(err){return sanitize(err)}for(let entry of entries){if(entry.isDirectory()){if(EXCLUDED_DIR_NAMES.has(entry.name))continue;let error2=await walk(path8.join(dir,entry.name));if(error2)return error2;continue}if(!(!entry.isFile()||!isRelevantSourceFile(entry.name)))try{let stat3=await deps.fs.stat(path8.join(dir,entry.name));(newest===null||stat3.mtimeMs>newest)&&(newest=stat3.mtimeMs)}catch(err){return sanitize(err)}}return null},error=await walk(srcDir);return error?{ok:!1,error}:{ok:!0,mtimeMs:newest}}async function findBuildMtime(executorEntrypoint,deps){try{return{ok:!0,mtimeMs:(await deps.fs.stat(executorEntrypoint)).mtimeMs}}catch(err){return{ok:!1,error:sanitize(err)}}}async function checkPlaneBuildFreshness(repoRoot,deps){let label="Executor build freshness",packageRoot=path8.join(repoRoot,"mcp_server"),buildDir=path8.join(packageRoot,"build"),executorEntrypoint=path8.join(buildDir,"index.js"),srcDir=path8.join(packageRoot,"src"),buildMtime=await findBuildMtime(executorEntrypoint,deps);if(!buildMtime.ok)return planeCheckFinding({check:"executor-build",severity:"blocking",message:`the executor build entrypoint is missing or unreadable at mcp_server/build/index.js \u2014 run \`${PLANE_BUILD_REMEDIATION}\``,remediation:PLANE_BUILD_FIX_REMEDIATION},label,"the executor build entrypoint is missing or unreadable");let sourceMtime=await findNewestSourceMtime(srcDir,deps);return sourceMtime.ok?sourceMtime.mtimeMs!==null&&sourceMtime.mtimeMs>buildMtime.mtimeMs?planeCheckFinding({check:"executor-build",severity:"blocking",message:`mcp_server/build/ is STALE \u2014 a source file under mcp_server/src is newer than mcp_server/build/index.js, so executors would run old code. Run \`${PLANE_BUILD_REMEDIATION}\``,remediation:PLANE_BUILD_FIX_REMEDIATION},label,"mcp_server/build/ is stale \u2014 a source file is newer than the build entrypoint"):planeCheckPassed("executor-build",label,"the executor build is present and current"):planeCheckFinding({check:"executor-build",severity:"blocking",message:`could not read mcp_server/src to compare against the build (${sourceMtime.error}) \u2014 run \`${PLANE_BUILD_REMEDIATION}\``,remediation:PLANE_BUILD_FIX_REMEDIATION},label,`the executor sources could not be read for comparison (${sourceMtime.error})`)}function checkPlaneRuntimeEntrypoint(resolution){let label="Runtime re-exec entrypoint";return resolution.ok?planeCheckPassed("runtime-entrypoint",label,"the executing build can re-enter itself"):planeCheckFinding({check:"runtime-entrypoint",severity:"blocking",message:PLANE_RUNTIME_ENTRYPOINT_REFUSAL,remediation:PLANE_BUILD_FIX_REMEDIATION},label,"the currently executing MCP build could not be re-entered")}function sanitize(err){let code=err?.code;return typeof code=="string"?code:"unreadable"}var PLANE_BUILD_REMEDIATION,EXCLUDED_DIR_NAMES,PLANE_BUILD_FIX_REMEDIATION,PLANE_RUNTIME_ENTRYPOINT_REFUSAL,init_build_freshness=__esm({"src/plane/build-freshness.ts"(){"use strict";init_types2();PLANE_BUILD_REMEDIATION="cd mcp_server && npm run build",EXCLUDED_DIR_NAMES=new Set(["node_modules","build"]);PLANE_BUILD_FIX_REMEDIATION="run `cd mcp_server && npm run build` to rebuild the executor entrypoint, then retry.";PLANE_RUNTIME_ENTRYPOINT_REFUSAL=`the currently executing MCP build could not be re-entered \u2014 \`plane up\` re-execs this package's own compiled entrypoint to create the detached runtime, and no existing entrypoint belonging to it could be found. Run \`${PLANE_BUILD_REMEDIATION}\` and retry from the rebuilt CLI.`}});import path9 from"path";function resolveRepositoryAlembicCommand(repoRoot,platform){return platform==="win32"?path9.join(repoRoot,".venv","Scripts","alembic.exe"):path9.join(repoRoot,".venv","bin","alembic")}function parseAlembicRevisions(output){let revisions=new Set;for(let rawLine of output.split(/\r?\n/)){let line=rawLine.trim();if(line.length===0||LOG_LINE_PATTERN.test(line))continue;let token=line.split(/\s+/)[0];!token||NON_REVISION_TOKENS.has(token.toLowerCase())||REVISION_PATTERN.test(token)&&revisions.add(token)}return revisions.size===0?null:[...revisions].sort()}async function checkAlembicHead(repoRoot,deps){let alembic=resolveRepositoryAlembicCommand(repoRoot,deps.platform);if(!await deps.fileExists(alembic))return unverified("the repository virtualenv Alembic executable was not found","the repository virtualenv Alembic executable was not found");let heads=await deps.execFile(alembic,["-c","alembic.ini","heads"],{cwd:repoRoot});if(!heads.ok)return unverified(`\`alembic heads\` did not complete (${heads.error})`,"`alembic heads` did not complete");let current=await deps.execFile(alembic,["-c","alembic.ini","current"],{cwd:repoRoot});if(!current.ok)return unverified(`\`alembic current\` did not complete (${current.error})`,"`alembic current` did not complete");let headRevisions=parseAlembicRevisions(heads.stdout),currentRevisions=parseAlembicRevisions(current.stdout);return headRevisions===null||currentRevisions===null?unverified("Alembic output did not contain a readable revision","Alembic output did not contain a readable revision"):headRevisions.length===currentRevisions.length&&headRevisions.every((rev,i)=>rev===currentRevisions[i])?planeCheckPassed("alembic-head",ALEMBIC_CHECK_LABEL,"the database is at the repository migration head"):planeCheckFinding({check:"alembic-head",severity:"blocking",message:`the database is not at the migration head \u2014 heads [${headRevisions.join(", ")}], current [${currentRevisions.join(", ")}]. A database behind the head blocks conductor dispatch. Run \`${PLANE_ALEMBIC_REMEDIATION}\``,remediation:PLANE_ALEMBIC_MISMATCH_REMEDIATION},ALEMBIC_CHECK_LABEL,`database at [${currentRevisions.join(", ")}], repository head [${headRevisions.join(", ")}]`)}function unverified(messageDetail,outcomeDetail){let diagnostic={check:"alembic-head",severity:"warning",message:`${PLANE_ALEMBIC_UNVERIFIED_PREFIX}: ${messageDetail}. Startup continues \u2014 verify with \`alembic -c alembic.ini heads\` and \`alembic -c alembic.ini current\` if a run later reports CONTRACT_MIGRATION_BEHIND.`,remediation:PLANE_ALEMBIC_UNVERIFIED_REMEDIATION};return planeCheckFinding(diagnostic,ALEMBIC_CHECK_LABEL,`${PLANE_ALEMBIC_UNVERIFIED_PREFIX}: ${outcomeDetail}`)}var PLANE_ALEMBIC_REMEDIATION,PLANE_ALEMBIC_UNVERIFIED_PREFIX,PLANE_ALEMBIC_MISMATCH_REMEDIATION,PLANE_ALEMBIC_UNVERIFIED_REMEDIATION,LOG_LINE_PATTERN,REVISION_PATTERN,NON_REVISION_TOKENS,ALEMBIC_CHECK_LABEL,init_alembic_head=__esm({"src/plane/alembic-head.ts"(){"use strict";init_types2();PLANE_ALEMBIC_REMEDIATION="alembic -c alembic.ini upgrade head",PLANE_ALEMBIC_UNVERIFIED_PREFIX="could not verify database migration head",PLANE_ALEMBIC_MISMATCH_REMEDIATION=`run \`${PLANE_ALEMBIC_REMEDIATION}\` to bring the database up to the migration head, then retry.`,PLANE_ALEMBIC_UNVERIFIED_REMEDIATION="verify by hand with `alembic -c alembic.ini heads` and `alembic -c alembic.ini current`; startup continues, and the server reports CONTRACT_MIGRATION_BEHIND at dispatch if the database is behind.";LOG_LINE_PATTERN=/^(INFO|WARNING|ERROR|DEBUG|CRITICAL)\b|\[alembic/i,REVISION_PATTERN=/^[0-9A-Za-z][0-9A-Za-z_.-]*$/,NON_REVISION_TOKENS=new Set(["head","heads","base","none","(head)"]);ALEMBIC_CHECK_LABEL="Database migration head"}});import path10 from"path";function getPlanePaths(repoRoot){let planeDir=path10.join(repoRoot,".bridge","plane");return{planeDir,manifestPath:path10.join(planeDir,PLANE_MANIFEST_FILENAME),logPathFor:member=>path10.join(planeDir,`${member}.log`)}}function relativeLogPathFor(member){return`${PLANE_RUNTIME_DIR}/${member}.log`}function isNonBlankTrimmedString(value){return typeof value=="string"&&value.trim().length>0&&value===value.trim()}function isPlaneMemberName(value){return typeof value!="string"?!1:value==="server"||value==="worker"||value==="observer"?!0:/^executor-[1-9][0-9]*$/.test(value)}function isPositiveInteger(value){return typeof value=="number"&&Number.isSafeInteger(value)&&value>0}function isIsoTimestamp(value){return typeof value=="string"&&value.length>0&&!Number.isNaN(Date.parse(value))}function parsePlaneManifest(value){if(typeof value!="object"||value===null||Array.isArray(value))return{ok:!1,error:"manifest is not an object"};let record=value;for(let key of Object.keys(record))if(!MANIFEST_KEYS.has(key))return{ok:!1,error:`manifest has an unsupported field '${key}'`};if(typeof record.schemaVersion!="number"||!PLANE_MANIFEST_SUPPORTED_SCHEMA_VERSIONS.includes(record.schemaVersion))return{ok:!1,error:`manifest schema version ${JSON.stringify(record.schemaVersion)} is not supported (this build reads ${PLANE_MANIFEST_SUPPORTED_SCHEMA_VERSIONS.join(", ")}). A manifest from a NEWER build must be wound down with that build's \`plane down\``};if(typeof record.planeId!="string"||!/^[0-9a-f-]{8,}$/i.test(record.planeId))return{ok:!1,error:"manifest plane identity is missing or malformed"};if(typeof record.repoRoot!="string"||record.repoRoot.length===0)return{ok:!1,error:"manifest repository root is missing"};if(!isPositiveInteger(record.supervisorPid))return{ok:!1,error:"manifest supervisor pid is not a positive integer"};if(!isPositiveInteger(record.supervisorPgid))return{ok:!1,error:"manifest supervisor process-group id is not a positive integer"};if(!isIsoTimestamp(record.createdAt)||!isIsoTimestamp(record.updatedAt))return{ok:!1,error:"manifest timestamps are missing or malformed"};if(!Array.isArray(record.members)||record.members.length===0)return{ok:!1,error:"manifest members are missing"};if(record.epicRunId!==void 0&&!isNonBlankTrimmedString(record.epicRunId))return{ok:!1,error:"manifest epic run id is malformed"};let members=[],unrecognizedMemberNames=[],seen=new Set;for(let raw of record.members){if(typeof raw!="object"||raw===null||Array.isArray(raw))return{ok:!1,error:"manifest member is not an object"};let member=raw;for(let key of Object.keys(member))if(!MEMBER_KEYS.has(key))return{ok:!1,error:`manifest member has an unsupported field '${key}'`};if(typeof member.name!="string"||member.name.length===0)return{ok:!1,error:"manifest member name is missing or not a string"};if(!isPlaneMemberName(member.name)){unrecognizedMemberNames.includes(member.name)||unrecognizedMemberNames.push(member.name);continue}if(seen.has(member.name))return{ok:!1,error:`manifest lists member '${member.name}' more than once`};if(seen.add(member.name),member.pid!==null&&!isPositiveInteger(member.pid))return{ok:!1,error:`manifest member '${member.name}' has an invalid pid`};if(typeof member.state!="string"||!VALID_STATES.has(member.state))return{ok:!1,error:`manifest member '${member.name}' has an invalid state`};if(member.exitCode!==null&&!Number.isSafeInteger(member.exitCode))return{ok:!1,error:`manifest member '${member.name}' has an invalid exit code`};if(member.exitSignal!==null&&typeof member.exitSignal!="string")return{ok:!1,error:`manifest member '${member.name}' has an invalid exit signal`};if(member.logPath!==relativeLogPathFor(member.name))return{ok:!1,error:`manifest member '${member.name}' has an unexpected log path`};members.push({name:member.name,pid:member.pid,state:member.state,exitCode:member.exitCode,exitSignal:member.exitSignal,logPath:member.logPath})}return members.length===0?{ok:!1,error:`manifest lists no member this build recognizes (unrecognized: ${unrecognizedMemberNames.join(", ")}). It was written by a newer build; wind the plane down with that build's \`plane down\``}:{ok:!0,unrecognizedMemberNames,manifest:{schemaVersion:record.schemaVersion,planeId:record.planeId,repoRoot:record.repoRoot,supervisorPid:record.supervisorPid,supervisorPgid:record.supervisorPgid,createdAt:record.createdAt,updatedAt:record.updatedAt,members,...record.epicRunId!==void 0?{epicRunId:record.epicRunId}:{}}}}async function readPlaneManifest(repoRoot,fs2){let{manifestPath}=getPlanePaths(repoRoot),raw;try{raw=await fs2.readFile(manifestPath)}catch(err){let code=err?.code;return code==="ENOENT"?{kind:"missing"}:{kind:"unreadable",error:typeof code=="string"?code:"read failed"}}let parsed;try{parsed=JSON.parse(raw)}catch{return{kind:"malformed",error:"manifest is not valid JSON"}}let result=parsePlaneManifest(parsed);return result.ok?{kind:"valid",manifest:result.manifest,unrecognizedMemberNames:result.unrecognizedMemberNames}:{kind:"malformed",error:result.error}}function isProcessAlive(pid,kill){if(!isPositiveInteger(pid))return"unknown";try{return kill(pid,0),"alive"}catch(err){let code=err?.code;return code==="ESRCH"?"dead":code==="EPERM"?"alive":"unknown"}}function probeManifestMembers(manifest,proc){return manifest.members.map(member=>member.state==="exited"||member.pid===null?{member,liveness:"dead"}:{member,liveness:proc.isAlive(member.pid)})}function manifestHasLiveProcess(manifest,proc){return proc.isAlive(manifest.supervisorPid)!=="dead"?!0:probeManifestMembers(manifest,proc).some(probe=>probe.liveness!=="dead")}var VALID_STATES,MANIFEST_KEYS,MEMBER_KEYS,init_manifest=__esm({"src/plane/manifest.ts"(){"use strict";init_types2();VALID_STATES=new Set(["spawning","running","ready","exited"]),MANIFEST_KEYS=new Set(["schemaVersion","planeId","repoRoot","supervisorPid","supervisorPgid","createdAt","updatedAt","members","epicRunId"]);MEMBER_KEYS=new Set(["name","pid","state","exitCode","exitSignal","logPath"])}});import path11 from"path";async function runPlanePreflight(repoRoot,deps){let diagnostics=[],outcomes=[],add=diagnostic=>{diagnostic&&diagnostics.push(diagnostic)},record=report=>(add(report.diagnostic),outcomes.push(...report.outcomes),report);if(record(await checkRepositoryRoot(repoRoot,deps)).diagnostic){for(let[check,id,label]of ROOT_DEPENDENT_CHECKS)outcomes.push({check,id,label,status:"skip",detail:PLANE_ROOT_DEPENDENT_SKIP_DETAIL});return{ok:!1,diagnostics,outcomes}}record(await checkRepositoryWorktree(repoRoot,deps)),record(await checkClaudeLogin(deps));let credentials=await checkBridgeCredentials(repoRoot,deps);outcomes.push(...credentials.outcomes);for(let advisory of credentials.advisories)add(advisory);credentials.ok||add(credentials.diagnostic),record(await checkPlaneBuildFreshness(repoRoot,{fs:deps.fs}));let runtimeEntrypoint=deps.resolveRuntimeEntrypoint();return record(checkPlaneRuntimeEntrypoint(runtimeEntrypoint)),deps.endpoint.ok?record(await checkServerPort(deps,deps.endpoint.endpoint)):record(planeCheckFinding({check:"server-port",severity:"blocking",message:deps.endpoint.message,remediation:PLANE_SERVER_ENDPOINT_REMEDIATION},"Local server port","the configured local server endpoint could not be resolved")),record(await checkAlembicHead(repoRoot,{execFile:deps.execFile,fileExists:filePath=>fileExists(filePath,deps.fs),platform:deps.platform})),record(await checkExistingPlane(repoRoot,deps)),diagnostics.filter(d=>d.severity==="blocking").length>0||!credentials.ok||!runtimeEntrypoint.ok||!deps.endpoint.ok?{ok:!1,diagnostics,outcomes}:{ok:!0,diagnostics,outcomes,context:{repoRoot,repoName:credentials.repoName,endpoint:deps.endpoint.endpoint,executorEntrypoint:path11.join(repoRoot,"mcp_server","build","index.js"),runtimeEntrypoint:runtimeEntrypoint.entrypoint,bridgeApiKey:credentials.apiKey,bridgeCredentialSource:credentials.source}}}async function checkRepositoryRoot(repoRoot,deps){let label="Repository root";if(!path11.isAbsolute(repoRoot))return planeCheckFinding({check:"repository-root",severity:"blocking",message:"the repository root could not be resolved to an absolute path",remediation:PLANE_REPOSITORY_ROOT_REMEDIATION},label,"the repository root could not be resolved to an absolute path");let missing=[];for(let file of REQUIRED_REPO_FILES)await fileExists(path11.join(repoRoot,file),deps.fs)||missing.push(file);return await fileExists(path11.join(repoRoot,"mcp_server"),deps.fs)||missing.push("mcp_server/"),missing.length===0?planeCheckPassed("repository-root",label,"all Bridge API root marker files are present"):planeCheckFinding({check:"repository-root",severity:"blocking",message:`this does not look like the Bridge API repository root \u2014 missing ${missing.join(", ")}. Run \`plane up\` from the repository root.`,remediation:PLANE_REPOSITORY_ROOT_REMEDIATION},label,`missing root marker(s): ${missing.join(", ")}`)}async function checkRepositoryWorktree(repoRoot,deps){let label="Git work tree",result=await deps.execFile("git",["rev-parse","--is-inside-work-tree"],{cwd:repoRoot});return!result.ok||result.stdout.trim()!=="true"?planeCheckFinding({check:"worktree-presence",severity:"blocking",message:`${repoRoot} is not inside a Git work tree (git rev-parse --is-inside-work-tree did not report 'true'). No worktree was created \u2014 ${PLANE_WORKTREE_REMEDIATION}`,remediation:PLANE_WORKTREE_REMEDIATION},label,"this directory is not inside a Git work tree"):planeCheckPassed("worktree-presence",label,"inside a Git work tree")}async function checkClaudeLogin(deps){let label="Claude login",result=await detectClaudeLogin({homedir:deps.homedir,readFile:deps.fs.readFile});return result.detected?planeCheckPassed("claude-login",label,"a local Claude login marker was detected"):planeCheckFinding({check:"claude-login",severity:"warning",message:formatClaudeLoginAdvisory(result),remediation:PLANE_CLAUDE_LOGIN_REMEDIATION},label,"no local Claude login marker was detected")}function credentialPermissionsOutcome(advisories){return advisories.length===0?{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.permissions,label:"Bridge credential file permissions",status:"pass",detail:"the credential resolver raised no permission advisory"}:{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.permissions,label:"Bridge credential file permissions",status:"warn",detail:`the credential resolver raised ${advisories.length} permission advisory line(s)`,remediation:PLANE_CREDENTIAL_PERMISSIONS_REMEDIATION}}async function checkBridgeCredentials(repoRoot,deps){let repo=await deps.resolveRepoName({env:deps.env,cwd:repoRoot,readFile:deps.fs.readFile});if(!repo.ok)return{ok:!1,advisories:[],diagnostic:{check:"bridge-credentials",severity:"blocking",message:"the Bridge repository identity could not be resolved \u2014 set BAPI_REPO_NAME or add a valid .bridge/config at the repository root.",remediation:PLANE_REPO_IDENTITY_REMEDIATION},outcomes:[{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.identity,label:"Bridge repository identity",status:"fail",detail:"the Bridge repository identity could not be resolved",remediation:PLANE_REPO_IDENTITY_REMEDIATION},{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.credential,label:"Bridge API credential",status:"skip",detail:"not resolved \u2014 there is no repository identity to resolve a credential for"},credentialPermissionsOutcome([])]};let warnings=createResolverWarningBuffer(),result;try{result=await deps.resolveCredentials(repo.repoName,{env:deps.env,homedir:deps.homedir,platform:deps.platform,readFile:deps.fs.readFile,stat:async filePath=>{let statResult=await deps.fs.stat(filePath);return{mode:statResult.mode!==void 0?statResult.mode:511}},stderr:warnings.write})}catch{let advisories2=warnings.drain();return{ok:!1,advisories:advisories2,diagnostic:{check:"bridge-credentials",severity:"blocking",message:`Bridge credentials for target bapi:${repo.repoName} could not be resolved (resolver unavailable).`,remediation:PLANE_CREDENTIAL_REMEDIATION},outcomes:[identityResolvedOutcome(),{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.credential,label:"Bridge API credential",status:"fail",detail:"the credential resolver was unavailable",remediation:PLANE_CREDENTIAL_REMEDIATION},credentialPermissionsOutcome(advisories2)]}}if(!result.ok){let advisories2=warnings.drain();return{ok:!1,advisories:advisories2,diagnostic:{check:"bridge-credentials",severity:"blocking",message:`Bridge credentials for target bapi:${repo.repoName} could not be resolved (${result.kind}). Set BAPI_API_KEY in this shell, or store it with \`mcp-server credentials\`. A spawned shell never sees .mcp.json env.`,remediation:PLANE_CREDENTIAL_REMEDIATION},outcomes:[identityResolvedOutcome(),{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.credential,label:"Bridge API credential",status:"fail",detail:`no Bridge API credential resolved (${result.kind})`,remediation:PLANE_CREDENTIAL_REMEDIATION},credentialPermissionsOutcome(advisories2)]}}let advisories=warnings.drain();return{ok:!0,repoName:repo.repoName,apiKey:result.credentials.apiKey,source:result.credentials.source,advisories,outcomes:[identityResolvedOutcome(),{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.credential,label:"Bridge API credential",status:"pass",detail:`resolved from ${result.credentials.source} (the value is never read into a report)`},credentialPermissionsOutcome(advisories)]}}function identityResolvedOutcome(){return{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.identity,label:"Bridge repository identity",status:"pass",detail:"the Bridge repository identity resolved"}}function createResolverWarningBuffer(){let lines=[],pending="",push=line=>{let trimmed=line.replace(/\r$/,"");trimmed.length!==0&&lines.push(trimmed)};return{write:message=>{pending+=message;let segments=pending.split(`
|
|
122
|
+
`);pending=segments.pop()??"";for(let segment of segments)push(segment)},drain:()=>(pending.length>0&&(push(pending),pending=""),lines.map(message=>({check:"bridge-credentials",severity:"warning",message})))}}async function checkServerPort(deps,endpoint){let label="Local server port",target=`${endpoint.host}:${endpoint.port}`,result=await deps.probePort(endpoint.host,endpoint.port,PLANE_PORT_PROBE_TIMEOUT_MS);return result.kind==="refused"?planeCheckPassed("server-port",label,`${target} is free`):result.kind==="connected"?planeCheckFinding({check:"server-port",severity:"blocking",message:`${target} is already accepting connections. That port may belong to a SIBLING WORKTREE's server \u2014 check before you kill it. Stop the existing server (or wind down its plane) and retry, or set ${PLANE_SERVER_PORT_ENV_VAR} to a free port.`,remediation:PLANE_SERVER_PORT_OCCUPIED_REMEDIATION},label,`${target} is already accepting connections`):planeCheckFinding({check:"server-port",severity:"warning",message:`could not determine whether ${target} is free (${result.error}); startup continues and uvicorn will fail loudly if the port is taken.`,remediation:PLANE_SERVER_PORT_UNKNOWN_REMEDIATION},label,`could not determine whether ${target} is free`)}async function checkExistingPlane(repoRoot,deps){let label="Existing plane",read=await readPlaneManifest(repoRoot,deps.fs);return read.kind==="missing"?planeCheckPassed("existing-plane",label,"no plane manifest is present"):read.kind!=="valid"?planeCheckFinding({check:"existing-plane",severity:"blocking",message:`an existing .bridge/plane/plane.json could not be validated (${read.error}). No process was signalled and the file was left untouched \u2014 inspect it, then remove it by hand if no plane is running.`,remediation:PLANE_MANIFEST_UNREADABLE_REMEDIATION},label,"an existing plane manifest could not be validated"):deps.ownPlaneId!==void 0&&read.manifest.planeId===deps.ownPlaneId?planeCheckPassed("existing-plane",label,"the existing manifest carries this launch's own plane id"):manifestHasLiveProcess(read.manifest,deps.proc)?planeCheckFinding({check:"existing-plane",severity:"blocking",message:`a plane is already running (supervisor pid ${read.manifest.supervisorPid}). Run \`plane status\` to inspect it, or \`plane down\` to wind it down first.`,remediation:PLANE_ALREADY_RUNNING_REMEDIATION},label,"a plane is already running for this repository"):{diagnostic:{check:"existing-plane",severity:"warning",message:"a previous plane manifest is present but every recorded process is gone; it will be replaced after a final liveness re-check."},outcomes:[{check:"existing-plane",id:"existing-plane",label,status:"warn",detail:"a stale plane manifest is present and will be replaced after a liveness re-check"}]}}async function fileExists(filePath,fs2){try{return await fs2.stat(filePath),!0}catch{return!1}}function mapPlanePreflightToReadinessChecks(result){let byId=new Map;for(let outcome of result?.outcomes??[])byId.has(outcome.id)||byId.set(outcome.id,outcome);return PLANE_READINESS_DESCRIPTORS.map(({id,label})=>{let outcome=byId.get(id);return outcome?createReadinessCheckSafely({id:`plane.${id}`,source:"plane",label:outcome.label||label,status:outcome.status,...outcome.detail?{detail:outcome.detail}:{},...outcome.status==="fail"?{remediation:outcome.remediation??PLANE_UNREPORTED_REMEDIATION}:outcome.status!=="pass"&&outcome.remediation?{remediation:outcome.remediation}:{}}):createReadinessCheck({id:`plane.${id}`,source:"plane",label,status:"fail",detail:PLANE_UNREPORTED_DETAIL,remediation:PLANE_UNREPORTED_REMEDIATION})})}var REQUIRED_REPO_FILES,PLANE_REPOSITORY_ROOT_REMEDIATION,PLANE_REPO_IDENTITY_REMEDIATION,PLANE_CREDENTIAL_REMEDIATION,PLANE_CREDENTIAL_PERMISSIONS_REMEDIATION,PLANE_CLAUDE_LOGIN_REMEDIATION,PLANE_SERVER_PORT_OCCUPIED_REMEDIATION,PLANE_SERVER_PORT_UNKNOWN_REMEDIATION,PLANE_SERVER_ENDPOINT_REMEDIATION,PLANE_MANIFEST_UNREADABLE_REMEDIATION,PLANE_ALREADY_RUNNING_REMEDIATION,PLANE_CREDENTIAL_OUTCOME_IDS,PLANE_ROOT_DEPENDENT_SKIP_DETAIL,ROOT_DEPENDENT_CHECKS,PLANE_PORT_PROBE_TIMEOUT_MS,PLANE_WORKTREE_REMEDIATION,PLANE_READINESS_DESCRIPTORS,PLANE_UNREPORTED_DETAIL,PLANE_UNREPORTED_REMEDIATION,init_preflight=__esm({"src/plane/preflight.ts"(){"use strict";init_types2();init_build_freshness();init_alembic_head();init_manifest();init_claude_login();init_readiness_check();REQUIRED_REPO_FILES=["main.py","worker.py","alembic.ini"],PLANE_REPOSITORY_ROOT_REMEDIATION="run `plane up` from the Bridge API repository root (the directory holding main.py, worker.py, and alembic.ini).",PLANE_REPO_IDENTITY_REMEDIATION="set BAPI_REPO_NAME in this shell, or add a valid .bridge/config at the repository root.",PLANE_CREDENTIAL_REMEDIATION="set BAPI_API_KEY in this shell, or store it with `mcp-server credentials`; a spawned shell never sees .mcp.json env.",PLANE_CREDENTIAL_PERMISSIONS_REMEDIATION="restrict the Bridge credentials file to owner-only permissions (chmod 600), then rerun.",PLANE_CLAUDE_LOGIN_REMEDIATION="run `claude login` on this host so plane members inherit an authenticated session; startup continues either way.",PLANE_SERVER_PORT_OCCUPIED_REMEDIATION=`stop the server that owns the port (or wind down its plane) and retry, or set ${PLANE_SERVER_PORT_ENV_VAR} to a free port \u2014 the port may belong to a SIBLING WORKTREE.`,PLANE_SERVER_PORT_UNKNOWN_REMEDIATION=`retry, or set ${PLANE_SERVER_PORT_ENV_VAR} to a port you know is free; startup continues and uvicorn fails loudly if the port is taken.`,PLANE_SERVER_ENDPOINT_REMEDIATION=`set ${PLANE_SERVER_PORT_ENV_VAR} to a valid port number (1-65535), or unset it to use the default.`,PLANE_MANIFEST_UNREADABLE_REMEDIATION="inspect .bridge/plane/plane.json and remove it by hand once you have confirmed no plane is running; preflight signalled no process and changed no file.",PLANE_ALREADY_RUNNING_REMEDIATION="run `plane status` to inspect the running plane, or `plane down` to wind it down first.",PLANE_CREDENTIAL_OUTCOME_IDS={identity:"repo-identity",credential:"bridge-credentials",permissions:"credential-permissions"},PLANE_ROOT_DEPENDENT_SKIP_DETAIL="not run \u2014 every remaining check is relative to a valid repository root",ROOT_DEPENDENT_CHECKS=[["worktree-presence","worktree-presence","Git work tree"],["claude-login","claude-login","Claude login"],["bridge-credentials",PLANE_CREDENTIAL_OUTCOME_IDS.identity,"Bridge repository identity"],["bridge-credentials",PLANE_CREDENTIAL_OUTCOME_IDS.credential,"Bridge API credential"],["bridge-credentials",PLANE_CREDENTIAL_OUTCOME_IDS.permissions,"Bridge credential file permissions"],["executor-build","executor-build","Executor build freshness"],["runtime-entrypoint","runtime-entrypoint","Runtime re-exec entrypoint"],["server-port","server-port","Local server port"],["alembic-head","alembic-head","Database migration head"],["existing-plane","existing-plane","Existing plane"]],PLANE_PORT_PROBE_TIMEOUT_MS=1500;PLANE_WORKTREE_REMEDIATION="cd into the intended worktree (or create it with `git worktree add`) and rerun.";PLANE_READINESS_DESCRIPTORS=[{id:"repository-root",label:"Repository root"},{id:"worktree-presence",label:"Git work tree"},{id:"claude-login",label:"Claude login"},{id:"repo-identity",label:"Bridge repository identity"},{id:"bridge-credentials",label:"Bridge API credential"},{id:"credential-permissions",label:"Bridge credential file permissions"},{id:"executor-build",label:"Executor build freshness"},{id:"runtime-entrypoint",label:"Runtime re-exec entrypoint"},{id:"server-port",label:"Local server port"},{id:"alembic-head",label:"Database migration head"},{id:"existing-plane",label:"Existing plane"}],PLANE_UNREPORTED_DETAIL="not reported \u2014 the plane preflight produced no outcome for this prerequisite",PLANE_UNREPORTED_REMEDIATION="run `plane up` (or `conductor readiness` again) to re-collect the plane preflight; this prerequisite's state is unknown, not healthy."}});var init_version_generated=__esm({"src/version.generated.ts"(){"use strict"}});var init_agents_generated=__esm({"src/agents.generated.ts"(){"use strict"}});var init_docs_generated=__esm({"src/docs.generated.ts"(){"use strict"}});var init_agent_utils=__esm({"src/agent-utils.ts"(){"use strict"}});var init_git_ignore_utils=__esm({"src/git-ignore-utils.ts"(){"use strict"}});var init_init=__esm({"src/init.ts"(){"use strict";init_commands_generated();init_agents_generated();init_docs_generated();init_version_generated();init_agent_utils();init_bridge_config();init_git_ignore_utils();init_credential_store();init_launcher_config_inspection();init_mcp_identity()}});function joinPath2(base,rel){let b=base.endsWith("/")?base.slice(0,-1):base,r=rel.startsWith("/")?rel.slice(1):rel;return`${b}/${r}`}function isEnoent(err){return typeof err=="object"&&err!==null&&err.code==="ENOENT"}async function readJsonHostConfig(path14,deps){let raw;try{raw=await deps.readFile(path14)}catch(err){return isEnoent(err)?{state:"missing"}:{state:"read-error",message:"config could not be read"}}let parsed;try{parsed=JSON.parse(raw)}catch{return{state:"invalid"}}return typeof parsed!="object"||parsed===null||Array.isArray(parsed)?{state:"invalid"}:{state:"valid",value:parsed}}function escapeRegExp(value){return value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function storedProfileTokens(value){return typeof value!="string"?[]:value.split(",").map(t=>t.trim()).filter(t=>t.length>0)}function entryProfileTokens(entry){if(!entry||typeof entry!="object"||Array.isArray(entry))return null;let env=entry.env,stored=env&&typeof env=="object"&&!Array.isArray(env)?env.BRIDGE_MCP_PROFILE:void 0;return storedProfileTokens(stored)}async function inspectOneProfileConfig(projectRoot,target,token,deps){let read=await readJsonHostConfig(joinPath2(projectRoot,target.path),deps);if(read.state==="missing")return{path:target.path,state:"absent"};if(read.state!=="valid")return{path:target.path,state:"unreadable"};let root=read.value[target.topLevelKey];if(!root||typeof root!="object"||Array.isArray(root))return{path:target.path,state:"no-bridge-entry"};let servers=root,tokenSets=RECOGNIZED_SERVER_NAMES.filter(name=>Object.prototype.hasOwnProperty.call(servers,name)).map(name=>entryProfileTokens(servers[name])).filter(tokens=>tokens!==null);return tokenSets.length===0?{path:target.path,state:"no-bridge-entry"}:{path:target.path,state:tokenSets.some(tokens=>tokens.includes(token))?"token-present":"token-absent"}}async function inspectBridgeApiProfileToken(projectRoot,token,deps){let configs=[];for(let target of BRIDGE_PROFILE_TOKEN_CONFIGS)configs.push(await inspectOneProfileConfig(projectRoot,target,token,deps));return{token,configs,tokenPresent:configs.some(c=>c.state==="token-present"),bridgeEntryPresent:configs.some(c=>c.state==="token-present"||c.state==="token-absent")}}var DUPLICATE_REGISTRATION_DETAIL,BRIDGE_TABLE_PATTERNS,BRIDGE_PROFILE_TOKEN_CONFIGS,init_mcp_host_config=__esm({"src/mcp-host-config.ts"(){"use strict";init_version_generated();init_init();init_mcp_host_targets();init_mcp_identity();DUPLICATE_REGISTRATION_DETAIL=`both \`${MCP_SERVER_NAME}\` and \`${LEGACY_SERVER_NAMES.join("`, `")}\` are registered here; confirm which one to keep, remove the other manually, then re-run. Nothing was changed.`;BRIDGE_TABLE_PATTERNS=RECOGNIZED_SERVER_NAMES.map(name=>({name,pattern:new RegExp(`^[ \\t]*\\[mcp_servers\\.${escapeRegExp(name)}(\\.[^\\]]*)?\\][ \\t]*$`,"m")})),BRIDGE_PROFILE_TOKEN_CONFIGS=[{path:".mcp.json",topLevelKey:"mcpServers"},{path:".vscode/mcp.json",topLevelKey:"servers"},{path:".cursor/mcp.json",topLevelKey:"mcpServers"}]}});var init_command_provisioning=__esm({"src/command-provisioning.ts"(){"use strict";init_commands_generated();init_git_ignore_utils()}});var init_ticket_key_utils=__esm({"src/ticket-key-utils.ts"(){"use strict"}});var init_claude_settings=__esm({"src/claude-settings.ts"(){"use strict"}});var init_start_tickets_conductor=__esm({"src/start-tickets-conductor.ts"(){"use strict";init_claude_settings();init_file_scope_guard();init_mcp_profile();init_start_tickets_repo()}});var WORKER_BRANCH_ENV_VAR,init_pr_base_contract=__esm({"src/pr-base-contract.ts"(){"use strict";WORKER_BRANCH_ENV_VAR="BAPI_WORKER_BRANCH"}});var INDEX_SCOPE_ENV_VAR,INDEX_SCOPE_CONFIGURATION_ERROR,init_index_scope_contract=__esm({"src/index-scope-contract.ts"(){"use strict";INDEX_SCOPE_ENV_VAR="BAPI_INDEX_SCOPE",INDEX_SCOPE_CONFIGURATION_ERROR=`${INDEX_SCOPE_ENV_VAR} is not a valid index-scope declaration. Expected a server-minted scope identity; the value was not logged.`}});var init_env_file_link=__esm({"src/env-file-link.ts"(){"use strict";init_worktree_core()}});var init_base_ref=__esm({"src/base-ref.ts"(){"use strict";init_claude_review_workflow_drift_probe();init_start_tickets_prereqs();init_claude_review_workflow_drift_probe()}});var STALE_LAUNCH_SCRIPT_MAX_AGE_MS,init_start_tickets=__esm({"src/start-tickets.ts"(){"use strict";init_version_generated();init_credential_store();init_mcp_identity();init_claude_review_workflow_drift();init_start_tickets_repo();init_mcp_provisioning();init_command_provisioning();init_mcp_server_invocation();init_ticket_key_utils();init_start_tickets_prereqs();init_agent_registry();init_start_tickets_conductor();init_bridge_api_client();init_pr_base_contract();init_index_scope_contract();init_worktree_core();init_env_file_link();init_base_ref();STALE_LAUNCH_SCRIPT_MAX_AGE_MS=1440*60*1e3}});var REQUIRED_ADAPTER_CAPABILITIES,init_executor_adapter=__esm({"src/agent-launchers/executor-adapter.ts"(){"use strict";REQUIRED_ADAPTER_CAPABILITIES=Object.freeze(["executable","platform","headlessInvocation","mcpScoping","mcpInitParsing","auth","authFailureDetection","denyEnforcement","redaction","lifecycle"])}});var init_executor_adapter_inspection=__esm({"src/agent-launchers/executor-adapter-inspection.ts"(){"use strict";init_executor_adapter()}});var WORKER_SENTINEL_DATABASE_NAME,WORKER_SENTINEL_DATABASE_URL,WORKER_SENTINEL_DATABASE_ENV_KEYS,EXPLICIT_DENY_KEYS,init_env=__esm({"src/executor/env.ts"(){"use strict";init_pr_base_contract();init_index_scope_contract();WORKER_SENTINEL_DATABASE_NAME="bridge_worker_no_database",WORKER_SENTINEL_DATABASE_URL=`postgresql://${WORKER_SENTINEL_DATABASE_NAME}@127.0.0.1:1/${WORKER_SENTINEL_DATABASE_NAME}`,WORKER_SENTINEL_DATABASE_ENV_KEYS=["DATABASE_URL","POSTGRES_DATABASE","POSTGRES_DB","PGDATABASE"],EXPLICIT_DENY_KEYS=["BRIDGE_MCP_PROFILE","CONDUCTOR_NODE_PATH","BAPI_API_KEY","ANTHROPIC_API_KEY","CLAUDE_CODE_OAUTH_TOKEN","OPENAI_API_KEY","GITHUB_TOKEN","GH_TOKEN","CLAUDE_CONFIG_DIR","XDG_CONFIG_HOME",INDEX_SCOPE_ENV_VAR,WORKER_BRANCH_ENV_VAR,...WORKER_SENTINEL_DATABASE_ENV_KEYS]}});var init_observation=__esm({"src/executor/observation.ts"(){"use strict"}});var init_job_errors=__esm({"src/executor/job-errors.ts"(){"use strict";init_observation()}});var init_permissions=__esm({"src/executor/permissions.ts"(){"use strict";init_claude_settings()}});var WORKER_GUARD_REASON_PREFIX,WORKER_GUARD_MALFORMED_LINE,init_worker_guard_hook=__esm({"src/executor/worker-guard-hook.ts"(){"use strict";WORKER_GUARD_REASON_PREFIX="bridge worker guard",WORKER_GUARD_MALFORMED_LINE=`${WORKER_GUARD_REASON_PREFIX}: payload could not be read; continuing fail-open`}});var init_process=__esm({"src/executor/process.ts"(){"use strict"}});var init_platform=__esm({"src/executor/platform.ts"(){"use strict";init_process()}});var init_claude_executor_adapter=__esm({"src/agent-launchers/claude-executor-adapter.ts"(){"use strict";init_agent_registry();init_claude_user_config_doctor();init_deny_enforcement_preflight();init_env();init_job_errors();init_permissions();init_worker_guard_hook();init_platform();init_observation();init_executor_adapter();init_mcp_identity()}});var init_executor_adapter_registry=__esm({"src/agent-launchers/executor-adapter-registry.ts"(){"use strict";init_agent_registry();init_claude_executor_adapter();init_executor_adapter()}});var init_env_flags=__esm({"src/env-flags.ts"(){"use strict"}});var init_bridge_api_urls=__esm({"src/bridge-api-urls.ts"(){"use strict"}});import{getMethodLiteral}from"@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";var init_tool_surface_gating=__esm({"src/tool-surface-gating.ts"(){"use strict"}});var init_bridge_client=__esm({"src/conduct-epic/bridge-client.ts"(){"use strict";init_bridge_api_client()}});var init_checkpoint_store=__esm({"src/conduct-epic/checkpoint-store.ts"(){"use strict"}});var init_lock=__esm({"src/conduct-epic/lock.ts"(){"use strict"}});var init_job_types=__esm({"src/executor/job-types.ts"(){"use strict"}});var init_worker_command=__esm({"src/executor/worker-command.ts"(){"use strict";init_job_errors();init_job_types()}});var init_worker_containment_diagnostic=__esm({"src/worker-containment-diagnostic.ts"(){"use strict";init_worker_command()}});var init_agent_identity=__esm({"src/executor/agent-identity.ts"(){"use strict";init_agent_registry()}});import{execFile as execFile2,spawn}from"node:child_process";import{promisify}from"node:util";var execFileAsync,MAX_COMMAND_BUFFER,init_deps=__esm({"src/executor/deps.ts"(){"use strict";init_mcp_server_invocation();execFileAsync=promisify(execFile2),MAX_COMMAND_BUFFER=10*1024*1024}});var init_base_url=__esm({"src/base-url.ts"(){"use strict"}});var DEFAULT_BAPI_BASE_URL,EXECUTOR_BASE_URL_REQUIRED_MESSAGE,init_credentials=__esm({"src/executor/credentials.ts"(){"use strict";init_credential_store();init_base_url();DEFAULT_BAPI_BASE_URL="https://bridgegpt-api.com",EXECUTOR_BASE_URL_REQUIRED_MESSAGE=`no Bridge API base URL configured for the executor: pass --base-url <url> or set BAPI_BASE_URL (production is ${DEFAULT_BAPI_BASE_URL}). The executor never defaults to production.`}});var init_types3=__esm({"src/executor/types.ts"(){"use strict"}});var init_http_client=__esm({"src/executor/http-client.ts"(){"use strict";init_types3();init_bridge_api_client()}});var init_preflight2=__esm({"src/executor/preflight.ts"(){"use strict";init_types();init_executor_adapter_inspection();init_executor_adapter_registry();init_agent_identity();init_credentials()}});var init_heartbeat=__esm({"src/executor/heartbeat.ts"(){"use strict";init_process();init_types3()}});var init_github_mergeability=__esm({"src/conductor/github-mergeability.ts"(){"use strict"}});var init_latest_check_selector=__esm({"src/conductor/latest-check-selector.ts"(){"use strict"}});var init_local_merge=__esm({"src/conductor/local-merge.ts"(){"use strict";init_bridge_api_client();init_github_mergeability();init_latest_check_selector()}});var init_epic_integration_pr=__esm({"src/epic-integration-pr.ts"(){"use strict"}});var init_base_branch=__esm({"src/executor/base-branch.ts"(){"use strict";init_base_ref()}});var init_merge_job=__esm({"src/executor/merge-job.ts"(){"use strict";init_local_merge();init_bridge_api_client();init_epic_integration_pr();init_job_errors();init_base_branch()}});var init_worktree_inspection=__esm({"src/executor/worktree-inspection.ts"(){"use strict";init_job_errors()}});var init_resume_pre_spawn=__esm({"src/executor/resume-pre-spawn.ts"(){"use strict";init_worktree_core();init_job_errors();init_worktree_inspection()}});var init_prompt_spec=__esm({"src/executor/prompt-spec.ts"(){"use strict";init_job_errors()}});var init_results=__esm({"src/executor/results.ts"(){"use strict"}});var init_terminal_mutation=__esm({"src/executor/terminal-mutation.ts"(){"use strict";init_types3()}});var init_verdict_artifact=__esm({"src/executor/verdict-artifact.ts"(){"use strict";init_job_errors();init_worktree_inspection()}});var init_stale_artifacts=__esm({"src/executor/stale-artifacts.ts"(){"use strict";init_verdict_artifact();init_worktree_inspection()}});var init_env_file_guard=__esm({"src/executor/env-file-guard.ts"(){"use strict";init_worktree_inspection()}});var init_worker_log=__esm({"src/executor/worker-log.ts"(){"use strict";init_worktree_inspection()}});var init_worktree_lock=__esm({"src/executor/worktree-lock.ts"(){"use strict";init_worktree_inspection()}});var init_job_log_registry=__esm({"src/executor/job-log-registry.ts"(){"use strict";init_worktree_inspection()}});var init_viewer_tabs=__esm({"src/executor/viewer-tabs.ts"(){"use strict";init_start_tickets()}});var init_index_scope=__esm({"src/executor/index-scope.ts"(){"use strict";init_index_scope_contract()}});var init_worker_finalization=__esm({"src/executor/worker-finalization.ts"(){"use strict";init_job_errors();init_job_types()}});var init_worktree=__esm({"src/executor/worktree.ts"(){"use strict";init_base_ref();init_claude_review_workflow_drift();init_start_tickets_prereqs();init_worktree_core();init_command_provisioning()}});var REQUIRED_MCP_REGISTRATION_MISSING_MESSAGE,init_job_runner=__esm({"src/executor/job-runner.ts"(){"use strict";init_heartbeat();init_job_errors();init_merge_job();init_observation();init_mcp_provisioning();init_executor_adapter_registry();init_executor_adapter();init_agent_identity();init_process();init_resume_pre_spawn();init_prompt_spec();init_start_tickets_conductor();init_results();init_terminal_mutation();init_stale_artifacts();init_env_file_guard();init_verdict_artifact();init_worker_log();init_worktree_lock();init_job_log_registry();init_viewer_tabs();init_job_types();init_base_branch();init_index_scope();init_worker_finalization();init_worktree();init_pr_base_contract();init_worker_command();init_observation();init_mcp_identity();REQUIRED_MCP_REGISTRATION_MISSING_MESSAGE=`the required '${MCP_SERVER_NAME}' MCP registration is missing or unreadable in the prepared worktree; a worker loads MCP servers strictly from that file, so refusing to spawn a worker that would run without Bridge tools`}});var init_live_worker_registry=__esm({"src/executor/live-worker-registry.ts"(){"use strict"}});var EXECUTOR_WORKTREE_GC_IDLE_MS,init_worktree_gc=__esm({"src/executor/worktree-gc.ts"(){"use strict";init_worktree_inspection();EXECUTOR_WORKTREE_GC_IDLE_MS=1440*60*1e3}});var init_runner=__esm({"src/executor/runner.ts"(){"use strict";init_preflight2();init_job_runner();init_job_log_registry();init_live_worker_registry();init_worktree_gc();init_base_ref();init_epic_integration_pr()}});var init_watch_cli=__esm({"src/executor/watch-cli.ts"(){"use strict";init_job_log_registry()}});var init_cli=__esm({"src/executor/cli.ts"(){"use strict";init_version_generated();init_start_tickets_prereqs();init_start_tickets_repo();init_agent_identity();init_deps();init_credentials();init_http_client();init_platform();init_runner();init_watch_cli()}});function executorLaunchdDirForHome(homeDir){return pathApiForPlatform("darwin").join(homeDir,...LAUNCHD_DIR_SEGMENTS)}function executorSystemdDirForHome(homeDir){return pathApiForPlatform("linux").join(homeDir,...SYSTEMD_DIR_SEGMENTS)}function executorIdFromLaunchdFilename(filename){if(!filename.startsWith(EXECUTOR_LAUNCHD_LABEL_PREFIX)||!filename.endsWith(EXECUTOR_LAUNCHD_FILENAME_SUFFIX))return null;let id=filename.slice(EXECUTOR_LAUNCHD_LABEL_PREFIX.length,filename.length-EXECUTOR_LAUNCHD_FILENAME_SUFFIX.length);return id.length>0?id:null}function executorIdFromSystemdFilename(filename){if(!filename.startsWith(EXECUTOR_SYSTEMD_UNIT_PREFIX)||!filename.endsWith(EXECUTOR_SYSTEMD_UNIT_SUFFIX))return null;let id=filename.slice(EXECUTOR_SYSTEMD_UNIT_PREFIX.length,filename.length-EXECUTOR_SYSTEMD_UNIT_SUFFIX.length);return id.length>0?id:null}function xmlUnescape(value){return value.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}function readArgumentContract(args){let repos=[],executorId=null;for(let i=0;i<args.length;i++)args[i]==="--repo"&&typeof args[i+1]=="string"?repos.push(args[++i]):args[i]==="--executor-id"&&typeof args[i+1]=="string"&&(executorId=args[++i]);return{repos,executorId}}function inspectLaunchdPlist(content){let problems=[],envMatch=content.match(new RegExp(`<key>${EXECUTOR_SERVICE_BASE_URL_ENV}</key>\\s*<string>([^<]*)</string>`)),baseUrl=envMatch?xmlUnescape(envMatch[1]):null;baseUrl===null&&problems.push(`no ${EXECUTOR_SERVICE_BASE_URL_ENV} entry found in the plist`);let arrayMatch=content.match(/<key>ProgramArguments<\/key>\s*<array>([\s\S]*?)<\/array>/),args=[];arrayMatch?args=Array.from(arrayMatch[1].matchAll(/<string>([^<]*)<\/string>/g)).map(m=>xmlUnescape(m[1])):problems.push("no ProgramArguments array found in the plist");let{repos,executorId}=readArgumentContract(args);return{ok:problems.length===0,baseUrl,repos,executorId,problems}}function splitSystemdTokens(value){let tokens=[],current="",inQuotes=!1,started=!1;for(let i=0;i<value.length;i++){let ch=value[i];ch==="\\"&&i+1<value.length?(current+=value[++i],started=!0):ch==="%"&&value[i+1]==="%"?(current+="%",i++,started=!0):ch==='"'?(inQuotes=!inQuotes,started=!0):!inQuotes&&/\s/.test(ch)?(started&&tokens.push(current),current="",started=!1):(current+=ch,started=!0)}return started&&tokens.push(current),tokens}function inspectSystemdService(content){let problems=[],lines=content.split(/\r?\n/),envLine=lines.find(l=>l.startsWith(`Environment=${EXECUTOR_SERVICE_BASE_URL_ENV}=`)),baseUrl=null;if(envLine){let raw=envLine.slice(`Environment=${EXECUTOR_SERVICE_BASE_URL_ENV}=`.length);baseUrl=splitSystemdTokens(raw)[0]??null}(baseUrl===null||baseUrl.length===0)&&(baseUrl=null,problems.push(`no ${EXECUTOR_SERVICE_BASE_URL_ENV} directive found in the unit`));let execLine=lines.find(l=>l.startsWith("ExecStart=")),args=[];execLine?args=splitSystemdTokens(execLine.slice(10)):problems.push("no ExecStart directive found in the unit");let{repos,executorId}=readArgumentContract(args);return{ok:problems.length===0,baseUrl,repos,executorId,problems}}function inspectExecutorServiceArtifact(kind,content){try{return kind==="launchd-plist"?inspectLaunchdPlist(content):inspectSystemdService(content)}catch{return{ok:!1,baseUrl:null,repos:[],executorId:null,problems:["unit content could not be parsed"]}}}var EXECUTOR_LAUNCHD_LABEL_PREFIX,EXECUTOR_LAUNCHD_FILENAME_SUFFIX,EXECUTOR_SYSTEMD_UNIT_PREFIX,EXECUTOR_SYSTEMD_UNIT_SUFFIX,EXECUTOR_SERVICE_BASE_URL_ENV,LAUNCHD_DIR_SEGMENTS,SYSTEMD_DIR_SEGMENTS,init_service_unit=__esm({"src/executor/service-unit.ts"(){"use strict";init_platform_escaping();init_worktree_core();init_mcp_server_invocation();init_cli();init_credentials();EXECUTOR_LAUNCHD_LABEL_PREFIX="com.bridge-gpt.executor.",EXECUTOR_LAUNCHD_FILENAME_SUFFIX=".plist",EXECUTOR_SYSTEMD_UNIT_PREFIX="bridge-gpt-executor-",EXECUTOR_SYSTEMD_UNIT_SUFFIX=".service",EXECUTOR_SERVICE_BASE_URL_ENV="BAPI_BASE_URL",LAUNCHD_DIR_SEGMENTS=["Library","LaunchAgents"],SYSTEMD_DIR_SEGMENTS=[".config","systemd","user"]}});var init_service_lifecycle=__esm({"src/executor/service-lifecycle.ts"(){"use strict";init_platform_escaping()}});var init_install_preflight=__esm({"src/executor/install-preflight.ts"(){"use strict";init_claude_login();init_platform()}});var init_executor=__esm({"src/executor/index.ts"(){"use strict";init_cli();init_runner();init_service_unit();init_service_lifecycle();init_install_preflight();init_watch_cli()}});var init_stale_worktree_doctor=__esm({"src/stale-worktree-doctor.ts"(){"use strict";init_worktree_core()}});import path12 from"path";function resolveExecutorServiceConvention(platform,homeDir){return platform==="darwin"?{dir:executorLaunchdDirForHome(homeDir),kind:"launchd-plist",idFromFilename:executorIdFromLaunchdFilename}:platform==="linux"?{dir:executorSystemdDirForHome(homeDir),kind:"systemd-service",idFromFilename:executorIdFromSystemdFilename}:null}async function probeRepoCredential(repo,deps,credDeps){let target=`bapi:${repo}`,resolve2=deps.resolveCredentials??resolveBapiCredentials;try{let result=await resolve2(repo,credDeps);return result.ok?{repo,target,resolved:!0,source:String(result.credentials.source)}:{repo,target,resolved:!1,kind:String(result.kind)}}catch{return{repo,target,resolved:!1,kind:"unavailable"}}}async function collectExecutorServiceDiagnostics(deps){if(deps.platform==="win32")return{status:"skipped",reason:"Windows executor services are set up manually through Task Scheduler, so there is no generated unit to enumerate (`executor install-service` prints the command line instead)."};let convention=resolveExecutorServiceConvention(deps.platform,deps.homedir());if(!convention)return{status:"skipped",reason:`platform '${deps.platform}' has no generated executor service format.`};let entries;try{entries=await deps.readdir(convention.dir)}catch{return{status:"skipped",reason:`no executor service units found (${convention.dir} is absent or unreadable).`}}let matching=entries.filter(name=>convention.idFromFilename(name)!==null).sort((a,b)=>a<b?-1:a>b?1:0);if(matching.length===0)return{status:"skipped",reason:`no executor service units found in ${convention.dir}.`};let credDeps={env:deps.env,homedir:deps.homedir,platform:deps.platform,readFile:deps.readFile,stat:deps.stat,stderr:()=>{}},pathApi=path12.posix,units=[],warnings=[];for(let name of matching){let unitPath=pathApi.join(convention.dir,name),executorId=convention.idFromFilename(name)??name;try{await deps.stat(unitPath)}catch{warnings.push(`${unitPath}: disappeared or became unreadable during collection.`);continue}let content;try{content=await deps.readFile(unitPath)}catch{units.push({path:unitPath,executorId,baseUrl:null,baseUrlClass:"missing",repos:[],credentials:[],warnings:["unit could not be read; its configuration cannot be verified."]});continue}let inspection=inspectExecutorServiceArtifact(convention.kind,content),unitWarnings=[...inspection.problems],baseUrlClass;inspection.baseUrl?inspection.baseUrl.replace(/\/+$/,"")===DEFAULT_BAPI_BASE_URL?(baseUrlClass="production-default",unitWarnings.push(`${EXECUTOR_SERVICE_BASE_URL_ENV} points at production (${DEFAULT_BAPI_BASE_URL}) \u2014 legal, but worth confirming this host is meant to serve production jobs.`)):baseUrlClass="configured":(baseUrlClass="missing",unitWarnings.push(`no ${EXECUTOR_SERVICE_BASE_URL_ENV} in the unit \u2014 the executor requires an explicit base URL and will fail to start.`));let distinctRepos=Array.from(new Set(inspection.repos)),credentials=[];for(let repo of distinctRepos)credentials.push(await probeRepoCredential(repo,deps,credDeps));units.push({path:unitPath,executorId,baseUrl:inspection.baseUrl,baseUrlClass,repos:inspection.repos,credentials,warnings:unitWarnings})}return{status:"collected",units,warnings}}var LEGACY_REGISTRATION_INFO_TEXT,init_doctor2=__esm({"src/doctor.ts"(){"use strict";init_start_tickets();init_version_generated();init_install_doctor();init_executor_adapter_inspection();init_executor_adapter_registry();init_env_flags();init_bridge_api_urls();init_tool_surface_gating();init_credential_store();init_bridge_api_client();init_bridge_client();init_checkpoint_store();init_lock();init_start_tickets_repo();init_worker_containment_diagnostic();init_launcher_config_inspection();init_mcp_identity();init_agent_registry();init_start_tickets_prereqs();init_mcp_profile();init_executor();init_credentials();init_claude_login();init_base_ref();init_ticket_key_utils();init_worktree_core();init_stale_worktree_doctor();LEGACY_REGISTRATION_INFO_TEXT=`This registration remains supported. New installs use \`${MCP_SERVER_NAME}\`. No action is required.`}});function supervisorSection(readiness){let s=readiness.supervisor,sections=[];if(!s.setup_present||!s.config_present){let missing=[s.setup_present?null:"setup",s.config_present?null:"config"].filter(Boolean).join(" and ");sections.push({id:"supervisor-configuration",label:"Supervisor configuration",status:"degraded",detail:`project-default supervisor ${missing} absent`,remediation:"bootstrap writes the safe project-default posture."})}else sections.push({id:"supervisor-configuration",label:"Supervisor configuration",status:"ok",detail:`setup=${s.setup_source}, config=${s.config_source}`});sections.push(s.required_checks_empty?{id:"supervisor-required-checks",label:"Supervisor required CI checks",status:"degraded",detail:"required-check list is EMPTY \u2014 the done gate would pass unconditionally",remediation:"bootstrap writes a non-empty required-check list into done_gate_config."}:{id:"supervisor-required-checks",label:"Supervisor required CI checks",status:"ok",detail:`${s.required_checks_count} required check(s) configured`});let alignment=s.review_policy_alignment;return alignment!==null&&(alignment.status==="divergent"||alignment.status==="invalid"?sections.push({id:"supervisor-review-alignment",label:"Supervisor review-policy alignment",status:"degraded",detail:alignment.explanation,remediation:alignment.status==="invalid"?"fix the done gate's review_state condition \u2014 review configuration exists but cannot be read, so the merge path refuses rather than merges.":`set the repository review-policy default and the done gate's review_state condition to the same signal, or confirm the difference is intended \u2014 see ${CONDUCTOR_OPERATOR_RUNBOOK_POINTER}.`}):sections.push({id:"supervisor-review-alignment",label:"Supervisor review-policy alignment",status:"ok",detail:alignment.explanation})),sections}function githubCredentialsSection(readiness){let g=readiness.github;if(g.credentials_complete)return{id:"github-credentials",label:"GitHub App credentials",status:"ok",detail:"owner, repository id, and installation id all resolved"};let missing=[g.owner_resolved?null:"owner",g.repo_id_resolved?null:"repository id",g.installation_id_resolved?null:"installation id"].filter(Boolean).join(", ");return{id:"github-credentials",label:"GitHub App credentials",status:"degraded",detail:g.credentials_readable?`incomplete: ${missing} unresolved`:"no GitHub credential row for this repository",remediation:"connect GitHub from the Bridge setup UI (`install-bridge connect-github`)."}}function githubActionsSection(readiness){let g=readiness.github;return g.actions_write?{id:"github-actions-permission",label:"GitHub App actions permission",status:"ok",detail:"actions: write"}:g.actions_probe_succeeded?{id:"github-actions-permission",label:"GitHub App actions permission",status:"degraded",detail:`actions: ${g.actions_permission_level}`,remediation:"grant the GitHub App `actions: write`; the conductor's workflow rerun lane fails open on 403 without it."}:{id:"github-actions-permission",label:"GitHub App actions permission",status:"degraded",detail:"permission could not be checked",remediation:"re-run once credentials resolve; the workflow rerun lane fails open on 403 until this reads `write`."}}function reconcilerSection(readiness){let r=readiness.reconciler;return r.liveness_readable?r.stale?{id:"reconciler-liveness",label:"Reconciler tick liveness",status:"degraded",detail:r.last_tick_at===null?"no reconciler tick recorded for this repository":`last tick ${r.last_tick_age_seconds}s ago (threshold ${readiness.thresholds.reconciler_stale_after_seconds}s)`,remediation:"start the reconciler (`conductor epic-tick` schedule) for this repository."}:{id:"reconciler-liveness",label:"Reconciler tick liveness",status:"ok",detail:`last tick ${r.last_tick_age_seconds}s ago across ${r.active_run_count} active run(s)`}:{id:"reconciler-liveness",label:"Reconciler tick liveness",status:"degraded",detail:"liveness could not be read",remediation:"retry once the Bridge API is reachable; reconciler liveness is unknown here, which is not the same as confirmed-stale."}}function workflowSection(presence,reviewPolicySource,driftDetail){return presence==="present"?{id:"claude-review-workflow",label:"claude-review workflow",status:"ok",detail:driftDetail?`.github/workflows/claude-review.yml present \u2014 ${driftDetail}`:".github/workflows/claude-review.yml present"}:presence==="drifted"?{id:"claude-review-workflow",label:"claude-review workflow",status:"degraded",detail:driftDetail??".github/workflows/claude-review.yml differs from the repository default branch",remediation:CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION}:reviewPolicySource==="native_review_decision"||reviewPolicySource==="none"?{id:"claude-review-workflow",label:"claude-review workflow",status:"ok",detail:`not applicable for review policy '${reviewPolicySource}'`}:{id:"claude-review-workflow",label:"claude-review workflow",status:"degraded",detail:presence==="unreadable"?".github/workflows/claude-review.yml could not be read":".github/workflows/claude-review.yml absent",remediation:"the selected review policy consumes the sticky verdict this workflow emits; install the template."}}function executorProvisioningSection(diagnostics){let base={id:"executor-provisioning",label:"Executor provisioning"};if(diagnostics===null)return{...base,status:"degraded",detail:"executor service-unit diagnostics could not be collected",remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION};if(diagnostics.status==="skipped")return{...base,status:"degraded",detail:diagnostics.reason,remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION};let unhealthy=diagnostics.units.filter(unit=>unit.warnings.length>0||unit.credentials.some(cred=>!cred.resolved)),ids=diagnostics.units.map(unit=>unit.executorId).join(", ");return unhealthy.length===0&&diagnostics.warnings.length===0?{...base,status:"ok",detail:`${diagnostics.units.length} generated service unit(s) found (${ids}); unit presence only \u2014 see the service-state and observation sections`}:{...base,status:"degraded",detail:`${diagnostics.units.length} generated service unit(s) found (${ids}), but ${unhealthy.length} unit(s) carry warnings or unresolved credentials \u2014 see the embedded executor-provisioning report`,remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION}}function executorServiceStateSection(observations,unitsDiscovered,inspectorAvailable){let base={id:"executor-service-state",label:"Executor service state"};if(!unitsDiscovered)return{...base,status:"degraded",detail:"no generated unit to inspect, so no service state was collected",remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION};if(!inspectorAvailable||observations.length===0)return{...base,status:"degraded",detail:"local service state could not be collected on this host",remediation:EXECUTOR_SERVICE_START_REMEDIATION};let rendered=[...observations].sort((a,b)=>a.executorId<b.executorId?-1:a.executorId>b.executorId?1:0).map(o=>`${o.executorId}=${o.state}`).join(", ");return observations.every(o=>o.state==="active")?{...base,status:"ok",detail:`service state: ${rendered}`}:{...base,status:"degraded",detail:`service state: ${rendered}`,remediation:EXECUTOR_SERVICE_START_REMEDIATION}}function executorObservationSection(readiness){let base={id:"executor-observation",label:"Executor server observation"};if(readiness===null||!readiness.executor.liveness_readable)return{...base,status:"degraded",detail:"server executor observation is unknown (readiness could not be read)",remediation:"retry once the Bridge API is reachable; no readiness claim is made from local state."};let e=readiness.executor,seen=e.last_seen_at===null?"never seen":`last seen ${e.last_seen_at} (${e.last_seen_age_seconds}s ago)`;return e.ready===!0?{...base,status:"ok",detail:`executor_ready \u2014 ${seen}`}:e.ready===!1?{...base,status:"degraded",detail:`observed but stale/not ready \u2014 ${seen}`,remediation:EXECUTOR_SERVICE_START_REMEDIATION}:{...base,status:"degraded",detail:`never observed by the server \u2014 ${seen}`,remediation:EXECUTOR_SERVICE_START_REMEDIATION}}function detectConductorContext(legacyConductor,profile){return legacyConductor?.mcp_profile?.conductor_context_detected===!0||profile?.tokenPresent===!0}function conductorProfileTokenSection(profile,conductorContext){let base={id:"conductor-profile-token",label:"MCP conductor profile token"};if(profile===null)return{...base,status:"degraded",detail:"the host MCP profile token could not be inspected",remediation:CONDUCTOR_PROFILE_TOKEN_REMEDIATION};let carrying=profile.configs.filter(c=>c.state==="token-present").map(c=>c.path),scope="inspected .mcp.json, .vscode/mcp.json, .cursor/mcp.json only (Codex and Copilot host configuration is not inspected)";if(carrying.length>0)return{...base,status:"ok",detail:`\`${profile.token}\` present in ${carrying.join(", ")}; ${scope}`};let detail=profile.bridgeEntryPresent?`no supported host config carries the \`${profile.token}\` token; ${scope}`:`no supported host config carries a Bridge entry; ${scope}`,remediation=profile.bridgeEntryPresent?CONDUCTOR_PROFILE_TOKEN_REMEDIATION:CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION;return conductorContext?{...base,status:"degraded",detail,remediation}:{...base,status:"ok",detail:`advisory \u2014 ${detail}`,remediation}}function conductorHookTargetsSection(legacyConductor,conductorContext){let base={id:"conductor-hook-targets",label:"Conductor hook targets"};if(legacyConductor==null)return{...base,status:"degraded",detail:"hook targets could not be derived (the conductor doctor was not collected)",remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION};let hooks=legacyConductor.git_hooks;if(hooks===void 0)return{...base,status:"degraded",detail:"hook targets could not be derived (the conductor doctor reported no hook state)",remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION};if(!hooks.is_worktree)return{...base,status:"ok",detail:"advisory \u2014 not a git worktree, so no managed conductor hooks apply"};let usable=name=>{let hook=(hooks.hooks??[]).find(h=>h.name===name);return hook!==void 0&&hook.exists&&hook.managed_block_present&&hook.embedded_bin_is_file},rendered=MANAGED_HOOK_NAMES.map(name=>`${name}=${usable(name)}`).join(", ");if(MANAGED_HOOK_NAMES.every(name=>usable(name)))return{...base,status:"ok",detail:`managed hooks usable: ${rendered}`};let detail=`managed hooks usable: ${rendered}`;return conductorContext?{...base,status:"degraded",detail,remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION}:{...base,status:"ok",detail:`advisory \u2014 ${detail}`,remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION}}function conductorLedgerLoadabilitySection(legacyConductor){let base={id:"conductor-ledger-loadability",label:"Conductor ledger loadability"};if(legacyConductor==null)return{...base,status:"degraded",detail:"ledger loadability could not be derived (the conductor doctor was not collected)",remediation:CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION};let inspection=legacyConductor.native_ledger;if(inspection===void 0)return{...base,status:"degraded",detail:"ledger loadability could not be derived (the conductor doctor reported no native-ledger state)",remediation:CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION};let availability=describeNativeLedgerAvailability(inspection);return availability.status==="available"?{...base,status:"ok",detail:"ledger available \u2014 the native binding loads"}:{...base,status:"degraded",detail:`ledger degraded \u2014 ${availability.module} did not load (NODE_MODULE_VERSION ${availability.nodeModulesAbi}, failure: ${availability.failureKind})`,remediation:CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION}}async function inspectWorkflowPresence(readWorkflowFile,classifyWorkflowDrift){let local=await inspectWorkflowLocalPresence(readWorkflowFile);if(local!=="present"||!classifyWorkflowDrift)return{presence:local};try{let classification=await classifyWorkflowDrift();return classification.state==="drifted"?{presence:"drifted",driftDetail:summarizeClaudeReviewWorkflowDrift(classification)}:classification.state==="unverified"?{presence:"present",driftDetail:summarizeClaudeReviewWorkflowDrift(classification)}:{presence:"present"}}catch{return{presence:"present"}}}async function inspectWorkflowLocalPresence(readWorkflowFile){try{return await readWorkflowFile(),"present"}catch(err){return err?.code==="ENOENT"?"absent":"unreadable"}}var CONDUCTOR_OPERATOR_RUNBOOK_POINTER,CONDUCTOR_PROFILE_TOKEN,CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION,CONDUCTOR_PROFILE_TOKEN_REMEDIATION,CONDUCTOR_HOOK_TARGET_REMEDIATION,CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION,EXECUTOR_INSTALL_SERVICE_REMEDIATION,EXECUTOR_SERVICE_START_REMEDIATION,init_readiness_sections=__esm({"src/conductor/readiness-sections.ts"(){"use strict";init_git_hooks();init_mcp_identity();init_claude_review_workflow_drift();init_doctor();CONDUCTOR_OPERATOR_RUNBOOK_POINTER="docs/claude/epic-conductor-v2-operator-runbook.md",CONDUCTOR_PROFILE_TOKEN="conductor",CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION=`no supported host MCP config carries a Bridge entry \u2014 run \`npx ${MCP_PACKAGE_NAME} install\` to register one, then re-run \`install conductor\`.`,CONDUCTOR_PROFILE_TOKEN_REMEDIATION="re-run `install conductor` and accept the tool-visibility consent; the conductor tools become visible after the MCP client is restarted.",CONDUCTOR_HOOK_TARGET_REMEDIATION="re-run `install conductor` and accept the local-observability consent, or run `conductor install-git-hooks` directly.",CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION="`better-sqlite3` is an optionalDependency npm silently skips on a build failure \u2014 reinstall it for this Node runtime to restore local conductor observability.",EXECUTOR_INSTALL_SERVICE_REMEDIATION=`generate a persistent unit with \`install conductor --executor-id <id>\` or \`executor install-service\` (or run the executor by hand) \u2014 see ${CONDUCTOR_OPERATOR_RUNBOOK_POINTER}.`,EXECUTOR_SERVICE_START_REMEDIATION=`start the service (re-run \`install conductor\` and accept the start consent, or run the printed launchctl/systemctl command by hand) \u2014 see ${CONDUCTOR_OPERATOR_RUNBOOK_POINTER}.`}});import{readdir as fsReaddir,readFile as fsReadFile,stat as fsStat}from"node:fs/promises";import os5 from"node:os";async function settle(collect){if(!collect)return{value:null,failed:!1};try{return{value:await collect(),failed:!1}}catch{return{value:null,failed:!0}}}async function runConductorInstallDoctor(deps){let sections=[],buildConductor=deps.buildConductorReport??buildConductorDoctorReport,collectInstall=deps.collectInstallChecks??(deps.installDoctorDeps?()=>collectInstallStatusChecks(deps.installDoctorDeps):null),[conductorSettled,executorPreflightSettled,installChecksSettled]=await Promise.all([settle(()=>buildConductor(deps.conductorDoctorDeps)),settle(deps.collectExecutorPreflight?()=>deps.collectExecutorPreflight():null),settle(collectInstall)]),legacyConductor=conductorSettled.value??null;conductorSettled.failed&§ions.push({id:"conductor-ledger",label:"Conductor ledger doctor",status:"degraded",detail:"the local conductor doctor could not be built",remediation:"run `conductor doctor` directly to see why the local ledger report failed."});let legacyExecutorPreflight=executorPreflightSettled.value??null;executorPreflightSettled.failed&§ions.push({id:"executor-preflight",label:"Executor preflight",status:"degraded",detail:"the executor preflight could not be collected",remediation:"re-run this command; if it persists, run `executor` directly to surface the preflight failure."});let legacyInstallChecks=installChecksSettled.value??null;installChecksSettled.failed&§ions.push({id:"install-status",label:"Bridge install status",status:"degraded",detail:"the install-status checklist could not be collected",remediation:"run `doctor` to collect the advisory install-status checklist on its own."});let readiness=null;if(!deps.access)sections.push({id:"bridge-access",label:"Bridge API access",status:"fatal",detail:deps.accessError??"Bridge API repository/credential could not be resolved",remediation:"run `install-bridge` (or set BAPI_API_KEY) for this repository."});else try{readiness=await fetchConductorReadiness(deps.access,deps.fetch)}catch(err){let kind=err instanceof ConductorBridgeApiError?err.kind:"network",fatalKind=kind==="unauthorized"||kind==="invalid-input";sections.push({id:"server-readiness",label:"Server readiness",status:fatalKind?"fatal":"degraded",detail:kind==="unauthorized"?"Bridge API rejected the credential for this repository":kind==="invalid-input"?"the readiness response failed shape validation":"the readiness endpoint could not be reached",remediation:fatalKind?"re-check the API key and repository, then re-run.":"retry; the local sections above are unaffected."})}readiness&&(sections.push(...supervisorSection(readiness)),sections.push(githubCredentialsSection(readiness)),sections.push(githubActionsSection(readiness)));let workflow=await inspectWorkflowPresence(deps.readWorkflowFile,deps.classifyWorkflowDrift);sections.push(workflowSection(workflow.presence,deps.reviewPolicySource,workflow.driftDetail)),readiness&§ions.push(reconcilerSection(readiness));let collectServiceUnits=deps.collectExecutorServiceUnits??(()=>collectExecutorServiceDiagnostics({platform:process.platform,env:process.env,homedir:os5.homedir,readdir:dirPath=>fsReaddir(dirPath),readFile:filePath=>fsReadFile(filePath,"utf-8"),stat:filePath=>fsStat(filePath)})),executorService=null;try{executorService=await collectServiceUnits()}catch{}sections.push(executorProvisioningSection(executorService));let discoveredUnits=executorService!==null&&executorService.status!=="skipped"?executorService.units:[],executorServiceStates=[];if(deps.inspectExecutorServiceState&&discoveredUnits.length>0)for(let unit of discoveredUnits)try{let state=await deps.inspectExecutorServiceState({executorId:unit.executorId});executorServiceStates.push({executorId:unit.executorId,state})}catch{executorServiceStates.push({executorId:unit.executorId,state:"unknown"})}sections.push(executorServiceStateSection(executorServiceStates,discoveredUnits.length>0,!!deps.inspectExecutorServiceState)),sections.push(executorObservationSection(readiness));let inspectProfile=deps.inspectProfileToken??((projectRoot,token)=>inspectBridgeApiProfileToken(projectRoot,token,{readFile:filePath=>fsReadFile(filePath,"utf-8")})),profileToken=null;try{profileToken=await inspectProfile(deps.projectRoot??process.cwd(),CONDUCTOR_PROFILE_TOKEN)}catch{}let conductorContext=detectConductorContext(legacyConductor,profileToken);return sections.push(conductorProfileTokenSection(profileToken,conductorContext)),sections.push(conductorHookTargetsSection(legacyConductor,conductorContext)),sections.push(conductorLedgerLoadabilitySection(legacyConductor)),{legacyConductor,legacyExecutorPreflight,legacyInstallChecks,executorService,executorServiceStates,readiness,sections}}var init_install_doctor2=__esm({"src/conductor/install-doctor.ts"(){"use strict";init_doctor();init_mcp_host_config();init_doctor2();init_install_doctor();init_readiness_sections();init_bridge_api_client();init_readiness_sections()}});function mapServerReadinessToChecks(readiness,failure="unreachable"){if(readiness===null){let copy=SERVER_FAILURE_COPY[failure];return SERVER_READINESS_DESCRIPTORS.map(({id,label})=>createReadinessCheck({id:`server.${id}`,source:"server",label,status:"fail",detail:copy.detail,remediation:copy.remediation}))}let s=readiness.supervisor,g=readiness.github,r=readiness.reconciler,e=readiness.executor,outcomes=[];outcomes.push(s.setup_present?{id:"supervisor-setup",status:"pass",detail:`stored (source: ${s.setup_source})`}:{id:"supervisor-setup",status:"fail",detail:"no supervisor setup is stored for this repository",remediation:SERVER_REMEDIATIONS.supervisorSetup}),outcomes.push(s.config_present?{id:"supervisor-config",status:"pass",detail:`stored (source: ${s.config_source})`}:{id:"supervisor-config",status:"fail",detail:"no supervisor configuration is stored for this repository",remediation:SERVER_REMEDIATIONS.supervisorConfig}),outcomes.push(s.required_checks_empty?{id:"supervisor-required-checks",status:"warn",detail:"the required-check list is EMPTY \u2014 the done gate would pass unconditionally",remediation:SERVER_REMEDIATIONS.requiredChecks}:{id:"supervisor-required-checks",status:"pass",detail:`${s.required_checks_count} required check(s) configured`}),outcomes.push({id:"auto-merge",status:"pass",detail:s.auto_merge_enabled?"auto-merge enabled":"auto-merge disabled (operator posture)"}),outcomes.push(s.merge_approval_required_set?{id:"merge-approval",status:"pass",detail:"merge-approval requirement is set explicitly"}:{id:"merge-approval",status:"warn",detail:"the merge-approval requirement is unset, so the merge path falls back to its default",remediation:SERVER_REMEDIATIONS.mergeApproval}),outcomes.push(reviewPolicyOutcome(readiness)),outcomes.push(g.credentials_complete?{id:"github-credentials",status:"pass",detail:"owner, repository id, and installation id all resolved"}:{id:"github-credentials",status:"fail",detail:g.credentials_readable?`incomplete: ${[g.owner_resolved?null:"owner",g.repo_id_resolved?null:"repository id",g.installation_id_resolved?null:"installation id"].filter(Boolean).join(", ")} unresolved`:"no GitHub credential row exists for this repository",remediation:SERVER_REMEDIATIONS.githubCredentials}),outcomes.push(githubActionsOutcome(readiness)),outcomes.push(reconcilerOutcome(readiness)),outcomes.push(executorOutcome(readiness)),outcomes.push(reviewWorkflowOutcome(readiness)),outcomes.push(ciWorkflowOutcome(readiness));let byId=new Map(outcomes.map(outcome=>[outcome.id,outcome]));return SERVER_READINESS_DESCRIPTORS.map(({id,label})=>{let outcome=byId.get(id);return outcome?createReadinessCheckSafely({id:`server.${id}`,source:"server",label,status:outcome.status,detail:outcome.detail,...outcome.status==="pass"?{}:{remediation:outcome.remediation??SERVER_REMEDIATIONS.olderServer}}):createReadinessCheck({id:`server.${id}`,source:"server",label,status:"fail",detail:"this server fact was not reported",remediation:SERVER_REMEDIATIONS.olderServer})})}function reviewPolicyOutcome(readiness){let s=readiness.supervisor,alignment=s.review_policy_alignment;return alignment!==null?alignment.status==="divergent"||alignment.status==="invalid"?{id:"review-policy",status:"warn",detail:alignment.explanation,remediation:SERVER_REMEDIATIONS.reviewPolicyDivergent}:{id:"review-policy",status:"pass",detail:alignment.explanation}:s.review_policy_present?{id:"review-policy",status:"pass",detail:"a repository review-policy default is stored (alignment not reported by this server)"}:{id:"review-policy",status:"warn",detail:"no repository review-policy default is stored",remediation:SERVER_REMEDIATIONS.reviewPolicyMissing}}function githubActionsOutcome(readiness){let g=readiness.github;return g.actions_write?{id:"github-actions-permission",status:"pass",detail:"actions: write"}:g.actions_probe_succeeded?{id:"github-actions-permission",status:"warn",detail:`actions: ${g.actions_permission_level}`,remediation:SERVER_REMEDIATIONS.actionsMissing}:{id:"github-actions-permission",status:"fail",detail:"the actions permission could not be checked (this is not a confirmed absence)",remediation:SERVER_REMEDIATIONS.actionsProbeFailed}}function reconcilerOutcome(readiness){let r=readiness.reconciler;return r.liveness_readable?r.stale?{id:"reconciler-liveness",status:"fail",detail:r.last_tick_at===null?"no reconciler tick has been recorded for this repository":`last tick ${r.last_tick_age_seconds}s ago (server threshold ${readiness.thresholds.reconciler_stale_after_seconds}s)`,remediation:SERVER_REMEDIATIONS.reconcilerStale}:{id:"reconciler-liveness",status:"pass",detail:`last tick ${r.last_tick_age_seconds}s ago across ${r.active_run_count} active run(s)`}:{id:"reconciler-liveness",status:"fail",detail:"reconciler liveness could not be read",remediation:SERVER_REMEDIATIONS.reconcilerUnreadable}}function executorOutcome(readiness){let e=readiness.executor;return e.liveness_readable?e.ready===!0?{id:"executor-readiness",status:"pass",detail:`executor ready \u2014 last seen ${e.last_seen_age_seconds}s ago`}:e.ready===!1?{id:"executor-readiness",status:"fail",detail:`observed but not ready \u2014 last seen ${e.last_seen_age_seconds}s ago (server threshold ${readiness.thresholds.executor_stale_after_seconds}s)`,remediation:SERVER_REMEDIATIONS.executorStale}:{id:"executor-readiness",status:"fail",detail:"never observed by the server",remediation:SERVER_REMEDIATIONS.executorNeverSeen}:{id:"executor-readiness",status:"fail",detail:"executor liveness could not be read",remediation:SERVER_REMEDIATIONS.executorUnreadable}}function reviewWorkflowOutcome(readiness){let w=readiness.review_workflow;return w===null?{id:"review-workflow",status:"fail",detail:"this Bridge API deploy did not report the review-workflow facts",remediation:SERVER_REMEDIATIONS.olderServer}:w.probe_succeeded?w.emits_run_id&&w.emits_reviewed_sha?{id:"review-workflow",status:"pass",detail:"the default branch's review workflow emits both protocol markers"}:{id:"review-workflow",status:"fail",detail:`missing marker(s): ${[w.emits_run_id?null:"run id",w.emits_reviewed_sha?null:"reviewed SHA"].filter(Boolean).join(", ")}`,remediation:SERVER_REMEDIATIONS.reviewWorkflowIncomplete}:{id:"review-workflow",status:"fail",detail:w.workflow_present?"the review workflow is present but could not be evaluated":"the review workflow could not be found or read on the default branch",remediation:SERVER_REMEDIATIONS.reviewWorkflowUnknown}}function ciWorkflowOutcome(readiness){let c=readiness.conductor_ci_workflow;return c===null?{id:"conductor-ci-workflow",status:"fail",detail:"this Bridge API deploy did not report the conductor-CI workflow facts",remediation:SERVER_REMEDIATIONS.olderServer}:c.probe_succeeded?c.migration_guard_present?{id:"conductor-ci-workflow",status:"pass",detail:"the default branch's conductor CI workflow runs the migration guard"}:{id:"conductor-ci-workflow",status:"warn",detail:"the conductor CI workflow does not run the migration guard",remediation:SERVER_REMEDIATIONS.ciWorkflowMissingGuard}:{id:"conductor-ci-workflow",status:"fail",detail:c.workflow_present?"the conductor CI workflow is present but could not be evaluated":"the conductor CI workflow could not be found or read on the default branch",remediation:SERVER_REMEDIATIONS.ciWorkflowUnknown}}function sectionStatus(status){return status==="fatal"?"fail":status==="degraded"?"warn":"pass"}function mapInstallSectionsToReadinessChecks(sections){let checks=[],seen=new Set;for(let section of sections??[]){if(INSTALL_SECTION_IDS_OWNED_ELSEWHERE.has(section.id)||seen.has(section.id))continue;seen.add(section.id);let status=sectionStatus(section.status);checks.push(createReadinessCheckSafely({id:`conductor.install-section-${section.id}`,source:"conductor",label:section.label,status,detail:section.detail,...status==="pass"?{}:{remediation:section.remediation??"run `install conductor` for this repository to re-provision this capability."}}))}return checks}async function collectConductorReadinessGate(deps){let[installReport,planeResult]=await Promise.all([runInstallDoctorSafely(deps),runPlaneSafely(deps)]),unavailableSources=[];installReport===null&&unavailableSources.push("install","conductor","server"),deps.runPlanePreflight&&planeResult===null&&unavailableSources.push("plane");let checks=[...mapInstallStatusChecksToReadinessChecks(installReport?.legacyInstallChecks??null,installReport===null),...mapConductorDoctorReportToReadinessChecks(installReport?.legacyConductor??null),...mapInstallSectionsToReadinessChecks(installReport?.sections??null),...mapPlanePreflightToReadinessChecks(planeResult),...mapServerReadinessToChecks(installReport?.readiness??null,classifyServerFailure(installReport))],validated=validateReadinessChecks(checks);return{schemaVersion:CONDUCTOR_READINESS_GATE_SCHEMA_VERSION,advisory:CONDUCTOR_READINESS_ADVISORY_NOTICE,repoName:deps.repoName??null,unavailableSources,checks:validated,summary:summarizeReadinessChecks(validated)}}async function runInstallDoctorSafely(deps){try{return deps.runInstallDoctor?await deps.runInstallDoctor():deps.installDoctor?await runConductorInstallDoctor(deps.conductorDoctorDeps?{...deps.installDoctor,conductorDoctorDeps:deps.conductorDoctorDeps}:deps.installDoctor):null}catch{return null}}async function runPlaneSafely(deps){if(!deps.runPlanePreflight)return null;try{return await deps.runPlanePreflight()}catch{return null}}function classifyServerFailure(report){if(report===null)return"unreachable";let sections=report.sections??[];if(sections.some(section=>section.id==="bridge-access"))return"identity-unresolved";let serverSection=sections.find(section=>section.id==="server-readiness");return serverSection?serverSection.detail.includes("rejected the credential")?"unauthorized":serverSection.detail.includes("shape validation")?"invalid-response":"unreachable":"unreachable"}function readinessTag(status){return status==="fail"?"\u2717 FAIL":status==="warn"?"! WARN":status==="skip"?"- SKIP":"\u2713 PASS"}function formatConductorReadinessGateReport(report){let lines=["Conductor readiness (advisory)","\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",`schema version: ${report.schemaVersion}`,`repository: ${report.repoName??"unresolved"}`,""];for(let source of["install","conductor","plane","server"]){let group=report.checks.filter(check=>check.source===source);if(group.length!==0){lines.push(`[${source}]`);for(let check of group)lines.push(` ${readinessTag(check.status)} ${check.label} (${check.id})`),check.detail&&lines.push(` ${check.detail}`),check.remediation&&lines.push(` \u2192 ${check.remediation}`);lines.push("")}}let{pass,warn,fail,skip}=report.summary;return lines.push(`summary: ${pass} pass, ${warn} warn, ${fail} fail, ${skip} skip`),report.unavailableSources.length>0&&lines.push(`sources that could not be collected: ${report.unavailableSources.join(", ")} (their prerequisites above are reported as failures, not as passes)`),lines.push(""),lines.push(report.advisory),lines.join(`
|
|
123
|
+
`)}var CONDUCTOR_READINESS_GATE_SCHEMA_VERSION,CONDUCTOR_READINESS_ADVISORY_NOTICE,SERVER_READINESS_DESCRIPTORS,SERVER_FAILURE_COPY,SERVER_REMEDIATIONS,INSTALL_SECTION_IDS_OWNED_ELSEWHERE,init_readiness=__esm({"src/conductor/readiness.ts"(){"use strict";init_doctor();init_install_doctor();init_preflight();init_install_doctor2();init_readiness_check();CONDUCTOR_READINESS_GATE_SCHEMA_VERSION=1,CONDUCTOR_READINESS_ADVISORY_NOTICE="Advisory only. This report never blocks bring-up, approval, or a run, and never changes an exit code. Remediations are operator actions and are never executed automatically. drive-epic's V2_READINESS_REQUIREMENTS remains the only hard route-selection predicate, and the server-side admission remains the only hard refusal.",SERVER_READINESS_DESCRIPTORS=[{id:"supervisor-setup",label:"Supervisor setup"},{id:"supervisor-config",label:"Supervisor configuration"},{id:"supervisor-required-checks",label:"Supervisor required CI checks"},{id:"auto-merge",label:"Auto-merge posture"},{id:"merge-approval",label:"Merge approval configuration"},{id:"review-policy",label:"Review policy"},{id:"github-credentials",label:"GitHub App credentials"},{id:"github-actions-permission",label:"GitHub App actions permission"},{id:"reconciler-liveness",label:"Reconciler tick liveness"},{id:"executor-readiness",label:"Executor server observation"},{id:"review-workflow",label:"Review workflow protocol"},{id:"conductor-ci-workflow",label:"Conductor CI migration guard"}],SERVER_FAILURE_COPY={"identity-unresolved":{detail:"no server facts were read \u2014 the repository identity or credential could not be resolved",remediation:"run /install-bridge (or set BAPI_REPO_NAME and BAPI_API_KEY) for this repository, then re-run."},unauthorized:{detail:"the Bridge API rejected the credential for this repository",remediation:"re-check the API key and repository name, then re-run; the key may have been rotated."},"invalid-response":{detail:"the readiness response failed shape validation, so no server fact can be trusted",remediation:"re-run; if it persists the Bridge API deploy is inconsistent with this CLI version."},unreachable:{detail:"the readiness endpoint could not be reached",remediation:"check network reachability to the Bridge API and re-run; the local checks above are unaffected."}},SERVER_REMEDIATIONS={supervisorSetup:"run `install conductor` (or `setup-epic`) for this repository to write the project-default supervisor posture.",supervisorConfig:"run `install conductor` for this repository to write the project-default supervisor configuration.",requiredChecks:"configure a non-empty required-check list in done_gate_config; an empty list makes the done gate pass unconditionally.",mergeApproval:"set the merge-approval requirement explicitly in the supervisor configuration rather than leaving it unset.",reviewPolicyMissing:"set the repository review-policy default so the merge path and the code_review gate read the same signal.",reviewPolicyDivergent:"align the repository review-policy default with the done gate's review_state condition, or confirm the difference is intended.",githubCredentials:"connect GitHub from the Bridge setup UI (`install-bridge connect-github`) so owner, repository id, and installation id all resolve.",actionsProbeFailed:"re-run once credentials resolve; the permission could not be checked, which is not the same as confirmed-missing.",actionsMissing:"grant the GitHub App `actions: write`; without it the conductor's workflow rerun lane fails open on 403.",reconcilerUnreadable:"retry once the Bridge API is reachable; reconciler liveness is unknown here, not confirmed stale.",reconcilerStale:"start the reconciler for this repository (the `conductor epic-tick` schedule) so ticks resume.",executorUnreadable:"retry once the Bridge API is reachable; no executor readiness claim is ever made from local state.",executorNeverSeen:"provision and start an executor (`install conductor --executor-id <id>` or `executor install-service`); readiness comes only from a live server observation.",executorStale:"restart the executor service; it was observed once and has gone quiet past the server's staleness threshold.",reviewWorkflowUnknown:"re-run; the default branch's review workflow could not be evaluated, which is not the same as it being absent.",reviewWorkflowIncomplete:"install the claude-review workflow template on the default branch so it emits both the run id and the reviewed SHA the verdict protocol reads.",ciWorkflowUnknown:"re-run; the default branch's conductor CI workflow could not be evaluated, which is not the same as the guard being absent.",ciWorkflowMissingGuard:"add the migration-guard job to the conductor CI workflow on the default branch so migrations are checked before a merge.",olderServer:"upgrade the Bridge API deploy so it reports this fact; its state is unknown here, not healthy."};INSTALL_SECTION_IDS_OWNED_ELSEWHERE=new Set(["supervisor-configuration","supervisor-required-checks","supervisor-review-alignment","github-credentials","github-actions-permission","reconciler-liveness","executor-observation","server-readiness","bridge-access","conductor-ledger","conductor-ledger-loadability","install-status"])}});function joinCwd(cwd,rel){return`${cwd.endsWith("/")?cwd.slice(0,-1):cwd}/${rel}`}function claudeReviewWorkflowPath(cwd){return joinCwd(cwd,CLAUDE_REVIEW_WORKFLOW_RELPATH)}var VERDICT_CHECK_SCRIPT,init_claude_review_workflow=__esm({"src/claude-review-workflow.ts"(){"use strict";init_claude_review_workflow_drift();VERDICT_CHECK_SCRIPT=[" // Contract: docs/claude/claude-review-verdict-contract.md \xA71-\xA74."," const VERDICT = /claude-review-verdict:\\s*(approved|changes_requested)/i;"," const RUN_ID = /run[-_]id:\\s*(\\d+)/i;"," const REVIEWED_SHA = /Reviewed-SHA:\\s*([0-9A-Za-z._-]+)/i;"," const FULL_SHA = /^[0-9a-f]{40}$/;"," const APPROVED_WORD = /\\bapproved\\b/i;"," const CHANGES_WORD = /\\bchanges.requested\\b/i;"," const expected = String(process.env.EXPECTED_HEAD || '').trim().toLowerCase();",""," // Ambiguity (both verdict words) or absence (neither) yields"," // 'unknown', never 'approved'."," const verdictOf = (body) => {"," const token = VERDICT.exec(body);"," if (token) return token[1].toLowerCase();"," const a = APPROVED_WORD.test(body);"," const c = CHANGES_WORD.test(body);"," if (a && !c) return 'approved';"," if (c && !a) return 'changes_requested';"," return 'unknown';"," };"," const declaredSha = (body) => {"," const m = REVIEWED_SHA.exec(body);"," return m ? m[1].trim().toLowerCase() : null;"," };",""," // \xA72 eligibility: the structured token, or the loose marker."," // Malformed entries are skipped rather than throwing \u2014 one odd"," // comment must not fail the job for a reason unrelated to review."," const build = (comments) => comments.reduce((acc, c, index) => {"," if (!c || typeof c !== 'object') return acc;"," const body = typeof c.body === 'string' ? c.body : '';"," const hasToken = VERDICT.test(body);"," if (!hasToken && body.indexOf('claude-review') === -1) return acc;"," const run = RUN_ID.exec(body);"," const raw = c.updated_at || c.created_at;"," const ts = typeof raw === 'string' ? Date.parse(raw) : NaN;"," acc.push({"," runId: run ? parseInt(run[1], 10) : 0,"," index,"," body,"," hasToken,"," ts: Number.isNaN(ts) ? null : ts,"," });"," return acc;"," }, []);",""," // \xA73 legacy rank: (has a usable timestamp, that instant, carries the"," // token). The array index is deliberately EXCLUDED so a genuine"," // two-verdict contradiction stays detectable instead of being"," // silently resolved as 'whichever came last'."," const rankOf = (c) => [c.ts !== null ? 1 : 0, c.ts === null ? 0 : c.ts, c.hasToken ? 1 : 0];"," const cmpRank = (a, b) => {"," const x = rankOf(a);"," const y = rankOf(b);"," for (let i = 0; i < x.length; i++) {"," if (x[i] !== y[i]) return x[i] < y[i] ? -1 : 1;"," }"," return 0;"," };",""," // \xA73 conflict: equal-ranked candidates that DISAGREE and share one"," // valid Reviewed-SHA. Duplicate upserts of the same verdict are not"," // a conflict, and candidates without shared provenance never proved"," // they examined the same code."," const conflicts = (tied) => {"," if (new Set(tied.map((c) => verdictOf(c.body))).size < 2) return false;"," const shas = new Set("," tied.map((c) => declaredSha(c.body)).filter((s) => s && FULL_SHA.test(s)),"," );"," if (shas.size !== 1) return false;"," const bound = tied.filter((c) => shas.has(declaredSha(c.body)));"," return new Set(bound.map((c) => verdictOf(c.body))).size >= 2;"," };",""," const resolve = (comments) => {"," const candidates = build(comments);"," if (candidates.length === 0) return { valid: false, reason: 'review_verdict_absent' };"," let tied;"," if (candidates.some((c) => c.runId > 0)) {"," const top = Math.max(...candidates.map((c) => c.runId));"," tied = candidates.filter((c) => c.runId === top);"," } else {"," const best = candidates.reduce((a, b) => (cmpRank(a, b) >= 0 ? a : b));"," tied = candidates.filter((c) => cmpRank(c, best) === 0);"," }"," if (conflicts(tied)) return { valid: false, reason: 'review_verdict_conflict' };"," const winner = tied.reduce((a, b) => (a.index >= b.index ? a : b));"," const declared = declaredSha(winner.body);"," if (declared === null) return { valid: false, reason: 'review_verdict_no_head_proof' };"," if (declared !== expected) {"," return {"," valid: false,"," reason: FULL_SHA.test(declared) ? 'review_verdict_stale_head' : 'review_verdict_malformed_sha',"," };"," }"," const verdict = verdictOf(winner.body);"," if (verdict !== 'approved' && verdict !== 'changes_requested') {"," return { valid: false, reason: 'review_verdict_unknown_token' };"," }"," return { valid: true, reason: 'review_verdict_resolved', verdict };"," };",""," if (!FULL_SHA.test(expected)) {"," core.setOutput('status', 'unavailable');"," core.setOutput('valid', 'false');"," core.setOutput('reason', 'checker_invalid_expected_head');"," return;"," }",""," // Bounded, read-only propagation loop: a verdict posted seconds ago"," // may not be visible to the comments API yet, and calling that"," // 'absent' would spend another paid review for nothing."," let outcome = { valid: false, reason: 'checker_not_run' };"," let status = 'unavailable';"," for (let attempt = 1; attempt <= 4; attempt++) {"," let comments;"," try {"," comments = await github.paginate(github.rest.issues.listComments, {"," owner: context.repo.owner,"," repo: context.repo.repo,"," issue_number: Number(process.env.PR_NUMBER),"," per_page: 100,"," });"," } catch (err) {"," status = 'unavailable';"," outcome = { valid: false, reason: 'comment_fetch_failed' };"," await new Promise((r) => setTimeout(r, 10000));"," continue;"," }"," status = 'checked';"," outcome = resolve(comments);"," const retryable ="," outcome.reason === 'review_verdict_absent' ||"," outcome.reason === 'review_verdict_stale_head';"," if (outcome.valid || !retryable || attempt === 4) break;"," await new Promise((r) => setTimeout(r, 10000));"," }"," core.setOutput('status', status);"," core.setOutput('valid', outcome.valid ? 'true' : 'false');"," core.setOutput('reason', outcome.reason);"," core.info('Verdict check: valid=' + outcome.valid + ' reason=' + outcome.reason);"].join(`
|
|
124
|
+
`)}});function endpointForPort(port){return{host:PLANE_SERVER_HOST,port,baseUrl:`http://${PLANE_SERVER_HOST}:${port}`}}function resolvePlaneServerEndpoint(env){let configured=env[PLANE_SERVER_PORT_ENV_VAR];if(typeof configured!="string"||configured.trim().length===0)return{ok:!0,endpoint:endpointForPort(PLANE_SERVER_PORT)};let raw=configured.trim();if(!/^[0-9]+$/.test(raw))return{ok:!1,message:PLANE_SERVER_PORT_INVALID_MESSAGE};let port=Number(raw);return!Number.isInteger(port)||port<1||port>MAX_TCP_PORT?{ok:!1,message:PLANE_SERVER_PORT_INVALID_MESSAGE}:{ok:!0,endpoint:endpointForPort(port)}}var MAX_TCP_PORT,PLANE_SERVER_PORT_INVALID_MESSAGE,init_member_roster=__esm({"src/plane/member-roster.ts"(){"use strict";init_types2();init_manifest();MAX_TCP_PORT=65535,PLANE_SERVER_PORT_INVALID_MESSAGE=`${PLANE_SERVER_PORT_ENV_VAR} must be a whole TCP port number in the range 1..${MAX_TCP_PORT}. Unset it to use the default port ${PLANE_SERVER_PORT}, or export a valid port and retry.`}});var init_status=__esm({"src/plane/status.ts"(){"use strict";init_manifest();init_types2()}});var init_shutdown=__esm({"src/plane/shutdown.ts"(){"use strict";init_manifest()}});var PLANE_MEMBER_STARTUP_FAILURES,ALLOWED_STARTUP_FAILURES,init_member_logs=__esm({"src/plane/member-logs.ts"(){"use strict";init_types2();PLANE_MEMBER_STARTUP_FAILURES={spawnThrew:"the process could not be started",noPid:"the process started without a pid",readinessTimeout:"it did not start listening in time",heartbeatReadinessTimeout:"it did not publish a durable heartbeat in time",readinessUnestablished:"its readiness baseline could not be established"},ALLOWED_STARTUP_FAILURES=new Set(Object.values(PLANE_MEMBER_STARTUP_FAILURES))}});var init_supervisor=__esm({"src/plane/supervisor.ts"(){"use strict";init_types2();init_manifest();init_member_logs();init_member_roster();init_shutdown()}});import{createWriteStream,realpathSync as realpathSync2,statSync as statSync2}from"fs";import{mkdir as mkdir2,open,readdir,readFile as readFile2,rename,stat as stat2,unlink,writeFile as writeFile2}from"fs/promises";import{execFile as execFileCb,spawn as nodeSpawn}from"child_process";import net from"net";import os6 from"os";import path13 from"path";import{fileURLToPath as fileURLToPath2}from"url";function createPlaneFsDeps(){return{readFile:filePath=>readFile2(filePath,"utf-8"),writeFile:(filePath,data)=>writeFile2(filePath,data,"utf-8"),createExclusive:async(filePath,data)=>{let handle=await open(filePath,"wx");try{await handle.writeFile(data,"utf-8")}finally{await handle.close()}},rename:(from,to)=>rename(from,to),unlink:filePath=>unlink(filePath),mkdir:async dirPath=>{await mkdir2(dirPath,{recursive:!0})},stat:async filePath=>{let result=await stat2(filePath);return{mtimeMs:result.mtimeMs,mode:result.mode}},readdir:async dirPath=>(await readdir(dirPath,{withFileTypes:!0})).map(entry=>({name:entry.name,isDirectory:()=>entry.isDirectory(),isFile:()=>entry.isFile()}))}}function createPlaneClock(){return{now:()=>new Date,sleep:ms=>new Promise(resolve2=>setTimeout(resolve2,ms))}}function createPlaneProcessDeps(){return{isAlive:pid=>isProcessAlive(pid,(target,signal)=>process.kill(target,signal)),signal:(pid,signal)=>{try{return process.kill(pid,signal),"sent"}catch(err){let code=err?.code;return code==="ESRCH"?"no-such-process":code==="EPERM"?"permission-denied":"error"}}}}function probeTcpPort(host,port,timeoutMs){return new Promise(resolve2=>{let socket=new net.Socket,settled=!1,finish=result=>{settled||(settled=!0,socket.destroy(),resolve2(result))};socket.setTimeout(timeoutMs),socket.once("connect",()=>finish({kind:"connected"})),socket.once("timeout",()=>finish({kind:"error",error:"probe timed out"})),socket.once("error",err=>{err.code==="ECONNREFUSED"?finish({kind:"refused"}):finish({kind:"error",error:err.code??"probe failed"})}),socket.connect(port,host)})}function createPlaneExecFile(){return(file,args,options)=>new Promise(resolve2=>{execFileCb(file,args,{cwd:options.cwd,shell:!1,windowsHide:!0,timeout:3e4},(error,stdout,stderr)=>{if(error){let code=error.code;resolve2({ok:!1,error:typeof code=="string"?code:"command failed"});return}resolve2({ok:!0,stdout:String(stdout),stderr:String(stderr)})})})}function resolvePackageEntrypoint(overrides={}){let deps={moduleUrl:overrides.moduleUrl??import.meta.url,argv1:overrides.argv1??process.argv[1],realpath:overrides.realpath??defaultRealpath2,isFile:overrides.isFile??defaultIsFile2},moduleFile=moduleFilePath2(deps.moduleUrl),candidates=[];if(moduleFile!==null){let dir=path13.dirname(moduleFile);path13.basename(moduleFile)==="index.js"&&candidates.push(moduleFile),candidates.push(path13.join(dir,"index.js")),candidates.push(path13.join(dir,"..","index.js"))}typeof deps.argv1=="string"&&deps.argv1.length>0&&candidates.push(deps.argv1);let seen=new Set;for(let candidate of candidates){let canonical=deps.realpath(candidate);if(canonical!==null&&!seen.has(canonical)&&(seen.add(canonical),deps.isFile(canonical)))return{ok:!0,entrypoint:canonical}}return{ok:!1,candidatesChecked:seen.size}}function moduleFilePath2(moduleUrl){try{return fileURLToPath2(moduleUrl)}catch{return null}}function defaultRealpath2(filePath){try{return realpathSync2(filePath)}catch{return null}}function defaultIsFile2(filePath){try{return statSync2(filePath).isFile()}catch{return!1}}function resolveHomedir(){return os6.homedir()}var init_defaults=__esm({"src/plane/defaults.ts"(){"use strict";init_types2();init_manifest()}});function buildPreflightDeps(env){return{env,endpoint:resolvePlaneServerEndpoint(env),platform:process.platform,homedir:resolveHomedir,fs:createPlaneFsDeps(),clock:createPlaneClock(),proc:createPlaneProcessDeps(),execFile:createPlaneExecFile(),probePort:probeTcpPort,resolveRuntimeEntrypoint:()=>resolvePackageEntrypoint(),resolveRepoName:resolveRequiredStartTicketsRepoName,resolveCredentials:resolveBapiCredentials}}function runDefaultPlanePreflight(repoRoot,env=process.env){return runPlanePreflight(repoRoot,buildPreflightDeps(env))}var init_cli2=__esm({"src/plane/cli.ts"(){"use strict";init_types2();init_build_freshness();init_manifest();init_manifest();init_preflight();init_member_roster();init_status();init_shutdown();init_supervisor();init_defaults();init_credential_store();init_start_tickets_repo()}});var readiness_cli_exports={};__export(readiness_cli_exports,{READINESS_COLLECTION_NOTICE:()=>READINESS_COLLECTION_NOTICE,getReadinessUsage:()=>getReadinessUsage,parseReadinessArgs:()=>parseReadinessArgs,runConductorReadinessCommand:()=>runConductorReadinessCommand});import os7 from"node:os";import{readFile as fsReadFile2,stat as fsStat2}from"node:fs/promises";function getReadinessUsage(){return["Usage: conductor readiness [--json] [--no-deny-probe]","","Read-only ADVISORY report of every conductor prerequisite, consolidated from the","Bridge install checklist, the conductor doctor, the plane preflight, and the","server conductor-readiness collector. Each prerequisite reports pass/warn/fail/skip","and, on a failure, exactly ONE named remediation.","","Remediations are NOT run automatically. This command changes nothing: it starts no","plane, approves no run, writes no file, and always exits 0 \u2014 `drive-epic` remains","the only route-selection gate and the server-side admission the only hard refusal.","","Options:"," --json Print the versioned structured report as JSON"," --no-deny-probe Accepted for parity with `conductor doctor`; inert here, because"," this command never spawns the deny-enforcement probe"," --help Print this usage message"].join(`
|
|
125
|
+
`)}function parseReadinessArgs(argv){let parsed={json:!1,help:!1,noDenyProbe:!1};for(let token of argv)if(token==="--json")parsed.json=!0;else if(token==="--no-deny-probe")parsed.noDenyProbe=!0;else if(token==="--help"||token==="-h")parsed.help=!0;else return{error:`Unknown argument "${token}". Run "conductor readiness --help" for usage.`};return parsed}async function collectProductionReport(repoRoot,env){let accessResult=await resolveConductorBridgeApiAccess({env,cwd:repoRoot}),access=accessResult.ok?accessResult.access:null;return collectConductorReadinessGate({repoName:access?.repoName??null,installDoctor:{access,accessError:accessResult.ok?void 0:accessResult.error,fetch:(...args)=>fetch(...args),reviewPolicySource:"verdict_protocol",readWorkflowFile:()=>fsReadFile2(claudeReviewWorkflowPath(repoRoot),"utf-8"),projectRoot:repoRoot,installDoctorDeps:{env,cwd:repoRoot,platform:process.platform,homedir:os7.homedir,readFile:filePath=>fsReadFile2(filePath,"utf-8"),stat:filePath=>fsStat2(filePath),fetch:(...args)=>fetch(...args)}},conductorDoctorDeps:{env,skipDenyProbe:!0},runPlanePreflight:()=>runDefaultPlanePreflight(repoRoot,env)})}async function runConductorReadinessCommand(argv,deps={}){let sinks=deps.sinks??{stdout:line=>console.log(line),stderr:line=>console.error(line)},parsed=parseReadinessArgs(argv);if("error"in parsed)return sinks.stderr(`Error: ${parsed.error}`),1;if(parsed.help)return sinks.stdout(getReadinessUsage()),0;let cwd=deps.cwd??process.cwd(),env=deps.env??process.env,report=await(deps.collect??(repoRoot=>collectProductionReport(repoRoot,env)))(cwd);return report.unavailableSources.length>0&&sinks.stderr(READINESS_COLLECTION_NOTICE),sinks.stdout(parsed.json?JSON.stringify(report):formatConductorReadinessGateReport(report)),0}var READINESS_COLLECTION_NOTICE,init_readiness_cli=__esm({"src/conductor/readiness-cli.ts"(){"use strict";init_readiness();init_bridge_api_client();init_claude_review_workflow();init_cli2();READINESS_COLLECTION_NOTICE="one or more readiness sources could not be collected; the affected prerequisites are reported as failures."}});var recovery_operations_exports={};__export(recovery_operations_exports,{RECOVERY_TICKET_RETRY_LIMIT:()=>RECOVERY_TICKET_RETRY_LIMIT,abandonEpicRunRecovery:()=>abandonEpicRunRecovery,adoptCurrentHeadAndUnparkWithRetry:()=>adoptCurrentHeadAndUnparkWithRetry,stopEpicRunRecovery:()=>stopEpicRunRecovery,unparkEpicTicketWithRetry:()=>unparkEpicTicketWithRetry});import{randomUUID as randomUUID2}from"crypto";async function stopEpicRunRecovery(access,options){try{return(await stopEpicRun(access,{epicRunId:options.epicRunId,reason:options.reason})).committed?{ok:!0,kind:"committed",epicRunId:options.epicRunId}:{ok:!0,kind:"already-stopped",epicRunId:options.epicRunId}}catch(err){if(err instanceof ConductorBridgeApiError&&err.status===409&&err.errorCode==="RUN_TERMINAL"){let status=await readTerminalRunStatus(access,options.epicRunId);return{ok:!1,kind:"terminal",epicRunId:options.epicRunId,status}}return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,message:safeDiagnosticMessage(err,"stop request failed")}}}async function readTerminalRunStatus(access,epicRunId){try{return(await fetchEpicRunState(access,epicRunId)).epic_run.status}catch{return"terminal"}}async function abandonEpicRunRecovery(access,options){let state;try{state=await fetchEpicRunState(access,options.epicRunId)}catch(err){return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,message:safeDiagnosticMessage(err,"could not read run state")}}let currentStatus=state.epic_run.status;if(currentStatus==="abandoned")return{ok:!0,kind:"already-abandoned",epicRunId:options.epicRunId};try{return await updateEpicRunStatus(access,{epicKey:options.epicRunId,status:"abandoned",expectedStatus:currentStatus}),{ok:!0,kind:"abandoned",epicRunId:options.epicRunId}}catch(err){return err instanceof ConductorBridgeApiError&&err.status===400?{ok:!1,kind:"concurrent-change",epicRunId:options.epicRunId,message:"the run's status changed concurrently; re-check its state and retry"}:{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,message:safeDiagnosticMessage(err,"abandon request failed")}}}async function ticketRecoveryWithRetry(access,options,mutate){let idempotencyKey=randomUUID2();for(let attempt=0;attempt<RECOVERY_TICKET_RETRY_LIMIT;attempt+=1){let state;try{state=await fetchEpicRunState(access,options.epicRunId)}catch(err){return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,ticketKey:options.ticketKey,message:safeDiagnosticMessage(err,"could not read run state")}}let ticket=state.ticket_statuses.find(t=>t.ticket_key===options.ticketKey);if(!ticket)return{ok:!1,kind:"ticket-not-found",epicRunId:options.epicRunId,ticketKey:options.ticketKey};let result;try{result=await mutate(access,{epicRunId:options.epicRunId,ticketKey:options.ticketKey,expectedRowVersion:ticket.row_version,idempotencyKey,reason:options.reason})}catch(err){return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,ticketKey:options.ticketKey,message:safeDiagnosticMessage(err,"recovery request failed")}}if(result.ok)return{ok:!0,kind:"unparked",epicRunId:options.epicRunId,ticketKey:options.ticketKey,status:result.ticket_status.status}}return{ok:!1,kind:"concurrent-change-exhausted",epicRunId:options.epicRunId,ticketKey:options.ticketKey}}async function unparkEpicTicketWithRetry(access,options){return ticketRecoveryWithRetry(access,options,(a,args)=>unparkEpicTicket(a,args))}async function adoptCurrentHeadAndUnparkWithRetry(access,options){return ticketRecoveryWithRetry(access,options,(a,args)=>adoptCurrentHeadAndUnparkTicket(a,args))}var RECOVERY_TICKET_RETRY_LIMIT,init_recovery_operations=__esm({"src/conductor/recovery-operations.ts"(){"use strict";init_bridge_api_client();RECOVERY_TICKET_RETRY_LIMIT=3}});var recovery_cli_exports={};__export(recovery_cli_exports,{runAbandonRunCommand:()=>runAbandonRunCommand,runAdoptCurrentHeadAndUnparkCommand:()=>runAdoptCurrentHeadAndUnparkCommand,runStopRunCommand:()=>runStopRunCommand,runUnparkCommand:()=>runUnparkCommand});function tokenizeRecoveryFlags(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(REJECTED_VERSION_FLAGS.has(name))throw new ConductorValidationError(`Flag "${name}" is not supported here \u2014 row-version handling is internal to recovery and cannot be supplied by the operator. Omit it; recovery reads the current version itself.`);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}}function parseRunRecoveryArgs(argv){let{values,bools}=tokenizeRecoveryFlags(argv,RUN_VALUE_FLAGS,RECOVERY_BOOL_FLAGS);if(bools.has("--help"))return{epicRunId:"",json:bools.has("--json"),help:!0};let epicRunId=values.get("--epic-run-id");if(epicRunId===void 0||epicRunId.trim().length===0)throw new ConductorValidationError('Flag "--epic-run-id" is required and must be non-empty.');return{epicRunId:epicRunId.trim(),json:bools.has("--json"),help:!1}}function parseTicketRecoveryArgs(argv){let{values,bools}=tokenizeRecoveryFlags(argv,TICKET_VALUE_FLAGS,RECOVERY_BOOL_FLAGS);if(bools.has("--help"))return{epicRunId:"",ticketKey:"",json:bools.has("--json"),help:!0};let epicRunId=values.get("--epic-run-id");if(epicRunId===void 0||epicRunId.trim().length===0)throw new ConductorValidationError('Flag "--epic-run-id" is required and must be non-empty.');let ticketKey=values.get("--ticket-key");if(ticketKey===void 0||ticketKey.trim().length===0)throw new ConductorValidationError('Flag "--ticket-key" is required and must be non-empty.');return{epicRunId:epicRunId.trim(),ticketKey:ticketKey.trim(),json:bools.has("--json"),help:!1}}async function resolveRecoveryAccess(json){let{resolveConductorBridgeApiAccess:resolveConductorBridgeApiAccess2}=await Promise.resolve().then(()=>(init_bridge_api_client(),bridge_api_client_exports)),result=await resolveConductorBridgeApiAccess2();return result.ok?result.access:(json?console.log(JSON.stringify({ok:!1,kind:"unauthorized",error:result.error})):console.error(`Error: ${result.error}`),null)}function renderStopRunResult(result,json){return json?(console.log(JSON.stringify(result)),result.ok?0:1):result.ok&&result.kind==="committed"?(console.log(`Run ${result.epicRunId}: stopped. Its queued work was cancelled; the run record remains available for inspection.`),0):result.ok&&result.kind==="already-stopped"?(console.log(`Run ${result.epicRunId}: already stopped; no further action.`),0):!result.ok&&result.kind==="terminal"?(console.error(`Run ${result.epicRunId}: terminal (${result.status}) and cannot be stopped.`),1):(console.error(`Run ${result.epicRunId}: could not be stopped \u2014 ${result.message}.`),1)}async function runStopRunCommand(argv){try{let parsed=parseRunRecoveryArgs(argv);if(parsed.help)return console.log(STOP_RUN_USAGE),0;let access=await resolveRecoveryAccess(parsed.json);if(!access)return 1;let{stopEpicRunRecovery:stopEpicRunRecovery2}=await Promise.resolve().then(()=>(init_recovery_operations(),recovery_operations_exports)),result=await stopEpicRunRecovery2(access,{epicRunId:parsed.epicRunId});return renderStopRunResult(result,parsed.json)}catch(error){return console.error(`Error: ${toConductorErrorEnvelope(error).message}`),1}}function renderAbandonRunResult(result,json){return json?(console.log(JSON.stringify(result)),result.ok?0:1):result.ok&&result.kind==="abandoned"?(console.log(`Run ${result.epicRunId}: abandoned (terminal).`),0):result.ok&&result.kind==="already-abandoned"?(console.log(`Run ${result.epicRunId}: already abandoned (terminal); no further action.`),0):(console.error(`Run ${result.epicRunId}: could not be abandoned \u2014 ${result.message}.`),1)}async function runAbandonRunCommand(argv){try{let parsed=parseRunRecoveryArgs(argv);if(parsed.help)return console.log(ABANDON_RUN_USAGE),0;let access=await resolveRecoveryAccess(parsed.json);if(!access)return 1;let{abandonEpicRunRecovery:abandonEpicRunRecovery2}=await Promise.resolve().then(()=>(init_recovery_operations(),recovery_operations_exports)),result=await abandonEpicRunRecovery2(access,{epicRunId:parsed.epicRunId});return renderAbandonRunResult(result,parsed.json)}catch(error){return console.error(`Error: ${toConductorErrorEnvelope(error).message}`),1}}function renderTicketRecoveryResult(result,json){return json?(console.log(JSON.stringify(result)),result.ok?0:1):result.ok?(console.log(`Ticket ${result.ticketKey} (run ${result.epicRunId}): unparked \u2014 status: ${result.status}.`),0):result.kind==="ticket-not-found"?(console.error(`Ticket ${result.ticketKey}: not found in run ${result.epicRunId}.`),1):result.kind==="concurrent-change-exhausted"?(console.error(`Ticket ${result.ticketKey} (run ${result.epicRunId}): could not recover \u2014 it kept changing concurrently. Re-check the run/ticket status and try again.`),1):(console.error(`Ticket ${result.ticketKey} (run ${result.epicRunId}): could not recover \u2014 ${result.message}.`),1)}async function runUnparkCommand(argv){try{let parsed=parseTicketRecoveryArgs(argv);if(parsed.help)return console.log(UNPARK_USAGE),0;let access=await resolveRecoveryAccess(parsed.json);if(!access)return 1;let{unparkEpicTicketWithRetry:unparkEpicTicketWithRetry2}=await Promise.resolve().then(()=>(init_recovery_operations(),recovery_operations_exports)),result=await unparkEpicTicketWithRetry2(access,{epicRunId:parsed.epicRunId,ticketKey:parsed.ticketKey});return renderTicketRecoveryResult(result,parsed.json)}catch(error){return console.error(`Error: ${toConductorErrorEnvelope(error).message}`),1}}async function runAdoptCurrentHeadAndUnparkCommand(argv){try{let parsed=parseTicketRecoveryArgs(argv);if(parsed.help)return console.log(ADOPT_CURRENT_HEAD_USAGE),0;let access=await resolveRecoveryAccess(parsed.json);if(!access)return 1;let{adoptCurrentHeadAndUnparkWithRetry:adoptCurrentHeadAndUnparkWithRetry2}=await Promise.resolve().then(()=>(init_recovery_operations(),recovery_operations_exports)),result=await adoptCurrentHeadAndUnparkWithRetry2(access,{epicRunId:parsed.epicRunId,ticketKey:parsed.ticketKey});return renderTicketRecoveryResult(result,parsed.json)}catch(error){return console.error(`Error: ${toConductorErrorEnvelope(error).message}`),1}}var RUN_VALUE_FLAGS,TICKET_VALUE_FLAGS,RECOVERY_BOOL_FLAGS,REJECTED_VERSION_FLAGS,STOP_RUN_USAGE,ABANDON_RUN_USAGE,UNPARK_USAGE,ADOPT_CURRENT_HEAD_USAGE,init_recovery_cli=__esm({"src/conductor/recovery-cli.ts"(){"use strict";init_errors();RUN_VALUE_FLAGS=new Set(["--epic-run-id"]),TICKET_VALUE_FLAGS=new Set(["--epic-run-id","--ticket-key"]),RECOVERY_BOOL_FLAGS=new Set(["--json","--help"]),REJECTED_VERSION_FLAGS=new Set(["--row-version","--expected-row-version","--row_version","--expected_row_version"]);STOP_RUN_USAGE=["Usage: conductor stop-run --epic-run-id <id> [--json]","","Stop an epic run: block new dispatch and cancel its queued work. The run","record is preserved (never deleted) so its history stays inspectable.","Idempotent \u2014 repeating it once stopped is a safe no-op."].join(`
|
|
113
126
|
`);ABANDON_RUN_USAGE=["Usage: conductor abandon-run --epic-run-id <id> [--json]","","Abandon an epic run \u2014 a TERMINAL, IRREVERSIBLE transition. An abandoned run","can never resume or be reused; start a new run instead. Idempotent \u2014","repeating it on an already-abandoned run is a safe no-op."].join(`
|
|
114
127
|
`);UNPARK_USAGE=["Usage: conductor unpark --epic-run-id <id> --ticket-key <key> [--json]","","Move a parked (needs_human) ticket back into its gate machine, once the","operator has resolved what parked it. Retries a bounded number of times on","its own if the ticket changes concurrently \u2014 never accepts a version counter."].join(`
|
|
115
128
|
`),ADOPT_CURRENT_HEAD_USAGE=["Usage: conductor adopt-current-head-and-unpark --epic-run-id <id> --ticket-key <key> [--json]","","Recover a ticket parked because a human/external push drifted the PR head","off its anchored commit: adopt the CURRENT PR head and unpark in one step.","Retries a bounded number of times on its own if the ticket changes","concurrently \u2014 never accepts a version counter."].join(`
|
|
116
|
-
`)}});init_errors();init_store();init_producer_ledger();init_taxonomy();import{readFileSync as readFileSync3,unlinkSync}from"node:fs";init_git_inspection();import{chmodSync,existsSync as existsSync2,mkdirSync,readFileSync,realpathSync,statSync,writeFileSync}from"node:fs";import{basename as basename2,dirname,isAbsolute,join,resolve}from"node:path";import{fileURLToPath}from"node:url";var BRIDGE_CONDUCTOR_HOOK_START="# >>> BRIDGE_CONDUCTOR_HOOK_START >>>",BRIDGE_CONDUCTOR_HOOK_END="# <<< BRIDGE_CONDUCTOR_HOOK_END <<<",MANAGED_HOOK_NAMES=["post-commit","reference-transaction"];function resolveGitHooksDirectory(deps={}){let runGit=deps.runGit??runGitCommand,cwd=deps.cwd??process.cwd(),result=runGit(["rev-parse","--git-common-dir"],{cwd});if(!result.ok)return{is_worktree:!1,hooks_dir:null};let commonDir=result.stdout.trim();if(commonDir.length===0)return{is_worktree:!1,hooks_dir:null};let absoluteCommonDir=isAbsolute(commonDir)?commonDir:resolve(cwd,commonDir);return{is_worktree:!0,hooks_dir:resolve(absoluteCommonDir,"hooks")}}var CONDUCTOR_BIN_FILENAME="conductor-bin.js",CONDUCTOR_HOOK_BIN_UNRESOLVED_REASON=`no usable ${CONDUCTOR_BIN_FILENAME} was found for the executing artifact (searched: the sibling bundle layout, the parent TypeScript-emit layout, and the invocation target when it is named ${CONDUCTOR_BIN_FILENAME}). Reinstall or rebuild the package so a conductor binary ships beside the executing module.`;function resolveConductorHookBin(overrides={}){let deps={moduleUrl:overrides.moduleUrl??import.meta.url,argv1:overrides.argv1??process.argv[1],realpath:overrides.realpath??defaultRealpath,isFile:overrides.isFile??defaultIsFile},moduleFile=moduleFilePath(deps.moduleUrl),candidates=[];if(moduleFile!==null){let dir=dirname(moduleFile);candidates.push(join(dir,CONDUCTOR_BIN_FILENAME)),candidates.push(join(dir,"..",CONDUCTOR_BIN_FILENAME))}typeof deps.argv1=="string"&&deps.argv1.length>0&&basename2(deps.argv1)===CONDUCTOR_BIN_FILENAME&&candidates.push(deps.argv1);let seen=new Set;for(let candidate of candidates){let canonical;try{canonical=deps.realpath(candidate)}catch{continue}if(canonical!==null&&!seen.has(canonical)){seen.add(canonical);try{if(deps.isFile(canonical))return{ok:!0,path:canonical}}catch{continue}}}return{ok:!1,reason:CONDUCTOR_HOOK_BIN_UNRESOLVED_REASON}}function moduleFilePath(moduleUrl){try{return fileURLToPath(moduleUrl)}catch{return null}}function defaultRealpath(filePath){try{return realpathSync(filePath)}catch{return null}}function defaultIsFile(filePath){try{return statSync(filePath).isFile()}catch{return!1}}function wrapManagedBlock(body){return[BRIDGE_CONDUCTOR_HOOK_START,body,BRIDGE_CONDUCTOR_HOOK_END].join(`
|
|
117
|
-
`)}function
|
|
118
|
-
`);return wrapManagedBlock(body)}function buildReferenceTransactionHookSnippet(conductorBin){let body=["# Managed by Bridge conductor (BAPI-395). Local, unversioned, opportunistic, bypassable.",'__bridge_tmp="$(mktemp 2>/dev/null || echo "/tmp/bridge-conductor-refs.$$")"','cat > "$__bridge_tmp"',`( node ${JSON.stringify(conductorBin)} git-hook reference-transaction --phase "$1" --stdin-file "$__bridge_tmp" >/dev/null 2>&1 & ) || true`].join(`
|
|
119
|
-
`);return wrapManagedBlock(body)}function looksBinary(content){return content.includes("\0")}function mergeManagedHookSnippet(existing,managedBlock){if(existing===null||existing.length===0)return{ok:!0,content:`#!/bin/sh
|
|
120
|
-
${managedBlock}
|
|
121
|
-
`,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(`
|
|
122
|
-
`)?"":`
|
|
123
|
-
`;return{ok:!0,content:`${existing}${separator}${managedBlock}
|
|
124
|
-
`,action:"appended"}}var CONDUCTOR_BIN_UNRESOLVED_ERROR="CONDUCTOR_BIN_UNRESOLVED";function snippetForHook(name,conductorBin){return name==="post-commit"?buildPostCommitHookSnippet(conductorBin):buildReferenceTransactionHookSnippet(conductorBin)}function validateResolvedBin(resolution){if(!resolution.ok)return resolution;let canonical=defaultRealpath(resolution.path);return canonical===null||!defaultIsFile(canonical)?{ok:!1,reason:CONDUCTOR_HOOK_BIN_UNRESOLVED_REASON}:{ok:!0,path:canonical}}function installConductorGitHooks(deps={}){let platform=deps.platform??process.platform,resolution=validateResolvedBin(deps.resolveBin?deps.resolveBin():resolveConductorHookBin());if(!resolution.ok)return{ok:!1,error:CONDUCTOR_BIN_UNRESOLVED_ERROR,reason:resolution.reason};let conductorBin=resolution.path,{is_worktree,hooks_dir}=resolveGitHooksDirectory(deps);if(!is_worktree||hooks_dir===null)return{ok:!0,is_worktree:!1,hooks_dir:null,installed:[],warnings:["not a git worktree; git hooks were not installed (degraded optional capability)"],conductor_bin:conductorBin};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{ok:!0,is_worktree:!0,hooks_dir,installed,warnings,conductor_bin:conductorBin}}function extractManagedHookBinPath(content){let startIdx=content.indexOf(BRIDGE_CONDUCTOR_HOOK_START),endIdx=content.indexOf(BRIDGE_CONDUCTOR_HOOK_END);if(startIdx===-1||endIdx===-1||endIdx<=startIdx)return null;let block=content.slice(startIdx,endIdx),match=/\bnode\s+("(?:[^"\\]|\\.)*")\s+git-hook\b/.exec(block);if(match===null)return null;try{let parsed=JSON.parse(match[1]);return typeof parsed=="string"&&parsed.length>0?parsed:null}catch{return null}}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,embeddedBinPath=null,embeddedBinIsFile=!1;if(exists){try{let mode=statSync(hookPath).mode;executable=platform==="win32"?!0:(mode&73)!==0}catch{}try{let content=readFileSync(hookPath,"utf-8");managedPresent=content.includes(BRIDGE_CONDUCTOR_HOOK_START),managedPresent&&(embeddedBinPath=extractManagedHookBinPath(content),embeddedBinIsFile=embeddedBinPath!==null&&defaultIsFile(embeddedBinPath),embeddedBinPath===null?warnings.push(`${name} hook has a managed block with no recognizable conductor command; reinstall with \`conductor install-git-hooks\``):embeddedBinIsFile||warnings.push(`${name} hook points at a missing or invalid conductor binary (${embeddedBinPath}); the hook is dead \u2014 reinstall with \`conductor install-git-hooks\``))}catch{}}else warnings.push(`${name} hook not installed (degraded optional capability)`);hooks.push({name,path:hookPath,exists,executable,managed_block_present:managedPresent,embedded_bin_path:embeddedBinPath,embedded_bin_is_file:embeddedBinIsFile})}let degraded=hooks.some(h=>!h.exists||!h.managed_block_present||!h.embedded_bin_is_file);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();init_mcp_identity();init_mcp_profile();var MCP_PROFILE_UNSET="(unset)";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 collectConductorNativeLedger(deps={}){let ledger=await(deps.doctorLedger??doctorConductorLedger)(),native_ledger=await inspectNativeLedger(ledger.native_load,deps);return{ledger,native_ledger}}function inspectMcpProfile(env){let raw=env.BRIDGE_MCP_PROFILE,raw_profile=raw===void 0?MCP_PROFILE_UNSET:raw,groups=resolveProfiles(raw),active_groups=Array.from(groups),conductor_context_detected=env.BAPI_CONDUCTOR_ENABLED==="1"||env.BAPI_CONDUCTOR_ENABLED==="true",degraded=conductor_context_detected&&!groups.has("conductor"),warnings=[];return degraded&&warnings.push(`BRIDGE_MCP_PROFILE is ${raw_profile} (active groups: ${active_groups.join(", ")}) but a conductor context is active. ADD \`conductor\` to BRIDGE_MCP_PROFILE (e.g. \`${raw_profile===MCP_PROFILE_UNSET?"conductor":`${raw_profile},conductor`}\`) \u2014 do NOT replace the value, which would drop the worker's other groups. Without it the conductor/event/supervisor tools are not registered.`),{raw_profile,active_groups,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 inspectHooks=deps.inspectHooks??inspectConductorGitHooks,mcp_profile=inspectMcpProfile(deps.env??process.env),{ledger,native_ledger}=await collectConductorNativeLedger(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),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,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} bin=${hook.embedded_bin_path??"n/a"} bin_is_file=${hook.embedded_bin_is_file}`);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 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 ${MCP_PACKAGE_NAME} 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(`raw profile: ${mcp_profile.raw_profile}`),lines.push(`active groups: ${mcp_profile.active_groups.join(", ")} ${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(`
|
|
125
|
-
`)}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)"," stop-run Stop an epic run: block dispatch and cancel queued work"," (the run record is preserved). Idempotent."," abandon-run Abandon an epic run \u2014 TERMINAL and IRREVERSIBLE."," Idempotent on an already-abandoned run."," unpark Move a parked (needs_human) ticket back into its gate"," machine. Retries internally on a concurrent change."," adopt-current-head-and-unpark"," Recover a ticket parked by a PR-head drift: adopt the"," CURRENT PR head and unpark in one step.","","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","","stop-run / abandon-run options:"," --epic-run-id <id> Epic run identifier (required)"," --json Print compact JSON result"," --help Print this usage message"," stop-run BLOCKS new dispatch and CANCELS queued work; the run record is"," preserved and the run cannot resume on its own \u2014 it is an emergency brake,"," not a pause. abandon-run is the SAME plus a TERMINAL, IRREVERSIBLE close-out:"," once abandoned, the run can never resume or be reused. Both are idempotent \u2014"," repeating either is a safe no-op once the run is already stopped/abandoned.","","unpark / adopt-current-head-and-unpark options:"," --epic-run-id <id> Epic run identifier (required)"," --ticket-key <key> Ticket key (required)"," --json Print compact JSON result"," --help Print this usage message"," unpark resumes a ticket PARKED with needs_human, once the underlying cause"," is resolved. adopt-current-head-and-unpark additionally REBINDS the ticket's"," anchored PR head to whatever the PR's head currently is, for a ticket parked"," by a human/external push. Both retry internally on a concurrent row change \u2014"," neither accepts, nor ever asks for, a version counter.","","Incident examples:"," # A run is misbehaving and must stop immediately:"," conductor stop-run --epic-run-id 3f9c2b7e-..."," # The run is done for good \u2014 close it out:"," conductor abandon-run --epic-run-id 3f9c2b7e-..."," # A ticket parked itself (needs_human) and the cause is now fixed:"," conductor unpark --epic-run-id 3f9c2b7e-... --ticket-key BAPI-852"," # A human pushed directly to the PR and the ticket parked on head drift:"," conductor adopt-current-head-and-unpark --epic-run-id 3f9c2b7e-... --ticket-key BAPI-852"].join(`
|
|
126
|
-
`)}var CONDUCTOR_HOOK_BIN_ACTION="__hook-bin",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","stop-run","abandon-run","unpark","adopt-current-head-and-unpark",CONDUCTOR_HOOK_BIN_ACTION]);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(`
|
|
129
|
+
`)}});init_errors();init_store();init_producer_ledger();init_taxonomy();init_git_hooks();init_file_scope_guard();import{readFileSync as readFileSync3,unlinkSync}from"node:fs";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_doctor();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)"," readiness Read-only ADVISORY report of every conductor prerequisite"," (install + conductor doctor + plane preflight + server),"," each with pass/warn/fail/skip and one named remediation."," Remediations are NOT run automatically; always exits 0."," 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)"," stop-run Stop an epic run: block dispatch and cancel queued work"," (the run record is preserved). Idempotent."," abandon-run Abandon an epic run \u2014 TERMINAL and IRREVERSIBLE."," Idempotent on an already-abandoned run."," unpark Move a parked (needs_human) ticket back into its gate"," machine. Retries internally on a concurrent change."," adopt-current-head-and-unpark"," Recover a ticket parked by a PR-head drift: adopt the"," CURRENT PR head and unpark in one step.","","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.","","readiness options:"," --json Print the versioned structured report as JSON"," --no-deny-probe Accepted for parity with `doctor`; inert here \u2014 `readiness`"," never spawns the deny-enforcement probe, and reports that"," check as an explicit skip naming `conductor doctor`"," --help Print the readiness usage message"," Note: advisory only. It blocks nothing and changes no exit code; `drive-epic`"," remains the sole route-selection gate and server-side admission the sole refusal.","","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","","stop-run / abandon-run options:"," --epic-run-id <id> Epic run identifier (required)"," --json Print compact JSON result"," --help Print this usage message"," stop-run BLOCKS new dispatch and CANCELS queued work; the run record is"," preserved and the run cannot resume on its own \u2014 it is an emergency brake,"," not a pause. abandon-run is the SAME plus a TERMINAL, IRREVERSIBLE close-out:"," once abandoned, the run can never resume or be reused. Both are idempotent \u2014"," repeating either is a safe no-op once the run is already stopped/abandoned.","","unpark / adopt-current-head-and-unpark options:"," --epic-run-id <id> Epic run identifier (required)"," --ticket-key <key> Ticket key (required)"," --json Print compact JSON result"," --help Print this usage message"," unpark resumes a ticket PARKED with needs_human, once the underlying cause"," is resolved. adopt-current-head-and-unpark additionally REBINDS the ticket's"," anchored PR head to whatever the PR's head currently is, for a ticket parked"," by a human/external push. Both retry internally on a concurrent row change \u2014"," neither accepts, nor ever asks for, a version counter.","","Incident examples:"," # A run is misbehaving and must stop immediately:"," conductor stop-run --epic-run-id 3f9c2b7e-..."," # The run is done for good \u2014 close it out:"," conductor abandon-run --epic-run-id 3f9c2b7e-..."," # A ticket parked itself (needs_human) and the cause is now fixed:"," conductor unpark --epic-run-id 3f9c2b7e-... --ticket-key BAPI-852"," # A human pushed directly to the PR and the ticket parked on head drift:"," conductor adopt-current-head-and-unpark --epic-run-id 3f9c2b7e-... --ticket-key BAPI-852"].join(`
|
|
130
|
+
`)}var CONDUCTOR_HOOK_BIN_ACTION="__hook-bin",VALID_COMMANDS=new Set(["emit-event","supervise","epic-tick","approve-plan","epic-status","send-message","check-messages","doctor","readiness","purge","install-git-hooks","git-hook","file-scope-guard","stop-run","abandon-run","unpark","adopt-current-head-and-unpark",CONDUCTOR_HOOK_BIN_ACTION]);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(`
|
|
127
131
|
`)),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(`
|
|
128
132
|
`)),0}var DIAGNOSTIC_BOOL_FLAGS=new Set(["--json","--help"]),DOCTOR_BOOL_FLAGS=new Set([...DIAGNOSTIC_BOOL_FLAGS,"--no-deny-probe"]);async function runDoctorCommand(argv,deps={}){let{bools}=tokenizeFlags(argv,new Set,DOCTOR_BOOL_FLAGS);if(bools.has("--help"))return console.log(getConductorUsage()),0;let report=await buildConductorDoctorReport(bools.has("--no-deny-probe")?{...deps,skipDenyProbe:!0}:deps);return bools.has("--json")?(console.log(JSON.stringify({...report.ledger,git_hooks:report.git_hooks,mcp_profile:report.mcp_profile,native_ledger:report.native_ledger,deny_enforcement:report.deny_enforcement})),0):(console.log(formatConductorDoctorReport(report)),0)}function runInstallGitHooksCommand(argv){let{bools}=tokenizeFlags(argv,new Set,DIAGNOSTIC_BOOL_FLAGS);if(bools.has("--help"))return console.log(getConductorUsage()),0;let result=installConductorGitHooks();if(!result.ok)return bools.has("--json")?(console.error(JSON.stringify({error:result.error,reason:result.reason})),1):(console.error(`Error: conductor git hooks were NOT installed (${result.error}): ${result.reason}`),1);if(bools.has("--json"))return console.log(JSON.stringify(result)),0;let lines=["Conductor git hooks install","\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",`is git worktree: ${result.is_worktree}`,`hooks dir: ${result.hooks_dir??"n/a"}`,`conductor bin: ${result.conductor_bin}`];for(let hook of result.installed)lines.push(` ${hook.name}: ${hook.action}${hook.warning?` (${hook.warning})`:""}`);if(result.warnings.length>0){lines.push("warnings:");for(let w of result.warnings)lines.push(` - ${w}`)}return console.log(lines.join(`
|
|
129
133
|
`)),0}function runHookBinDiagnosticCommand(){let resolution=resolveConductorHookBin();return resolution.ok?(console.log(resolution.path),0):(console.error(`conductor hook bin UNRESOLVED: ${resolution.reason}`),1)}var GIT_HOOK_VALUE_FLAGS=new Set(["--phase","--stdin-file"]),GIT_HOOK_BOOL_FLAGS=new Set(["--help"]);function parseGitHookArgs(argv){let subcommand=argv[0];if(subcommand!=="post-commit"&&subcommand!=="reference-transaction")throw new ConductorValidationError(`Unknown git-hook subcommand "${subcommand??""}". Expected "post-commit" or "reference-transaction".`);let{values}=tokenizeFlags(argv.slice(1),GIT_HOOK_VALUE_FLAGS,GIT_HOOK_BOOL_FLAGS);return{subcommand,phase:values.get("--phase"),stdinFile:values.get("--stdin-file")}}async function runGitHookCommand(argv){let parsed;try{parsed=parseGitHookArgs(argv)}catch{return process.stderr.write(`Warning: conductor git-hook invocation was invalid.
|
|
@@ -132,5 +136,5 @@ ${managedBlock}
|
|
|
132
136
|
Tickets (${state.ticket_statuses.length}):`);for(let t of state.ticket_statuses){let dispatchRef=t.dispatch_run_id?`dispatch_run_id=${t.dispatch_run_id}`:"-";lines.push(` ${t.ticket_key} [${t.status}] ${dispatchRef} remediation=${t.remediation_attempts}/${t.remediation_no_progress_attempts}`)}lines.push(`
|
|
133
137
|
Dispatches (${state.dispatches.length}):`);for(let d of state.dispatches){let runRef=d.run_id?`run_id=${d.run_id}`:"-";lines.push(` ${d.dispatch_key} [${d.status}] ${runRef}`)}return console.log(lines.join(`
|
|
134
138
|
`)),0}catch(error){if(error instanceof BridgeApiError&&error.status===404)return parsed.json?console.log(JSON.stringify({epic_key:parsed.epicKey,status:"unknown",state:null})):console.log("No such epic found."),0;let envelope=toConductorErrorEnvelope(error);return parsed.json?console.log(JSON.stringify(envelope)):console.error(`Error: ${formatConductorErrorLine(envelope)}`),envelope.status>=500?2:1}}var SUPERVISE_VALUE_FLAGS=new Set(["--run-id","--wake-interval-ms","--global-timeout-ms","--escalation-cooldown-ms"]),SUPERVISE_BOOL_FLAGS=new Set(["--help"]);function parsePositiveIntFlag(values,flag){let raw=values.get(flag);if(raw===void 0)return;if(!/^\d+$/.test(raw.trim()))throw new ConductorValidationError(`Flag "${flag}" must be a non-negative integer.`);let n=Number.parseInt(raw.trim(),10);if(!Number.isFinite(n))throw new ConductorValidationError(`Flag "${flag}" must be a non-negative integer.`);return n}function parseSuperviseArgs(argv){let{values,bools}=tokenizeFlags(argv,SUPERVISE_VALUE_FLAGS,SUPERVISE_BOOL_FLAGS);if(bools.has("--help"))return{runId:"",overrides:{},help:!0};let runIdRaw=values.get("--run-id");if(runIdRaw===void 0||runIdRaw.trim().length===0)throw new ConductorValidationError('Flag "--run-id" is required for supervise and must be non-empty.');let overrides={},wake=parsePositiveIntFlag(values,"--wake-interval-ms");wake!==void 0&&(overrides.wake_interval_ms=wake);let globalTimeout=parsePositiveIntFlag(values,"--global-timeout-ms");globalTimeout!==void 0&&(overrides.global_timeout_ms=globalTimeout);let cooldown=parsePositiveIntFlag(values,"--escalation-cooldown-ms");return cooldown!==void 0&&(overrides.escalation_cooldown_ms=cooldown),{runId:runIdRaw.trim(),overrides,help:!1}}async function runSuperviseCommand(argv){let parsed=parseSuperviseArgs(argv);if(parsed.help)return console.log(getConductorUsage()),0;let config=resolveSupervisorConfig(parsed.overrides);console.log(`[supervisor] starting run=${parsed.runId} wake=${config.wake_interval_ms}ms global_timeout=${config.global_timeout_ms}ms`);let{runSupervisor:runSupervisor2}=await Promise.resolve().then(()=>(init_supervisor_runtime(),supervisor_runtime_exports));return(await runSupervisor2({run_id:parsed.runId,config})).exit_code}async function runPurgeCommand(argv){let{bools}=tokenizeFlags(argv,new Set,DIAGNOSTIC_BOOL_FLAGS);if(bools.has("--help"))return console.log(getConductorUsage()),0;let result=await purgeConductorLedger();return bools.has("--json")?(console.log(JSON.stringify(result)),0):(console.log([`Conductor ledger purged (existed: ${result.existed}).`,` events: ${result.deleted.events}`,` messages: ${result.deleted.messages}`,` supervisor_projection: ${result.deleted.supervisor_projection}`].join(`
|
|
135
|
-
`)),0)}async function runConductorCli(argv){let parsed=parseConductorArgs(argv);if(parsed.kind==="help")return console.log(getConductorUsage()),0;if(parsed.kind==="error")return console.error(`Error: ${parsed.message}`),1;try{switch(parsed.command){case"emit-event":return await runEmitEventCommand(parsed.argv);case"supervise":return await runSuperviseCommand(parsed.argv);case"epic-tick":return await runEpicTickCommand(parsed.argv);case"approve-plan":return await runApprovePlanCommand(parsed.argv);case"epic-status":return await runEpicStatusCommand(parsed.argv);case"send-message":return await runSendMessageCommand(parsed.argv);case"check-messages":return await runCheckMessagesCommand(parsed.argv);case"doctor":return await runDoctorCommand(parsed.argv);case"purge":return await runPurgeCommand(parsed.argv);case"install-git-hooks":return runInstallGitHooksCommand(parsed.argv);case"git-hook":return await runGitHookCommand(parsed.argv);case CONDUCTOR_HOOK_BIN_ACTION:return runHookBinDiagnosticCommand();case"file-scope-guard":return runFileScopeGuardCli();case"stop-run":{let{runStopRunCommand:runStopRunCommand2}=await Promise.resolve().then(()=>(init_recovery_cli(),recovery_cli_exports));return await runStopRunCommand2(parsed.argv)}case"abandon-run":{let{runAbandonRunCommand:runAbandonRunCommand2}=await Promise.resolve().then(()=>(init_recovery_cli(),recovery_cli_exports));return await runAbandonRunCommand2(parsed.argv)}case"unpark":{let{runUnparkCommand:runUnparkCommand2}=await Promise.resolve().then(()=>(init_recovery_cli(),recovery_cli_exports));return await runUnparkCommand2(parsed.argv)}case"adopt-current-head-and-unpark":{let{runAdoptCurrentHeadAndUnparkCommand:runAdoptCurrentHeadAndUnparkCommand2}=await Promise.resolve().then(()=>(init_recovery_cli(),recovery_cli_exports));return await runAdoptCurrentHeadAndUnparkCommand2(parsed.argv)}default:return console.error('Error: Unknown command. Run "conductor --help" for usage.'),1}}catch(error){let envelope=toConductorErrorEnvelope(error);return console.error(`Error: ${formatConductorErrorLine(envelope)}`),envelope.status>=500?2:1}}Promise.resolve(runConductorCli(process.argv.slice(2))).then(exitCode=>{process.exit(exitCode)}).catch(()=>{process.stderr.write(`Error: conductor command failed.
|
|
139
|
+
`)),0)}async function runConductorCli(argv){let parsed=parseConductorArgs(argv);if(parsed.kind==="help")return console.log(getConductorUsage()),0;if(parsed.kind==="error")return console.error(`Error: ${parsed.message}`),1;try{switch(parsed.command){case"emit-event":return await runEmitEventCommand(parsed.argv);case"supervise":return await runSuperviseCommand(parsed.argv);case"epic-tick":return await runEpicTickCommand(parsed.argv);case"approve-plan":return await runApprovePlanCommand(parsed.argv);case"epic-status":return await runEpicStatusCommand(parsed.argv);case"send-message":return await runSendMessageCommand(parsed.argv);case"check-messages":return await runCheckMessagesCommand(parsed.argv);case"doctor":return await runDoctorCommand(parsed.argv);case"readiness":{let{runConductorReadinessCommand:runConductorReadinessCommand2}=await Promise.resolve().then(()=>(init_readiness_cli(),readiness_cli_exports));return await runConductorReadinessCommand2(parsed.argv)}case"purge":return await runPurgeCommand(parsed.argv);case"install-git-hooks":return runInstallGitHooksCommand(parsed.argv);case"git-hook":return await runGitHookCommand(parsed.argv);case CONDUCTOR_HOOK_BIN_ACTION:return runHookBinDiagnosticCommand();case"file-scope-guard":return runFileScopeGuardCli();case"stop-run":{let{runStopRunCommand:runStopRunCommand2}=await Promise.resolve().then(()=>(init_recovery_cli(),recovery_cli_exports));return await runStopRunCommand2(parsed.argv)}case"abandon-run":{let{runAbandonRunCommand:runAbandonRunCommand2}=await Promise.resolve().then(()=>(init_recovery_cli(),recovery_cli_exports));return await runAbandonRunCommand2(parsed.argv)}case"unpark":{let{runUnparkCommand:runUnparkCommand2}=await Promise.resolve().then(()=>(init_recovery_cli(),recovery_cli_exports));return await runUnparkCommand2(parsed.argv)}case"adopt-current-head-and-unpark":{let{runAdoptCurrentHeadAndUnparkCommand:runAdoptCurrentHeadAndUnparkCommand2}=await Promise.resolve().then(()=>(init_recovery_cli(),recovery_cli_exports));return await runAdoptCurrentHeadAndUnparkCommand2(parsed.argv)}default:return console.error('Error: Unknown command. Run "conductor --help" for usage.'),1}}catch(error){let envelope=toConductorErrorEnvelope(error);return console.error(`Error: ${formatConductorErrorLine(envelope)}`),envelope.status>=500?2:1}}Promise.resolve(runConductorCli(process.argv.slice(2))).then(exitCode=>{process.exit(exitCode)}).catch(()=>{process.stderr.write(`Error: conductor command failed.
|
|
136
140
|
`),process.exit(2)});
|