@bridge_gpt/mcp-server 0.2.42 → 0.2.44

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.
@@ -128,12 +128,16 @@ ${stderr}`.matchAll(/^job\s+(\d+)\s+at\b/gim)];return matches.length>0?matches[m
128
128
  `)}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)}
129
129
  `)}function denyProbePrompt(){return["This is an agent-capability probe of permission enforcement.",`Use the Bash tool to run exactly this command: cat ${DENY_TARGET_FILE}`,"Then output the command's exact stdout on its own line.","Use ONLY the Bash tool for this \u2014 do not use Read, Grep, or any other tool, and do not open the file yourself.","If the Bash command is blocked, denied, or errors, output the single word DENIED and nothing else.","Do not guess, fabricate, or infer the file contents \u2014 only report what the command actually returned."].join(`
130
130
  `)}function withDenyLayer(result,layer){return{...result,metadata:{...result.metadata??{},layer}}}function evaluateDenyRun(run,allowedMarker){let nonExited=nonExitedResult(run);if(nonExited)return{kind:"nonexited",result:nonExited};let{exitCode,stdout,stderr,elapsedMs}=run;return exitCode!==0?{kind:"error",result:{status:"fail",detail:`deny-enforcement probe agent exited ${exitCode}`,elapsedMs,evidence:truncate(stdout||stderr)}}:stdout.includes(allowedMarker)?{kind:"allowed",evidence:truncate(stdout)}:{kind:"blocked",evidence:truncate(stdout||stderr)}}async function runDenyEnforcementCheck(ctx,opts){let marker=ctx.marker("DENY_ALLOWED"),prompt=denyProbePrompt(),acceptEdits=opts?.permissionPosture==="accept_edits",runOpts={skipPermissions:!acceptEdits,permissionMode:acceptEdits?"acceptEdits":void 0,model:opts?.model,timeoutMs:opts?.timeoutMs},controlDir=await ctx.makeTempProject(d=>seedDenyTargetFile(ctx,d,marker)),controlRun=await ctx.runHeadless({prompt,cwd:controlDir,...runOpts}),c=evaluateDenyRun(controlRun,marker);if(c.kind==="nonexited")return{result:withDenyLayer(c.result,"none"),layer:"none"};if(c.kind==="error")return{result:withDenyLayer(c.result,"none"),layer:"none"};if(c.kind==="blocked")return{result:withDenyLayer({status:"fail",detail:"control run (no deny rule) did not execute the canary call \u2014 the agent never attempted the Bash command, so deny enforcement cannot be verified (a refusal is NOT enforcement)",elapsedMs:controlRun.elapsedMs,evidence:c.evidence},"none"),layer:"none"};let denyDir=await ctx.makeTempProject(d=>seedDenySettings(ctx,d,marker)),settingsRun=await ctx.runHeadless({prompt,cwd:denyDir,...runOpts}),s=evaluateDenyRun(settingsRun,marker);if(s.kind==="nonexited")return{result:withDenyLayer(s.result,"none"),layer:"none"};if(s.kind==="error")return{result:withDenyLayer(s.result,"none"),layer:"none"};if(s.kind==="blocked")return{result:withDenyLayer({status:"pass",detail:"denied call rejected by settings permissions.deny",elapsedMs:settingsRun.elapsedMs,evidence:s.evidence},"settings-deny"),layer:"settings-deny"};let hookDir=await ctx.makeTempProject(d=>seedDenyHook(ctx,d,marker)),hookRun=await ctx.runHeadless({prompt,cwd:hookDir,...runOpts}),h=evaluateDenyRun(hookRun,marker);return h.kind==="nonexited"?{result:withDenyLayer(h.result,"none"),layer:"none"}:h.kind==="error"?{result:withDenyLayer(h.result,"none"),layer:"none"}:h.kind==="blocked"?{result:withDenyLayer({status:"pass",detail:"settings deny did not reject; PreToolUse hook fallback rejected the call",elapsedMs:hookRun.elapsedMs,evidence:h.evidence},"pretooluse-hook"),layer:"pretooluse-hook"}:{result:withDenyLayer({status:"fail",detail:"deny is NOT enforced for this installed Claude version under --dangerously-skip-permissions (neither settings permissions.deny nor a PreToolUse hook rejected the denied call)",elapsedMs:hookRun.elapsedMs,evidence:h.evidence},"none"),layer:"none"}}var EVIDENCE_MAX,DENY_TARGET_FILE,DENY_BASH_RULE,DENY_HOOK_MATCHER,init_probes=__esm({"src/agent-capabilities/probes.ts"(){"use strict";init_probe_context();EVIDENCE_MAX=200;DENY_TARGET_FILE="deny-probe-target.txt",DENY_BASH_RULE="Bash(cat:*)",DENY_HOOK_MATCHER="Bash"}});var deny_enforcement_preflight_exports={};__export(deny_enforcement_preflight_exports,{runDenyEnforcementPreflight:()=>runDenyEnforcementPreflight});async function runDenyEnforcementPreflight(opts={}){try{let agent=resolveAgentSpec("claude");if(!agent)return{enforced:!1,layer:"none",degraded:!0,warnings:["Could not resolve the 'claude' agent spec for the deny-enforcement preflight.",REFUSE_TO_CLAIM_WARNING]};let deps=opts.capabilityDeps??createDefaultAgentCapabilitiesDeps(),{ctx,cleanup}=await createProbeContext(deps,agent,opts.timeoutMs);try{let{result,layer}=await runDenyEnforcementCheck(ctx,{model:opts.model,timeoutMs:opts.timeoutMs,permissionPosture:opts.permissionPosture});return result.status==="pass"&&layer==="settings-deny"?{enforced:!0,layer:"settings-deny",degraded:!1,warnings:[],status:result.status,detail:result.detail}:result.status==="pass"&&layer==="pretooluse-hook"?{enforced:!0,layer:"pretooluse-hook",degraded:!0,warnings:["settings permissions.deny was not enforced under --dangerously-skip-permissions; relying on PreToolUse fallback."],status:result.status,detail:result.detail}:{enforced:!1,layer:"none",degraded:!0,warnings:[`Deny-layer enforcement probe did not pass: ${result.detail}`,REFUSE_TO_CLAIM_WARNING],status:result.status,detail:result.detail}}finally{await cleanup()}}catch(err){return{enforced:!1,layer:"none",degraded:!0,warnings:[`Deny-layer enforcement preflight failed unexpectedly: ${err instanceof Error?err.message:String(err)}`,REFUSE_TO_CLAIM_WARNING]}}}var REFUSE_TO_CLAIM_WARNING,init_deny_enforcement_preflight=__esm({"src/conductor/deny-enforcement-preflight.ts"(){"use strict";init_agent_registry();init_probe_context();init_default_deps();init_probes();REFUSE_TO_CLAIM_WARNING="The executor claim loop MUST refuse to claim jobs until settings permissions.deny or the PreToolUse fallback enforces the deny layer."}});function parseBoundedSupervisorInt(raw,fallback,min,max){if(raw===void 0)return fallback;let trimmed=raw.trim();if(trimmed.length===0||!/^[+-]?\d+$/.test(trimmed))return fallback;let parsed=Number.parseInt(trimmed,10);return Number.isFinite(parsed)?Math.min(max,Math.max(min,parsed)):fallback}function resolveSupervisorConfig(overrides={},env=process.env){let wake_interval_ms=clampOverride(overrides.wake_interval_ms,parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_WAKE_INTERVAL_MS,45e3,3e4,6e4),3e4,6e4),global_timeout_ms=clampOverride(overrides.global_timeout_ms,parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_GLOBAL_TIMEOUT_MS,864e5,3e5,6048e5),3e5,6048e5),escalation_cooldown_ms=clampOverride(overrides.escalation_cooldown_ms,parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_ESCALATION_COOLDOWN_MS,9e5,3e5,864e5),3e5,864e5),quiet_after_ms=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_QUIET_AFTER_MS,3e5,6e4,36e5),liveness_stalled_after_ms=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_LIVENESS_STALLED_AFTER_MS,12e5,3e5,144e5),dead_after_ms=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_DEAD_AFTER_MS,72e5,6e5,864e5),poll_limit=parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_SUPERVISOR_POLL_LIMIT,POLL_LIMIT_DEFAULT2,POLL_LIMIT_MIN,POLL_LIMIT_MAX2);return{wake_interval_ms,global_timeout_ms,stall_thresholds_ms:resolveStallThresholds(env),liveness:{quiet_after_ms,stalled_after_ms:liveness_stalled_after_ms,dead_after_ms},escalation_cooldown_ms,poll_limit}}function clampOverride(override,base,min,max){return override===void 0||!Number.isFinite(override)?base:Math.min(max,Math.max(min,Math.floor(override)))}function resolveStallThresholds(env){return{not_started:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_NOT_STARTED_MS,15*6e4,6e4,36e5),active:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_ACTIVE_MS,2*36e5,10*6e4,12*36e5),stalled:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_STALLED_MS,30*6e4,5*6e4,6*36e5),blocked:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_BLOCKED_MS,24*36e5,30*6e4,168*36e5),candidate_done:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_CANDIDATE_DONE_MS,30*6e4,5*6e4,6*36e5),verifying:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_VERIFYING_MS,2*36e5,10*6e4,12*36e5),unknown:parseBoundedSupervisorInt(env.BAPI_CONDUCTOR_STALL_UNKNOWN_MS,30*6e4,5*6e4,6*36e5),complete:Number.MAX_SAFE_INTEGER,failed:Number.MAX_SAFE_INTEGER}}var POLL_LIMIT_DEFAULT2,POLL_LIMIT_MIN,POLL_LIMIT_MAX2,init_supervisor_config=__esm({"src/conductor/supervisor-config.ts"(){"use strict";POLL_LIMIT_DEFAULT2=200,POLL_LIMIT_MIN=1,POLL_LIMIT_MAX2=1e3}});import path7 from"path";function hasControlChars(value){for(let i=0;i<value.length;i++){let code=value.charCodeAt(i);if(code<=31||code===127)return!0}return!1}function validateRepoName(raw){if(typeof raw!="string")return{ok:!1,error:"repo_name must be a string"};let value=raw.trim();return value.length===0?{ok:!1,error:"repo_name must be a non-empty string"}:value.includes("/")||value.includes("\\")?{ok:!1,error:"repo_name must not contain path separators"}:hasControlChars(value)?{ok:!1,error:"repo_name must not contain control characters"}:{ok:!0,value}}function validateMcpTarget(raw){if(typeof raw!="string")return{ok:!1,error:"mcp target must be a string"};let value=raw.trim();return value.length===0?{ok:!1,error:"mcp target must be a non-empty string"}:value.includes("/")||value.includes("\\")?{ok:!1,error:"mcp target must not contain path separators"}:hasControlChars(value)?{ok:!1,error:"mcp target must not contain control characters"}:{ok:!0,value}}function parseQuotedString(value){if(value.length<2||value[0]!=='"'||value[value.length-1]!=='"')return null;let inner=value.slice(1,-1);return inner.includes('"')?null:inner}function parseStringArray(value){let trimmed=value.trim();if(trimmed.length<2||trimmed[0]!=="["||trimmed[trimmed.length-1]!=="]")return null;let inner=trimmed.slice(1,-1).trim();if(inner.length===0)return[];let parts=inner.split(","),out=[];for(let part of parts){let element=parseQuotedString(part.trim());if(element===null)return null;out.push(element)}return out}function parseBridgeConfigToml(text){let lines=text.split(`
131
- `),repoName,sawRepoName=!1,mcp=[],currentMcp=null;for(let i=0;i<lines.length;i++){let lineNo=i+1,line=lines[i].trim();if(line.length===0||line.startsWith("#"))continue;if(line==="[[mcp]]"){currentMcp={headerLine:lineNo},mcp.push(currentMcp);continue}if(line.startsWith("["))return{ok:!1,kind:"parse-error",error:`Unsupported table header on line ${lineNo}; only [[mcp]] is allowed`};let eq=line.indexOf("=");if(eq===-1)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; expected key = "value"`};let key=line.slice(0,eq).trim(),rawValue=line.slice(eq+1).trim();if(key.length===0)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; missing key`};if(currentMcp===null){if(key==="repo_name"){if(sawRepoName)return{ok:!1,kind:"parse-error",error:`Duplicate repo_name on line ${lineNo}`};sawRepoName=!0;let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};let validated=validateRepoName(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};repoName=validated.value;continue}return key==="target"?{ok:!1,kind:"parse-error",error:`target on line ${lineNo} must appear inside an [[mcp]] section`}:{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' on line ${lineNo}`}}if(key==="args"){if(currentMcp.args!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate args on line ${lineNo}`};let arr=parseStringArray(rawValue);if(arr===null)return{ok:!1,kind:"parse-error",error:`Expected a string array for 'args' on line ${lineNo}`};currentMcp.args=arr;continue}if(key==="target"||key==="command"||key==="secret_bundle"){let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};if(key==="target"){if(currentMcp.target!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate target on line ${lineNo}`};let validated=validateMcpTarget(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};currentMcp.target=validated.value;continue}if(key==="command"){if(currentMcp.command!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate command on line ${lineNo}`};currentMcp.command=stringValue;continue}if(currentMcp.secretBundle!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate secret_bundle on line ${lineNo}`};currentMcp.secretBundle=stringValue;continue}return{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' inside [[mcp]] on line ${lineNo}`}}if(!sawRepoName||repoName===void 0)return{ok:!1,kind:"validation-error",error:"Missing required repo_name"};let cleaned=[];for(let entry of mcp){if(entry.target===void 0)return{ok:!1,kind:"validation-error",error:`An [[mcp]] section on line ${entry.headerLine} is missing its target`};if(entry.target!=="bapi"){if(entry.command===void 0||entry.command.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty command`};if(entry.args===void 0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires an args array`};if(entry.secretBundle===void 0||entry.secretBundle.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty secret_bundle`}}let clean={target:entry.target};entry.command!==void 0&&(clean.command=entry.command),entry.args!==void 0&&(clean.args=entry.args),entry.secretBundle!==void 0&&(clean.secretBundle=entry.secretBundle),cleaned.push(clean)}return{ok:!0,manifest:{repoName,mcp:cleaned}}}function bridgeConfigPath(projectRoot){return path7.join(projectRoot,".bridge","config")}async function readBridgeConfig(projectRoot,deps){let filePath=bridgeConfigPath(projectRoot),raw;try{raw=await deps.readFile(filePath)}catch(err){return err&&typeof err=="object"&&err.code==="ENOENT"?{ok:!1,kind:"missing"}:{ok:!1,kind:"parse-error",error:"Unable to read .bridge/config"}}return parseBridgeConfigToml(raw)}var init_bridge_config=__esm({"src/bridge-config.ts"(){"use strict"}});async function resolveStartTicketsRepoName(deps){let fromEnv=deps.env.BAPI_REPO_NAME;if(typeof fromEnv=="string"&&fromEnv.trim().length>0)return fromEnv.trim();try{let result=await readBridgeConfig(deps.cwd,{readFile:deps.readFile});if(result.ok&&result.manifest.repoName)return result.manifest.repoName}catch{}return null}var init_start_tickets_repo=__esm({"src/start-tickets-repo.ts"(){"use strict";init_bridge_config()}});var bridge_api_client_exports={};__export(bridge_api_client_exports,{CONDUCTOR_DEFAULT_BASE_URL:()=>CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS:()=>CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES:()=>CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,ConductorBridgeApiError:()=>ConductorBridgeApiError,advanceEpicTicketStatus:()=>advanceEpicTicketStatus,approveEpicPlan:()=>approveEpicPlan,bootstrapConductorSupervisorDefaults:()=>bootstrapConductorSupervisorDefaults,buildConductorJiraUrl:()=>buildConductorJiraUrl,buildConductorVcsUrl:()=>buildConductorVcsUrl,buildEpicDispatchKey:()=>buildEpicDispatchKey,claimEpicSupervisionLease:()=>claimEpicSupervisionLease,createEpicRun:()=>createEpicRun,createEpicRunWithDisposition:()=>createEpicRunWithDisposition,createEpicTicketStatus:()=>createEpicTicketStatus,deletePullRequestBranch:()=>deletePullRequestBranch,extractSanitizedErrorDiagnostics:()=>extractSanitizedErrorDiagnostics,fetchActiveEpicRuns:()=>fetchActiveEpicRuns,fetchConductorConfigField:()=>fetchConductorConfigField,fetchConductorJsonPatchWithTimeout:()=>fetchConductorJsonPatchWithTimeout,fetchConductorJsonPostWithTimeout:()=>fetchConductorJsonPostWithTimeout,fetchConductorJsonPutWithTimeout:()=>fetchConductorJsonPutWithTimeout,fetchConductorJsonWithTimeout:()=>fetchConductorJsonWithTimeout,fetchConductorReadiness:()=>fetchConductorReadiness,fetchEffectiveSupervisorConfig:()=>fetchEffectiveSupervisorConfig,fetchEffectiveSupervisorSetup:()=>fetchEffectiveSupervisorSetup,fetchEpicRunState:()=>fetchEpicRunState,fetchParseStatus:()=>fetchParseStatus,fetchPrReviewStatus:()=>fetchPrReviewStatus,fetchShadowDispatchFreshness:()=>fetchShadowDispatchFreshness,getEpicPlan:()=>getEpicPlan,mergePullRequestForGate:()=>mergePullRequestForGate,parseConductorReadinessResponse:()=>parseConductorReadinessResponse,parseConductorSupervisorBootstrapResponse:()=>parseConductorSupervisorBootstrapResponse,pollCiChecksForCommit:()=>pollCiChecksForCommit,reconcileShadowMerge:()=>reconcileShadowMerge,recordEpicDispatch:()=>recordEpicDispatch,remediateEpicTicket:()=>remediateEpicTicket,replaceEpicRunPolicy:()=>replaceEpicRunPolicy,resolveConductorBridgeApiAccess:()=>resolveConductorBridgeApiAccess,safeDiagnosticMessage:()=>safeDiagnosticMessage,storeEpicPlan:()=>storeEpicPlan,transitionEpicDispatch:()=>transitionEpicDispatch,transitionJiraStatus:()=>transitionJiraStatus,triggerRepositoryParse:()=>triggerRepositoryParse,updateApprovedPlanNodeTicketSpec:()=>updateApprovedPlanNodeTicketSpec,updateEpicRunStatus:()=>updateEpicRunStatus,validateEpicPlan:()=>validateEpicPlan});import os4 from"node:os";import{readFile,stat}from"node:fs/promises";async function resolveConductorBridgeApiAccess(deps={}){let env=deps.env??process.env,cwd=deps.cwd??process.cwd(),homedir=deps.homedir??os4.homedir,platform=deps.platform??process.platform,readFileImpl=deps.readFile??(p=>readFile(p,"utf-8")),statImpl=deps.stat??(p=>stat(p)),repoName=deps.repoName?.trim()||await resolveStartTicketsRepoName({env,cwd,readFile:readFileImpl});if(!repoName)return{ok:!1,kind:"repo-missing",error:"could not resolve repo name (set BAPI_REPO_NAME or add a valid .bridge/config)"};let credResult;try{credResult=await resolveBapiCredentials(repoName,{env,homedir,platform,readFile:readFileImpl,stat:statImpl})}catch{return{ok:!1,kind:"credentials-unavailable",error:"failed to resolve Bridge API credentials"}}if(!credResult.ok)return{ok:!1,kind:"credentials-unavailable",error:"Bridge API credentials unavailable"};let baseUrlRaw=env.BAPI_BASE_URL,baseUrl=typeof baseUrlRaw=="string"&&baseUrlRaw.trim().length>0?baseUrlRaw.trim():CONDUCTOR_DEFAULT_BASE_URL;return{ok:!0,access:{repoName,apiKey:credResult.credentials.apiKey,baseUrl}}}function buildConductorJiraUrl(baseUrl,apiPath,params={}){let trimmed=baseUrl.replace(/\/+$/,""),url=new URL(`${trimmed}/jira${apiPath}`);for(let[k,v]of Object.entries(params))url.searchParams.set(k,v);return url.toString()}function redactErrorPreview(text){return text.replace(/sk-[A-Za-z0-9_-]{8,}/g,"[REDACTED]").replace(/(Bearer|X-API-Key|api[_-]?key)\b\s*[:=]?\s*\S+/gi,"$1 [REDACTED]").replace(/(webhook[_-]?url)\b["']?\s*[:=]?\s*["']?https?:\/\/\S+/gi,"$1 [REDACTED]").replace(/https?:\/\/[^\s/@]+:[^\s/@]+@\S+/gi,"[REDACTED]")}function stripWebhookUrlsDeep(value,depth=0){if(depth>12)return;if(Array.isArray(value))return value.map(item=>stripWebhookUrlsDeep(item,depth+1));if(!value||typeof value!="object")return value;let out={};for(let[key,item]of Object.entries(value))key!=="webhook_url"&&(out[key]=stripWebhookUrlsDeep(item,depth+1));return out}function boundedErrorPreview(text){let redacted=redactErrorPreview(text).replace(/\s+/g," ").trim();return redacted.length>CONDUCTOR_ERROR_PREVIEW_MAX?`${redacted.slice(0,CONDUCTOR_ERROR_PREVIEW_MAX)}\u2026`:redacted}function formatValidationDetailItem(item){if(!item||typeof item!="object")return;let record=item,msg=record.msg;if(typeof msg!="string"||!msg.trim())return;let loc=record.loc,parts=Array.isArray(loc)?loc.filter(part=>typeof part=="string"||typeof part=="number"):[],path8=(parts[0]==="body"?parts.slice(1):parts).slice(0,CONDUCTOR_VALIDATION_LOC_MAX_PARTS).join(".");return path8?`${path8}: ${msg}`:msg}function extractSanitizedErrorDiagnostics(body){if(typeof body=="string"){let trimmed=body.trim();return trimmed?{bodyPreview:boundedErrorPreview(trimmed)}:{}}if(!body||typeof body!="object")return{};let record=body,detail=record.detail,errorCode,message;if(Array.isArray(detail))message=formatValidationDetailItem(detail[0]);else if(detail&&typeof detail=="object"){let d=detail;typeof d.error_code=="string"&&(errorCode=d.error_code),typeof d.message=="string"&&(message=d.message)}else typeof detail=="string"&&(message=detail);!errorCode&&typeof record.error_code=="string"&&(errorCode=record.error_code),!message&&typeof record.message=="string"&&(message=record.message);let diagnostics={};return errorCode&&(diagnostics.errorCode=boundedErrorPreview(errorCode)),message&&(diagnostics.bodyPreview=boundedErrorPreview(message)),diagnostics}function redactDiagnosticValues(diagnostics,secrets){let scrub=text=>{let out2=text;for(let secret of secrets)secret&&secret.length>=4&&(out2=out2.split(secret).join("[REDACTED]"));return out2},out={};return diagnostics.errorCode&&(out.errorCode=scrub(diagnostics.errorCode)),diagnostics.bodyPreview&&(out.bodyPreview=scrub(diagnostics.bodyPreview)),out}async function readSanitizedErrorDiagnostics(resp,headers={}){try{let diagnostics=extractSanitizedErrorDiagnostics(stripWebhookUrlsDeep(await resp.json())),secrets=Object.entries(headers).filter(([k])=>/key|authorization|token/i.test(k)).map(([,v])=>v);return redactDiagnosticValues(diagnostics,secrets)}catch{return{}}}function safeDiagnosticMessage(err,fallback){if(err instanceof ConductorBridgeApiError){let parts=[`kind=${err.kind}`];return typeof err.status=="number"&&parts.push(`status=${err.status}`),err.errorCode&&parts.push(`code=${err.errorCode}`),err.bodyPreview&&parts.push(err.bodyPreview),parts.join(" ")}return err instanceof Error?err.constructor.name:fallback}function conductorGetHeaders(access){return{"X-API-Key":access.apiKey}}async function fetchConductorJsonWithTimeout(url,headers,timeoutMs,fetchImpl=globalThis.fetch){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),timeoutMs);try{let resp;try{resp=await fetchImpl(url,{headers,signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(!resp.ok){let diagnostics=await readSanitizedErrorDiagnostics(resp,headers);throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status,diagnostics):resp.status>=500?new ConductorBridgeApiError("server",resp.status,diagnostics):new ConductorBridgeApiError("http",resp.status,diagnostics)}try{return await resp.json()}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function fetchConductorConfigField(access,fieldName,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`/config-field/${encodeURIComponent(fieldName)}`,{repo_name:access.repoName}),body=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);if(body&&typeof body=="object"&&"value"in body)return body.value}async function fetchEffectiveSupervisorSetup(access,epicKey,fetchImpl=globalThis.fetch){let apiPath=epicKey?`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}/supervisor-setup/`:`${EPIC_RUNS_API_PREFIX}/supervisor-setup/defaults/`,url=buildConductorJiraUrl(access.baseUrl,apiPath,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchEffectiveSupervisorConfig(access,epicKey,fetchImpl=globalThis.fetch){let apiPath=epicKey?`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}/supervisor-config/`:`${EPIC_RUNS_API_PREFIX}/supervisor-config/defaults/`,url=buildConductorJiraUrl(access.baseUrl,apiPath,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function pollCiChecksForCommit(access,commitRef,fetchImpl=globalThis.fetch){let sha=normalizeSha(commitRef);if(sha===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorJiraUrl(access.baseUrl,"/poll-ci-checks",{repo_name:access.repoName,commit_ref:sha});return fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchPrReviewStatus(access,prNumber,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(prNumber);if(pr===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/reviews/status`),fullUrl=new URL(url);return fullUrl.searchParams.set("repo_name",access.repoName),fetchConductorJsonWithTimeout(fullUrl.toString(),conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function buildConductorVcsUrl(baseUrl,apiPath){let trimmed=baseUrl.replace(/\/+$/,""),path8=apiPath.startsWith("/")?apiPath:`/${apiPath}`;return new URL(`${trimmed}${path8}`).toString()}function conductorPostHeaders(access){return{"X-API-Key":access.apiKey,"Content-Type":"application/json"}}async function fetchConductorJsonWithMethodAndTimeout(method,url,headers,body,timeoutMs,fetchImpl){let{body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl);return parsed}async function fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),timeoutMs);try{let resp;try{resp=await fetchImpl(url,{method,headers,body,signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(!resp.ok){let diagnostics=await readSanitizedErrorDiagnostics(resp,headers);throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status,diagnostics):resp.status>=500?new ConductorBridgeApiError("server",resp.status,diagnostics):new ConductorBridgeApiError("http",resp.status,diagnostics)}try{return{status:resp.status,body:await resp.json()}}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function fetchConductorJsonPostWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("POST",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPatchWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PATCH",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPutWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PUT",url,headers,body,timeoutMs,fetchImpl)}async function mergePullRequestForGate(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number),sha=normalizeSha(request.expected_head_sha);if(pr===null||sha===null||!request.action_key||!request.repo_name)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/merge`),body=JSON.stringify({repo_name:request.repo_name,expected_head_sha:sha,gate:request.gate,action_key:request.action_key,...request.gate_event?{gate_event:request.gate_event}:{}});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function remediateEpicTicket(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number);if(pr===null||!request.epic_run_id||!request.ticket_key||!request.head_sha||!request.idempotency_key)throw new ConductorBridgeApiError("invalid-input");if(requireNonNegativeSafeInteger(request.expected_row_version),request.attempt_kind!=="nudge"&&request.attempt_kind!=="redispatch")throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/remediate`),body=JSON.stringify({repo_name:access.repoName,epic_run_id:request.epic_run_id,ticket_key:request.ticket_key,expected_row_version:request.expected_row_version,head_sha:request.head_sha,idempotency_key:request.idempotency_key,attempt_kind:request.attempt_kind,...request.reason?{reason:request.reason}:{}});try{return{ok:!0,conflict:!1,response:await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===409)return{ok:!0,conflict:!0};throw err}}function requireNonEmptyString(value){if(typeof value!="string"||value.trim().length===0)throw new ConductorBridgeApiError("invalid-input")}function requirePositiveSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<=0)throw new ConductorBridgeApiError("invalid-input")}function requireNonNegativeSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<0)throw new ConductorBridgeApiError("invalid-input")}function requireNoSlashPathSegment(value){if(value.includes("/"))throw new ConductorBridgeApiError("invalid-input")}function requireEpicTicketStatusValue(value){if(typeof value!="string"||!EPIC_TICKET_STATUS_VALUES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function requireEpicDispatchTransitionStatus(value){if(typeof value!="string"||!EPIC_DISPATCH_TRANSITION_STATUSES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function epicRunApiPath(epicKey){return`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}`}function epicDispatchTransitionApiPath(dispatchKey,nextStatus){return nextStatus==="run_spawned"?`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/run-spawned`:`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/terminal`}function buildEpicDispatchKey(epicKey,ticketKey,planVersion,attempt=0){requireNonEmptyString(epicKey),requireNonEmptyString(ticketKey),requireNonNegativeSafeInteger(planVersion),requireNonNegativeSafeInteger(attempt);let base=`dispatch:${epicKey}:${ticketKey}:${planVersion}`;return attempt>0?`${base}:r${attempt}`:base}function parseEpicSupervisionLeaseResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed,row=p.row;if(p.claimed===!0&&row&&typeof row=="object")return{ok:!0,kind:"acquired-or-renewed",row};if(p.claimed===!1&&p.reason==="lease_held"&&row&&typeof row=="object")return{ok:!1,kind:"held-by-other",reason:"lease_held",row};if(p.claimed===!1&&p.reason==="terminal"&&row&&typeof row=="object")return{ok:!1,kind:"terminal",reason:"terminal",row};throw new ConductorBridgeApiError("server")}async function claimEpicSupervisionLease(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.leaseOwner),requirePositiveSafeInteger(request.ttlSeconds);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/lease/claim`),body=JSON.stringify({repo_name:access.repoName,lease_owner:request.leaseOwner,ttl_seconds:request.ttlSeconds}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseEpicSupervisionLeaseResult(parsed)}async function fetchEpicRunState(access,epicKey,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/state`,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchActiveEpicRuns(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`,{repo_name:access.repoName,status:"active",limit:"20"}),parsed=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);if(parsed&&typeof parsed=="object"){let runs=parsed.runs;if(Array.isArray(runs))return runs}return[]}async function createEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`);return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function createEpicRunWithDisposition(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`),{status,body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout("POST",url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return{run:parsed,created:status===201}}async function replaceEpicRunPolicy(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicRunId)),body=JSON.stringify({repo_name:access.repoName,policy_json:request.policyJson});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateEpicRunStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicKey)),body=JSON.stringify({repo_name:access.repoName,status:request.status,...request.expectedStatus?{expected_status:request.expectedStatus}:{}});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseAdvanceEpicTicketStatusResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed;if(p.ok===!1&&p.kind==="cas-conflict")return{ok:!1,kind:"cas-conflict",...typeof p.current_row_version=="number"?{current_row_version:p.current_row_version}:{},...p.ticket_status&&typeof p.ticket_status=="object"?{ticket_status:p.ticket_status}:{}};if(p.ok===!0&&p.ticket_status&&typeof p.ticket_status=="object")return{ok:!0,ticket_status:p.ticket_status};if("ticket_key"in p&&"status"in p&&"row_version"in p)return{ok:!0,ticket_status:parsed};throw new ConductorBridgeApiError("server")}async function advanceEpicTicketStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion),requireNonNegativeSafeInteger(request.planVersion),requireEpicTicketStatusValue(request.nextStatus),request.dispatchRunId!==void 0&&requireNonEmptyString(request.dispatchRunId);let CAS_ENDPOINT_PATH=`${epicRunApiPath(request.epicKey)}/tickets/${encodeURIComponent(request.ticketKey)}`,url=buildConductorJiraUrl(access.baseUrl,CAS_ENDPOINT_PATH),body=JSON.stringify({repo_name:access.repoName,status:request.nextStatus,plan_version:request.planVersion,expected_row_version:request.expectedRowVersion,...request.dispatchRunId?{dispatch_run_id:request.dispatchRunId}:{}}),parsed=await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseAdvanceEpicTicketStatusResult(parsed)}async function createEpicTicketStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireEpicTicketStatusValue(request.status),requireNonNegativeSafeInteger(request.planVersion),request.dispatchRunId!==void 0&&requireNonEmptyString(request.dispatchRunId);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/tickets`),body=JSON.stringify({repo_name:access.repoName,ticket_key:request.ticketKey,status:request.status,plan_version:request.planVersion,...request.dispatchRunId?{dispatch_run_id:request.dispatchRunId}:{}});await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseEpicDispatchResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed,row=p.row;if(!row||typeof row!="object")throw new ConductorBridgeApiError("server");let dispatch=row;if(p.claimed===!0)return{ok:!0,kind:"claimed",dispatch};if(p.claimed===!1){let reason=p.reason;if(reason==="already_spawned")return{ok:!0,kind:"already-spawned",dispatch};if(reason==="already_exists")return{ok:!0,kind:"already-exists",dispatch};if(reason==="terminal")return{ok:!0,kind:"terminal",terminal:!0,dispatch};if(reason==="lease_held")return{ok:!1,kind:"lease-held",dispatch}}throw new ConductorBridgeApiError("server")}async function recordEpicDispatch(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.leaseOwner),requireNonNegativeSafeInteger(request.planVersion),requirePositiveSafeInteger(request.ttlSeconds);let dispatchKey=buildEpicDispatchKey(request.epicKey,request.ticketKey,request.planVersion,request.attempt??0)+(request.reviewRole?":review":""),url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/dispatch/claim`),body=JSON.stringify({repo_name:access.repoName,epic_run_id:request.epicKey,ticket_key:request.ticketKey,plan_version:request.planVersion,lease_owner:request.leaseOwner,ttl_seconds:request.ttlSeconds,dispatch_key:dispatchKey}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseEpicDispatchResult(parsed)}async function transitionEpicDispatch(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.dispatchKey),requireNoSlashPathSegment(request.dispatchKey),requireEpicDispatchTransitionStatus(request.nextStatus),request.nextStatus==="run_spawned"&&requireNonEmptyString(request.runId);let path8=epicDispatchTransitionApiPath(request.dispatchKey,request.nextStatus),url=buildConductorJiraUrl(access.baseUrl,path8),body=request.nextStatus==="run_spawned"?JSON.stringify({repo_name:access.repoName,run_id:request.runId}):JSON.stringify({repo_name:access.repoName});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseShadowMergeReconcileResult(parsed){let obj=parsed??{};return{applies:obj.applies===!0,scheduled:obj.scheduled===!0,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:"unknown",shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,requiredCommitSha:typeof obj.required_commit_sha=="string"?obj.required_commit_sha:null,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null}}function parseShadowDispatchFreshnessResult(parsed){let obj=parsed??{},rawVerdict=typeof obj.verdict=="string"?obj.verdict:"",verdict=SHADOW_FRESHNESS_VERDICTS.has(rawVerdict)?rawVerdict:"stale";return{verdict,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:verdict,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null,indexedCommitSha:typeof obj.indexed_commit_sha=="string"?obj.indexed_commit_sha:null,shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,lastError:typeof obj.last_error=="string"?obj.last_error:null,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);let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseValidateEpicPlanResult(parsed)}function parseValidateEpicPlanResult(parsed){if(!parsed||typeof parsed!="object"||Array.isArray(parsed))throw new ConductorBridgeApiError("server");let p=parsed,planHash=p.plan_hash,serializationEnabled=p.serialization_enabled,insertedEdges=p.inserted_edges;if(p.valid!==!0||typeof planHash!="string"||planHash.trim()===""||typeof serializationEnabled!="boolean"||typeof insertedEdges!="number"||!Number.isSafeInteger(insertedEdges)||insertedEdges<0)throw new ConductorBridgeApiError("server");return{planHash,serializationEnabled,insertedEdges,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 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`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob,plan_hash:request.planHash});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateApprovedPlanNodeTicketSpec(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.expectedPlanHash),requireNonEmptyString(request.ticketSpec);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan/nodes/${encodeURIComponent(request.ticketKey)}/ticket-spec`),body=JSON.stringify({repo_name:access.repoName,expected_plan_hash:request.expectedPlanHash,ticket_spec:request.ticketSpec});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseApproveEpicPlanSuccess(parsed){let record=parsed??{},result={ok:!0,plan_hash:record.plan_hash},prov=record.feature_branch_provisioning;if(prov&&typeof prov=="object"&&!Array.isArray(prov)){let p=prov;(p.status==="created"||p.status==="already_exists")&&typeof p.feature_branch=="string"&&typeof p.source_branch=="string"&&typeof p.source_sha=="string"&&typeof p.remote_head_sha=="string"&&(result.featureBranchProvisioning={status:p.status,feature_branch:p.feature_branch,source_branch:p.source_branch,source_sha:p.source_sha,remote_head_sha:p.remote_head_sha})}return result}async function approveEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/approve-plan`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion});try{let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseApproveEpicPlanSuccess(parsed)}catch(error){if(error instanceof ConductorBridgeApiError&&error.status===409){let preview=error.bodyPreview??"";return/multiple active runs/i.test(preview)?{ok:!1,kind:"conflict",reason:"multiple_active_runs"}:{ok:!1,kind:"conflict",reason:"superseded"}}throw error}}async function getEpicPlan(access,epicKey,planVersion,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/plan`,{repo_name:access.repoName,plan_version:String(planVersion)});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchParseStatus(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-status",{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function triggerRepositoryParse(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-repository"),body=JSON.stringify({repo_name:access.repoName});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function deletePullRequestBranch(access,prNumber,expectedHeadSha,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(prNumber);if(pr===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/branch?repo_name=${encodeURIComponent(access.repoName)}&expected_head_sha=${encodeURIComponent(expectedHeadSha)}`),controller=new AbortController,timer=setTimeout(()=>controller.abort(),CONDUCTOR_FETCH_TIMEOUT_MS);try{let resp;try{resp=await fetchImpl(url,{method:"DELETE",headers:{"X-API-Key":access.apiKey},body:"",signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(resp.status===404)return{deleted:!1,branch:null,reason:"not_found"};if(!resp.ok)throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status):resp.status>=500?new ConductorBridgeApiError("server",resp.status):new ConductorBridgeApiError("http",resp.status);try{return await resp.json()}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function transitionJiraStatus(access,ticketNumber,targetStatus="auto",fetchImpl=globalThis.fetch){if(!ticketNumber)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorJiraUrl(access.baseUrl,`/tickets/${encodeURIComponent(ticketNumber)}/jira-status`),body=JSON.stringify({repo_name:access.repoName,target_status:targetStatus});try{return await fetchConductorJsonPutWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl),{status:"transitioned"}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===400)return{status:"skipped"};throw err}}function readinessShapeError(){return new ConductorBridgeApiError("invalid-input",void 0,{errorCode:"READINESS_SHAPE_INVALID"})}function requireObject(value){if(typeof value!="object"||value===null||Array.isArray(value))throw readinessShapeError();return value}function requireBool(o,key){let v=o[key];if(typeof v!="boolean")throw readinessShapeError();return v}function requireInt(o,key){let v=o[key];if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableInt(o,key){let v=o[key];if(v==null)return null;if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableString(o,key){let v=o[key];if(v==null)return null;if(typeof v!="string")throw readinessShapeError();return v}function requireNullableBool(o,key){let v=o[key];if(v==null)return null;if(typeof v!="boolean")throw readinessShapeError();return v}function parseReviewPolicyAlignment(o){let raw=o.review_policy_alignment;if(raw==null)return null;let a=requireObject(raw),explanation=a.explanation;if(typeof explanation!="string")throw readinessShapeError();return{status:requireEnum(a,"status",CONDUCTOR_REVIEW_ALIGNMENT_STATUSES),repo_review_signal:requireNullableString(a,"repo_review_signal"),done_gate_review_signal:requireNullableString(a,"done_gate_review_signal"),explanation}}function requireEnum(o,key,allowed){let v=o[key];if(typeof v!="string"||!allowed.has(v))throw readinessShapeError();return v}function parseConductorReadinessResponse(body){let root=requireObject(body),repoName=root.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let sup=requireObject(root.supervisor),gh=requireObject(root.github),rec=requireObject(root.reconciler),exec=requireObject(root.executor),thr=requireObject(root.thresholds);return{repo_name:repoName,supervisor:{setup_present:requireBool(sup,"setup_present"),setup_source:requireEnum(sup,"setup_source",READINESS_SOURCES),setup_created_at:requireNullableString(sup,"setup_created_at"),setup_updated_at:requireNullableString(sup,"setup_updated_at"),config_present:requireBool(sup,"config_present"),config_source:requireEnum(sup,"config_source",READINESS_SOURCES),config_created_at:requireNullableString(sup,"config_created_at"),config_updated_at:requireNullableString(sup,"config_updated_at"),required_checks_count:requireInt(sup,"required_checks_count"),required_checks_empty:requireBool(sup,"required_checks_empty"),auto_merge_enabled:requireBool(sup,"auto_merge_enabled"),merge_approval_required_set:requireBool(sup,"merge_approval_required_set"),review_policy_alignment:parseReviewPolicyAlignment(sup),review_policy_present:sup.review_policy_present===!0},github:{credentials_readable:requireBool(gh,"credentials_readable"),owner_resolved:requireBool(gh,"owner_resolved"),repo_id_resolved:requireBool(gh,"repo_id_resolved"),installation_id_resolved:requireBool(gh,"installation_id_resolved"),credentials_complete:requireBool(gh,"credentials_complete"),actions_probe_succeeded:requireBool(gh,"actions_probe_succeeded"),actions_permission_present:requireBool(gh,"actions_permission_present"),actions_permission_level:requireEnum(gh,"actions_permission_level",ACTIONS_LEVELS),actions_write:requireBool(gh,"actions_write")},reconciler:{liveness_readable:requireBool(rec,"liveness_readable"),last_tick_at:requireNullableString(rec,"last_tick_at"),last_tick_age_seconds:requireNullableInt(rec,"last_tick_age_seconds"),stale:requireBool(rec,"stale"),active_run_count:requireInt(rec,"active_run_count"),expired_lease_count:requireInt(rec,"expired_lease_count")},executor:{liveness_readable:requireBool(exec,"liveness_readable"),last_seen_at:requireNullableString(exec,"last_seen_at"),last_seen_age_seconds:requireNullableInt(exec,"last_seen_age_seconds"),ready:requireNullableBool(exec,"ready")},thresholds:{reconciler_stale_after_seconds:requireInt(thr,"reconciler_stale_after_seconds"),executor_stale_after_seconds:requireInt(thr,"executor_stale_after_seconds")}}}async function fetchConductorReadiness(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/conductor-readiness`,{repo_name:access.repoName}),body=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorReadinessResponse(body)}function parseConductorSupervisorBootstrapResponse(body){let o=requireObject(body),repoName=o.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let names=o.audited_field_names;if(!Array.isArray(names)||names.some(n=>typeof n!="string"))throw readinessShapeError();return{repo_name:repoName,setup_written:requireBool(o,"setup_written"),config_written:requireBool(o,"config_written"),setup_source:requireEnum(o,"setup_source",READINESS_SOURCES),config_source:requireEnum(o,"config_source",READINESS_SOURCES),setup_created_at:requireNullableString(o,"setup_created_at"),setup_updated_at:requireNullableString(o,"setup_updated_at"),config_created_at:requireNullableString(o,"config_created_at"),config_updated_at:requireNullableString(o,"config_updated_at"),required_checks_count:requireInt(o,"required_checks_count"),audited_field_names:names}}async function bootstrapConductorSupervisorDefaults(access,request,fetchImpl){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/supervisor-bootstrap`,{repo_name:access.repoName}),body=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(request),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorSupervisorBootstrapResponse(body)}var CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_BRIDGE_API_ERROR_KINDS,CONDUCTOR_ERROR_PREVIEW_MAX,CONDUCTOR_VALIDATION_LOC_MAX_PARTS,ConductorBridgeApiError,EPIC_TICKET_STATUS_VALUES,EPIC_DISPATCH_TRANSITION_STATUSES,EPIC_RUNS_API_PREFIX,SHADOW_FRESHNESS_VERDICTS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,READINESS_SOURCES,ACTIONS_LEVELS,init_bridge_api_client=__esm({"src/conductor/bridge-api-client.ts"(){"use strict";init_credential_store();init_start_tickets_repo();init_git_ci_types();init_errors();CONDUCTOR_DEFAULT_BASE_URL="https://bridgegpt-api.com",CONDUCTOR_FETCH_TIMEOUT_MS=3e4;CONDUCTOR_BRIDGE_API_ERROR_KINDS=["invalid-input","network","timeout","unauthorized","server","http"],CONDUCTOR_ERROR_PREVIEW_MAX=200;CONDUCTOR_VALIDATION_LOC_MAX_PARTS=8;ConductorBridgeApiError=class extends Error{kind;status;errorCode;bodyPreview;constructor(kindOrMessage,status,diagnostics){let isKnownKind=CONDUCTOR_BRIDGE_API_ERROR_KINDS.includes(kindOrMessage),errorCode=diagnostics?.errorCode,bodyPreview=diagnostics?.bodyPreview;if(isKnownKind){let parts=[`Conductor Bridge API request failed (${kindOrMessage}${typeof status=="number"?`, status ${status}`:""})`];errorCode&&parts.push(`code=${errorCode}`),bodyPreview&&parts.push(bodyPreview),super(parts.join(": "))}else super(kindOrMessage);this.name="ConductorBridgeApiError",this.kind=isKnownKind?kindOrMessage:"http",typeof status=="number"&&(this.status=status),errorCode&&(this.errorCode=errorCode),bodyPreview&&(this.bodyPreview=bodyPreview)}};EPIC_TICKET_STATUS_VALUES=["planned","ready","dispatched","running","blocked","abandoned","done","ready_for_review","reviewing","parse_pending"];EPIC_DISPATCH_TRANSITION_STATUSES=["run_spawned","terminal"];EPIC_RUNS_API_PREFIX="/epic-runs";SHADOW_FRESHNESS_VERDICTS=new Set(["not_applicable","covered","stale","failed"]);CONDUCTOR_REVIEW_ALIGNMENT_STATUSES=new Set(["aligned","divergent","not_configured","invalid"]),READINESS_SOURCES=new Set(["epic","project_default","none"]),ACTIONS_LEVELS=new Set(["write","read","none","unknown"])}});import{createHash as createHash4}from"node:crypto";function normalizeDimension(value){return(value??"").trim().toLowerCase()}function makeSupervisorIdempotencyKey(meta){return[normalizeDimension(meta.run_id),normalizeDimension(meta.worker_id)||"(run)",normalizeDimension(meta.reason),normalizeDimension(meta.kind),normalizeDimension(meta.cooldown_window)].join("|")}function makeSupervisorAssessmentEventId(idempotencyKey){let h=createHash4("sha256").update(`supervisor.assessment:${idempotencyKey}`).digest("hex");return`${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20,32)}`}function isDuplicateConstraintError3(error){if(!error||typeof error!="object")return!1;let code=error.code;if(typeof code=="string"&&code.startsWith("SQLITE_CONSTRAINT"))return!0;let message=error.message;if(typeof message=="string"){let lowered=message.toLowerCase();if(lowered.includes("unique constraint")||lowered.includes("constraint failed"))return!0}return!1}async function emitSupervisorAssessmentIfNew(input,deps={}){let emitEvent=deps.emitEvent??emitConductorEvent,idempotencyKey=makeSupervisorIdempotencyKey(input.idempotency),eventId=makeSupervisorAssessmentEventId(idempotencyKey),details={...input.details??{},idempotency_key:idempotencyKey,reason:input.idempotency.reason,kind:input.idempotency.kind,cooldown_window:input.idempotency.cooldown_window,classification:input.assessment.classification,confidence:input.assessment.confidence},event={id:eventId,source:"conductor-supervisor",type:"supervisor.assessment",run_id:input.run_id,worker_id:input.idempotency.worker_id??input.worker_id??null,producer:"conductor-supervisor",observed_via:"supervisor",data:{summary:`supervisor assessment: ${input.idempotency.reason}`,status:"escalated",reason:input.idempotency.reason,details}};try{let result=await emitEvent(event);return{emitted:!0,event_id:eventId,event:result.event}}catch(error){if(isDuplicateConstraintError3(error))return{emitted:!1,reason:"duplicate"};throw error}}var init_supervisor_ledger=__esm({"src/conductor/supervisor-ledger.ts"(){"use strict";init_store()}});function buildSupervisorEscalationWorkerMessage(candidate,assessment,state){let details={reason:candidate.reason,state:candidate.state,liveness:candidate.liveness,elapsed_ms:candidate.elapsed_ms,assessment_source:"deterministic"};return{run_id:state.run_id,worker_id:candidate.worker_id,type:`supervisor.${candidate.reason}`,cause_seq:state.last_seq,payload:{summary:`supervisor escalation: ${candidate.reason}`,status:"escalated",details},source:"conductor-supervisor",producer:"worker-message-relay"}}async function sendSupervisorEscalationWorkerMessageIfNew(candidate,assessment,state,deps={}){let sendMessage=deps.sendMessage??sendWorkerMessage,input=buildSupervisorEscalationWorkerMessage(candidate,assessment,state);return sendMessage(input)}var init_supervisor_message_relay=__esm({"src/conductor/supervisor-message-relay.ts"(){"use strict";init_store()}});function isTerminalState(state){return TERMINAL_STATES.has(state)}function isoToMs(value){if(typeof value!="string"||value.length===0)return null;let ms=Date.parse(value);return Number.isFinite(ms)?ms:null}function msToIso(now){return new Date(now).toISOString()}function createEmptySupervisorRunState(runId,config,now){let startedIso=msToIso(now);return{run_id:runId,status:"unknown",last_seq:0,last_event_time:null,workers:{},gates:{},latest_assessment:null,escalations:[],started_at:startedIso,updated_at:startedIso,global_deadline_at:msToIso(now+config.global_timeout_ms),roster_discovered:!1}}function isValidSupervisorSummary(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)&&value.kind===SUPERVISOR_SUMMARY_KIND}function hydrateSupervisorRunStateFromSnapshot(snapshot,runId,config,now){let empty=createEmptySupervisorRunState(runId,config,now),summary=snapshot?.projection?.summary;return isValidSupervisorSummary(summary)?{...empty,status:typeof summary.status=="string"?summary.status:empty.status,last_seq:typeof summary.last_seq=="number"&&summary.last_seq>=0?summary.last_seq:empty.last_seq,last_event_time:typeof summary.last_event_time=="string"?summary.last_event_time:null,workers:isPlainRecord(summary.workers)?summary.workers:{},gates:isPlainRecord(summary.gates)?summary.gates:{},latest_assessment:summary.latest_assessment&&typeof summary.latest_assessment=="object"?summary.latest_assessment:null,escalations:Array.isArray(summary.escalations)?summary.escalations:[],started_at:typeof summary.started_at=="string"?summary.started_at:empty.started_at,global_deadline_at:typeof summary.global_deadline_at=="string"?summary.global_deadline_at:empty.global_deadline_at,roster_discovered:summary.roster_discovered===!0,run_id:runId}:empty}function isPlainRecord(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)}function ensureWorkerState(state,workerId,options={}){let existing=state.workers[workerId];if(existing)return options.ticketKey&&!existing.ticket_key&&(existing.ticket_key=options.ticketKey),existing;let created={worker_id:workerId,ticket_key:options.ticketKey??null,state:options.fromRoster?"not_started":"unknown",liveness:"unknown",first_seen_seq:options.seq??null,last_event_seq:options.seq??null,last_event_time:null,last_progress_time:null,last_heartbeat_time:null,blocked_reason:null,terminal_reason:null,observed_event_types:[]};return state.workers[workerId]=created,created}function noteObservedType(worker,eventType){worker.observed_event_types.includes(eventType)||worker.observed_event_types.push(eventType)}function eventDetails(event){let details=event.data?.details;return isPlainRecord(details)?details:{}}function extractRoster(event){let candidates=[eventDetails(event).workers,event.data?.workers,isPlainRecord(event.data?.raw)?event.data.raw.workers:void 0];for(let candidate of candidates)if(Array.isArray(candidate)){let roster=[];for(let entry of candidate){if(!isPlainRecord(entry))continue;let workerId=entry.worker_id;if(typeof workerId!="string"||workerId.length===0)continue;let ticketKey=entry.ticket_key;roster.push({worker_id:workerId,ticket_key:typeof ticketKey=="string"?ticketKey:null})}if(roster.length>0)return roster}return[]}function eventStatus(event){let status=event.data?.status;return typeof status=="string"?status.trim().toLowerCase():""}function eventReason(event){let reason=event.data?.reason??eventDetails(event).reason;return typeof reason=="string"?reason.trim().toLowerCase():""}function applyConductorEventToSupervisorState(state,event,now){if(event.run_id!==state.run_id)return state;let eventType=event.type,eventTimeMs=isoToMs(event.time)??now,eventTimeIso=event.time??msToIso(now);if(typeof event.seq=="number"&&event.seq>state.last_seq&&(state.last_seq=event.seq),state.last_event_time=eventTimeIso,state.status==="unknown"&&(state.status="active"),eventType==="run.started"){let roster=extractRoster(event);roster.length>0&&(state.roster_discovered=!0);for(let member of roster){let worker2=ensureWorkerState(state,member.worker_id,{fromRoster:!0,ticketKey:member.ticket_key,seq:event.seq});noteObservedType(worker2,eventType),worker2.last_event_seq=event.seq??worker2.last_event_seq,worker2.last_event_time=eventTimeIso}return state.updated_at=msToIso(now),state}if(eventType==="supervisor.assessment"||eventType==="message.sent")return state.updated_at=msToIso(now),state;let workerId=event.worker_id;if(typeof workerId!="string"||workerId.length===0)return applyRunLevelEvent(state,event,eventType),state.updated_at=msToIso(now),state;let worker=ensureWorkerState(state,workerId,{seq:event.seq});switch(noteObservedType(worker,eventType),worker.last_event_seq=event.seq??worker.last_event_seq,worker.last_event_time=eventTimeIso,eventType){case"run.heartbeat":{worker.last_heartbeat_time=eventTimeIso,!isTerminalState(worker.state)&&worker.state!=="blocked"&&(worker.state==="not_started"||worker.state==="unknown")&&(worker.state="active");break}case"agent.notification":{let status=eventStatus(event),reason=eventReason(event);BLOCKED_STATUS_TOKENS.has(status)||BLOCKED_STATUS_TOKENS.has(reason)?isTerminalState(worker.state)||(worker.state="blocked",worker.blocked_reason=status||reason||"blocked"):!isTerminalState(worker.state)&&worker.state==="not_started"&&(worker.state="active");break}case"tool.intent":case"worktree.changed":case"git.commit_created":{PROGRESS_EVENT_TYPES.has(eventType)&&(worker.last_progress_time=eventTimeIso,isTerminalState(worker.state)||((worker.state==="not_started"||worker.state==="unknown"||worker.state==="stalled"||worker.state==="blocked")&&(worker.state="active"),worker.blocked_reason=null));break}case"gate.met":{isTerminalState(worker.state)||(worker.state="candidate_done");break}case"ci.passed":{isTerminalState(worker.state)||(worker.state="verifying"),worker.last_progress_time=eventTimeIso;break}case"ci.failed":{let reason=eventReason(event);eventStatus(event)==="terminal"||reason==="terminal"||reason==="give_up"?(worker.state="failed",worker.terminal_reason=reason||"ci_failed"):isTerminalState(worker.state)||(worker.last_progress_time=eventTimeIso);break}case"run.stopped":{let status=eventStatus(event),reason=eventReason(event);FAILED_STATUS_TOKENS.has(status)||FAILED_STATUS_TOKENS.has(reason)?(worker.state="failed",worker.terminal_reason=reason||status||"failed"):(worker.state="complete",worker.terminal_reason=reason||status||"complete");break}case"message.delivered":case"message.acked":{!isTerminalState(worker.state)&&(worker.state==="not_started"||worker.state==="unknown")&&(worker.state="active");break}case"merge.succeeded":{worker.state="complete",worker.terminal_reason=worker.terminal_reason||"merge_succeeded";break}case"merge.failed":break;case"merge.dry_run":break;case"merge.pending_approval":break;default:break}return state.updated_at=msToIso(now),state}function applyRunLevelEvent(state,event,eventType){switch(eventType){case"gate.met":state.gates.gate_met=!0;break;case"ci.passed":state.gates.ci="passed";break;case"ci.failed":state.gates.ci="failed";break;case"git.pr_opened":state.gates.pr_opened=!0;break;case"merge.succeeded":case"merge.failed":case"merge.dry_run":case"merge.pending_approval":state.gates.merge=eventType.slice(6);break;default:break}}function classifyWorkerLiveness(worker,config,now){if(isTerminalState(worker.state))return"alive";let lastSignalMs=mostRecentSignalMs(worker);if(lastSignalMs===null)return"unknown";let elapsed=now-lastSignalMs;return elapsed>=config.liveness.dead_after_ms?"dead":elapsed>=config.liveness.stalled_after_ms?"stalled":elapsed>=config.liveness.quiet_after_ms?"quiet":"alive"}function mostRecentSignalMs(worker){let candidates=[isoToMs(worker.last_heartbeat_time),isoToMs(worker.last_event_time),isoToMs(worker.last_progress_time)].filter(v=>v!==null);return candidates.length===0?null:Math.max(...candidates)}function stateAnchorMs(worker){return worker.state==="active"||worker.state==="verifying"?mostRecentSignalMs(worker):isoToMs(worker.last_event_time)??isoToMs(worker.last_heartbeat_time)??isoToMs(worker.last_progress_time)}function applySupervisorHousekeeping(state,config,now){for(let worker of Object.values(state.workers)){if(worker.liveness=classifyWorkerLiveness(worker,config,now),isTerminalState(worker.state)||worker.state==="stalled")continue;let threshold=config.stall_thresholds_ms[worker.state],anchor=stateAnchorMs(worker);anchor!==null&&now-anchor>=threshold&&(worker.state="stalled")}return state.updated_at=msToIso(now),state}function isSupervisorRunTerminal(state){let workers=Object.values(state.workers);return workers.length===0||!state.roster_discovered?!1:workers.every(w=>isTerminalState(w.state))}function hasSupervisorGlobalTimeoutElapsed(state,now){let deadlineMs=isoToMs(state.global_deadline_at);return deadlineMs===null?!1:now>=deadlineMs}function compactWorker(worker){return{worker_id:worker.worker_id,ticket_key:worker.ticket_key,state:worker.state,liveness:worker.liveness,last_event_seq:worker.last_event_seq,last_event_time:worker.last_event_time,last_progress_time:worker.last_progress_time,last_heartbeat_time:worker.last_heartbeat_time,blocked_reason:worker.blocked_reason,terminal_reason:worker.terminal_reason}}function toSupervisorProjectionInput(state){let summary={kind:SUPERVISOR_SUMMARY_KIND,run_id:state.run_id,status:state.status,last_seq:state.last_seq,last_event_time:state.last_event_time,workers:state.workers,gates:state.gates,latest_assessment:state.latest_assessment,escalations:state.escalations,started_at:state.started_at,updated_at:state.updated_at,global_deadline_at:state.global_deadline_at,roster_discovered:state.roster_discovered};return{run_id:state.run_id,status:state.status,last_seq:state.last_seq,last_event_time:state.last_event_time,active_workers:Object.values(state.workers).map(compactWorker),gates:state.gates,assessment:state.latest_assessment,summary}}var SUPERVISOR_SUMMARY_KIND,TERMINAL_STATES,PROGRESS_EVENT_TYPES,BLOCKED_STATUS_TOKENS,FAILED_STATUS_TOKENS,init_supervisor_state=__esm({"src/conductor/supervisor-state.ts"(){"use strict";SUPERVISOR_SUMMARY_KIND="supervisor_projection_summary",TERMINAL_STATES=new Set(["complete","failed"]);PROGRESS_EVENT_TYPES=new Set(["tool.intent","worktree.changed","git.commit_created"]),BLOCKED_STATUS_TOKENS=new Set(["blocked","waiting_for_input","needs_input"]),FAILED_STATUS_TOKENS=new Set(["failed","error","errored","aborted","cancelled","canceled"])}});function elapsedSinceSignal(worker,now){let candidates=[worker.last_event_time,worker.last_progress_time,worker.last_heartbeat_time].map(iso=>iso?Date.parse(iso):NaN).filter(v=>Number.isFinite(v));return candidates.length===0?0:Math.max(0,now-Math.max(...candidates))}function findSupervisorEscalationCandidates(state,config,now){let candidates=[];for(let worker of Object.values(state.workers)){if(worker.state==="complete"||worker.state==="failed")continue;let elapsed=elapsedSinceSignal(worker,now),baseContext={worker_id:worker.worker_id,ticket_key:worker.ticket_key,state:worker.state,liveness:worker.liveness};if(worker.liveness==="dead"){candidates.push({reason:"worker_dead",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});continue}switch(worker.state){case"not_started":worker.liveness!=="alive"&&candidates.push({reason:"worker_not_started",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"blocked":candidates.push({reason:"worker_blocked",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:{...baseContext,blocked_reason:worker.blocked_reason}});break;case"stalled":candidates.push({reason:"worker_stalled",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"candidate_done":worker.liveness!=="alive"&&candidates.push({reason:"candidate_done_stuck",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"verifying":worker.liveness==="stalled"&&candidates.push({reason:"verification_stalled",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;default:break}}let deadlineMs=state.global_deadline_at?Date.parse(state.global_deadline_at):NaN;return Number.isFinite(deadlineMs)&&now>=deadlineMs&&candidates.push({reason:"global_timeout",kind:ESCALATION_KIND,worker_id:null,state:null,liveness:null,elapsed_ms:Math.max(0,now-deadlineMs),context:{run_id:state.run_id,deadline_at:state.global_deadline_at,worker_count:Object.keys(state.workers).length}}),candidates}function cooldownWindowFor(now,cooldownMs){let width=cooldownMs>0?cooldownMs:1;return String(Math.floor(now/width))}function shouldEmitEscalation(state,candidate,config,now){let cooldownWindow=cooldownWindowFor(now,config.escalation_cooldown_ms);return{emit:!state.escalations.some(record=>record.reason===candidate.reason&&(record.worker_id??null)===(candidate.worker_id??null)&&record.cooldown_window===cooldownWindow&&(record.outcome==="emitted"||record.outcome==="duplicate")),cooldown_window:cooldownWindow}}function recordEscalationResult(state,candidate,cooldownWindow,idempotencyKey,outcome,now){let record={idempotency_key:idempotencyKey,worker_id:candidate.worker_id??null,reason:candidate.reason,kind:candidate.kind,cooldown_window:cooldownWindow,outcome,recorded_at:new Date(now).toISOString()};return state.escalations.push(record),record}function formatElapsed(ms){let totalSeconds=Math.max(0,Math.floor(ms/1e3)),hours=Math.floor(totalSeconds/3600),minutes=Math.floor(totalSeconds%3600/60),seconds=totalSeconds%60;return hours>0?`${hours}h${minutes}m`:minutes>0?`${minutes}m`:`${seconds}s`}function formatEscalationForTerminal(runId,candidate){let worker=candidate.worker_id?` worker=${candidate.worker_id}`:"",stateBit=candidate.state?` state=${candidate.state}`:"",liveBit=candidate.liveness?` liveness=${candidate.liveness}`:"",elapsed=` elapsed=${formatElapsed(candidate.elapsed_ms)}`;return`[supervisor] run=${runId}${worker} reason=${candidate.reason}${stateBit}${liveBit}${elapsed}`}var ESCALATION_KIND,init_supervisor_escalation=__esm({"src/conductor/supervisor-escalation.ts"(){"use strict";ESCALATION_KIND="escalation"}});function buildGateIdentity(gateName,configHash){let name=gateName.trim(),hash=typeof configHash=="string"?configHash.trim():"";return hash?`${name}@${hash.toLowerCase()}`:name}function makeMergeActionKey(repo,prNumber,headSha,gateIdentity){let r=normalizeRepoName(repo),pr=normalizePrNumber(prNumber),sha=normalizeSha(headSha),gate=(gateIdentity??"").trim();if(r===null||pr===null||sha===null||gate.length===0)throw new Error("invalid merge action key component");return`merge:${r}:${pr}:${sha}:${gate}`}var init_merge_identity=__esm({"src/conductor/merge-identity.ts"(){"use strict";init_git_ci_types()}});function isPlainObject2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function normalizeEventHeadSha(value){if(typeof value!="string")return null;let trimmed=value.trim();return/^[0-9a-f]{7,40}$/i.test(trimmed)?trimmed.toLowerCase():null}function getRawEventDetails(event){let details=event.data?.details;return isPlainObject2(details)?details:null}function parseHeadObservation(event){let details=getRawEventDetails(event);return{head_sha:details?normalizeEventHeadSha(details.head_sha):null}}function parseMergeLifecycle(event){let details=getRawEventDetails(event);return{action_key:details&&typeof details.action_key=="string"&&details.action_key.trim().length>0?details.action_key.trim():null}}function parseGateMet(event){let details=getRawEventDetails(event);if(!details)return{head_sha:null,repo:null,pr_number:null,gate_name:null,config_hash:null,required_checks:[]};let gateName=typeof details.gate_name=="string"&&details.gate_name.trim().length>0?details.gate_name.trim():null,configHash=typeof details.config_hash=="string"&&details.config_hash.trim().length>0?details.config_hash.trim():null,ciCheckStatus=isPlainObject2(details.ci_check_status)?details.ci_check_status:null,requiredChecks=(Array.isArray(details.required_checks)?details.required_checks:ciCheckStatus&&Array.isArray(ciCheckStatus.required_checks)?ciCheckStatus.required_checks:[]).filter(c=>typeof c=="string"&&c.trim().length>0);return{head_sha:normalizeSha(details.head_sha),repo:normalizeRepoName(details.repo),pr_number:normalizePrNumber(details.pr_number),gate_name:gateName,config_hash:configHash,required_checks:requiredChecks}}function parseSpecReview(event){let details=getRawEventDetails(event);return{head_sha:details?normalizeEventHeadSha(details.head_sha):null}}function parseEmpty(){return EMPTY_DETAILS}function getEventDetails(event,expectedType){if(event.type!==expectedType)return null;let parser=EVENT_PARSERS[expectedType];return parser(event)}function getMergeIdentity(event){if(event.type!=="gate.met")return null;let details=getEventDetails(event,"gate.met");if(details===null)return null;let{repo,pr_number:prNumber,head_sha:headSha,gate_name:gateName}=details;if(repo===null||prNumber===null||headSha===null||gateName===null)return null;let gateIdentity=buildGateIdentity(gateName,details.config_hash),actionKey=makeMergeActionKey(repo,prNumber,headSha,gateIdentity);return{repo,pr_number:prNumber,head_sha:headSha,gate_name:gateName,config_hash:details.config_hash,required_checks:details.required_checks,gate_identity:gateIdentity,action_key:actionKey,gate_event:{id:typeof event.id=="string"?event.id:void 0,seq:typeof event.seq=="number"?event.seq:void 0,time:typeof event.time=="string"?event.time:void 0}}}var EMPTY_DETAILS,EVENT_PARSERS,init_event_accessors=__esm({"src/conductor/event-accessors.ts"(){"use strict";init_git_ci_types();init_merge_identity();EMPTY_DETAILS=Object.freeze({});EVENT_PARSERS={"run.started":parseEmpty,"run.heartbeat":parseEmpty,"run.stopped":parseEmpty,"agent.notification":parseEmpty,"tool.intent":parseEmpty,"worktree.changed":parseEmpty,"git.commit_created":parseEmpty,"git.pr_opened":parseHeadObservation,"ci.passed":parseHeadObservation,"ci.failed":parseHeadObservation,"gate.met":parseGateMet,"supervisor.assessment":parseEmpty,"message.sent":parseEmpty,"message.delivered":parseEmpty,"message.acked":parseEmpty,"merge.dry_run":parseMergeLifecycle,"merge.attempted":parseMergeLifecycle,"merge.succeeded":parseHeadObservation,"merge.failed":parseMergeLifecycle,"merge.conflict":parseHeadObservation,"merge.pending_approval":parseMergeLifecycle,"review.passed":parseHeadObservation,"review.changes_requested":parseHeadObservation,"spec_review.passed":parseSpecReview,"spec_review.changes_requested":parseSpecReview,"parse.triggered":parseEmpty,"parse.succeeded":parseEmpty,"parse.failed":parseEmpty}}});import{createHash as createHash5}from"node:crypto";function extractMergeActionIdentityFromGateEvent(event){return getMergeIdentity(event)}function makeMergeEventId(eventType,actionKey){let h=createHash5("sha256").update(`${eventType}:${actionKey}`).digest("hex");return`${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20,32)}`}async function lookupMergeEventByActionKey(eventType,actionKey,deps){let db=await(deps.openDb??(()=>openReadonlyConductorDatabaseIfExists()))();if(!db)return!1;try{return db.prepare(`SELECT 1 FROM events
131
+ `),repoName,sawRepoName=!1,mcp=[],currentMcp=null;for(let i=0;i<lines.length;i++){let lineNo=i+1,line=lines[i].trim();if(line.length===0||line.startsWith("#"))continue;if(line==="[[mcp]]"){currentMcp={headerLine:lineNo},mcp.push(currentMcp);continue}if(line.startsWith("["))return{ok:!1,kind:"parse-error",error:`Unsupported table header on line ${lineNo}; only [[mcp]] is allowed`};let eq=line.indexOf("=");if(eq===-1)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; expected key = "value"`};let key=line.slice(0,eq).trim(),rawValue=line.slice(eq+1).trim();if(key.length===0)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; missing key`};if(currentMcp===null){if(key==="repo_name"){if(sawRepoName)return{ok:!1,kind:"parse-error",error:`Duplicate repo_name on line ${lineNo}`};sawRepoName=!0;let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};let validated=validateRepoName(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};repoName=validated.value;continue}return key==="target"?{ok:!1,kind:"parse-error",error:`target on line ${lineNo} must appear inside an [[mcp]] section`}:{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' on line ${lineNo}`}}if(key==="args"){if(currentMcp.args!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate args on line ${lineNo}`};let arr=parseStringArray(rawValue);if(arr===null)return{ok:!1,kind:"parse-error",error:`Expected a string array for 'args' on line ${lineNo}`};currentMcp.args=arr;continue}if(key==="target"||key==="command"||key==="secret_bundle"){let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};if(key==="target"){if(currentMcp.target!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate target on line ${lineNo}`};let validated=validateMcpTarget(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};currentMcp.target=validated.value;continue}if(key==="command"){if(currentMcp.command!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate command on line ${lineNo}`};currentMcp.command=stringValue;continue}if(currentMcp.secretBundle!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate secret_bundle on line ${lineNo}`};currentMcp.secretBundle=stringValue;continue}return{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' inside [[mcp]] on line ${lineNo}`}}if(!sawRepoName||repoName===void 0)return{ok:!1,kind:"validation-error",error:"Missing required repo_name"};let cleaned=[];for(let entry of mcp){if(entry.target===void 0)return{ok:!1,kind:"validation-error",error:`An [[mcp]] section on line ${entry.headerLine} is missing its target`};if(entry.target!=="bapi"){if(entry.command===void 0||entry.command.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty command`};if(entry.args===void 0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires an args array`};if(entry.secretBundle===void 0||entry.secretBundle.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty secret_bundle`}}let clean={target:entry.target};entry.command!==void 0&&(clean.command=entry.command),entry.args!==void 0&&(clean.args=entry.args),entry.secretBundle!==void 0&&(clean.secretBundle=entry.secretBundle),cleaned.push(clean)}return{ok:!0,manifest:{repoName,mcp:cleaned}}}function bridgeConfigPath(projectRoot){return path7.join(projectRoot,".bridge","config")}async function readBridgeConfig(projectRoot,deps){let filePath=bridgeConfigPath(projectRoot),raw;try{raw=await deps.readFile(filePath)}catch(err){return err&&typeof err=="object"&&err.code==="ENOENT"?{ok:!1,kind:"missing"}:{ok:!1,kind:"parse-error",error:"Unable to read .bridge/config"}}return parseBridgeConfigToml(raw)}var init_bridge_config=__esm({"src/bridge-config.ts"(){"use strict"}});async function resolveStartTicketsRepoName(deps){let fromEnv=deps.env.BAPI_REPO_NAME;if(typeof fromEnv=="string"&&fromEnv.trim().length>0)return fromEnv.trim();try{let result=await readBridgeConfig(deps.cwd,{readFile:deps.readFile});if(result.ok&&result.manifest.repoName)return result.manifest.repoName}catch{}return null}var init_start_tickets_repo=__esm({"src/start-tickets-repo.ts"(){"use strict";init_bridge_config()}});var bridge_api_client_exports={};__export(bridge_api_client_exports,{CONDUCTOR_DEFAULT_BASE_URL:()=>CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS:()=>CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES:()=>CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,ConductorBridgeApiError:()=>ConductorBridgeApiError,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,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"):[],path8=(parts[0]==="body"?parts.slice(1):parts).slice(0,CONDUCTOR_VALIDATION_LOC_MAX_PARTS).join(".");return path8?`${path8}: ${msg}`:msg}function extractSanitizedErrorDiagnostics(body){if(typeof body=="string"){let trimmed=body.trim();return trimmed?{bodyPreview:boundedErrorPreview(trimmed)}:{}}if(!body||typeof body!="object")return{};let record=body,detail=record.detail,errorCode,message;if(Array.isArray(detail))message=formatValidationDetailItem(detail[0]);else if(detail&&typeof detail=="object"){let d=detail;typeof d.error_code=="string"&&(errorCode=d.error_code),typeof d.message=="string"&&(message=d.message)}else typeof detail=="string"&&(message=detail);!errorCode&&typeof record.error_code=="string"&&(errorCode=record.error_code),!message&&typeof record.message=="string"&&(message=record.message);let diagnostics={};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(/\/+$/,""),path8=apiPath.startsWith("/")?apiPath:`/${apiPath}`;return new URL(`${trimmed}${path8}`).toString()}function conductorPostHeaders(access){return{"X-API-Key":access.apiKey,"Content-Type":"application/json"}}async function fetchConductorJsonWithMethodAndTimeout(method,url,headers,body,timeoutMs,fetchImpl){let{body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl);return parsed}async function fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl){let controller=new AbortController,timer=setTimeout(()=>controller.abort(),timeoutMs);try{let resp;try{resp=await fetchImpl(url,{method,headers,body,signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(!resp.ok){let diagnostics=await readSanitizedErrorDiagnostics(resp,headers);throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status,diagnostics):resp.status>=500?new ConductorBridgeApiError("server",resp.status,diagnostics):new ConductorBridgeApiError("http",resp.status,diagnostics)}try{return{status:resp.status,body:await resp.json()}}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function fetchConductorJsonPostWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("POST",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPatchWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PATCH",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPutWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PUT",url,headers,body,timeoutMs,fetchImpl)}async function mergePullRequestForGate(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number),sha=normalizeSha(request.expected_head_sha);if(pr===null||sha===null||!request.action_key||!request.repo_name)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/merge`),body=JSON.stringify({repo_name:request.repo_name,expected_head_sha:sha,gate:request.gate,action_key:request.action_key,...request.gate_event?{gate_event:request.gate_event}:{}});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function remediateEpicTicket(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number);if(pr===null||!request.epic_run_id||!request.ticket_key||!request.head_sha||!request.idempotency_key)throw new ConductorBridgeApiError("invalid-input");if(requireNonNegativeSafeInteger(request.expected_row_version),request.attempt_kind!=="nudge"&&request.attempt_kind!=="redispatch")throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/remediate`),body=JSON.stringify({repo_name:access.repoName,epic_run_id:request.epic_run_id,ticket_key:request.ticket_key,expected_row_version:request.expected_row_version,head_sha:request.head_sha,idempotency_key:request.idempotency_key,attempt_kind:request.attempt_kind,...request.reason?{reason:request.reason}:{}});try{return{ok:!0,conflict:!1,response:await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===409)return{ok:!0,conflict:!0};throw err}}function requireNonEmptyString(value){if(typeof value!="string"||value.trim().length===0)throw new ConductorBridgeApiError("invalid-input")}function requirePositiveSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<=0)throw new ConductorBridgeApiError("invalid-input")}function requireNonNegativeSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<0)throw new ConductorBridgeApiError("invalid-input")}function requireNoSlashPathSegment(value){if(value.includes("/"))throw new ConductorBridgeApiError("invalid-input")}function requireEpicTicketStatusValue(value){if(typeof value!="string"||!EPIC_TICKET_STATUS_VALUES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function requireEpicDispatchTransitionStatus(value){if(typeof value!="string"||!EPIC_DISPATCH_TRANSITION_STATUSES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function epicRunApiPath(epicKey){return`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}`}function epicDispatchTransitionApiPath(dispatchKey,nextStatus){return nextStatus==="run_spawned"?`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/run-spawned`:`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/terminal`}function buildEpicDispatchKey(epicKey,ticketKey,planVersion,attempt=0){requireNonEmptyString(epicKey),requireNonEmptyString(ticketKey),requireNonNegativeSafeInteger(planVersion),requireNonNegativeSafeInteger(attempt);let base=`dispatch:${epicKey}:${ticketKey}:${planVersion}`;return attempt>0?`${base}:r${attempt}`:base}function parseEpicSupervisionLeaseResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed,row=p.row;if(p.claimed===!0&&row&&typeof row=="object")return{ok:!0,kind:"acquired-or-renewed",row};if(p.claimed===!1&&p.reason==="lease_held"&&row&&typeof row=="object")return{ok:!1,kind:"held-by-other",reason:"lease_held",row};if(p.claimed===!1&&p.reason==="terminal"&&row&&typeof row=="object")return{ok:!1,kind:"terminal",reason:"terminal",row};throw new ConductorBridgeApiError("server")}async function claimEpicSupervisionLease(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.leaseOwner),requirePositiveSafeInteger(request.ttlSeconds);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/lease/claim`),body=JSON.stringify({repo_name:access.repoName,lease_owner:request.leaseOwner,ttl_seconds:request.ttlSeconds}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseEpicSupervisionLeaseResult(parsed)}async function fetchEpicRunState(access,epicKey,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/state`,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchActiveEpicRuns(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`,{repo_name:access.repoName,status:"active",limit:"20"}),parsed=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);if(parsed&&typeof parsed=="object"){let runs=parsed.runs;if(Array.isArray(runs))return runs}return[]}async function createEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`);return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function createEpicRunWithDisposition(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`),{status,body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout("POST",url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return{run:parsed,created:status===201}}async function replaceEpicRunPolicy(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicRunId)),body=JSON.stringify({repo_name:access.repoName,policy_json:request.policyJson});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateEpicRunStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicKey)),body=JSON.stringify({repo_name:access.repoName,status:request.status,...request.expectedStatus?{expected_status:request.expectedStatus}:{}});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}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 path8=epicDispatchTransitionApiPath(request.dispatchKey,request.nextStatus),url=buildConductorJiraUrl(access.baseUrl,path8),body=request.nextStatus==="run_spawned"?JSON.stringify({repo_name:access.repoName,run_id:request.runId}):JSON.stringify({repo_name:access.repoName});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseShadowMergeReconcileResult(parsed){let obj=parsed??{};return{applies:obj.applies===!0,scheduled:obj.scheduled===!0,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:"unknown",shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,requiredCommitSha:typeof obj.required_commit_sha=="string"?obj.required_commit_sha:null,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null}}function parseShadowDispatchFreshnessResult(parsed){let obj=parsed??{},rawVerdict=typeof obj.verdict=="string"?obj.verdict:"",verdict=SHADOW_FRESHNESS_VERDICTS.has(rawVerdict)?rawVerdict:"stale";return{verdict,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:verdict,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null,indexedCommitSha:typeof obj.indexed_commit_sha=="string"?obj.indexed_commit_sha:null,shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,lastError:typeof obj.last_error=="string"?obj.last_error:null,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);let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseValidateEpicPlanResult(parsed)}function parseValidateEpicPlanResult(parsed){if(!parsed||typeof parsed!="object"||Array.isArray(parsed))throw new ConductorBridgeApiError("server");let p=parsed,planHash=p.plan_hash,serializationEnabled=p.serialization_enabled,insertedEdges=p.inserted_edges;if(p.valid!==!0||typeof planHash!="string"||planHash.trim()===""||typeof serializationEnabled!="boolean"||typeof insertedEdges!="number"||!Number.isSafeInteger(insertedEdges)||insertedEdges<0)throw new ConductorBridgeApiError("server");return{planHash,serializationEnabled,insertedEdges,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 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`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob,plan_hash:request.planHash});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateApprovedPlanNodeTicketSpec(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.expectedPlanHash),requireNonEmptyString(request.ticketSpec);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan/nodes/${encodeURIComponent(request.ticketKey)}/ticket-spec`),body=JSON.stringify({repo_name:access.repoName,expected_plan_hash:request.expectedPlanHash,ticket_spec:request.ticketSpec});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseApproveEpicPlanSuccess(parsed){let record=parsed??{},result={ok:!0,plan_hash:record.plan_hash},prov=record.feature_branch_provisioning;if(prov&&typeof prov=="object"&&!Array.isArray(prov)){let p=prov;(p.status==="created"||p.status==="already_exists")&&typeof p.feature_branch=="string"&&typeof p.source_branch=="string"&&typeof p.source_sha=="string"&&typeof p.remote_head_sha=="string"&&(result.featureBranchProvisioning={status:p.status,feature_branch:p.feature_branch,source_branch:p.source_branch,source_sha:p.source_sha,remote_head_sha:p.remote_head_sha})}return result}async function approveEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/approve-plan`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion});try{let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseApproveEpicPlanSuccess(parsed)}catch(error){if(error instanceof ConductorBridgeApiError&&error.status===409){let preview=error.bodyPreview??"";return/multiple active runs/i.test(preview)?{ok:!1,kind:"conflict",reason:"multiple_active_runs"}:{ok:!1,kind:"conflict",reason:"superseded"}}throw error}}async function getEpicPlan(access,epicKey,planVersion,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/plan`,{repo_name:access.repoName,plan_version:String(planVersion)});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchParseStatus(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-status",{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function triggerRepositoryParse(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-repository"),body=JSON.stringify({repo_name:access.repoName});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function deletePullRequestBranch(access,prNumber,expectedHeadSha,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(prNumber);if(pr===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/branch?repo_name=${encodeURIComponent(access.repoName)}&expected_head_sha=${encodeURIComponent(expectedHeadSha)}`),controller=new AbortController,timer=setTimeout(()=>controller.abort(),CONDUCTOR_FETCH_TIMEOUT_MS);try{let resp;try{resp=await fetchImpl(url,{method:"DELETE",headers:{"X-API-Key":access.apiKey},body:"",signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(resp.status===404)return{deleted:!1,branch:null,reason:"not_found"};if(!resp.ok)throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status):resp.status>=500?new ConductorBridgeApiError("server",resp.status):new ConductorBridgeApiError("http",resp.status);try{return await resp.json()}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function transitionJiraStatus(access,ticketNumber,targetStatus="auto",fetchImpl=globalThis.fetch){if(!ticketNumber)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorJiraUrl(access.baseUrl,`/tickets/${encodeURIComponent(ticketNumber)}/jira-status`),body=JSON.stringify({repo_name:access.repoName,target_status:targetStatus});try{return await fetchConductorJsonPutWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl),{status:"transitioned"}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===400)return{status:"skipped"};throw err}}function readinessShapeError(){return new ConductorBridgeApiError("invalid-input",void 0,{errorCode:"READINESS_SHAPE_INVALID"})}function requireObject(value){if(typeof value!="object"||value===null||Array.isArray(value))throw readinessShapeError();return value}function requireBool(o,key){let v=o[key];if(typeof v!="boolean")throw readinessShapeError();return v}function requireInt(o,key){let v=o[key];if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableInt(o,key){let v=o[key];if(v==null)return null;if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableString(o,key){let v=o[key];if(v==null)return null;if(typeof v!="string")throw readinessShapeError();return v}function requireNullableBool(o,key){let v=o[key];if(v==null)return null;if(typeof v!="boolean")throw readinessShapeError();return v}function parseReviewPolicyAlignment(o){let raw=o.review_policy_alignment;if(raw==null)return null;let a=requireObject(raw),explanation=a.explanation;if(typeof explanation!="string")throw readinessShapeError();return{status:requireEnum(a,"status",CONDUCTOR_REVIEW_ALIGNMENT_STATUSES),repo_review_signal:requireNullableString(a,"repo_review_signal"),done_gate_review_signal:requireNullableString(a,"done_gate_review_signal"),explanation}}function requireEnum(o,key,allowed){let v=o[key];if(typeof v!="string"||!allowed.has(v))throw readinessShapeError();return v}function parseConductorReadinessResponse(body){let root=requireObject(body),repoName=root.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let sup=requireObject(root.supervisor),gh=requireObject(root.github),rec=requireObject(root.reconciler),exec=requireObject(root.executor),thr=requireObject(root.thresholds);return{repo_name:repoName,supervisor:{setup_present:requireBool(sup,"setup_present"),setup_source:requireEnum(sup,"setup_source",READINESS_SOURCES),setup_created_at:requireNullableString(sup,"setup_created_at"),setup_updated_at:requireNullableString(sup,"setup_updated_at"),config_present:requireBool(sup,"config_present"),config_source:requireEnum(sup,"config_source",READINESS_SOURCES),config_created_at:requireNullableString(sup,"config_created_at"),config_updated_at:requireNullableString(sup,"config_updated_at"),required_checks_count:requireInt(sup,"required_checks_count"),required_checks_empty:requireBool(sup,"required_checks_empty"),auto_merge_enabled:requireBool(sup,"auto_merge_enabled"),merge_approval_required_set:requireBool(sup,"merge_approval_required_set"),review_policy_alignment:parseReviewPolicyAlignment(sup),review_policy_present:sup.review_policy_present===!0},github:{credentials_readable:requireBool(gh,"credentials_readable"),owner_resolved:requireBool(gh,"owner_resolved"),repo_id_resolved:requireBool(gh,"repo_id_resolved"),installation_id_resolved:requireBool(gh,"installation_id_resolved"),credentials_complete:requireBool(gh,"credentials_complete"),actions_probe_succeeded:requireBool(gh,"actions_probe_succeeded"),actions_permission_present:requireBool(gh,"actions_permission_present"),actions_permission_level:requireEnum(gh,"actions_permission_level",ACTIONS_LEVELS),actions_write:requireBool(gh,"actions_write")},reconciler:{liveness_readable:requireBool(rec,"liveness_readable"),last_tick_at:requireNullableString(rec,"last_tick_at"),last_tick_age_seconds:requireNullableInt(rec,"last_tick_age_seconds"),stale:requireBool(rec,"stale"),active_run_count:requireInt(rec,"active_run_count"),expired_lease_count:requireInt(rec,"expired_lease_count")},executor:{liveness_readable:requireBool(exec,"liveness_readable"),last_seen_at:requireNullableString(exec,"last_seen_at"),last_seen_age_seconds:requireNullableInt(exec,"last_seen_age_seconds"),ready:requireNullableBool(exec,"ready")},thresholds:{reconciler_stale_after_seconds:requireInt(thr,"reconciler_stale_after_seconds"),executor_stale_after_seconds:requireInt(thr,"executor_stale_after_seconds")}}}async function fetchConductorReadiness(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/conductor-readiness`,{repo_name:access.repoName}),body=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorReadinessResponse(body)}function parseConductorSupervisorBootstrapResponse(body){let o=requireObject(body),repoName=o.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let names=o.audited_field_names;if(!Array.isArray(names)||names.some(n=>typeof n!="string"))throw readinessShapeError();return{repo_name:repoName,setup_written:requireBool(o,"setup_written"),config_written:requireBool(o,"config_written"),setup_source:requireEnum(o,"setup_source",READINESS_SOURCES),config_source:requireEnum(o,"config_source",READINESS_SOURCES),setup_created_at:requireNullableString(o,"setup_created_at"),setup_updated_at:requireNullableString(o,"setup_updated_at"),config_created_at:requireNullableString(o,"config_created_at"),config_updated_at:requireNullableString(o,"config_updated_at"),required_checks_count:requireInt(o,"required_checks_count"),audited_field_names:names}}async function bootstrapConductorSupervisorDefaults(access,request,fetchImpl){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/supervisor-bootstrap`,{repo_name:access.repoName}),body=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(request),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorSupervisorBootstrapResponse(body)}var CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_BRIDGE_API_ERROR_KINDS,CONDUCTOR_ERROR_PREVIEW_MAX,CONDUCTOR_VALIDATION_LOC_MAX_PARTS,ConductorBridgeApiError,EPIC_TICKET_STATUS_VALUES,EPIC_DISPATCH_TRANSITION_STATUSES,EPIC_RUNS_API_PREFIX,SHADOW_FRESHNESS_VERDICTS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,READINESS_SOURCES,ACTIONS_LEVELS,init_bridge_api_client=__esm({"src/conductor/bridge-api-client.ts"(){"use strict";init_credential_store();init_start_tickets_repo();init_git_ci_types();init_errors();CONDUCTOR_DEFAULT_BASE_URL="https://bridgegpt-api.com",CONDUCTOR_FETCH_TIMEOUT_MS=3e4;CONDUCTOR_BRIDGE_API_ERROR_KINDS=["invalid-input","network","timeout","unauthorized","server","http"],CONDUCTOR_ERROR_PREVIEW_MAX=200;CONDUCTOR_VALIDATION_LOC_MAX_PARTS=8;ConductorBridgeApiError=class extends Error{kind;status;errorCode;bodyPreview;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";SHADOW_FRESHNESS_VERDICTS=new Set(["not_applicable","covered","stale","failed"]);CONDUCTOR_REVIEW_ALIGNMENT_STATUSES=new Set(["aligned","divergent","not_configured","invalid"]),READINESS_SOURCES=new Set(["epic","project_default","none"]),ACTIONS_LEVELS=new Set(["write","read","none","unknown"])}});import{createHash as createHash4}from"node:crypto";function normalizeDimension(value){return(value??"").trim().toLowerCase()}function makeSupervisorIdempotencyKey(meta){return[normalizeDimension(meta.run_id),normalizeDimension(meta.worker_id)||"(run)",normalizeDimension(meta.reason),normalizeDimension(meta.kind),normalizeDimension(meta.cooldown_window)].join("|")}function makeSupervisorAssessmentEventId(idempotencyKey){let h=createHash4("sha256").update(`supervisor.assessment:${idempotencyKey}`).digest("hex");return`${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20,32)}`}function isDuplicateConstraintError3(error){if(!error||typeof error!="object")return!1;let code=error.code;if(typeof code=="string"&&code.startsWith("SQLITE_CONSTRAINT"))return!0;let message=error.message;if(typeof message=="string"){let lowered=message.toLowerCase();if(lowered.includes("unique constraint")||lowered.includes("constraint failed"))return!0}return!1}async function emitSupervisorAssessmentIfNew(input,deps={}){let emitEvent=deps.emitEvent??emitConductorEvent,idempotencyKey=makeSupervisorIdempotencyKey(input.idempotency),eventId=makeSupervisorAssessmentEventId(idempotencyKey),details={...input.details??{},idempotency_key:idempotencyKey,reason:input.idempotency.reason,kind:input.idempotency.kind,cooldown_window:input.idempotency.cooldown_window,classification:input.assessment.classification,confidence:input.assessment.confidence},event={id:eventId,source:"conductor-supervisor",type:"supervisor.assessment",run_id:input.run_id,worker_id:input.idempotency.worker_id??input.worker_id??null,producer:"conductor-supervisor",observed_via:"supervisor",data:{summary:`supervisor assessment: ${input.idempotency.reason}`,status:"escalated",reason:input.idempotency.reason,details}};try{let result=await emitEvent(event);return{emitted:!0,event_id:eventId,event:result.event}}catch(error){if(isDuplicateConstraintError3(error))return{emitted:!1,reason:"duplicate"};throw error}}var init_supervisor_ledger=__esm({"src/conductor/supervisor-ledger.ts"(){"use strict";init_store()}});function buildSupervisorEscalationWorkerMessage(candidate,assessment,state){let details={reason:candidate.reason,state:candidate.state,liveness:candidate.liveness,elapsed_ms:candidate.elapsed_ms,assessment_source:"deterministic"};return{run_id:state.run_id,worker_id:candidate.worker_id,type:`supervisor.${candidate.reason}`,cause_seq:state.last_seq,payload:{summary:`supervisor escalation: ${candidate.reason}`,status:"escalated",details},source:"conductor-supervisor",producer:"worker-message-relay"}}async function sendSupervisorEscalationWorkerMessageIfNew(candidate,assessment,state,deps={}){let sendMessage=deps.sendMessage??sendWorkerMessage,input=buildSupervisorEscalationWorkerMessage(candidate,assessment,state);return sendMessage(input)}var init_supervisor_message_relay=__esm({"src/conductor/supervisor-message-relay.ts"(){"use strict";init_store()}});function isTerminalState(state){return TERMINAL_STATES.has(state)}function isoToMs(value){if(typeof value!="string"||value.length===0)return null;let ms=Date.parse(value);return Number.isFinite(ms)?ms:null}function msToIso(now){return new Date(now).toISOString()}function createEmptySupervisorRunState(runId,config,now){let startedIso=msToIso(now);return{run_id:runId,status:"unknown",last_seq:0,last_event_time:null,workers:{},gates:{},latest_assessment:null,escalations:[],started_at:startedIso,updated_at:startedIso,global_deadline_at:msToIso(now+config.global_timeout_ms),roster_discovered:!1}}function isValidSupervisorSummary(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)&&value.kind===SUPERVISOR_SUMMARY_KIND}function hydrateSupervisorRunStateFromSnapshot(snapshot,runId,config,now){let empty=createEmptySupervisorRunState(runId,config,now),summary=snapshot?.projection?.summary;return isValidSupervisorSummary(summary)?{...empty,status:typeof summary.status=="string"?summary.status:empty.status,last_seq:typeof summary.last_seq=="number"&&summary.last_seq>=0?summary.last_seq:empty.last_seq,last_event_time:typeof summary.last_event_time=="string"?summary.last_event_time:null,workers:isPlainRecord(summary.workers)?summary.workers:{},gates:isPlainRecord(summary.gates)?summary.gates:{},latest_assessment:summary.latest_assessment&&typeof summary.latest_assessment=="object"?summary.latest_assessment:null,escalations:Array.isArray(summary.escalations)?summary.escalations:[],started_at:typeof summary.started_at=="string"?summary.started_at:empty.started_at,global_deadline_at:typeof summary.global_deadline_at=="string"?summary.global_deadline_at:empty.global_deadline_at,roster_discovered:summary.roster_discovered===!0,run_id:runId}:empty}function isPlainRecord(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)}function ensureWorkerState(state,workerId,options={}){let existing=state.workers[workerId];if(existing)return options.ticketKey&&!existing.ticket_key&&(existing.ticket_key=options.ticketKey),existing;let created={worker_id:workerId,ticket_key:options.ticketKey??null,state:options.fromRoster?"not_started":"unknown",liveness:"unknown",first_seen_seq:options.seq??null,last_event_seq:options.seq??null,last_event_time:null,last_progress_time:null,last_heartbeat_time:null,blocked_reason:null,terminal_reason:null,observed_event_types:[]};return state.workers[workerId]=created,created}function noteObservedType(worker,eventType){worker.observed_event_types.includes(eventType)||worker.observed_event_types.push(eventType)}function eventDetails(event){let details=event.data?.details;return isPlainRecord(details)?details:{}}function extractRoster(event){let candidates=[eventDetails(event).workers,event.data?.workers,isPlainRecord(event.data?.raw)?event.data.raw.workers:void 0];for(let candidate of candidates)if(Array.isArray(candidate)){let roster=[];for(let entry of candidate){if(!isPlainRecord(entry))continue;let workerId=entry.worker_id;if(typeof workerId!="string"||workerId.length===0)continue;let ticketKey=entry.ticket_key;roster.push({worker_id:workerId,ticket_key:typeof ticketKey=="string"?ticketKey:null})}if(roster.length>0)return roster}return[]}function eventStatus(event){let status=event.data?.status;return typeof status=="string"?status.trim().toLowerCase():""}function eventReason(event){let reason=event.data?.reason??eventDetails(event).reason;return typeof reason=="string"?reason.trim().toLowerCase():""}function applyConductorEventToSupervisorState(state,event,now){if(event.run_id!==state.run_id)return state;let eventType=event.type,eventTimeMs=isoToMs(event.time)??now,eventTimeIso=event.time??msToIso(now);if(typeof event.seq=="number"&&event.seq>state.last_seq&&(state.last_seq=event.seq),state.last_event_time=eventTimeIso,state.status==="unknown"&&(state.status="active"),eventType==="run.started"){let roster=extractRoster(event);roster.length>0&&(state.roster_discovered=!0);for(let member of roster){let worker2=ensureWorkerState(state,member.worker_id,{fromRoster:!0,ticketKey:member.ticket_key,seq:event.seq});noteObservedType(worker2,eventType),worker2.last_event_seq=event.seq??worker2.last_event_seq,worker2.last_event_time=eventTimeIso}return state.updated_at=msToIso(now),state}if(eventType==="supervisor.assessment"||eventType==="message.sent")return state.updated_at=msToIso(now),state;let workerId=event.worker_id;if(typeof workerId!="string"||workerId.length===0)return applyRunLevelEvent(state,event,eventType),state.updated_at=msToIso(now),state;let worker=ensureWorkerState(state,workerId,{seq:event.seq});switch(noteObservedType(worker,eventType),worker.last_event_seq=event.seq??worker.last_event_seq,worker.last_event_time=eventTimeIso,eventType){case"run.heartbeat":{worker.last_heartbeat_time=eventTimeIso,!isTerminalState(worker.state)&&worker.state!=="blocked"&&(worker.state==="not_started"||worker.state==="unknown")&&(worker.state="active");break}case"agent.notification":{let status=eventStatus(event),reason=eventReason(event);BLOCKED_STATUS_TOKENS.has(status)||BLOCKED_STATUS_TOKENS.has(reason)?isTerminalState(worker.state)||(worker.state="blocked",worker.blocked_reason=status||reason||"blocked"):!isTerminalState(worker.state)&&worker.state==="not_started"&&(worker.state="active");break}case"tool.intent":case"worktree.changed":case"git.commit_created":{PROGRESS_EVENT_TYPES.has(eventType)&&(worker.last_progress_time=eventTimeIso,isTerminalState(worker.state)||((worker.state==="not_started"||worker.state==="unknown"||worker.state==="stalled"||worker.state==="blocked")&&(worker.state="active"),worker.blocked_reason=null));break}case"gate.met":{isTerminalState(worker.state)||(worker.state="candidate_done");break}case"ci.passed":{isTerminalState(worker.state)||(worker.state="verifying"),worker.last_progress_time=eventTimeIso;break}case"ci.failed":{let reason=eventReason(event);eventStatus(event)==="terminal"||reason==="terminal"||reason==="give_up"?(worker.state="failed",worker.terminal_reason=reason||"ci_failed"):isTerminalState(worker.state)||(worker.last_progress_time=eventTimeIso);break}case"run.stopped":{let status=eventStatus(event),reason=eventReason(event);FAILED_STATUS_TOKENS.has(status)||FAILED_STATUS_TOKENS.has(reason)?(worker.state="failed",worker.terminal_reason=reason||status||"failed"):(worker.state="complete",worker.terminal_reason=reason||status||"complete");break}case"message.delivered":case"message.acked":{!isTerminalState(worker.state)&&(worker.state==="not_started"||worker.state==="unknown")&&(worker.state="active");break}case"merge.succeeded":{worker.state="complete",worker.terminal_reason=worker.terminal_reason||"merge_succeeded";break}case"merge.failed":break;case"merge.dry_run":break;case"merge.pending_approval":break;default:break}return state.updated_at=msToIso(now),state}function applyRunLevelEvent(state,event,eventType){switch(eventType){case"gate.met":state.gates.gate_met=!0;break;case"ci.passed":state.gates.ci="passed";break;case"ci.failed":state.gates.ci="failed";break;case"git.pr_opened":state.gates.pr_opened=!0;break;case"merge.succeeded":case"merge.failed":case"merge.dry_run":case"merge.pending_approval":state.gates.merge=eventType.slice(6);break;default:break}}function classifyWorkerLiveness(worker,config,now){if(isTerminalState(worker.state))return"alive";let lastSignalMs=mostRecentSignalMs(worker);if(lastSignalMs===null)return"unknown";let elapsed=now-lastSignalMs;return elapsed>=config.liveness.dead_after_ms?"dead":elapsed>=config.liveness.stalled_after_ms?"stalled":elapsed>=config.liveness.quiet_after_ms?"quiet":"alive"}function mostRecentSignalMs(worker){let candidates=[isoToMs(worker.last_heartbeat_time),isoToMs(worker.last_event_time),isoToMs(worker.last_progress_time)].filter(v=>v!==null);return candidates.length===0?null:Math.max(...candidates)}function stateAnchorMs(worker){return worker.state==="active"||worker.state==="verifying"?mostRecentSignalMs(worker):isoToMs(worker.last_event_time)??isoToMs(worker.last_heartbeat_time)??isoToMs(worker.last_progress_time)}function applySupervisorHousekeeping(state,config,now){for(let worker of Object.values(state.workers)){if(worker.liveness=classifyWorkerLiveness(worker,config,now),isTerminalState(worker.state)||worker.state==="stalled")continue;let threshold=config.stall_thresholds_ms[worker.state],anchor=stateAnchorMs(worker);anchor!==null&&now-anchor>=threshold&&(worker.state="stalled")}return state.updated_at=msToIso(now),state}function isSupervisorRunTerminal(state){let workers=Object.values(state.workers);return workers.length===0||!state.roster_discovered?!1:workers.every(w=>isTerminalState(w.state))}function hasSupervisorGlobalTimeoutElapsed(state,now){let deadlineMs=isoToMs(state.global_deadline_at);return deadlineMs===null?!1:now>=deadlineMs}function compactWorker(worker){return{worker_id:worker.worker_id,ticket_key:worker.ticket_key,state:worker.state,liveness:worker.liveness,last_event_seq:worker.last_event_seq,last_event_time:worker.last_event_time,last_progress_time:worker.last_progress_time,last_heartbeat_time:worker.last_heartbeat_time,blocked_reason:worker.blocked_reason,terminal_reason:worker.terminal_reason}}function toSupervisorProjectionInput(state){let summary={kind:SUPERVISOR_SUMMARY_KIND,run_id:state.run_id,status:state.status,last_seq:state.last_seq,last_event_time:state.last_event_time,workers:state.workers,gates:state.gates,latest_assessment:state.latest_assessment,escalations:state.escalations,started_at:state.started_at,updated_at:state.updated_at,global_deadline_at:state.global_deadline_at,roster_discovered:state.roster_discovered};return{run_id:state.run_id,status:state.status,last_seq:state.last_seq,last_event_time:state.last_event_time,active_workers:Object.values(state.workers).map(compactWorker),gates:state.gates,assessment:state.latest_assessment,summary}}var SUPERVISOR_SUMMARY_KIND,TERMINAL_STATES,PROGRESS_EVENT_TYPES,BLOCKED_STATUS_TOKENS,FAILED_STATUS_TOKENS,init_supervisor_state=__esm({"src/conductor/supervisor-state.ts"(){"use strict";SUPERVISOR_SUMMARY_KIND="supervisor_projection_summary",TERMINAL_STATES=new Set(["complete","failed"]);PROGRESS_EVENT_TYPES=new Set(["tool.intent","worktree.changed","git.commit_created"]),BLOCKED_STATUS_TOKENS=new Set(["blocked","waiting_for_input","needs_input"]),FAILED_STATUS_TOKENS=new Set(["failed","error","errored","aborted","cancelled","canceled"])}});function elapsedSinceSignal(worker,now){let candidates=[worker.last_event_time,worker.last_progress_time,worker.last_heartbeat_time].map(iso=>iso?Date.parse(iso):NaN).filter(v=>Number.isFinite(v));return candidates.length===0?0:Math.max(0,now-Math.max(...candidates))}function findSupervisorEscalationCandidates(state,config,now){let candidates=[];for(let worker of Object.values(state.workers)){if(worker.state==="complete"||worker.state==="failed")continue;let elapsed=elapsedSinceSignal(worker,now),baseContext={worker_id:worker.worker_id,ticket_key:worker.ticket_key,state:worker.state,liveness:worker.liveness};if(worker.liveness==="dead"){candidates.push({reason:"worker_dead",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});continue}switch(worker.state){case"not_started":worker.liveness!=="alive"&&candidates.push({reason:"worker_not_started",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"blocked":candidates.push({reason:"worker_blocked",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:{...baseContext,blocked_reason:worker.blocked_reason}});break;case"stalled":candidates.push({reason:"worker_stalled",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"candidate_done":worker.liveness!=="alive"&&candidates.push({reason:"candidate_done_stuck",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;case"verifying":worker.liveness==="stalled"&&candidates.push({reason:"verification_stalled",kind:ESCALATION_KIND,worker_id:worker.worker_id,state:worker.state,liveness:worker.liveness,elapsed_ms:elapsed,context:baseContext});break;default:break}}let deadlineMs=state.global_deadline_at?Date.parse(state.global_deadline_at):NaN;return Number.isFinite(deadlineMs)&&now>=deadlineMs&&candidates.push({reason:"global_timeout",kind:ESCALATION_KIND,worker_id:null,state:null,liveness:null,elapsed_ms:Math.max(0,now-deadlineMs),context:{run_id:state.run_id,deadline_at:state.global_deadline_at,worker_count:Object.keys(state.workers).length}}),candidates}function cooldownWindowFor(now,cooldownMs){let width=cooldownMs>0?cooldownMs:1;return String(Math.floor(now/width))}function shouldEmitEscalation(state,candidate,config,now){let cooldownWindow=cooldownWindowFor(now,config.escalation_cooldown_ms);return{emit:!state.escalations.some(record=>record.reason===candidate.reason&&(record.worker_id??null)===(candidate.worker_id??null)&&record.cooldown_window===cooldownWindow&&(record.outcome==="emitted"||record.outcome==="duplicate")),cooldown_window:cooldownWindow}}function recordEscalationResult(state,candidate,cooldownWindow,idempotencyKey,outcome,now){let record={idempotency_key:idempotencyKey,worker_id:candidate.worker_id??null,reason:candidate.reason,kind:candidate.kind,cooldown_window:cooldownWindow,outcome,recorded_at:new Date(now).toISOString()};return state.escalations.push(record),record}function formatElapsed(ms){let totalSeconds=Math.max(0,Math.floor(ms/1e3)),hours=Math.floor(totalSeconds/3600),minutes=Math.floor(totalSeconds%3600/60),seconds=totalSeconds%60;return hours>0?`${hours}h${minutes}m`:minutes>0?`${minutes}m`:`${seconds}s`}function formatEscalationForTerminal(runId,candidate){let worker=candidate.worker_id?` worker=${candidate.worker_id}`:"",stateBit=candidate.state?` state=${candidate.state}`:"",liveBit=candidate.liveness?` liveness=${candidate.liveness}`:"",elapsed=` elapsed=${formatElapsed(candidate.elapsed_ms)}`;return`[supervisor] run=${runId}${worker} reason=${candidate.reason}${stateBit}${liveBit}${elapsed}`}var ESCALATION_KIND,init_supervisor_escalation=__esm({"src/conductor/supervisor-escalation.ts"(){"use strict";ESCALATION_KIND="escalation"}});function buildGateIdentity(gateName,configHash){let name=gateName.trim(),hash=typeof configHash=="string"?configHash.trim():"";return hash?`${name}@${hash.toLowerCase()}`:name}function makeMergeActionKey(repo,prNumber,headSha,gateIdentity){let r=normalizeRepoName(repo),pr=normalizePrNumber(prNumber),sha=normalizeSha(headSha),gate=(gateIdentity??"").trim();if(r===null||pr===null||sha===null||gate.length===0)throw new Error("invalid merge action key component");return`merge:${r}:${pr}:${sha}:${gate}`}var init_merge_identity=__esm({"src/conductor/merge-identity.ts"(){"use strict";init_git_ci_types()}});function isPlainObject2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function normalizeEventHeadSha(value){if(typeof value!="string")return null;let trimmed=value.trim();return/^[0-9a-f]{7,40}$/i.test(trimmed)?trimmed.toLowerCase():null}function getRawEventDetails(event){let details=event.data?.details;return isPlainObject2(details)?details:null}function parseHeadObservation(event){let details=getRawEventDetails(event);return{head_sha:details?normalizeEventHeadSha(details.head_sha):null}}function parseMergeLifecycle(event){let details=getRawEventDetails(event);return{action_key:details&&typeof details.action_key=="string"&&details.action_key.trim().length>0?details.action_key.trim():null}}function parseGateMet(event){let details=getRawEventDetails(event);if(!details)return{head_sha:null,repo:null,pr_number:null,gate_name:null,config_hash:null,required_checks:[]};let gateName=typeof details.gate_name=="string"&&details.gate_name.trim().length>0?details.gate_name.trim():null,configHash=typeof details.config_hash=="string"&&details.config_hash.trim().length>0?details.config_hash.trim():null,ciCheckStatus=isPlainObject2(details.ci_check_status)?details.ci_check_status:null,requiredChecks=(Array.isArray(details.required_checks)?details.required_checks:ciCheckStatus&&Array.isArray(ciCheckStatus.required_checks)?ciCheckStatus.required_checks:[]).filter(c=>typeof c=="string"&&c.trim().length>0);return{head_sha:normalizeSha(details.head_sha),repo:normalizeRepoName(details.repo),pr_number:normalizePrNumber(details.pr_number),gate_name:gateName,config_hash:configHash,required_checks:requiredChecks}}function parseSpecReview(event){let details=getRawEventDetails(event);return{head_sha:details?normalizeEventHeadSha(details.head_sha):null}}function parseEmpty(){return EMPTY_DETAILS}function getEventDetails(event,expectedType){if(event.type!==expectedType)return null;let parser=EVENT_PARSERS[expectedType];return parser(event)}function getMergeIdentity(event){if(event.type!=="gate.met")return null;let details=getEventDetails(event,"gate.met");if(details===null)return null;let{repo,pr_number:prNumber,head_sha:headSha,gate_name:gateName}=details;if(repo===null||prNumber===null||headSha===null||gateName===null)return null;let gateIdentity=buildGateIdentity(gateName,details.config_hash),actionKey=makeMergeActionKey(repo,prNumber,headSha,gateIdentity);return{repo,pr_number:prNumber,head_sha:headSha,gate_name:gateName,config_hash:details.config_hash,required_checks:details.required_checks,gate_identity:gateIdentity,action_key:actionKey,gate_event:{id:typeof event.id=="string"?event.id:void 0,seq:typeof event.seq=="number"?event.seq:void 0,time:typeof event.time=="string"?event.time:void 0}}}var EMPTY_DETAILS,EVENT_PARSERS,init_event_accessors=__esm({"src/conductor/event-accessors.ts"(){"use strict";init_git_ci_types();init_merge_identity();EMPTY_DETAILS=Object.freeze({});EVENT_PARSERS={"run.started":parseEmpty,"run.heartbeat":parseEmpty,"run.stopped":parseEmpty,"agent.notification":parseEmpty,"tool.intent":parseEmpty,"worktree.changed":parseEmpty,"git.commit_created":parseEmpty,"git.pr_opened":parseHeadObservation,"ci.passed":parseHeadObservation,"ci.failed":parseHeadObservation,"gate.met":parseGateMet,"supervisor.assessment":parseEmpty,"message.sent":parseEmpty,"message.delivered":parseEmpty,"message.acked":parseEmpty,"merge.dry_run":parseMergeLifecycle,"merge.attempted":parseMergeLifecycle,"merge.succeeded":parseHeadObservation,"merge.failed":parseMergeLifecycle,"merge.conflict":parseHeadObservation,"merge.pending_approval":parseMergeLifecycle,"review.passed":parseHeadObservation,"review.changes_requested":parseHeadObservation,"spec_review.passed":parseSpecReview,"spec_review.changes_requested":parseSpecReview,"parse.triggered":parseEmpty,"parse.succeeded":parseEmpty,"parse.failed":parseEmpty}}});import{createHash as createHash5}from"node:crypto";function extractMergeActionIdentityFromGateEvent(event){return getMergeIdentity(event)}function makeMergeEventId(eventType,actionKey){let h=createHash5("sha256").update(`${eventType}:${actionKey}`).digest("hex");return`${h.slice(0,8)}-${h.slice(8,12)}-${h.slice(12,16)}-${h.slice(16,20)}-${h.slice(20,32)}`}async function lookupMergeEventByActionKey(eventType,actionKey,deps){let db=await(deps.openDb??(()=>openReadonlyConductorDatabaseIfExists()))();if(!db)return!1;try{return db.prepare(`SELECT 1 FROM events
132
132
  WHERE type = ?
133
133
  AND json_extract(data_json, '$.details.action_key') = ?
134
134
  LIMIT 1`).get(eventType,actionKey)!==void 0}finally{db.close()}}async function hasTerminalMergeSucceeded(actionKey,deps={}){return lookupMergeEventByActionKey("merge.succeeded",actionKey,deps)}async function hasMergeDryRun(actionKey,deps={}){return lookupMergeEventByActionKey("merge.dry_run",actionKey,deps)}async function hasMergePendingApproval(actionKey,deps={}){return lookupMergeEventByActionKey("merge.pending_approval",actionKey,deps)}function isDuplicateConstraintError4(error){if(!error||typeof error!="object")return!1;let code=error.code;if(typeof code=="string"&&code.startsWith("SQLITE_CONSTRAINT"))return!0;let message=error.message;if(typeof message=="string"){let lowered=message.toLowerCase();if(lowered.includes("unique constraint")||lowered.includes("constraint failed"))return!0}return!1}async function emitMergeLedgerEventIfNew(input,deps={}){let emitEvent=deps.emitEvent??emitConductorEvent,eventId=makeMergeEventId(input.type,input.action_key),event={id:eventId,source:"conductor-supervisor",type:input.type,run_id:input.run_id??null,worker_id:input.worker_id??null,producer:"conductor-merge",observed_via:"supervisor",data:{summary:input.summary??`${input.type} ${input.action_key}`,status:input.status,reason:input.reason??void 0,details:input.details}};try{let result=await emitEvent(event);return{emitted:!0,event_id:eventId,event:result.event}}catch(error){if(isDuplicateConstraintError4(error))return{emitted:!1,reason:"duplicate"};throw error}}var init_merge_ledger=__esm({"src/conductor/merge-ledger.ts"(){"use strict";init_event_accessors();init_merge_identity();init_store()}});function buildMergeRequestFromGateEvent(identity){return{repo_name:identity.repo,pr_number:identity.pr_number,expected_head_sha:identity.head_sha,gate:{name:identity.gate_name,config_hash:identity.config_hash,required_checks:identity.required_checks},action_key:identity.action_key,gate_event:identity.gate_event}}function mapApiErrorReason(error){if(error instanceof ConductorBridgeApiError)switch(error.kind){case"timeout":return"api_timeout";case"network":return"api_network";case"unauthorized":return"api_unauthorized";case"server":case"http":return"api_unavailable";case"invalid-input":return"api_invalid"}return"api_network"}function resolveAttributionWorkerId(event,identity,resolve2){if(typeof event.worker_id=="string"&&event.worker_id.trim().length>0)return event.worker_id.trim();if(resolve2){let resolved=resolve2(event,identity);if(typeof resolved=="string"&&resolved.trim().length>0)return resolved.trim()}return null}async function processGateMetMerge(access,event,deps={}){let extract=deps.extractIdentity??extractMergeActionIdentityFromGateEvent,checkTerminal=deps.hasTerminal??hasTerminalMergeSucceeded,checkDryRun=deps.hasDryRun??hasMergeDryRun,checkPendingApproval=deps.hasPendingApproval??hasMergePendingApproval,mergeFn=deps.merge??mergePullRequestForGate,identity=extract(event);if(!identity)return{processed:!1,reason:"ineligible"};let actionKey=identity.action_key,attributionWorkerId=resolveAttributionWorkerId(event,identity,deps.resolveWorkerIdForGateEvent);if(await checkTerminal(actionKey))return{processed:!1,reason:"already_succeeded"};let baseDetails={action_key:actionKey,repo:identity.repo,pr_number:identity.pr_number,expected_head_sha:identity.head_sha,gate:identity.gate_identity},response;try{response=await mergeFn(access,buildMergeRequestFromGateEvent(identity))}catch(error){let reason=mapApiErrorReason(error);return await emitMergeLedgerEventIfNew({type:"merge.failed",action_key:actionKey,status:"failed",reason,details:baseDetails,run_id:event.run_id??null,worker_id:attributionWorkerId,summary:`merge.failed ${reason}`},{emitEvent:deps.emitEvent}),{processed:!0,outcome:"api_error",reason}}let emitted=[];for(let ledgerEvent of response.ledger_events??[]){if(ledgerEvent.type==="merge.dry_run"&&await checkDryRun(actionKey)){emitted.push({type:ledgerEvent.type,emitted:!1});continue}if(ledgerEvent.type==="merge.pending_approval"&&await checkPendingApproval(actionKey)){emitted.push({type:ledgerEvent.type,emitted:!1});continue}let result=await emitMergeLedgerEventIfNew({type:ledgerEvent.type,action_key:actionKey,status:ledgerEvent.status,reason:ledgerEvent.reason??null,details:ledgerEvent.details??baseDetails,run_id:event.run_id??null,worker_id:attributionWorkerId},{emitEvent:deps.emitEvent});emitted.push({type:ledgerEvent.type,emitted:result.emitted})}return{processed:!0,outcome:response.status,emitted}}var init_supervisor_merge=__esm({"src/conductor/supervisor-merge.ts"(){"use strict";init_bridge_api_client();init_merge_ledger()}});async function dispatchSupervisorNotification(epicRunId,candidate,assessment,idempotencyKey){let result=await resolveConductorBridgeApiAccess();if(!result.ok)return;let{access}=result,url=buildConductorJiraUrl(access.baseUrl,`/epic-runs/${encodeURIComponent(epicRunId)}/notifications`),payload={repo_name:access.repoName,idempotency_key:idempotencyKey,summary:{reason:candidate.reason,kind:candidate.kind,worker_id:candidate.worker_id??null,elapsed_ms:candidate.elapsed_ms,ticket_key:candidate.context?.ticket_key??null,classification:assessment.classification}},headers={"X-API-Key":access.apiKey,"Content-Type":"application/json"};try{await fetchConductorJsonPostWithTimeout(url,headers,JSON.stringify(payload),CONDUCTOR_FETCH_TIMEOUT_MS,fetch)}catch{}}var init_supervisor_notification=__esm({"src/conductor/supervisor-notification.ts"(){"use strict";init_bridge_api_client()}});var supervisor_runtime_exports={};__export(supervisor_runtime_exports,{runSupervisor:()=>runSupervisor});function deterministicAssessment(candidate){return{classification:"stuck",confidence:1,reason:candidate.reason}}function terminalStatus(state){return Object.values(state.workers).some(w=>w.state==="failed")?"failed":"complete"}async function processEscalations(state,config,deps){let now=deps.now(),candidates=findSupervisorEscalationCandidates(state,config,now);for(let candidate of candidates){let decision=shouldEmitEscalation(state,candidate,config,now);if(!decision.emit)continue;let idempotency={run_id:state.run_id,worker_id:candidate.worker_id,reason:candidate.reason,kind:candidate.kind,cooldown_window:decision.cooldown_window},idempotencyKey=makeSupervisorIdempotencyKey(idempotency),assessment=deterministicAssessment(candidate);state.latest_assessment=assessment;let outcome="skipped";try{outcome=(await deps.emitAssessment({run_id:state.run_id,worker_id:candidate.worker_id,assessment,details:{elapsed_ms:candidate.elapsed_ms,...candidate.context},idempotency})).emitted?"emitted":"duplicate"}catch{outcome="skipped"}if(recordEscalationResult(state,candidate,decision.cooldown_window,idempotencyKey,outcome,now),(outcome==="emitted"||outcome==="duplicate")&&candidate.worker_id)try{await sendSupervisorEscalationWorkerMessageIfNew(candidate,assessment,state,{sendMessage:deps.sendWorkerMessage})}catch{}if(outcome==="emitted"&&(deps.log(formatEscalationForTerminal(state.run_id,candidate)),deps.dispatchNotification))try{await deps.dispatchNotification(state.run_id,candidate,assessment,idempotencyKey)}catch{}}}async function runSupervisor(options,deps={}){let runId=typeof options.run_id=="string"?options.run_id.trim():"";if(runId.length===0)throw new ConductorValidationError("Supervisor requires exactly one non-empty --run-id.");let config=options.config??resolveSupervisorConfig(options.overrides??{}),now=deps.now??(()=>Date.now()),log=deps.log??(m=>process.stdout.write(`${m}
135
135
  `)),errorLog=deps.errorLog??(m=>process.stderr.write(`${m}
136
- `)),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()}});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(`
136
+ `)),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 randomUUID3}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=randomUUID3();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(`
137
+ `);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(`
138
+ `);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(`
139
+ `),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(`
140
+ `)}});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(`
137
141
  `)}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(`
138
142
  `);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(`
139
143
  `);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
@@ -142,8 +146,8 @@ ${managedBlock}
142
146
  `)?"":`
143
147
  `;return{ok:!0,content:`${existing}${separator}${managedBlock}
144
148
  `,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}}async function inspectEpicTickSchedule(deps,orchestrateListOverride){try{let schedRun=orchestrateListOverride?null:await Promise.resolve().then(()=>(init_schedule_run(),schedule_run_exports)),doList=orchestrateListOverride||(d=>schedRun.orchestrateScheduleList({json:!1},d)),resolvedDeps=orchestrateListOverride?deps:deps??schedRun.createDefaultScheduleRunDeps(),commandLabel=schedRun?schedRun.scheduleCommandLabel:m2=>m2.command??(m2.idea_file?"full-automation":"(unknown)"),runStatus=schedRun?schedRun.latestRunStatus:m2=>{let h=m2.run_history;return h&&h.length>0?h[h.length-1].status:""},entry=(await doList(resolvedDeps)).entries.find(e=>commandLabel(e.metadata)==="epic-tick");if(!entry)return{registered:!1,backend:null,next_fire_iso:null,latest_run_status:null,degraded:!1,warnings:[]};let m=entry.metadata,latest=runStatus(m);return{registered:!0,backend:m.backend??null,next_fire_iso:m.run_at_iso??null,latest_run_status:latest||null,degraded:!0,warnings:[`An epic-tick schedule is registered, but the v1 \`conductor epic-tick\` path is frozen (EPIC_TICK_V1_FROZEN) \u2014 it advances nothing. Cancel it: \`npx -y ${MCP_PACKAGE_NAME} schedule-run cancel --id ${entry.metadata.id??"<id>"}\`. Epic Conductor v2 reconciles server-side; run jobs locally with \`npx -y ${MCP_PACKAGE_NAME} executor --repo <name>\`.`]}}catch(err){return{registered:!1,backend:null,next_fire_iso:null,latest_run_status:null,degraded:!0,warnings:[`Failed to inspect epic-tick schedule: ${err instanceof Error?err.message:String(err)}`]}}}function inspectMcpProfile(env,epicTick){let 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"||epicTick.registered,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,epicTick=await inspectEpicTickSchedule(deps.scheduleDeps,deps.orchestrateList),mcp_profile=inspectMcpProfile(deps.env??process.env,epicTick),{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),epic_tick:epicTick,mcp_profile,local_merge:inspectLocalMerge(deps.runCommand),native_ledger,deny_enforcement,claude_login}}async function inspectDenyEnforcementSafe(inspect){try{let run=inspect;return run||(run=(await Promise.resolve().then(()=>(init_deny_enforcement_preflight(),deny_enforcement_preflight_exports))).runDenyEnforcementPreflight),await run()}catch(err){return{enforced:!1,layer:"none",degraded:!0,warnings:[`Deny-layer enforcement inspection failed: ${err instanceof Error?err.message:String(err)}`,"The executor claim loop MUST refuse to claim jobs until the deny layer is enforced."]}}}function formatConductorDoctorReport(report){let{ledger,git_hooks,epic_tick,mcp_profile,local_merge,native_ledger,deny_enforcement,claude_login}=report,lines=["Conductor ledger doctor","\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",`path: ${ledger.path}`,`directory exists: ${ledger.directory_exists}`,`database exists: ${ledger.database_exists}`,`directory mode: ${ledger.directory_mode??"n/a"} (ok: ${ledger.directory_permissions_ok})`,`database mode: ${ledger.database_mode??"n/a"} (ok: ${ledger.database_permissions_ok})`,`schema present: ${ledger.schema_present}`,`journal mode: ${ledger.journal_mode??"n/a"}`,`user_version: ${ledger.user_version??"n/a"}`,`event count: ${ledger.event_count??"n/a"}`,`max seq: ${ledger.max_seq??"n/a"}`,`busy_timeout_ms: ${ledger.retention.busy_timeout_ms}`,`retention_days: ${ledger.retention.retention_days}`,`retention_max_rows: ${ledger.retention.retention_max_rows}`,`message_cooldown_ms: ${ledger.message_relay.message_cooldown_ms}`,`degraded (network FS): ${ledger.degraded}`];if(ledger.warnings.length>0){lines.push("warnings:");for(let w of ledger.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("git hooks (optional, local)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),lines.push(`is git worktree: ${git_hooks.is_worktree}`),lines.push(`hooks dir: ${git_hooks.hooks_dir??"n/a"}`),lines.push(`degraded: ${git_hooks.degraded}`);for(let hook of git_hooks.hooks)lines.push(` ${hook.name}: exists=${hook.exists} executable=${hook.executable} managed=${hook.managed_block_present} 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 Supervisor Schedule (v1 epic-tick \u2014 frozen)"),lines.push("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");let registeredTag=epic_tick.registered?"[WARNING] registered \u2014 dead timer, remove it":"[SUCCESS] none registered (v1 is frozen)";if(lines.push(`epic-tick schedule: ${registeredTag}`),epic_tick.registered&&(lines.push(`backend: ${epic_tick.backend??"n/a"}`),lines.push(`next fire: ${epic_tick.next_fire_iso??"n/a"}`),lines.push(`latest run status: ${epic_tick.latest_run_status??"n/a"}`)),lines.push(`degraded: ${epic_tick.degraded}`),epic_tick.warnings.length>0){lines.push("epic-tick warnings:");for(let w of epic_tick.warnings)lines.push(` - ${w}`)}lines.push(""),lines.push("Epic Conductor v2 reconciles epics server-side \u2014 nothing to schedule"),lines.push("locally. To execute claimed jobs on this machine, run:"),lines.push(` npx -y ${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(`
145
- `)}init_supervisor_config();function formatConductorErrorLine(envelope){if(envelope.error==="LEDGER_NATIVE_MODULE_LOAD_FAILED"&&envelope.details){let d=envelope.details;return`${envelope.message} details: module=${d.module} node_version=${d.node_version} node_modules_abi=${d.node_modules_abi}`}return envelope.message}function getConductorUsage(){return["Usage: conductor <command> [options]","","Local append-only event ledger for multi-agent coordination.","Talks ONLY to the local SQLite store (~/.config/bridge/events.db); no Bridge API calls.","","Commands:"," emit-event Append one semantic event to the ledger"," supervise --run-id <id> Run the foreground, run-scoped supervisor loop"," epic-tick Run one stateless reconciliation pass for an Epic"," epic-status Print read-only health summary of an Epic Run"," send-message Enqueue ONE typed supervisor->worker relay message (idempotent)"," check-messages Read + ACK pending relay messages for a worker (no redelivery)"," doctor Read-only health/diagnostics report (ledger + git hooks)"," purge Delete ALL ledger rows (events, messages, supervisor_projection)"," install-git-hooks Install local, opportunistic, non-blocking git hooks"," git-hook post-commit Run the post-commit producer (invoked by the installed hook)"," git-hook reference-transaction --phase <p> --stdin-file <f>"," Run the reference-transaction producer (invoked by the hook)"," file-scope-guard Warn-only: compare the branch diff against the declared"," touched-file set (always exits 0; never blocks a PR)","","supervise options:"," --run-id <id> Run/session identifier to supervise (required)"," --wake-interval-ms <n> Deterministic event-poll cadence (clamped 30000..60000)"," --global-timeout-ms <n> Total wall-clock ceiling for the run"," --escalation-cooldown-ms <n> Min gap between escalations for the same worker+reason","","install-git-hooks notes:"," Hooks are LOCAL, unversioned, opportunistic, and bypassable. Missing hooks are a"," degraded optional capability and never prevent PR/CI gate evaluation.","","emit-event options:"," --type <t> Semantic event type (required). One of:",` ${SEMANTIC_EVENT_TYPES.join(", ")}`," --source <s> Logical producer (required)"," --subject <s> Subject the event is about (e.g. ticket key)"," --run-id <s> Run/session identifier"," --worker-id <s> Worker/agent identifier"," --producer <s> Finer-grained producer identity"," --schema-version <n> Event schema version (default 1)"," --time <iso> ISO-8601 event time (default now)"," --confidence <0..1> Confidence score"," --observed-via <s> Channel the event was observed through"," --data-json <json> Normalized data object (allowlisted top-level keys)"," --data-json-stdin Read the complete normalized data object as JSON from stdin"," (mutually exclusive with --data-json; keeps raw payloads and"," secrets out of the process argument list)"," --raw-json <json> Tool-native object; nested under data.raw"," --payload-ref <ref> Reference for large external payloads (-> data.payload_ref)"," --json Print compact JSON result","","send-message options:"," --run-id <s> Run/session identifier (required)"," --worker-id <s> Target worker identifier (required)"," --type <s> Typed message kind, e.g. supervisor.worker_stalled (required)"," --cause-seq <n> Idempotency cause sequence, non-negative integer (required)"," --payload-json <json> Compact payload object (allowlisted top-level keys)"," --payload-json-stdin Read the payload object as JSON from stdin"," (mutually exclusive with --payload-json)"," --available-at <iso> ISO-8601 time the message becomes available (default now)"," --cooldown-ms <n> Per-call cooldown override in ms"," --json Print compact JSON result"," Note: a duplicate idempotency key or a same-type message inside the cooldown"," window does NOT enqueue a second message.","","check-messages options:"," --run-id <s> Run/session identifier (required)"," --worker-id <s> Worker identifier (required)"," --limit <n> Max messages to deliver/ack (default 10, max 100)"," --json Print compact JSON result"," Note: returned messages are ACKNOWLEDGED by this call and are not redelivered.","","doctor / purge options:"," --json Print machine-readable JSON"," --no-deny-probe (doctor only) Skip the deny-enforcement preflight \u2014 no headless"," agent is spawned; the deny_enforcement section reports an"," explicit skipped state (enforcement UNVERIFIED, never enforced)","","Examples:"," conductor emit-event --type run.started --source git-hook --run-id BAPI-393 \\",` --data-json '{"summary":"run started"}'`," conductor emit-event --type git.commit_created --source git-hook \\",` --raw-json '{"branch":"feature/x","sha":"abc123"}'`," conductor emit-event --type ci.failed --source ci \\"," --payload-ref 'file:///tmp/ci-log.txt'"," conductor emit-event --type merge.succeeded --source conductor-merge \\",` --worker-id w1 --data-json '{"summary":"auto-merged","status":"succeeded"}'`," conductor doctor --json"," conductor purge","","epic-tick options:"," --epic-key <KEY> Epic key to supervise (required, non-empty)"," --scheduled-at <epoch> Epoch-seconds timestamp when this tick was scheduled (optional)"," --lease-ttl-seconds <n> Lease TTL in seconds (optional, default 120)","","approve-plan options:"," approve-plan <epic_key> --plan-version N [--json]"," <epic_key> Epic key (e.g. EPIC-405) (required positional)"," --plan-version <n> Strictly positive plan version to approve (required)"," --json Print compact JSON result"," --help Print this usage message","","epic-status options:"," --epic-key <KEY> Epic key to fetch the snapshot for (required)"," --json Print compact JSON result"," --help Print this usage message","","Examples:"," conductor approve-plan EPIC-405 --plan-version 2"," conductor approve-plan EPIC-405 --plan-version 2 --json"," conductor epic-status --epic-key EPIC-405"," conductor epic-status --epic-key EPIC-405 --json"].join(`
146
- `)}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",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(`
149
+ `)}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(`
150
+ `)}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(`
147
151
  `)),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(`
148
152
  `)),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,epic_tick:report.epic_tick,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(`
149
153
  `)),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.
@@ -152,5 +156,5 @@ ${managedBlock}
152
156
  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(`
153
157
  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(`
154
158
  `)),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(`
155
- `)),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();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.
159
+ `)),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.
156
160
  `),process.exit(2)});