@bridge_gpt/mcp-server 0.2.56 → 0.2.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -5
- package/build/codex-bridge-profile.js +151 -0
- package/build/codex-home.js +7 -0
- package/build/codex-launch-scope.js +12 -7
- package/build/doctor.js +6 -1
- package/build/epic-implementer-bin.js +3 -3
- package/build/index.js +88 -84
- package/build/install-bridge.js +47 -1
- package/build/mcp-host-config.js +4 -0
- package/build/mcp-host-targets.js +3 -0
- package/build/readme.generated.js +1 -1
- package/build/start-tickets.js +76 -17
- package/build/version.generated.js +3 -3
- package/package.json +1 -1
|
@@ -108,7 +108,7 @@ ${managedBlock}
|
|
|
108
108
|
`)){let norm=normalizeRepoRelativePath(line);norm&&!seen.has(norm)&&(seen.add(norm),files.push(norm))}return{ok:!0,files}}function analyzeDiffScope(input){if(!input.declared.specified)return{checked:!1,outOfScopeFiles:[],warning:null};let declaredSet=new Set(input.declared.files),outOfScope=input.changedFiles.filter(f=>!declaredSet.has(f)).sort();if(outOfScope.length===0)return{checked:!0,outOfScopeFiles:[],warning:null};let warning=`[file-scope-guard] ${input.ticketKey&&input.ticketKey.trim().length>0?input.ticketKey.trim():"unknown-ticket"}: ${outOfScope.length} file(s) changed outside the declared touched-file set (${input.declared.files.length} declared): ${outOfScope.join(", ")}. Warn-only \u2014 PR creation continues.`;return{checked:!0,outOfScopeFiles:outOfScope,warning}}function runFileScopeGuardCli(deps={}){let env=deps.env??process.env,writeOut=deps.writeOut??(m=>process.stdout.write(`${m}
|
|
109
109
|
`)),writeErr=deps.writeErr??(m=>process.stderr.write(`${m}
|
|
110
110
|
`)),ticketKey=env[FILE_SCOPE_GUARD_TICKET_KEY_ENV],declared=parseDeclaredTouchedFilesFromEnv(env);if(!declared.specified)return 0;let collected=collectBranchChangedFiles({cwd:deps.cwd,spawnSyncFn:deps.spawnSyncFn});if(!collected.ok)return writeErr(`[file-scope-guard] ${ticketKey??"unknown-ticket"}: unable to check file scope (git diff failed); continuing \u2014 PR creation is not blocked.`),0;let analysis=analyzeDiffScope({ticketKey,declared,changedFiles:collected.files});return analysis.warning&&writeOut(analysis.warning),0}var DECLARED_TOUCHED_FILES_ENV,FILE_SCOPE_GUARD_TICKET_KEY_ENV,FILE_SCOPE_GUARD_BASE_REF,defaultSpawnSync,init_file_scope_guard=__esm({"src/conductor/file-scope-guard.ts"(){"use strict";DECLARED_TOUCHED_FILES_ENV="BAPI_CONDUCTOR_DECLARED_TOUCHED_FILES_JSON",FILE_SCOPE_GUARD_TICKET_KEY_ENV="BAPI_CONDUCTOR_TICKET_KEY",FILE_SCOPE_GUARD_BASE_REF="origin/main";defaultSpawnSync=(command,args,options)=>spawnSync(command,args,options)}});import path3 from"path";async function detectClaudeLogin(deps){let raw;try{raw=await deps.readFile(path3.join(deps.homedir(),".claude.json"))}catch{return{detected:!1}}let parsed;try{parsed=JSON.parse(raw)}catch{return{detected:!1}}if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return{detected:!1};let oauthAccount=parsed.oauthAccount;return oauthAccount!==null&&typeof oauthAccount=="object"&&!Array.isArray(oauthAccount)?{detected:!0}:{detected:!1}}function formatClaudeLoginAdvisory(result){return result.detected?"Claude login: detected (~/.claude.json has an OAuth account). This is advisory only \u2014 it does not guarantee the next worker spawn will authenticate.":"Claude login: not detected. Run `claude login` on this host, or, on a headless host, export CLAUDE_CODE_OAUTH_TOKEN before starting the executor."}var init_claude_login=__esm({"src/claude-login.ts"(){"use strict"}});function resolveRegistrationKey(servers){let absent={state:"absent",writeKey:MCP_SERVER_NAME};if(typeof servers!="object"||servers===null||Array.isArray(servers))return absent;let present=RECOGNIZED_SERVER_NAMES.filter(name=>Object.prototype.hasOwnProperty.call(servers,name));if(present.length===0)return absent;if(present.length>1)return{state:"conflict",keys:present};let[only]=present;return only===MCP_SERVER_NAME?{state:"canonical",key:MCP_SERVER_NAME}:{state:"legacy",key:only}}function existingRegistrationKey(servers){let resolution=resolveRegistrationKey(servers);return resolution.state==="canonical"||resolution.state==="legacy"?resolution.key:null}var MCP_SERVER_NAME,MCP_PACKAGE_NAME,MCP_README_URI,LEGACY_SERVER_NAMES,RECOGNIZED_SERVER_NAMES,init_mcp_identity=__esm({"src/mcp-identity.ts"(){"use strict";MCP_SERVER_NAME="bridge",MCP_PACKAGE_NAME="@bridge_gpt/mcp-server",MCP_README_URI=`${MCP_SERVER_NAME}://readme`,LEGACY_SERVER_NAMES=["bridge-api"],RECOGNIZED_SERVER_NAMES=[MCP_SERVER_NAME,...LEGACY_SERVER_NAMES]}});import path4 from"node:path";function resolvePackageRootFromModuleUrl(moduleUrl){let pathname;try{pathname=decodeURIComponent(new URL(moduleUrl).pathname)}catch{return null}/^\/[A-Za-z]:/.test(pathname)&&(pathname=pathname.slice(1));let segments=pathname.split(/[\\/]/),markerIndex=-1;for(let i=segments.length-1;i>=0;i--)if(segments[i]==="src"||segments[i]==="build"){markerIndex=i;break}return markerIndex<=0?null:segments.slice(0,markerIndex).join("/")}function basenameAnySep(filePath){let segments=filePath.split(/[\\/]/);return segments[segments.length-1]??""}function resolveMcpShimInvocationForRuntime(deps){let nodeExecutable=deps.nodeExecutable??"node",packageRoot=resolvePackageRootFromModuleUrl(deps.moduleUrl);if(packageRoot){let candidate=`${packageRoot}/build/index.js`;if(deps.fileExists(candidate))return{form:"absolute-build-path",nodeExecutable,serverEntryPath:candidate}}let argv1=deps.argv1;return typeof argv1=="string"&&argv1.length>0&&path4.isAbsolute(argv1)&&basenameAnySep(argv1)==="index.js"&&deps.fileExists(argv1)?{form:"absolute-build-path",nodeExecutable,serverEntryPath:argv1}:{form:"npm-channel",command:"npx",packageSpec:deps.npmPackageSpec??DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC}}var DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC,init_mcp_server_invocation=__esm({"src/mcp-server-invocation.ts"(){"use strict";init_mcp_identity();DEFAULT_MCP_SERVER_NPM_CHANNEL_SPEC=`${MCP_PACKAGE_NAME}@latest`}});function resolveProfiles(raw){let baseline=new Set(["core"]);if(raw===void 0)return baseline;let trimmed=raw.trim();if(trimmed==="")return baseline;let tokens=trimmed.split(",").map(t=>t.trim().toLowerCase());if(tokens.some(t=>t==="full"))return new Set(["core","conductor","estimation","pipeline-authoring","sfcc","sfcc-write"]);for(let token of tokens)VALID_GROUPS.has(token)&&baseline.add(token);return baseline}var VALID_GROUPS,init_mcp_profile=__esm({"src/mcp-profile.ts"(){"use strict";VALID_GROUPS=new Set(["core","conductor","estimation","pipeline-authoring","sfcc","sfcc-write"])}});function containsAbsolutePath(value){return ABSOLUTE_PATH_PATTERN.test(value)}function containsTransportArtifact(value){return TRANSPORT_ARTIFACT_PATTERN.test(value)}function normalizeProse(value,field,maxLength){if(typeof value!="string")throw new ReadinessCheckValidationError(Array.isArray(value)?`${field} must be a single string, not an array`:`${field} must be a string`);let collapsed=value.replace(/[\u0000-\u001f\u007f]+/g," ").replace(/\s{2,}/g," ").trim();if(collapsed.length===0)throw new ReadinessCheckValidationError(`${field} must not be blank`);if(containsAbsolutePath(collapsed))throw new ReadinessCheckValidationError(`${field} must not contain an absolute path`);if(containsTransportArtifact(collapsed))throw new ReadinessCheckValidationError(`${field} must not contain a request header or a response body`);return collapsed.length>maxLength?`${collapsed.slice(0,maxLength-1).trimEnd()}\u2026`:collapsed}function normalizeReadinessDetail(value){return normalizeProse(value,"detail",READINESS_DETAIL_MAX_LENGTH)}function normalizeReadinessRemediation(value){return normalizeProse(value,"remediation",READINESS_REMEDIATION_MAX_LENGTH)}function createReadinessCheck(input){if(input===null||typeof input!="object")throw new ReadinessCheckValidationError("check must be an object");if(!READINESS_CHECK_SOURCES.includes(input.source))throw new ReadinessCheckValidationError("source is not a supported readiness source");if(!READINESS_CHECK_STATUSES.includes(input.status))throw new ReadinessCheckValidationError("status is not a supported readiness status");if(typeof input.id!="string"||!READINESS_ID_PATTERN.test(input.id))throw new ReadinessCheckValidationError("id is not a stable dotted lowercase identifier");if(!input.id.startsWith(`${input.source}.`))throw new ReadinessCheckValidationError("id namespace does not match its source");let label=normalizeProse(input.label,"label",READINESS_DETAIL_MAX_LENGTH),detail=input.detail===void 0?void 0:normalizeReadinessDetail(input.detail);if(input.status==="pass"){if(input.remediation!==void 0)throw new ReadinessCheckValidationError("a passing check must not carry a remediation");return{id:input.id,source:input.source,label,status:"pass",...detail?{detail}:{}}}if(input.status==="fail"){if(input.remediation===void 0)throw new ReadinessCheckValidationError("a failing check must carry exactly one remediation");return{id:input.id,source:input.source,label,status:"fail",...detail?{detail}:{},remediation:normalizeReadinessRemediation(input.remediation)}}let remediation=input.remediation===void 0?void 0:normalizeReadinessRemediation(input.remediation);return{id:input.id,source:input.source,label,status:input.status,...detail?{detail}:{},...remediation?{remediation}:{}}}function validateReadinessChecks(checks,fallbackSource="conductor"){let validated=[],malformedIndex=0;for(let candidate of checks)try{validated.push(createReadinessCheck(candidate))}catch{let raw=candidate??{},source=READINESS_CHECK_SOURCES.includes(raw.source)?raw.source:fallbackSource;malformedIndex+=1,validated.push(createReadinessCheck({id:`${source}.unreadable-check-${malformedIndex}`,source,label:READINESS_MALFORMED_CHECK_LABEL,status:"fail",detail:READINESS_MALFORMED_CHECK_DETAIL,remediation:READINESS_MALFORMED_CHECK_REMEDIATION}))}return validated}function summarizeReadinessChecks(checks){let counts={pass:0,warn:0,fail:0,skip:0};for(let check of checks)counts[check.status]+=1;return counts}function createReadinessCheckSafely(input){let safeRemediation=()=>input?.status==="pass"?{remediation:void 0}:{remediation:READINESS_UNSAFE_REMEDIATION_REPLACEMENT};try{return createReadinessCheck(input)}catch{}try{return createReadinessCheck({...input,detail:READINESS_UNSAFE_DETAIL_REPLACEMENT})}catch{}try{return createReadinessCheck({...input,...safeRemediation()})}catch{}try{return createReadinessCheck({...input,detail:READINESS_UNSAFE_DETAIL_REPLACEMENT,...safeRemediation()})}catch{}let source=READINESS_CHECK_SOURCES.includes(input?.source)?input.source:"conductor";return createReadinessCheck({id:`${source}.unreadable-check`,source,label:READINESS_MALFORMED_CHECK_LABEL,status:"fail",detail:READINESS_MALFORMED_CHECK_DETAIL,remediation:READINESS_MALFORMED_CHECK_REMEDIATION})}var READINESS_CHECK_STATUSES,READINESS_CHECK_SOURCES,ReadinessCheckValidationError,READINESS_DETAIL_MAX_LENGTH,READINESS_REMEDIATION_MAX_LENGTH,ID_SEGMENT,READINESS_ID_PATTERN,POSIX_PATH_ROOTS,ABSOLUTE_PATH_PATTERN,TRANSPORT_ARTIFACT_PATTERN,READINESS_MALFORMED_CHECK_DETAIL,READINESS_MALFORMED_CHECK_REMEDIATION,READINESS_MALFORMED_CHECK_LABEL,READINESS_UNSAFE_DETAIL_REPLACEMENT,READINESS_UNSAFE_REMEDIATION_REPLACEMENT,init_readiness_check=__esm({"src/readiness-check.ts"(){"use strict";READINESS_CHECK_STATUSES=["pass","warn","fail","skip"],READINESS_CHECK_SOURCES=["install","conductor","plane","server"],ReadinessCheckValidationError=class extends Error{constructor(reason){super(`invalid readiness check: ${reason}`),this.name="ReadinessCheckValidationError"}},READINESS_DETAIL_MAX_LENGTH=400,READINESS_REMEDIATION_MAX_LENGTH=400,ID_SEGMENT="[a-z0-9]+(?:-[a-z0-9]+)*",READINESS_ID_PATTERN=new RegExp(`^${ID_SEGMENT}(?:\\.${ID_SEGMENT})+$`),POSIX_PATH_ROOTS=["Users","home","root","var","tmp","private","opt","usr","etc","srv","mnt","media","Applications","Library","System","Volumes","node_modules"],ABSOLUTE_PATH_PATTERN=new RegExp(`(^|[\\s"'\`(<])(?:\\/(?:${POSIX_PATH_ROOTS.join("|")})\\/|[A-Za-z]:[\\\\/]|file:\\/\\/)`);TRANSPORT_ARTIFACT_PATTERN=/(^|[\s"'`(<])(?:authorization\s*:|x-api-key\s*:|bearer\s+\S|\{\s*"[A-Za-z_$][\w$]*"\s*:)/i;READINESS_MALFORMED_CHECK_DETAIL="this prerequisite reported a result that failed the readiness contract, so its real state is unknown",READINESS_MALFORMED_CHECK_REMEDIATION="re-run `epic-implementer readiness`; if it persists, run `epic-implementer doctor` and `install conductor` to re-collect this locus.",READINESS_MALFORMED_CHECK_LABEL="Unreadable prerequisite";READINESS_UNSAFE_DETAIL_REPLACEMENT="detail withheld \u2014 the source reported it in a form this report may not carry",READINESS_UNSAFE_REMEDIATION_REPLACEMENT="re-run `epic-implementer readiness`; this prerequisite's own fix text could not be carried into this report safely."}});import path5 from"path";function hasControlChars(value){for(let i=0;i<value.length;i++){let code=value.charCodeAt(i);if(code<=31||code===127)return!0}return!1}function validateRepoName(raw){if(typeof raw!="string")return{ok:!1,error:"repo_name must be a string"};let value=raw.trim();return value.length===0?{ok:!1,error:"repo_name must be a non-empty string"}:value.includes("/")||value.includes("\\")?{ok:!1,error:"repo_name must not contain path separators"}:hasControlChars(value)?{ok:!1,error:"repo_name must not contain control characters"}:{ok:!0,value}}function validateMcpTarget(raw){if(typeof raw!="string")return{ok:!1,error:"mcp target must be a string"};let value=raw.trim();return value.length===0?{ok:!1,error:"mcp target must be a non-empty string"}:value.includes("/")||value.includes("\\")?{ok:!1,error:"mcp target must not contain path separators"}:hasControlChars(value)?{ok:!1,error:"mcp target must not contain control characters"}:{ok:!0,value}}function parseQuotedString(value){if(value.length<2||value[0]!=='"'||value[value.length-1]!=='"')return null;let inner=value.slice(1,-1);return inner.includes('"')?null:inner}function parseStringArray(value){let trimmed=value.trim();if(trimmed.length<2||trimmed[0]!=="["||trimmed[trimmed.length-1]!=="]")return null;let inner=trimmed.slice(1,-1).trim();if(inner.length===0)return[];let parts=inner.split(","),out=[];for(let part of parts){let element=parseQuotedString(part.trim());if(element===null)return null;out.push(element)}return out}function parseBridgeConfigToml(text){let lines=text.split(`
|
|
111
|
-
`),repoName,sawRepoName=!1,mcp=[],currentMcp=null;for(let i=0;i<lines.length;i++){let lineNo=i+1,line=lines[i].trim();if(line.length===0||line.startsWith("#"))continue;if(line==="[[mcp]]"){currentMcp={headerLine:lineNo},mcp.push(currentMcp);continue}if(line.startsWith("["))return{ok:!1,kind:"parse-error",error:`Unsupported table header on line ${lineNo}; only [[mcp]] is allowed`};let eq=line.indexOf("=");if(eq===-1)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; expected key = "value"`};let key=line.slice(0,eq).trim(),rawValue=line.slice(eq+1).trim();if(key.length===0)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; missing key`};if(currentMcp===null){if(key==="repo_name"){if(sawRepoName)return{ok:!1,kind:"parse-error",error:`Duplicate repo_name on line ${lineNo}`};sawRepoName=!0;let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};let validated=validateRepoName(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};repoName=validated.value;continue}return key==="target"?{ok:!1,kind:"parse-error",error:`target on line ${lineNo} must appear inside an [[mcp]] section`}:{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' on line ${lineNo}`}}if(key==="args"){if(currentMcp.args!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate args on line ${lineNo}`};let arr=parseStringArray(rawValue);if(arr===null)return{ok:!1,kind:"parse-error",error:`Expected a string array for 'args' on line ${lineNo}`};currentMcp.args=arr;continue}if(key==="target"||key==="command"||key==="secret_bundle"){let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};if(key==="target"){if(currentMcp.target!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate target on line ${lineNo}`};let validated=validateMcpTarget(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};currentMcp.target=validated.value;continue}if(key==="command"){if(currentMcp.command!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate command on line ${lineNo}`};currentMcp.command=stringValue;continue}if(currentMcp.secretBundle!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate secret_bundle on line ${lineNo}`};currentMcp.secretBundle=stringValue;continue}return{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' inside [[mcp]] on line ${lineNo}`}}if(!sawRepoName||repoName===void 0)return{ok:!1,kind:"validation-error",error:"Missing required repo_name"};let cleaned=[];for(let entry of mcp){if(entry.target===void 0)return{ok:!1,kind:"validation-error",error:`An [[mcp]] section on line ${entry.headerLine} is missing its target`};if(entry.target!=="bapi"){if(entry.command===void 0||entry.command.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty command`};if(entry.args===void 0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires an args array`};if(entry.secretBundle===void 0||entry.secretBundle.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty secret_bundle`}}let clean={target:entry.target};entry.command!==void 0&&(clean.command=entry.command),entry.args!==void 0&&(clean.args=entry.args),entry.secretBundle!==void 0&&(clean.secretBundle=entry.secretBundle),cleaned.push(clean)}return{ok:!0,manifest:{repoName,mcp:cleaned}}}function bridgeConfigPath(projectRoot){return path5.join(projectRoot,".bridge","config")}async function readBridgeConfig(projectRoot,deps){let filePath=bridgeConfigPath(projectRoot),raw;try{raw=await deps.readFile(filePath)}catch(err){return err&&typeof err=="object"&&err.code==="ENOENT"?{ok:!1,kind:"missing"}:{ok:!1,kind:"parse-error",error:"Unable to read .bridge/config"}}return parseBridgeConfigToml(raw)}var init_bridge_config=__esm({"src/bridge-config.ts"(){"use strict"}});async function resolveStartTicketsRepoName(deps){let fromEnv=deps.env.BAPI_REPO_NAME;if(typeof fromEnv=="string"&&fromEnv.trim().length>0)return fromEnv.trim();try{let result=await readBridgeConfig(deps.cwd,{readFile:deps.readFile});if(result.ok&&result.manifest.repoName)return result.manifest.repoName}catch{}return null}async function resolveRequiredStartTicketsRepoName(deps){let repoName=await resolveStartTicketsRepoName(deps);return repoName?{ok:!0,repoName}:{ok:!1,kind:"repo-missing",error:"could not resolve repo name (set BAPI_REPO_NAME or add a valid .bridge/config)"}}var init_start_tickets_repo=__esm({"src/start-tickets-repo.ts"(){"use strict";init_bridge_config()}});function nonblank(candidate){if(typeof candidate!="string")return;let trimmed=candidate.trim();return trimmed.length>0?trimmed:void 0}function resolveDeclaredRunBaseBranch(policyJson){if(policyJson===null||typeof policyJson!="object"||Array.isArray(policyJson))return;let policy=policyJson;for(let key of POLICY_BASE_BRANCH_KEYS){if(!Object.prototype.hasOwnProperty.call(policy,key))continue;let resolved=nonblank(policy[key]);if(resolved!==void 0)return resolved}}var POLICY_BASE_BRANCH_KEYS,init_run_branch=__esm({"src/conductor/run-branch.ts"(){"use strict";POLICY_BASE_BRANCH_KEYS=["base_branch","baseBranch"]}});var bridge_api_client_exports={};__export(bridge_api_client_exports,{CONDUCTOR_DEFAULT_BASE_URL:()=>CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS:()=>CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES:()=>CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,ConductorBridgeApiError:()=>ConductorBridgeApiError,EPIC_RUN_STATUS_VALUES:()=>EPIC_RUN_STATUS_VALUES,READINESS_FRESH_RECONCILER_COUNT_CAP:()=>READINESS_FRESH_RECONCILER_COUNT_CAP,adoptCurrentHeadAndUnparkTicket:()=>adoptCurrentHeadAndUnparkTicket,advanceEpicTicketStatus:()=>advanceEpicTicketStatus,approveEpicPlan:()=>approveEpicPlan,bootstrapConductorSupervisorDefaults:()=>bootstrapConductorSupervisorDefaults,buildConductorJiraUrl:()=>buildConductorJiraUrl,buildConductorVcsUrl:()=>buildConductorVcsUrl,buildEpicDispatchKey:()=>buildEpicDispatchKey,claimEpicSupervisionLease:()=>claimEpicSupervisionLease,completeMergeChild:()=>completeMergeChild,createEpicRun:()=>createEpicRun,createEpicRunWithDisposition:()=>createEpicRunWithDisposition,createEpicTicketStatus:()=>createEpicTicketStatus,deletePullRequestBranch:()=>deletePullRequestBranch,dispatchRemediation:()=>dispatchRemediation,extractSanitizedErrorDiagnostics:()=>extractSanitizedErrorDiagnostics,fetchActiveEpicRuns:()=>fetchActiveEpicRuns,fetchConductorConfigField:()=>fetchConductorConfigField,fetchConductorJsonPatchWithTimeout:()=>fetchConductorJsonPatchWithTimeout,fetchConductorJsonPostWithTimeout:()=>fetchConductorJsonPostWithTimeout,fetchConductorJsonPutWithTimeout:()=>fetchConductorJsonPutWithTimeout,fetchConductorJsonWithTimeout:()=>fetchConductorJsonWithTimeout,fetchConductorReadiness:()=>fetchConductorReadiness,fetchEffectiveSupervisorConfig:()=>fetchEffectiveSupervisorConfig,fetchEffectiveSupervisorSetup:()=>fetchEffectiveSupervisorSetup,fetchEpicRunState:()=>fetchEpicRunState,fetchExplainRun:()=>fetchExplainRun,fetchParseStatus:()=>fetchParseStatus,fetchPrReviewStatus:()=>fetchPrReviewStatus,fetchShadowDispatchFreshness:()=>fetchShadowDispatchFreshness,getEpicPlan:()=>getEpicPlan,mergeChild:()=>mergeChild,mergePullRequestForGate:()=>mergePullRequestForGate,parseConductorReadinessResponse:()=>parseConductorReadinessResponse,parseConductorSupervisorBootstrapResponse:()=>parseConductorSupervisorBootstrapResponse,pollCiChecksForCommit:()=>pollCiChecksForCommit,readEpicRunCompletionState:()=>readEpicRunCompletionState,reconcileShadowMerge:()=>reconcileShadowMerge,recordEpicDispatch:()=>recordEpicDispatch,remediateEpicTicket:()=>remediateEpicTicket,replaceEpicRunPolicy:()=>replaceEpicRunPolicy,resolveConductorBridgeApiAccess:()=>resolveConductorBridgeApiAccess,safeDiagnosticMessage:()=>safeDiagnosticMessage,scopeReparse:()=>scopeReparse,stopEpicRun:()=>stopEpicRun,storeEpicPlan:()=>storeEpicPlan,transitionEpicDispatch:()=>transitionEpicDispatch,transitionJiraStatus:()=>transitionJiraStatus,triggerRepositoryParse:()=>triggerRepositoryParse,unparkEpicTicket:()=>unparkEpicTicket,updateApprovedPlanNodeTicketSpec:()=>updateApprovedPlanNodeTicketSpec,updateEpicRunStatus:()=>updateEpicRunStatus,validateEpicPlan:()=>validateEpicPlan});import os2 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??os2.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"):[],path15=(parts[0]==="body"?parts.slice(1):parts).slice(0,CONDUCTOR_VALIDATION_LOC_MAX_PARTS).join(".");return path15?`${path15}: ${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={},options={}){try{let parsed=stripWebhookUrlsDeep(await resp.json()),diagnostics=extractSanitizedErrorDiagnostics(parsed);if(options.readErrorField&&!diagnostics.bodyPreview){let detail=parsed&&typeof parsed=="object"&&!Array.isArray(parsed)?parsed.detail:void 0,error=detail&&typeof detail=="object"&&!Array.isArray(detail)?detail.error:void 0;typeof error=="string"&&error.trim()&&(diagnostics.bodyPreview=boundedErrorPreview(error.trim()))}let 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(/\/+$/,""),path15=apiPath.startsWith("/")?apiPath:`/${apiPath}`;return new URL(`${trimmed}${path15}`).toString()}function conductorPostHeaders(access){return{"X-API-Key":access.apiKey,"Content-Type":"application/json"}}async function fetchConductorJsonWithMethodAndTimeout(method,url,headers,body,timeoutMs,fetchImpl,errorOptions={}){let{body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl,errorOptions);return parsed}async function fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl,errorOptions={}){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,errorOptions);throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status,diagnostics):resp.status>=500?new ConductorBridgeApiError("server",resp.status,diagnostics):new ConductorBridgeApiError("http",resp.status,diagnostics)}try{return{status:resp.status,body:await resp.json()}}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function fetchConductorJsonPostWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("POST",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPatchWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PATCH",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPutWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PUT",url,headers,body,timeoutMs,fetchImpl)}async function mergePullRequestForGate(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number),sha=normalizeSha(request.expected_head_sha);if(pr===null||sha===null||!request.action_key||!request.repo_name)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/merge`),body=JSON.stringify({repo_name:request.repo_name,expected_head_sha:sha,gate:request.gate,action_key:request.action_key,...request.gate_event?{gate_event:request.gate_event}:{}});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function remediateEpicTicket(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number);if(pr===null||!request.epic_run_id||!request.ticket_key||!request.head_sha||!request.idempotency_key)throw new ConductorBridgeApiError("invalid-input");if(requireNonNegativeSafeInteger(request.expected_row_version),request.attempt_kind!=="nudge"&&request.attempt_kind!=="redispatch")throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/remediate`),body=JSON.stringify({repo_name:access.repoName,epic_run_id:request.epic_run_id,ticket_key:request.ticket_key,expected_row_version:request.expected_row_version,head_sha:request.head_sha,idempotency_key:request.idempotency_key,attempt_kind:request.attempt_kind,...request.reason?{reason:request.reason}:{}});try{return{ok:!0,conflict:!1,response:await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===409)return{ok:!0,conflict:!0};throw err}}function requireNonEmptyString(value){if(typeof value!="string"||value.trim().length===0)throw new ConductorBridgeApiError("invalid-input")}function requirePositiveSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<=0)throw new ConductorBridgeApiError("invalid-input")}function requireNonNegativeSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<0)throw new ConductorBridgeApiError("invalid-input")}function requireNoSlashPathSegment(value){if(value.includes("/"))throw new ConductorBridgeApiError("invalid-input")}function requireEpicTicketStatusValue(value){if(typeof value!="string"||!EPIC_TICKET_STATUS_VALUES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function requireEpicDispatchTransitionStatus(value){if(typeof value!="string"||!EPIC_DISPATCH_TRANSITION_STATUSES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function epicRunApiPath(epicKey){return`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}`}function epicDispatchTransitionApiPath(dispatchKey,nextStatus){return nextStatus==="run_spawned"?`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/run-spawned`:`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/terminal`}function buildEpicDispatchKey(epicKey,ticketKey,planVersion,attempt=0){requireNonEmptyString(epicKey),requireNonEmptyString(ticketKey),requireNonNegativeSafeInteger(planVersion),requireNonNegativeSafeInteger(attempt);let base=`dispatch:${epicKey}:${ticketKey}:${planVersion}`;return attempt>0?`${base}:r${attempt}`:base}function parseEpicSupervisionLeaseResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed,row=p.row;if(p.claimed===!0&&row&&typeof row=="object")return{ok:!0,kind:"acquired-or-renewed",row};if(p.claimed===!1&&p.reason==="lease_held"&&row&&typeof row=="object")return{ok:!1,kind:"held-by-other",reason:"lease_held",row};if(p.claimed===!1&&p.reason==="terminal"&&row&&typeof row=="object")return{ok:!1,kind:"terminal",reason:"terminal",row};throw new ConductorBridgeApiError("server")}async function claimEpicSupervisionLease(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.leaseOwner),requirePositiveSafeInteger(request.ttlSeconds);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/lease/claim`),body=JSON.stringify({repo_name:access.repoName,lease_owner:request.leaseOwner,ttl_seconds:request.ttlSeconds}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseEpicSupervisionLeaseResult(parsed)}async function fetchEpicRunState(access,epicKey,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/state`,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchExplainRun(access,epicRunId,ticketKey,fetchImpl=globalThis.fetch){requireNonEmptyString(epicRunId);let apiPath=`${epicRunApiPath(epicRunId)}/explain`;ticketKey!==void 0&&(requireNonEmptyString(ticketKey),requireNoSlashPathSegment(ticketKey),apiPath=`${epicRunApiPath(epicRunId)}/tickets/${encodeURIComponent(ticketKey)}/explain`);let url=buildConductorJiraUrl(access.baseUrl,apiPath,{repo_name:access.repoName});return fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function isEpicRunStatus(value){return typeof value=="string"&&EPIC_RUN_STATUS_VALUES.includes(value)}async function readEpicRunCompletionState(access,epicRunId,fetchImpl=globalThis.fetch){if(typeof epicRunId!="string"||epicRunId.trim().length===0)return{ok:!1,reason:"invalid-input"};let parsed;try{parsed=await fetchEpicRunState(access,epicRunId,fetchImpl)}catch(err){return err instanceof ConductorBridgeApiError?err.kind==="http"&&err.status===404?{ok:!1,reason:"not-found"}:err.kind==="unauthorized"?{ok:!1,reason:"unauthorized"}:err.kind==="timeout"?{ok:!1,reason:"timeout"}:err.kind==="server"?{ok:!1,reason:"server"}:err.kind==="network"?{ok:!1,reason:"network"}:err.kind==="invalid-input"?{ok:!1,reason:"invalid-input"}:{ok:!1,reason:"malformed"}:{ok:!1,reason:"network"}}if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return{ok:!1,reason:"malformed"};let epicRun=parsed.epic_run;if(!epicRun||typeof epicRun!="object"||Array.isArray(epicRun))return{ok:!1,reason:"malformed"};let status=epicRun.status;if(!isEpicRunStatus(status))return{ok:!1,reason:"malformed"};let policyJson=epicRun.policy_json,featureBranch=resolveDeclaredRunBaseBranch(policyJson);return{ok:!0,state:featureBranch!==void 0?{status,featureBranch}:{status}}}async function fetchActiveEpicRuns(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`,{repo_name:access.repoName,status:"active",limit:"20"}),parsed=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);if(parsed&&typeof parsed=="object"){let runs=parsed.runs;if(Array.isArray(runs))return runs}return[]}async function createEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`);return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function createEpicRunWithDisposition(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`),{status,body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout("POST",url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return{run:parsed,created:status===201}}async function replaceEpicRunPolicy(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicRunId)),body=JSON.stringify({repo_name:access.repoName,policy_json:request.policyJson});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateEpicRunStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicKey)),body=JSON.stringify({repo_name:access.repoName,status:request.status,...request.expectedStatus?{expected_status:request.expectedStatus}:{}});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function stopEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/stop`),body=JSON.stringify({repo_name:access.repoName,...request.reason!==void 0?{reason:request.reason}:{},...request.expectedGeneration!==void 0?{expected_generation:request.expectedGeneration}:{}});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseAdvanceEpicTicketStatusResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed;if(p.ok===!1&&p.kind==="cas-conflict")return{ok:!1,kind:"cas-conflict",...typeof p.current_row_version=="number"?{current_row_version:p.current_row_version}:{},...p.ticket_status&&typeof p.ticket_status=="object"?{ticket_status:p.ticket_status}:{}};if(p.ok===!0&&p.ticket_status&&typeof p.ticket_status=="object")return{ok:!0,ticket_status:p.ticket_status};if("ticket_key"in p&&"status"in p&&"row_version"in p)return{ok:!0,ticket_status:parsed};throw new ConductorBridgeApiError("server")}async function advanceEpicTicketStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion),requireNonNegativeSafeInteger(request.planVersion),requireEpicTicketStatusValue(request.nextStatus),request.dispatchRunId!==void 0&&requireNonEmptyString(request.dispatchRunId);let CAS_ENDPOINT_PATH=`${epicRunApiPath(request.epicKey)}/tickets/${encodeURIComponent(request.ticketKey)}`,url=buildConductorJiraUrl(access.baseUrl,CAS_ENDPOINT_PATH),body=JSON.stringify({repo_name:access.repoName,status:request.nextStatus,plan_version:request.planVersion,expected_row_version:request.expectedRowVersion,...request.dispatchRunId?{dispatch_run_id:request.dispatchRunId}:{}}),parsed=await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseAdvanceEpicTicketStatusResult(parsed)}async function postUnparkLikeRequest(url,headers,body,fetchImpl){try{let parsed=await fetchConductorJsonPostWithTimeout(url,headers,body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseAdvanceEpicTicketStatusResult(parsed)}catch(err){if(err instanceof ConductorBridgeApiError&&err.status===400&&typeof err.currentRowVersion=="number")return parseAdvanceEpicTicketStatusResult({ok:!1,kind:"cas-conflict",current_row_version:err.currentRowVersion});throw err}}async function unparkEpicTicket(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/unpark`),body=JSON.stringify({repo_name:access.repoName,expected_row_version:request.expectedRowVersion,...request.idempotencyKey!==void 0?{idempotency_key:request.idempotencyKey}:{},...request.reason!==void 0?{reason:request.reason}:{}});return postUnparkLikeRequest(url,conductorPostHeaders(access),body,fetchImpl)}async function adoptCurrentHeadAndUnparkTicket(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/adopt-current-head-and-unpark`),body=JSON.stringify({repo_name:access.repoName,expected_row_version:request.expectedRowVersion,...request.idempotencyKey!==void 0?{idempotency_key:request.idempotencyKey}:{},...request.reason!==void 0?{reason:request.reason}:{}});return postUnparkLikeRequest(url,conductorPostHeaders(access),body,fetchImpl)}function parseRepairNullableString(value){return typeof value=="string"?value:null}function parseRepairBase(parsed){if(!parsed||typeof parsed!="object"||Array.isArray(parsed))throw new ConductorBridgeApiError("server");let p=parsed;if(typeof p.epic_run_id!="string"||typeof p.committed!="boolean"||typeof p.event_recorded!="boolean")throw new ConductorBridgeApiError("server");return p}function parseScopeReparseResult(parsed){let p=parseRepairBase(parsed);if(typeof p.scope_id!="string"||typeof p.parse_scheduled!="boolean")throw new ConductorBridgeApiError("server");return{epic_run_id:p.epic_run_id,scope_id:p.scope_id,before:parseRepairNullableString(p.before),after:parseRepairNullableString(p.after),committed:p.committed,event_recorded:p.event_recorded,outcome:typeof p.outcome=="string"?p.outcome:"",parse_scheduled:p.parse_scheduled}}function parseDispatchRemediationResult(parsed){let p=parseRepairBase(parsed);if(typeof p.ticket_key!="string")throw new ConductorBridgeApiError("server");let jobId=p.job_id;return{epic_run_id:p.epic_run_id,ticket_key:p.ticket_key,before:parseRepairNullableString(p.before),after:parseRepairNullableString(p.after),committed:p.committed,event_recorded:p.event_recorded,job_type:typeof p.job_type=="string"?p.job_type:"",job_id:typeof jobId=="number"&&Number.isSafeInteger(jobId)?jobId:null}}function parseMergeChildRouteResponse(parsed){let p=parseRepairBase(parsed),prNumber=p.pr_number;if(typeof prNumber!="number"||!Number.isSafeInteger(prNumber)||prNumber<=0)throw new ConductorBridgeApiError("server");let localExecution=null,local=p.local_execution;if(local&&typeof local=="object"&&!Array.isArray(local)){let l=local,sha=normalizeSha(l.expected_head_sha);if(sha===null)throw new ConductorBridgeApiError("server");localExecution={expected_head_sha:sha,merge_method:parseRepairNullableString(l.merge_method)}}return{epic_run_id:p.epic_run_id,pr_number:prNumber,ticket_key:typeof p.ticket_key=="string"?p.ticket_key:"",before:parseRepairNullableString(p.before),after:parseRepairNullableString(p.after),committed:p.committed,event_recorded:p.event_recorded,reason:parseRepairNullableString(p.reason),local_execution:localExecution}}async function postRepairRequest(access,apiPath,body,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("POST",buildConductorJiraUrl(access.baseUrl,apiPath),conductorPostHeaders(access),JSON.stringify({repo_name:access.repoName,...body}),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl,{readErrorField:!0})}async function scopeReparse(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.scopeId);let parsed=await postRepairRequest(access,`${epicRunApiPath(request.epicRunId)}/scope-reparse`,{scope_id:request.scopeId},fetchImpl);return parseScopeReparseResult(parsed)}async function dispatchRemediation(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.context);let parsed=await postRepairRequest(access,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/dispatch-remediation`,{context:request.context},fetchImpl);return parseDispatchRemediationResult(parsed)}async function mergeChild(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requirePositiveSafeInteger(request.prNumber);let parsed=await postRepairRequest(access,`${epicRunApiPath(request.epicRunId)}/merge-child`,{pr_number:request.prNumber},fetchImpl);return parseMergeChildRouteResponse(parsed)}async function completeMergeChild(access,request,fetchImpl=globalThis.fetch){if(requireNonEmptyString(request.epicRunId),requirePositiveSafeInteger(request.prNumber),!["merged","already_merged","failed"].includes(request.result))throw new ConductorBridgeApiError("invalid-input");let parsed=await postRepairRequest(access,`${epicRunApiPath(request.epicRunId)}/merge-child/complete`,{pr_number:request.prNumber,result:request.result,...request.reason!==void 0?{reason:request.reason}:{}},fetchImpl);return parseMergeChildRouteResponse(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 path15=epicDispatchTransitionApiPath(request.dispatchKey,request.nextStatus),url=buildConductorJiraUrl(access.baseUrl,path15),body=request.nextStatus==="run_spawned"?JSON.stringify({repo_name:access.repoName,run_id:request.runId}):JSON.stringify({repo_name:access.repoName});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseShadowMergeReconcileResult(parsed){let obj=parsed??{};return{applies:obj.applies===!0,scheduled:obj.scheduled===!0,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:"unknown",shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,requiredCommitSha:typeof obj.required_commit_sha=="string"?obj.required_commit_sha:null,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null}}function parseShadowDispatchFreshnessResult(parsed){let obj=parsed??{},rawVerdict=typeof obj.verdict=="string"?obj.verdict:"",verdict=SHADOW_FRESHNESS_VERDICTS.has(rawVerdict)?rawVerdict:"stale";return{verdict,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:verdict,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null,indexedCommitSha:typeof obj.indexed_commit_sha=="string"?obj.indexed_commit_sha:null,shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,lastError:typeof obj.last_error=="string"?obj.last_error:null,deadlineExpired:obj.deadline_expired===!0,blockedAdvanceReason:typeof obj.blocked_advance_reason=="string"&&obj.blocked_advance_reason.length>0?obj.blocked_advance_reason:null}}async function reconcileShadowMerge(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/shadow/merge-reconcile`),body=JSON.stringify({repo_name:access.repoName,merged_ticket_key:request.mergedTicketKey??null}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseShadowMergeReconcileResult(parsed)}async function fetchShadowDispatchFreshness(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNoSlashPathSegment(request.ticketKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/tickets/${encodeURIComponent(request.ticketKey)}/shadow-freshness`),body=JSON.stringify({repo_name:access.repoName}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseShadowDispatchFreshnessResult(parsed)}async function validateEpicPlan(access,request,fetchImpl=globalThis.fetch){requirePositiveSafeInteger(request.planVersion);let blobVersion=request.planBlob.plan_version;if(blobVersion!==void 0&&blobVersion!==request.planVersion)throw new ConductorValidationError(`planVersion mismatch: request.planVersion=${request.planVersion} but planBlob.plan_version=${blobVersion}`);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/plan/validate`),body={repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob};request.epicKey!==void 0&&(body.epic_key=request.epicKey),request.trackedPaths!==void 0&&(body.tracked_paths=request.trackedPaths);let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseValidateEpicPlanResult(parsed)}function parseValidateEpicPlanResult(parsed){if(!parsed||typeof parsed!="object"||Array.isArray(parsed))throw new ConductorBridgeApiError("server");let p=parsed,planHash=p.plan_hash,serializationEnabled=p.serialization_enabled,insertedEdges=p.inserted_edges,valid=p.valid;if(typeof valid!="boolean"||typeof planHash!="string"||planHash.trim()===""||typeof serializationEnabled!="boolean"||typeof insertedEdges!="number"||!Number.isSafeInteger(insertedEdges)||insertedEdges<0)throw new ConductorBridgeApiError("server");let rejections=parsePlanLintRejections(p.rejections),notices=parsePlanLintNotices(p.notices);if(!valid&&rejections.length===0)throw new ConductorBridgeApiError("server");return{valid,rejections,notices,evaluationComplete:typeof p.evaluation_complete=="boolean"?p.evaluation_complete:!0,planHash,serializationEnabled,insertedEdges,overlappingPairsFound:safeCount(p.overlapping_pairs_found),undeclaredNodes:safeCount(p.undeclared_nodes),undeclaredPairsSkipped:safeCount(p.undeclared_pairs_skipped),coverageScope:typeof p.coverage_scope=="string"&&p.coverage_scope.trim()!==""?p.coverage_scope:"unreported"}}function parsePlanLintRejections(value){if(!Array.isArray(value))return[];let out=[];for(let raw of value){if(!raw||typeof raw!="object"||Array.isArray(raw))continue;let entry=raw,reasonCode=entry.reason_code,explanation=entry.explanation;if(typeof reasonCode!="string"||reasonCode.trim()===""||typeof explanation!="string"||explanation.trim()==="")continue;let rejection={reasonCode,explanation,ticketKeys:safeStringArray(entry.ticket_keys)};typeof entry.path=="string"&&entry.path!==""&&(rejection.path=entry.path),typeof entry.migration_id=="string"&&entry.migration_id!==""&&(rejection.migrationId=entry.migration_id),out.push(rejection)}return out}function parsePlanLintNotices(value){if(!Array.isArray(value))return[];let out=[];for(let raw of value){if(!raw||typeof raw!="object"||Array.isArray(raw))continue;let entry=raw,noticeCode=entry.notice_code,explanation=entry.explanation;typeof noticeCode!="string"||noticeCode.trim()===""||typeof explanation!="string"||explanation.trim()===""||out.push({noticeCode,explanation,ticketKeys:safeStringArray(entry.ticket_keys),paths:safeStringArray(entry.paths)})}return out}function safeStringArray(value){return Array.isArray(value)?value.filter(v=>typeof v=="string"&&v!==""):[]}function safeCount(value){return typeof value=="number"&&Number.isSafeInteger(value)&&value>=0?value:0}async function storeEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion),requireNonEmptyString(request.planHash);let blobVersion=request.planBlob.plan_version;if(blobVersion!==void 0&&blobVersion!==request.planVersion)throw new ConductorValidationError(`planVersion mismatch: request.planVersion=${request.planVersion} but planBlob.plan_version=${blobVersion}`);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan`),storeBody={repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob,plan_hash:request.planHash};request.trackedPaths!==void 0&&(storeBody.tracked_paths=request.trackedPaths);let body=JSON.stringify(storeBody);return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateApprovedPlanNodeTicketSpec(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.expectedPlanHash),requireNonEmptyString(request.ticketSpec);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan/nodes/${encodeURIComponent(request.ticketKey)}/ticket-spec`),body=JSON.stringify({repo_name:access.repoName,expected_plan_hash:request.expectedPlanHash,ticket_spec:request.ticketSpec});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseApproveEpicPlanSuccess(parsed){let record=parsed??{},result={ok:!0,plan_hash:record.plan_hash},prov=record.feature_branch_provisioning;if(prov&&typeof prov=="object"&&!Array.isArray(prov)){let p=prov;(p.status==="created"||p.status==="already_exists")&&typeof p.feature_branch=="string"&&typeof p.source_branch=="string"&&typeof p.source_sha=="string"&&typeof p.remote_head_sha=="string"&&(result.featureBranchProvisioning={status:p.status,feature_branch:p.feature_branch,source_branch:p.source_branch,source_sha:p.source_sha,remote_head_sha:p.remote_head_sha})}return result}async function approveEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/approve-plan`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion});try{let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseApproveEpicPlanSuccess(parsed)}catch(error){if(error instanceof ConductorBridgeApiError&&error.status===409){let preview=error.bodyPreview??"";return/multiple active runs/i.test(preview)?{ok:!1,kind:"conflict",reason:"multiple_active_runs"}:{ok:!1,kind:"conflict",reason:"superseded"}}throw error}}async function getEpicPlan(access,epicKey,planVersion,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/plan`,{repo_name:access.repoName,plan_version:String(planVersion)});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchParseStatus(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-status",{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function triggerRepositoryParse(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-repository"),body=JSON.stringify({repo_name:access.repoName});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function deletePullRequestBranch(access,prNumber,expectedHeadSha,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(prNumber);if(pr===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/branch?repo_name=${encodeURIComponent(access.repoName)}&expected_head_sha=${encodeURIComponent(expectedHeadSha)}`),controller=new AbortController,timer=setTimeout(()=>controller.abort(),CONDUCTOR_FETCH_TIMEOUT_MS);try{let resp;try{resp=await fetchImpl(url,{method:"DELETE",headers:{"X-API-Key":access.apiKey},body:"",signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(resp.status===404)return{deleted:!1,branch:null,reason:"not_found"};if(!resp.ok)throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status):resp.status>=500?new ConductorBridgeApiError("server",resp.status):new ConductorBridgeApiError("http",resp.status);try{return await resp.json()}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function transitionJiraStatus(access,ticketNumber,targetStatus="auto",fetchImpl=globalThis.fetch){if(!ticketNumber)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorJiraUrl(access.baseUrl,`/tickets/${encodeURIComponent(ticketNumber)}/jira-status`),body=JSON.stringify({repo_name:access.repoName,target_status:targetStatus});try{return await fetchConductorJsonPutWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl),{status:"transitioned"}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===400)return{status:"skipped"};throw err}}function readinessShapeError(){return new ConductorBridgeApiError("invalid-input",void 0,{errorCode:"READINESS_SHAPE_INVALID"})}function requireObject(value){if(typeof value!="object"||value===null||Array.isArray(value))throw readinessShapeError();return value}function requireBool(o,key){let v=o[key];if(typeof v!="boolean")throw readinessShapeError();return v}function requireInt(o,key){let v=o[key];if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableInt(o,key){let v=o[key];if(v==null)return null;if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableString(o,key){let v=o[key];if(v==null)return null;if(typeof v!="string")throw readinessShapeError();return v}function requireNullableBool(o,key){let v=o[key];if(v==null)return null;if(typeof v!="boolean")throw readinessShapeError();return v}function parseReviewPolicyAlignment(o){let raw=o.review_policy_alignment;if(raw==null)return null;let a=requireObject(raw),explanation=a.explanation;if(typeof explanation!="string")throw readinessShapeError();return{status:requireEnum(a,"status",CONDUCTOR_REVIEW_ALIGNMENT_STATUSES),repo_review_signal:requireNullableString(a,"repo_review_signal"),done_gate_review_signal:requireNullableString(a,"done_gate_review_signal"),explanation}}function requireEnum(o,key,allowed){let v=o[key];if(typeof v!="string"||!allowed.has(v))throw readinessShapeError();return v}function parseConductorReadinessResponse(body){let root=requireObject(body),repoName=root.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let sup=requireObject(root.supervisor),gh=requireObject(root.github),rec=requireObject(root.reconciler),exec=requireObject(root.executor),thr=requireObject(root.thresholds);return{repo_name:repoName,supervisor:{setup_present:requireBool(sup,"setup_present"),setup_source:requireEnum(sup,"setup_source",READINESS_SOURCES),setup_created_at:requireNullableString(sup,"setup_created_at"),setup_updated_at:requireNullableString(sup,"setup_updated_at"),config_present:requireBool(sup,"config_present"),config_source:requireEnum(sup,"config_source",READINESS_SOURCES),config_created_at:requireNullableString(sup,"config_created_at"),config_updated_at:requireNullableString(sup,"config_updated_at"),required_checks_count:requireInt(sup,"required_checks_count"),required_checks_empty:requireBool(sup,"required_checks_empty"),auto_merge_enabled:requireBool(sup,"auto_merge_enabled"),merge_approval_required_set:requireBool(sup,"merge_approval_required_set"),review_policy_alignment:parseReviewPolicyAlignment(sup),review_policy_present:sup.review_policy_present===!0},github:{credentials_readable:requireBool(gh,"credentials_readable"),owner_resolved:requireBool(gh,"owner_resolved"),repo_id_resolved:requireBool(gh,"repo_id_resolved"),installation_id_resolved:requireBool(gh,"installation_id_resolved"),credentials_complete:requireBool(gh,"credentials_complete"),actions_probe_succeeded:requireBool(gh,"actions_probe_succeeded"),actions_permission_present:requireBool(gh,"actions_permission_present"),actions_permission_level:requireEnum(gh,"actions_permission_level",ACTIONS_LEVELS),actions_write:requireBool(gh,"actions_write")},reconciler:{liveness_readable:requireBool(rec,"liveness_readable"),last_tick_at:requireNullableString(rec,"last_tick_at"),last_tick_age_seconds:requireNullableInt(rec,"last_tick_age_seconds"),stale:requireBool(rec,"stale"),active_run_count:requireInt(rec,"active_run_count"),expired_lease_count:requireInt(rec,"expired_lease_count")},executor:{liveness_readable:requireBool(exec,"liveness_readable"),last_seen_at:requireNullableString(exec,"last_seen_at"),last_seen_age_seconds:requireNullableInt(exec,"last_seen_age_seconds"),ready:requireNullableBool(exec,"ready")},thresholds:{reconciler_stale_after_seconds:requireInt(thr,"reconciler_stale_after_seconds"),executor_stale_after_seconds:requireInt(thr,"executor_stale_after_seconds")},review_workflow:parseReviewWorkflow(root),conductor_ci_workflow:parseConductorCiWorkflow(root),unattended:parseUnattended(root),bring_up:parseBringUp(root)}}function parseBringUp(body){let raw=body.bring_up;if(raw==null)return null;let o=requireObject(raw),freshCount=requireInt(o,"fresh_reconciler_count");if(freshCount<0||freshCount>READINESS_FRESH_RECONCILER_COUNT_CAP)throw readinessShapeError();return{migration_readable:requireBool(o,"migration_readable"),database_migration_current:requireBool(o,"database_migration_current"),heartbeat_readable:requireBool(o,"heartbeat_readable"),worker_present:requireBool(o,"worker_present"),fresh_reconciler_count:freshCount,single_transition_authority:requireBool(o,"single_transition_authority")}}function parseReviewWorkflow(body){let raw=body.review_workflow;if(raw==null)return null;let o=requireObject(raw);return{probe_succeeded:requireBool(o,"probe_succeeded"),workflow_present:requireBool(o,"workflow_present"),emits_run_id:requireBool(o,"emits_run_id"),emits_reviewed_sha:requireBool(o,"emits_reviewed_sha")}}function parseConductorCiWorkflow(body){let raw=body.conductor_ci_workflow;if(raw==null)return null;let o=requireObject(raw);return{probe_succeeded:requireBool(o,"probe_succeeded"),workflow_present:requireBool(o,"workflow_present"),migration_guard_present:requireBool(o,"migration_guard_present")}}function parseUnattended(body){let raw=body.unattended;if(raw==null)return null;let o=requireObject(raw);return{conductor_allowed:requireBool(o,"conductor_allowed"),notify_webhook_default_declared:requireBool(o,"notify_webhook_default_declared"),notify_webhook_default_verified:o.notify_webhook_default_verified===void 0?null:requireNullableBool(o,"notify_webhook_default_verified"),repository_readiness_confirmed:requireBool(o,"repository_readiness_confirmed")}}async function fetchConductorReadiness(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/conductor-readiness`,{repo_name:access.repoName}),body=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorReadinessResponse(body)}function parseConductorSupervisorBootstrapResponse(body){let o=requireObject(body),repoName=o.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let names=o.audited_field_names;if(!Array.isArray(names)||names.some(n=>typeof n!="string"))throw readinessShapeError();return{repo_name:repoName,setup_written:requireBool(o,"setup_written"),config_written:requireBool(o,"config_written"),setup_source:requireEnum(o,"setup_source",READINESS_SOURCES),config_source:requireEnum(o,"config_source",READINESS_SOURCES),setup_created_at:requireNullableString(o,"setup_created_at"),setup_updated_at:requireNullableString(o,"setup_updated_at"),config_created_at:requireNullableString(o,"config_created_at"),config_updated_at:requireNullableString(o,"config_updated_at"),required_checks_count:requireInt(o,"required_checks_count"),audited_field_names:names}}async function bootstrapConductorSupervisorDefaults(access,request,fetchImpl){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/supervisor-bootstrap`,{repo_name:access.repoName}),body=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(request),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorSupervisorBootstrapResponse(body)}var CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_BRIDGE_API_ERROR_KINDS,CONDUCTOR_ERROR_PREVIEW_MAX,CONDUCTOR_VALIDATION_LOC_MAX_PARTS,ConductorBridgeApiError,EPIC_TICKET_STATUS_VALUES,EPIC_DISPATCH_TRANSITION_STATUSES,EPIC_RUNS_API_PREFIX,EPIC_RUN_STATUS_VALUES,SHADOW_FRESHNESS_VERDICTS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,READINESS_FRESH_RECONCILER_COUNT_CAP,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();init_run_branch();CONDUCTOR_DEFAULT_BASE_URL="https://bridgegpt-api.com",CONDUCTOR_FETCH_TIMEOUT_MS=3e4;CONDUCTOR_BRIDGE_API_ERROR_KINDS=["invalid-input","network","timeout","unauthorized","server","http"],CONDUCTOR_ERROR_PREVIEW_MAX=200;CONDUCTOR_VALIDATION_LOC_MAX_PARTS=8;ConductorBridgeApiError=class extends Error{kind;status;errorCode;bodyPreview;currentRowVersion;constructor(kindOrMessage,status,diagnostics){let isKnownKind=CONDUCTOR_BRIDGE_API_ERROR_KINDS.includes(kindOrMessage),errorCode=diagnostics?.errorCode,bodyPreview=diagnostics?.bodyPreview;if(isKnownKind){let parts=[`Conductor Bridge API request failed (${kindOrMessage}${typeof status=="number"?`, status ${status}`:""})`];errorCode&&parts.push(`code=${errorCode}`),bodyPreview&&parts.push(bodyPreview),super(parts.join(": "))}else super(kindOrMessage);this.name="ConductorBridgeApiError",this.kind=isKnownKind?kindOrMessage:"http",typeof status=="number"&&(this.status=status),errorCode&&(this.errorCode=errorCode),bodyPreview&&(this.bodyPreview=bodyPreview),typeof diagnostics?.currentRowVersion=="number"&&(this.currentRowVersion=diagnostics.currentRowVersion)}};EPIC_TICKET_STATUS_VALUES=["planned","ready","dispatched","running","blocked","abandoned","done","ready_for_review","reviewing","parse_pending"];EPIC_DISPATCH_TRANSITION_STATUSES=["run_spawned","terminal"];EPIC_RUNS_API_PREFIX="/epic-runs";EPIC_RUN_STATUS_VALUES=["planning","pending_approval","active","blocked","abandoned","done"];SHADOW_FRESHNESS_VERDICTS=new Set(["not_applicable","covered","stale","failed"]);CONDUCTOR_REVIEW_ALIGNMENT_STATUSES=new Set(["aligned","divergent","not_configured","invalid"]),READINESS_FRESH_RECONCILER_COUNT_CAP=2,READINESS_SOURCES=new Set(["epic","project_default","none"]),ACTIONS_LEVELS=new Set(["write","read","none","unknown"])}});function listAgentNames(){return Object.keys(AGENT_REGISTRY)}function isAgentName(value){return listAgentNames().includes(value)}function resolveAgentSpec(name){let resolved=name??DEFAULT_AGENT_NAME;return isAgentName(resolved)?AGENT_REGISTRY[resolved]:null}var AGENT_REGISTRY,DEFAULT_AGENT_NAME,init_agent_registry=__esm({"src/agent-registry.ts"(){"use strict";AGENT_REGISTRY={claude:{name:"claude",command:"claude",promptArgStyle:"positional",installHint:{darwin:"npm install -g @anthropic-ai/claude-code",linux:"npm install -g @anthropic-ai/claude-code",win32:"npm install -g @anthropic-ai/claude-code"},authNote:"Claude Code authenticates interactively on first run \u2014 follow its login/auth prompt if asked.",supportsModelOverride:!0,modelFlag:"--model",tierModels:{cheap:"sonnet",basic:"sonnet",premium:"opus"},staticModelAliasAllowlist:["haiku","sonnet","opus"],executorAdapter:{adapterId:"claude-reference",strategyId:"claude-strict-mcp-v1",adapterVersion:"1.0.0",supportedPlatforms:["darwin","linux"],capabilityStrategyIds:{mcpScoping:"strict-mcp-config",mcpInitParsing:"claude-system-init",authFailureDetection:"claude-stream-json-result",denyEnforcement:"claude-settings-deny",redaction:"claude-env-name-redaction",lifecycle:"claude-no-lifecycle"},managedCarriers:[],passthroughs:[{passthroughId:"claude-code-oauth-token",envName:"CLAUDE_CODE_OAUTH_TOKEN",billingClass:"subscription",ownership:"operator-owned",rule:"forward-when-present"}]}},"cursor-agent":{name:"cursor-agent",command:"cursor-agent",promptArgStyle:"positional",installHint:{darwin:"curl https://cursor.com/install -fsSL | bash",linux:"curl https://cursor.com/install -fsSL | bash",win32:"irm 'https://cursor.com/install?win32=true' | iex"},authNote:"Run cursor-agent login to authenticate; doctor checks PATH presence only, not login state.",supportsModelOverride:!0,modelFlag:"--model",tierModels:{cheap:"auto",basic:"claude-4.6-sonnet-medium",premium:"claude-opus-4-8-thinking-high"}},codex:{name:"codex",command:"codex",promptArgStyle:"positional",installHint:{darwin:"npm install -g @openai/codex",linux:"npm install -g @openai/codex",win32:"npm install -g @openai/codex"},authNote:"Codex authenticates interactively on first run \u2014 follow its login prompt if asked.",supportsModelOverride:!0,modelFlag:"--model"}},DEFAULT_AGENT_NAME="claude"}});function joinPath(base,rel){let trimmedBase=base.endsWith("/")?base.slice(0,-1):base,trimmedRel=rel.startsWith("/")?rel.slice(1):rel;return`${trimmedBase}/${trimmedRel}`}function hostAdapterForTarget(target){return HOST_ADAPTERS[target.hostKind]}function allHostTargets(){return HOST_PLATFORM_ORDER.map(id=>MCP_HOST_TARGETS[id])}function getProjectJsonTargets(){return allHostTargets().filter(t=>t.scope==="project"&&hostAdapterForTarget(t).format==="json")}var HOST_ADAPTERS,MCP_HOST_TARGETS,HOST_PLATFORM_ORDER,init_mcp_host_targets=__esm({"src/mcp-host-targets.ts"(){"use strict";HOST_ADAPTERS={"claude-code-json":{format:"json",topLevelKey:"mcpServers",transportType:void 0},"cursor-json":{format:"json",topLevelKey:"mcpServers",transportType:"stdio"},"vscode-json":{format:"json",topLevelKey:"servers",transportType:"stdio"},"codex-toml":{format:"toml",topLevelKey:"mcp_servers",transportType:void 0}};MCP_HOST_TARGETS={"claude-code":{id:"claude-code",label:"Claude Code",scope:"project",relPath:".mcp.json",displayPath:".mcp.json",hostKind:"claude-code-json",vendorCli:{bin:"claude",kind:"claude-add-json"},launchAgent:"claude",capabilities:{mcpConfiguration:!0,customCommands:!0,worktreeProvisioning:!0,sessionSpawning:!0},writeStrategy:"vendor-first",detect:()=>!0},cursor:{id:"cursor",label:"Cursor",scope:"project",relPath:".cursor/mcp.json",displayPath:".cursor/mcp.json",hostKind:"cursor-json",launchAgent:"cursor-agent",capabilities:{mcpConfiguration:!0,customCommands:!0,worktreeProvisioning:!0,sessionSpawning:!0},writeStrategy:"direct",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".cursor"))||typeof ctx.env.CURSOR_TRACE_DIR=="string"&&ctx.env.CURSOR_TRACE_DIR.length>0},"copilot-vscode":{id:"copilot-vscode",label:"GitHub Copilot",scope:"project",relPath:".vscode/mcp.json",displayPath:".vscode/mcp.json",hostKind:"vscode-json",capabilities:{mcpConfiguration:!0,customCommands:!0,worktreeProvisioning:!1,sessionSpawning:!1},writeStrategy:"direct",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".vscode"))},codex:{id:"codex",label:"OpenAI Codex",scope:"global",absPathResolver:homedir=>joinPath(homedir,".codex/config.toml"),displayPath:"~/.codex/config.toml",hostKind:"codex-toml",vendorCli:{bin:"codex",kind:"codex-add"},launchAgent:"codex",capabilities:{mcpConfiguration:!0,customCommands:!0,worktreeProvisioning:!0,sessionSpawning:!0},writeStrategy:"vendor-first",detect:ctx=>ctx.exists(joinPath(ctx.homedir,".codex"))},windsurf:{id:"windsurf",label:"Windsurf",scope:"global",absPathResolver:homedir=>joinPath(homedir,".codeium/windsurf/mcp_config.json"),displayPath:"~/.codeium/windsurf/mcp_config.json",hostKind:"claude-code-json",capabilities:{mcpConfiguration:!0,customCommands:!1,worktreeProvisioning:!1,sessionSpawning:!1},writeStrategy:"manual-instructions",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".windsurf"))||ctx.exists(joinPath(ctx.cwd,".windsurfrules"))}},HOST_PLATFORM_ORDER=["claude-code","cursor","copilot-vscode","codex","windsurf"]}});var LAUNCHER_CONFIG_TARGETS,DUPLICATE_REGISTRATION_GUIDANCE,REASON_TEXT,init_launcher_config_inspection=__esm({"src/launcher-config-inspection.ts"(){"use strict";init_mcp_host_targets();init_mcp_identity();LAUNCHER_CONFIG_TARGETS=getProjectJsonTargets().map(target=>({relPath:target.relPath,topLevelKey:hostAdapterForTarget(target).topLevelKey})),DUPLICATE_REGISTRATION_GUIDANCE=`duplicate Bridge registrations: this config carries both \`${MCP_SERVER_NAME}\` and \`${LEGACY_SERVER_NAMES.join("`, `")}\`. Confirm which registration you want to keep, then remove the unintended entry manually. Bridge will not choose for you.`,REASON_TEXT={"file-unreadable":"the file exists but could not be read","invalid-json":"the file is not valid JSON","root-not-object":"the JSON root is not an object","servers-not-object":"the servers section is not an object","entry-not-object":"the Bridge entry is not an object","no-package-token":`the Bridge launcher has no recognizable ${MCP_PACKAGE_NAME} token`,"version-range":"the launcher pin is a version range, which an automated repin must not rewrite","non-release-specifier":"the launcher pin is a dist-tag or channel, not an exact release","malformed-version":"the launcher pin is not a valid MAJOR.MINOR.PATCH release","pinned-ahead-of-target":"the launcher pin is newer than the target version and must not be downgraded","duplicate-registration":DUPLICATE_REGISTRATION_GUIDANCE}}});var init_mcp_registration_doctor=__esm({"src/mcp-registration-doctor.ts"(){"use strict";init_mcp_host_targets();init_mcp_identity();init_launcher_config_inspection()}});var init_commands_generated=__esm({"src/commands.generated.ts"(){"use strict"}});var init_command_assets_doctor=__esm({"src/command-assets-doctor.ts"(){"use strict";init_commands_generated()}});function summarizeClaudeReviewWorkflowDrift(classification){let{baseRef,defaultRef,workflowPath}=classification;return classification.state==="aligned"?`'${baseRef}' matches '${defaultRef}' for ${workflowPath}`:classification.state==="unverified"?`comparison unavailable (${classification.reason}) \u2014 advisory check failed open, ${workflowPath} lineage unknown`:`WARNING: '${baseRef}' carries a stale ${workflowPath} (differs from '${defaultRef}') \u2014 Claude review cannot run for pull requests based on it; reconcile '${baseRef}' with '${defaultRef}'`}var CLAUDE_REVIEW_WORKFLOW_RELPATH,CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION,init_claude_review_workflow_drift=__esm({"src/claude-review-workflow-drift.ts"(){"use strict";CLAUDE_REVIEW_WORKFLOW_RELPATH=".github/workflows/claude-review.yml";CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION=`Reconcile the base branch with the repository default branch \u2014 merge the default branch in, or sync ${CLAUDE_REVIEW_WORKFLOW_RELPATH} together with tests/pytest/commands/test_claude_review_workflow_prompt.py. See docs/claude/runbooks/claude-review-base-branch-drift.md.`}});var init_claude_review_workflow_drift_probe=__esm({"src/claude-review-workflow-drift-probe.ts"(){"use strict";init_claude_review_workflow_drift()}});var init_third_party_mcp_targets=__esm({"src/third-party-mcp-targets.ts"(){"use strict";init_credential_store()}});var init_mcp_provisioning=__esm({"src/mcp-provisioning.ts"(){"use strict";init_bridge_config();init_third_party_mcp_targets();init_mcp_server_invocation();init_mcp_host_targets();init_mcp_identity()}});function claudeMcpShadowingRemediationCommand(registrationKey){return`claude mcp remove ${registrationKey} -s local`}var CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV,CLAUDE_MCP_SHADOWING_OVERRIDE_WARNING,CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND,init_claude_user_config_doctor=__esm({"src/claude-user-config-doctor.ts"(){"use strict";init_mcp_registration_doctor();init_mcp_provisioning();init_mcp_identity();init_launcher_config_inspection();CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV="BAPI_CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING",CLAUDE_MCP_SHADOWING_OVERRIDE_WARNING=`Proceeding anyway because ${CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV} is set`;CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND=claudeMcpShadowingRemediationCommand(MCP_SERVER_NAME)}});var START_TICKETS_DOCTOR_COMMAND,CONDUCTOR_LIVE_SOURCE_PATH_ENV,CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV,GIT_INSTALL_HINTS,REVIEW_TICKETS_GIT_INSTALL_HINTS,RIPGREP_SHELL_FUNCTION_CAVEAT,RIPGREP_INSTALL_HINTS,CREDENTIAL_RESOLUTION_HINT,CLAUDE_MCP_SHADOWING_HINT,LIVE_SOURCE_GUARD_HINT,init_start_tickets_prereqs=__esm({"src/start-tickets-prereqs.ts"(){"use strict";init_credential_store();init_start_tickets_repo();init_mcp_registration_doctor();init_command_assets_doctor();init_mcp_identity();init_claude_review_workflow_drift();init_claude_review_workflow_drift_probe();init_claude_user_config_doctor();START_TICKETS_DOCTOR_COMMAND=`npx -y ${MCP_PACKAGE_NAME} doctor`,CONDUCTOR_LIVE_SOURCE_PATH_ENV="BAPI_CONDUCTOR_LIVE_SOURCE_PATH",CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV="BAPI_CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH",GIT_INSTALL_HINTS={darwin:"xcode-select --install (or brew install git)",linux:"Install git with your distro package manager, e.g. apt install git",win32:"Install Git for Windows: https://git-scm.com/download/win"},REVIEW_TICKETS_GIT_INSTALL_HINTS={darwin:`${GIT_INSTALL_HINTS.darwin} (or rerun review-tickets with --no-refresh-base to skip the fetch)`,linux:`${GIT_INSTALL_HINTS.linux} (or rerun review-tickets with --no-refresh-base to skip the fetch)`,win32:`${GIT_INSTALL_HINTS.win32} (or rerun review-tickets with --no-refresh-base to skip the fetch)`},RIPGREP_SHELL_FUNCTION_CAVEAT="a shell function/alias will not satisfy this check \u2014 ripgrep must be installed as a real PATH binary.",RIPGREP_INSTALL_HINTS={darwin:`brew install ripgrep (${RIPGREP_SHELL_FUNCTION_CAVEAT})`,linux:`Install ripgrep with your distro package manager, e.g. apt install ripgrep (${RIPGREP_SHELL_FUNCTION_CAVEAT})`,win32:`winget install BurntSushi.ripgrep.MSVC (${RIPGREP_SHELL_FUNCTION_CAVEAT})`},CREDENTIAL_RESOLUTION_HINT=`Rerun /install-bridge to persist the routing credential, set BAPI_API_KEY in the environment, or add it under "bapi:<repo_name>" in ~/.config/bridge/credentials.json. To migrate a key that only lives in .mcp.json / .cursor/mcp.json, run: npx -y ${MCP_PACKAGE_NAME} credentials migrate-agent-config --write-credentials.`,CLAUDE_MCP_SHADOWING_HINT=`Run \`${CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND}\` to clear the '${MCP_SERVER_NAME}' MCP registration in ~/.claude.json (use the matching scope if it is registered at user scope, or under the projects entry for this repository/worktree). This is ADVISORY: workers load MCP servers with --strict-mcp-config from their own worktree registration, so this entry does not reach a worker and does not block a conductor run.`,LIVE_SOURCE_GUARD_HINT=`Point ${CONDUCTOR_LIVE_SOURCE_PATH_ENV} at your live dev server's checkout ONLY when it differs from this conductor base checkout, or dispatch the conductor from a separate clone. To override the guard and dispatch anyway (not recommended), set ${CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV}=1.`}});import path6 from"path";function pathApiForPlatform(platform){return platform==="win32"?path6.win32:path6.posix}var init_worktree_core=__esm({"src/worktree-core.ts"(){"use strict";init_start_tickets_prereqs()}});var init_platform_escaping=__esm({"src/platform-escaping.ts"(){"use strict"}});var init_prompt=__esm({"src/agent-launchers/prompt.ts"(){"use strict"}});async function resolveCommandOnPath(command,envPath,deps){let pathApi=pathApiForPlatform(deps.platform),probe=deps.platform==="win32"?"where.exe":"which",env={...deps.env,PATH:envPath};deps.platform==="win32"&&(env.Path=envPath);let result=await deps.runCommand(probe,[command],{env});if(result.exitCode!==0)return null;let candidate=result.stdout.split(/\r?\n/).map(line=>line.trim()).find(line=>line.length>0);return!candidate||!pathApi.isAbsolute(candidate)?null:pathApi.normalize(candidate)}var init_claude=__esm({"src/agent-launchers/claude.ts"(){"use strict";init_worktree_core();init_platform_escaping();init_prompt()}});var DEFAULT_PROBE_TIMEOUT_MS,init_types=__esm({"src/agent-capabilities/types.ts"(){"use strict";DEFAULT_PROBE_TIMEOUT_MS=9e4}});import{join as join2}from"node:path";function buildHeadlessArgs(agentName,opts){let fmt=opts.outputFormat??"text";if(agentName==="cursor-agent")return["-p","--output-format",fmt,"--trust","--workspace",opts.cwd,opts.prompt];let args=["-p"];return opts.permissionMode==="auto"?args.push("--permission-mode","auto"):opts.permissionMode==="acceptEdits"?args.push("--permission-mode","acceptEdits"):opts.skipPermissions===!0&&args.push("--dangerously-skip-permissions"),typeof opts.model=="string"&&opts.model.trim().length>0&&args.push("--model",opts.model),fmt==="json"?args.push("--output-format","json"):fmt==="stream-json"&&args.push("--output-format","stream-json","--verbose"),args.push(opts.prompt),args}async function createProbeContext(deps,agent,defaultTimeoutMs=DEFAULT_PROBE_TIMEOUT_MS){let launcherDeps={platform:deps.platform,env:deps.env,runCommand:(file,args,options)=>deps.runCommand(file,args,options)},resolvedBinary=await resolveCommandOnPath(agent.command,deps.env.PATH??"",launcherDeps),createdDirs=[],counter=0;return{ctx:{agent,deps,resolvedBinary,marker(name){return`${name}_${deps.uniqueSuffix()}_${counter++}`},async makeTempProject(seed){let dir=await deps.mkdtemp(join2(deps.tmpRoot,"agent-cap-"));return createdDirs.push(dir),seed&&await seed(dir),dir},async runHeadless(opts){let exe=resolvedBinary??agent.command,args=buildHeadlessArgs(agent.name,opts),timeoutMs=opts.timeoutMs??defaultTimeoutMs,controller=new AbortController,timedOut=!1,timer=setTimeout(()=>{timedOut=!0,controller.abort()},timeoutMs),start=deps.now();try{let result=await deps.runCommand(exe,args,{cwd:opts.cwd,env:deps.env,signal:controller.signal}),elapsedMs=deps.now()-start;return timedOut?{kind:"hang",elapsedMs,partialStdout:result.stdout??""}:{kind:"exited",exitCode:result.exitCode,stdout:result.stdout??"",stderr:result.stderr??"",elapsedMs}}catch(err){let elapsedMs=deps.now()-start;return timedOut?{kind:"hang",elapsedMs,partialStdout:""}:{kind:"spawn-error",message:err instanceof Error?err.message:String(err)}}finally{clearTimeout(timer)}}},cleanup:async()=>{for(let dir of createdDirs.splice(0))try{await deps.rm(dir,{recursive:!0,force:!0})}catch{}}}}var init_probe_context=__esm({"src/agent-capabilities/probe-context.ts"(){"use strict";init_claude();init_types()}});import{execFile}from"node:child_process";import{mkdtemp,rm,writeFile,mkdir}from"node:fs/promises";import os3 from"node:os";import{randomBytes}from"node:crypto";function createDefaultAgentCapabilitiesDeps(){let runCommand=(file,args,options)=>new Promise(resolve2=>{execFile(file,args,{cwd:options?.cwd,env:options?.env??process.env,signal:options?.signal,killSignal:"SIGKILL",maxBuffer:67108864,encoding:"utf-8"},(error,stdout,stderr)=>{let exitCode=error&&typeof error.code=="number"?error.code:error?1:0;resolve2({stdout:stdout??"",stderr:stderr??"",exitCode})})});return{platform:process.platform,env:process.env,runCommand,tmpRoot:os3.tmpdir(),mkdtemp:prefix=>mkdtemp(prefix),rm:(target,opts)=>rm(target,opts),writeFile:(target,data)=>writeFile(target,data,"utf-8"),mkdir:(target,opts)=>mkdir(target,opts).then(()=>{}),now:()=>Date.now(),uniqueSuffix:()=>randomBytes(3).toString("hex").toUpperCase()}}var init_default_deps=__esm({"src/agent-capabilities/default-deps.ts"(){"use strict"}});import{join as join3}from"node:path";function truncate(text){let flat=text.replace(/\s+/g," ").trim();return flat.length>EVIDENCE_MAX?`${flat.slice(0,EVIDENCE_MAX)}\u2026`:flat}function nonExitedResult(run){return run.kind==="hang"?{status:"hang",detail:`agent did not exit within the timeout (${run.elapsedMs}ms) \u2014 likely the version-sensitive -p hang`,elapsedMs:run.elapsedMs,evidence:run.partialStdout?truncate(run.partialStdout):void 0}:run.kind==="spawn-error"?{status:"fail",detail:`could not spawn agent: ${run.message}`}:null}function denyHookCommand(){return`printf '%s' '${JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"agent-capability deny-enforcement probe fallback: tool call denied."}})}'`}async function seedDenyTargetFile(ctx,dir,marker){await ctx.deps.writeFile(join3(dir,DENY_TARGET_FILE),`${marker}
|
|
111
|
+
`),repoName,sawRepoName=!1,mcp=[],currentMcp=null;for(let i=0;i<lines.length;i++){let lineNo=i+1,line=lines[i].trim();if(line.length===0||line.startsWith("#"))continue;if(line==="[[mcp]]"){currentMcp={headerLine:lineNo},mcp.push(currentMcp);continue}if(line.startsWith("["))return{ok:!1,kind:"parse-error",error:`Unsupported table header on line ${lineNo}; only [[mcp]] is allowed`};let eq=line.indexOf("=");if(eq===-1)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; expected key = "value"`};let key=line.slice(0,eq).trim(),rawValue=line.slice(eq+1).trim();if(key.length===0)return{ok:!1,kind:"parse-error",error:`Malformed line ${lineNo}; missing key`};if(currentMcp===null){if(key==="repo_name"){if(sawRepoName)return{ok:!1,kind:"parse-error",error:`Duplicate repo_name on line ${lineNo}`};sawRepoName=!0;let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};let validated=validateRepoName(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};repoName=validated.value;continue}return key==="target"?{ok:!1,kind:"parse-error",error:`target on line ${lineNo} must appear inside an [[mcp]] section`}:{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' on line ${lineNo}`}}if(key==="args"){if(currentMcp.args!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate args on line ${lineNo}`};let arr=parseStringArray(rawValue);if(arr===null)return{ok:!1,kind:"parse-error",error:`Expected a string array for 'args' on line ${lineNo}`};currentMcp.args=arr;continue}if(key==="target"||key==="command"||key==="secret_bundle"){let stringValue=parseQuotedString(rawValue);if(stringValue===null)return{ok:!1,kind:"parse-error",error:`Expected a double-quoted string for '${key}' on line ${lineNo}`};if(key==="target"){if(currentMcp.target!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate target on line ${lineNo}`};let validated=validateMcpTarget(stringValue);if(!validated.ok)return{ok:!1,kind:"validation-error",error:validated.error};currentMcp.target=validated.value;continue}if(key==="command"){if(currentMcp.command!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate command on line ${lineNo}`};currentMcp.command=stringValue;continue}if(currentMcp.secretBundle!==void 0)return{ok:!1,kind:"parse-error",error:`Duplicate secret_bundle on line ${lineNo}`};currentMcp.secretBundle=stringValue;continue}return{ok:!1,kind:"parse-error",error:`Unsupported key '${key}' inside [[mcp]] on line ${lineNo}`}}if(!sawRepoName||repoName===void 0)return{ok:!1,kind:"validation-error",error:"Missing required repo_name"};let cleaned=[];for(let entry of mcp){if(entry.target===void 0)return{ok:!1,kind:"validation-error",error:`An [[mcp]] section on line ${entry.headerLine} is missing its target`};if(entry.target!=="bapi"){if(entry.command===void 0||entry.command.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty command`};if(entry.args===void 0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires an args array`};if(entry.secretBundle===void 0||entry.secretBundle.trim().length===0)return{ok:!1,kind:"validation-error",error:`[[mcp]] target '${entry.target}' on line ${entry.headerLine} requires a non-empty secret_bundle`}}let clean={target:entry.target};entry.command!==void 0&&(clean.command=entry.command),entry.args!==void 0&&(clean.args=entry.args),entry.secretBundle!==void 0&&(clean.secretBundle=entry.secretBundle),cleaned.push(clean)}return{ok:!0,manifest:{repoName,mcp:cleaned}}}function bridgeConfigPath(projectRoot){return path5.join(projectRoot,".bridge","config")}async function readBridgeConfig(projectRoot,deps){let filePath=bridgeConfigPath(projectRoot),raw;try{raw=await deps.readFile(filePath)}catch(err){return err&&typeof err=="object"&&err.code==="ENOENT"?{ok:!1,kind:"missing"}:{ok:!1,kind:"parse-error",error:"Unable to read .bridge/config"}}return parseBridgeConfigToml(raw)}var init_bridge_config=__esm({"src/bridge-config.ts"(){"use strict"}});async function resolveStartTicketsRepoName(deps){let fromEnv=deps.env.BAPI_REPO_NAME;if(typeof fromEnv=="string"&&fromEnv.trim().length>0)return fromEnv.trim();try{let result=await readBridgeConfig(deps.cwd,{readFile:deps.readFile});if(result.ok&&result.manifest.repoName)return result.manifest.repoName}catch{}return null}async function resolveRequiredStartTicketsRepoName(deps){let repoName=await resolveStartTicketsRepoName(deps);return repoName?{ok:!0,repoName}:{ok:!1,kind:"repo-missing",error:"could not resolve repo name (set BAPI_REPO_NAME or add a valid .bridge/config)"}}var init_start_tickets_repo=__esm({"src/start-tickets-repo.ts"(){"use strict";init_bridge_config()}});function nonblank(candidate){if(typeof candidate!="string")return;let trimmed=candidate.trim();return trimmed.length>0?trimmed:void 0}function resolveDeclaredRunBaseBranch(policyJson){if(policyJson===null||typeof policyJson!="object"||Array.isArray(policyJson))return;let policy=policyJson;for(let key of POLICY_BASE_BRANCH_KEYS){if(!Object.prototype.hasOwnProperty.call(policy,key))continue;let resolved=nonblank(policy[key]);if(resolved!==void 0)return resolved}}var POLICY_BASE_BRANCH_KEYS,init_run_branch=__esm({"src/conductor/run-branch.ts"(){"use strict";POLICY_BASE_BRANCH_KEYS=["base_branch","baseBranch"]}});var bridge_api_client_exports={};__export(bridge_api_client_exports,{CONDUCTOR_DEFAULT_BASE_URL:()=>CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS:()=>CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES:()=>CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,ConductorBridgeApiError:()=>ConductorBridgeApiError,EPIC_RUN_STATUS_VALUES:()=>EPIC_RUN_STATUS_VALUES,READINESS_FRESH_RECONCILER_COUNT_CAP:()=>READINESS_FRESH_RECONCILER_COUNT_CAP,adoptCurrentHeadAndUnparkTicket:()=>adoptCurrentHeadAndUnparkTicket,advanceEpicTicketStatus:()=>advanceEpicTicketStatus,approveEpicPlan:()=>approveEpicPlan,bootstrapConductorSupervisorDefaults:()=>bootstrapConductorSupervisorDefaults,buildConductorJiraUrl:()=>buildConductorJiraUrl,buildConductorVcsUrl:()=>buildConductorVcsUrl,buildEpicDispatchKey:()=>buildEpicDispatchKey,claimEpicSupervisionLease:()=>claimEpicSupervisionLease,completeMergeChild:()=>completeMergeChild,createEpicRun:()=>createEpicRun,createEpicRunWithDisposition:()=>createEpicRunWithDisposition,createEpicTicketStatus:()=>createEpicTicketStatus,deletePullRequestBranch:()=>deletePullRequestBranch,dispatchRemediation:()=>dispatchRemediation,extractSanitizedErrorDiagnostics:()=>extractSanitizedErrorDiagnostics,fetchActiveEpicRuns:()=>fetchActiveEpicRuns,fetchConductorConfigField:()=>fetchConductorConfigField,fetchConductorJsonPatchWithTimeout:()=>fetchConductorJsonPatchWithTimeout,fetchConductorJsonPostWithTimeout:()=>fetchConductorJsonPostWithTimeout,fetchConductorJsonPutWithTimeout:()=>fetchConductorJsonPutWithTimeout,fetchConductorJsonWithTimeout:()=>fetchConductorJsonWithTimeout,fetchConductorReadiness:()=>fetchConductorReadiness,fetchEffectiveSupervisorConfig:()=>fetchEffectiveSupervisorConfig,fetchEffectiveSupervisorSetup:()=>fetchEffectiveSupervisorSetup,fetchEpicRunState:()=>fetchEpicRunState,fetchExplainRun:()=>fetchExplainRun,fetchParseStatus:()=>fetchParseStatus,fetchPrReviewStatus:()=>fetchPrReviewStatus,fetchShadowDispatchFreshness:()=>fetchShadowDispatchFreshness,getEpicPlan:()=>getEpicPlan,mergeChild:()=>mergeChild,mergePullRequestForGate:()=>mergePullRequestForGate,parseConductorReadinessResponse:()=>parseConductorReadinessResponse,parseConductorSupervisorBootstrapResponse:()=>parseConductorSupervisorBootstrapResponse,pollCiChecksForCommit:()=>pollCiChecksForCommit,readEpicRunCompletionState:()=>readEpicRunCompletionState,reconcileShadowMerge:()=>reconcileShadowMerge,recordEpicDispatch:()=>recordEpicDispatch,remediateEpicTicket:()=>remediateEpicTicket,replaceEpicRunPolicy:()=>replaceEpicRunPolicy,resolveConductorBridgeApiAccess:()=>resolveConductorBridgeApiAccess,safeDiagnosticMessage:()=>safeDiagnosticMessage,scopeReparse:()=>scopeReparse,stopEpicRun:()=>stopEpicRun,storeEpicPlan:()=>storeEpicPlan,transitionEpicDispatch:()=>transitionEpicDispatch,transitionJiraStatus:()=>transitionJiraStatus,triggerRepositoryParse:()=>triggerRepositoryParse,unparkEpicTicket:()=>unparkEpicTicket,updateApprovedPlanNodeTicketSpec:()=>updateApprovedPlanNodeTicketSpec,updateEpicRunStatus:()=>updateEpicRunStatus,validateEpicPlan:()=>validateEpicPlan});import os2 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??os2.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"):[],path15=(parts[0]==="body"?parts.slice(1):parts).slice(0,CONDUCTOR_VALIDATION_LOC_MAX_PARTS).join(".");return path15?`${path15}: ${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={},options={}){try{let parsed=stripWebhookUrlsDeep(await resp.json()),diagnostics=extractSanitizedErrorDiagnostics(parsed);if(options.readErrorField&&!diagnostics.bodyPreview){let detail=parsed&&typeof parsed=="object"&&!Array.isArray(parsed)?parsed.detail:void 0,error=detail&&typeof detail=="object"&&!Array.isArray(detail)?detail.error:void 0;typeof error=="string"&&error.trim()&&(diagnostics.bodyPreview=boundedErrorPreview(error.trim()))}let 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(/\/+$/,""),path15=apiPath.startsWith("/")?apiPath:`/${apiPath}`;return new URL(`${trimmed}${path15}`).toString()}function conductorPostHeaders(access){return{"X-API-Key":access.apiKey,"Content-Type":"application/json"}}async function fetchConductorJsonWithMethodAndTimeout(method,url,headers,body,timeoutMs,fetchImpl,errorOptions={}){let{body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl,errorOptions);return parsed}async function fetchConductorJsonWithMethodStatusAndTimeout(method,url,headers,body,timeoutMs,fetchImpl,errorOptions={}){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,errorOptions);throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status,diagnostics):resp.status>=500?new ConductorBridgeApiError("server",resp.status,diagnostics):new ConductorBridgeApiError("http",resp.status,diagnostics)}try{return{status:resp.status,body:await resp.json()}}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function fetchConductorJsonPostWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("POST",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPatchWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PATCH",url,headers,body,timeoutMs,fetchImpl)}async function fetchConductorJsonPutWithTimeout(url,headers,body,timeoutMs,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("PUT",url,headers,body,timeoutMs,fetchImpl)}async function mergePullRequestForGate(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number),sha=normalizeSha(request.expected_head_sha);if(pr===null||sha===null||!request.action_key||!request.repo_name)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/merge`),body=JSON.stringify({repo_name:request.repo_name,expected_head_sha:sha,gate:request.gate,action_key:request.action_key,...request.gate_event?{gate_event:request.gate_event}:{}});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function remediateEpicTicket(access,request,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(request.pr_number);if(pr===null||!request.epic_run_id||!request.ticket_key||!request.head_sha||!request.idempotency_key)throw new ConductorBridgeApiError("invalid-input");if(requireNonNegativeSafeInteger(request.expected_row_version),request.attempt_kind!=="nudge"&&request.attempt_kind!=="redispatch")throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/remediate`),body=JSON.stringify({repo_name:access.repoName,epic_run_id:request.epic_run_id,ticket_key:request.ticket_key,expected_row_version:request.expected_row_version,head_sha:request.head_sha,idempotency_key:request.idempotency_key,attempt_kind:request.attempt_kind,...request.reason?{reason:request.reason}:{}});try{return{ok:!0,conflict:!1,response:await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===409)return{ok:!0,conflict:!0};throw err}}function requireNonEmptyString(value){if(typeof value!="string"||value.trim().length===0)throw new ConductorBridgeApiError("invalid-input")}function requirePositiveSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<=0)throw new ConductorBridgeApiError("invalid-input")}function requireNonNegativeSafeInteger(value){if(typeof value!="number"||!Number.isSafeInteger(value)||value<0)throw new ConductorBridgeApiError("invalid-input")}function requireNoSlashPathSegment(value){if(value.includes("/"))throw new ConductorBridgeApiError("invalid-input")}function requireEpicTicketStatusValue(value){if(typeof value!="string"||!EPIC_TICKET_STATUS_VALUES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function requireEpicDispatchTransitionStatus(value){if(typeof value!="string"||!EPIC_DISPATCH_TRANSITION_STATUSES.includes(value))throw new ConductorBridgeApiError("invalid-input")}function epicRunApiPath(epicKey){return`${EPIC_RUNS_API_PREFIX}/runs/${encodeURIComponent(epicKey)}`}function epicDispatchTransitionApiPath(dispatchKey,nextStatus){return nextStatus==="run_spawned"?`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/run-spawned`:`/epic-runs/dispatch/${encodeURIComponent(dispatchKey)}/terminal`}function buildEpicDispatchKey(epicKey,ticketKey,planVersion,attempt=0){requireNonEmptyString(epicKey),requireNonEmptyString(ticketKey),requireNonNegativeSafeInteger(planVersion),requireNonNegativeSafeInteger(attempt);let base=`dispatch:${epicKey}:${ticketKey}:${planVersion}`;return attempt>0?`${base}:r${attempt}`:base}function parseEpicSupervisionLeaseResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed,row=p.row;if(p.claimed===!0&&row&&typeof row=="object")return{ok:!0,kind:"acquired-or-renewed",row};if(p.claimed===!1&&p.reason==="lease_held"&&row&&typeof row=="object")return{ok:!1,kind:"held-by-other",reason:"lease_held",row};if(p.claimed===!1&&p.reason==="terminal"&&row&&typeof row=="object")return{ok:!1,kind:"terminal",reason:"terminal",row};throw new ConductorBridgeApiError("server")}async function claimEpicSupervisionLease(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.leaseOwner),requirePositiveSafeInteger(request.ttlSeconds);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/lease/claim`),body=JSON.stringify({repo_name:access.repoName,lease_owner:request.leaseOwner,ttl_seconds:request.ttlSeconds}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseEpicSupervisionLeaseResult(parsed)}async function fetchEpicRunState(access,epicKey,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/state`,{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchExplainRun(access,epicRunId,ticketKey,fetchImpl=globalThis.fetch){requireNonEmptyString(epicRunId);let apiPath=`${epicRunApiPath(epicRunId)}/explain`;ticketKey!==void 0&&(requireNonEmptyString(ticketKey),requireNoSlashPathSegment(ticketKey),apiPath=`${epicRunApiPath(epicRunId)}/tickets/${encodeURIComponent(ticketKey)}/explain`);let url=buildConductorJiraUrl(access.baseUrl,apiPath,{repo_name:access.repoName});return fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function isEpicRunStatus(value){return typeof value=="string"&&EPIC_RUN_STATUS_VALUES.includes(value)}async function readEpicRunCompletionState(access,epicRunId,fetchImpl=globalThis.fetch){if(typeof epicRunId!="string"||epicRunId.trim().length===0)return{ok:!1,reason:"invalid-input"};let parsed;try{parsed=await fetchEpicRunState(access,epicRunId,fetchImpl)}catch(err){return err instanceof ConductorBridgeApiError?err.kind==="http"&&err.status===404?{ok:!1,reason:"not-found"}:err.kind==="unauthorized"?{ok:!1,reason:"unauthorized"}:err.kind==="timeout"?{ok:!1,reason:"timeout"}:err.kind==="server"?{ok:!1,reason:"server"}:err.kind==="network"?{ok:!1,reason:"network"}:err.kind==="invalid-input"?{ok:!1,reason:"invalid-input"}:{ok:!1,reason:"malformed"}:{ok:!1,reason:"network"}}if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return{ok:!1,reason:"malformed"};let epicRun=parsed.epic_run;if(!epicRun||typeof epicRun!="object"||Array.isArray(epicRun))return{ok:!1,reason:"malformed"};let status=epicRun.status;if(!isEpicRunStatus(status))return{ok:!1,reason:"malformed"};let policyJson=epicRun.policy_json,featureBranch=resolveDeclaredRunBaseBranch(policyJson);return{ok:!0,state:featureBranch!==void 0?{status,featureBranch}:{status}}}async function fetchActiveEpicRuns(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`,{repo_name:access.repoName,status:"active",limit:"20"}),parsed=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);if(parsed&&typeof parsed=="object"){let runs=parsed.runs;if(Array.isArray(runs))return runs}return[]}async function createEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`);return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function createEpicRunWithDisposition(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let body={repo_name:access.repoName,epic_key:request.epicKey,status:request.status??"planning",current_plan_version:request.currentPlanVersion??0};request.policyJson!==void 0&&(body.policy_json=request.policyJson),request.budgetWallClockSeconds!==void 0&&(body.budget_wall_clock_seconds=request.budgetWallClockSeconds),request.budgetCostCents!==void 0&&(body.budget_cost_cents=request.budgetCostCents);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/runs`),{status,body:parsed}=await fetchConductorJsonWithMethodStatusAndTimeout("POST",url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return{run:parsed,created:status===201}}async function replaceEpicRunPolicy(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicRunId)),body=JSON.stringify({repo_name:access.repoName,policy_json:request.policyJson});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateEpicRunStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,epicRunApiPath(request.epicKey)),body=JSON.stringify({repo_name:access.repoName,status:request.status,...request.expectedStatus?{expected_status:request.expectedStatus}:{}});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function stopEpicRun(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/stop`),body=JSON.stringify({repo_name:access.repoName,...request.reason!==void 0?{reason:request.reason}:{},...request.expectedGeneration!==void 0?{expected_generation:request.expectedGeneration}:{}});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseAdvanceEpicTicketStatusResult(parsed){if(!parsed||typeof parsed!="object")throw new ConductorBridgeApiError("server");let p=parsed;if(p.ok===!1&&p.kind==="cas-conflict")return{ok:!1,kind:"cas-conflict",...typeof p.current_row_version=="number"?{current_row_version:p.current_row_version}:{},...p.ticket_status&&typeof p.ticket_status=="object"?{ticket_status:p.ticket_status}:{}};if(p.ok===!0&&p.ticket_status&&typeof p.ticket_status=="object")return{ok:!0,ticket_status:p.ticket_status};if("ticket_key"in p&&"status"in p&&"row_version"in p)return{ok:!0,ticket_status:parsed};throw new ConductorBridgeApiError("server")}async function advanceEpicTicketStatus(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion),requireNonNegativeSafeInteger(request.planVersion),requireEpicTicketStatusValue(request.nextStatus),request.dispatchRunId!==void 0&&requireNonEmptyString(request.dispatchRunId);let CAS_ENDPOINT_PATH=`${epicRunApiPath(request.epicKey)}/tickets/${encodeURIComponent(request.ticketKey)}`,url=buildConductorJiraUrl(access.baseUrl,CAS_ENDPOINT_PATH),body=JSON.stringify({repo_name:access.repoName,status:request.nextStatus,plan_version:request.planVersion,expected_row_version:request.expectedRowVersion,...request.dispatchRunId?{dispatch_run_id:request.dispatchRunId}:{}}),parsed=await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseAdvanceEpicTicketStatusResult(parsed)}async function postUnparkLikeRequest(url,headers,body,fetchImpl){try{let parsed=await fetchConductorJsonPostWithTimeout(url,headers,body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseAdvanceEpicTicketStatusResult(parsed)}catch(err){if(err instanceof ConductorBridgeApiError&&err.status===400&&typeof err.currentRowVersion=="number")return parseAdvanceEpicTicketStatusResult({ok:!1,kind:"cas-conflict",current_row_version:err.currentRowVersion});throw err}}async function unparkEpicTicket(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/unpark`),body=JSON.stringify({repo_name:access.repoName,expected_row_version:request.expectedRowVersion,...request.idempotencyKey!==void 0?{idempotency_key:request.idempotencyKey}:{},...request.reason!==void 0?{reason:request.reason}:{}});return postUnparkLikeRequest(url,conductorPostHeaders(access),body,fetchImpl)}async function adoptCurrentHeadAndUnparkTicket(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonNegativeSafeInteger(request.expectedRowVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/adopt-current-head-and-unpark`),body=JSON.stringify({repo_name:access.repoName,expected_row_version:request.expectedRowVersion,...request.idempotencyKey!==void 0?{idempotency_key:request.idempotencyKey}:{},...request.reason!==void 0?{reason:request.reason}:{}});return postUnparkLikeRequest(url,conductorPostHeaders(access),body,fetchImpl)}function parseRepairNullableString(value){return typeof value=="string"?value:null}function parseRepairBase(parsed){if(!parsed||typeof parsed!="object"||Array.isArray(parsed))throw new ConductorBridgeApiError("server");let p=parsed;if(typeof p.epic_run_id!="string"||typeof p.committed!="boolean"||typeof p.event_recorded!="boolean")throw new ConductorBridgeApiError("server");return p}function parseScopeReparseResult(parsed){let p=parseRepairBase(parsed);if(typeof p.scope_id!="string"||typeof p.parse_scheduled!="boolean")throw new ConductorBridgeApiError("server");return{epic_run_id:p.epic_run_id,scope_id:p.scope_id,before:parseRepairNullableString(p.before),after:parseRepairNullableString(p.after),committed:p.committed,event_recorded:p.event_recorded,outcome:typeof p.outcome=="string"?p.outcome:"",parse_scheduled:p.parse_scheduled}}function parseDispatchRemediationResult(parsed){let p=parseRepairBase(parsed);if(typeof p.ticket_key!="string")throw new ConductorBridgeApiError("server");let jobId=p.job_id;return{epic_run_id:p.epic_run_id,ticket_key:p.ticket_key,before:parseRepairNullableString(p.before),after:parseRepairNullableString(p.after),committed:p.committed,event_recorded:p.event_recorded,job_type:typeof p.job_type=="string"?p.job_type:"",job_id:typeof jobId=="number"&&Number.isSafeInteger(jobId)?jobId:null}}function parseMergeChildRouteResponse(parsed){let p=parseRepairBase(parsed),prNumber=p.pr_number;if(typeof prNumber!="number"||!Number.isSafeInteger(prNumber)||prNumber<=0)throw new ConductorBridgeApiError("server");let localExecution=null,local=p.local_execution;if(local&&typeof local=="object"&&!Array.isArray(local)){let l=local,sha=normalizeSha(l.expected_head_sha);if(sha===null)throw new ConductorBridgeApiError("server");localExecution={expected_head_sha:sha,merge_method:parseRepairNullableString(l.merge_method)}}return{epic_run_id:p.epic_run_id,pr_number:prNumber,ticket_key:typeof p.ticket_key=="string"?p.ticket_key:"",before:parseRepairNullableString(p.before),after:parseRepairNullableString(p.after),committed:p.committed,event_recorded:p.event_recorded,reason:parseRepairNullableString(p.reason),local_execution:localExecution}}async function postRepairRequest(access,apiPath,body,fetchImpl){return fetchConductorJsonWithMethodAndTimeout("POST",buildConductorJiraUrl(access.baseUrl,apiPath),conductorPostHeaders(access),JSON.stringify({repo_name:access.repoName,...body}),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl,{readErrorField:!0})}async function scopeReparse(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.scopeId);let parsed=await postRepairRequest(access,`${epicRunApiPath(request.epicRunId)}/scope-reparse`,{scope_id:request.scopeId},fetchImpl);return parseScopeReparseResult(parsed)}async function dispatchRemediation(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.context);let parsed=await postRepairRequest(access,`${epicRunApiPath(request.epicRunId)}/tickets/${encodeURIComponent(request.ticketKey)}/dispatch-remediation`,{context:request.context},fetchImpl);return parseDispatchRemediationResult(parsed)}async function mergeChild(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicRunId),requirePositiveSafeInteger(request.prNumber);let parsed=await postRepairRequest(access,`${epicRunApiPath(request.epicRunId)}/merge-child`,{pr_number:request.prNumber},fetchImpl);return parseMergeChildRouteResponse(parsed)}async function completeMergeChild(access,request,fetchImpl=globalThis.fetch){if(requireNonEmptyString(request.epicRunId),requirePositiveSafeInteger(request.prNumber),!["merged","already_merged","failed"].includes(request.result))throw new ConductorBridgeApiError("invalid-input");let parsed=await postRepairRequest(access,`${epicRunApiPath(request.epicRunId)}/merge-child/complete`,{pr_number:request.prNumber,result:request.result,...request.reason!==void 0?{reason:request.reason}:{}},fetchImpl);return parseMergeChildRouteResponse(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 path15=epicDispatchTransitionApiPath(request.dispatchKey,request.nextStatus),url=buildConductorJiraUrl(access.baseUrl,path15),body=request.nextStatus==="run_spawned"?JSON.stringify({repo_name:access.repoName,run_id:request.runId}):JSON.stringify({repo_name:access.repoName});return await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseShadowMergeReconcileResult(parsed){let obj=parsed??{};return{applies:obj.applies===!0,scheduled:obj.scheduled===!0,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:"unknown",shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,requiredCommitSha:typeof obj.required_commit_sha=="string"?obj.required_commit_sha:null,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null}}function parseShadowDispatchFreshnessResult(parsed){let obj=parsed??{},rawVerdict=typeof obj.verdict=="string"?obj.verdict:"",verdict=SHADOW_FRESHNESS_VERDICTS.has(rawVerdict)?rawVerdict:"stale";return{verdict,reasonCode:typeof obj.reason_code=="string"?obj.reason_code:verdict,lifecycleState:typeof obj.lifecycle_state=="string"?obj.lifecycle_state:null,indexedCommitSha:typeof obj.indexed_commit_sha=="string"?obj.indexed_commit_sha:null,shadowRepoName:typeof obj.shadow_repo_name=="string"?obj.shadow_repo_name:null,lastError:typeof obj.last_error=="string"?obj.last_error:null,deadlineExpired:obj.deadline_expired===!0,blockedAdvanceReason:typeof obj.blocked_advance_reason=="string"&&obj.blocked_advance_reason.length>0?obj.blocked_advance_reason:null}}async function reconcileShadowMerge(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/shadow/merge-reconcile`),body=JSON.stringify({repo_name:access.repoName,merged_ticket_key:request.mergedTicketKey??null}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseShadowMergeReconcileResult(parsed)}async function fetchShadowDispatchFreshness(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNoSlashPathSegment(request.ticketKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/tickets/${encodeURIComponent(request.ticketKey)}/shadow-freshness`),body=JSON.stringify({repo_name:access.repoName}),parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseShadowDispatchFreshnessResult(parsed)}async function validateEpicPlan(access,request,fetchImpl=globalThis.fetch){requirePositiveSafeInteger(request.planVersion);let blobVersion=request.planBlob.plan_version;if(blobVersion!==void 0&&blobVersion!==request.planVersion)throw new ConductorValidationError(`planVersion mismatch: request.planVersion=${request.planVersion} but planBlob.plan_version=${blobVersion}`);let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/plan/validate`),body={repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob};request.epicKey!==void 0&&(body.epic_key=request.epicKey),request.trackedPaths!==void 0&&(body.tracked_paths=request.trackedPaths);let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(body),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseValidateEpicPlanResult(parsed)}function parseValidateEpicPlanResult(parsed){if(!parsed||typeof parsed!="object"||Array.isArray(parsed))throw new ConductorBridgeApiError("server");let p=parsed,planHash=p.plan_hash,serializationEnabled=p.serialization_enabled,insertedEdges=p.inserted_edges,valid=p.valid;if(typeof valid!="boolean"||typeof planHash!="string"||planHash.trim()===""||typeof serializationEnabled!="boolean"||typeof insertedEdges!="number"||!Number.isSafeInteger(insertedEdges)||insertedEdges<0)throw new ConductorBridgeApiError("server");let rejections=parsePlanLintRejections(p.rejections),notices=parsePlanLintNotices(p.notices);if(!valid&&rejections.length===0)throw new ConductorBridgeApiError("server");return{valid,rejections,notices,evaluationComplete:typeof p.evaluation_complete=="boolean"?p.evaluation_complete:!0,planHash,serializationEnabled,insertedEdges,overlappingPairsFound:safeCount(p.overlapping_pairs_found),undeclaredNodes:safeCount(p.undeclared_nodes),undeclaredPairsSkipped:safeCount(p.undeclared_pairs_skipped),coverageScope:typeof p.coverage_scope=="string"&&p.coverage_scope.trim()!==""?p.coverage_scope:"unreported"}}function parsePlanLintRejections(value){if(!Array.isArray(value))return[];let out=[];for(let raw of value){if(!raw||typeof raw!="object"||Array.isArray(raw))continue;let entry=raw,reasonCode=entry.reason_code,explanation=entry.explanation;if(typeof reasonCode!="string"||reasonCode.trim()===""||typeof explanation!="string"||explanation.trim()==="")continue;let rejection={reasonCode,explanation,ticketKeys:safeStringArray(entry.ticket_keys)};typeof entry.path=="string"&&entry.path!==""&&(rejection.path=entry.path),typeof entry.migration_id=="string"&&entry.migration_id!==""&&(rejection.migrationId=entry.migration_id),out.push(rejection)}return out}function parsePlanLintNotices(value){if(!Array.isArray(value))return[];let out=[];for(let raw of value){if(!raw||typeof raw!="object"||Array.isArray(raw))continue;let entry=raw,noticeCode=entry.notice_code,explanation=entry.explanation;typeof noticeCode!="string"||noticeCode.trim()===""||typeof explanation!="string"||explanation.trim()===""||out.push({noticeCode,explanation,ticketKeys:safeStringArray(entry.ticket_keys),paths:safeStringArray(entry.paths)})}return out}function safeStringArray(value){return Array.isArray(value)?value.filter(v=>typeof v=="string"&&v!==""):[]}function safeCount(value){return typeof value=="number"&&Number.isSafeInteger(value)&&value>=0?value:0}async function storeEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion),requireNonEmptyString(request.planHash);let blobVersion=request.planBlob.plan_version;if(blobVersion!==void 0&&blobVersion!==request.planVersion)throw new ConductorValidationError(`planVersion mismatch: request.planVersion=${request.planVersion} but planBlob.plan_version=${blobVersion}`);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan`),storeBody={repo_name:access.repoName,plan_version:request.planVersion,plan_blob:request.planBlob,plan_hash:request.planHash};request.trackedPaths!==void 0&&(storeBody.tracked_paths=request.trackedPaths);let body=JSON.stringify(storeBody);return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function updateApprovedPlanNodeTicketSpec(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requireNonEmptyString(request.ticketKey),requireNonEmptyString(request.expectedPlanHash),requireNonEmptyString(request.ticketSpec);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/plan/nodes/${encodeURIComponent(request.ticketKey)}/ticket-spec`),body=JSON.stringify({repo_name:access.repoName,expected_plan_hash:request.expectedPlanHash,ticket_spec:request.ticketSpec});return await fetchConductorJsonPatchWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}function parseApproveEpicPlanSuccess(parsed){let record=parsed??{},result={ok:!0,plan_hash:record.plan_hash},prov=record.feature_branch_provisioning;if(prov&&typeof prov=="object"&&!Array.isArray(prov)){let p=prov;(p.status==="created"||p.status==="already_exists")&&typeof p.feature_branch=="string"&&typeof p.source_branch=="string"&&typeof p.source_sha=="string"&&typeof p.remote_head_sha=="string"&&(result.featureBranchProvisioning={status:p.status,feature_branch:p.feature_branch,source_branch:p.source_branch,source_sha:p.source_sha,remote_head_sha:p.remote_head_sha})}return result}async function approveEpicPlan(access,request,fetchImpl=globalThis.fetch){requireNonEmptyString(request.epicKey),requirePositiveSafeInteger(request.planVersion);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(request.epicKey)}/approve-plan`),body=JSON.stringify({repo_name:access.repoName,plan_version:request.planVersion});try{let parsed=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseApproveEpicPlanSuccess(parsed)}catch(error){if(error instanceof ConductorBridgeApiError&&error.status===409){let preview=error.bodyPreview??"";return/multiple active runs/i.test(preview)?{ok:!1,kind:"conflict",reason:"multiple_active_runs"}:{ok:!1,kind:"conflict",reason:"superseded"}}throw error}}async function getEpicPlan(access,epicKey,planVersion,fetchImpl=globalThis.fetch){requireNonEmptyString(epicKey);let url=buildConductorJiraUrl(access.baseUrl,`${epicRunApiPath(epicKey)}/plan`,{repo_name:access.repoName,plan_version:String(planVersion)});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function fetchParseStatus(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-status",{repo_name:access.repoName});return await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function triggerRepositoryParse(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,"/parse-repository"),body=JSON.stringify({repo_name:access.repoName});return fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl)}async function deletePullRequestBranch(access,prNumber,expectedHeadSha,fetchImpl=globalThis.fetch){let pr=normalizePrNumber(prNumber);if(pr===null)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorVcsUrl(access.baseUrl,`/vcs/pull-requests/${pr}/branch?repo_name=${encodeURIComponent(access.repoName)}&expected_head_sha=${encodeURIComponent(expectedHeadSha)}`),controller=new AbortController,timer=setTimeout(()=>controller.abort(),CONDUCTOR_FETCH_TIMEOUT_MS);try{let resp;try{resp=await fetchImpl(url,{method:"DELETE",headers:{"X-API-Key":access.apiKey},body:"",signal:controller.signal})}catch{throw new ConductorBridgeApiError(controller.signal.aborted?"timeout":"network")}if(resp.status===404)return{deleted:!1,branch:null,reason:"not_found"};if(!resp.ok)throw resp.status===401||resp.status===403?new ConductorBridgeApiError("unauthorized",resp.status):resp.status>=500?new ConductorBridgeApiError("server",resp.status):new ConductorBridgeApiError("http",resp.status);try{return await resp.json()}catch{throw new ConductorBridgeApiError("network")}}finally{clearTimeout(timer)}}async function transitionJiraStatus(access,ticketNumber,targetStatus="auto",fetchImpl=globalThis.fetch){if(!ticketNumber)throw new ConductorBridgeApiError("invalid-input");let url=buildConductorJiraUrl(access.baseUrl,`/tickets/${encodeURIComponent(ticketNumber)}/jira-status`),body=JSON.stringify({repo_name:access.repoName,target_status:targetStatus});try{return await fetchConductorJsonPutWithTimeout(url,conductorPostHeaders(access),body,CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl),{status:"transitioned"}}catch(err){if(err instanceof ConductorBridgeApiError&&err.kind==="http"&&err.status===400)return{status:"skipped"};throw err}}function readinessShapeError(){return new ConductorBridgeApiError("invalid-input",void 0,{errorCode:"READINESS_SHAPE_INVALID"})}function requireObject(value){if(typeof value!="object"||value===null||Array.isArray(value))throw readinessShapeError();return value}function requireBool(o,key){let v=o[key];if(typeof v!="boolean")throw readinessShapeError();return v}function requireInt(o,key){let v=o[key];if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableInt(o,key){let v=o[key];if(v==null)return null;if(typeof v!="number"||!Number.isInteger(v))throw readinessShapeError();return v}function requireNullableString(o,key){let v=o[key];if(v==null)return null;if(typeof v!="string")throw readinessShapeError();return v}function requireNullableBool(o,key){let v=o[key];if(v==null)return null;if(typeof v!="boolean")throw readinessShapeError();return v}function parseReviewPolicyAlignment(o){let raw=o.review_policy_alignment;if(raw==null)return null;let a=requireObject(raw),explanation=a.explanation;if(typeof explanation!="string")throw readinessShapeError();return{status:requireEnum(a,"status",CONDUCTOR_REVIEW_ALIGNMENT_STATUSES),repo_review_signal:requireNullableString(a,"repo_review_signal"),done_gate_review_signal:requireNullableString(a,"done_gate_review_signal"),explanation}}function requireEnum(o,key,allowed){let v=o[key];if(typeof v!="string"||!allowed.has(v))throw readinessShapeError();return v}function parseConductorReadinessResponse(body){let root=requireObject(body),repoName=root.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let sup=requireObject(root.supervisor),gh=requireObject(root.github),rec=requireObject(root.reconciler),exec=requireObject(root.executor),thr=requireObject(root.thresholds);return{repo_name:repoName,supervisor:{setup_present:requireBool(sup,"setup_present"),setup_source:requireEnum(sup,"setup_source",READINESS_SOURCES),setup_created_at:requireNullableString(sup,"setup_created_at"),setup_updated_at:requireNullableString(sup,"setup_updated_at"),config_present:requireBool(sup,"config_present"),config_source:requireEnum(sup,"config_source",READINESS_SOURCES),config_created_at:requireNullableString(sup,"config_created_at"),config_updated_at:requireNullableString(sup,"config_updated_at"),required_checks_count:requireInt(sup,"required_checks_count"),required_checks_empty:requireBool(sup,"required_checks_empty"),auto_merge_enabled:requireBool(sup,"auto_merge_enabled"),merge_approval_required_set:requireBool(sup,"merge_approval_required_set"),review_policy_alignment:parseReviewPolicyAlignment(sup),review_policy_present:sup.review_policy_present===!0},github:{credentials_readable:requireBool(gh,"credentials_readable"),owner_resolved:requireBool(gh,"owner_resolved"),repo_id_resolved:requireBool(gh,"repo_id_resolved"),installation_id_resolved:requireBool(gh,"installation_id_resolved"),credentials_complete:requireBool(gh,"credentials_complete"),actions_probe_succeeded:requireBool(gh,"actions_probe_succeeded"),actions_permission_present:requireBool(gh,"actions_permission_present"),actions_permission_level:requireEnum(gh,"actions_permission_level",ACTIONS_LEVELS),actions_write:requireBool(gh,"actions_write")},reconciler:{liveness_readable:requireBool(rec,"liveness_readable"),last_tick_at:requireNullableString(rec,"last_tick_at"),last_tick_age_seconds:requireNullableInt(rec,"last_tick_age_seconds"),stale:requireBool(rec,"stale"),active_run_count:requireInt(rec,"active_run_count"),expired_lease_count:requireInt(rec,"expired_lease_count")},executor:{liveness_readable:requireBool(exec,"liveness_readable"),last_seen_at:requireNullableString(exec,"last_seen_at"),last_seen_age_seconds:requireNullableInt(exec,"last_seen_age_seconds"),ready:requireNullableBool(exec,"ready")},thresholds:{reconciler_stale_after_seconds:requireInt(thr,"reconciler_stale_after_seconds"),executor_stale_after_seconds:requireInt(thr,"executor_stale_after_seconds")},review_workflow:parseReviewWorkflow(root),conductor_ci_workflow:parseConductorCiWorkflow(root),unattended:parseUnattended(root),bring_up:parseBringUp(root)}}function parseBringUp(body){let raw=body.bring_up;if(raw==null)return null;let o=requireObject(raw),freshCount=requireInt(o,"fresh_reconciler_count");if(freshCount<0||freshCount>READINESS_FRESH_RECONCILER_COUNT_CAP)throw readinessShapeError();return{migration_readable:requireBool(o,"migration_readable"),database_migration_current:requireBool(o,"database_migration_current"),heartbeat_readable:requireBool(o,"heartbeat_readable"),worker_present:requireBool(o,"worker_present"),fresh_reconciler_count:freshCount,single_transition_authority:requireBool(o,"single_transition_authority")}}function parseReviewWorkflow(body){let raw=body.review_workflow;if(raw==null)return null;let o=requireObject(raw);return{probe_succeeded:requireBool(o,"probe_succeeded"),workflow_present:requireBool(o,"workflow_present"),emits_run_id:requireBool(o,"emits_run_id"),emits_reviewed_sha:requireBool(o,"emits_reviewed_sha")}}function parseConductorCiWorkflow(body){let raw=body.conductor_ci_workflow;if(raw==null)return null;let o=requireObject(raw);return{probe_succeeded:requireBool(o,"probe_succeeded"),workflow_present:requireBool(o,"workflow_present"),migration_guard_present:requireBool(o,"migration_guard_present")}}function parseUnattended(body){let raw=body.unattended;if(raw==null)return null;let o=requireObject(raw);return{conductor_allowed:requireBool(o,"conductor_allowed"),notify_webhook_default_declared:requireBool(o,"notify_webhook_default_declared"),notify_webhook_default_verified:o.notify_webhook_default_verified===void 0?null:requireNullableBool(o,"notify_webhook_default_verified"),repository_readiness_confirmed:requireBool(o,"repository_readiness_confirmed")}}async function fetchConductorReadiness(access,fetchImpl=globalThis.fetch){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/conductor-readiness`,{repo_name:access.repoName}),body=await fetchConductorJsonWithTimeout(url,conductorGetHeaders(access),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorReadinessResponse(body)}function parseConductorSupervisorBootstrapResponse(body){let o=requireObject(body),repoName=o.repo_name;if(typeof repoName!="string"||repoName.length===0)throw readinessShapeError();let names=o.audited_field_names;if(!Array.isArray(names)||names.some(n=>typeof n!="string"))throw readinessShapeError();return{repo_name:repoName,setup_written:requireBool(o,"setup_written"),config_written:requireBool(o,"config_written"),setup_source:requireEnum(o,"setup_source",READINESS_SOURCES),config_source:requireEnum(o,"config_source",READINESS_SOURCES),setup_created_at:requireNullableString(o,"setup_created_at"),setup_updated_at:requireNullableString(o,"setup_updated_at"),config_created_at:requireNullableString(o,"config_created_at"),config_updated_at:requireNullableString(o,"config_updated_at"),required_checks_count:requireInt(o,"required_checks_count"),audited_field_names:names}}async function bootstrapConductorSupervisorDefaults(access,request,fetchImpl){let url=buildConductorJiraUrl(access.baseUrl,`${EPIC_RUNS_API_PREFIX}/supervisor-bootstrap`,{repo_name:access.repoName}),body=await fetchConductorJsonPostWithTimeout(url,conductorPostHeaders(access),JSON.stringify(request),CONDUCTOR_FETCH_TIMEOUT_MS,fetchImpl);return parseConductorSupervisorBootstrapResponse(body)}var CONDUCTOR_DEFAULT_BASE_URL,CONDUCTOR_FETCH_TIMEOUT_MS,CONDUCTOR_BRIDGE_API_ERROR_KINDS,CONDUCTOR_ERROR_PREVIEW_MAX,CONDUCTOR_VALIDATION_LOC_MAX_PARTS,ConductorBridgeApiError,EPIC_TICKET_STATUS_VALUES,EPIC_DISPATCH_TRANSITION_STATUSES,EPIC_RUNS_API_PREFIX,EPIC_RUN_STATUS_VALUES,SHADOW_FRESHNESS_VERDICTS,CONDUCTOR_REVIEW_ALIGNMENT_STATUSES,READINESS_FRESH_RECONCILER_COUNT_CAP,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();init_run_branch();CONDUCTOR_DEFAULT_BASE_URL="https://bridgegpt-api.com",CONDUCTOR_FETCH_TIMEOUT_MS=3e4;CONDUCTOR_BRIDGE_API_ERROR_KINDS=["invalid-input","network","timeout","unauthorized","server","http"],CONDUCTOR_ERROR_PREVIEW_MAX=200;CONDUCTOR_VALIDATION_LOC_MAX_PARTS=8;ConductorBridgeApiError=class extends Error{kind;status;errorCode;bodyPreview;currentRowVersion;constructor(kindOrMessage,status,diagnostics){let isKnownKind=CONDUCTOR_BRIDGE_API_ERROR_KINDS.includes(kindOrMessage),errorCode=diagnostics?.errorCode,bodyPreview=diagnostics?.bodyPreview;if(isKnownKind){let parts=[`Conductor Bridge API request failed (${kindOrMessage}${typeof status=="number"?`, status ${status}`:""})`];errorCode&&parts.push(`code=${errorCode}`),bodyPreview&&parts.push(bodyPreview),super(parts.join(": "))}else super(kindOrMessage);this.name="ConductorBridgeApiError",this.kind=isKnownKind?kindOrMessage:"http",typeof status=="number"&&(this.status=status),errorCode&&(this.errorCode=errorCode),bodyPreview&&(this.bodyPreview=bodyPreview),typeof diagnostics?.currentRowVersion=="number"&&(this.currentRowVersion=diagnostics.currentRowVersion)}};EPIC_TICKET_STATUS_VALUES=["planned","ready","dispatched","running","blocked","abandoned","done","ready_for_review","reviewing","parse_pending"];EPIC_DISPATCH_TRANSITION_STATUSES=["run_spawned","terminal"];EPIC_RUNS_API_PREFIX="/epic-runs";EPIC_RUN_STATUS_VALUES=["planning","pending_approval","active","blocked","abandoned","done"];SHADOW_FRESHNESS_VERDICTS=new Set(["not_applicable","covered","stale","failed"]);CONDUCTOR_REVIEW_ALIGNMENT_STATUSES=new Set(["aligned","divergent","not_configured","invalid"]),READINESS_FRESH_RECONCILER_COUNT_CAP=2,READINESS_SOURCES=new Set(["epic","project_default","none"]),ACTIONS_LEVELS=new Set(["write","read","none","unknown"])}});function listAgentNames(){return Object.keys(AGENT_REGISTRY)}function isAgentName(value){return listAgentNames().includes(value)}function resolveAgentSpec(name){let resolved=name??DEFAULT_AGENT_NAME;return isAgentName(resolved)?AGENT_REGISTRY[resolved]:null}var AGENT_REGISTRY,DEFAULT_AGENT_NAME,init_agent_registry=__esm({"src/agent-registry.ts"(){"use strict";AGENT_REGISTRY={claude:{name:"claude",command:"claude",promptArgStyle:"positional",installHint:{darwin:"npm install -g @anthropic-ai/claude-code",linux:"npm install -g @anthropic-ai/claude-code",win32:"npm install -g @anthropic-ai/claude-code"},authNote:"Claude Code authenticates interactively on first run \u2014 follow its login/auth prompt if asked.",supportsModelOverride:!0,modelFlag:"--model",tierModels:{cheap:"sonnet",basic:"sonnet",premium:"opus"},staticModelAliasAllowlist:["haiku","sonnet","opus"],executorAdapter:{adapterId:"claude-reference",strategyId:"claude-strict-mcp-v1",adapterVersion:"1.0.0",supportedPlatforms:["darwin","linux"],capabilityStrategyIds:{mcpScoping:"strict-mcp-config",mcpInitParsing:"claude-system-init",authFailureDetection:"claude-stream-json-result",denyEnforcement:"claude-settings-deny",redaction:"claude-env-name-redaction",lifecycle:"claude-no-lifecycle"},managedCarriers:[],passthroughs:[{passthroughId:"claude-code-oauth-token",envName:"CLAUDE_CODE_OAUTH_TOKEN",billingClass:"subscription",ownership:"operator-owned",rule:"forward-when-present"}]}},"cursor-agent":{name:"cursor-agent",command:"cursor-agent",promptArgStyle:"positional",installHint:{darwin:"curl https://cursor.com/install -fsSL | bash",linux:"curl https://cursor.com/install -fsSL | bash",win32:"irm 'https://cursor.com/install?win32=true' | iex"},authNote:"Run cursor-agent login to authenticate; doctor checks PATH presence only, not login state.",supportsModelOverride:!0,modelFlag:"--model",tierModels:{cheap:"auto",basic:"claude-4.6-sonnet-medium",premium:"claude-opus-4-8-thinking-high"}},codex:{name:"codex",command:"codex",promptArgStyle:"positional",installHint:{darwin:"npm install -g @openai/codex",linux:"npm install -g @openai/codex",win32:"npm install -g @openai/codex"},authNote:"Codex authenticates interactively on first run \u2014 follow its login prompt if asked.",supportsModelOverride:!0,modelFlag:"--model"}},DEFAULT_AGENT_NAME="claude"}});var init_codex_home=__esm({"src/codex-home.ts"(){"use strict"}});function joinPath(base,rel){let trimmedBase=base.endsWith("/")?base.slice(0,-1):base,trimmedRel=rel.startsWith("/")?rel.slice(1):rel;return`${trimmedBase}/${trimmedRel}`}function hostAdapterForTarget(target){return HOST_ADAPTERS[target.hostKind]}function allHostTargets(){return HOST_PLATFORM_ORDER.map(id=>MCP_HOST_TARGETS[id])}function getProjectJsonTargets(){return allHostTargets().filter(t=>t.scope==="project"&&hostAdapterForTarget(t).format==="json")}var HOST_ADAPTERS,MCP_HOST_TARGETS,HOST_PLATFORM_ORDER,init_mcp_host_targets=__esm({"src/mcp-host-targets.ts"(){"use strict";init_codex_home();HOST_ADAPTERS={"claude-code-json":{format:"json",topLevelKey:"mcpServers",transportType:void 0},"cursor-json":{format:"json",topLevelKey:"mcpServers",transportType:"stdio"},"vscode-json":{format:"json",topLevelKey:"servers",transportType:"stdio"},"codex-toml":{format:"toml",topLevelKey:"mcp_servers",transportType:void 0}};MCP_HOST_TARGETS={"claude-code":{id:"claude-code",label:"Claude Code",scope:"project",relPath:".mcp.json",displayPath:".mcp.json",hostKind:"claude-code-json",vendorCli:{bin:"claude",kind:"claude-add-json"},launchAgent:"claude",capabilities:{mcpConfiguration:!0,customCommands:!0,worktreeProvisioning:!0,sessionSpawning:!0},writeStrategy:"vendor-first",detect:()=>!0},cursor:{id:"cursor",label:"Cursor",scope:"project",relPath:".cursor/mcp.json",displayPath:".cursor/mcp.json",hostKind:"cursor-json",launchAgent:"cursor-agent",capabilities:{mcpConfiguration:!0,customCommands:!0,worktreeProvisioning:!0,sessionSpawning:!0},writeStrategy:"direct",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".cursor"))||typeof ctx.env.CURSOR_TRACE_DIR=="string"&&ctx.env.CURSOR_TRACE_DIR.length>0},"copilot-vscode":{id:"copilot-vscode",label:"GitHub Copilot",scope:"project",relPath:".vscode/mcp.json",displayPath:".vscode/mcp.json",hostKind:"vscode-json",capabilities:{mcpConfiguration:!0,customCommands:!0,worktreeProvisioning:!1,sessionSpawning:!1},writeStrategy:"direct",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".vscode"))},codex:{id:"codex",label:"OpenAI Codex",scope:"global",absPathResolver:homedir=>joinPath(homedir,".codex/config.toml"),displayPath:"~/.codex/config.toml",hostKind:"codex-toml",vendorCli:{bin:"codex",kind:"codex-add"},launchAgent:"codex",capabilities:{mcpConfiguration:!0,customCommands:!0,worktreeProvisioning:!0,sessionSpawning:!0},writeStrategy:"vendor-first",detect:ctx=>ctx.exists(joinPath(ctx.homedir,".codex"))},windsurf:{id:"windsurf",label:"Windsurf",scope:"global",absPathResolver:homedir=>joinPath(homedir,".codeium/windsurf/mcp_config.json"),displayPath:"~/.codeium/windsurf/mcp_config.json",hostKind:"claude-code-json",capabilities:{mcpConfiguration:!0,customCommands:!1,worktreeProvisioning:!1,sessionSpawning:!1},writeStrategy:"manual-instructions",detect:ctx=>ctx.exists(joinPath(ctx.cwd,".windsurf"))||ctx.exists(joinPath(ctx.cwd,".windsurfrules"))}},HOST_PLATFORM_ORDER=["claude-code","cursor","copilot-vscode","codex","windsurf"]}});var LAUNCHER_CONFIG_TARGETS,DUPLICATE_REGISTRATION_GUIDANCE,REASON_TEXT,init_launcher_config_inspection=__esm({"src/launcher-config-inspection.ts"(){"use strict";init_mcp_host_targets();init_mcp_identity();LAUNCHER_CONFIG_TARGETS=getProjectJsonTargets().map(target=>({relPath:target.relPath,topLevelKey:hostAdapterForTarget(target).topLevelKey})),DUPLICATE_REGISTRATION_GUIDANCE=`duplicate Bridge registrations: this config carries both \`${MCP_SERVER_NAME}\` and \`${LEGACY_SERVER_NAMES.join("`, `")}\`. Confirm which registration you want to keep, then remove the unintended entry manually. Bridge will not choose for you.`,REASON_TEXT={"file-unreadable":"the file exists but could not be read","invalid-json":"the file is not valid JSON","root-not-object":"the JSON root is not an object","servers-not-object":"the servers section is not an object","entry-not-object":"the Bridge entry is not an object","no-package-token":`the Bridge launcher has no recognizable ${MCP_PACKAGE_NAME} token`,"version-range":"the launcher pin is a version range, which an automated repin must not rewrite","non-release-specifier":"the launcher pin is a dist-tag or channel, not an exact release","malformed-version":"the launcher pin is not a valid MAJOR.MINOR.PATCH release","pinned-ahead-of-target":"the launcher pin is newer than the target version and must not be downgraded","duplicate-registration":DUPLICATE_REGISTRATION_GUIDANCE}}});var init_mcp_registration_doctor=__esm({"src/mcp-registration-doctor.ts"(){"use strict";init_mcp_host_targets();init_mcp_identity();init_launcher_config_inspection()}});var init_commands_generated=__esm({"src/commands.generated.ts"(){"use strict"}});var init_command_assets_doctor=__esm({"src/command-assets-doctor.ts"(){"use strict";init_commands_generated()}});function summarizeClaudeReviewWorkflowDrift(classification){let{baseRef,defaultRef,workflowPath}=classification;return classification.state==="aligned"?`'${baseRef}' matches '${defaultRef}' for ${workflowPath}`:classification.state==="unverified"?`comparison unavailable (${classification.reason}) \u2014 advisory check failed open, ${workflowPath} lineage unknown`:`WARNING: '${baseRef}' carries a stale ${workflowPath} (differs from '${defaultRef}') \u2014 Claude review cannot run for pull requests based on it; reconcile '${baseRef}' with '${defaultRef}'`}var CLAUDE_REVIEW_WORKFLOW_RELPATH,CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION,init_claude_review_workflow_drift=__esm({"src/claude-review-workflow-drift.ts"(){"use strict";CLAUDE_REVIEW_WORKFLOW_RELPATH=".github/workflows/claude-review.yml";CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION=`Reconcile the base branch with the repository default branch \u2014 merge the default branch in, or sync ${CLAUDE_REVIEW_WORKFLOW_RELPATH} together with tests/pytest/commands/test_claude_review_workflow_prompt.py. See docs/claude/runbooks/claude-review-base-branch-drift.md.`}});var init_claude_review_workflow_drift_probe=__esm({"src/claude-review-workflow-drift-probe.ts"(){"use strict";init_claude_review_workflow_drift()}});var init_third_party_mcp_targets=__esm({"src/third-party-mcp-targets.ts"(){"use strict";init_credential_store()}});var init_mcp_provisioning=__esm({"src/mcp-provisioning.ts"(){"use strict";init_bridge_config();init_third_party_mcp_targets();init_mcp_server_invocation();init_mcp_host_targets();init_mcp_identity()}});function claudeMcpShadowingRemediationCommand(registrationKey){return`claude mcp remove ${registrationKey} -s local`}var CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV,CLAUDE_MCP_SHADOWING_OVERRIDE_WARNING,CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND,init_claude_user_config_doctor=__esm({"src/claude-user-config-doctor.ts"(){"use strict";init_mcp_registration_doctor();init_mcp_provisioning();init_mcp_identity();init_launcher_config_inspection();CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV="BAPI_CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING",CLAUDE_MCP_SHADOWING_OVERRIDE_WARNING=`Proceeding anyway because ${CONDUCTOR_ALLOW_CLAUDE_MCP_SHADOWING_ENV} is set`;CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND=claudeMcpShadowingRemediationCommand(MCP_SERVER_NAME)}});var START_TICKETS_DOCTOR_COMMAND,CONDUCTOR_LIVE_SOURCE_PATH_ENV,CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV,GIT_INSTALL_HINTS,REVIEW_TICKETS_GIT_INSTALL_HINTS,RIPGREP_SHELL_FUNCTION_CAVEAT,RIPGREP_INSTALL_HINTS,CREDENTIAL_RESOLUTION_HINT,CLAUDE_MCP_SHADOWING_HINT,LIVE_SOURCE_GUARD_HINT,init_start_tickets_prereqs=__esm({"src/start-tickets-prereqs.ts"(){"use strict";init_credential_store();init_start_tickets_repo();init_mcp_registration_doctor();init_command_assets_doctor();init_mcp_identity();init_claude_review_workflow_drift();init_claude_review_workflow_drift_probe();init_claude_user_config_doctor();START_TICKETS_DOCTOR_COMMAND=`npx -y ${MCP_PACKAGE_NAME} doctor`,CONDUCTOR_LIVE_SOURCE_PATH_ENV="BAPI_CONDUCTOR_LIVE_SOURCE_PATH",CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV="BAPI_CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH",GIT_INSTALL_HINTS={darwin:"xcode-select --install (or brew install git)",linux:"Install git with your distro package manager, e.g. apt install git",win32:"Install Git for Windows: https://git-scm.com/download/win"},REVIEW_TICKETS_GIT_INSTALL_HINTS={darwin:`${GIT_INSTALL_HINTS.darwin} (or rerun review-tickets with --no-refresh-base to skip the fetch)`,linux:`${GIT_INSTALL_HINTS.linux} (or rerun review-tickets with --no-refresh-base to skip the fetch)`,win32:`${GIT_INSTALL_HINTS.win32} (or rerun review-tickets with --no-refresh-base to skip the fetch)`},RIPGREP_SHELL_FUNCTION_CAVEAT="a shell function/alias will not satisfy this check \u2014 ripgrep must be installed as a real PATH binary.",RIPGREP_INSTALL_HINTS={darwin:`brew install ripgrep (${RIPGREP_SHELL_FUNCTION_CAVEAT})`,linux:`Install ripgrep with your distro package manager, e.g. apt install ripgrep (${RIPGREP_SHELL_FUNCTION_CAVEAT})`,win32:`winget install BurntSushi.ripgrep.MSVC (${RIPGREP_SHELL_FUNCTION_CAVEAT})`},CREDENTIAL_RESOLUTION_HINT=`Rerun /install-bridge to persist the routing credential, set BAPI_API_KEY in the environment, or add it under "bapi:<repo_name>" in ~/.config/bridge/credentials.json. To migrate a key that only lives in .mcp.json / .cursor/mcp.json, run: npx -y ${MCP_PACKAGE_NAME} credentials migrate-agent-config --write-credentials.`,CLAUDE_MCP_SHADOWING_HINT=`Run \`${CLAUDE_MCP_SHADOWING_REMEDIATION_COMMAND}\` to clear the '${MCP_SERVER_NAME}' MCP registration in ~/.claude.json (use the matching scope if it is registered at user scope, or under the projects entry for this repository/worktree). This is ADVISORY: workers load MCP servers with --strict-mcp-config from their own worktree registration, so this entry does not reach a worker and does not block a conductor run.`,LIVE_SOURCE_GUARD_HINT=`Point ${CONDUCTOR_LIVE_SOURCE_PATH_ENV} at your live dev server's checkout ONLY when it differs from this conductor base checkout, or dispatch the conductor from a separate clone. To override the guard and dispatch anyway (not recommended), set ${CONDUCTOR_ALLOW_LIVE_SOURCE_DISPATCH_ENV}=1.`}});import path6 from"path";function pathApiForPlatform(platform){return platform==="win32"?path6.win32:path6.posix}var init_worktree_core=__esm({"src/worktree-core.ts"(){"use strict";init_start_tickets_prereqs()}});var init_platform_escaping=__esm({"src/platform-escaping.ts"(){"use strict"}});var init_prompt=__esm({"src/agent-launchers/prompt.ts"(){"use strict"}});async function resolveCommandOnPath(command,envPath,deps){let pathApi=pathApiForPlatform(deps.platform),probe=deps.platform==="win32"?"where.exe":"which",env={...deps.env,PATH:envPath};deps.platform==="win32"&&(env.Path=envPath);let result=await deps.runCommand(probe,[command],{env});if(result.exitCode!==0)return null;let candidate=result.stdout.split(/\r?\n/).map(line=>line.trim()).find(line=>line.length>0);return!candidate||!pathApi.isAbsolute(candidate)?null:pathApi.normalize(candidate)}var init_claude=__esm({"src/agent-launchers/claude.ts"(){"use strict";init_worktree_core();init_platform_escaping();init_prompt()}});var DEFAULT_PROBE_TIMEOUT_MS,init_types=__esm({"src/agent-capabilities/types.ts"(){"use strict";DEFAULT_PROBE_TIMEOUT_MS=9e4}});import{join as join2}from"node:path";function buildHeadlessArgs(agentName,opts){let fmt=opts.outputFormat??"text";if(agentName==="cursor-agent")return["-p","--output-format",fmt,"--trust","--workspace",opts.cwd,opts.prompt];let args=["-p"];return opts.permissionMode==="auto"?args.push("--permission-mode","auto"):opts.permissionMode==="acceptEdits"?args.push("--permission-mode","acceptEdits"):opts.skipPermissions===!0&&args.push("--dangerously-skip-permissions"),typeof opts.model=="string"&&opts.model.trim().length>0&&args.push("--model",opts.model),fmt==="json"?args.push("--output-format","json"):fmt==="stream-json"&&args.push("--output-format","stream-json","--verbose"),args.push(opts.prompt),args}async function createProbeContext(deps,agent,defaultTimeoutMs=DEFAULT_PROBE_TIMEOUT_MS){let launcherDeps={platform:deps.platform,env:deps.env,runCommand:(file,args,options)=>deps.runCommand(file,args,options)},resolvedBinary=await resolveCommandOnPath(agent.command,deps.env.PATH??"",launcherDeps),createdDirs=[],counter=0;return{ctx:{agent,deps,resolvedBinary,marker(name){return`${name}_${deps.uniqueSuffix()}_${counter++}`},async makeTempProject(seed){let dir=await deps.mkdtemp(join2(deps.tmpRoot,"agent-cap-"));return createdDirs.push(dir),seed&&await seed(dir),dir},async runHeadless(opts){let exe=resolvedBinary??agent.command,args=buildHeadlessArgs(agent.name,opts),timeoutMs=opts.timeoutMs??defaultTimeoutMs,controller=new AbortController,timedOut=!1,timer=setTimeout(()=>{timedOut=!0,controller.abort()},timeoutMs),start=deps.now();try{let result=await deps.runCommand(exe,args,{cwd:opts.cwd,env:deps.env,signal:controller.signal}),elapsedMs=deps.now()-start;return timedOut?{kind:"hang",elapsedMs,partialStdout:result.stdout??""}:{kind:"exited",exitCode:result.exitCode,stdout:result.stdout??"",stderr:result.stderr??"",elapsedMs}}catch(err){let elapsedMs=deps.now()-start;return timedOut?{kind:"hang",elapsedMs,partialStdout:""}:{kind:"spawn-error",message:err instanceof Error?err.message:String(err)}}finally{clearTimeout(timer)}}},cleanup:async()=>{for(let dir of createdDirs.splice(0))try{await deps.rm(dir,{recursive:!0,force:!0})}catch{}}}}var init_probe_context=__esm({"src/agent-capabilities/probe-context.ts"(){"use strict";init_claude();init_types()}});import{execFile}from"node:child_process";import{mkdtemp,rm,writeFile,mkdir}from"node:fs/promises";import os3 from"node:os";import{randomBytes}from"node:crypto";function createDefaultAgentCapabilitiesDeps(){let runCommand=(file,args,options)=>new Promise(resolve2=>{execFile(file,args,{cwd:options?.cwd,env:options?.env??process.env,signal:options?.signal,killSignal:"SIGKILL",maxBuffer:67108864,encoding:"utf-8"},(error,stdout,stderr)=>{let exitCode=error&&typeof error.code=="number"?error.code:error?1:0;resolve2({stdout:stdout??"",stderr:stderr??"",exitCode})})});return{platform:process.platform,env:process.env,runCommand,tmpRoot:os3.tmpdir(),mkdtemp:prefix=>mkdtemp(prefix),rm:(target,opts)=>rm(target,opts),writeFile:(target,data)=>writeFile(target,data,"utf-8"),mkdir:(target,opts)=>mkdir(target,opts).then(()=>{}),now:()=>Date.now(),uniqueSuffix:()=>randomBytes(3).toString("hex").toUpperCase()}}var init_default_deps=__esm({"src/agent-capabilities/default-deps.ts"(){"use strict"}});import{join as join3}from"node:path";function truncate(text){let flat=text.replace(/\s+/g," ").trim();return flat.length>EVIDENCE_MAX?`${flat.slice(0,EVIDENCE_MAX)}\u2026`:flat}function nonExitedResult(run){return run.kind==="hang"?{status:"hang",detail:`agent did not exit within the timeout (${run.elapsedMs}ms) \u2014 likely the version-sensitive -p hang`,elapsedMs:run.elapsedMs,evidence:run.partialStdout?truncate(run.partialStdout):void 0}:run.kind==="spawn-error"?{status:"fail",detail:`could not spawn agent: ${run.message}`}:null}function denyHookCommand(){return`printf '%s' '${JSON.stringify({hookSpecificOutput:{hookEventName:"PreToolUse",permissionDecision:"deny",permissionDecisionReason:"agent-capability deny-enforcement probe fallback: tool call denied."}})}'`}async function seedDenyTargetFile(ctx,dir,marker){await ctx.deps.writeFile(join3(dir,DENY_TARGET_FILE),`${marker}
|
|
112
112
|
`)}async function seedDenySettings(ctx,dir,marker){await seedDenyTargetFile(ctx,dir,marker);let claudeDir=join3(dir,".claude");await ctx.deps.mkdir(claudeDir,{recursive:!0});let settings={permissions:{deny:[DENY_BASH_RULE]}};await ctx.deps.writeFile(join3(claudeDir,"settings.local.json"),`${JSON.stringify(settings,null,2)}
|
|
113
113
|
`)}async function seedDenyHook(ctx,dir,marker){await seedDenyTargetFile(ctx,dir,marker);let claudeDir=join3(dir,".claude");await ctx.deps.mkdir(claudeDir,{recursive:!0});let settings={hooks:{PreToolUse:[{matcher:DENY_HOOK_MATCHER,hooks:[{type:"command",command:denyHookCommand()}]}]}};await ctx.deps.writeFile(join3(claudeDir,"settings.local.json"),`${JSON.stringify(settings,null,2)}
|
|
114
114
|
`)}function denyProbePrompt(){return["This is an agent-capability probe of permission enforcement.",`Use the Bash tool to run exactly this command: cat ${DENY_TARGET_FILE}`,"Then output the command's exact stdout on its own line.","Use ONLY the Bash tool for this \u2014 do not use Read, Grep, or any other tool, and do not open the file yourself.","If the Bash command is blocked, denied, or errors, output the single word DENIED and nothing else.","Do not guess, fabricate, or infer the file contents \u2014 only report what the command actually returned."].join(`
|
|
@@ -119,8 +119,8 @@ ${managedBlock}
|
|
|
119
119
|
LIMIT 1`).get(eventType,actionKey)!==void 0}finally{db.close()}}async function hasTerminalMergeSucceeded(actionKey,deps={}){return lookupMergeEventByActionKey("merge.succeeded",actionKey,deps)}async function hasMergeDryRun(actionKey,deps={}){return lookupMergeEventByActionKey("merge.dry_run",actionKey,deps)}async function hasMergePendingApproval(actionKey,deps={}){return lookupMergeEventByActionKey("merge.pending_approval",actionKey,deps)}function isDuplicateConstraintError4(error){if(!error||typeof error!="object")return!1;let code=error.code;if(typeof code=="string"&&code.startsWith("SQLITE_CONSTRAINT"))return!0;let message=error.message;if(typeof message=="string"){let lowered=message.toLowerCase();if(lowered.includes("unique constraint")||lowered.includes("constraint failed"))return!0}return!1}async function emitMergeLedgerEventIfNew(input,deps={}){let emitEvent=deps.emitEvent??emitConductorEvent,eventId=makeMergeEventId(input.type,input.action_key),event={id:eventId,source:"conductor-supervisor",type:input.type,run_id:input.run_id??null,worker_id:input.worker_id??null,producer:"conductor-merge",observed_via:"supervisor",data:{summary:input.summary??`${input.type} ${input.action_key}`,status:input.status,reason:input.reason??void 0,details:input.details}};try{let result=await emitEvent(event);return{emitted:!0,event_id:eventId,event:result.event}}catch(error){if(isDuplicateConstraintError4(error))return{emitted:!1,reason:"duplicate"};throw error}}var init_merge_ledger=__esm({"src/conductor/merge-ledger.ts"(){"use strict";init_event_accessors();init_merge_identity();init_store()}});function buildMergeRequestFromGateEvent(identity){return{repo_name:identity.repo,pr_number:identity.pr_number,expected_head_sha:identity.head_sha,gate:{name:identity.gate_name,config_hash:identity.config_hash,required_checks:identity.required_checks},action_key:identity.action_key,gate_event:identity.gate_event}}function mapApiErrorReason(error){if(error instanceof ConductorBridgeApiError)switch(error.kind){case"timeout":return"api_timeout";case"network":return"api_network";case"unauthorized":return"api_unauthorized";case"server":case"http":return"api_unavailable";case"invalid-input":return"api_invalid"}return"api_network"}function resolveAttributionWorkerId(event,identity,resolve2){if(typeof event.worker_id=="string"&&event.worker_id.trim().length>0)return event.worker_id.trim();if(resolve2){let resolved=resolve2(event,identity);if(typeof resolved=="string"&&resolved.trim().length>0)return resolved.trim()}return null}async function processGateMetMerge(access,event,deps={}){let extract=deps.extractIdentity??extractMergeActionIdentityFromGateEvent,checkTerminal=deps.hasTerminal??hasTerminalMergeSucceeded,checkDryRun=deps.hasDryRun??hasMergeDryRun,checkPendingApproval=deps.hasPendingApproval??hasMergePendingApproval,mergeFn=deps.merge??mergePullRequestForGate,identity=extract(event);if(!identity)return{processed:!1,reason:"ineligible"};let actionKey=identity.action_key,attributionWorkerId=resolveAttributionWorkerId(event,identity,deps.resolveWorkerIdForGateEvent);if(await checkTerminal(actionKey))return{processed:!1,reason:"already_succeeded"};let baseDetails={action_key:actionKey,repo:identity.repo,pr_number:identity.pr_number,expected_head_sha:identity.head_sha,gate:identity.gate_identity},response;try{response=await mergeFn(access,buildMergeRequestFromGateEvent(identity))}catch(error){let reason=mapApiErrorReason(error);return await emitMergeLedgerEventIfNew({type:"merge.failed",action_key:actionKey,status:"failed",reason,details:baseDetails,run_id:event.run_id??null,worker_id:attributionWorkerId,summary:`merge.failed ${reason}`},{emitEvent:deps.emitEvent}),{processed:!0,outcome:"api_error",reason}}let emitted=[];for(let ledgerEvent of response.ledger_events??[]){if(ledgerEvent.type==="merge.dry_run"&&await checkDryRun(actionKey)){emitted.push({type:ledgerEvent.type,emitted:!1});continue}if(ledgerEvent.type==="merge.pending_approval"&&await checkPendingApproval(actionKey)){emitted.push({type:ledgerEvent.type,emitted:!1});continue}let result=await emitMergeLedgerEventIfNew({type:ledgerEvent.type,action_key:actionKey,status:ledgerEvent.status,reason:ledgerEvent.reason??null,details:ledgerEvent.details??baseDetails,run_id:event.run_id??null,worker_id:attributionWorkerId},{emitEvent:deps.emitEvent});emitted.push({type:ledgerEvent.type,emitted:result.emitted})}return{processed:!0,outcome:response.status,emitted}}var init_supervisor_merge=__esm({"src/conductor/supervisor-merge.ts"(){"use strict";init_bridge_api_client();init_merge_ledger()}});async function dispatchSupervisorNotification(epicRunId,candidate,assessment,idempotencyKey){let result=await resolveConductorBridgeApiAccess();if(!result.ok)return;let{access}=result,url=buildConductorJiraUrl(access.baseUrl,`/epic-runs/${encodeURIComponent(epicRunId)}/notifications`),payload={repo_name:access.repoName,idempotency_key:idempotencyKey,summary:{reason:candidate.reason,kind:candidate.kind,worker_id:candidate.worker_id??null,elapsed_ms:candidate.elapsed_ms,ticket_key:candidate.context?.ticket_key??null,classification:assessment.classification}},headers={"X-API-Key":access.apiKey,"Content-Type":"application/json"};try{await fetchConductorJsonPostWithTimeout(url,headers,JSON.stringify(payload),CONDUCTOR_FETCH_TIMEOUT_MS,fetch)}catch{}}var init_supervisor_notification=__esm({"src/conductor/supervisor-notification.ts"(){"use strict";init_bridge_api_client()}});var supervisor_runtime_exports={};__export(supervisor_runtime_exports,{runSupervisor:()=>runSupervisor});function deterministicAssessment(candidate){return{classification:"stuck",confidence:1,reason:candidate.reason}}function terminalStatus(state){return Object.values(state.workers).some(w=>w.state==="failed")?"failed":"complete"}async function processEscalations(state,config,deps){let now=deps.now(),candidates=findSupervisorEscalationCandidates(state,config,now);for(let candidate of candidates){let decision=shouldEmitEscalation(state,candidate,config,now);if(!decision.emit)continue;let idempotency={run_id:state.run_id,worker_id:candidate.worker_id,reason:candidate.reason,kind:candidate.kind,cooldown_window:decision.cooldown_window},idempotencyKey=makeSupervisorIdempotencyKey(idempotency),assessment=deterministicAssessment(candidate);state.latest_assessment=assessment;let outcome="skipped";try{outcome=(await deps.emitAssessment({run_id:state.run_id,worker_id:candidate.worker_id,assessment,details:{elapsed_ms:candidate.elapsed_ms,...candidate.context},idempotency})).emitted?"emitted":"duplicate"}catch{outcome="skipped"}if(recordEscalationResult(state,candidate,decision.cooldown_window,idempotencyKey,outcome,now),(outcome==="emitted"||outcome==="duplicate")&&candidate.worker_id)try{await sendSupervisorEscalationWorkerMessageIfNew(candidate,assessment,state,{sendMessage:deps.sendWorkerMessage})}catch{}if(outcome==="emitted"&&(deps.log(formatEscalationForTerminal(state.run_id,candidate)),deps.dispatchNotification))try{await deps.dispatchNotification(state.run_id,candidate,assessment,idempotencyKey)}catch{}}}async function runSupervisor(options,deps={}){let runId=typeof options.run_id=="string"?options.run_id.trim():"";if(runId.length===0)throw new ConductorValidationError("Supervisor requires exactly one non-empty --run-id.");let config=options.config??resolveSupervisorConfig(options.overrides??{}),now=deps.now??(()=>Date.now()),log=deps.log??(m=>process.stdout.write(`${m}
|
|
120
120
|
`)),errorLog=deps.errorLog??(m=>process.stderr.write(`${m}
|
|
121
121
|
`)),waitForEvent=deps.waitForEvent??waitForConductorEvent,getSnapshot=deps.getSnapshot??getSupervisorSnapshot,upsertProjection=deps.upsertProjection??upsertSupervisorProjection,emitAssessment=deps.emitAssessment??emitSupervisorAssessmentIfNew,sendMessage=deps.sendWorkerMessage??sendWorkerMessage,resolveBridgeAccess=deps.resolveBridgeAccess??(()=>resolveConductorBridgeApiAccess()),processMerge=deps.processMerge??processGateMetMerge,dispatchNotification=deps.dispatchNotification??dispatchSupervisorNotification,bridgeAccess=null,bridgeAccessResolved=!1,processGateMetMerges=async events=>{let eligible=events.filter(e=>extractMergeActionIdentityFromGateEvent(e)!==null);if(eligible.length!==0){if(!bridgeAccessResolved){bridgeAccessResolved=!0;try{let result=await resolveBridgeAccess();bridgeAccess=result.ok?result.access:null,result.ok||errorLog(`[supervisor] run=${runId} auto-merge disabled: ${result.kind}`)}catch{bridgeAccess=null}}if(bridgeAccess)for(let event of eligible)try{await processMerge(bridgeAccess,event)}catch{}}},persist=async state2=>{try{await upsertProjection(toSupervisorProjectionInput(state2))}catch{}},state;try{let snapshot=await getSnapshot(runId);state=hydrateSupervisorRunStateFromSnapshot(snapshot,runId,config,now())}catch{return{run_id:runId,status:"failed",exit_code:2,reason:"supervisor failed to load initial snapshot",last_seq:0,worker_count:0}}let sinceSeq=state.last_seq>0?state.last_seq+1:1,iterationCap=Math.max(1e3,Math.ceil(config.global_timeout_ms/Math.max(1,config.wake_interval_ms))+16);try{applySupervisorHousekeeping(state,config,now());for(let iteration=0;iteration<iterationCap;iteration+=1){if(isSupervisorRunTerminal(state))return state.status=terminalStatus(state),await persist(state),log(`[supervisor] run=${runId} complete status=${state.status} workers=${Object.keys(state.workers).length}`),{run_id:runId,status:state.status,exit_code:0,reason:"all workers terminal",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length};if(hasSupervisorGlobalTimeoutElapsed(state,now()))return state.status="timed_out",await persist(state),errorLog(`[supervisor] run=${runId} global timeout elapsed`),{run_id:runId,status:"timed_out",exit_code:2,reason:"global timeout elapsed",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length};let waitResult=await waitForEvent({since_seq:sinceSeq,filter:{run_id:runId},data_mode:"full",timeout_ms:config.wake_interval_ms,limit:config.poll_limit});if(waitResult.events.length>0){let sorted=[...waitResult.events].sort((a,b)=>a.seq-b.seq);for(let event of sorted)applyConductorEventToSupervisorState(state,event,now());sinceSeq=sorted[sorted.length-1].seq+1,await processGateMetMerges(sorted)}applySupervisorHousekeeping(state,config,now()),await processEscalations(state,config,{emitAssessment,sendWorkerMessage:sendMessage,log,now,dispatchNotification}),await persist(state)}return state.status="timed_out",await persist(state),{run_id:runId,status:"timed_out",exit_code:2,reason:"supervisor iteration cap reached",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length}}catch{state.status="failed";try{await upsertProjection(toSupervisorProjectionInput(state))}catch{}return errorLog(`[supervisor] run=${runId} failed unexpectedly`),{run_id:runId,status:"failed",exit_code:2,reason:"supervisor failed unexpectedly",last_seq:state.last_seq,worker_count:Object.keys(state.workers).length}}}var init_supervisor_runtime=__esm({"src/conductor/supervisor-runtime.ts"(){"use strict";init_store();init_supervisor_ledger();init_supervisor_message_relay();init_supervisor_config();init_supervisor_state();init_supervisor_escalation();init_supervisor_ledger();init_bridge_api_client();init_merge_ledger();init_supervisor_merge();init_supervisor_notification();init_errors()}});import path7 from"path";function buildSetupUrl(baseUrl){return`${baseUrl.replace(/\/+$/,"")}/setup`}async function resolveInstallDoctorTarget(deps){let envRepo=deps.env.BAPI_REPO_NAME?.trim(),envBase=deps.env.BAPI_BASE_URL?.trim(),repoName=envRepo&&envRepo.length>0?envRepo:null,repoSource=repoName?"env":null,baseUrl=envBase&&envBase.length>0?envBase:null;if(!repoName||!baseUrl)for(let{relPath,topLevelKey}of MCP_CONFIG_ENV_TARGETS){let raw;try{raw=await deps.readFile(path7.join(deps.cwd,relPath))}catch{continue}let parsed;try{parsed=JSON.parse(raw)}catch{continue}let servers=parsed&&typeof parsed=="object"?parsed[topLevelKey]:void 0,registrationKey=existingRegistrationKey(servers),envBlock=registrationKey!==null?servers[registrationKey]?.env:void 0;if(envBlock&&(!repoName&&typeof envBlock.BAPI_REPO_NAME=="string"&&envBlock.BAPI_REPO_NAME.trim()&&(repoName=envBlock.BAPI_REPO_NAME.trim(),repoSource="config"),!baseUrl&&typeof envBlock.BAPI_BASE_URL=="string"&&envBlock.BAPI_BASE_URL.trim()&&(baseUrl=envBlock.BAPI_BASE_URL.trim()),repoName&&baseUrl))break}return{repoName,repoSource,baseUrl:baseUrl??DEFAULT_BASE_URL}}function classifyProbeFailure(error){let name=error?.name;return name==="TimeoutError"||name==="AbortError"?"request timed out":"request unavailable"}async function probeGet(deps,url,apiKey){try{let resp=await deps.fetch(url,{headers:{"X-API-Key":apiKey},signal:AbortSignal.timeout(PROBE_TIMEOUT_MS)}),body=null;try{body=await resp.json()}catch{}return{ok:!0,status:resp.status,body}}catch(e){return{ok:!1,error:classifyProbeFailure(e)}}}function summarizeManifestGroups(body){if(!body||typeof body!="object")return null;let groups=body.groups;if(!Array.isArray(groups))return null;let total=0,unset=[];for(let group of groups){let fields=group?.fields;if(Array.isArray(fields))for(let field of fields){let name=field?.field_name;typeof name=="string"&&(total+=1,field.is_set||unset.push(name))}}return{total,unset}}function summarizeIntegrations(body){if(!body||typeof body!="object")return null;let integrations=body.integrations;if(!Array.isArray(integrations))return null;let total=0,unconfigured=[];for(let item of integrations){let label=item?.label;typeof label=="string"&&(total+=1,item.is_configured||unconfigured.push(label))}return{total,unconfigured}}function readGithubConfiguredFlag(body){if(!body||typeof body!="object")return null;let integrations=body.integrations;if(!Array.isArray(integrations))return null;for(let item of integrations){if(item?.id!=="github_app")continue;let configured=item.is_configured;return typeof configured=="boolean"?configured:null}return null}async function collectInstallStatusChecks(deps){let checks=[],loginResult=await detectClaudeLogin({homedir:deps.homedir,readFile:deps.readFile});checks.push({id:"claude-login",label:"Claude login",status:loginResult.detected?"PASS":"INFO",detail:formatClaudeLoginAdvisory(loginResult)});let target=await resolveInstallDoctorTarget(deps);if(!target.repoName)return checks.push({id:"identity",label:"Repository identity",status:"SKIP",detail:"no BAPI_REPO_NAME in the environment or project-local MCP configs",remediation:"run install-bridge (or set BAPI_REPO_NAME) to configure this project."}),checks;checks.push({id:"identity",label:"Repository identity",status:"PASS",detail:`${target.repoName} (from ${target.repoSource}), base URL ${target.baseUrl}`});let setupUrl=buildSetupUrl(target.baseUrl),credDeps={env:deps.env,homedir:deps.homedir,platform:deps.platform,readFile:deps.readFile,stat:deps.stat,stderr:()=>{}},cred=await resolveBapiCredentials(target.repoName,credDeps);if(!cred.ok){checks.push({id:"credential",label:"Bridge API credential",status:"WARN",detail:`not resolved (${cred.kind})`,remediation:"set BAPI_API_KEY or persist it via /install-bridge / the credentials subcommand; until then the remaining install checks are skipped."});for(let[id,label]of[["connectivity","Server connectivity"],["bootstrap","Bootstrap config fields"],["indexing","Repository indexing"]])checks.push({id,label,status:"SKIP",detail:"no credential resolved"});return checks}checks.push({id:"credential",label:"Bridge API credential",status:"PASS",detail:`resolved from ${cred.credentials.source} (value never read into the report)`});let apiKey=cred.credentials.apiKey,repoQuery=`repo_name=${encodeURIComponent(target.repoName)}`,ping=await probeGet(deps,`${target.baseUrl}/jira/ping?${repoQuery}`,apiKey);ping.ok?ping.status===200?checks.push({id:"connectivity",label:"Server connectivity",status:"PASS",detail:"ping OK"}):ping.status===401||ping.status===403?checks.push({id:"connectivity",label:"Server connectivity",status:"WARN",detail:`the server rejected the resolved key (HTTP ${ping.status})`,remediation:"the key may have been rotated \u2014 re-run install-bridge with a current key."}):ping.status===404?checks.push({id:"connectivity",label:"Server connectivity",status:"WARN",detail:`the server does not know repo '${target.repoName}' (HTTP 404)`,remediation:`create the project at ${setupUrl} (setup UI), or check BAPI_REPO_NAME spelling.`}):checks.push({id:"connectivity",label:"Server connectivity",status:"WARN",detail:`unexpected HTTP ${ping.status} from /jira/ping`,remediation:"the server answered but not with a status this check understands \u2014 re-run doctor; if it persists the Bridge API is unhealthy and no install fact below can be trusted."}):checks.push({id:"connectivity",label:"Server connectivity",status:"WARN",detail:`unreachable (${ping.error})`,remediation:`check ${target.baseUrl} and your network, then re-run doctor.`});let manifest=await probeGet(deps,`${target.baseUrl}/jira/config/install-manifest?${repoQuery}`,apiKey);if(!manifest.ok)checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:`manifest unreachable (${manifest.error})`,remediation:`check ${target.baseUrl} and your network, then re-run doctor.`});else if(manifest.status===404)checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:"no configuration row found for this repository",remediation:`create the project at ${setupUrl} (setup UI), then run /install-bridge.`});else if(manifest.status===200){let summary=summarizeManifestGroups(manifest.body);summary?summary.unset.length===0?checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"PASS",detail:`${summary.total}/${summary.total} bootstrap fields set`}):checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:`${summary.total-summary.unset.length}/${summary.total} set; unset: ${summary.unset.join(", ")}`,remediation:"run /install-bridge to derive the unset fields (intentionally-unset fields are fine to leave)."}):checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:"manifest response had an unexpected shape",remediation:"the manifest could not be read, so no bootstrap field state is known \u2014 re-run doctor, then run /install-bridge to re-derive the project configuration."})}else checks.push({id:"bootstrap",label:"Bootstrap config fields",status:"WARN",detail:`unexpected HTTP ${manifest.status} from the install manifest`,remediation:"the manifest endpoint answered with an unrecognized status \u2014 re-run doctor; if it persists, re-run /install-bridge for this repository."});if(manifest.ok&&manifest.status===200){let integrations=summarizeIntegrations(manifest.body);integrations===null?checks.push({id:"integrations",label:"Integration credentials",status:"SKIP",detail:"the manifest response carried no integrations checklist"}):integrations.unconfigured.length===0?checks.push({id:"integrations",label:"Integration credentials",status:"PASS",detail:`${integrations.total}/${integrations.total} configured`}):checks.push({id:"integrations",label:"Integration credentials",status:"WARN",detail:`not configured: ${integrations.unconfigured.join(", ")}`,remediation:`a human configures these at ${setupUrl} (setup UI \u2192 project settings) \u2014 Bridge API never accepts integration secrets through an agent or MCP tool.`})}else checks.push({id:"integrations",label:"Integration credentials",status:"SKIP",detail:"manifest unavailable"});if(manifest.ok&&manifest.status===200){let github=readGithubConfiguredFlag(manifest.body);github===null?checks.push({id:"github",label:"GitHub connection",status:"SKIP",detail:"the manifest response carried no GitHub integration entry"}):github?checks.push({id:"github",label:"GitHub connection",status:"PASS",detail:"a GitHub repository is connected to this project"}):checks.push({id:"github",label:"GitHub connection",status:"WARN",detail:"no GitHub repository is connected to this project",remediation:`run 'npx -y ${MCP_PACKAGE_NAME}@latest connect-github --repo ${target.repoName}'.`})}else checks.push({id:"github",label:"GitHub connection",status:"SKIP",detail:"manifest unavailable"});let parse=await probeGet(deps,`${target.baseUrl}/jira/parse-status?${repoQuery}`,apiKey);if(!parse.ok||parse.status!==200)checks.push({id:"indexing",label:"Repository indexing",status:"SKIP",detail:parse.ok?`HTTP ${parse.status} from /jira/parse-status`:`unreachable (${parse.error})`});else if(parse.body?.status==="in_progress"){let startedAt=parse.body.started_at;checks.push({id:"indexing",label:"Repository indexing",status:"INFO",detail:`parse job in progress${typeof startedAt=="string"?` (started ${startedAt})`:""}`})}else checks.push({id:"indexing",label:"Repository indexing",status:"INFO",detail:'no parse job currently running \u2014 if this repository has never been indexed, queue one with /parse-repository (monitor with parse_repository action "status").'});return checks}function projectInstallStatus(check){return check.status==="PASS"?{status:"pass"}:check.status==="WARN"?{status:"warn",...check.remediation?{remediation:check.remediation}:{}}:check.status==="INFO"?check.id==="claude-login"?{status:"warn",remediation:INSTALL_CLAUDE_LOGIN_REMEDIATION}:{status:"pass"}:check.id==="identity"?{status:"fail",remediation:check.remediation??INSTALL_IDENTITY_REMEDIATION}:{status:"skip",...check.remediation?{remediation:check.remediation}:{}}}function mapInstallStatusChecksToReadinessChecks(checks,collectorUnavailable=!1){let byId=new Map;for(let check of checks??[])byId.has(check.id)||byId.set(check.id,check);return INSTALL_READINESS_DESCRIPTORS.map(({id,label})=>{let source=byId.get(id);if(!source)return collectorUnavailable?createReadinessCheck({id:`install.${id}`,source:"install",label,status:"fail",detail:INSTALL_UNAVAILABLE_DETAIL,remediation:INSTALL_UNAVAILABLE_REMEDIATION}):createReadinessCheck({id:`install.${id}`,source:"install",label,status:"skip",detail:INSTALL_NOT_COLLECTED_DETAIL});let projected=projectInstallStatus(source);return createReadinessCheckSafely({id:`install.${id}`,source:"install",label:source.label||label,status:projected.status,...source.detail?{detail:source.detail}:{},...projected.status==="pass"?{}:projected.remediation?{remediation:projected.remediation}:projected.status==="fail"?{remediation:INSTALL_IDENTITY_REMEDIATION}:{}})})}var DEFAULT_BASE_URL,MCP_CONFIG_ENV_TARGETS,PROBE_TIMEOUT_MS,INSTALL_READINESS_DESCRIPTORS,INSTALL_IDENTITY_REMEDIATION,INSTALL_CLAUDE_LOGIN_REMEDIATION,INSTALL_NOT_COLLECTED_DETAIL,INSTALL_UNAVAILABLE_DETAIL,INSTALL_UNAVAILABLE_REMEDIATION,init_install_doctor=__esm({"src/install-doctor.ts"(){"use strict";init_readiness_check();init_credential_store();init_claude_login();init_mcp_host_targets();init_mcp_identity();DEFAULT_BASE_URL="https://bridgegpt-api.com";MCP_CONFIG_ENV_TARGETS=getProjectJsonTargets().map(target=>({relPath:target.relPath,topLevelKey:hostAdapterForTarget(target).topLevelKey})),PROBE_TIMEOUT_MS=5e3;INSTALL_READINESS_DESCRIPTORS=[{id:"claude-login",label:"Claude login"},{id:"identity",label:"Repository identity"},{id:"credential",label:"Bridge API credential"},{id:"connectivity",label:"Server connectivity"},{id:"bootstrap",label:"Bootstrap config fields"},{id:"integrations",label:"Integration credentials"},{id:"github",label:"GitHub connection"},{id:"indexing",label:"Repository indexing"}],INSTALL_IDENTITY_REMEDIATION="run /install-bridge (or set BAPI_REPO_NAME) to configure this project; without a repository identity no server-side conductor fact can be resolved.",INSTALL_CLAUDE_LOGIN_REMEDIATION="run `claude login` on the host that will run conductor workers; Bridge stores no Anthropic credential and cannot confirm this for you.",INSTALL_NOT_COLLECTED_DETAIL="not collected \u2014 an earlier install prerequisite stopped the checklist",INSTALL_UNAVAILABLE_DETAIL="unknown \u2014 the install-status checklist could not be collected at all",INSTALL_UNAVAILABLE_REMEDIATION="run `doctor` to collect the advisory install-status checklist directly; this prerequisite's state is unknown, not healthy."}});function planeCheckPassed(check,label,detail){return{diagnostic:null,outcomes:[{check,id:check,label,status:"pass",...detail?{detail}:{}}]}}function planeCheckFinding(diagnostic,label,detail){return{diagnostic,outcomes:[{check:diagnostic.check,id:diagnostic.check,label,status:diagnostic.severity==="blocking"?"fail":"warn",detail,...diagnostic.remediation?{remediation:diagnostic.remediation}:{}}]}}var PLANE_MANIFEST_SUPPORTED_SCHEMA_VERSIONS,PLANE_RUNTIME_DIR,PLANE_MANIFEST_FILENAME,PLANE_RUNTIME_LOG_FILENAME,PLANE_RUNTIME_LOG_PATH,PLANE_SERVER_HOST,PLANE_SERVER_PORT,PLANE_SERVER_BASE_URL,PLANE_SERVER_PORT_ENV_VAR,PLANE_LIFECYCLE_PHASES,init_types2=__esm({"src/plane/types.ts"(){"use strict";PLANE_MANIFEST_SUPPORTED_SCHEMA_VERSIONS=[1,2,3],PLANE_RUNTIME_DIR=".bridge/plane",PLANE_MANIFEST_FILENAME="plane.json",PLANE_RUNTIME_LOG_FILENAME="runtime.log",PLANE_RUNTIME_LOG_PATH=`${PLANE_RUNTIME_DIR}/${PLANE_RUNTIME_LOG_FILENAME}`,PLANE_SERVER_HOST="127.0.0.1",PLANE_SERVER_PORT=8e3,PLANE_SERVER_BASE_URL=`http://${PLANE_SERVER_HOST}:${PLANE_SERVER_PORT}`,PLANE_SERVER_PORT_ENV_VAR="BAPI_PLANE_PORT";PLANE_LIFECYCLE_PHASES=["control-plane-starting","control-plane-ready","lanes-starting","lanes-ready","ready","lanes-failed"]}});import path8 from"path";function isRelevantSourceFile(name){return!(!name.endsWith(".ts")||name.endsWith(".generated.ts"))}async function findNewestSourceMtime(srcDir,deps){let newest=null,walk=async dir=>{let entries;try{entries=await deps.fs.readdir(dir)}catch(err){return sanitize(err)}for(let entry of entries){if(entry.isDirectory()){if(EXCLUDED_DIR_NAMES.has(entry.name))continue;let error2=await walk(path8.join(dir,entry.name));if(error2)return error2;continue}if(!(!entry.isFile()||!isRelevantSourceFile(entry.name)))try{let stat3=await deps.fs.stat(path8.join(dir,entry.name));(newest===null||stat3.mtimeMs>newest)&&(newest=stat3.mtimeMs)}catch(err){return sanitize(err)}}return null},error=await walk(srcDir);return error?{ok:!1,error}:{ok:!0,mtimeMs:newest}}async function findBuildMtime(executorEntrypoint,deps){try{return{ok:!0,mtimeMs:(await deps.fs.stat(executorEntrypoint)).mtimeMs}}catch(err){return{ok:!1,error:sanitize(err)}}}async function checkPlaneBuildFreshness(repoRoot,deps){let label="Executor build freshness",packageRoot=path8.join(repoRoot,"mcp_server"),buildDir=path8.join(packageRoot,"build"),executorEntrypoint=path8.join(buildDir,"index.js"),srcDir=path8.join(packageRoot,"src"),buildMtime=await findBuildMtime(executorEntrypoint,deps);if(!buildMtime.ok)return planeCheckFinding({check:"executor-build",severity:"blocking",message:`the executor build entrypoint is missing or unreadable at mcp_server/build/index.js \u2014 run \`${PLANE_BUILD_REMEDIATION}\``,remediation:PLANE_BUILD_FIX_REMEDIATION},label,"the executor build entrypoint is missing or unreadable");let sourceMtime=await findNewestSourceMtime(srcDir,deps);return sourceMtime.ok?sourceMtime.mtimeMs!==null&&sourceMtime.mtimeMs>buildMtime.mtimeMs?planeCheckFinding({check:"executor-build",severity:"blocking",message:`mcp_server/build/ is STALE \u2014 a source file under mcp_server/src is newer than mcp_server/build/index.js, so executors would run old code. Run \`${PLANE_BUILD_REMEDIATION}\``,remediation:PLANE_BUILD_FIX_REMEDIATION},label,"mcp_server/build/ is stale \u2014 a source file is newer than the build entrypoint"):planeCheckPassed("executor-build",label,"the executor build is present and current"):planeCheckFinding({check:"executor-build",severity:"blocking",message:`could not read mcp_server/src to compare against the build (${sourceMtime.error}) \u2014 run \`${PLANE_BUILD_REMEDIATION}\``,remediation:PLANE_BUILD_FIX_REMEDIATION},label,`the executor sources could not be read for comparison (${sourceMtime.error})`)}function checkPlaneRuntimeEntrypoint(resolution){let label="Runtime re-exec entrypoint";return resolution.ok?planeCheckPassed("runtime-entrypoint",label,"the executing build can re-enter itself"):planeCheckFinding({check:"runtime-entrypoint",severity:"blocking",message:PLANE_RUNTIME_ENTRYPOINT_REFUSAL,remediation:PLANE_BUILD_FIX_REMEDIATION},label,"the currently executing MCP build could not be re-entered")}function sanitize(err){let code=err?.code;return typeof code=="string"?code:"unreadable"}var PLANE_BUILD_REMEDIATION,EXCLUDED_DIR_NAMES,PLANE_BUILD_FIX_REMEDIATION,PLANE_RUNTIME_ENTRYPOINT_REFUSAL,init_build_freshness=__esm({"src/plane/build-freshness.ts"(){"use strict";init_types2();PLANE_BUILD_REMEDIATION="cd mcp_server && npm run build",EXCLUDED_DIR_NAMES=new Set(["node_modules","build"]);PLANE_BUILD_FIX_REMEDIATION="run `cd mcp_server && npm run build` to rebuild the executor entrypoint, then retry.";PLANE_RUNTIME_ENTRYPOINT_REFUSAL=`the currently executing MCP build could not be re-entered \u2014 \`plane up\` re-execs this package's own compiled entrypoint to create the detached runtime, and no existing entrypoint belonging to it could be found. Run \`${PLANE_BUILD_REMEDIATION}\` and retry from the rebuilt CLI.`}});import path9 from"path";function resolveRepositoryAlembicCommand(repoRoot,platform){return platform==="win32"?path9.join(repoRoot,".venv","Scripts","alembic.exe"):path9.join(repoRoot,".venv","bin","alembic")}function parseAlembicRevisions(output){let revisions=new Set;for(let rawLine of output.split(/\r?\n/)){let line=rawLine.trim();if(line.length===0||LOG_LINE_PATTERN.test(line))continue;let token=line.split(/\s+/)[0];!token||NON_REVISION_TOKENS.has(token.toLowerCase())||REVISION_PATTERN.test(token)&&revisions.add(token)}return revisions.size===0?null:[...revisions].sort()}async function checkAlembicHead(repoRoot,deps){let alembic=resolveRepositoryAlembicCommand(repoRoot,deps.platform);if(!await deps.fileExists(alembic))return unverified("the repository virtualenv Alembic executable was not found","the repository virtualenv Alembic executable was not found");let heads=await deps.execFile(alembic,["-c","alembic.ini","heads"],{cwd:repoRoot});if(!heads.ok)return unverified(`\`alembic heads\` did not complete (${heads.error})`,"`alembic heads` did not complete");let current=await deps.execFile(alembic,["-c","alembic.ini","current"],{cwd:repoRoot});if(!current.ok)return unverified(`\`alembic current\` did not complete (${current.error})`,"`alembic current` did not complete");let headRevisions=parseAlembicRevisions(heads.stdout),currentRevisions=parseAlembicRevisions(current.stdout);return headRevisions===null||currentRevisions===null?unverified("Alembic output did not contain a readable revision","Alembic output did not contain a readable revision"):headRevisions.length===currentRevisions.length&&headRevisions.every((rev,i)=>rev===currentRevisions[i])?planeCheckPassed("alembic-head",ALEMBIC_CHECK_LABEL,"the database is at the repository migration head"):planeCheckFinding({check:"alembic-head",severity:"blocking",message:`the database is not at the migration head \u2014 heads [${headRevisions.join(", ")}], current [${currentRevisions.join(", ")}]. A database behind the head blocks conductor dispatch. Run \`${PLANE_ALEMBIC_REMEDIATION}\``,remediation:PLANE_ALEMBIC_MISMATCH_REMEDIATION},ALEMBIC_CHECK_LABEL,`database at [${currentRevisions.join(", ")}], repository head [${headRevisions.join(", ")}]`)}function unverified(messageDetail,outcomeDetail){let diagnostic={check:"alembic-head",severity:"warning",message:`${PLANE_ALEMBIC_UNVERIFIED_PREFIX}: ${messageDetail}. Startup continues \u2014 verify with \`alembic -c alembic.ini heads\` and \`alembic -c alembic.ini current\` if a run later reports CONTRACT_MIGRATION_BEHIND.`,remediation:PLANE_ALEMBIC_UNVERIFIED_REMEDIATION};return planeCheckFinding(diagnostic,ALEMBIC_CHECK_LABEL,`${PLANE_ALEMBIC_UNVERIFIED_PREFIX}: ${outcomeDetail}`)}var PLANE_ALEMBIC_REMEDIATION,PLANE_ALEMBIC_UNVERIFIED_PREFIX,PLANE_ALEMBIC_MISMATCH_REMEDIATION,PLANE_ALEMBIC_UNVERIFIED_REMEDIATION,LOG_LINE_PATTERN,REVISION_PATTERN,NON_REVISION_TOKENS,ALEMBIC_CHECK_LABEL,init_alembic_head=__esm({"src/plane/alembic-head.ts"(){"use strict";init_types2();PLANE_ALEMBIC_REMEDIATION="alembic -c alembic.ini upgrade head",PLANE_ALEMBIC_UNVERIFIED_PREFIX="could not verify database migration head",PLANE_ALEMBIC_MISMATCH_REMEDIATION=`run \`${PLANE_ALEMBIC_REMEDIATION}\` to bring the database up to the migration head, then retry.`,PLANE_ALEMBIC_UNVERIFIED_REMEDIATION="verify by hand with `alembic -c alembic.ini heads` and `alembic -c alembic.ini current`; startup continues, and the server reports CONTRACT_MIGRATION_BEHIND at dispatch if the database is behind.";LOG_LINE_PATTERN=/^(INFO|WARNING|ERROR|DEBUG|CRITICAL)\b|\[alembic/i,REVISION_PATTERN=/^[0-9A-Za-z][0-9A-Za-z_.-]*$/,NON_REVISION_TOKENS=new Set(["head","heads","base","none","(head)"]);ALEMBIC_CHECK_LABEL="Database migration head"}});import path10 from"path";function getPlanePaths(repoRoot){let planeDir=path10.join(repoRoot,".bridge","plane");return{planeDir,manifestPath:path10.join(planeDir,PLANE_MANIFEST_FILENAME),logPathFor:member=>path10.join(planeDir,`${member}.log`)}}function relativeLogPathFor(member){return`${PLANE_RUNTIME_DIR}/${member}.log`}function isNonBlankTrimmedString(value){return typeof value=="string"&&value.trim().length>0&&value===value.trim()}function isPlaneMemberName(value){return typeof value!="string"?!1:value==="server"||value==="worker"||value==="observer"?!0:/^executor-[1-9][0-9]*$/.test(value)}function isPositiveInteger(value){return typeof value=="number"&&Number.isSafeInteger(value)&&value>0}function isIsoTimestamp(value){return typeof value=="string"&&value.length>0&&!Number.isNaN(Date.parse(value))}function parsePlaneManifest(value){if(typeof value!="object"||value===null||Array.isArray(value))return{ok:!1,error:"manifest is not an object"};let record=value;for(let key of Object.keys(record))if(!MANIFEST_KEYS.has(key))return{ok:!1,error:`manifest has an unsupported field '${key}'`};if(typeof record.schemaVersion!="number"||!PLANE_MANIFEST_SUPPORTED_SCHEMA_VERSIONS.includes(record.schemaVersion))return{ok:!1,error:`manifest schema version ${JSON.stringify(record.schemaVersion)} is not supported (this build reads ${PLANE_MANIFEST_SUPPORTED_SCHEMA_VERSIONS.join(", ")}). A manifest from a NEWER build must be wound down with that build's \`plane down\``};if(typeof record.planeId!="string"||!/^[0-9a-f-]{8,}$/i.test(record.planeId))return{ok:!1,error:"manifest plane identity is missing or malformed"};if(typeof record.repoRoot!="string"||record.repoRoot.length===0)return{ok:!1,error:"manifest repository root is missing"};if(!isPositiveInteger(record.supervisorPid))return{ok:!1,error:"manifest supervisor pid is not a positive integer"};if(!isPositiveInteger(record.supervisorPgid))return{ok:!1,error:"manifest supervisor process-group id is not a positive integer"};if(!isIsoTimestamp(record.createdAt)||!isIsoTimestamp(record.updatedAt))return{ok:!1,error:"manifest timestamps are missing or malformed"};if(!Array.isArray(record.members)||record.members.length===0)return{ok:!1,error:"manifest members are missing"};if(record.epicRunId!==void 0&&!isNonBlankTrimmedString(record.epicRunId))return{ok:!1,error:"manifest epic run id is malformed"};if(record.lifecycle!==void 0&&!LIFECYCLE_PHASES.has(record.lifecycle))return{ok:!1,error:"manifest lifecycle phase is malformed"};let laneScope=parseManifestLaneScope(record.laneScope);if(!laneScope.ok)return{ok:!1,error:laneScope.error};let members=[],unrecognizedMemberNames=[],seen=new Set;for(let raw of record.members){if(typeof raw!="object"||raw===null||Array.isArray(raw))return{ok:!1,error:"manifest member is not an object"};let member=raw;for(let key of Object.keys(member))if(!MEMBER_KEYS.has(key))return{ok:!1,error:`manifest member has an unsupported field '${key}'`};if(typeof member.name!="string"||member.name.length===0)return{ok:!1,error:"manifest member name is missing or not a string"};if(!isPlaneMemberName(member.name)){unrecognizedMemberNames.includes(member.name)||unrecognizedMemberNames.push(member.name);continue}if(seen.has(member.name))return{ok:!1,error:`manifest lists member '${member.name}' more than once`};if(seen.add(member.name),member.pid!==null&&!isPositiveInteger(member.pid))return{ok:!1,error:`manifest member '${member.name}' has an invalid pid`};if(typeof member.state!="string"||!VALID_STATES.has(member.state))return{ok:!1,error:`manifest member '${member.name}' has an invalid state`};if(member.exitCode!==null&&!Number.isSafeInteger(member.exitCode))return{ok:!1,error:`manifest member '${member.name}' has an invalid exit code`};if(member.exitSignal!==null&&typeof member.exitSignal!="string")return{ok:!1,error:`manifest member '${member.name}' has an invalid exit signal`};if(member.logPath!==relativeLogPathFor(member.name))return{ok:!1,error:`manifest member '${member.name}' has an unexpected log path`};members.push({name:member.name,pid:member.pid,state:member.state,exitCode:member.exitCode,exitSignal:member.exitSignal,logPath:member.logPath})}return members.length===0?{ok:!1,error:`manifest lists no member this build recognizes (unrecognized: ${unrecognizedMemberNames.join(", ")}). It was written by a newer build; wind the plane down with that build's \`plane down\``}:{ok:!0,unrecognizedMemberNames,manifest:{schemaVersion:record.schemaVersion,planeId:record.planeId,repoRoot:record.repoRoot,supervisorPid:record.supervisorPid,supervisorPgid:record.supervisorPgid,createdAt:record.createdAt,updatedAt:record.updatedAt,members,...record.epicRunId!==void 0?{epicRunId:record.epicRunId}:{},...record.lifecycle!==void 0?{lifecycle:record.lifecycle}:{},...laneScope.scope!==void 0?{laneScope:laneScope.scope}:{}}}}function parseManifestLaneScope(value){if(value===void 0)return{ok:!0};if(typeof value!="object"||value===null||Array.isArray(value))return{ok:!1,error:"manifest lane scope is not an object"};let record=value;if(record.kind==="repo-wide")return Object.keys(record).length!==1?{ok:!1,error:"manifest lane scope has unsupported fields"}:{ok:!0,scope:{kind:"repo-wide"}};if(record.kind!=="epic-runs")return{ok:!1,error:"manifest lane scope kind is malformed"};if(Object.keys(record).length!==2||!Array.isArray(record.epicRunIds))return{ok:!1,error:"manifest lane scope epic run ids are malformed"};let ids=record.epicRunIds;return ids.length===0||!ids.every(id=>isNonBlankTrimmedString(id))?{ok:!1,error:"manifest lane scope epic run ids are malformed"}:{ok:!0,scope:{kind:"epic-runs",epicRunIds:ids}}}function planeManifestLifecycle(manifest){return manifest.lifecycle??"ready"}async function readPlaneManifest(repoRoot,fs2){let{manifestPath}=getPlanePaths(repoRoot),raw;try{raw=await fs2.readFile(manifestPath)}catch(err){let code=err?.code;return code==="ENOENT"?{kind:"missing"}:{kind:"unreadable",error:typeof code=="string"?code:"read failed"}}let parsed;try{parsed=JSON.parse(raw)}catch{return{kind:"malformed",error:"manifest is not valid JSON"}}let result=parsePlaneManifest(parsed);return result.ok?{kind:"valid",manifest:result.manifest,unrecognizedMemberNames:result.unrecognizedMemberNames}:{kind:"malformed",error:result.error}}function isProcessAlive(pid,kill){if(!isPositiveInteger(pid))return"unknown";try{return kill(pid,0),"alive"}catch(err){let code=err?.code;return code==="ESRCH"?"dead":code==="EPERM"?"alive":"unknown"}}function probeManifestMembers(manifest,proc){return manifest.members.map(member=>member.state==="exited"||member.pid===null?{member,liveness:"dead"}:{member,liveness:proc.isAlive(member.pid)})}function manifestHasLiveProcess(manifest,proc){return proc.isAlive(manifest.supervisorPid)!=="dead"?!0:probeManifestMembers(manifest,proc).some(probe=>probe.liveness!=="dead")}var VALID_STATES,MANIFEST_KEYS,LIFECYCLE_PHASES,MEMBER_KEYS,init_manifest=__esm({"src/plane/manifest.ts"(){"use strict";init_types2();VALID_STATES=new Set(["spawning","running","ready","exited"]),MANIFEST_KEYS=new Set(["schemaVersion","planeId","repoRoot","supervisorPid","supervisorPgid","createdAt","updatedAt","members","epicRunId","lifecycle","laneScope"]),LIFECYCLE_PHASES=new Set(PLANE_LIFECYCLE_PHASES);MEMBER_KEYS=new Set(["name","pid","state","exitCode","exitSignal","logPath"])}});import path11 from"path";function classifyLivePlaneForAttach(repoRoot,manifest,proc){if(manifest.repoRoot!==repoRoot)return{kind:"foreign-root"};let lifecycle=planeManifestLifecycle(manifest),probes=probeManifestMembers(manifest,proc),memberAlive=name=>probes.some(probe=>probe.member.name===name&&probe.liveness==="alive");return!memberAlive("server")||!memberAlive("worker")?{kind:"not-attachable",lifecycle}:lifecycle==="control-plane-ready"?{kind:"attachable",manifest}:BOUND_RUN_ATTACHABLE_PHASES.includes(lifecycle)&&manifest.epicRunId!==void 0&&manifest.laneScope!==void 0?{kind:"attachable",manifest}:{kind:"not-attachable",lifecycle}}async function runPlanePreflight(repoRoot,deps){let diagnostics=[],outcomes=[],add=diagnostic=>{diagnostic&&diagnostics.push(diagnostic)},record=report=>(add(report.diagnostic),outcomes.push(...report.outcomes),report);if(record(await checkRepositoryRoot(repoRoot,deps)).diagnostic){for(let[check,id,label]of ROOT_DEPENDENT_CHECKS)outcomes.push({check,id,label,status:"skip",detail:PLANE_ROOT_DEPENDENT_SKIP_DETAIL});return{ok:!1,diagnostics,outcomes}}record(await checkRepositoryWorktree(repoRoot,deps)),record(await checkClaudeLogin(deps));let credentials=await checkBridgeCredentials(repoRoot,deps);outcomes.push(...credentials.outcomes);for(let advisory of credentials.advisories)add(advisory);credentials.ok||add(credentials.diagnostic),record(await checkPlaneBuildFreshness(repoRoot,{fs:deps.fs}));let runtimeEntrypoint=deps.resolveRuntimeEntrypoint();record(checkPlaneRuntimeEntrypoint(runtimeEntrypoint));let observations={};if(deps.endpoint.ok){let port=await checkServerPort(deps,deps.endpoint.endpoint);record(port),observations.serverPort=port.probe}else record(planeCheckFinding({check:"server-port",severity:"blocking",message:deps.endpoint.message,remediation:PLANE_SERVER_ENDPOINT_REMEDIATION},"Local server port","the configured local server endpoint could not be resolved"));record(await checkAlembicHead(repoRoot,{execFile:deps.execFile,fileExists:filePath=>fileExists(filePath,deps.fs),platform:deps.platform}));let existing=await checkExistingPlane(repoRoot,deps);return record(existing),observations.existingPlane=existing.observation,diagnostics.filter(d=>d.severity==="blocking").length>0||!credentials.ok||!runtimeEntrypoint.ok||!deps.endpoint.ok?{ok:!1,diagnostics,outcomes,observations}:{ok:!0,diagnostics,outcomes,observations,context:{repoRoot,repoName:credentials.repoName,endpoint:deps.endpoint.endpoint,executorEntrypoint:path11.join(repoRoot,"mcp_server","build","index.js"),runtimeEntrypoint:runtimeEntrypoint.entrypoint,bridgeApiKey:credentials.apiKey,bridgeCredentialSource:credentials.source}}}async function checkRepositoryRoot(repoRoot,deps){let label="Repository root";if(!path11.isAbsolute(repoRoot))return planeCheckFinding({check:"repository-root",severity:"blocking",message:"the repository root could not be resolved to an absolute path",remediation:PLANE_REPOSITORY_ROOT_REMEDIATION},label,"the repository root could not be resolved to an absolute path");let missing=[];for(let file of REQUIRED_REPO_FILES)await fileExists(path11.join(repoRoot,file),deps.fs)||missing.push(file);return await fileExists(path11.join(repoRoot,"mcp_server"),deps.fs)||missing.push("mcp_server/"),missing.length===0?planeCheckPassed("repository-root",label,"all Bridge API root marker files are present"):planeCheckFinding({check:"repository-root",severity:"blocking",message:`this does not look like the Bridge API repository root \u2014 missing ${missing.join(", ")}. Run \`plane up\` from the repository root.`,remediation:PLANE_REPOSITORY_ROOT_REMEDIATION},label,`missing root marker(s): ${missing.join(", ")}`)}async function checkRepositoryWorktree(repoRoot,deps){let label="Git work tree",result=await deps.execFile("git",["rev-parse","--is-inside-work-tree"],{cwd:repoRoot});return!result.ok||result.stdout.trim()!=="true"?planeCheckFinding({check:"worktree-presence",severity:"blocking",message:`${repoRoot} is not inside a Git work tree (git rev-parse --is-inside-work-tree did not report 'true'). No worktree was created \u2014 ${PLANE_WORKTREE_REMEDIATION}`,remediation:PLANE_WORKTREE_REMEDIATION},label,"this directory is not inside a Git work tree"):planeCheckPassed("worktree-presence",label,"inside a Git work tree")}async function checkClaudeLogin(deps){let label="Claude login",result=await detectClaudeLogin({homedir:deps.homedir,readFile:deps.fs.readFile});return result.detected?planeCheckPassed("claude-login",label,"a local Claude login marker was detected"):planeCheckFinding({check:"claude-login",severity:"warning",message:formatClaudeLoginAdvisory(result),remediation:PLANE_CLAUDE_LOGIN_REMEDIATION},label,"no local Claude login marker was detected")}function credentialPermissionsOutcome(advisories){return advisories.length===0?{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.permissions,label:"Bridge credential file permissions",status:"pass",detail:"the credential resolver raised no permission advisory"}:{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.permissions,label:"Bridge credential file permissions",status:"warn",detail:`the credential resolver raised ${advisories.length} permission advisory line(s)`,remediation:PLANE_CREDENTIAL_PERMISSIONS_REMEDIATION}}async function checkBridgeCredentials(repoRoot,deps){let repo=await deps.resolveRepoName({env:deps.env,cwd:repoRoot,readFile:deps.fs.readFile});if(!repo.ok)return{ok:!1,advisories:[],diagnostic:{check:"bridge-credentials",severity:"blocking",message:"the Bridge repository identity could not be resolved \u2014 set BAPI_REPO_NAME or add a valid .bridge/config at the repository root.",remediation:PLANE_REPO_IDENTITY_REMEDIATION},outcomes:[{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.identity,label:"Bridge repository identity",status:"fail",detail:"the Bridge repository identity could not be resolved",remediation:PLANE_REPO_IDENTITY_REMEDIATION},{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.credential,label:"Bridge API credential",status:"skip",detail:"not resolved \u2014 there is no repository identity to resolve a credential for"},credentialPermissionsOutcome([])]};let warnings=createResolverWarningBuffer(),result;try{result=await deps.resolveCredentials(repo.repoName,{env:deps.env,homedir:deps.homedir,platform:deps.platform,readFile:deps.fs.readFile,stat:async filePath=>{let statResult=await deps.fs.stat(filePath);return{mode:statResult.mode!==void 0?statResult.mode:511}},stderr:warnings.write})}catch{let advisories2=warnings.drain();return{ok:!1,advisories:advisories2,diagnostic:{check:"bridge-credentials",severity:"blocking",message:`Bridge credentials for target bapi:${repo.repoName} could not be resolved (resolver unavailable).`,remediation:PLANE_CREDENTIAL_REMEDIATION},outcomes:[identityResolvedOutcome(),{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.credential,label:"Bridge API credential",status:"fail",detail:"the credential resolver was unavailable",remediation:PLANE_CREDENTIAL_REMEDIATION},credentialPermissionsOutcome(advisories2)]}}if(!result.ok){let advisories2=warnings.drain();return{ok:!1,advisories:advisories2,diagnostic:{check:"bridge-credentials",severity:"blocking",message:`Bridge credentials for target bapi:${repo.repoName} could not be resolved (${result.kind}). Set BAPI_API_KEY in this shell, or store it with \`mcp-server credentials\`. A spawned shell never sees .mcp.json env.`,remediation:PLANE_CREDENTIAL_REMEDIATION},outcomes:[identityResolvedOutcome(),{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.credential,label:"Bridge API credential",status:"fail",detail:`no Bridge API credential resolved (${result.kind})`,remediation:PLANE_CREDENTIAL_REMEDIATION},credentialPermissionsOutcome(advisories2)]}}let advisories=warnings.drain();return{ok:!0,repoName:repo.repoName,apiKey:result.credentials.apiKey,source:result.credentials.source,advisories,outcomes:[identityResolvedOutcome(),{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.credential,label:"Bridge API credential",status:"pass",detail:`resolved from ${result.credentials.source} (the value is never read into a report)`},credentialPermissionsOutcome(advisories)]}}function identityResolvedOutcome(){return{check:"bridge-credentials",id:PLANE_CREDENTIAL_OUTCOME_IDS.identity,label:"Bridge repository identity",status:"pass",detail:"the Bridge repository identity resolved"}}function createResolverWarningBuffer(){let lines=[],pending="",push=line=>{let trimmed=line.replace(/\r$/,"");trimmed.length!==0&&lines.push(trimmed)};return{write:message=>{pending+=message;let segments=pending.split(`
|
|
122
|
-
`);pending=segments.pop()??"";for(let segment of segments)push(segment)},drain:()=>(pending.length>0&&(push(pending),pending=""),lines.map(message=>({check:"bridge-credentials",severity:"warning",message})))}}async function checkServerPort(deps,endpoint){let report=await checkServerPortReport(deps,endpoint);return{...report.report,probe:report.probe}}async function checkServerPortReport(deps,endpoint){let label="Local server port",target=`${endpoint.host}:${endpoint.port}`,result=await deps.probePort(endpoint.host,endpoint.port,PLANE_PORT_PROBE_TIMEOUT_MS);return result.kind==="refused"?{report:planeCheckPassed("server-port",label,`${target} is free`),probe:"refused"}:result.kind==="connected"?{report:planeCheckFinding({check:"server-port",severity:"blocking",message:`${target} is already accepting connections. That port may belong to a SIBLING WORKTREE's server \u2014 check before you kill it. Stop the existing server (or wind down its plane) and retry, or set ${PLANE_SERVER_PORT_ENV_VAR} to a free port.`,remediation:PLANE_SERVER_PORT_OCCUPIED_REMEDIATION},label,`${target} is already accepting connections`),probe:"connected"}:{report:planeCheckFinding({check:"server-port",severity:"warning",message:`could not determine whether ${target} is free (${result.error}); startup continues and uvicorn will fail loudly if the port is taken.`,remediation:PLANE_SERVER_PORT_UNKNOWN_REMEDIATION},label,`could not determine whether ${target} is free`),probe:"error"}}async function checkExistingPlane(repoRoot,deps){let label="Existing plane",read=await readPlaneManifest(repoRoot,deps.fs);return read.kind==="missing"?{...planeCheckPassed("existing-plane",label,"no plane manifest is present"),observation:{kind:"none"}}:read.kind!=="valid"?{...planeCheckFinding({check:"existing-plane",severity:"blocking",message:`an existing .bridge/plane/plane.json could not be validated (${read.error}). No process was signalled and the file was left untouched \u2014 inspect it, then remove it by hand if no plane is running.`,remediation:PLANE_MANIFEST_UNREADABLE_REMEDIATION},label,"an existing plane manifest could not be validated"),observation:{kind:"unvalidated"}}:deps.ownPlaneId!==void 0&&read.manifest.planeId===deps.ownPlaneId?{...planeCheckPassed("existing-plane",label,"the existing manifest carries this launch's own plane id"),observation:{kind:"own-plane"}}:manifestHasLiveProcess(read.manifest,deps.proc)?{...planeCheckFinding({check:"existing-plane",severity:"blocking",message:`a plane is already running (supervisor pid ${read.manifest.supervisorPid}). Run \`plane status\` to inspect it, or \`plane down\` to wind it down first.`,remediation:PLANE_ALREADY_RUNNING_REMEDIATION},label,"a plane is already running for this repository"),observation:classifyLivePlaneForAttach(repoRoot,read.manifest,deps.proc)}:{observation:{kind:"stale"},diagnostic:{check:"existing-plane",severity:"warning",message:"a previous plane manifest is present but every recorded process is gone; it will be replaced after a final liveness re-check."},outcomes:[{check:"existing-plane",id:"existing-plane",label,status:"warn",detail:"a stale plane manifest is present and will be replaced after a liveness re-check"}]}}async function fileExists(filePath,fs2){try{return await fs2.stat(filePath),!0}catch{return!1}}function mapPlanePreflightToReadinessChecks(result){let byId=new Map;for(let outcome of result?.outcomes??[])byId.has(outcome.id)||byId.set(outcome.id,outcome);return PLANE_READINESS_DESCRIPTORS.map(({id,label})=>{let outcome=byId.get(id);return outcome?createReadinessCheckSafely({id:`plane.${id}`,source:"plane",label:outcome.label||label,status:outcome.status,...outcome.detail?{detail:outcome.detail}:{},...outcome.status==="fail"?{remediation:outcome.remediation??PLANE_UNREPORTED_REMEDIATION}:outcome.status!=="pass"&&outcome.remediation?{remediation:outcome.remediation}:{}}):createReadinessCheck({id:`plane.${id}`,source:"plane",label,status:"fail",detail:PLANE_UNREPORTED_DETAIL,remediation:PLANE_UNREPORTED_REMEDIATION})})}var REQUIRED_REPO_FILES,BOUND_RUN_ATTACHABLE_PHASES,PLANE_ATTACHABLE_BASE_URL_REMEDIATION,PLANE_REPOSITORY_ROOT_REMEDIATION,PLANE_REPO_IDENTITY_REMEDIATION,PLANE_CREDENTIAL_REMEDIATION,PLANE_CREDENTIAL_PERMISSIONS_REMEDIATION,PLANE_CLAUDE_LOGIN_REMEDIATION,PLANE_SERVER_PORT_OCCUPIED_REMEDIATION,PLANE_SERVER_PORT_UNKNOWN_REMEDIATION,PLANE_SERVER_ENDPOINT_REMEDIATION,PLANE_MANIFEST_UNREADABLE_REMEDIATION,PLANE_ALREADY_RUNNING_REMEDIATION,PLANE_CREDENTIAL_OUTCOME_IDS,PLANE_ROOT_DEPENDENT_SKIP_DETAIL,ROOT_DEPENDENT_CHECKS,PLANE_PORT_PROBE_TIMEOUT_MS,PLANE_WORKTREE_REMEDIATION,PLANE_READINESS_DESCRIPTORS,PLANE_UNREPORTED_DETAIL,PLANE_UNREPORTED_REMEDIATION,init_preflight=__esm({"src/plane/preflight.ts"(){"use strict";init_types2();init_build_freshness();init_alembic_head();init_manifest();init_claude_login();init_readiness_check();REQUIRED_REPO_FILES=["main.py","worker.py","alembic.ini"],BOUND_RUN_ATTACHABLE_PHASES=["lanes-starting","lanes-ready","ready"];PLANE_ATTACHABLE_BASE_URL_REMEDIATION=`do not stop it \u2014 point BAPI_BASE_URL at the plane endpoint (http://127.0.0.1:<port>, the port ${PLANE_SERVER_PORT_ENV_VAR} or the default, with no trailing slash) and run drive-epic again to attach.`,PLANE_REPOSITORY_ROOT_REMEDIATION="run `plane up` from the Bridge API repository root (the directory holding main.py, worker.py, and alembic.ini).",PLANE_REPO_IDENTITY_REMEDIATION="set BAPI_REPO_NAME in this shell, or add a valid .bridge/config at the repository root.",PLANE_CREDENTIAL_REMEDIATION="set BAPI_API_KEY in this shell, or store it with `mcp-server credentials`; a spawned shell never sees .mcp.json env.",PLANE_CREDENTIAL_PERMISSIONS_REMEDIATION="restrict the Bridge credentials file to owner-only permissions (chmod 600), then rerun.",PLANE_CLAUDE_LOGIN_REMEDIATION="run `claude login` on this host so plane members inherit an authenticated session; startup continues either way.",PLANE_SERVER_PORT_OCCUPIED_REMEDIATION=`stop the server that owns the port (or wind down its plane) and retry, or set ${PLANE_SERVER_PORT_ENV_VAR} to a free port \u2014 the port may belong to a SIBLING WORKTREE.`,PLANE_SERVER_PORT_UNKNOWN_REMEDIATION=`retry, or set ${PLANE_SERVER_PORT_ENV_VAR} to a port you know is free; startup continues and uvicorn fails loudly if the port is taken.`,PLANE_SERVER_ENDPOINT_REMEDIATION=`set ${PLANE_SERVER_PORT_ENV_VAR} to a valid port number (1-65535), or unset it to use the default.`,PLANE_MANIFEST_UNREADABLE_REMEDIATION="inspect .bridge/plane/plane.json and remove it by hand once you have confirmed no plane is running; preflight signalled no process and changed no file.",PLANE_ALREADY_RUNNING_REMEDIATION="run `plane status` to inspect the running plane, or `plane down` to wind it down first.",PLANE_CREDENTIAL_OUTCOME_IDS={identity:"repo-identity",credential:"bridge-credentials",permissions:"credential-permissions"},PLANE_ROOT_DEPENDENT_SKIP_DETAIL="not run \u2014 every remaining check is relative to a valid repository root",ROOT_DEPENDENT_CHECKS=[["worktree-presence","worktree-presence","Git work tree"],["claude-login","claude-login","Claude login"],["bridge-credentials",PLANE_CREDENTIAL_OUTCOME_IDS.identity,"Bridge repository identity"],["bridge-credentials",PLANE_CREDENTIAL_OUTCOME_IDS.credential,"Bridge API credential"],["bridge-credentials",PLANE_CREDENTIAL_OUTCOME_IDS.permissions,"Bridge credential file permissions"],["executor-build","executor-build","Executor build freshness"],["runtime-entrypoint","runtime-entrypoint","Runtime re-exec entrypoint"],["server-port","server-port","Local server port"],["alembic-head","alembic-head","Database migration head"],["existing-plane","existing-plane","Existing plane"]],PLANE_PORT_PROBE_TIMEOUT_MS=1500;PLANE_WORKTREE_REMEDIATION="cd into the intended worktree (or create it with `git worktree add`) and rerun.";PLANE_READINESS_DESCRIPTORS=[{id:"repository-root",label:"Repository root"},{id:"worktree-presence",label:"Git work tree"},{id:"claude-login",label:"Claude login"},{id:"repo-identity",label:"Bridge repository identity"},{id:"bridge-credentials",label:"Bridge API credential"},{id:"credential-permissions",label:"Bridge credential file permissions"},{id:"executor-build",label:"Executor build freshness"},{id:"runtime-entrypoint",label:"Runtime re-exec entrypoint"},{id:"server-port",label:"Local server port"},{id:"alembic-head",label:"Database migration head"},{id:"existing-plane",label:"Existing plane"}],PLANE_UNREPORTED_DETAIL="not reported \u2014 the plane preflight produced no outcome for this prerequisite",PLANE_UNREPORTED_REMEDIATION="run `plane up` (or `epic-implementer readiness` again) to re-collect the plane preflight; this prerequisite's state is unknown, not healthy."}});var init_version_generated=__esm({"src/version.generated.ts"(){"use strict"}});var init_command_host=__esm({"src/command-host.ts"(){"use strict"}});var init_codex_skill_adapter=__esm({"src/codex-skill-adapter.ts"(){"use strict"}});var init_agents_generated=__esm({"src/agents.generated.ts"(){"use strict"}});var init_docs_generated=__esm({"src/docs.generated.ts"(){"use strict"}});var init_agent_utils=__esm({"src/agent-utils.ts"(){"use strict"}});var init_git_ignore_utils=__esm({"src/git-ignore-utils.ts"(){"use strict"}});var init_mcp_host_entry_adapter=__esm({"src/mcp-host-entry-adapter.ts"(){"use strict";init_mcp_host_targets()}});var init_init=__esm({"src/init.ts"(){"use strict";init_commands_generated();init_command_host();init_codex_skill_adapter();init_agents_generated();init_docs_generated();init_version_generated();init_agent_utils();init_bridge_config();init_git_ignore_utils();init_credential_store();init_launcher_config_inspection();init_mcp_identity();init_mcp_host_entry_adapter();init_mcp_host_targets()}});function joinPath2(base,rel){let b=base.endsWith("/")?base.slice(0,-1):base,r=rel.startsWith("/")?rel.slice(1):rel;return`${b}/${r}`}function isEnoent(err){return typeof err=="object"&&err!==null&&err.code==="ENOENT"}async function readJsonHostConfig(path15,deps){let raw;try{raw=await deps.readFile(path15)}catch(err){return isEnoent(err)?{state:"missing"}:{state:"read-error",message:"config could not be read"}}let parsed;try{parsed=JSON.parse(raw)}catch{return{state:"invalid"}}return typeof parsed!="object"||parsed===null||Array.isArray(parsed)?{state:"invalid"}:{state:"valid",value:parsed}}function escapeRegExp(value){return value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function storedProfileTokens(value){return typeof value!="string"?[]:value.split(",").map(t=>t.trim()).filter(t=>t.length>0)}function entryProfileTokens(entry){if(!entry||typeof entry!="object"||Array.isArray(entry))return null;let env=entry.env,stored=env&&typeof env=="object"&&!Array.isArray(env)?env.BRIDGE_MCP_PROFILE:void 0;return storedProfileTokens(stored)}async function inspectOneProfileConfig(projectRoot,target,token,deps){let read=await readJsonHostConfig(joinPath2(projectRoot,target.path),deps);if(read.state==="missing")return{path:target.path,state:"absent"};if(read.state!=="valid")return{path:target.path,state:"unreadable"};let root=read.value[target.topLevelKey];if(!root||typeof root!="object"||Array.isArray(root))return{path:target.path,state:"no-bridge-entry"};let servers=root,tokenSets=RECOGNIZED_SERVER_NAMES.filter(name=>Object.prototype.hasOwnProperty.call(servers,name)).map(name=>entryProfileTokens(servers[name])).filter(tokens=>tokens!==null);return tokenSets.length===0?{path:target.path,state:"no-bridge-entry"}:{path:target.path,state:tokenSets.some(tokens=>tokens.includes(token))?"token-present":"token-absent"}}async function inspectBridgeApiProfileToken(projectRoot,token,deps){let configs=[];for(let target of BRIDGE_PROFILE_TOKEN_CONFIGS)configs.push(await inspectOneProfileConfig(projectRoot,target,token,deps));return{token,configs,tokenPresent:configs.some(c=>c.state==="token-present"),bridgeEntryPresent:configs.some(c=>c.state==="token-present"||c.state==="token-absent")}}var DUPLICATE_REGISTRATION_DETAIL,BRIDGE_TABLE_PATTERNS,BRIDGE_PROFILE_TOKEN_CONFIGS,init_mcp_host_config=__esm({"src/mcp-host-config.ts"(){"use strict";init_version_generated();init_init();init_mcp_host_targets();init_mcp_host_entry_adapter();init_mcp_host_entry_adapter();init_mcp_identity();DUPLICATE_REGISTRATION_DETAIL=`both \`${MCP_SERVER_NAME}\` and \`${LEGACY_SERVER_NAMES.join("`, `")}\` are registered here; confirm which one to keep, remove the other manually, then re-run. Nothing was changed.`;BRIDGE_TABLE_PATTERNS=RECOGNIZED_SERVER_NAMES.map(name=>({name,pattern:new RegExp(`^[ \\t]*\\[mcp_servers\\.${escapeRegExp(name)}(\\.[^\\]]*)?\\][ \\t]*$`,"m")})),BRIDGE_PROFILE_TOKEN_CONFIGS=[{path:".mcp.json",topLevelKey:"mcpServers"},{path:".vscode/mcp.json",topLevelKey:"servers"},{path:".cursor/mcp.json",topLevelKey:"mcpServers"}]}});var init_command_provisioning=__esm({"src/command-provisioning.ts"(){"use strict";init_commands_generated();init_codex_skill_adapter();init_git_ignore_utils()}});var init_ticket_key_utils=__esm({"src/ticket-key-utils.ts"(){"use strict"}});var init_codex_launch_scope=__esm({"src/codex-launch-scope.ts"(){"use strict";init_bridge_config();init_mcp_host_config();init_mcp_host_targets();init_mcp_provisioning();init_mcp_identity()}});var init_claude_settings=__esm({"src/claude-settings.ts"(){"use strict"}});var init_start_tickets_conductor=__esm({"src/start-tickets-conductor.ts"(){"use strict";init_claude_settings();init_file_scope_guard();init_mcp_profile();init_start_tickets_repo()}});var WORKER_BRANCH_ENV_VAR,init_pr_base_contract=__esm({"src/pr-base-contract.ts"(){"use strict";WORKER_BRANCH_ENV_VAR="BAPI_WORKER_BRANCH"}});var INDEX_SCOPE_ENV_VAR,INDEX_SCOPE_CONFIGURATION_ERROR,init_index_scope_contract=__esm({"src/index-scope-contract.ts"(){"use strict";INDEX_SCOPE_ENV_VAR="BAPI_INDEX_SCOPE",INDEX_SCOPE_CONFIGURATION_ERROR=`${INDEX_SCOPE_ENV_VAR} is not a valid index-scope declaration. Expected a server-minted scope identity; the value was not logged.`}});var init_env_file_link=__esm({"src/env-file-link.ts"(){"use strict";init_worktree_core()}});var init_base_ref=__esm({"src/base-ref.ts"(){"use strict";init_claude_review_workflow_drift_probe();init_start_tickets_prereqs();init_claude_review_workflow_drift_probe()}});var STALE_LAUNCH_SCRIPT_MAX_AGE_MS,init_start_tickets=__esm({"src/start-tickets.ts"(){"use strict";init_version_generated();init_credential_store();init_mcp_identity();init_claude_review_workflow_drift();init_start_tickets_repo();init_mcp_provisioning();init_command_provisioning();init_mcp_server_invocation();init_ticket_key_utils();init_start_tickets_prereqs();init_agent_registry();init_mcp_host_targets();init_codex_launch_scope();init_start_tickets_conductor();init_bridge_api_client();init_pr_base_contract();init_index_scope_contract();init_worktree_core();init_env_file_link();init_base_ref();STALE_LAUNCH_SCRIPT_MAX_AGE_MS=1440*60*1e3}});var REQUIRED_ADAPTER_CAPABILITIES,init_executor_adapter=__esm({"src/agent-launchers/executor-adapter.ts"(){"use strict";REQUIRED_ADAPTER_CAPABILITIES=Object.freeze(["executable","platform","headlessInvocation","mcpScoping","mcpInitParsing","auth","authFailureDetection","denyEnforcement","redaction","lifecycle"])}});var init_executor_adapter_inspection=__esm({"src/agent-launchers/executor-adapter-inspection.ts"(){"use strict";init_executor_adapter()}});var WORKER_SENTINEL_DATABASE_NAME,WORKER_SENTINEL_DATABASE_URL,WORKER_SENTINEL_DATABASE_ENV_KEYS,EXPLICIT_DENY_KEYS,init_env=__esm({"src/executor/env.ts"(){"use strict";init_pr_base_contract();init_file_scope_guard();init_index_scope_contract();WORKER_SENTINEL_DATABASE_NAME="bridge_worker_no_database",WORKER_SENTINEL_DATABASE_URL=`postgresql://${WORKER_SENTINEL_DATABASE_NAME}@127.0.0.1:1/${WORKER_SENTINEL_DATABASE_NAME}`,WORKER_SENTINEL_DATABASE_ENV_KEYS=["DATABASE_URL","POSTGRES_DATABASE","POSTGRES_DB","PGDATABASE"],EXPLICIT_DENY_KEYS=["BRIDGE_MCP_PROFILE","CONDUCTOR_NODE_PATH","BAPI_API_KEY","ANTHROPIC_API_KEY","CLAUDE_CODE_OAUTH_TOKEN","OPENAI_API_KEY","GITHUB_TOKEN","GH_TOKEN","CLAUDE_CONFIG_DIR","XDG_CONFIG_HOME",INDEX_SCOPE_ENV_VAR,WORKER_BRANCH_ENV_VAR,...WORKER_SENTINEL_DATABASE_ENV_KEYS]}});var init_observation=__esm({"src/executor/observation.ts"(){"use strict"}});var init_job_errors=__esm({"src/executor/job-errors.ts"(){"use strict";init_observation()}});var init_permissions=__esm({"src/executor/permissions.ts"(){"use strict";init_claude_settings()}});var WORKER_GUARD_REASON_PREFIX,WORKER_GUARD_MALFORMED_LINE,init_worker_guard_hook=__esm({"src/executor/worker-guard-hook.ts"(){"use strict";WORKER_GUARD_REASON_PREFIX="bridge worker guard",WORKER_GUARD_MALFORMED_LINE=`${WORKER_GUARD_REASON_PREFIX}: payload could not be read; continuing fail-open`}});var init_process=__esm({"src/executor/process.ts"(){"use strict"}});var init_platform=__esm({"src/executor/platform.ts"(){"use strict";init_process()}});var init_claude_executor_adapter=__esm({"src/agent-launchers/claude-executor-adapter.ts"(){"use strict";init_agent_registry();init_claude_user_config_doctor();init_deny_enforcement_preflight();init_env();init_job_errors();init_permissions();init_worker_guard_hook();init_platform();init_observation();init_executor_adapter();init_mcp_identity()}});var init_executor_adapter_registry=__esm({"src/agent-launchers/executor-adapter-registry.ts"(){"use strict";init_agent_registry();init_claude_executor_adapter();init_executor_adapter()}});var init_env_flags=__esm({"src/env-flags.ts"(){"use strict"}});var init_bridge_api_urls=__esm({"src/bridge-api-urls.ts"(){"use strict"}});import{getMethodLiteral}from"@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";var init_tool_surface_gating=__esm({"src/tool-surface-gating.ts"(){"use strict"}});var init_bridge_client=__esm({"src/implement-epic/bridge-client.ts"(){"use strict";init_bridge_api_client()}});var init_checkpoint_store=__esm({"src/implement-epic/checkpoint-store.ts"(){"use strict"}});var init_lock=__esm({"src/implement-epic/lock.ts"(){"use strict"}});var init_job_types=__esm({"src/executor/job-types.ts"(){"use strict"}});var init_worker_command=__esm({"src/executor/worker-command.ts"(){"use strict";init_job_errors();init_job_types()}});var init_worker_containment_diagnostic=__esm({"src/worker-containment-diagnostic.ts"(){"use strict";init_worker_command()}});var init_agent_identity=__esm({"src/executor/agent-identity.ts"(){"use strict";init_agent_registry()}});var init_claim_scope=__esm({"src/executor/claim-scope.ts"(){"use strict"}});import{execFile as execFile2,spawn}from"node:child_process";import{promisify}from"node:util";var execFileAsync,MAX_COMMAND_BUFFER,init_deps=__esm({"src/executor/deps.ts"(){"use strict";init_mcp_server_invocation();execFileAsync=promisify(execFile2),MAX_COMMAND_BUFFER=10*1024*1024}});var init_base_url=__esm({"src/base-url.ts"(){"use strict"}});var DEFAULT_BAPI_BASE_URL,EXECUTOR_BASE_URL_REQUIRED_MESSAGE,init_credentials=__esm({"src/executor/credentials.ts"(){"use strict";init_credential_store();init_base_url();DEFAULT_BAPI_BASE_URL="https://bridgegpt-api.com",EXECUTOR_BASE_URL_REQUIRED_MESSAGE=`no Bridge API base URL configured for the executor: pass --base-url <url> or set BAPI_BASE_URL (production is ${DEFAULT_BAPI_BASE_URL}). The executor never defaults to production.`}});var init_types3=__esm({"src/executor/types.ts"(){"use strict"}});var init_http_client=__esm({"src/executor/http-client.ts"(){"use strict";init_types3();init_bridge_api_client()}});var init_preflight2=__esm({"src/executor/preflight.ts"(){"use strict";init_types();init_executor_adapter_inspection();init_executor_adapter_registry();init_agent_identity();init_credentials()}});var init_heartbeat=__esm({"src/executor/heartbeat.ts"(){"use strict";init_process();init_types3()}});function normalizeGhMergeabilityValue(value){if(typeof value!="string")return null;let trimmed=value.trim();return trimmed.length===0?null:trimmed.toUpperCase()}function parseGhPrMergeabilityFields(record){return{mergeable:normalizeGhMergeabilityValue(record.mergeable),mergeStateStatus:normalizeGhMergeabilityValue(record.mergeStateStatus)}}function isPrMergeConflict(mergeability){return mergeability.mergeable==="CONFLICTING"||mergeability.mergeStateStatus==="DIRTY"}function isLikelyGhMergeConflictOutput(output){if(!output)return!1;let stdout=typeof output.stdout=="string"?output.stdout:"",stderr=typeof output.stderr=="string"?output.stderr:"",haystack=`${stdout}
|
|
123
|
-
${stderr}`.toLowerCase();return haystack.trim().length===0?!1:MERGE_CONFLICT_OUTPUT_SIGNATURES.some(sig=>haystack.includes(sig))}var MERGE_CONFLICT_OUTPUT_SIGNATURES,init_github_mergeability=__esm({"src/conductor/github-mergeability.ts"(){"use strict";MERGE_CONFLICT_OUTPUT_SIGNATURES=["merge conflict","merge conflicts","conflicting","conflict with the base branch","not possible to fast-forward","non-fast-forward","not mergeable","is not mergeable","cannot be cleanly created","would create a merge conflict"]}});function normalizeSelectorCheckName(value){if(typeof value!="string")return null;let trimmed=value.trim();return trimmed.length>0?trimmed:null}function parseTimestamp(value){if(typeof value!="string")return null;let trimmed=value.trim();if(trimmed.length===0)return null;let millis=Date.parse(trimmed);return Number.isNaN(millis)?null:millis}function parseRecencyId(record){let candidates=[record.recency_id,record.id,record.check_suite_id],suite=record.check_suite;suite!==null&&typeof suite=="object"&&candidates.push(suite.id);for(let candidate of candidates){if(typeof candidate=="number"&&Number.isFinite(candidate))return candidate;if(typeof candidate=="string"&&INTEGER_TEXT.test(candidate.trim()))return Number.parseInt(candidate.trim(),10)}return null}function recencyKey(record){let started=parseTimestamp(record.started_at),completed=parseTimestamp(record.completed_at),id=parseRecencyId(record);return[started!==null?[1,started]:[0,0],completed!==null?[1,completed]:[0,0],id!==null?[1,id]:[0,0]]}function compareRecency(a,b){let ka=recencyKey(a),kb=recencyKey(b);for(let i=0;i<ka.length;i+=1){if(ka[i][0]!==kb[i][0])return ka[i][0]-kb[i][0];if(ka[i][1]!==kb[i][1])return ka[i][1]<kb[i][1]?-1:1}return 0}function outcomeKey(record){let status=typeof record.status=="string"?record.status.toLowerCase():"",conclusion=typeof record.conclusion=="string"?record.conclusion.toLowerCase():"";return status+" "+conclusion}function looksSuccessful(record){let conclusion=typeof record.conclusion=="string"?record.conclusion.toLowerCase():"",status=typeof record.status=="string"?record.status.toLowerCase():"",bucket=typeof record.bucket=="string"?record.bucket.toLowerCase():"";return record.green===!0||conclusion==="success"||status==="success"||bucket==="pass"}function selectLatestChecks(records){let grouped=new Map,order=[];for(let record of records){if(record===null||typeof record!="object"||Array.isArray(record))continue;let name=normalizeSelectorCheckName(record.name);if(name===null)continue;let bucket=grouped.get(name);bucket===void 0?(grouped.set(name,[record]),order.push(name)):bucket.push(record)}let selected=[],ambiguousNames=new Set;for(let name of order){let candidates=grouped.get(name);if(candidates.length===1){selected.push(candidates[0]);continue}let best=candidates[0];for(let i=1;i<candidates.length;i+=1)compareRecency(candidates[i],best)>0&&(best=candidates[i]);let tied=candidates.filter(c=>compareRecency(c,best)===0);tied.length>1&&new Set(tied.map(outcomeKey)).size>1&&(ambiguousNames.add(name),best=tied.find(c=>!looksSuccessful(c))??tied[0]),selected.push(best)}return{selected,ambiguousNames}}function selectLatestChecksByName(records){let{selected,ambiguousNames}=selectLatestChecks(records),byName=new Map;for(let record of selected){let name=normalizeSelectorCheckName(record.name);name===null||ambiguousNames.has(name)||byName.set(name,record)}return{byName,ambiguousNames}}var INTEGER_TEXT,init_latest_check_selector=__esm({"src/conductor/latest-check-selector.ts"(){"use strict";INTEGER_TEXT=/^[0-9]+$/}});import{spawn as spawn2}from"child_process";function defaultSleep(ms){return new Promise(resolve2=>setTimeout(resolve2,ms))}function sanitizeWaitMs(value,fallback){return typeof value=="number"&&Number.isFinite(value)&&value>=0?Math.floor(value):fallback}function resolveLocalMergeMethod(value){return typeof value=="string"&&MERGE_METHODS.has(value)?value:"squash"}async function defaultRunCommand(cmd,args,env,signal){return await new Promise(resolve2=>{let settled=!1,timedOut=!1,stdout="",stderr="",child=spawn2(cmd,args,{env:{...process.env,...env}}),killChild=()=>{try{child.kill("SIGKILL")}catch{}},timer=setTimeout(()=>{timedOut=!0,killChild()},DEFAULT_COMMAND_TIMEOUT_MS),onAbort=()=>{timedOut=!0,killChild()},finish=result=>{settled||(settled=!0,clearTimeout(timer),signal&&signal.removeEventListener("abort",onAbort),resolve2(result))};signal&&(signal.aborted?onAbort():signal.addEventListener("abort",onAbort)),child.stdout?.setEncoding("utf8"),child.stderr?.setEncoding("utf8"),child.stdout?.on("data",chunk=>{stdout+=chunk}),child.stderr?.on("data",chunk=>{stderr+=chunk}),child.on("error",()=>{finish({status:null,stdout,stderr,timedOut})}),child.on("close",(code,sig)=>{finish({status:code,stdout,stderr,timedOut:timedOut||sig==="SIGKILL"||sig==="SIGTERM"})})})}function buildResponse(request,status,reason,terminal,ledgerEvents){return{action_key:request.action_key,repo_name:request.repo_name,pr_number:request.pr_number,expected_head_sha:request.expected_head_sha,status,reason,terminal,ledger_events:ledgerEvents}}function isNeutralCheckRecord(record){if(!record)return!1;let conclusion=typeof record.conclusion=="string"?record.conclusion.trim().toLowerCase():"";return NEUTRAL_CHECK_CONCLUSIONS.has(conclusion)}function allRequiredChecksGreen(pollResponse,requiredChecks){if(pollResponse===null||typeof pollResponse!="object")return!1;let obj=pollResponse,maybeDetail=obj.detail;maybeDetail&&typeof maybeDetail=="object"&&(Array.isArray(maybeDetail.checks)||"all_passed"in maybeDetail)&&(obj=maybeDetail);let rawChecks=Array.isArray(obj.checks)?obj.checks:[];if(requiredChecks.length===0)return obj.all_passed===!0;let meaningfulNames=new Set;for(let record of rawChecks){if(record===null||typeof record!="object"||Array.isArray(record))continue;let name=normalizeSelectorCheckName(record.name);name!==null&&!isNeutralCheckRecord(record)&&meaningfulNames.add(name)}let arbitrated=rawChecks.filter(record=>{if(record===null||typeof record!="object"||Array.isArray(record))return!0;let name=normalizeSelectorCheckName(record.name);return name===null?!0:!(isNeutralCheckRecord(record)&&meaningfulNames.has(name))}),{byName}=selectLatestChecksByName(arbitrated),isGreen=c=>{if(!c)return!1;let conclusion=typeof c.conclusion=="string"?c.conclusion.toLowerCase():"",status=typeof c.status=="string"?c.status.toLowerCase():"",bucket=typeof c.bucket=="string"?c.bucket.toLowerCase():"";return c.green===!0||conclusion==="success"||status==="success"||bucket==="pass"||isNeutralCheckRecord(c)};return requiredChecks.every(name=>isGreen(byName.get(name)))}function extractMergeCommitOid(parsed){let mc=parsed?.mergeCommit;if(mc&&typeof mc=="object"&&typeof mc.oid=="string")return mc.oid}function isMergedAtExpectedHead(state,headOid,expectedSha){return typeof state=="string"&&state.toUpperCase()==="MERGED"&&typeof headOid=="string"&&headOid.toLowerCase()===expectedSha.toLowerCase()}function readBoundedRefName(value){if(typeof value!="string")return;let trimmed=value.trim();return trimmed.length>0?trimmed:void 0}async function readPrMergeState(run,ghEnv,pr,json=PR_STATE_JSON){let view=await run("gh",["pr","view",String(pr),"--json",json],ghEnv);if(view.timedOut)return{ok:!1,reason:"gh_pr_view_timeout"};if(view.status!==0)return{ok:!1,reason:"gh_pr_view_failed"};try{let parsed=JSON.parse(view.stdout);return{ok:!0,headOid:parsed.headRefOid,state:parsed.state,mergeCommitOid:extractMergeCommitOid(parsed),baseRefName:readBoundedRefName(parsed.baseRefName),headRefName:readBoundedRefName(parsed.headRefName),raw:parsed}}catch{return{ok:!1,reason:"gh_pr_view_unparseable"}}}function buildAlreadyMergedResponse(request,baseDetails,mergeCommitSha){let details={...baseDetails,already_merged:!0,...mergeCommitSha?{merge_commit_sha:mergeCommitSha}:{}};return buildResponse(request,"succeeded",null,!0,[{type:"merge.succeeded",status:"succeeded",details}])}function ciPollFailureDetailFromError(err){if(!(err instanceof ConductorBridgeApiError))return;let kind=err.kind;if(kind!=="timeout"&&kind!=="network"&&kind!=="unauthorized"&&kind!=="server"&&kind!=="http")return;let detail={kind,diagnostic:safeDiagnosticMessage(err,"ci_poll_failed")};return typeof err.status=="number"&&Number.isInteger(err.status)&&(detail.status=err.status),detail}function ciPollFailureReasonFromDetail(detail){if(!detail)return"ci_poll_failed";switch(detail.kind){case"timeout":return"ci_poll_timeout";case"network":return"ci_poll_network";case"unauthorized":return"ci_poll_unauthorized";case"server":return"ci_poll_server";case"http":return typeof detail.status=="number"&&Number.isInteger(detail.status)?`ci_poll_http_${detail.status}`:"ci_poll_http"}}function isAmbiguousCiPollFailureReason(reason){return reason.startsWith("ci_poll_")}async function waitForRequiredChecksGreen(pollCi,access,expectedSha,requiredChecks,timeoutMs,pollIntervalMs,sleep2,now,signal){let start=now();for(;;){if(signal?.aborted)return{ok:!1,reason:"merge_aborted"};let pollResponse;try{pollResponse=await pollCi(access,expectedSha)}catch(err){let pollFailure=ciPollFailureDetailFromError(err);return{ok:!1,reason:ciPollFailureReasonFromDetail(pollFailure),pollFailure}}if(allRequiredChecksGreen(pollResponse,requiredChecks))return{ok:!0};if(now()-start>=timeoutMs)return{ok:!1,reason:"ci_not_green"};if(await sleep2(pollIntervalMs),signal?.aborted)return{ok:!1,reason:"merge_aborted"}}}function makeLocalMergeExecutor(options={},deps={}){let method=resolveLocalMergeMethod(options.method),expectedBaseBranch=readBoundedRefName(options.expectedBaseBranch),expectedHeadBranch=readBoundedRefName(options.expectedHeadBranch),rawRun=deps.runCommand??defaultRunCommand,run=(cmd,args,env)=>Promise.resolve(rawRun(cmd,args,env,deps.signal)),pollCi=deps.pollCi??pollCiChecksForCommit,sleep2=deps.sleep??defaultSleep,now=deps.now??(()=>Date.now()),signal=deps.signal,ciWaitTimeoutMs=sanitizeWaitMs(options.ciWaitTimeoutMs,DEFAULT_CI_WAIT_TIMEOUT_MS),ciWaitPollIntervalMs=sanitizeWaitMs(options.ciWaitPollIntervalMs,DEFAULT_CI_WAIT_POLL_INTERVAL_MS),ghEnv={...deps.env,GH_PROMPT_DISABLED:"1",GH_NO_UPDATE_NOTIFIER:"1"};return async(access,request)=>{let pr=request.pr_number,expectedSha=request.expected_head_sha,requiredChecks=request.gate?.required_checks??[],baseDetails={action_key:request.action_key,repo:request.repo_name,pr_number:pr,expected_head_sha:expectedSha,merge_method:method,executor:"local"},fail=(reason,pollFailure)=>{let details=pollFailure?{...baseDetails,poll_error:{kind:pollFailure.kind,...typeof pollFailure.status=="number"?{status:pollFailure.status}:{},diagnostic:pollFailure.diagnostic}}:baseDetails;return buildResponse(request,"failed",reason,!1,[{type:"merge.failed",status:"failed",reason,details}])},verifyMergedStateAfterAmbiguousFailure=async()=>{let read=await readPrMergeState(run,ghEnv,pr);return read.ok&&isMergedAtExpectedHead(read.state,read.headOid,expectedSha)?buildAlreadyMergedResponse(request,baseDetails,read.mergeCommitOid):null};if(signal?.aborted)return fail("merge_aborted");if(options.approvalRequired)return buildResponse(request,"pending_approval","local_merge_approval_required",!1,[{type:"merge.pending_approval",status:"pending_approval",reason:"local_merge_approval_required",details:baseDetails}]);let firstRead=await readPrMergeState(run,ghEnv,pr);if(!firstRead.ok){let verified=await verifyMergedStateAfterAmbiguousFailure();return verified||fail(firstRead.reason)}if(isMergedAtExpectedHead(firstRead.state,firstRead.headOid,expectedSha))return buildAlreadyMergedResponse(request,baseDetails,firstRead.mergeCommitOid);let firstRefMismatch=findRefMismatch(expectedBaseBranch,expectedHeadBranch,firstRead);if(firstRefMismatch)return buildRefMismatchResponse(request,baseDetails,firstRefMismatch);if(typeof firstRead.headOid!="string"||firstRead.headOid.toLowerCase()!==expectedSha.toLowerCase())return fail("head_drift");if(typeof firstRead.state=="string"&&firstRead.state.toUpperCase()!=="OPEN")return fail("pr_not_open");if(!options.skipCiWait){let ciWait=await waitForRequiredChecksGreen(pollCi,access,expectedSha,requiredChecks,ciWaitTimeoutMs,ciWaitPollIntervalMs,sleep2,now,signal);if(!ciWait.ok){if(isAmbiguousCiPollFailureReason(ciWait.reason)){let verified=await verifyMergedStateAfterAmbiguousFailure();if(verified)return verified}return fail(ciWait.reason,ciWait.pollFailure)}let secondRead=await readPrMergeState(run,ghEnv,pr);if(!secondRead.ok){let verified=await verifyMergedStateAfterAmbiguousFailure();return verified||fail(secondRead.reason)}if(isMergedAtExpectedHead(secondRead.state,secondRead.headOid,expectedSha))return buildAlreadyMergedResponse(request,baseDetails,secondRead.mergeCommitOid);let secondRefMismatch=findRefMismatch(expectedBaseBranch,expectedHeadBranch,secondRead);if(secondRefMismatch)return buildRefMismatchResponse(request,baseDetails,secondRefMismatch);if(typeof secondRead.headOid!="string"||secondRead.headOid.toLowerCase()!==expectedSha.toLowerCase())return fail("head_drift");if(typeof secondRead.state=="string"&&secondRead.state.toUpperCase()!=="OPEN")return fail("pr_not_open")}if(signal?.aborted)return fail("merge_aborted");let merge=await run("gh",["pr","merge",String(pr),`--${method}`,"--match-head-commit",expectedSha],ghEnv);if(merge.status!==0){if(merge.timedOut){let verified=await verifyMergedStateAfterAmbiguousFailure();if(verified)return verified;let reason="gh_merge_timeout";return buildResponse(request,"failed",reason,!1,[{type:"merge.attempted",status:"attempted",details:baseDetails},{type:"merge.failed",status:"failed",reason,details:baseDetails}])}if(isLikelyGhMergeConflictOutput(merge))return buildConflictResponse(request,baseDetails,expectedSha,{mergeable:null,mergeStateStatus:null});let recheck=await readPrMergeState(run,ghEnv,pr,PR_STATE_MERGEABILITY_JSON);if(recheck.ok){if(isMergedAtExpectedHead(recheck.state,recheck.headOid,expectedSha))return buildAlreadyMergedResponse(request,baseDetails,recheck.mergeCommitOid);let mergeability={mergeable:null,mergeStateStatus:null};try{mergeability=parseGhPrMergeabilityFields(recheck.raw)}catch{}if(isPrMergeConflict(mergeability))return buildConflictResponse(request,baseDetails,expectedSha,mergeability)}let mergeFailReason="gh_merge_failed";return buildResponse(request,"failed",mergeFailReason,!1,[{type:"merge.attempted",status:"attempted",details:baseDetails},{type:"merge.failed",status:"failed",reason:mergeFailReason,details:baseDetails}])}let mergeCommitSha,post=await run("gh",["pr","view",String(pr),"--json","mergeCommit"],ghEnv);if(post.status===0)try{mergeCommitSha=extractMergeCommitOid(JSON.parse(post.stdout))}catch{}let succeededDetails={...baseDetails,...mergeCommitSha?{merge_commit_sha:mergeCommitSha}:{}};return buildResponse(request,"succeeded",null,!0,[{type:"merge.attempted",status:"attempted",details:baseDetails},{type:"merge.succeeded",status:"succeeded",details:succeededDetails}])}}function buildConflictResponse(request,baseDetails,expectedSha,mergeability){let reason="gh_merge_conflict",conflictDetails={...baseDetails,head_sha:expectedSha,...mergeability.mergeable?{mergeable:mergeability.mergeable}:{},...mergeability.mergeStateStatus?{mergeStateStatus:mergeability.mergeStateStatus}:{}};return buildResponse(request,"failed",reason,!1,[{type:"merge.attempted",status:"attempted",details:baseDetails},{type:"merge.conflict",status:"failed",reason,details:conflictDetails}])}function findRefMismatch(expectedBaseBranch,expectedHeadBranch,actual){if(expectedBaseBranch!==void 0&&actual.baseRefName!==expectedBaseBranch)return{field:"base",expected:expectedBaseBranch,actual:actual.baseRefName??""};if(expectedHeadBranch!==void 0&&actual.headRefName!==expectedHeadBranch)return{field:"head",expected:expectedHeadBranch,actual:actual.headRefName??""}}function buildRefMismatchResponse(request,baseDetails,mismatch){let reason="ref_mismatch",details={...baseDetails,mismatched_field:mismatch.field,[`expected_${mismatch.field}_branch`]:mismatch.expected,[`actual_${mismatch.field}_branch`]:mismatch.actual,message:`No provider merge was attempted: the pull request's current ${mismatch.field} branch does not match the run's expected ${mismatch.field} branch. Rebuild or cherry-pick the change against the expected run base rather than retargeting the pull request in the GitHub UI.`};return buildResponse(request,"failed",reason,!1,[{type:"merge.failed",status:"failed",reason,details}])}async function preflightLocalGh(run,ghEnv){let version;try{version=await run("gh",["--version"],ghEnv)}catch{return{ok:!1,reason:"local_gh_unavailable"}}if(version.status!==0)return{ok:!1,reason:"local_gh_unavailable"};let auth;try{auth=await run("gh",["auth","status"],ghEnv)}catch{return{ok:!1,reason:"local_gh_unauthenticated"}}return auth.status!==0?{ok:!1,reason:"local_gh_unauthenticated"}:{ok:!0}}async function runApprovedLocalMerge(request,options={},deps={}){let ghEnv={...deps.env,GH_PROMPT_DISABLED:"1",GH_NO_UPDATE_NOTIFIER:"1"},rawRun=deps.runCommand??defaultRunCommand,preflight=await preflightLocalGh((cmd,args,env)=>Promise.resolve(rawRun(cmd,args,env,deps.signal)),ghEnv);return preflight.ok?makeLocalMergeExecutor({method:options.method,skipCiWait:!0},deps)({get baseUrl(){throw new Error("runApprovedLocalMerge must not poll CI")},get apiKey(){throw new Error("runApprovedLocalMerge must not poll CI")},get repoName(){throw new Error("runApprovedLocalMerge must not poll CI")}},request):buildResponse(request,"failed",preflight.reason,!1,[{type:"merge.failed",status:"failed",reason:preflight.reason,details:{action_key:request.action_key,repo:request.repo_name,pr_number:request.pr_number,expected_head_sha:request.expected_head_sha,executor:"local"}}])}var MERGE_METHODS,PR_STATE_JSON,PR_STATE_MERGEABILITY_JSON,DEFAULT_COMMAND_TIMEOUT_MS,DEFAULT_CI_WAIT_TIMEOUT_MS,DEFAULT_CI_WAIT_POLL_INTERVAL_MS,NEUTRAL_CHECK_CONCLUSIONS,init_local_merge=__esm({"src/conductor/local-merge.ts"(){"use strict";init_bridge_api_client();init_github_mergeability();init_latest_check_selector();MERGE_METHODS=new Set(["squash","merge","rebase"]),PR_STATE_JSON="headRefOid,state,mergeCommit,baseRefName,headRefName",PR_STATE_MERGEABILITY_JSON="headRefOid,state,mergeCommit,mergeable,mergeStateStatus,baseRefName,headRefName",DEFAULT_COMMAND_TIMEOUT_MS=6e4,DEFAULT_CI_WAIT_TIMEOUT_MS=18e4,DEFAULT_CI_WAIT_POLL_INTERVAL_MS=5e3;NEUTRAL_CHECK_CONCLUSIONS=new Set(["skipped","neutral"])}});var init_epic_integration_pr=__esm({"src/epic-integration-pr.ts"(){"use strict"}});var init_base_branch=__esm({"src/executor/base-branch.ts"(){"use strict";init_base_ref()}});var init_merge_job=__esm({"src/executor/merge-job.ts"(){"use strict";init_local_merge();init_bridge_api_client();init_epic_integration_pr();init_job_errors();init_base_branch()}});var init_worktree_inspection=__esm({"src/executor/worktree-inspection.ts"(){"use strict";init_job_errors()}});var init_resume_pre_spawn=__esm({"src/executor/resume-pre-spawn.ts"(){"use strict";init_worktree_core();init_job_errors();init_worktree_inspection()}});var init_prompt_spec=__esm({"src/executor/prompt-spec.ts"(){"use strict";init_job_errors()}});var init_results=__esm({"src/executor/results.ts"(){"use strict"}});var init_terminal_mutation=__esm({"src/executor/terminal-mutation.ts"(){"use strict";init_types3()}});var init_verdict_artifact=__esm({"src/executor/verdict-artifact.ts"(){"use strict";init_job_errors();init_worktree_inspection()}});var init_stale_artifacts=__esm({"src/executor/stale-artifacts.ts"(){"use strict";init_verdict_artifact();init_worktree_inspection()}});var init_env_file_guard=__esm({"src/executor/env-file-guard.ts"(){"use strict";init_worktree_inspection()}});var init_worker_log=__esm({"src/executor/worker-log.ts"(){"use strict";init_worktree_inspection()}});var init_worktree_lock=__esm({"src/executor/worktree-lock.ts"(){"use strict";init_worktree_inspection()}});var init_job_log_registry=__esm({"src/executor/job-log-registry.ts"(){"use strict";init_worktree_inspection()}});var init_viewer_tabs=__esm({"src/executor/viewer-tabs.ts"(){"use strict";init_start_tickets()}});var init_interrupted_worktree=__esm({"src/executor/interrupted-worktree.ts"(){"use strict"}});var init_merge_tree_classifier=__esm({"src/executor/merge-tree-classifier.ts"(){"use strict";init_file_scope_guard()}});var init_reconcile_overlap_governance=__esm({"src/executor/reconcile-overlap-governance.ts"(){"use strict"}});var init_reconcile_overlap_types=__esm({"src/executor/reconcile-overlap-types.ts"(){"use strict"}});var init_worker_finalization=__esm({"src/executor/worker-finalization.ts"(){"use strict";init_job_errors();init_job_types()}});var init_reconcile_overlap_job=__esm({"src/executor/reconcile-overlap-job.ts"(){"use strict";init_bridge_api_client();init_file_scope_guard();init_local_merge();init_env();init_job_errors();init_merge_tree_classifier();init_reconcile_overlap_governance();init_reconcile_overlap_types();init_worker_finalization()}});var init_index_scope=__esm({"src/executor/index-scope.ts"(){"use strict";init_index_scope_contract()}});var init_worktree=__esm({"src/executor/worktree.ts"(){"use strict";init_base_ref();init_claude_review_workflow_drift();init_start_tickets_prereqs();init_worktree_core();init_command_provisioning()}});var REQUIRED_MCP_REGISTRATION_MISSING_MESSAGE,init_job_runner=__esm({"src/executor/job-runner.ts"(){"use strict";init_heartbeat();init_job_errors();init_merge_job();init_observation();init_mcp_provisioning();init_executor_adapter_registry();init_executor_adapter();init_agent_identity();init_process();init_resume_pre_spawn();init_prompt_spec();init_start_tickets_conductor();init_results();init_terminal_mutation();init_stale_artifacts();init_env_file_guard();init_verdict_artifact();init_worker_log();init_worktree_lock();init_job_log_registry();init_viewer_tabs();init_job_types();init_interrupted_worktree();init_reconcile_overlap_job();init_base_branch();init_index_scope();init_worker_finalization();init_worktree();init_pr_base_contract();init_worker_command();init_observation();init_mcp_identity();REQUIRED_MCP_REGISTRATION_MISSING_MESSAGE=`the required '${MCP_SERVER_NAME}' MCP registration is missing or unreadable in the prepared worktree; a worker loads MCP servers strictly from that file, so refusing to spawn a worker that would run without Bridge tools`}});var init_live_worker_registry=__esm({"src/executor/live-worker-registry.ts"(){"use strict"}});var EXECUTOR_WORKTREE_GC_IDLE_MS,init_worktree_gc=__esm({"src/executor/worktree-gc.ts"(){"use strict";init_worktree_inspection();EXECUTOR_WORKTREE_GC_IDLE_MS=1440*60*1e3}});var init_runner=__esm({"src/executor/runner.ts"(){"use strict";init_preflight2();init_job_runner();init_job_log_registry();init_live_worker_registry();init_worktree_gc();init_base_ref();init_epic_integration_pr()}});var init_watch_cli=__esm({"src/executor/watch-cli.ts"(){"use strict";init_job_log_registry()}});var init_cli=__esm({"src/executor/cli.ts"(){"use strict";init_version_generated();init_start_tickets_prereqs();init_start_tickets_repo();init_agent_identity();init_claim_scope();init_deps();init_credentials();init_http_client();init_platform();init_runner();init_watch_cli()}});function executorLaunchdDirForHome(homeDir){return pathApiForPlatform("darwin").join(homeDir,...LAUNCHD_DIR_SEGMENTS)}function executorSystemdDirForHome(homeDir){return pathApiForPlatform("linux").join(homeDir,...SYSTEMD_DIR_SEGMENTS)}function executorIdFromLaunchdFilename(filename){if(!filename.startsWith(EXECUTOR_LAUNCHD_LABEL_PREFIX)||!filename.endsWith(EXECUTOR_LAUNCHD_FILENAME_SUFFIX))return null;let id=filename.slice(EXECUTOR_LAUNCHD_LABEL_PREFIX.length,filename.length-EXECUTOR_LAUNCHD_FILENAME_SUFFIX.length);return id.length>0?id:null}function executorIdFromSystemdFilename(filename){if(!filename.startsWith(EXECUTOR_SYSTEMD_UNIT_PREFIX)||!filename.endsWith(EXECUTOR_SYSTEMD_UNIT_SUFFIX))return null;let id=filename.slice(EXECUTOR_SYSTEMD_UNIT_PREFIX.length,filename.length-EXECUTOR_SYSTEMD_UNIT_SUFFIX.length);return id.length>0?id:null}function xmlUnescape(value){return value.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}function readArgumentContract(args){let repos=[],executorId=null;for(let i=0;i<args.length;i++)args[i]==="--repo"&&typeof args[i+1]=="string"?repos.push(args[++i]):args[i]==="--executor-id"&&typeof args[i+1]=="string"&&(executorId=args[++i]);return{repos,executorId}}function inspectLaunchdPlist(content){let problems=[],envMatch=content.match(new RegExp(`<key>${EXECUTOR_SERVICE_BASE_URL_ENV}</key>\\s*<string>([^<]*)</string>`)),baseUrl=envMatch?xmlUnescape(envMatch[1]):null;baseUrl===null&&problems.push(`no ${EXECUTOR_SERVICE_BASE_URL_ENV} entry found in the plist`);let arrayMatch=content.match(/<key>ProgramArguments<\/key>\s*<array>([\s\S]*?)<\/array>/),args=[];arrayMatch?args=Array.from(arrayMatch[1].matchAll(/<string>([^<]*)<\/string>/g)).map(m=>xmlUnescape(m[1])):problems.push("no ProgramArguments array found in the plist");let{repos,executorId}=readArgumentContract(args);return{ok:problems.length===0,baseUrl,repos,executorId,problems}}function splitSystemdTokens(value){let tokens=[],current="",inQuotes=!1,started=!1;for(let i=0;i<value.length;i++){let ch=value[i];ch==="\\"&&i+1<value.length?(current+=value[++i],started=!0):ch==="%"&&value[i+1]==="%"?(current+="%",i++,started=!0):ch==='"'?(inQuotes=!inQuotes,started=!0):!inQuotes&&/\s/.test(ch)?(started&&tokens.push(current),current="",started=!1):(current+=ch,started=!0)}return started&&tokens.push(current),tokens}function inspectSystemdService(content){let problems=[],lines=content.split(/\r?\n/),envLine=lines.find(l=>l.startsWith(`Environment=${EXECUTOR_SERVICE_BASE_URL_ENV}=`)),baseUrl=null;if(envLine){let raw=envLine.slice(`Environment=${EXECUTOR_SERVICE_BASE_URL_ENV}=`.length);baseUrl=splitSystemdTokens(raw)[0]??null}(baseUrl===null||baseUrl.length===0)&&(baseUrl=null,problems.push(`no ${EXECUTOR_SERVICE_BASE_URL_ENV} directive found in the unit`));let execLine=lines.find(l=>l.startsWith("ExecStart=")),args=[];execLine?args=splitSystemdTokens(execLine.slice(10)):problems.push("no ExecStart directive found in the unit");let{repos,executorId}=readArgumentContract(args);return{ok:problems.length===0,baseUrl,repos,executorId,problems}}function inspectExecutorServiceArtifact(kind,content){try{return kind==="launchd-plist"?inspectLaunchdPlist(content):inspectSystemdService(content)}catch{return{ok:!1,baseUrl:null,repos:[],executorId:null,problems:["unit content could not be parsed"]}}}var EXECUTOR_LAUNCHD_LABEL_PREFIX,EXECUTOR_LAUNCHD_FILENAME_SUFFIX,EXECUTOR_SYSTEMD_UNIT_PREFIX,EXECUTOR_SYSTEMD_UNIT_SUFFIX,EXECUTOR_SERVICE_BASE_URL_ENV,LAUNCHD_DIR_SEGMENTS,SYSTEMD_DIR_SEGMENTS,init_service_unit=__esm({"src/executor/service-unit.ts"(){"use strict";init_platform_escaping();init_worktree_core();init_mcp_server_invocation();init_cli();init_credentials();EXECUTOR_LAUNCHD_LABEL_PREFIX="com.bridge-gpt.executor.",EXECUTOR_LAUNCHD_FILENAME_SUFFIX=".plist",EXECUTOR_SYSTEMD_UNIT_PREFIX="bridge-gpt-executor-",EXECUTOR_SYSTEMD_UNIT_SUFFIX=".service",EXECUTOR_SERVICE_BASE_URL_ENV="BAPI_BASE_URL",LAUNCHD_DIR_SEGMENTS=["Library","LaunchAgents"],SYSTEMD_DIR_SEGMENTS=[".config","systemd","user"]}});var init_service_lifecycle=__esm({"src/executor/service-lifecycle.ts"(){"use strict";init_platform_escaping()}});var init_install_preflight=__esm({"src/executor/install-preflight.ts"(){"use strict";init_claude_login();init_platform()}});var init_executor=__esm({"src/executor/index.ts"(){"use strict";init_cli();init_runner();init_service_unit();init_service_lifecycle();init_install_preflight();init_watch_cli()}});var init_stale_worktree_doctor=__esm({"src/stale-worktree-doctor.ts"(){"use strict";init_worktree_core()}});import path12 from"path";function resolveExecutorServiceConvention(platform,homeDir){return platform==="darwin"?{dir:executorLaunchdDirForHome(homeDir),kind:"launchd-plist",idFromFilename:executorIdFromLaunchdFilename}:platform==="linux"?{dir:executorSystemdDirForHome(homeDir),kind:"systemd-service",idFromFilename:executorIdFromSystemdFilename}:null}async function probeRepoCredential(repo,deps,credDeps){let target=`bapi:${repo}`,resolve2=deps.resolveCredentials??resolveBapiCredentials;try{let result=await resolve2(repo,credDeps);return result.ok?{repo,target,resolved:!0,source:String(result.credentials.source)}:{repo,target,resolved:!1,kind:String(result.kind)}}catch{return{repo,target,resolved:!1,kind:"unavailable"}}}async function collectExecutorServiceDiagnostics(deps){if(deps.platform==="win32")return{status:"skipped",reason:"Windows executor services are set up manually through Task Scheduler, so there is no generated unit to enumerate (`executor install-service` prints the command line instead)."};let convention=resolveExecutorServiceConvention(deps.platform,deps.homedir());if(!convention)return{status:"skipped",reason:`platform '${deps.platform}' has no generated executor service format.`};let entries;try{entries=await deps.readdir(convention.dir)}catch{return{status:"skipped",reason:`no executor service units found (${convention.dir} is absent or unreadable).`}}let matching=entries.filter(name=>convention.idFromFilename(name)!==null).sort((a,b)=>a<b?-1:a>b?1:0);if(matching.length===0)return{status:"skipped",reason:`no executor service units found in ${convention.dir}.`};let credDeps={env:deps.env,homedir:deps.homedir,platform:deps.platform,readFile:deps.readFile,stat:deps.stat,stderr:()=>{}},pathApi=path12.posix,units=[],warnings=[];for(let name of matching){let unitPath=pathApi.join(convention.dir,name),executorId=convention.idFromFilename(name)??name;try{await deps.stat(unitPath)}catch{warnings.push(`${unitPath}: disappeared or became unreadable during collection.`);continue}let content;try{content=await deps.readFile(unitPath)}catch{units.push({path:unitPath,executorId,baseUrl:null,baseUrlClass:"missing",repos:[],credentials:[],warnings:["unit could not be read; its configuration cannot be verified."]});continue}let inspection=inspectExecutorServiceArtifact(convention.kind,content),unitWarnings=[...inspection.problems],baseUrlClass;inspection.baseUrl?inspection.baseUrl.replace(/\/+$/,"")===DEFAULT_BAPI_BASE_URL?(baseUrlClass="production-default",unitWarnings.push(`${EXECUTOR_SERVICE_BASE_URL_ENV} points at production (${DEFAULT_BAPI_BASE_URL}) \u2014 legal, but worth confirming this host is meant to serve production jobs.`)):baseUrlClass="configured":(baseUrlClass="missing",unitWarnings.push(`no ${EXECUTOR_SERVICE_BASE_URL_ENV} in the unit \u2014 the executor requires an explicit base URL and will fail to start.`));let distinctRepos=Array.from(new Set(inspection.repos)),credentials=[];for(let repo of distinctRepos)credentials.push(await probeRepoCredential(repo,deps,credDeps));units.push({path:unitPath,executorId,baseUrl:inspection.baseUrl,baseUrlClass,repos:inspection.repos,credentials,warnings:unitWarnings})}return{status:"collected",units,warnings}}var LEGACY_REGISTRATION_INFO_TEXT,init_doctor2=__esm({"src/doctor.ts"(){"use strict";init_start_tickets();init_version_generated();init_install_doctor();init_executor_adapter_inspection();init_executor_adapter_registry();init_env_flags();init_bridge_api_urls();init_tool_surface_gating();init_credential_store();init_bridge_api_client();init_bridge_client();init_checkpoint_store();init_lock();init_start_tickets_repo();init_worker_containment_diagnostic();init_launcher_config_inspection();init_mcp_identity();init_agent_registry();init_start_tickets_prereqs();init_mcp_profile();init_executor();init_credentials();init_claude_login();init_base_ref();init_manifest();init_ticket_key_utils();init_worktree_core();init_stale_worktree_doctor();LEGACY_REGISTRATION_INFO_TEXT=`This registration remains supported. New installs use \`${MCP_SERVER_NAME}\`. No action is required.`}});function unreported(id){return{id,state:"unreported",detail:UNREPORTED_DETAIL,remediation:BRING_UP_UNREPORTED_REMEDIATION,refusal:"bring-up-facts-unreported"}}function classifyDatabaseMigration(bringUp){let id="database-migration-current";return bringUp===null?unreported(id):bringUp.migration_readable?bringUp.database_migration_current?{id,state:"ok",detail:"the database is at (or ahead of) the code migration head"}:{id,state:"bad",detail:"the database is BEHIND the server's code migration head",remediation:DATABASE_MIGRATION_BEHIND_REMEDIATION,refusal:"database-migration-behind"}:{id,state:"unreadable",detail:"the migration state could not be read (unknown, not confirmed behind)",remediation:DATABASE_MIGRATION_UNREADABLE_REMEDIATION,refusal:"database-migration-unreadable"}}function classifyWorkerPresent(bringUp){let id="worker-present";return bringUp===null?unreported(id):bringUp.heartbeat_readable?bringUp.worker_present?{id,state:"ok",detail:"a reconciler heartbeat is fresh"}:{id,state:"bad",detail:"0 fresh reconcilers \u2014 no worker is running against this deployment",remediation:WORKER_NOT_PRESENT_REMEDIATION,refusal:"worker-not-present"}:{id,state:"unreadable",detail:"the reconciler heartbeat could not be read (unknown, not confirmed absent)",remediation:WORKER_HEARTBEAT_UNREADABLE_REMEDIATION,refusal:"worker-heartbeat-unreadable"}}function classifySingleTransitionAuthority(bringUp){let id="single-transition-authority";return bringUp===null?unreported(id):bringUp.heartbeat_readable?bringUp.fresh_reconciler_count>=2?{id,state:"bad",detail:"2+ fresh reconcilers \u2014 more than one transition authority is ticking",remediation:SECOND_RECONCILER_REMEDIATION,refusal:"second-reconciler-detected"}:bringUp.fresh_reconciler_count===0?{id,state:"bad",detail:"0 fresh reconcilers \u2014 no transition authority is ticking",remediation:WORKER_NOT_PRESENT_REMEDIATION,refusal:"worker-not-present"}:{id,state:"ok",detail:"exactly 1 fresh reconciler"}:{id,state:"unreadable",detail:"the reconciler heartbeat could not be read (unknown, not confirmed)",remediation:WORKER_HEARTBEAT_UNREADABLE_REMEDIATION,refusal:"worker-heartbeat-unreadable"}}function classifyBringUpFacts(bringUp){return[classifyDatabaseMigration(bringUp),classifyWorkerPresent(bringUp),classifySingleTransitionAuthority(bringUp)]}function capitalize(text){return text.length===0?text:text[0].toUpperCase()+text.slice(1)}var BRING_UP_RUNBOOK,BRING_UP_UNREPORTED_REMEDIATION,DATABASE_MIGRATION_UNREADABLE_REMEDIATION,DATABASE_MIGRATION_BEHIND_REMEDIATION,WORKER_HEARTBEAT_UNREADABLE_REMEDIATION,WORKER_NOT_PRESENT_REMEDIATION,SECOND_RECONCILER_REMEDIATION,UNREPORTED_DETAIL,BRING_UP_REFUSAL_MESSAGES,init_bring_up_facts=__esm({"src/conductor/bring-up-facts.ts"(){"use strict";BRING_UP_RUNBOOK="docs/claude/epic-conductor-v2-operator-runbook.md",BRING_UP_UNREPORTED_REMEDIATION="upgrade the Bridge API deploy to a build that reports the bring-up safety facts; their state is unknown here, not healthy.",DATABASE_MIGRATION_UNREADABLE_REMEDIATION=`retry; the migration state could not be read, which is not the same as confirmed-behind. If it persists, check the applied revision with \`alembic current\` (${BRING_UP_RUNBOOK} \xA73d).`,DATABASE_MIGRATION_BEHIND_REMEDIATION=`confirm the applied revision with \`alembic current\` (not \`alembic heads\`, which reads the migration scripts), apply this checkout's migrations with \`alembic -c alembic.ini upgrade head\`, then retry (${BRING_UP_RUNBOOK} \xA73d).`,WORKER_HEARTBEAT_UNREADABLE_REMEDIATION="retry once the Bridge API database is reachable; the reconciler heartbeat could not be read, so worker presence is unknown, not confirmed absent.",WORKER_NOT_PRESENT_REMEDIATION=`start a worker (\`python worker.py\`, or bring up a local plane) \u2014 a server started with DISABLE_SCHEDULER=true runs none. Create and approve only against a server that has a worker (${BRING_UP_RUNBOOK} \xA73d).`,SECOND_RECONCILER_REMEDIATION=`find and stop the extra reconciler: check \`ps aux | grep worker.py\` for a reparented survivor of an earlier plane (${BRING_UP_RUNBOOK} \xA76), and note that a dev server started without DISABLE_SCHEDULER=true runs a reconciler too. A reconciler stopped in the last 120 seconds still counts \u2014 heartbeat rows are not deleted on shutdown \u2014 so wait and retry.`,UNREPORTED_DETAIL="not reported by this Bridge API deploy";BRING_UP_REFUSAL_MESSAGES={"bring-up-facts-unreported":"the Bridge API did not report the bring-up safety facts (database migration, worker presence, single reconciler), so none of them could be confirmed. "+capitalize(BRING_UP_UNREPORTED_REMEDIATION),"database-migration-unreadable":"database migration: the server could not read whether its database is at the migration head, so this is unknown, not confirmed behind. "+capitalize(DATABASE_MIGRATION_UNREADABLE_REMEDIATION),"database-migration-behind":"database migration: the server's database is BEHIND its code's migration head, so the code would run against a schema that was never applied. "+capitalize(DATABASE_MIGRATION_BEHIND_REMEDIATION),"worker-heartbeat-unreadable":"worker presence: the durable reconciler heartbeat could not be read, so whether a worker is running is unknown, not confirmed absent. "+capitalize(WORKER_HEARTBEAT_UNREADABLE_REMEDIATION),"worker-not-present":"worker presence: no reconciler heartbeat is fresh, so nothing would drive this run. "+capitalize(WORKER_NOT_PRESENT_REMEDIATION),"second-reconciler-detected":"single transition authority: two or more reconcilers are ticking the shared database, and two transition authorities wedge an epic. "+capitalize(SECOND_RECONCILER_REMEDIATION)}}});function supervisorSection(readiness){let s=readiness.supervisor,sections=[];if(!s.setup_present||!s.config_present){let missing=[s.setup_present?null:"setup",s.config_present?null:"config"].filter(Boolean).join(" and ");sections.push({id:"supervisor-configuration",label:"Supervisor configuration",status:"degraded",detail:`project-default supervisor ${missing} absent`,remediation:"bootstrap writes the safe project-default posture."})}else sections.push({id:"supervisor-configuration",label:"Supervisor configuration",status:"ok",detail:`setup=${s.setup_source}, config=${s.config_source}`});sections.push(s.required_checks_empty?{id:"supervisor-required-checks",label:"Supervisor required CI checks",status:"degraded",detail:"required-check list is EMPTY \u2014 the done gate would pass unconditionally",remediation:"bootstrap writes a non-empty required-check list into done_gate_config."}:{id:"supervisor-required-checks",label:"Supervisor required CI checks",status:"ok",detail:`${s.required_checks_count} required check(s) configured`});let alignment=s.review_policy_alignment;return alignment!==null&&(alignment.status==="divergent"||alignment.status==="invalid"?sections.push({id:"supervisor-review-alignment",label:"Supervisor review-policy alignment",status:"degraded",detail:alignment.explanation,remediation:alignment.status==="invalid"?"fix the done gate's review_state condition \u2014 review configuration exists but cannot be read, so the merge path refuses rather than merges.":`set the repository review-policy default and the done gate's review_state condition to the same signal, or confirm the difference is intended \u2014 see ${CONDUCTOR_OPERATOR_RUNBOOK_POINTER}.`}):sections.push({id:"supervisor-review-alignment",label:"Supervisor review-policy alignment",status:"ok",detail:alignment.explanation})),sections}function githubCredentialsSection(readiness){let g=readiness.github;if(g.credentials_complete)return{id:"github-credentials",label:"GitHub App credentials",status:"ok",detail:"owner, repository id, and installation id all resolved"};let missing=[g.owner_resolved?null:"owner",g.repo_id_resolved?null:"repository id",g.installation_id_resolved?null:"installation id"].filter(Boolean).join(", ");return{id:"github-credentials",label:"GitHub App credentials",status:"degraded",detail:g.credentials_readable?`incomplete: ${missing} unresolved`:"no GitHub credential row for this repository",remediation:"connect GitHub from the Bridge setup UI (`install-bridge connect-github`)."}}function githubActionsSection(readiness){let g=readiness.github;return g.actions_write?{id:"github-actions-permission",label:"GitHub App actions permission",status:"ok",detail:"actions: write"}:g.actions_probe_succeeded?{id:"github-actions-permission",label:"GitHub App actions permission",status:"degraded",detail:`actions: ${g.actions_permission_level}`,remediation:"grant the GitHub App `actions: write`; the conductor's workflow rerun lane fails open on 403 without it."}:{id:"github-actions-permission",label:"GitHub App actions permission",status:"degraded",detail:"permission could not be checked",remediation:"re-run once credentials resolve; the workflow rerun lane fails open on 403 until this reads `write`."}}function reconcilerSection(readiness){let r=readiness.reconciler;return r.liveness_readable?r.stale?{id:"reconciler-liveness",label:"Reconciler tick liveness",status:"degraded",detail:r.last_tick_at===null?"no reconciler tick recorded for this repository":`last tick ${r.last_tick_age_seconds}s ago (threshold ${readiness.thresholds.reconciler_stale_after_seconds}s)`,remediation:"start the reconciler (`epic-implementer epic-tick` schedule) for this repository."}:{id:"reconciler-liveness",label:"Reconciler tick liveness",status:"ok",detail:`last tick ${r.last_tick_age_seconds}s ago across ${r.active_run_count} active run(s)`}:{id:"reconciler-liveness",label:"Reconciler tick liveness",status:"degraded",detail:"liveness could not be read",remediation:"retry once the Bridge API is reachable; reconciler liveness is unknown here, which is not the same as confirmed-stale."}}function bringUpSection(verdict){let base={id:verdict.id,label:BRING_UP_SECTION_LABELS[verdict.id]};return verdict.state==="ok"?{...base,status:"ok",detail:verdict.detail}:{...base,status:"degraded",detail:verdict.detail,...verdict.remediation?{remediation:verdict.remediation}:{}}}function databaseMigrationCurrentSection(readiness){return bringUpSection(classifyDatabaseMigration(readiness.bring_up??null))}function workerPresentSection(readiness){return bringUpSection(classifyWorkerPresent(readiness.bring_up??null))}function singleTransitionAuthoritySection(readiness){return bringUpSection(classifySingleTransitionAuthority(readiness.bring_up??null))}function bringUpSafetySections(readiness){return[databaseMigrationCurrentSection(readiness),workerPresentSection(readiness),singleTransitionAuthoritySection(readiness)]}function workflowSection(presence,reviewPolicySource,driftDetail){return presence==="present"?{id:"claude-review-workflow",label:"claude-review workflow",status:"ok",detail:driftDetail?`.github/workflows/claude-review.yml present \u2014 ${driftDetail}`:".github/workflows/claude-review.yml present"}:presence==="drifted"?{id:"claude-review-workflow",label:"claude-review workflow",status:"degraded",detail:driftDetail??".github/workflows/claude-review.yml differs from the repository default branch",remediation:CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION}:reviewPolicySource==="native_review_decision"||reviewPolicySource==="none"?{id:"claude-review-workflow",label:"claude-review workflow",status:"ok",detail:`not applicable for review policy '${reviewPolicySource}'`}:{id:"claude-review-workflow",label:"claude-review workflow",status:"degraded",detail:presence==="unreadable"?".github/workflows/claude-review.yml could not be read":".github/workflows/claude-review.yml absent",remediation:"the selected review policy consumes the sticky verdict this workflow emits; install the template."}}function executorProvisioningSection(diagnostics){let base={id:"executor-provisioning",label:"Executor provisioning"};if(diagnostics===null)return{...base,status:"degraded",detail:"executor service-unit diagnostics could not be collected",remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION};if(diagnostics.status==="skipped")return{...base,status:"degraded",detail:diagnostics.reason,remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION};let unhealthy=diagnostics.units.filter(unit=>unit.warnings.length>0||unit.credentials.some(cred=>!cred.resolved)),ids=diagnostics.units.map(unit=>unit.executorId).join(", ");return unhealthy.length===0&&diagnostics.warnings.length===0?{...base,status:"ok",detail:`${diagnostics.units.length} generated service unit(s) found (${ids}); unit presence only \u2014 see the service-state and observation sections`}:{...base,status:"degraded",detail:`${diagnostics.units.length} generated service unit(s) found (${ids}), but ${unhealthy.length} unit(s) carry warnings or unresolved credentials \u2014 see the embedded executor-provisioning report`,remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION}}function executorServiceStateSection(observations,unitsDiscovered,inspectorAvailable){let base={id:"executor-service-state",label:"Executor service state"};if(!unitsDiscovered)return{...base,status:"degraded",detail:"no generated unit to inspect, so no service state was collected",remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION};if(!inspectorAvailable||observations.length===0)return{...base,status:"degraded",detail:"local service state could not be collected on this host",remediation:EXECUTOR_SERVICE_START_REMEDIATION};let rendered=[...observations].sort((a,b)=>a.executorId<b.executorId?-1:a.executorId>b.executorId?1:0).map(o=>`${o.executorId}=${o.state}`).join(", ");return observations.every(o=>o.state==="active")?{...base,status:"ok",detail:`service state: ${rendered}`}:{...base,status:"degraded",detail:`service state: ${rendered}`,remediation:EXECUTOR_SERVICE_START_REMEDIATION}}function executorObservationSection(readiness){let base={id:"executor-observation",label:"Executor server observation"};if(readiness===null||!readiness.executor.liveness_readable)return{...base,status:"degraded",detail:"server executor observation is unknown (readiness could not be read)",remediation:"retry once the Bridge API is reachable; no readiness claim is made from local state."};let e=readiness.executor,seen=e.last_seen_at===null?"never seen":`last seen ${e.last_seen_at} (${e.last_seen_age_seconds}s ago)`;return e.ready===!0?{...base,status:"ok",detail:`executor_ready \u2014 ${seen}`}:e.ready===!1?{...base,status:"degraded",detail:`observed but stale/not ready \u2014 ${seen}`,remediation:EXECUTOR_SERVICE_START_REMEDIATION}:{...base,status:"degraded",detail:`never observed by the server \u2014 ${seen}`,remediation:EXECUTOR_SERVICE_START_REMEDIATION}}function detectConductorContext(legacyConductor,profile){return legacyConductor?.mcp_profile?.conductor_context_detected===!0||profile?.tokenPresent===!0}function conductorProfileTokenSection(profile,conductorContext){let base={id:"conductor-profile-token",label:"MCP conductor profile token"};if(profile===null)return{...base,status:"degraded",detail:"the host MCP profile token could not be inspected",remediation:CONDUCTOR_PROFILE_TOKEN_REMEDIATION};let carrying=profile.configs.filter(c=>c.state==="token-present").map(c=>c.path),scope="inspected .mcp.json, .vscode/mcp.json, .cursor/mcp.json only (Codex and Copilot host configuration is not inspected)";if(carrying.length>0)return{...base,status:"ok",detail:`\`${profile.token}\` present in ${carrying.join(", ")}; ${scope}`};let detail=profile.bridgeEntryPresent?`no supported host config carries the \`${profile.token}\` token; ${scope}`:`no supported host config carries a Bridge entry; ${scope}`,remediation=profile.bridgeEntryPresent?CONDUCTOR_PROFILE_TOKEN_REMEDIATION:CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION;return conductorContext?{...base,status:"degraded",detail,remediation}:{...base,status:"ok",detail:`advisory \u2014 ${detail}`,remediation}}function conductorHookTargetsSection(legacyConductor,conductorContext){let base={id:"conductor-hook-targets",label:"Conductor hook targets"};if(legacyConductor==null)return{...base,status:"degraded",detail:"hook targets could not be derived (the epic-implementer doctor was not collected)",remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION};let hooks=legacyConductor.git_hooks;if(hooks===void 0)return{...base,status:"degraded",detail:"hook targets could not be derived (the epic-implementer doctor reported no hook state)",remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION};if(!hooks.is_worktree)return{...base,status:"ok",detail:"advisory \u2014 not a git worktree, so no managed conductor hooks apply"};let usable=name=>{let hook=(hooks.hooks??[]).find(h=>h.name===name);return hook!==void 0&&hook.exists&&hook.managed_block_present&&hook.embedded_bin_is_file},rendered=MANAGED_HOOK_NAMES.map(name=>`${name}=${usable(name)}`).join(", ");if(MANAGED_HOOK_NAMES.every(name=>usable(name)))return{...base,status:"ok",detail:`managed hooks usable: ${rendered}`};let detail=`managed hooks usable: ${rendered}`;return conductorContext?{...base,status:"degraded",detail,remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION}:{...base,status:"ok",detail:`advisory \u2014 ${detail}`,remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION}}function conductorLedgerLoadabilitySection(legacyConductor){let base={id:"conductor-ledger-loadability",label:"Conductor ledger loadability"};if(legacyConductor==null)return{...base,status:"degraded",detail:"ledger loadability could not be derived (the epic-implementer doctor was not collected)",remediation:CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION};let inspection=legacyConductor.native_ledger;if(inspection===void 0)return{...base,status:"degraded",detail:"ledger loadability could not be derived (the epic-implementer doctor reported no native-ledger state)",remediation:CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION};let availability=describeNativeLedgerAvailability(inspection);return availability.status==="available"?{...base,status:"ok",detail:"ledger available \u2014 the native binding loads"}:{...base,status:"degraded",detail:`ledger degraded \u2014 ${availability.module} did not load (NODE_MODULE_VERSION ${availability.nodeModulesAbi}, failure: ${availability.failureKind})`,remediation:CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION}}async function inspectWorkflowPresence(readWorkflowFile,classifyWorkflowDrift){let local=await inspectWorkflowLocalPresence(readWorkflowFile);if(local!=="present"||!classifyWorkflowDrift)return{presence:local};try{let classification=await classifyWorkflowDrift();return classification.state==="drifted"?{presence:"drifted",driftDetail:summarizeClaudeReviewWorkflowDrift(classification)}:classification.state==="unverified"?{presence:"present",driftDetail:summarizeClaudeReviewWorkflowDrift(classification)}:{presence:"present"}}catch{return{presence:"present"}}}async function inspectWorkflowLocalPresence(readWorkflowFile){try{return await readWorkflowFile(),"present"}catch(err){return err?.code==="ENOENT"?"absent":"unreadable"}}var CONDUCTOR_OPERATOR_RUNBOOK_POINTER,CONDUCTOR_PROFILE_TOKEN,CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION,CONDUCTOR_PROFILE_TOKEN_REMEDIATION,CONDUCTOR_HOOK_TARGET_REMEDIATION,CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION,EXECUTOR_INSTALL_SERVICE_REMEDIATION,EXECUTOR_SERVICE_START_REMEDIATION,BRING_UP_SECTION_LABELS,init_readiness_sections=__esm({"src/conductor/readiness-sections.ts"(){"use strict";init_git_hooks();init_mcp_identity();init_claude_review_workflow_drift();init_doctor();init_bring_up_facts();CONDUCTOR_OPERATOR_RUNBOOK_POINTER="docs/claude/epic-conductor-v2-operator-runbook.md",CONDUCTOR_PROFILE_TOKEN="conductor",CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION=`no supported host MCP config carries a Bridge entry \u2014 run \`npx ${MCP_PACKAGE_NAME} install\` to register one, then re-run \`install conductor\`.`,CONDUCTOR_PROFILE_TOKEN_REMEDIATION="re-run `install conductor` and accept the tool-visibility consent; the conductor tools become visible after the MCP client is restarted.",CONDUCTOR_HOOK_TARGET_REMEDIATION="re-run `install conductor` and accept the local-observability consent, or run `epic-implementer install-git-hooks` directly.",CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION="`better-sqlite3` is an optionalDependency npm silently skips on a build failure \u2014 reinstall it for this Node runtime to restore local conductor observability.",EXECUTOR_INSTALL_SERVICE_REMEDIATION=`generate a persistent unit with \`install conductor --executor-id <id>\` or \`executor install-service\` (or run the executor by hand) \u2014 see ${CONDUCTOR_OPERATOR_RUNBOOK_POINTER}.`,EXECUTOR_SERVICE_START_REMEDIATION=`start the service (re-run \`install conductor\` and accept the start consent, or run the printed launchctl/systemctl command by hand) \u2014 see ${CONDUCTOR_OPERATOR_RUNBOOK_POINTER}.`;BRING_UP_SECTION_LABELS={"database-migration-current":"Database migration","worker-present":"Worker present","single-transition-authority":"Single transition authority"}}});import{readdir as fsReaddir,readFile as fsReadFile,stat as fsStat}from"node:fs/promises";import os5 from"node:os";async function settle(collect){if(!collect)return{value:null,failed:!1};try{return{value:await collect(),failed:!1}}catch{return{value:null,failed:!0}}}async function runConductorInstallDoctor(deps){let sections=[],buildConductor=deps.buildConductorReport??buildConductorDoctorReport,collectInstall=deps.collectInstallChecks??(deps.installDoctorDeps?()=>collectInstallStatusChecks(deps.installDoctorDeps):null),[conductorSettled,executorPreflightSettled,installChecksSettled]=await Promise.all([settle(()=>buildConductor(deps.conductorDoctorDeps)),settle(deps.collectExecutorPreflight?()=>deps.collectExecutorPreflight():null),settle(collectInstall)]),legacyConductor=conductorSettled.value??null;conductorSettled.failed&§ions.push({id:"conductor-ledger",label:"Conductor ledger doctor",status:"degraded",detail:"the local epic-implementer doctor could not be built",remediation:"run `epic-implementer doctor` directly to see why the local ledger report failed."});let legacyExecutorPreflight=executorPreflightSettled.value??null;executorPreflightSettled.failed&§ions.push({id:"executor-preflight",label:"Executor preflight",status:"degraded",detail:"the executor preflight could not be collected",remediation:"re-run this command; if it persists, run `executor` directly to surface the preflight failure."});let legacyInstallChecks=installChecksSettled.value??null;installChecksSettled.failed&§ions.push({id:"install-status",label:"Bridge install status",status:"degraded",detail:"the install-status checklist could not be collected",remediation:"run `doctor` to collect the advisory install-status checklist on its own."});let readiness=null;if(!deps.access)sections.push({id:"bridge-access",label:"Bridge API access",status:"fatal",detail:deps.accessError??"Bridge API repository/credential could not be resolved",remediation:"run `install-bridge` (or set BAPI_API_KEY) for this repository."});else try{readiness=await fetchConductorReadiness(deps.access,deps.fetch)}catch(err){let kind=err instanceof ConductorBridgeApiError?err.kind:"network",fatalKind=kind==="unauthorized"||kind==="invalid-input";sections.push({id:"server-readiness",label:"Server readiness",status:fatalKind?"fatal":"degraded",detail:kind==="unauthorized"?"Bridge API rejected the credential for this repository":kind==="invalid-input"?"the readiness response failed shape validation":"the readiness endpoint could not be reached",remediation:fatalKind?"re-check the API key and repository, then re-run.":"retry; the local sections above are unaffected."})}readiness&&(sections.push(...supervisorSection(readiness)),sections.push(githubCredentialsSection(readiness)),sections.push(githubActionsSection(readiness)));let workflow=await inspectWorkflowPresence(deps.readWorkflowFile,deps.classifyWorkflowDrift);sections.push(workflowSection(workflow.presence,deps.reviewPolicySource,workflow.driftDetail)),readiness&&(sections.push(...bringUpSafetySections(readiness)),sections.push(reconcilerSection(readiness)));let collectServiceUnits=deps.collectExecutorServiceUnits??(()=>collectExecutorServiceDiagnostics({platform:process.platform,env:process.env,homedir:os5.homedir,readdir:dirPath=>fsReaddir(dirPath),readFile:filePath=>fsReadFile(filePath,"utf-8"),stat:filePath=>fsStat(filePath)})),executorService=null;try{executorService=await collectServiceUnits()}catch{}sections.push(executorProvisioningSection(executorService));let discoveredUnits=executorService!==null&&executorService.status!=="skipped"?executorService.units:[],executorServiceStates=[];if(deps.inspectExecutorServiceState&&discoveredUnits.length>0)for(let unit of discoveredUnits)try{let state=await deps.inspectExecutorServiceState({executorId:unit.executorId});executorServiceStates.push({executorId:unit.executorId,state})}catch{executorServiceStates.push({executorId:unit.executorId,state:"unknown"})}sections.push(executorServiceStateSection(executorServiceStates,discoveredUnits.length>0,!!deps.inspectExecutorServiceState)),sections.push(executorObservationSection(readiness));let inspectProfile=deps.inspectProfileToken??((projectRoot,token)=>inspectBridgeApiProfileToken(projectRoot,token,{readFile:filePath=>fsReadFile(filePath,"utf-8")})),profileToken=null;try{profileToken=await inspectProfile(deps.projectRoot??process.cwd(),CONDUCTOR_PROFILE_TOKEN)}catch{}let conductorContext=detectConductorContext(legacyConductor,profileToken);return sections.push(conductorProfileTokenSection(profileToken,conductorContext)),sections.push(conductorHookTargetsSection(legacyConductor,conductorContext)),sections.push(conductorLedgerLoadabilitySection(legacyConductor)),{legacyConductor,legacyExecutorPreflight,legacyInstallChecks,executorService,executorServiceStates,readiness,sections}}var init_install_doctor2=__esm({"src/conductor/install-doctor.ts"(){"use strict";init_doctor();init_mcp_host_config();init_doctor2();init_install_doctor();init_readiness_sections();init_bridge_api_client();init_readiness_sections();init_bring_up_facts()}});function mapServerReadinessToChecks(readiness,failure="unreachable"){if(readiness===null){let copy=SERVER_FAILURE_COPY[failure];return SERVER_READINESS_DESCRIPTORS.map(({id,label})=>createReadinessCheck({id:`server.${id}`,source:"server",label,status:"fail",detail:copy.detail,remediation:copy.remediation}))}let s=readiness.supervisor,g=readiness.github,r=readiness.reconciler,e=readiness.executor,outcomes=[];outcomes.push(s.setup_present?{id:"supervisor-setup",status:"pass",detail:`stored (source: ${s.setup_source})`}:{id:"supervisor-setup",status:"fail",detail:"no supervisor setup is stored for this repository",remediation:SERVER_REMEDIATIONS.supervisorSetup}),outcomes.push(s.config_present?{id:"supervisor-config",status:"pass",detail:`stored (source: ${s.config_source})`}:{id:"supervisor-config",status:"fail",detail:"no supervisor configuration is stored for this repository",remediation:SERVER_REMEDIATIONS.supervisorConfig}),outcomes.push(s.required_checks_empty?{id:"supervisor-required-checks",status:"warn",detail:"the required-check list is EMPTY \u2014 the done gate would pass unconditionally",remediation:SERVER_REMEDIATIONS.requiredChecks}:{id:"supervisor-required-checks",status:"pass",detail:`${s.required_checks_count} required check(s) configured`}),outcomes.push({id:"auto-merge",status:"pass",detail:s.auto_merge_enabled?"auto-merge enabled":"auto-merge disabled (operator posture)"}),outcomes.push(s.merge_approval_required_set?{id:"merge-approval",status:"pass",detail:"merge-approval requirement is set explicitly"}:{id:"merge-approval",status:"warn",detail:"the merge-approval requirement is unset, so the merge path falls back to its default",remediation:SERVER_REMEDIATIONS.mergeApproval}),outcomes.push(reviewPolicyOutcome(readiness)),outcomes.push(g.credentials_complete?{id:"github-credentials",status:"pass",detail:"owner, repository id, and installation id all resolved"}:{id:"github-credentials",status:"fail",detail:g.credentials_readable?`incomplete: ${[g.owner_resolved?null:"owner",g.repo_id_resolved?null:"repository id",g.installation_id_resolved?null:"installation id"].filter(Boolean).join(", ")} unresolved`:"no GitHub credential row exists for this repository",remediation:SERVER_REMEDIATIONS.githubCredentials}),outcomes.push(githubActionsOutcome(readiness)),outcomes.push(...bringUpOutcomes(readiness)),outcomes.push(reconcilerOutcome(readiness)),outcomes.push(executorOutcome(readiness)),outcomes.push(reviewWorkflowOutcome(readiness)),outcomes.push(ciWorkflowOutcome(readiness)),outcomes.push(...unattendedOutcomes(readiness));let byId=new Map(outcomes.map(outcome=>[outcome.id,outcome]));return SERVER_READINESS_DESCRIPTORS.map(({id,label})=>{let outcome=byId.get(id);return outcome?createReadinessCheckSafely({id:`server.${id}`,source:"server",label,status:outcome.status,detail:outcome.detail,...outcome.status==="pass"?{}:{remediation:outcome.remediation??SERVER_REMEDIATIONS.olderServer}}):createReadinessCheck({id:`server.${id}`,source:"server",label,status:"fail",detail:"this server fact was not reported",remediation:SERVER_REMEDIATIONS.olderServer})})}function bringUpOutcomes(readiness){return classifyBringUpFacts(readiness.bring_up??null).map(verdict=>verdict.state==="ok"?{id:verdict.id,status:"pass",detail:verdict.detail}:{id:verdict.id,status:"fail",detail:verdict.detail,remediation:verdict.remediation??SERVER_REMEDIATIONS.olderServer})}function unattendedOutcomes(readiness){let u=readiness.unattended;return u===null?["unattended-consent","unattended-notify-default","repository-workflow-readiness"].map(id=>({id,status:"fail",detail:"this server fact was not reported",remediation:SERVER_REMEDIATIONS.olderServer})):[u.conductor_allowed?{id:"unattended-consent",status:"pass",detail:"this repository has consented to unattended conductor runs"}:{id:"unattended-consent",status:"warn",detail:"unattended_epic_implementer_allowed is NOT set \u2014 an unattended run will be refused before it is created",remediation:SERVER_REMEDIATIONS.unattendedConsent},u.notify_webhook_default_declared?{id:"unattended-notify-default",status:"pass",detail:u.notify_webhook_default_verified===!0?"a notify webhook default is declared and verified":"a notify webhook default is declared (verified at approval, not here)"}:{id:"unattended-notify-default",status:"warn",detail:"no repository notify webhook default is declared \u2014 an unattended run needs an escalation channel, and no column supplies a repository default today, so the run must declare notify.webhook_url itself",remediation:SERVER_REMEDIATIONS.unattendedNotifyDefault},u.repository_readiness_confirmed?{id:"repository-workflow-readiness",status:"pass",detail:"the review and conductor-CI workflows are both confirmed"}:{id:"repository-workflow-readiness",status:"warn",detail:"the review and conductor-CI workflows are not both confirmed \u2014 an unattended auto-merging run will be refused",remediation:SERVER_REMEDIATIONS.repositoryWorkflowReadiness}]}function reviewPolicyOutcome(readiness){let s=readiness.supervisor,alignment=s.review_policy_alignment;return alignment!==null?alignment.status==="divergent"||alignment.status==="invalid"?{id:"review-policy",status:"warn",detail:alignment.explanation,remediation:SERVER_REMEDIATIONS.reviewPolicyDivergent}:{id:"review-policy",status:"pass",detail:alignment.explanation}:s.review_policy_present?{id:"review-policy",status:"pass",detail:"a repository review-policy default is stored (alignment not reported by this server)"}:{id:"review-policy",status:"warn",detail:"no repository review-policy default is stored",remediation:SERVER_REMEDIATIONS.reviewPolicyMissing}}function githubActionsOutcome(readiness){let g=readiness.github;return g.actions_write?{id:"github-actions-permission",status:"pass",detail:"actions: write"}:g.actions_probe_succeeded?{id:"github-actions-permission",status:"warn",detail:`actions: ${g.actions_permission_level}`,remediation:SERVER_REMEDIATIONS.actionsMissing}:{id:"github-actions-permission",status:"fail",detail:"the actions permission could not be checked (this is not a confirmed absence)",remediation:SERVER_REMEDIATIONS.actionsProbeFailed}}function reconcilerOutcome(readiness){let r=readiness.reconciler;return r.liveness_readable?r.stale?{id:"reconciler-liveness",status:"fail",detail:r.last_tick_at===null?"no reconciler tick has been recorded for this repository":`last tick ${r.last_tick_age_seconds}s ago (server threshold ${readiness.thresholds.reconciler_stale_after_seconds}s)`,remediation:SERVER_REMEDIATIONS.reconcilerStale}:{id:"reconciler-liveness",status:"pass",detail:`last tick ${r.last_tick_age_seconds}s ago across ${r.active_run_count} active run(s)`}:{id:"reconciler-liveness",status:"fail",detail:"reconciler liveness could not be read",remediation:SERVER_REMEDIATIONS.reconcilerUnreadable}}function executorOutcome(readiness){let e=readiness.executor;return e.liveness_readable?e.ready===!0?{id:"executor-readiness",status:"pass",detail:`executor ready \u2014 last seen ${e.last_seen_age_seconds}s ago`}:e.ready===!1?{id:"executor-readiness",status:"fail",detail:`observed but not ready \u2014 last seen ${e.last_seen_age_seconds}s ago (server threshold ${readiness.thresholds.executor_stale_after_seconds}s)`,remediation:SERVER_REMEDIATIONS.executorStale}:{id:"executor-readiness",status:"fail",detail:"never observed by the server",remediation:SERVER_REMEDIATIONS.executorNeverSeen}:{id:"executor-readiness",status:"fail",detail:"executor liveness could not be read",remediation:SERVER_REMEDIATIONS.executorUnreadable}}function reviewWorkflowOutcome(readiness){let w=readiness.review_workflow;return w===null?{id:"review-workflow",status:"fail",detail:"this Bridge API deploy did not report the review-workflow facts",remediation:SERVER_REMEDIATIONS.olderServer}:w.probe_succeeded?w.emits_run_id&&w.emits_reviewed_sha?{id:"review-workflow",status:"pass",detail:"the default branch's review workflow emits both protocol markers"}:{id:"review-workflow",status:"fail",detail:`missing marker(s): ${[w.emits_run_id?null:"run id",w.emits_reviewed_sha?null:"reviewed SHA"].filter(Boolean).join(", ")}`,remediation:SERVER_REMEDIATIONS.reviewWorkflowIncomplete}:{id:"review-workflow",status:"fail",detail:w.workflow_present?"the review workflow is present but could not be evaluated":"the review workflow could not be found or read on the default branch",remediation:SERVER_REMEDIATIONS.reviewWorkflowUnknown}}function ciWorkflowOutcome(readiness){let c=readiness.conductor_ci_workflow;return c===null?{id:"conductor-ci-workflow",status:"fail",detail:"this Bridge API deploy did not report the conductor-CI workflow facts",remediation:SERVER_REMEDIATIONS.olderServer}:c.probe_succeeded?c.migration_guard_present?{id:"conductor-ci-workflow",status:"pass",detail:"the default branch's conductor CI workflow runs the migration guard"}:{id:"conductor-ci-workflow",status:"warn",detail:"the conductor CI workflow does not run the migration guard",remediation:SERVER_REMEDIATIONS.ciWorkflowMissingGuard}:{id:"conductor-ci-workflow",status:"fail",detail:c.workflow_present?"the conductor CI workflow is present but could not be evaluated":"the conductor CI workflow could not be found or read on the default branch",remediation:SERVER_REMEDIATIONS.ciWorkflowUnknown}}function sectionStatus(status){return status==="fatal"?"fail":status==="degraded"?"warn":"pass"}function mapInstallSectionsToReadinessChecks(sections){let checks=[],seen=new Set;for(let section of sections??[]){if(INSTALL_SECTION_IDS_OWNED_ELSEWHERE.has(section.id)||seen.has(section.id))continue;seen.add(section.id);let status=sectionStatus(section.status);checks.push(createReadinessCheckSafely({id:`conductor.install-section-${section.id}`,source:"conductor",label:section.label,status,detail:section.detail,...status==="pass"?{}:{remediation:section.remediation??"run `install conductor` for this repository to re-provision this capability."}}))}return checks}async function collectConductorReadinessGate(deps){let[installReport,planeResult]=await Promise.all([runInstallDoctorSafely(deps),runPlaneSafely(deps)]),unavailableSources=[];installReport===null&&unavailableSources.push("install","conductor","server"),deps.runPlanePreflight&&planeResult===null&&unavailableSources.push("plane");let checks=[...mapInstallStatusChecksToReadinessChecks(installReport?.legacyInstallChecks??null,installReport===null),...mapConductorDoctorReportToReadinessChecks(installReport?.legacyConductor??null),...mapInstallSectionsToReadinessChecks(installReport?.sections??null),...mapPlanePreflightToReadinessChecks(planeResult),...mapServerReadinessToChecks(installReport?.readiness??null,classifyServerFailure(installReport))],validated=validateReadinessChecks(checks);return{schemaVersion:CONDUCTOR_READINESS_GATE_SCHEMA_VERSION,advisory:CONDUCTOR_READINESS_ADVISORY_NOTICE,repoName:deps.repoName??null,unavailableSources,checks:validated,summary:summarizeReadinessChecks(validated)}}async function runInstallDoctorSafely(deps){try{return deps.runInstallDoctor?await deps.runInstallDoctor():deps.installDoctor?await runConductorInstallDoctor(deps.conductorDoctorDeps?{...deps.installDoctor,conductorDoctorDeps:deps.conductorDoctorDeps}:deps.installDoctor):null}catch{return null}}async function runPlaneSafely(deps){if(!deps.runPlanePreflight)return null;try{return await deps.runPlanePreflight()}catch{return null}}function classifyServerFailure(report){if(report===null)return"unreachable";let sections=report.sections??[];if(sections.some(section=>section.id==="bridge-access"))return"identity-unresolved";let serverSection=sections.find(section=>section.id==="server-readiness");return serverSection?serverSection.detail.includes("rejected the credential")?"unauthorized":serverSection.detail.includes("shape validation")?"invalid-response":"unreachable":"unreachable"}function readinessTag(status){return status==="fail"?"\u2717 FAIL":status==="warn"?"! WARN":status==="skip"?"- SKIP":"\u2713 PASS"}function formatConductorReadinessGateReport(report){let lines=["Conductor readiness (advisory)","\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",`schema version: ${report.schemaVersion}`,`repository: ${report.repoName??"unresolved"}`,""];for(let source of["install","conductor","plane","server"]){let group=report.checks.filter(check=>check.source===source);if(group.length!==0){lines.push(`[${source}]`);for(let check of group)lines.push(` ${readinessTag(check.status)} ${check.label} (${check.id})`),check.detail&&lines.push(` ${check.detail}`),check.remediation&&lines.push(` \u2192 ${check.remediation}`);lines.push("")}}let{pass,warn,fail,skip}=report.summary;return lines.push(`summary: ${pass} pass, ${warn} warn, ${fail} fail, ${skip} skip`),report.unavailableSources.length>0&&lines.push(`sources that could not be collected: ${report.unavailableSources.join(", ")} (their prerequisites above are reported as failures, not as passes)`),lines.push(""),lines.push(report.advisory),lines.join(`
|
|
122
|
+
`);pending=segments.pop()??"";for(let segment of segments)push(segment)},drain:()=>(pending.length>0&&(push(pending),pending=""),lines.map(message=>({check:"bridge-credentials",severity:"warning",message})))}}async function checkServerPort(deps,endpoint){let report=await checkServerPortReport(deps,endpoint);return{...report.report,probe:report.probe}}async function checkServerPortReport(deps,endpoint){let label="Local server port",target=`${endpoint.host}:${endpoint.port}`,result=await deps.probePort(endpoint.host,endpoint.port,PLANE_PORT_PROBE_TIMEOUT_MS);return result.kind==="refused"?{report:planeCheckPassed("server-port",label,`${target} is free`),probe:"refused"}:result.kind==="connected"?{report:planeCheckFinding({check:"server-port",severity:"blocking",message:`${target} is already accepting connections. That port may belong to a SIBLING WORKTREE's server \u2014 check before you kill it. Stop the existing server (or wind down its plane) and retry, or set ${PLANE_SERVER_PORT_ENV_VAR} to a free port.`,remediation:PLANE_SERVER_PORT_OCCUPIED_REMEDIATION},label,`${target} is already accepting connections`),probe:"connected"}:{report:planeCheckFinding({check:"server-port",severity:"warning",message:`could not determine whether ${target} is free (${result.error}); startup continues and uvicorn will fail loudly if the port is taken.`,remediation:PLANE_SERVER_PORT_UNKNOWN_REMEDIATION},label,`could not determine whether ${target} is free`),probe:"error"}}async function checkExistingPlane(repoRoot,deps){let label="Existing plane",read=await readPlaneManifest(repoRoot,deps.fs);return read.kind==="missing"?{...planeCheckPassed("existing-plane",label,"no plane manifest is present"),observation:{kind:"none"}}:read.kind!=="valid"?{...planeCheckFinding({check:"existing-plane",severity:"blocking",message:`an existing .bridge/plane/plane.json could not be validated (${read.error}). No process was signalled and the file was left untouched \u2014 inspect it, then remove it by hand if no plane is running.`,remediation:PLANE_MANIFEST_UNREADABLE_REMEDIATION},label,"an existing plane manifest could not be validated"),observation:{kind:"unvalidated"}}:deps.ownPlaneId!==void 0&&read.manifest.planeId===deps.ownPlaneId?{...planeCheckPassed("existing-plane",label,"the existing manifest carries this launch's own plane id"),observation:{kind:"own-plane"}}:manifestHasLiveProcess(read.manifest,deps.proc)?{...planeCheckFinding({check:"existing-plane",severity:"blocking",message:`a plane is already running (supervisor pid ${read.manifest.supervisorPid}). Run \`plane status\` to inspect it, or \`plane down\` to wind it down first.`,remediation:PLANE_ALREADY_RUNNING_REMEDIATION},label,"a plane is already running for this repository"),observation:classifyLivePlaneForAttach(repoRoot,read.manifest,deps.proc)}:{observation:{kind:"stale"},diagnostic:{check:"existing-plane",severity:"warning",message:"a previous plane manifest is present but every recorded process is gone; it will be replaced after a final liveness re-check."},outcomes:[{check:"existing-plane",id:"existing-plane",label,status:"warn",detail:"a stale plane manifest is present and will be replaced after a liveness re-check"}]}}async function fileExists(filePath,fs2){try{return await fs2.stat(filePath),!0}catch{return!1}}function mapPlanePreflightToReadinessChecks(result){let byId=new Map;for(let outcome of result?.outcomes??[])byId.has(outcome.id)||byId.set(outcome.id,outcome);return PLANE_READINESS_DESCRIPTORS.map(({id,label})=>{let outcome=byId.get(id);return outcome?createReadinessCheckSafely({id:`plane.${id}`,source:"plane",label:outcome.label||label,status:outcome.status,...outcome.detail?{detail:outcome.detail}:{},...outcome.status==="fail"?{remediation:outcome.remediation??PLANE_UNREPORTED_REMEDIATION}:outcome.status!=="pass"&&outcome.remediation?{remediation:outcome.remediation}:{}}):createReadinessCheck({id:`plane.${id}`,source:"plane",label,status:"fail",detail:PLANE_UNREPORTED_DETAIL,remediation:PLANE_UNREPORTED_REMEDIATION})})}var REQUIRED_REPO_FILES,BOUND_RUN_ATTACHABLE_PHASES,PLANE_ATTACHABLE_BASE_URL_REMEDIATION,PLANE_REPOSITORY_ROOT_REMEDIATION,PLANE_REPO_IDENTITY_REMEDIATION,PLANE_CREDENTIAL_REMEDIATION,PLANE_CREDENTIAL_PERMISSIONS_REMEDIATION,PLANE_CLAUDE_LOGIN_REMEDIATION,PLANE_SERVER_PORT_OCCUPIED_REMEDIATION,PLANE_SERVER_PORT_UNKNOWN_REMEDIATION,PLANE_SERVER_ENDPOINT_REMEDIATION,PLANE_MANIFEST_UNREADABLE_REMEDIATION,PLANE_ALREADY_RUNNING_REMEDIATION,PLANE_CREDENTIAL_OUTCOME_IDS,PLANE_ROOT_DEPENDENT_SKIP_DETAIL,ROOT_DEPENDENT_CHECKS,PLANE_PORT_PROBE_TIMEOUT_MS,PLANE_WORKTREE_REMEDIATION,PLANE_READINESS_DESCRIPTORS,PLANE_UNREPORTED_DETAIL,PLANE_UNREPORTED_REMEDIATION,init_preflight=__esm({"src/plane/preflight.ts"(){"use strict";init_types2();init_build_freshness();init_alembic_head();init_manifest();init_claude_login();init_readiness_check();REQUIRED_REPO_FILES=["main.py","worker.py","alembic.ini"],BOUND_RUN_ATTACHABLE_PHASES=["lanes-starting","lanes-ready","ready"];PLANE_ATTACHABLE_BASE_URL_REMEDIATION=`do not stop it \u2014 point BAPI_BASE_URL at the plane endpoint (http://127.0.0.1:<port>, the port ${PLANE_SERVER_PORT_ENV_VAR} or the default, with no trailing slash) and run drive-epic again to attach.`,PLANE_REPOSITORY_ROOT_REMEDIATION="run `plane up` from the Bridge API repository root (the directory holding main.py, worker.py, and alembic.ini).",PLANE_REPO_IDENTITY_REMEDIATION="set BAPI_REPO_NAME in this shell, or add a valid .bridge/config at the repository root.",PLANE_CREDENTIAL_REMEDIATION="set BAPI_API_KEY in this shell, or store it with `mcp-server credentials`; a spawned shell never sees .mcp.json env.",PLANE_CREDENTIAL_PERMISSIONS_REMEDIATION="restrict the Bridge credentials file to owner-only permissions (chmod 600), then rerun.",PLANE_CLAUDE_LOGIN_REMEDIATION="run `claude login` on this host so plane members inherit an authenticated session; startup continues either way.",PLANE_SERVER_PORT_OCCUPIED_REMEDIATION=`stop the server that owns the port (or wind down its plane) and retry, or set ${PLANE_SERVER_PORT_ENV_VAR} to a free port \u2014 the port may belong to a SIBLING WORKTREE.`,PLANE_SERVER_PORT_UNKNOWN_REMEDIATION=`retry, or set ${PLANE_SERVER_PORT_ENV_VAR} to a port you know is free; startup continues and uvicorn fails loudly if the port is taken.`,PLANE_SERVER_ENDPOINT_REMEDIATION=`set ${PLANE_SERVER_PORT_ENV_VAR} to a valid port number (1-65535), or unset it to use the default.`,PLANE_MANIFEST_UNREADABLE_REMEDIATION="inspect .bridge/plane/plane.json and remove it by hand once you have confirmed no plane is running; preflight signalled no process and changed no file.",PLANE_ALREADY_RUNNING_REMEDIATION="run `plane status` to inspect the running plane, or `plane down` to wind it down first.",PLANE_CREDENTIAL_OUTCOME_IDS={identity:"repo-identity",credential:"bridge-credentials",permissions:"credential-permissions"},PLANE_ROOT_DEPENDENT_SKIP_DETAIL="not run \u2014 every remaining check is relative to a valid repository root",ROOT_DEPENDENT_CHECKS=[["worktree-presence","worktree-presence","Git work tree"],["claude-login","claude-login","Claude login"],["bridge-credentials",PLANE_CREDENTIAL_OUTCOME_IDS.identity,"Bridge repository identity"],["bridge-credentials",PLANE_CREDENTIAL_OUTCOME_IDS.credential,"Bridge API credential"],["bridge-credentials",PLANE_CREDENTIAL_OUTCOME_IDS.permissions,"Bridge credential file permissions"],["executor-build","executor-build","Executor build freshness"],["runtime-entrypoint","runtime-entrypoint","Runtime re-exec entrypoint"],["server-port","server-port","Local server port"],["alembic-head","alembic-head","Database migration head"],["existing-plane","existing-plane","Existing plane"]],PLANE_PORT_PROBE_TIMEOUT_MS=1500;PLANE_WORKTREE_REMEDIATION="cd into the intended worktree (or create it with `git worktree add`) and rerun.";PLANE_READINESS_DESCRIPTORS=[{id:"repository-root",label:"Repository root"},{id:"worktree-presence",label:"Git work tree"},{id:"claude-login",label:"Claude login"},{id:"repo-identity",label:"Bridge repository identity"},{id:"bridge-credentials",label:"Bridge API credential"},{id:"credential-permissions",label:"Bridge credential file permissions"},{id:"executor-build",label:"Executor build freshness"},{id:"runtime-entrypoint",label:"Runtime re-exec entrypoint"},{id:"server-port",label:"Local server port"},{id:"alembic-head",label:"Database migration head"},{id:"existing-plane",label:"Existing plane"}],PLANE_UNREPORTED_DETAIL="not reported \u2014 the plane preflight produced no outcome for this prerequisite",PLANE_UNREPORTED_REMEDIATION="run `plane up` (or `epic-implementer readiness` again) to re-collect the plane preflight; this prerequisite's state is unknown, not healthy."}});var init_version_generated=__esm({"src/version.generated.ts"(){"use strict"}});var init_command_host=__esm({"src/command-host.ts"(){"use strict"}});var init_codex_skill_adapter=__esm({"src/codex-skill-adapter.ts"(){"use strict"}});var init_agents_generated=__esm({"src/agents.generated.ts"(){"use strict"}});var init_docs_generated=__esm({"src/docs.generated.ts"(){"use strict"}});var init_agent_utils=__esm({"src/agent-utils.ts"(){"use strict"}});var init_git_ignore_utils=__esm({"src/git-ignore-utils.ts"(){"use strict"}});var init_mcp_host_entry_adapter=__esm({"src/mcp-host-entry-adapter.ts"(){"use strict";init_mcp_host_targets()}});var init_init=__esm({"src/init.ts"(){"use strict";init_commands_generated();init_command_host();init_codex_skill_adapter();init_agents_generated();init_docs_generated();init_version_generated();init_agent_utils();init_bridge_config();init_git_ignore_utils();init_credential_store();init_launcher_config_inspection();init_mcp_identity();init_mcp_host_entry_adapter();init_mcp_host_targets()}});function joinPath2(base,rel){let b=base.endsWith("/")?base.slice(0,-1):base,r=rel.startsWith("/")?rel.slice(1):rel;return`${b}/${r}`}function isEnoent(err){return typeof err=="object"&&err!==null&&err.code==="ENOENT"}async function readJsonHostConfig(path15,deps){let raw;try{raw=await deps.readFile(path15)}catch(err){return isEnoent(err)?{state:"missing"}:{state:"read-error",message:"config could not be read"}}let parsed;try{parsed=JSON.parse(raw)}catch{return{state:"invalid"}}return typeof parsed!="object"||parsed===null||Array.isArray(parsed)?{state:"invalid"}:{state:"valid",value:parsed}}function escapeRegExp(value){return value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function storedProfileTokens(value){return typeof value!="string"?[]:value.split(",").map(t=>t.trim()).filter(t=>t.length>0)}function entryProfileTokens(entry){if(!entry||typeof entry!="object"||Array.isArray(entry))return null;let env=entry.env,stored=env&&typeof env=="object"&&!Array.isArray(env)?env.BRIDGE_MCP_PROFILE:void 0;return storedProfileTokens(stored)}async function inspectOneProfileConfig(projectRoot,target,token,deps){let read=await readJsonHostConfig(joinPath2(projectRoot,target.path),deps);if(read.state==="missing")return{path:target.path,state:"absent"};if(read.state!=="valid")return{path:target.path,state:"unreadable"};let root=read.value[target.topLevelKey];if(!root||typeof root!="object"||Array.isArray(root))return{path:target.path,state:"no-bridge-entry"};let servers=root,tokenSets=RECOGNIZED_SERVER_NAMES.filter(name=>Object.prototype.hasOwnProperty.call(servers,name)).map(name=>entryProfileTokens(servers[name])).filter(tokens=>tokens!==null);return tokenSets.length===0?{path:target.path,state:"no-bridge-entry"}:{path:target.path,state:tokenSets.some(tokens=>tokens.includes(token))?"token-present":"token-absent"}}async function inspectBridgeApiProfileToken(projectRoot,token,deps){let configs=[];for(let target of BRIDGE_PROFILE_TOKEN_CONFIGS)configs.push(await inspectOneProfileConfig(projectRoot,target,token,deps));return{token,configs,tokenPresent:configs.some(c=>c.state==="token-present"),bridgeEntryPresent:configs.some(c=>c.state==="token-present"||c.state==="token-absent")}}var DUPLICATE_REGISTRATION_DETAIL,BRIDGE_TABLE_PATTERNS,BRIDGE_PROFILE_TOKEN_CONFIGS,init_mcp_host_config=__esm({"src/mcp-host-config.ts"(){"use strict";init_version_generated();init_codex_home();init_init();init_mcp_host_targets();init_mcp_host_entry_adapter();init_mcp_host_entry_adapter();init_mcp_identity();DUPLICATE_REGISTRATION_DETAIL=`both \`${MCP_SERVER_NAME}\` and \`${LEGACY_SERVER_NAMES.join("`, `")}\` are registered here; confirm which one to keep, remove the other manually, then re-run. Nothing was changed.`;BRIDGE_TABLE_PATTERNS=RECOGNIZED_SERVER_NAMES.map(name=>({name,pattern:new RegExp(`^[ \\t]*\\[mcp_servers\\.${escapeRegExp(name)}(\\.[^\\]]*)?\\][ \\t]*$`,"m")})),BRIDGE_PROFILE_TOKEN_CONFIGS=[{path:".mcp.json",topLevelKey:"mcpServers"},{path:".vscode/mcp.json",topLevelKey:"servers"},{path:".cursor/mcp.json",topLevelKey:"mcpServers"}]}});var init_base_url=__esm({"src/base-url.ts"(){"use strict"}});var init_command_provisioning=__esm({"src/command-provisioning.ts"(){"use strict";init_commands_generated();init_codex_skill_adapter();init_git_ignore_utils()}});var init_ticket_key_utils=__esm({"src/ticket-key-utils.ts"(){"use strict"}});var init_codex_bridge_profile=__esm({"src/codex-bridge-profile.ts"(){"use strict";init_mcp_host_config();init_mcp_identity();init_codex_home()}});var init_codex_launch_scope=__esm({"src/codex-launch-scope.ts"(){"use strict";init_bridge_config();init_mcp_host_config();init_codex_home();init_codex_bridge_profile();init_mcp_provisioning();init_mcp_identity()}});var init_claude_settings=__esm({"src/claude-settings.ts"(){"use strict"}});var init_start_tickets_conductor=__esm({"src/start-tickets-conductor.ts"(){"use strict";init_claude_settings();init_file_scope_guard();init_mcp_profile();init_start_tickets_repo()}});var WORKER_BRANCH_ENV_VAR,init_pr_base_contract=__esm({"src/pr-base-contract.ts"(){"use strict";WORKER_BRANCH_ENV_VAR="BAPI_WORKER_BRANCH"}});var INDEX_SCOPE_ENV_VAR,INDEX_SCOPE_CONFIGURATION_ERROR,init_index_scope_contract=__esm({"src/index-scope-contract.ts"(){"use strict";INDEX_SCOPE_ENV_VAR="BAPI_INDEX_SCOPE",INDEX_SCOPE_CONFIGURATION_ERROR=`${INDEX_SCOPE_ENV_VAR} is not a valid index-scope declaration. Expected a server-minted scope identity; the value was not logged.`}});var init_env_file_link=__esm({"src/env-file-link.ts"(){"use strict";init_worktree_core()}});var init_base_ref=__esm({"src/base-ref.ts"(){"use strict";init_claude_review_workflow_drift_probe();init_start_tickets_prereqs();init_claude_review_workflow_drift_probe()}});var STALE_LAUNCH_SCRIPT_MAX_AGE_MS,init_start_tickets=__esm({"src/start-tickets.ts"(){"use strict";init_base_url();init_version_generated();init_credential_store();init_mcp_identity();init_claude_review_workflow_drift();init_start_tickets_repo();init_mcp_provisioning();init_command_provisioning();init_mcp_server_invocation();init_ticket_key_utils();init_start_tickets_prereqs();init_agent_registry();init_mcp_host_targets();init_codex_launch_scope();init_start_tickets_conductor();init_bridge_api_client();init_pr_base_contract();init_index_scope_contract();init_worktree_core();init_env_file_link();init_base_ref();STALE_LAUNCH_SCRIPT_MAX_AGE_MS=1440*60*1e3}});var REQUIRED_ADAPTER_CAPABILITIES,init_executor_adapter=__esm({"src/agent-launchers/executor-adapter.ts"(){"use strict";REQUIRED_ADAPTER_CAPABILITIES=Object.freeze(["executable","platform","headlessInvocation","mcpScoping","mcpInitParsing","auth","authFailureDetection","denyEnforcement","redaction","lifecycle"])}});var init_executor_adapter_inspection=__esm({"src/agent-launchers/executor-adapter-inspection.ts"(){"use strict";init_executor_adapter()}});var WORKER_SENTINEL_DATABASE_NAME,WORKER_SENTINEL_DATABASE_URL,WORKER_SENTINEL_DATABASE_ENV_KEYS,EXPLICIT_DENY_KEYS,init_env=__esm({"src/executor/env.ts"(){"use strict";init_pr_base_contract();init_file_scope_guard();init_index_scope_contract();WORKER_SENTINEL_DATABASE_NAME="bridge_worker_no_database",WORKER_SENTINEL_DATABASE_URL=`postgresql://${WORKER_SENTINEL_DATABASE_NAME}@127.0.0.1:1/${WORKER_SENTINEL_DATABASE_NAME}`,WORKER_SENTINEL_DATABASE_ENV_KEYS=["DATABASE_URL","POSTGRES_DATABASE","POSTGRES_DB","PGDATABASE"],EXPLICIT_DENY_KEYS=["BRIDGE_MCP_PROFILE","CONDUCTOR_NODE_PATH","BAPI_API_KEY","ANTHROPIC_API_KEY","CLAUDE_CODE_OAUTH_TOKEN","OPENAI_API_KEY","GITHUB_TOKEN","GH_TOKEN","CLAUDE_CONFIG_DIR","XDG_CONFIG_HOME",INDEX_SCOPE_ENV_VAR,WORKER_BRANCH_ENV_VAR,...WORKER_SENTINEL_DATABASE_ENV_KEYS]}});var init_observation=__esm({"src/executor/observation.ts"(){"use strict"}});var init_job_errors=__esm({"src/executor/job-errors.ts"(){"use strict";init_observation()}});var init_permissions=__esm({"src/executor/permissions.ts"(){"use strict";init_claude_settings()}});var WORKER_GUARD_REASON_PREFIX,WORKER_GUARD_MALFORMED_LINE,init_worker_guard_hook=__esm({"src/executor/worker-guard-hook.ts"(){"use strict";WORKER_GUARD_REASON_PREFIX="bridge worker guard",WORKER_GUARD_MALFORMED_LINE=`${WORKER_GUARD_REASON_PREFIX}: payload could not be read; continuing fail-open`}});var init_process=__esm({"src/executor/process.ts"(){"use strict"}});var init_platform=__esm({"src/executor/platform.ts"(){"use strict";init_process()}});var init_claude_executor_adapter=__esm({"src/agent-launchers/claude-executor-adapter.ts"(){"use strict";init_agent_registry();init_claude_user_config_doctor();init_deny_enforcement_preflight();init_env();init_job_errors();init_permissions();init_worker_guard_hook();init_platform();init_observation();init_executor_adapter();init_mcp_identity()}});var init_executor_adapter_registry=__esm({"src/agent-launchers/executor-adapter-registry.ts"(){"use strict";init_agent_registry();init_claude_executor_adapter();init_executor_adapter()}});var init_env_flags=__esm({"src/env-flags.ts"(){"use strict"}});var init_bridge_api_urls=__esm({"src/bridge-api-urls.ts"(){"use strict"}});import{getMethodLiteral}from"@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";var init_tool_surface_gating=__esm({"src/tool-surface-gating.ts"(){"use strict"}});var init_bridge_client=__esm({"src/implement-epic/bridge-client.ts"(){"use strict";init_bridge_api_client()}});var init_checkpoint_store=__esm({"src/implement-epic/checkpoint-store.ts"(){"use strict"}});var init_lock=__esm({"src/implement-epic/lock.ts"(){"use strict"}});var init_job_types=__esm({"src/executor/job-types.ts"(){"use strict"}});var init_worker_command=__esm({"src/executor/worker-command.ts"(){"use strict";init_job_errors();init_job_types()}});var init_worker_containment_diagnostic=__esm({"src/worker-containment-diagnostic.ts"(){"use strict";init_worker_command()}});var init_agent_identity=__esm({"src/executor/agent-identity.ts"(){"use strict";init_agent_registry()}});var init_claim_scope=__esm({"src/executor/claim-scope.ts"(){"use strict"}});import{execFile as execFile2,spawn}from"node:child_process";import{promisify}from"node:util";var execFileAsync,MAX_COMMAND_BUFFER,init_deps=__esm({"src/executor/deps.ts"(){"use strict";init_mcp_server_invocation();execFileAsync=promisify(execFile2),MAX_COMMAND_BUFFER=10*1024*1024}});var DEFAULT_BAPI_BASE_URL,EXECUTOR_BASE_URL_REQUIRED_MESSAGE,init_credentials=__esm({"src/executor/credentials.ts"(){"use strict";init_credential_store();init_base_url();DEFAULT_BAPI_BASE_URL="https://bridgegpt-api.com",EXECUTOR_BASE_URL_REQUIRED_MESSAGE=`no Bridge API base URL configured for the executor: pass --base-url <url> or set BAPI_BASE_URL (production is ${DEFAULT_BAPI_BASE_URL}). The executor never defaults to production.`}});var init_types3=__esm({"src/executor/types.ts"(){"use strict"}});var init_http_client=__esm({"src/executor/http-client.ts"(){"use strict";init_types3();init_bridge_api_client()}});var init_preflight2=__esm({"src/executor/preflight.ts"(){"use strict";init_types();init_executor_adapter_inspection();init_executor_adapter_registry();init_agent_identity();init_credentials()}});var init_heartbeat=__esm({"src/executor/heartbeat.ts"(){"use strict";init_process();init_types3()}});function normalizeGhMergeabilityValue(value){if(typeof value!="string")return null;let trimmed=value.trim();return trimmed.length===0?null:trimmed.toUpperCase()}function parseGhPrMergeabilityFields(record){return{mergeable:normalizeGhMergeabilityValue(record.mergeable),mergeStateStatus:normalizeGhMergeabilityValue(record.mergeStateStatus)}}function isPrMergeConflict(mergeability){return mergeability.mergeable==="CONFLICTING"||mergeability.mergeStateStatus==="DIRTY"}function isLikelyGhMergeConflictOutput(output){if(!output)return!1;let stdout=typeof output.stdout=="string"?output.stdout:"",stderr=typeof output.stderr=="string"?output.stderr:"",haystack=`${stdout}
|
|
123
|
+
${stderr}`.toLowerCase();return haystack.trim().length===0?!1:MERGE_CONFLICT_OUTPUT_SIGNATURES.some(sig=>haystack.includes(sig))}var MERGE_CONFLICT_OUTPUT_SIGNATURES,init_github_mergeability=__esm({"src/conductor/github-mergeability.ts"(){"use strict";MERGE_CONFLICT_OUTPUT_SIGNATURES=["merge conflict","merge conflicts","conflicting","conflict with the base branch","not possible to fast-forward","non-fast-forward","not mergeable","is not mergeable","cannot be cleanly created","would create a merge conflict"]}});function normalizeSelectorCheckName(value){if(typeof value!="string")return null;let trimmed=value.trim();return trimmed.length>0?trimmed:null}function parseTimestamp(value){if(typeof value!="string")return null;let trimmed=value.trim();if(trimmed.length===0)return null;let millis=Date.parse(trimmed);return Number.isNaN(millis)?null:millis}function parseRecencyId(record){let candidates=[record.recency_id,record.id,record.check_suite_id],suite=record.check_suite;suite!==null&&typeof suite=="object"&&candidates.push(suite.id);for(let candidate of candidates){if(typeof candidate=="number"&&Number.isFinite(candidate))return candidate;if(typeof candidate=="string"&&INTEGER_TEXT.test(candidate.trim()))return Number.parseInt(candidate.trim(),10)}return null}function recencyKey(record){let started=parseTimestamp(record.started_at),completed=parseTimestamp(record.completed_at),id=parseRecencyId(record);return[started!==null?[1,started]:[0,0],completed!==null?[1,completed]:[0,0],id!==null?[1,id]:[0,0]]}function compareRecency(a,b){let ka=recencyKey(a),kb=recencyKey(b);for(let i=0;i<ka.length;i+=1){if(ka[i][0]!==kb[i][0])return ka[i][0]-kb[i][0];if(ka[i][1]!==kb[i][1])return ka[i][1]<kb[i][1]?-1:1}return 0}function outcomeKey(record){let status=typeof record.status=="string"?record.status.toLowerCase():"",conclusion=typeof record.conclusion=="string"?record.conclusion.toLowerCase():"";return status+" "+conclusion}function looksSuccessful(record){let conclusion=typeof record.conclusion=="string"?record.conclusion.toLowerCase():"",status=typeof record.status=="string"?record.status.toLowerCase():"",bucket=typeof record.bucket=="string"?record.bucket.toLowerCase():"";return record.green===!0||conclusion==="success"||status==="success"||bucket==="pass"}function selectLatestChecks(records){let grouped=new Map,order=[];for(let record of records){if(record===null||typeof record!="object"||Array.isArray(record))continue;let name=normalizeSelectorCheckName(record.name);if(name===null)continue;let bucket=grouped.get(name);bucket===void 0?(grouped.set(name,[record]),order.push(name)):bucket.push(record)}let selected=[],ambiguousNames=new Set;for(let name of order){let candidates=grouped.get(name);if(candidates.length===1){selected.push(candidates[0]);continue}let best=candidates[0];for(let i=1;i<candidates.length;i+=1)compareRecency(candidates[i],best)>0&&(best=candidates[i]);let tied=candidates.filter(c=>compareRecency(c,best)===0);tied.length>1&&new Set(tied.map(outcomeKey)).size>1&&(ambiguousNames.add(name),best=tied.find(c=>!looksSuccessful(c))??tied[0]),selected.push(best)}return{selected,ambiguousNames}}function selectLatestChecksByName(records){let{selected,ambiguousNames}=selectLatestChecks(records),byName=new Map;for(let record of selected){let name=normalizeSelectorCheckName(record.name);name===null||ambiguousNames.has(name)||byName.set(name,record)}return{byName,ambiguousNames}}var INTEGER_TEXT,init_latest_check_selector=__esm({"src/conductor/latest-check-selector.ts"(){"use strict";INTEGER_TEXT=/^[0-9]+$/}});import{spawn as spawn2}from"child_process";function defaultSleep(ms){return new Promise(resolve2=>setTimeout(resolve2,ms))}function sanitizeWaitMs(value,fallback){return typeof value=="number"&&Number.isFinite(value)&&value>=0?Math.floor(value):fallback}function resolveLocalMergeMethod(value){return typeof value=="string"&&MERGE_METHODS.has(value)?value:"squash"}async function defaultRunCommand(cmd,args,env,signal){return await new Promise(resolve2=>{let settled=!1,timedOut=!1,stdout="",stderr="",child=spawn2(cmd,args,{env:{...process.env,...env}}),killChild=()=>{try{child.kill("SIGKILL")}catch{}},timer=setTimeout(()=>{timedOut=!0,killChild()},DEFAULT_COMMAND_TIMEOUT_MS),onAbort=()=>{timedOut=!0,killChild()},finish=result=>{settled||(settled=!0,clearTimeout(timer),signal&&signal.removeEventListener("abort",onAbort),resolve2(result))};signal&&(signal.aborted?onAbort():signal.addEventListener("abort",onAbort)),child.stdout?.setEncoding("utf8"),child.stderr?.setEncoding("utf8"),child.stdout?.on("data",chunk=>{stdout+=chunk}),child.stderr?.on("data",chunk=>{stderr+=chunk}),child.on("error",()=>{finish({status:null,stdout,stderr,timedOut})}),child.on("close",(code,sig)=>{finish({status:code,stdout,stderr,timedOut:timedOut||sig==="SIGKILL"||sig==="SIGTERM"})})})}function buildResponse(request,status,reason,terminal,ledgerEvents){return{action_key:request.action_key,repo_name:request.repo_name,pr_number:request.pr_number,expected_head_sha:request.expected_head_sha,status,reason,terminal,ledger_events:ledgerEvents}}function isNeutralCheckRecord(record){if(!record)return!1;let conclusion=typeof record.conclusion=="string"?record.conclusion.trim().toLowerCase():"";return NEUTRAL_CHECK_CONCLUSIONS.has(conclusion)}function allRequiredChecksGreen(pollResponse,requiredChecks){if(pollResponse===null||typeof pollResponse!="object")return!1;let obj=pollResponse,maybeDetail=obj.detail;maybeDetail&&typeof maybeDetail=="object"&&(Array.isArray(maybeDetail.checks)||"all_passed"in maybeDetail)&&(obj=maybeDetail);let rawChecks=Array.isArray(obj.checks)?obj.checks:[];if(requiredChecks.length===0)return obj.all_passed===!0;let meaningfulNames=new Set;for(let record of rawChecks){if(record===null||typeof record!="object"||Array.isArray(record))continue;let name=normalizeSelectorCheckName(record.name);name!==null&&!isNeutralCheckRecord(record)&&meaningfulNames.add(name)}let arbitrated=rawChecks.filter(record=>{if(record===null||typeof record!="object"||Array.isArray(record))return!0;let name=normalizeSelectorCheckName(record.name);return name===null?!0:!(isNeutralCheckRecord(record)&&meaningfulNames.has(name))}),{byName}=selectLatestChecksByName(arbitrated),isGreen=c=>{if(!c)return!1;let conclusion=typeof c.conclusion=="string"?c.conclusion.toLowerCase():"",status=typeof c.status=="string"?c.status.toLowerCase():"",bucket=typeof c.bucket=="string"?c.bucket.toLowerCase():"";return c.green===!0||conclusion==="success"||status==="success"||bucket==="pass"||isNeutralCheckRecord(c)};return requiredChecks.every(name=>isGreen(byName.get(name)))}function extractMergeCommitOid(parsed){let mc=parsed?.mergeCommit;if(mc&&typeof mc=="object"&&typeof mc.oid=="string")return mc.oid}function isMergedAtExpectedHead(state,headOid,expectedSha){return typeof state=="string"&&state.toUpperCase()==="MERGED"&&typeof headOid=="string"&&headOid.toLowerCase()===expectedSha.toLowerCase()}function readBoundedRefName(value){if(typeof value!="string")return;let trimmed=value.trim();return trimmed.length>0?trimmed:void 0}async function readPrMergeState(run,ghEnv,pr,json=PR_STATE_JSON){let view=await run("gh",["pr","view",String(pr),"--json",json],ghEnv);if(view.timedOut)return{ok:!1,reason:"gh_pr_view_timeout"};if(view.status!==0)return{ok:!1,reason:"gh_pr_view_failed"};try{let parsed=JSON.parse(view.stdout);return{ok:!0,headOid:parsed.headRefOid,state:parsed.state,mergeCommitOid:extractMergeCommitOid(parsed),baseRefName:readBoundedRefName(parsed.baseRefName),headRefName:readBoundedRefName(parsed.headRefName),raw:parsed}}catch{return{ok:!1,reason:"gh_pr_view_unparseable"}}}function buildAlreadyMergedResponse(request,baseDetails,mergeCommitSha){let details={...baseDetails,already_merged:!0,...mergeCommitSha?{merge_commit_sha:mergeCommitSha}:{}};return buildResponse(request,"succeeded",null,!0,[{type:"merge.succeeded",status:"succeeded",details}])}function ciPollFailureDetailFromError(err){if(!(err instanceof ConductorBridgeApiError))return;let kind=err.kind;if(kind!=="timeout"&&kind!=="network"&&kind!=="unauthorized"&&kind!=="server"&&kind!=="http")return;let detail={kind,diagnostic:safeDiagnosticMessage(err,"ci_poll_failed")};return typeof err.status=="number"&&Number.isInteger(err.status)&&(detail.status=err.status),detail}function ciPollFailureReasonFromDetail(detail){if(!detail)return"ci_poll_failed";switch(detail.kind){case"timeout":return"ci_poll_timeout";case"network":return"ci_poll_network";case"unauthorized":return"ci_poll_unauthorized";case"server":return"ci_poll_server";case"http":return typeof detail.status=="number"&&Number.isInteger(detail.status)?`ci_poll_http_${detail.status}`:"ci_poll_http"}}function isAmbiguousCiPollFailureReason(reason){return reason.startsWith("ci_poll_")}async function waitForRequiredChecksGreen(pollCi,access,expectedSha,requiredChecks,timeoutMs,pollIntervalMs,sleep2,now,signal){let start=now();for(;;){if(signal?.aborted)return{ok:!1,reason:"merge_aborted"};let pollResponse;try{pollResponse=await pollCi(access,expectedSha)}catch(err){let pollFailure=ciPollFailureDetailFromError(err);return{ok:!1,reason:ciPollFailureReasonFromDetail(pollFailure),pollFailure}}if(allRequiredChecksGreen(pollResponse,requiredChecks))return{ok:!0};if(now()-start>=timeoutMs)return{ok:!1,reason:"ci_not_green"};if(await sleep2(pollIntervalMs),signal?.aborted)return{ok:!1,reason:"merge_aborted"}}}function makeLocalMergeExecutor(options={},deps={}){let method=resolveLocalMergeMethod(options.method),expectedBaseBranch=readBoundedRefName(options.expectedBaseBranch),expectedHeadBranch=readBoundedRefName(options.expectedHeadBranch),rawRun=deps.runCommand??defaultRunCommand,run=(cmd,args,env)=>Promise.resolve(rawRun(cmd,args,env,deps.signal)),pollCi=deps.pollCi??pollCiChecksForCommit,sleep2=deps.sleep??defaultSleep,now=deps.now??(()=>Date.now()),signal=deps.signal,ciWaitTimeoutMs=sanitizeWaitMs(options.ciWaitTimeoutMs,DEFAULT_CI_WAIT_TIMEOUT_MS),ciWaitPollIntervalMs=sanitizeWaitMs(options.ciWaitPollIntervalMs,DEFAULT_CI_WAIT_POLL_INTERVAL_MS),ghEnv={...deps.env,GH_PROMPT_DISABLED:"1",GH_NO_UPDATE_NOTIFIER:"1"};return async(access,request)=>{let pr=request.pr_number,expectedSha=request.expected_head_sha,requiredChecks=request.gate?.required_checks??[],baseDetails={action_key:request.action_key,repo:request.repo_name,pr_number:pr,expected_head_sha:expectedSha,merge_method:method,executor:"local"},fail=(reason,pollFailure)=>{let details=pollFailure?{...baseDetails,poll_error:{kind:pollFailure.kind,...typeof pollFailure.status=="number"?{status:pollFailure.status}:{},diagnostic:pollFailure.diagnostic}}:baseDetails;return buildResponse(request,"failed",reason,!1,[{type:"merge.failed",status:"failed",reason,details}])},verifyMergedStateAfterAmbiguousFailure=async()=>{let read=await readPrMergeState(run,ghEnv,pr);return read.ok&&isMergedAtExpectedHead(read.state,read.headOid,expectedSha)?buildAlreadyMergedResponse(request,baseDetails,read.mergeCommitOid):null};if(signal?.aborted)return fail("merge_aborted");if(options.approvalRequired)return buildResponse(request,"pending_approval","local_merge_approval_required",!1,[{type:"merge.pending_approval",status:"pending_approval",reason:"local_merge_approval_required",details:baseDetails}]);let firstRead=await readPrMergeState(run,ghEnv,pr);if(!firstRead.ok){let verified=await verifyMergedStateAfterAmbiguousFailure();return verified||fail(firstRead.reason)}if(isMergedAtExpectedHead(firstRead.state,firstRead.headOid,expectedSha))return buildAlreadyMergedResponse(request,baseDetails,firstRead.mergeCommitOid);let firstRefMismatch=findRefMismatch(expectedBaseBranch,expectedHeadBranch,firstRead);if(firstRefMismatch)return buildRefMismatchResponse(request,baseDetails,firstRefMismatch);if(typeof firstRead.headOid!="string"||firstRead.headOid.toLowerCase()!==expectedSha.toLowerCase())return fail("head_drift");if(typeof firstRead.state=="string"&&firstRead.state.toUpperCase()!=="OPEN")return fail("pr_not_open");if(!options.skipCiWait){let ciWait=await waitForRequiredChecksGreen(pollCi,access,expectedSha,requiredChecks,ciWaitTimeoutMs,ciWaitPollIntervalMs,sleep2,now,signal);if(!ciWait.ok){if(isAmbiguousCiPollFailureReason(ciWait.reason)){let verified=await verifyMergedStateAfterAmbiguousFailure();if(verified)return verified}return fail(ciWait.reason,ciWait.pollFailure)}let secondRead=await readPrMergeState(run,ghEnv,pr);if(!secondRead.ok){let verified=await verifyMergedStateAfterAmbiguousFailure();return verified||fail(secondRead.reason)}if(isMergedAtExpectedHead(secondRead.state,secondRead.headOid,expectedSha))return buildAlreadyMergedResponse(request,baseDetails,secondRead.mergeCommitOid);let secondRefMismatch=findRefMismatch(expectedBaseBranch,expectedHeadBranch,secondRead);if(secondRefMismatch)return buildRefMismatchResponse(request,baseDetails,secondRefMismatch);if(typeof secondRead.headOid!="string"||secondRead.headOid.toLowerCase()!==expectedSha.toLowerCase())return fail("head_drift");if(typeof secondRead.state=="string"&&secondRead.state.toUpperCase()!=="OPEN")return fail("pr_not_open")}if(signal?.aborted)return fail("merge_aborted");let merge=await run("gh",["pr","merge",String(pr),`--${method}`,"--match-head-commit",expectedSha],ghEnv);if(merge.status!==0){if(merge.timedOut){let verified=await verifyMergedStateAfterAmbiguousFailure();if(verified)return verified;let reason="gh_merge_timeout";return buildResponse(request,"failed",reason,!1,[{type:"merge.attempted",status:"attempted",details:baseDetails},{type:"merge.failed",status:"failed",reason,details:baseDetails}])}if(isLikelyGhMergeConflictOutput(merge))return buildConflictResponse(request,baseDetails,expectedSha,{mergeable:null,mergeStateStatus:null});let recheck=await readPrMergeState(run,ghEnv,pr,PR_STATE_MERGEABILITY_JSON);if(recheck.ok){if(isMergedAtExpectedHead(recheck.state,recheck.headOid,expectedSha))return buildAlreadyMergedResponse(request,baseDetails,recheck.mergeCommitOid);let mergeability={mergeable:null,mergeStateStatus:null};try{mergeability=parseGhPrMergeabilityFields(recheck.raw)}catch{}if(isPrMergeConflict(mergeability))return buildConflictResponse(request,baseDetails,expectedSha,mergeability)}let mergeFailReason="gh_merge_failed";return buildResponse(request,"failed",mergeFailReason,!1,[{type:"merge.attempted",status:"attempted",details:baseDetails},{type:"merge.failed",status:"failed",reason:mergeFailReason,details:baseDetails}])}let mergeCommitSha,post=await run("gh",["pr","view",String(pr),"--json","mergeCommit"],ghEnv);if(post.status===0)try{mergeCommitSha=extractMergeCommitOid(JSON.parse(post.stdout))}catch{}let succeededDetails={...baseDetails,...mergeCommitSha?{merge_commit_sha:mergeCommitSha}:{}};return buildResponse(request,"succeeded",null,!0,[{type:"merge.attempted",status:"attempted",details:baseDetails},{type:"merge.succeeded",status:"succeeded",details:succeededDetails}])}}function buildConflictResponse(request,baseDetails,expectedSha,mergeability){let reason="gh_merge_conflict",conflictDetails={...baseDetails,head_sha:expectedSha,...mergeability.mergeable?{mergeable:mergeability.mergeable}:{},...mergeability.mergeStateStatus?{mergeStateStatus:mergeability.mergeStateStatus}:{}};return buildResponse(request,"failed",reason,!1,[{type:"merge.attempted",status:"attempted",details:baseDetails},{type:"merge.conflict",status:"failed",reason,details:conflictDetails}])}function findRefMismatch(expectedBaseBranch,expectedHeadBranch,actual){if(expectedBaseBranch!==void 0&&actual.baseRefName!==expectedBaseBranch)return{field:"base",expected:expectedBaseBranch,actual:actual.baseRefName??""};if(expectedHeadBranch!==void 0&&actual.headRefName!==expectedHeadBranch)return{field:"head",expected:expectedHeadBranch,actual:actual.headRefName??""}}function buildRefMismatchResponse(request,baseDetails,mismatch){let reason="ref_mismatch",details={...baseDetails,mismatched_field:mismatch.field,[`expected_${mismatch.field}_branch`]:mismatch.expected,[`actual_${mismatch.field}_branch`]:mismatch.actual,message:`No provider merge was attempted: the pull request's current ${mismatch.field} branch does not match the run's expected ${mismatch.field} branch. Rebuild or cherry-pick the change against the expected run base rather than retargeting the pull request in the GitHub UI.`};return buildResponse(request,"failed",reason,!1,[{type:"merge.failed",status:"failed",reason,details}])}async function preflightLocalGh(run,ghEnv){let version;try{version=await run("gh",["--version"],ghEnv)}catch{return{ok:!1,reason:"local_gh_unavailable"}}if(version.status!==0)return{ok:!1,reason:"local_gh_unavailable"};let auth;try{auth=await run("gh",["auth","status"],ghEnv)}catch{return{ok:!1,reason:"local_gh_unauthenticated"}}return auth.status!==0?{ok:!1,reason:"local_gh_unauthenticated"}:{ok:!0}}async function runApprovedLocalMerge(request,options={},deps={}){let ghEnv={...deps.env,GH_PROMPT_DISABLED:"1",GH_NO_UPDATE_NOTIFIER:"1"},rawRun=deps.runCommand??defaultRunCommand,preflight=await preflightLocalGh((cmd,args,env)=>Promise.resolve(rawRun(cmd,args,env,deps.signal)),ghEnv);return preflight.ok?makeLocalMergeExecutor({method:options.method,skipCiWait:!0},deps)({get baseUrl(){throw new Error("runApprovedLocalMerge must not poll CI")},get apiKey(){throw new Error("runApprovedLocalMerge must not poll CI")},get repoName(){throw new Error("runApprovedLocalMerge must not poll CI")}},request):buildResponse(request,"failed",preflight.reason,!1,[{type:"merge.failed",status:"failed",reason:preflight.reason,details:{action_key:request.action_key,repo:request.repo_name,pr_number:request.pr_number,expected_head_sha:request.expected_head_sha,executor:"local"}}])}var MERGE_METHODS,PR_STATE_JSON,PR_STATE_MERGEABILITY_JSON,DEFAULT_COMMAND_TIMEOUT_MS,DEFAULT_CI_WAIT_TIMEOUT_MS,DEFAULT_CI_WAIT_POLL_INTERVAL_MS,NEUTRAL_CHECK_CONCLUSIONS,init_local_merge=__esm({"src/conductor/local-merge.ts"(){"use strict";init_bridge_api_client();init_github_mergeability();init_latest_check_selector();MERGE_METHODS=new Set(["squash","merge","rebase"]),PR_STATE_JSON="headRefOid,state,mergeCommit,baseRefName,headRefName",PR_STATE_MERGEABILITY_JSON="headRefOid,state,mergeCommit,mergeable,mergeStateStatus,baseRefName,headRefName",DEFAULT_COMMAND_TIMEOUT_MS=6e4,DEFAULT_CI_WAIT_TIMEOUT_MS=18e4,DEFAULT_CI_WAIT_POLL_INTERVAL_MS=5e3;NEUTRAL_CHECK_CONCLUSIONS=new Set(["skipped","neutral"])}});var init_epic_integration_pr=__esm({"src/epic-integration-pr.ts"(){"use strict"}});var init_base_branch=__esm({"src/executor/base-branch.ts"(){"use strict";init_base_ref()}});var init_merge_job=__esm({"src/executor/merge-job.ts"(){"use strict";init_local_merge();init_bridge_api_client();init_epic_integration_pr();init_job_errors();init_base_branch()}});var init_worktree_inspection=__esm({"src/executor/worktree-inspection.ts"(){"use strict";init_job_errors()}});var init_resume_pre_spawn=__esm({"src/executor/resume-pre-spawn.ts"(){"use strict";init_worktree_core();init_job_errors();init_worktree_inspection()}});var init_prompt_spec=__esm({"src/executor/prompt-spec.ts"(){"use strict";init_job_errors()}});var init_results=__esm({"src/executor/results.ts"(){"use strict"}});var init_terminal_mutation=__esm({"src/executor/terminal-mutation.ts"(){"use strict";init_types3()}});var init_verdict_artifact=__esm({"src/executor/verdict-artifact.ts"(){"use strict";init_job_errors();init_worktree_inspection()}});var init_stale_artifacts=__esm({"src/executor/stale-artifacts.ts"(){"use strict";init_verdict_artifact();init_worktree_inspection()}});var init_env_file_guard=__esm({"src/executor/env-file-guard.ts"(){"use strict";init_worktree_inspection()}});var init_worker_log=__esm({"src/executor/worker-log.ts"(){"use strict";init_worktree_inspection()}});var init_worktree_lock=__esm({"src/executor/worktree-lock.ts"(){"use strict";init_worktree_inspection()}});var init_job_log_registry=__esm({"src/executor/job-log-registry.ts"(){"use strict";init_worktree_inspection()}});var init_viewer_tabs=__esm({"src/executor/viewer-tabs.ts"(){"use strict";init_start_tickets()}});var init_interrupted_worktree=__esm({"src/executor/interrupted-worktree.ts"(){"use strict"}});var init_merge_tree_classifier=__esm({"src/executor/merge-tree-classifier.ts"(){"use strict";init_file_scope_guard()}});var init_reconcile_overlap_governance=__esm({"src/executor/reconcile-overlap-governance.ts"(){"use strict"}});var init_reconcile_overlap_types=__esm({"src/executor/reconcile-overlap-types.ts"(){"use strict"}});var init_worker_finalization=__esm({"src/executor/worker-finalization.ts"(){"use strict";init_job_errors();init_job_types()}});var init_reconcile_overlap_job=__esm({"src/executor/reconcile-overlap-job.ts"(){"use strict";init_bridge_api_client();init_file_scope_guard();init_local_merge();init_env();init_job_errors();init_merge_tree_classifier();init_reconcile_overlap_governance();init_reconcile_overlap_types();init_worker_finalization()}});var init_index_scope=__esm({"src/executor/index-scope.ts"(){"use strict";init_index_scope_contract()}});var init_worktree=__esm({"src/executor/worktree.ts"(){"use strict";init_base_ref();init_claude_review_workflow_drift();init_start_tickets_prereqs();init_worktree_core();init_command_provisioning()}});var REQUIRED_MCP_REGISTRATION_MISSING_MESSAGE,init_job_runner=__esm({"src/executor/job-runner.ts"(){"use strict";init_heartbeat();init_job_errors();init_merge_job();init_observation();init_mcp_provisioning();init_executor_adapter_registry();init_executor_adapter();init_agent_identity();init_process();init_resume_pre_spawn();init_prompt_spec();init_start_tickets_conductor();init_results();init_terminal_mutation();init_stale_artifacts();init_env_file_guard();init_verdict_artifact();init_worker_log();init_worktree_lock();init_job_log_registry();init_viewer_tabs();init_job_types();init_interrupted_worktree();init_reconcile_overlap_job();init_base_branch();init_index_scope();init_worker_finalization();init_worktree();init_pr_base_contract();init_worker_command();init_observation();init_mcp_identity();REQUIRED_MCP_REGISTRATION_MISSING_MESSAGE=`the required '${MCP_SERVER_NAME}' MCP registration is missing or unreadable in the prepared worktree; a worker loads MCP servers strictly from that file, so refusing to spawn a worker that would run without Bridge tools`}});var init_live_worker_registry=__esm({"src/executor/live-worker-registry.ts"(){"use strict"}});var EXECUTOR_WORKTREE_GC_IDLE_MS,init_worktree_gc=__esm({"src/executor/worktree-gc.ts"(){"use strict";init_worktree_inspection();EXECUTOR_WORKTREE_GC_IDLE_MS=1440*60*1e3}});var init_runner=__esm({"src/executor/runner.ts"(){"use strict";init_preflight2();init_job_runner();init_job_log_registry();init_live_worker_registry();init_worktree_gc();init_base_ref();init_epic_integration_pr()}});var init_watch_cli=__esm({"src/executor/watch-cli.ts"(){"use strict";init_job_log_registry()}});var init_cli=__esm({"src/executor/cli.ts"(){"use strict";init_version_generated();init_start_tickets_prereqs();init_start_tickets_repo();init_agent_identity();init_claim_scope();init_deps();init_credentials();init_http_client();init_platform();init_runner();init_watch_cli()}});function executorLaunchdDirForHome(homeDir){return pathApiForPlatform("darwin").join(homeDir,...LAUNCHD_DIR_SEGMENTS)}function executorSystemdDirForHome(homeDir){return pathApiForPlatform("linux").join(homeDir,...SYSTEMD_DIR_SEGMENTS)}function executorIdFromLaunchdFilename(filename){if(!filename.startsWith(EXECUTOR_LAUNCHD_LABEL_PREFIX)||!filename.endsWith(EXECUTOR_LAUNCHD_FILENAME_SUFFIX))return null;let id=filename.slice(EXECUTOR_LAUNCHD_LABEL_PREFIX.length,filename.length-EXECUTOR_LAUNCHD_FILENAME_SUFFIX.length);return id.length>0?id:null}function executorIdFromSystemdFilename(filename){if(!filename.startsWith(EXECUTOR_SYSTEMD_UNIT_PREFIX)||!filename.endsWith(EXECUTOR_SYSTEMD_UNIT_SUFFIX))return null;let id=filename.slice(EXECUTOR_SYSTEMD_UNIT_PREFIX.length,filename.length-EXECUTOR_SYSTEMD_UNIT_SUFFIX.length);return id.length>0?id:null}function xmlUnescape(value){return value.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}function readArgumentContract(args){let repos=[],executorId=null;for(let i=0;i<args.length;i++)args[i]==="--repo"&&typeof args[i+1]=="string"?repos.push(args[++i]):args[i]==="--executor-id"&&typeof args[i+1]=="string"&&(executorId=args[++i]);return{repos,executorId}}function inspectLaunchdPlist(content){let problems=[],envMatch=content.match(new RegExp(`<key>${EXECUTOR_SERVICE_BASE_URL_ENV}</key>\\s*<string>([^<]*)</string>`)),baseUrl=envMatch?xmlUnescape(envMatch[1]):null;baseUrl===null&&problems.push(`no ${EXECUTOR_SERVICE_BASE_URL_ENV} entry found in the plist`);let arrayMatch=content.match(/<key>ProgramArguments<\/key>\s*<array>([\s\S]*?)<\/array>/),args=[];arrayMatch?args=Array.from(arrayMatch[1].matchAll(/<string>([^<]*)<\/string>/g)).map(m=>xmlUnescape(m[1])):problems.push("no ProgramArguments array found in the plist");let{repos,executorId}=readArgumentContract(args);return{ok:problems.length===0,baseUrl,repos,executorId,problems}}function splitSystemdTokens(value){let tokens=[],current="",inQuotes=!1,started=!1;for(let i=0;i<value.length;i++){let ch=value[i];ch==="\\"&&i+1<value.length?(current+=value[++i],started=!0):ch==="%"&&value[i+1]==="%"?(current+="%",i++,started=!0):ch==='"'?(inQuotes=!inQuotes,started=!0):!inQuotes&&/\s/.test(ch)?(started&&tokens.push(current),current="",started=!1):(current+=ch,started=!0)}return started&&tokens.push(current),tokens}function inspectSystemdService(content){let problems=[],lines=content.split(/\r?\n/),envLine=lines.find(l=>l.startsWith(`Environment=${EXECUTOR_SERVICE_BASE_URL_ENV}=`)),baseUrl=null;if(envLine){let raw=envLine.slice(`Environment=${EXECUTOR_SERVICE_BASE_URL_ENV}=`.length);baseUrl=splitSystemdTokens(raw)[0]??null}(baseUrl===null||baseUrl.length===0)&&(baseUrl=null,problems.push(`no ${EXECUTOR_SERVICE_BASE_URL_ENV} directive found in the unit`));let execLine=lines.find(l=>l.startsWith("ExecStart=")),args=[];execLine?args=splitSystemdTokens(execLine.slice(10)):problems.push("no ExecStart directive found in the unit");let{repos,executorId}=readArgumentContract(args);return{ok:problems.length===0,baseUrl,repos,executorId,problems}}function inspectExecutorServiceArtifact(kind,content){try{return kind==="launchd-plist"?inspectLaunchdPlist(content):inspectSystemdService(content)}catch{return{ok:!1,baseUrl:null,repos:[],executorId:null,problems:["unit content could not be parsed"]}}}var EXECUTOR_LAUNCHD_LABEL_PREFIX,EXECUTOR_LAUNCHD_FILENAME_SUFFIX,EXECUTOR_SYSTEMD_UNIT_PREFIX,EXECUTOR_SYSTEMD_UNIT_SUFFIX,EXECUTOR_SERVICE_BASE_URL_ENV,LAUNCHD_DIR_SEGMENTS,SYSTEMD_DIR_SEGMENTS,init_service_unit=__esm({"src/executor/service-unit.ts"(){"use strict";init_platform_escaping();init_worktree_core();init_mcp_server_invocation();init_cli();init_credentials();EXECUTOR_LAUNCHD_LABEL_PREFIX="com.bridge-gpt.executor.",EXECUTOR_LAUNCHD_FILENAME_SUFFIX=".plist",EXECUTOR_SYSTEMD_UNIT_PREFIX="bridge-gpt-executor-",EXECUTOR_SYSTEMD_UNIT_SUFFIX=".service",EXECUTOR_SERVICE_BASE_URL_ENV="BAPI_BASE_URL",LAUNCHD_DIR_SEGMENTS=["Library","LaunchAgents"],SYSTEMD_DIR_SEGMENTS=[".config","systemd","user"]}});var init_service_lifecycle=__esm({"src/executor/service-lifecycle.ts"(){"use strict";init_platform_escaping()}});var init_install_preflight=__esm({"src/executor/install-preflight.ts"(){"use strict";init_claude_login();init_platform()}});var init_executor=__esm({"src/executor/index.ts"(){"use strict";init_cli();init_runner();init_service_unit();init_service_lifecycle();init_install_preflight();init_watch_cli()}});var init_stale_worktree_doctor=__esm({"src/stale-worktree-doctor.ts"(){"use strict";init_worktree_core()}});import path12 from"path";function resolveExecutorServiceConvention(platform,homeDir){return platform==="darwin"?{dir:executorLaunchdDirForHome(homeDir),kind:"launchd-plist",idFromFilename:executorIdFromLaunchdFilename}:platform==="linux"?{dir:executorSystemdDirForHome(homeDir),kind:"systemd-service",idFromFilename:executorIdFromSystemdFilename}:null}async function probeRepoCredential(repo,deps,credDeps){let target=`bapi:${repo}`,resolve2=deps.resolveCredentials??resolveBapiCredentials;try{let result=await resolve2(repo,credDeps);return result.ok?{repo,target,resolved:!0,source:String(result.credentials.source)}:{repo,target,resolved:!1,kind:String(result.kind)}}catch{return{repo,target,resolved:!1,kind:"unavailable"}}}async function collectExecutorServiceDiagnostics(deps){if(deps.platform==="win32")return{status:"skipped",reason:"Windows executor services are set up manually through Task Scheduler, so there is no generated unit to enumerate (`executor install-service` prints the command line instead)."};let convention=resolveExecutorServiceConvention(deps.platform,deps.homedir());if(!convention)return{status:"skipped",reason:`platform '${deps.platform}' has no generated executor service format.`};let entries;try{entries=await deps.readdir(convention.dir)}catch{return{status:"skipped",reason:`no executor service units found (${convention.dir} is absent or unreadable).`}}let matching=entries.filter(name=>convention.idFromFilename(name)!==null).sort((a,b)=>a<b?-1:a>b?1:0);if(matching.length===0)return{status:"skipped",reason:`no executor service units found in ${convention.dir}.`};let credDeps={env:deps.env,homedir:deps.homedir,platform:deps.platform,readFile:deps.readFile,stat:deps.stat,stderr:()=>{}},pathApi=path12.posix,units=[],warnings=[];for(let name of matching){let unitPath=pathApi.join(convention.dir,name),executorId=convention.idFromFilename(name)??name;try{await deps.stat(unitPath)}catch{warnings.push(`${unitPath}: disappeared or became unreadable during collection.`);continue}let content;try{content=await deps.readFile(unitPath)}catch{units.push({path:unitPath,executorId,baseUrl:null,baseUrlClass:"missing",repos:[],credentials:[],warnings:["unit could not be read; its configuration cannot be verified."]});continue}let inspection=inspectExecutorServiceArtifact(convention.kind,content),unitWarnings=[...inspection.problems],baseUrlClass;inspection.baseUrl?inspection.baseUrl.replace(/\/+$/,"")===DEFAULT_BAPI_BASE_URL?(baseUrlClass="production-default",unitWarnings.push(`${EXECUTOR_SERVICE_BASE_URL_ENV} points at production (${DEFAULT_BAPI_BASE_URL}) \u2014 legal, but worth confirming this host is meant to serve production jobs.`)):baseUrlClass="configured":(baseUrlClass="missing",unitWarnings.push(`no ${EXECUTOR_SERVICE_BASE_URL_ENV} in the unit \u2014 the executor requires an explicit base URL and will fail to start.`));let distinctRepos=Array.from(new Set(inspection.repos)),credentials=[];for(let repo of distinctRepos)credentials.push(await probeRepoCredential(repo,deps,credDeps));units.push({path:unitPath,executorId,baseUrl:inspection.baseUrl,baseUrlClass,repos:inspection.repos,credentials,warnings:unitWarnings})}return{status:"collected",units,warnings}}var LEGACY_REGISTRATION_INFO_TEXT,init_doctor2=__esm({"src/doctor.ts"(){"use strict";init_start_tickets();init_version_generated();init_install_doctor();init_codex_bridge_profile();init_executor_adapter_inspection();init_executor_adapter_registry();init_env_flags();init_bridge_api_urls();init_tool_surface_gating();init_credential_store();init_bridge_api_client();init_bridge_client();init_checkpoint_store();init_lock();init_start_tickets_repo();init_worker_containment_diagnostic();init_launcher_config_inspection();init_mcp_identity();init_agent_registry();init_start_tickets_prereqs();init_mcp_profile();init_executor();init_credentials();init_claude_login();init_base_ref();init_manifest();init_ticket_key_utils();init_worktree_core();init_stale_worktree_doctor();LEGACY_REGISTRATION_INFO_TEXT=`This registration remains supported. New installs use \`${MCP_SERVER_NAME}\`. No action is required.`}});function unreported(id){return{id,state:"unreported",detail:UNREPORTED_DETAIL,remediation:BRING_UP_UNREPORTED_REMEDIATION,refusal:"bring-up-facts-unreported"}}function classifyDatabaseMigration(bringUp){let id="database-migration-current";return bringUp===null?unreported(id):bringUp.migration_readable?bringUp.database_migration_current?{id,state:"ok",detail:"the database is at (or ahead of) the code migration head"}:{id,state:"bad",detail:"the database is BEHIND the server's code migration head",remediation:DATABASE_MIGRATION_BEHIND_REMEDIATION,refusal:"database-migration-behind"}:{id,state:"unreadable",detail:"the migration state could not be read (unknown, not confirmed behind)",remediation:DATABASE_MIGRATION_UNREADABLE_REMEDIATION,refusal:"database-migration-unreadable"}}function classifyWorkerPresent(bringUp){let id="worker-present";return bringUp===null?unreported(id):bringUp.heartbeat_readable?bringUp.worker_present?{id,state:"ok",detail:"a reconciler heartbeat is fresh"}:{id,state:"bad",detail:"0 fresh reconcilers \u2014 no worker is running against this deployment",remediation:WORKER_NOT_PRESENT_REMEDIATION,refusal:"worker-not-present"}:{id,state:"unreadable",detail:"the reconciler heartbeat could not be read (unknown, not confirmed absent)",remediation:WORKER_HEARTBEAT_UNREADABLE_REMEDIATION,refusal:"worker-heartbeat-unreadable"}}function classifySingleTransitionAuthority(bringUp){let id="single-transition-authority";return bringUp===null?unreported(id):bringUp.heartbeat_readable?bringUp.fresh_reconciler_count>=2?{id,state:"bad",detail:"2+ fresh reconcilers \u2014 more than one transition authority is ticking",remediation:SECOND_RECONCILER_REMEDIATION,refusal:"second-reconciler-detected"}:bringUp.fresh_reconciler_count===0?{id,state:"bad",detail:"0 fresh reconcilers \u2014 no transition authority is ticking",remediation:WORKER_NOT_PRESENT_REMEDIATION,refusal:"worker-not-present"}:{id,state:"ok",detail:"exactly 1 fresh reconciler"}:{id,state:"unreadable",detail:"the reconciler heartbeat could not be read (unknown, not confirmed)",remediation:WORKER_HEARTBEAT_UNREADABLE_REMEDIATION,refusal:"worker-heartbeat-unreadable"}}function classifyBringUpFacts(bringUp){return[classifyDatabaseMigration(bringUp),classifyWorkerPresent(bringUp),classifySingleTransitionAuthority(bringUp)]}function capitalize(text){return text.length===0?text:text[0].toUpperCase()+text.slice(1)}var BRING_UP_RUNBOOK,BRING_UP_UNREPORTED_REMEDIATION,DATABASE_MIGRATION_UNREADABLE_REMEDIATION,DATABASE_MIGRATION_BEHIND_REMEDIATION,WORKER_HEARTBEAT_UNREADABLE_REMEDIATION,WORKER_NOT_PRESENT_REMEDIATION,SECOND_RECONCILER_REMEDIATION,UNREPORTED_DETAIL,BRING_UP_REFUSAL_MESSAGES,init_bring_up_facts=__esm({"src/conductor/bring-up-facts.ts"(){"use strict";BRING_UP_RUNBOOK="docs/claude/epic-conductor-v2-operator-runbook.md",BRING_UP_UNREPORTED_REMEDIATION="upgrade the Bridge API deploy to a build that reports the bring-up safety facts; their state is unknown here, not healthy.",DATABASE_MIGRATION_UNREADABLE_REMEDIATION=`retry; the migration state could not be read, which is not the same as confirmed-behind. If it persists, check the applied revision with \`alembic current\` (${BRING_UP_RUNBOOK} \xA73d).`,DATABASE_MIGRATION_BEHIND_REMEDIATION=`confirm the applied revision with \`alembic current\` (not \`alembic heads\`, which reads the migration scripts), apply this checkout's migrations with \`alembic -c alembic.ini upgrade head\`, then retry (${BRING_UP_RUNBOOK} \xA73d).`,WORKER_HEARTBEAT_UNREADABLE_REMEDIATION="retry once the Bridge API database is reachable; the reconciler heartbeat could not be read, so worker presence is unknown, not confirmed absent.",WORKER_NOT_PRESENT_REMEDIATION=`start a worker (\`python worker.py\`, or bring up a local plane) \u2014 a server started with DISABLE_SCHEDULER=true runs none. Create and approve only against a server that has a worker (${BRING_UP_RUNBOOK} \xA73d).`,SECOND_RECONCILER_REMEDIATION=`find and stop the extra reconciler: check \`ps aux | grep worker.py\` for a reparented survivor of an earlier plane (${BRING_UP_RUNBOOK} \xA76), and note that a dev server started without DISABLE_SCHEDULER=true runs a reconciler too. A reconciler stopped in the last 120 seconds still counts \u2014 heartbeat rows are not deleted on shutdown \u2014 so wait and retry.`,UNREPORTED_DETAIL="not reported by this Bridge API deploy";BRING_UP_REFUSAL_MESSAGES={"bring-up-facts-unreported":"the Bridge API did not report the bring-up safety facts (database migration, worker presence, single reconciler), so none of them could be confirmed. "+capitalize(BRING_UP_UNREPORTED_REMEDIATION),"database-migration-unreadable":"database migration: the server could not read whether its database is at the migration head, so this is unknown, not confirmed behind. "+capitalize(DATABASE_MIGRATION_UNREADABLE_REMEDIATION),"database-migration-behind":"database migration: the server's database is BEHIND its code's migration head, so the code would run against a schema that was never applied. "+capitalize(DATABASE_MIGRATION_BEHIND_REMEDIATION),"worker-heartbeat-unreadable":"worker presence: the durable reconciler heartbeat could not be read, so whether a worker is running is unknown, not confirmed absent. "+capitalize(WORKER_HEARTBEAT_UNREADABLE_REMEDIATION),"worker-not-present":"worker presence: no reconciler heartbeat is fresh, so nothing would drive this run. "+capitalize(WORKER_NOT_PRESENT_REMEDIATION),"second-reconciler-detected":"single transition authority: two or more reconcilers are ticking the shared database, and two transition authorities wedge an epic. "+capitalize(SECOND_RECONCILER_REMEDIATION)}}});function supervisorSection(readiness){let s=readiness.supervisor,sections=[];if(!s.setup_present||!s.config_present){let missing=[s.setup_present?null:"setup",s.config_present?null:"config"].filter(Boolean).join(" and ");sections.push({id:"supervisor-configuration",label:"Supervisor configuration",status:"degraded",detail:`project-default supervisor ${missing} absent`,remediation:"bootstrap writes the safe project-default posture."})}else sections.push({id:"supervisor-configuration",label:"Supervisor configuration",status:"ok",detail:`setup=${s.setup_source}, config=${s.config_source}`});sections.push(s.required_checks_empty?{id:"supervisor-required-checks",label:"Supervisor required CI checks",status:"degraded",detail:"required-check list is EMPTY \u2014 the done gate would pass unconditionally",remediation:"bootstrap writes a non-empty required-check list into done_gate_config."}:{id:"supervisor-required-checks",label:"Supervisor required CI checks",status:"ok",detail:`${s.required_checks_count} required check(s) configured`});let alignment=s.review_policy_alignment;return alignment!==null&&(alignment.status==="divergent"||alignment.status==="invalid"?sections.push({id:"supervisor-review-alignment",label:"Supervisor review-policy alignment",status:"degraded",detail:alignment.explanation,remediation:alignment.status==="invalid"?"fix the done gate's review_state condition \u2014 review configuration exists but cannot be read, so the merge path refuses rather than merges.":`set the repository review-policy default and the done gate's review_state condition to the same signal, or confirm the difference is intended \u2014 see ${CONDUCTOR_OPERATOR_RUNBOOK_POINTER}.`}):sections.push({id:"supervisor-review-alignment",label:"Supervisor review-policy alignment",status:"ok",detail:alignment.explanation})),sections}function githubCredentialsSection(readiness){let g=readiness.github;if(g.credentials_complete)return{id:"github-credentials",label:"GitHub App credentials",status:"ok",detail:"owner, repository id, and installation id all resolved"};let missing=[g.owner_resolved?null:"owner",g.repo_id_resolved?null:"repository id",g.installation_id_resolved?null:"installation id"].filter(Boolean).join(", ");return{id:"github-credentials",label:"GitHub App credentials",status:"degraded",detail:g.credentials_readable?`incomplete: ${missing} unresolved`:"no GitHub credential row for this repository",remediation:"connect GitHub from the Bridge setup UI (`install-bridge connect-github`)."}}function githubActionsSection(readiness){let g=readiness.github;return g.actions_write?{id:"github-actions-permission",label:"GitHub App actions permission",status:"ok",detail:"actions: write"}:g.actions_probe_succeeded?{id:"github-actions-permission",label:"GitHub App actions permission",status:"degraded",detail:`actions: ${g.actions_permission_level}`,remediation:"grant the GitHub App `actions: write`; the conductor's workflow rerun lane fails open on 403 without it."}:{id:"github-actions-permission",label:"GitHub App actions permission",status:"degraded",detail:"permission could not be checked",remediation:"re-run once credentials resolve; the workflow rerun lane fails open on 403 until this reads `write`."}}function reconcilerSection(readiness){let r=readiness.reconciler;return r.liveness_readable?r.stale?{id:"reconciler-liveness",label:"Reconciler tick liveness",status:"degraded",detail:r.last_tick_at===null?"no reconciler tick recorded for this repository":`last tick ${r.last_tick_age_seconds}s ago (threshold ${readiness.thresholds.reconciler_stale_after_seconds}s)`,remediation:"start the reconciler (`epic-implementer epic-tick` schedule) for this repository."}:{id:"reconciler-liveness",label:"Reconciler tick liveness",status:"ok",detail:`last tick ${r.last_tick_age_seconds}s ago across ${r.active_run_count} active run(s)`}:{id:"reconciler-liveness",label:"Reconciler tick liveness",status:"degraded",detail:"liveness could not be read",remediation:"retry once the Bridge API is reachable; reconciler liveness is unknown here, which is not the same as confirmed-stale."}}function bringUpSection(verdict){let base={id:verdict.id,label:BRING_UP_SECTION_LABELS[verdict.id]};return verdict.state==="ok"?{...base,status:"ok",detail:verdict.detail}:{...base,status:"degraded",detail:verdict.detail,...verdict.remediation?{remediation:verdict.remediation}:{}}}function databaseMigrationCurrentSection(readiness){return bringUpSection(classifyDatabaseMigration(readiness.bring_up??null))}function workerPresentSection(readiness){return bringUpSection(classifyWorkerPresent(readiness.bring_up??null))}function singleTransitionAuthoritySection(readiness){return bringUpSection(classifySingleTransitionAuthority(readiness.bring_up??null))}function bringUpSafetySections(readiness){return[databaseMigrationCurrentSection(readiness),workerPresentSection(readiness),singleTransitionAuthoritySection(readiness)]}function workflowSection(presence,reviewPolicySource,driftDetail){return presence==="present"?{id:"claude-review-workflow",label:"claude-review workflow",status:"ok",detail:driftDetail?`.github/workflows/claude-review.yml present \u2014 ${driftDetail}`:".github/workflows/claude-review.yml present"}:presence==="drifted"?{id:"claude-review-workflow",label:"claude-review workflow",status:"degraded",detail:driftDetail??".github/workflows/claude-review.yml differs from the repository default branch",remediation:CLAUDE_REVIEW_WORKFLOW_DRIFT_REMEDIATION}:reviewPolicySource==="native_review_decision"||reviewPolicySource==="none"?{id:"claude-review-workflow",label:"claude-review workflow",status:"ok",detail:`not applicable for review policy '${reviewPolicySource}'`}:{id:"claude-review-workflow",label:"claude-review workflow",status:"degraded",detail:presence==="unreadable"?".github/workflows/claude-review.yml could not be read":".github/workflows/claude-review.yml absent",remediation:"the selected review policy consumes the sticky verdict this workflow emits; install the template."}}function executorProvisioningSection(diagnostics){let base={id:"executor-provisioning",label:"Executor provisioning"};if(diagnostics===null)return{...base,status:"degraded",detail:"executor service-unit diagnostics could not be collected",remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION};if(diagnostics.status==="skipped")return{...base,status:"degraded",detail:diagnostics.reason,remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION};let unhealthy=diagnostics.units.filter(unit=>unit.warnings.length>0||unit.credentials.some(cred=>!cred.resolved)),ids=diagnostics.units.map(unit=>unit.executorId).join(", ");return unhealthy.length===0&&diagnostics.warnings.length===0?{...base,status:"ok",detail:`${diagnostics.units.length} generated service unit(s) found (${ids}); unit presence only \u2014 see the service-state and observation sections`}:{...base,status:"degraded",detail:`${diagnostics.units.length} generated service unit(s) found (${ids}), but ${unhealthy.length} unit(s) carry warnings or unresolved credentials \u2014 see the embedded executor-provisioning report`,remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION}}function executorServiceStateSection(observations,unitsDiscovered,inspectorAvailable){let base={id:"executor-service-state",label:"Executor service state"};if(!unitsDiscovered)return{...base,status:"degraded",detail:"no generated unit to inspect, so no service state was collected",remediation:EXECUTOR_INSTALL_SERVICE_REMEDIATION};if(!inspectorAvailable||observations.length===0)return{...base,status:"degraded",detail:"local service state could not be collected on this host",remediation:EXECUTOR_SERVICE_START_REMEDIATION};let rendered=[...observations].sort((a,b)=>a.executorId<b.executorId?-1:a.executorId>b.executorId?1:0).map(o=>`${o.executorId}=${o.state}`).join(", ");return observations.every(o=>o.state==="active")?{...base,status:"ok",detail:`service state: ${rendered}`}:{...base,status:"degraded",detail:`service state: ${rendered}`,remediation:EXECUTOR_SERVICE_START_REMEDIATION}}function executorObservationSection(readiness){let base={id:"executor-observation",label:"Executor server observation"};if(readiness===null||!readiness.executor.liveness_readable)return{...base,status:"degraded",detail:"server executor observation is unknown (readiness could not be read)",remediation:"retry once the Bridge API is reachable; no readiness claim is made from local state."};let e=readiness.executor,seen=e.last_seen_at===null?"never seen":`last seen ${e.last_seen_at} (${e.last_seen_age_seconds}s ago)`;return e.ready===!0?{...base,status:"ok",detail:`executor_ready \u2014 ${seen}`}:e.ready===!1?{...base,status:"degraded",detail:`observed but stale/not ready \u2014 ${seen}`,remediation:EXECUTOR_SERVICE_START_REMEDIATION}:{...base,status:"degraded",detail:`never observed by the server \u2014 ${seen}`,remediation:EXECUTOR_SERVICE_START_REMEDIATION}}function detectConductorContext(legacyConductor,profile){return legacyConductor?.mcp_profile?.conductor_context_detected===!0||profile?.tokenPresent===!0}function conductorProfileTokenSection(profile,conductorContext){let base={id:"conductor-profile-token",label:"MCP conductor profile token"};if(profile===null)return{...base,status:"degraded",detail:"the host MCP profile token could not be inspected",remediation:CONDUCTOR_PROFILE_TOKEN_REMEDIATION};let carrying=profile.configs.filter(c=>c.state==="token-present").map(c=>c.path),scope="inspected .mcp.json, .vscode/mcp.json, .cursor/mcp.json only (Codex and Copilot host configuration is not inspected)";if(carrying.length>0)return{...base,status:"ok",detail:`\`${profile.token}\` present in ${carrying.join(", ")}; ${scope}`};let detail=profile.bridgeEntryPresent?`no supported host config carries the \`${profile.token}\` token; ${scope}`:`no supported host config carries a Bridge entry; ${scope}`,remediation=profile.bridgeEntryPresent?CONDUCTOR_PROFILE_TOKEN_REMEDIATION:CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION;return conductorContext?{...base,status:"degraded",detail,remediation}:{...base,status:"ok",detail:`advisory \u2014 ${detail}`,remediation}}function conductorHookTargetsSection(legacyConductor,conductorContext){let base={id:"conductor-hook-targets",label:"Conductor hook targets"};if(legacyConductor==null)return{...base,status:"degraded",detail:"hook targets could not be derived (the epic-implementer doctor was not collected)",remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION};let hooks=legacyConductor.git_hooks;if(hooks===void 0)return{...base,status:"degraded",detail:"hook targets could not be derived (the epic-implementer doctor reported no hook state)",remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION};if(!hooks.is_worktree)return{...base,status:"ok",detail:"advisory \u2014 not a git worktree, so no managed conductor hooks apply"};let usable=name=>{let hook=(hooks.hooks??[]).find(h=>h.name===name);return hook!==void 0&&hook.exists&&hook.managed_block_present&&hook.embedded_bin_is_file},rendered=MANAGED_HOOK_NAMES.map(name=>`${name}=${usable(name)}`).join(", ");if(MANAGED_HOOK_NAMES.every(name=>usable(name)))return{...base,status:"ok",detail:`managed hooks usable: ${rendered}`};let detail=`managed hooks usable: ${rendered}`;return conductorContext?{...base,status:"degraded",detail,remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION}:{...base,status:"ok",detail:`advisory \u2014 ${detail}`,remediation:CONDUCTOR_HOOK_TARGET_REMEDIATION}}function conductorLedgerLoadabilitySection(legacyConductor){let base={id:"conductor-ledger-loadability",label:"Conductor ledger loadability"};if(legacyConductor==null)return{...base,status:"degraded",detail:"ledger loadability could not be derived (the epic-implementer doctor was not collected)",remediation:CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION};let inspection=legacyConductor.native_ledger;if(inspection===void 0)return{...base,status:"degraded",detail:"ledger loadability could not be derived (the epic-implementer doctor reported no native-ledger state)",remediation:CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION};let availability=describeNativeLedgerAvailability(inspection);return availability.status==="available"?{...base,status:"ok",detail:"ledger available \u2014 the native binding loads"}:{...base,status:"degraded",detail:`ledger degraded \u2014 ${availability.module} did not load (NODE_MODULE_VERSION ${availability.nodeModulesAbi}, failure: ${availability.failureKind})`,remediation:CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION}}async function inspectWorkflowPresence(readWorkflowFile,classifyWorkflowDrift){let local=await inspectWorkflowLocalPresence(readWorkflowFile);if(local!=="present"||!classifyWorkflowDrift)return{presence:local};try{let classification=await classifyWorkflowDrift();return classification.state==="drifted"?{presence:"drifted",driftDetail:summarizeClaudeReviewWorkflowDrift(classification)}:classification.state==="unverified"?{presence:"present",driftDetail:summarizeClaudeReviewWorkflowDrift(classification)}:{presence:"present"}}catch{return{presence:"present"}}}async function inspectWorkflowLocalPresence(readWorkflowFile){try{return await readWorkflowFile(),"present"}catch(err){return err?.code==="ENOENT"?"absent":"unreadable"}}var CONDUCTOR_OPERATOR_RUNBOOK_POINTER,CONDUCTOR_PROFILE_TOKEN,CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION,CONDUCTOR_PROFILE_TOKEN_REMEDIATION,CONDUCTOR_HOOK_TARGET_REMEDIATION,CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION,EXECUTOR_INSTALL_SERVICE_REMEDIATION,EXECUTOR_SERVICE_START_REMEDIATION,BRING_UP_SECTION_LABELS,init_readiness_sections=__esm({"src/conductor/readiness-sections.ts"(){"use strict";init_git_hooks();init_mcp_identity();init_claude_review_workflow_drift();init_doctor();init_bring_up_facts();CONDUCTOR_OPERATOR_RUNBOOK_POINTER="docs/claude/epic-conductor-v2-operator-runbook.md",CONDUCTOR_PROFILE_TOKEN="conductor",CONDUCTOR_PROFILE_TOKEN_NO_ENTRY_REMEDIATION=`no supported host MCP config carries a Bridge entry \u2014 run \`npx ${MCP_PACKAGE_NAME} install\` to register one, then re-run \`install conductor\`.`,CONDUCTOR_PROFILE_TOKEN_REMEDIATION="re-run `install conductor` and accept the tool-visibility consent; the conductor tools become visible after the MCP client is restarted.",CONDUCTOR_HOOK_TARGET_REMEDIATION="re-run `install conductor` and accept the local-observability consent, or run `epic-implementer install-git-hooks` directly.",CONDUCTOR_LEDGER_LOADABILITY_REMEDIATION="`better-sqlite3` is an optionalDependency npm silently skips on a build failure \u2014 reinstall it for this Node runtime to restore local conductor observability.",EXECUTOR_INSTALL_SERVICE_REMEDIATION=`generate a persistent unit with \`install conductor --executor-id <id>\` or \`executor install-service\` (or run the executor by hand) \u2014 see ${CONDUCTOR_OPERATOR_RUNBOOK_POINTER}.`,EXECUTOR_SERVICE_START_REMEDIATION=`start the service (re-run \`install conductor\` and accept the start consent, or run the printed launchctl/systemctl command by hand) \u2014 see ${CONDUCTOR_OPERATOR_RUNBOOK_POINTER}.`;BRING_UP_SECTION_LABELS={"database-migration-current":"Database migration","worker-present":"Worker present","single-transition-authority":"Single transition authority"}}});import{readdir as fsReaddir,readFile as fsReadFile,stat as fsStat}from"node:fs/promises";import os5 from"node:os";async function settle(collect){if(!collect)return{value:null,failed:!1};try{return{value:await collect(),failed:!1}}catch{return{value:null,failed:!0}}}async function runConductorInstallDoctor(deps){let sections=[],buildConductor=deps.buildConductorReport??buildConductorDoctorReport,collectInstall=deps.collectInstallChecks??(deps.installDoctorDeps?()=>collectInstallStatusChecks(deps.installDoctorDeps):null),[conductorSettled,executorPreflightSettled,installChecksSettled]=await Promise.all([settle(()=>buildConductor(deps.conductorDoctorDeps)),settle(deps.collectExecutorPreflight?()=>deps.collectExecutorPreflight():null),settle(collectInstall)]),legacyConductor=conductorSettled.value??null;conductorSettled.failed&§ions.push({id:"conductor-ledger",label:"Conductor ledger doctor",status:"degraded",detail:"the local epic-implementer doctor could not be built",remediation:"run `epic-implementer doctor` directly to see why the local ledger report failed."});let legacyExecutorPreflight=executorPreflightSettled.value??null;executorPreflightSettled.failed&§ions.push({id:"executor-preflight",label:"Executor preflight",status:"degraded",detail:"the executor preflight could not be collected",remediation:"re-run this command; if it persists, run `executor` directly to surface the preflight failure."});let legacyInstallChecks=installChecksSettled.value??null;installChecksSettled.failed&§ions.push({id:"install-status",label:"Bridge install status",status:"degraded",detail:"the install-status checklist could not be collected",remediation:"run `doctor` to collect the advisory install-status checklist on its own."});let readiness=null;if(!deps.access)sections.push({id:"bridge-access",label:"Bridge API access",status:"fatal",detail:deps.accessError??"Bridge API repository/credential could not be resolved",remediation:"run `install-bridge` (or set BAPI_API_KEY) for this repository."});else try{readiness=await fetchConductorReadiness(deps.access,deps.fetch)}catch(err){let kind=err instanceof ConductorBridgeApiError?err.kind:"network",fatalKind=kind==="unauthorized"||kind==="invalid-input";sections.push({id:"server-readiness",label:"Server readiness",status:fatalKind?"fatal":"degraded",detail:kind==="unauthorized"?"Bridge API rejected the credential for this repository":kind==="invalid-input"?"the readiness response failed shape validation":"the readiness endpoint could not be reached",remediation:fatalKind?"re-check the API key and repository, then re-run.":"retry; the local sections above are unaffected."})}readiness&&(sections.push(...supervisorSection(readiness)),sections.push(githubCredentialsSection(readiness)),sections.push(githubActionsSection(readiness)));let workflow=await inspectWorkflowPresence(deps.readWorkflowFile,deps.classifyWorkflowDrift);sections.push(workflowSection(workflow.presence,deps.reviewPolicySource,workflow.driftDetail)),readiness&&(sections.push(...bringUpSafetySections(readiness)),sections.push(reconcilerSection(readiness)));let collectServiceUnits=deps.collectExecutorServiceUnits??(()=>collectExecutorServiceDiagnostics({platform:process.platform,env:process.env,homedir:os5.homedir,readdir:dirPath=>fsReaddir(dirPath),readFile:filePath=>fsReadFile(filePath,"utf-8"),stat:filePath=>fsStat(filePath)})),executorService=null;try{executorService=await collectServiceUnits()}catch{}sections.push(executorProvisioningSection(executorService));let discoveredUnits=executorService!==null&&executorService.status!=="skipped"?executorService.units:[],executorServiceStates=[];if(deps.inspectExecutorServiceState&&discoveredUnits.length>0)for(let unit of discoveredUnits)try{let state=await deps.inspectExecutorServiceState({executorId:unit.executorId});executorServiceStates.push({executorId:unit.executorId,state})}catch{executorServiceStates.push({executorId:unit.executorId,state:"unknown"})}sections.push(executorServiceStateSection(executorServiceStates,discoveredUnits.length>0,!!deps.inspectExecutorServiceState)),sections.push(executorObservationSection(readiness));let inspectProfile=deps.inspectProfileToken??((projectRoot,token)=>inspectBridgeApiProfileToken(projectRoot,token,{readFile:filePath=>fsReadFile(filePath,"utf-8")})),profileToken=null;try{profileToken=await inspectProfile(deps.projectRoot??process.cwd(),CONDUCTOR_PROFILE_TOKEN)}catch{}let conductorContext=detectConductorContext(legacyConductor,profileToken);return sections.push(conductorProfileTokenSection(profileToken,conductorContext)),sections.push(conductorHookTargetsSection(legacyConductor,conductorContext)),sections.push(conductorLedgerLoadabilitySection(legacyConductor)),{legacyConductor,legacyExecutorPreflight,legacyInstallChecks,executorService,executorServiceStates,readiness,sections}}var init_install_doctor2=__esm({"src/conductor/install-doctor.ts"(){"use strict";init_doctor();init_mcp_host_config();init_doctor2();init_install_doctor();init_readiness_sections();init_bridge_api_client();init_readiness_sections();init_bring_up_facts()}});function mapServerReadinessToChecks(readiness,failure="unreachable"){if(readiness===null){let copy=SERVER_FAILURE_COPY[failure];return SERVER_READINESS_DESCRIPTORS.map(({id,label})=>createReadinessCheck({id:`server.${id}`,source:"server",label,status:"fail",detail:copy.detail,remediation:copy.remediation}))}let s=readiness.supervisor,g=readiness.github,r=readiness.reconciler,e=readiness.executor,outcomes=[];outcomes.push(s.setup_present?{id:"supervisor-setup",status:"pass",detail:`stored (source: ${s.setup_source})`}:{id:"supervisor-setup",status:"fail",detail:"no supervisor setup is stored for this repository",remediation:SERVER_REMEDIATIONS.supervisorSetup}),outcomes.push(s.config_present?{id:"supervisor-config",status:"pass",detail:`stored (source: ${s.config_source})`}:{id:"supervisor-config",status:"fail",detail:"no supervisor configuration is stored for this repository",remediation:SERVER_REMEDIATIONS.supervisorConfig}),outcomes.push(s.required_checks_empty?{id:"supervisor-required-checks",status:"warn",detail:"the required-check list is EMPTY \u2014 the done gate would pass unconditionally",remediation:SERVER_REMEDIATIONS.requiredChecks}:{id:"supervisor-required-checks",status:"pass",detail:`${s.required_checks_count} required check(s) configured`}),outcomes.push({id:"auto-merge",status:"pass",detail:s.auto_merge_enabled?"auto-merge enabled":"auto-merge disabled (operator posture)"}),outcomes.push(s.merge_approval_required_set?{id:"merge-approval",status:"pass",detail:"merge-approval requirement is set explicitly"}:{id:"merge-approval",status:"warn",detail:"the merge-approval requirement is unset, so the merge path falls back to its default",remediation:SERVER_REMEDIATIONS.mergeApproval}),outcomes.push(reviewPolicyOutcome(readiness)),outcomes.push(g.credentials_complete?{id:"github-credentials",status:"pass",detail:"owner, repository id, and installation id all resolved"}:{id:"github-credentials",status:"fail",detail:g.credentials_readable?`incomplete: ${[g.owner_resolved?null:"owner",g.repo_id_resolved?null:"repository id",g.installation_id_resolved?null:"installation id"].filter(Boolean).join(", ")} unresolved`:"no GitHub credential row exists for this repository",remediation:SERVER_REMEDIATIONS.githubCredentials}),outcomes.push(githubActionsOutcome(readiness)),outcomes.push(...bringUpOutcomes(readiness)),outcomes.push(reconcilerOutcome(readiness)),outcomes.push(executorOutcome(readiness)),outcomes.push(reviewWorkflowOutcome(readiness)),outcomes.push(ciWorkflowOutcome(readiness)),outcomes.push(...unattendedOutcomes(readiness));let byId=new Map(outcomes.map(outcome=>[outcome.id,outcome]));return SERVER_READINESS_DESCRIPTORS.map(({id,label})=>{let outcome=byId.get(id);return outcome?createReadinessCheckSafely({id:`server.${id}`,source:"server",label,status:outcome.status,detail:outcome.detail,...outcome.status==="pass"?{}:{remediation:outcome.remediation??SERVER_REMEDIATIONS.olderServer}}):createReadinessCheck({id:`server.${id}`,source:"server",label,status:"fail",detail:"this server fact was not reported",remediation:SERVER_REMEDIATIONS.olderServer})})}function bringUpOutcomes(readiness){return classifyBringUpFacts(readiness.bring_up??null).map(verdict=>verdict.state==="ok"?{id:verdict.id,status:"pass",detail:verdict.detail}:{id:verdict.id,status:"fail",detail:verdict.detail,remediation:verdict.remediation??SERVER_REMEDIATIONS.olderServer})}function unattendedOutcomes(readiness){let u=readiness.unattended;return u===null?["unattended-consent","unattended-notify-default","repository-workflow-readiness"].map(id=>({id,status:"fail",detail:"this server fact was not reported",remediation:SERVER_REMEDIATIONS.olderServer})):[u.conductor_allowed?{id:"unattended-consent",status:"pass",detail:"this repository has consented to unattended conductor runs"}:{id:"unattended-consent",status:"warn",detail:"unattended_epic_implementer_allowed is NOT set \u2014 an unattended run will be refused before it is created",remediation:SERVER_REMEDIATIONS.unattendedConsent},u.notify_webhook_default_declared?{id:"unattended-notify-default",status:"pass",detail:u.notify_webhook_default_verified===!0?"a notify webhook default is declared and verified":"a notify webhook default is declared (verified at approval, not here)"}:{id:"unattended-notify-default",status:"warn",detail:"no repository notify webhook default is declared \u2014 an unattended run needs an escalation channel, and no column supplies a repository default today, so the run must declare notify.webhook_url itself",remediation:SERVER_REMEDIATIONS.unattendedNotifyDefault},u.repository_readiness_confirmed?{id:"repository-workflow-readiness",status:"pass",detail:"the review and conductor-CI workflows are both confirmed"}:{id:"repository-workflow-readiness",status:"warn",detail:"the review and conductor-CI workflows are not both confirmed \u2014 an unattended auto-merging run will be refused",remediation:SERVER_REMEDIATIONS.repositoryWorkflowReadiness}]}function reviewPolicyOutcome(readiness){let s=readiness.supervisor,alignment=s.review_policy_alignment;return alignment!==null?alignment.status==="divergent"||alignment.status==="invalid"?{id:"review-policy",status:"warn",detail:alignment.explanation,remediation:SERVER_REMEDIATIONS.reviewPolicyDivergent}:{id:"review-policy",status:"pass",detail:alignment.explanation}:s.review_policy_present?{id:"review-policy",status:"pass",detail:"a repository review-policy default is stored (alignment not reported by this server)"}:{id:"review-policy",status:"warn",detail:"no repository review-policy default is stored",remediation:SERVER_REMEDIATIONS.reviewPolicyMissing}}function githubActionsOutcome(readiness){let g=readiness.github;return g.actions_write?{id:"github-actions-permission",status:"pass",detail:"actions: write"}:g.actions_probe_succeeded?{id:"github-actions-permission",status:"warn",detail:`actions: ${g.actions_permission_level}`,remediation:SERVER_REMEDIATIONS.actionsMissing}:{id:"github-actions-permission",status:"fail",detail:"the actions permission could not be checked (this is not a confirmed absence)",remediation:SERVER_REMEDIATIONS.actionsProbeFailed}}function reconcilerOutcome(readiness){let r=readiness.reconciler;return r.liveness_readable?r.stale?{id:"reconciler-liveness",status:"fail",detail:r.last_tick_at===null?"no reconciler tick has been recorded for this repository":`last tick ${r.last_tick_age_seconds}s ago (server threshold ${readiness.thresholds.reconciler_stale_after_seconds}s)`,remediation:SERVER_REMEDIATIONS.reconcilerStale}:{id:"reconciler-liveness",status:"pass",detail:`last tick ${r.last_tick_age_seconds}s ago across ${r.active_run_count} active run(s)`}:{id:"reconciler-liveness",status:"fail",detail:"reconciler liveness could not be read",remediation:SERVER_REMEDIATIONS.reconcilerUnreadable}}function executorOutcome(readiness){let e=readiness.executor;return e.liveness_readable?e.ready===!0?{id:"executor-readiness",status:"pass",detail:`executor ready \u2014 last seen ${e.last_seen_age_seconds}s ago`}:e.ready===!1?{id:"executor-readiness",status:"fail",detail:`observed but not ready \u2014 last seen ${e.last_seen_age_seconds}s ago (server threshold ${readiness.thresholds.executor_stale_after_seconds}s)`,remediation:SERVER_REMEDIATIONS.executorStale}:{id:"executor-readiness",status:"fail",detail:"never observed by the server",remediation:SERVER_REMEDIATIONS.executorNeverSeen}:{id:"executor-readiness",status:"fail",detail:"executor liveness could not be read",remediation:SERVER_REMEDIATIONS.executorUnreadable}}function reviewWorkflowOutcome(readiness){let w=readiness.review_workflow;return w===null?{id:"review-workflow",status:"fail",detail:"this Bridge API deploy did not report the review-workflow facts",remediation:SERVER_REMEDIATIONS.olderServer}:w.probe_succeeded?w.emits_run_id&&w.emits_reviewed_sha?{id:"review-workflow",status:"pass",detail:"the default branch's review workflow emits both protocol markers"}:{id:"review-workflow",status:"fail",detail:`missing marker(s): ${[w.emits_run_id?null:"run id",w.emits_reviewed_sha?null:"reviewed SHA"].filter(Boolean).join(", ")}`,remediation:SERVER_REMEDIATIONS.reviewWorkflowIncomplete}:{id:"review-workflow",status:"fail",detail:w.workflow_present?"the review workflow is present but could not be evaluated":"the review workflow could not be found or read on the default branch",remediation:SERVER_REMEDIATIONS.reviewWorkflowUnknown}}function ciWorkflowOutcome(readiness){let c=readiness.conductor_ci_workflow;return c===null?{id:"conductor-ci-workflow",status:"fail",detail:"this Bridge API deploy did not report the conductor-CI workflow facts",remediation:SERVER_REMEDIATIONS.olderServer}:c.probe_succeeded?c.migration_guard_present?{id:"conductor-ci-workflow",status:"pass",detail:"the default branch's conductor CI workflow runs the migration guard"}:{id:"conductor-ci-workflow",status:"warn",detail:"the conductor CI workflow does not run the migration guard",remediation:SERVER_REMEDIATIONS.ciWorkflowMissingGuard}:{id:"conductor-ci-workflow",status:"fail",detail:c.workflow_present?"the conductor CI workflow is present but could not be evaluated":"the conductor CI workflow could not be found or read on the default branch",remediation:SERVER_REMEDIATIONS.ciWorkflowUnknown}}function sectionStatus(status){return status==="fatal"?"fail":status==="degraded"?"warn":"pass"}function mapInstallSectionsToReadinessChecks(sections){let checks=[],seen=new Set;for(let section of sections??[]){if(INSTALL_SECTION_IDS_OWNED_ELSEWHERE.has(section.id)||seen.has(section.id))continue;seen.add(section.id);let status=sectionStatus(section.status);checks.push(createReadinessCheckSafely({id:`conductor.install-section-${section.id}`,source:"conductor",label:section.label,status,detail:section.detail,...status==="pass"?{}:{remediation:section.remediation??"run `install conductor` for this repository to re-provision this capability."}}))}return checks}async function collectConductorReadinessGate(deps){let[installReport,planeResult]=await Promise.all([runInstallDoctorSafely(deps),runPlaneSafely(deps)]),unavailableSources=[];installReport===null&&unavailableSources.push("install","conductor","server"),deps.runPlanePreflight&&planeResult===null&&unavailableSources.push("plane");let checks=[...mapInstallStatusChecksToReadinessChecks(installReport?.legacyInstallChecks??null,installReport===null),...mapConductorDoctorReportToReadinessChecks(installReport?.legacyConductor??null),...mapInstallSectionsToReadinessChecks(installReport?.sections??null),...mapPlanePreflightToReadinessChecks(planeResult),...mapServerReadinessToChecks(installReport?.readiness??null,classifyServerFailure(installReport))],validated=validateReadinessChecks(checks);return{schemaVersion:CONDUCTOR_READINESS_GATE_SCHEMA_VERSION,advisory:CONDUCTOR_READINESS_ADVISORY_NOTICE,repoName:deps.repoName??null,unavailableSources,checks:validated,summary:summarizeReadinessChecks(validated)}}async function runInstallDoctorSafely(deps){try{return deps.runInstallDoctor?await deps.runInstallDoctor():deps.installDoctor?await runConductorInstallDoctor(deps.conductorDoctorDeps?{...deps.installDoctor,conductorDoctorDeps:deps.conductorDoctorDeps}:deps.installDoctor):null}catch{return null}}async function runPlaneSafely(deps){if(!deps.runPlanePreflight)return null;try{return await deps.runPlanePreflight()}catch{return null}}function classifyServerFailure(report){if(report===null)return"unreachable";let sections=report.sections??[];if(sections.some(section=>section.id==="bridge-access"))return"identity-unresolved";let serverSection=sections.find(section=>section.id==="server-readiness");return serverSection?serverSection.detail.includes("rejected the credential")?"unauthorized":serverSection.detail.includes("shape validation")?"invalid-response":"unreachable":"unreachable"}function readinessTag(status){return status==="fail"?"\u2717 FAIL":status==="warn"?"! WARN":status==="skip"?"- SKIP":"\u2713 PASS"}function formatConductorReadinessGateReport(report){let lines=["Conductor readiness (advisory)","\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",`schema version: ${report.schemaVersion}`,`repository: ${report.repoName??"unresolved"}`,""];for(let source of["install","conductor","plane","server"]){let group=report.checks.filter(check=>check.source===source);if(group.length!==0){lines.push(`[${source}]`);for(let check of group)lines.push(` ${readinessTag(check.status)} ${check.label} (${check.id})`),check.detail&&lines.push(` ${check.detail}`),check.remediation&&lines.push(` \u2192 ${check.remediation}`);lines.push("")}}let{pass,warn,fail,skip}=report.summary;return lines.push(`summary: ${pass} pass, ${warn} warn, ${fail} fail, ${skip} skip`),report.unavailableSources.length>0&&lines.push(`sources that could not be collected: ${report.unavailableSources.join(", ")} (their prerequisites above are reported as failures, not as passes)`),lines.push(""),lines.push(report.advisory),lines.join(`
|
|
124
124
|
`)}var CONDUCTOR_READINESS_GATE_SCHEMA_VERSION,CONDUCTOR_READINESS_ADVISORY_NOTICE,SERVER_READINESS_DESCRIPTORS,SERVER_FAILURE_COPY,SERVER_REMEDIATIONS,INSTALL_SECTION_IDS_OWNED_ELSEWHERE,init_readiness=__esm({"src/conductor/readiness.ts"(){"use strict";init_doctor();init_install_doctor();init_preflight();init_install_doctor2();init_readiness_sections();init_bring_up_facts();init_readiness_check();CONDUCTOR_READINESS_GATE_SCHEMA_VERSION=1,CONDUCTOR_READINESS_ADVISORY_NOTICE="Advisory only. This report never blocks bring-up, approval, or a run, and never changes an exit code. Remediations are operator actions and are never executed automatically. drive-epic's V2_READINESS_REQUIREMENTS remains the only hard route-selection predicate, and the server-side admission remains the only hard refusal.",SERVER_READINESS_DESCRIPTORS=[{id:"supervisor-setup",label:"Supervisor setup"},{id:"supervisor-config",label:"Supervisor configuration"},{id:"supervisor-required-checks",label:"Supervisor required CI checks"},{id:"auto-merge",label:"Auto-merge posture"},{id:"merge-approval",label:"Merge approval configuration"},{id:"review-policy",label:"Review policy"},{id:"github-credentials",label:"GitHub App credentials"},{id:"github-actions-permission",label:"GitHub App actions permission"},{id:"database-migration-current",label:BRING_UP_SECTION_LABELS["database-migration-current"]},{id:"worker-present",label:BRING_UP_SECTION_LABELS["worker-present"]},{id:"single-transition-authority",label:BRING_UP_SECTION_LABELS["single-transition-authority"]},{id:"reconciler-liveness",label:"Reconciler tick liveness"},{id:"executor-readiness",label:"Executor server observation"},{id:"review-workflow",label:"Review workflow protocol"},{id:"conductor-ci-workflow",label:"Conductor CI migration guard"},{id:"unattended-consent",label:"Repository unattended consent"},{id:"unattended-notify-default",label:"Verified notify webhook default"},{id:"repository-workflow-readiness",label:"Repository workflow readiness"}],SERVER_FAILURE_COPY={"identity-unresolved":{detail:"no server facts were read \u2014 the repository identity or credential could not be resolved",remediation:"run /install-bridge (or set BAPI_REPO_NAME and BAPI_API_KEY) for this repository, then re-run."},unauthorized:{detail:"the Bridge API rejected the credential for this repository",remediation:"re-check the API key and repository name, then re-run; the key may have been rotated."},"invalid-response":{detail:"the readiness response failed shape validation, so no server fact can be trusted",remediation:"re-run; if it persists the Bridge API deploy is inconsistent with this CLI version."},unreachable:{detail:"the readiness endpoint could not be reached",remediation:"check network reachability to the Bridge API and re-run; the local checks above are unaffected."}},SERVER_REMEDIATIONS={supervisorSetup:"run `install conductor` (or `setup-epic`) for this repository to write the project-default supervisor posture.",supervisorConfig:"run `install conductor` for this repository to write the project-default supervisor configuration.",requiredChecks:"configure a non-empty required-check list in done_gate_config; an empty list makes the done gate pass unconditionally.",mergeApproval:"set the merge-approval requirement explicitly in the supervisor configuration rather than leaving it unset.",reviewPolicyMissing:"set the repository review-policy default so the merge path and the code_review gate read the same signal.",reviewPolicyDivergent:"align the repository review-policy default with the done gate's review_state condition, or confirm the difference is intended.",githubCredentials:"connect GitHub from the Bridge setup UI (`install-bridge connect-github`) so owner, repository id, and installation id all resolve.",actionsProbeFailed:"re-run once credentials resolve; the permission could not be checked, which is not the same as confirmed-missing.",actionsMissing:"grant the GitHub App `actions: write`; without it the conductor's workflow rerun lane fails open on 403.",reconcilerUnreadable:"retry once the Bridge API is reachable; reconciler liveness is unknown here, not confirmed stale.",reconcilerStale:"start the reconciler for this repository (the `epic-implementer epic-tick` schedule) so ticks resume.",executorUnreadable:"retry once the Bridge API is reachable; no executor readiness claim is ever made from local state.",executorNeverSeen:"provision and start an executor (`install conductor --executor-id <id>` or `executor install-service`); readiness comes only from a live server observation.",executorStale:"restart the executor service; it was observed once and has gone quiet past the server's staleness threshold.",reviewWorkflowUnknown:"re-run; the default branch's review workflow could not be evaluated, which is not the same as it being absent.",reviewWorkflowIncomplete:"install the claude-review workflow template on the default branch so it emits both the run id and the reviewed SHA the verdict protocol reads.",ciWorkflowUnknown:"re-run; the default branch's conductor CI workflow could not be evaluated, which is not the same as the guard being absent.",ciWorkflowMissingGuard:"add the migration-guard job to the conductor CI workflow on the default branch so migrations are checked before a merge.",olderServer:"upgrade the Bridge API deploy so it reports this fact; its state is unknown here, not healthy.",unattendedConsent:"set `unattended_epic_implementer_allowed` for this repository (docs/claude/account-settings-operator-runbook.md), or run setup with --attended.",unattendedNotifyDefault:"supply a --policy-file declaring notify.webhook_url, or run setup with --attended; an unattended run must have a working escalation channel, and notify.local_sink is not one.",repositoryWorkflowReadiness:"run `install-bridge conductor` so the review and conductor-CI workflows are confirmed on the default branch, or run setup with --attended."};INSTALL_SECTION_IDS_OWNED_ELSEWHERE=new Set(["supervisor-configuration","supervisor-required-checks","supervisor-review-alignment","github-credentials","github-actions-permission","reconciler-liveness","executor-observation","server-readiness","bridge-access","conductor-ledger","conductor-ledger-loadability","install-status"])}});function joinCwd(cwd,rel){return`${cwd.endsWith("/")?cwd.slice(0,-1):cwd}/${rel}`}function claudeReviewWorkflowPath(cwd){return joinCwd(cwd,CLAUDE_REVIEW_WORKFLOW_RELPATH)}var VERDICT_CHECK_SCRIPT,init_claude_review_workflow=__esm({"src/claude-review-workflow.ts"(){"use strict";init_claude_review_workflow_drift();VERDICT_CHECK_SCRIPT=[" // Contract: docs/claude/claude-review-verdict-contract.md \xA71-\xA74."," const VERDICT = /claude-review-verdict:\\s*(approved|changes_requested)/i;"," const RUN_ID = /run[-_]id:\\s*(\\d+)/i;"," const REVIEWED_SHA = /Reviewed-SHA:\\s*([0-9A-Za-z._-]+)/i;"," const FULL_SHA = /^[0-9a-f]{40}$/;"," const APPROVED_WORD = /\\bapproved\\b/i;"," const CHANGES_WORD = /\\bchanges.requested\\b/i;"," const expected = String(process.env.EXPECTED_HEAD || '').trim().toLowerCase();",""," // Ambiguity (both verdict words) or absence (neither) yields"," // 'unknown', never 'approved'."," const verdictOf = (body) => {"," const token = VERDICT.exec(body);"," if (token) return token[1].toLowerCase();"," const a = APPROVED_WORD.test(body);"," const c = CHANGES_WORD.test(body);"," if (a && !c) return 'approved';"," if (c && !a) return 'changes_requested';"," return 'unknown';"," };"," const declaredSha = (body) => {"," const m = REVIEWED_SHA.exec(body);"," return m ? m[1].trim().toLowerCase() : null;"," };",""," // \xA72 eligibility: the structured token, or the loose marker."," // Malformed entries are skipped rather than throwing \u2014 one odd"," // comment must not fail the job for a reason unrelated to review."," const build = (comments) => comments.reduce((acc, c, index) => {"," if (!c || typeof c !== 'object') return acc;"," const body = typeof c.body === 'string' ? c.body : '';"," const hasToken = VERDICT.test(body);"," if (!hasToken && body.indexOf('claude-review') === -1) return acc;"," const run = RUN_ID.exec(body);"," const raw = c.updated_at || c.created_at;"," const ts = typeof raw === 'string' ? Date.parse(raw) : NaN;"," acc.push({"," runId: run ? parseInt(run[1], 10) : 0,"," index,"," body,"," hasToken,"," ts: Number.isNaN(ts) ? null : ts,"," });"," return acc;"," }, []);",""," // \xA73 legacy rank: (has a usable timestamp, that instant, carries the"," // token). The array index is deliberately EXCLUDED so a genuine"," // two-verdict contradiction stays detectable instead of being"," // silently resolved as 'whichever came last'."," const rankOf = (c) => [c.ts !== null ? 1 : 0, c.ts === null ? 0 : c.ts, c.hasToken ? 1 : 0];"," const cmpRank = (a, b) => {"," const x = rankOf(a);"," const y = rankOf(b);"," for (let i = 0; i < x.length; i++) {"," if (x[i] !== y[i]) return x[i] < y[i] ? -1 : 1;"," }"," return 0;"," };",""," // \xA73 conflict: equal-ranked candidates that DISAGREE and share one"," // valid Reviewed-SHA. Duplicate upserts of the same verdict are not"," // a conflict, and candidates without shared provenance never proved"," // they examined the same code."," const conflicts = (tied) => {"," if (new Set(tied.map((c) => verdictOf(c.body))).size < 2) return false;"," const shas = new Set("," tied.map((c) => declaredSha(c.body)).filter((s) => s && FULL_SHA.test(s)),"," );"," if (shas.size !== 1) return false;"," const bound = tied.filter((c) => shas.has(declaredSha(c.body)));"," return new Set(bound.map((c) => verdictOf(c.body))).size >= 2;"," };",""," const resolve = (comments) => {"," const candidates = build(comments);"," if (candidates.length === 0) return { valid: false, reason: 'review_verdict_absent' };"," let tied;"," if (candidates.some((c) => c.runId > 0)) {"," const top = Math.max(...candidates.map((c) => c.runId));"," tied = candidates.filter((c) => c.runId === top);"," } else {"," const best = candidates.reduce((a, b) => (cmpRank(a, b) >= 0 ? a : b));"," tied = candidates.filter((c) => cmpRank(c, best) === 0);"," }"," if (conflicts(tied)) return { valid: false, reason: 'review_verdict_conflict' };"," const winner = tied.reduce((a, b) => (a.index >= b.index ? a : b));"," const declared = declaredSha(winner.body);"," if (declared === null) return { valid: false, reason: 'review_verdict_no_head_proof' };"," if (declared !== expected) {"," return {"," valid: false,"," reason: FULL_SHA.test(declared) ? 'review_verdict_stale_head' : 'review_verdict_malformed_sha',"," };"," }"," const verdict = verdictOf(winner.body);"," if (verdict !== 'approved' && verdict !== 'changes_requested') {"," return { valid: false, reason: 'review_verdict_unknown_token' };"," }"," return { valid: true, reason: 'review_verdict_resolved', verdict };"," };",""," if (!FULL_SHA.test(expected)) {"," core.setOutput('status', 'unavailable');"," core.setOutput('valid', 'false');"," core.setOutput('reason', 'checker_invalid_expected_head');"," return;"," }",""," // Bounded, read-only propagation loop: a verdict posted seconds ago"," // may not be visible to the comments API yet, and calling that"," // 'absent' would spend another paid review for nothing."," let outcome = { valid: false, reason: 'checker_not_run' };"," let status = 'unavailable';"," for (let attempt = 1; attempt <= 4; attempt++) {"," let comments;"," try {"," comments = await github.paginate(github.rest.issues.listComments, {"," owner: context.repo.owner,"," repo: context.repo.repo,"," issue_number: Number(process.env.PR_NUMBER),"," per_page: 100,"," });"," } catch (err) {"," status = 'unavailable';"," outcome = { valid: false, reason: 'comment_fetch_failed' };"," await new Promise((r) => setTimeout(r, 10000));"," continue;"," }"," status = 'checked';"," outcome = resolve(comments);"," const retryable ="," outcome.reason === 'review_verdict_absent' ||"," outcome.reason === 'review_verdict_stale_head';"," if (outcome.valid || !retryable || attempt === 4) break;"," await new Promise((r) => setTimeout(r, 10000));"," }"," core.setOutput('status', status);"," core.setOutput('valid', outcome.valid ? 'true' : 'false');"," core.setOutput('reason', outcome.reason);"," core.info('Verdict check: valid=' + outcome.valid + ' reason=' + outcome.reason);"].join(`
|
|
125
125
|
`)}});function endpointForPort(port){return{host:PLANE_SERVER_HOST,port,baseUrl:`http://${PLANE_SERVER_HOST}:${port}`}}function resolvePlaneServerEndpoint(env){let configured=env[PLANE_SERVER_PORT_ENV_VAR];if(typeof configured!="string"||configured.trim().length===0)return{ok:!0,endpoint:endpointForPort(PLANE_SERVER_PORT)};let raw=configured.trim();if(!/^[0-9]+$/.test(raw))return{ok:!1,message:PLANE_SERVER_PORT_INVALID_MESSAGE};let port=Number(raw);return!Number.isInteger(port)||port<1||port>MAX_TCP_PORT?{ok:!1,message:PLANE_SERVER_PORT_INVALID_MESSAGE}:{ok:!0,endpoint:endpointForPort(port)}}var MAX_TCP_PORT,PLANE_SERVER_PORT_INVALID_MESSAGE,init_member_roster=__esm({"src/plane/member-roster.ts"(){"use strict";init_types2();init_manifest();init_claim_scope();MAX_TCP_PORT=65535,PLANE_SERVER_PORT_INVALID_MESSAGE=`${PLANE_SERVER_PORT_ENV_VAR} must be a whole TCP port number in the range 1..${MAX_TCP_PORT}. Unset it to use the default port ${PLANE_SERVER_PORT}, or export a valid port and retry.`}});var init_status=__esm({"src/plane/status.ts"(){"use strict";init_manifest();init_types2()}});var init_shutdown=__esm({"src/plane/shutdown.ts"(){"use strict";init_manifest()}});var PLANE_MEMBER_STARTUP_FAILURES,ALLOWED_STARTUP_FAILURES,init_member_logs=__esm({"src/plane/member-logs.ts"(){"use strict";init_types2();PLANE_MEMBER_STARTUP_FAILURES={spawnThrew:"the process could not be started",noPid:"the process started without a pid",readinessTimeout:"it did not start listening in time",heartbeatReadinessTimeout:"it did not publish a durable heartbeat in time",readinessUnestablished:"its readiness baseline could not be established"},ALLOWED_STARTUP_FAILURES=new Set(Object.values(PLANE_MEMBER_STARTUP_FAILURES))}});var PLANE_PHASE_REQUEST_TIMEOUT_MS,init_supervisor=__esm({"src/plane/supervisor.ts"(){"use strict";init_types2();init_manifest();init_claim_scope();init_member_logs();init_member_roster();init_shutdown();PLANE_PHASE_REQUEST_TIMEOUT_MS=15*6e4}});import{createWriteStream,realpathSync as realpathSync2,statSync as statSync2}from"fs";import{mkdir as mkdir2,open,readdir,readFile as readFile2,rename,stat as stat2,unlink,writeFile as writeFile2}from"fs/promises";import{execFile as execFileCb,spawn as nodeSpawn}from"child_process";import net from"net";import os6 from"os";import path13 from"path";import{fileURLToPath as fileURLToPath2}from"url";function createPlaneFsDeps(){return{readFile:filePath=>readFile2(filePath,"utf-8"),writeFile:(filePath,data)=>writeFile2(filePath,data,"utf-8"),createExclusive:async(filePath,data)=>{let handle=await open(filePath,"wx");try{await handle.writeFile(data,"utf-8")}finally{await handle.close()}},rename:(from,to)=>rename(from,to),unlink:filePath=>unlink(filePath),mkdir:async dirPath=>{await mkdir2(dirPath,{recursive:!0})},stat:async filePath=>{let result=await stat2(filePath);return{mtimeMs:result.mtimeMs,mode:result.mode}},readdir:async dirPath=>(await readdir(dirPath,{withFileTypes:!0})).map(entry=>({name:entry.name,isDirectory:()=>entry.isDirectory(),isFile:()=>entry.isFile()}))}}function createPlaneClock(){return{now:()=>new Date,sleep:ms=>new Promise(resolve2=>setTimeout(resolve2,ms))}}function createPlaneProcessDeps(){return{isAlive:pid=>isProcessAlive(pid,(target,signal)=>process.kill(target,signal)),signal:(pid,signal)=>{try{return process.kill(pid,signal),"sent"}catch(err){let code=err?.code;return code==="ESRCH"?"no-such-process":code==="EPERM"?"permission-denied":"error"}}}}function probeTcpPort(host,port,timeoutMs){return new Promise(resolve2=>{let socket=new net.Socket,settled=!1,finish=result=>{settled||(settled=!0,socket.destroy(),resolve2(result))};socket.setTimeout(timeoutMs),socket.once("connect",()=>finish({kind:"connected"})),socket.once("timeout",()=>finish({kind:"error",error:"probe timed out"})),socket.once("error",err=>{err.code==="ECONNREFUSED"?finish({kind:"refused"}):finish({kind:"error",error:err.code??"probe failed"})}),socket.connect(port,host)})}function createPlaneExecFile(){return(file,args,options)=>new Promise(resolve2=>{execFileCb(file,args,{cwd:options.cwd,shell:!1,windowsHide:!0,timeout:3e4},(error,stdout,stderr)=>{if(error){let code=error.code;resolve2({ok:!1,error:typeof code=="string"?code:"command failed"});return}resolve2({ok:!0,stdout:String(stdout),stderr:String(stderr)})})})}function resolvePackageEntrypoint(overrides={}){let deps={moduleUrl:overrides.moduleUrl??import.meta.url,argv1:overrides.argv1??process.argv[1],realpath:overrides.realpath??defaultRealpath2,isFile:overrides.isFile??defaultIsFile2},moduleFile=moduleFilePath2(deps.moduleUrl),candidates=[];if(moduleFile!==null){let dir=path13.dirname(moduleFile);path13.basename(moduleFile)==="index.js"&&candidates.push(moduleFile),candidates.push(path13.join(dir,"index.js")),candidates.push(path13.join(dir,"..","index.js"))}typeof deps.argv1=="string"&&deps.argv1.length>0&&candidates.push(deps.argv1);let seen=new Set;for(let candidate of candidates){let canonical=deps.realpath(candidate);if(canonical!==null&&!seen.has(canonical)&&(seen.add(canonical),deps.isFile(canonical)))return{ok:!0,entrypoint:canonical}}return{ok:!1,candidatesChecked:seen.size}}function moduleFilePath2(moduleUrl){try{return fileURLToPath2(moduleUrl)}catch{return null}}function defaultRealpath2(filePath){try{return realpathSync2(filePath)}catch{return null}}function defaultIsFile2(filePath){try{return statSync2(filePath).isFile()}catch{return!1}}function resolveHomedir(){return os6.homedir()}var init_defaults=__esm({"src/plane/defaults.ts"(){"use strict";init_types2();init_manifest()}});function buildPreflightDeps(env){return{env,endpoint:resolvePlaneServerEndpoint(env),platform:process.platform,homedir:resolveHomedir,fs:createPlaneFsDeps(),clock:createPlaneClock(),proc:createPlaneProcessDeps(),execFile:createPlaneExecFile(),probePort:probeTcpPort,resolveRuntimeEntrypoint:()=>resolvePackageEntrypoint(),resolveRepoName:resolveRequiredStartTicketsRepoName,resolveCredentials:resolveBapiCredentials}}function runDefaultPlanePreflight(repoRoot,env=process.env){return runPlanePreflight(repoRoot,buildPreflightDeps(env))}var init_cli2=__esm({"src/plane/cli.ts"(){"use strict";init_types2();init_claim_scope();init_build_freshness();init_manifest();init_manifest();init_preflight();init_member_roster();init_status();init_shutdown();init_supervisor();init_defaults();init_credential_store();init_start_tickets_repo()}});var readiness_cli_exports={};__export(readiness_cli_exports,{READINESS_COLLECTION_NOTICE:()=>READINESS_COLLECTION_NOTICE,getReadinessUsage:()=>getReadinessUsage,parseReadinessArgs:()=>parseReadinessArgs,runConductorReadinessCommand:()=>runConductorReadinessCommand});import os7 from"node:os";import{readFile as fsReadFile2,stat as fsStat2}from"node:fs/promises";function getReadinessUsage(){return["Usage: epic-implementer readiness [--json] [--no-deny-probe]","","Read-only ADVISORY report of every conductor prerequisite, consolidated from the","Bridge install checklist, the epic-implementer doctor, the plane preflight, and the","server conductor-readiness collector. Each prerequisite reports pass/warn/fail/skip","and, on a failure, exactly ONE named remediation.","","Remediations are NOT run automatically. This command changes nothing: it starts no","plane, approves no run, writes no file, and always exits 0 \u2014 `drive-epic` remains","the only route-selection gate and the server-side admission the only hard refusal.","","Options:"," --json Print the versioned structured report as JSON"," --no-deny-probe Accepted for parity with `epic-implementer doctor`; inert here, because"," this command never spawns the deny-enforcement probe"," --help Print this usage message"].join(`
|
|
126
126
|
`)}function parseReadinessArgs(argv){let parsed={json:!1,help:!1,noDenyProbe:!1};for(let token of argv)if(token==="--json")parsed.json=!0;else if(token==="--no-deny-probe")parsed.noDenyProbe=!0;else if(token==="--help"||token==="-h")parsed.help=!0;else return{error:`Unknown argument "${token}". Run "epic-implementer readiness --help" for usage.`};return parsed}async function collectProductionReport(repoRoot,env){let accessResult=await resolveConductorBridgeApiAccess({env,cwd:repoRoot}),access=accessResult.ok?accessResult.access:null;return collectConductorReadinessGate({repoName:access?.repoName??null,installDoctor:{access,accessError:accessResult.ok?void 0:accessResult.error,fetch:(...args)=>fetch(...args),reviewPolicySource:"verdict_protocol",readWorkflowFile:()=>fsReadFile2(claudeReviewWorkflowPath(repoRoot),"utf-8"),projectRoot:repoRoot,installDoctorDeps:{env,cwd:repoRoot,platform:process.platform,homedir:os7.homedir,readFile:filePath=>fsReadFile2(filePath,"utf-8"),stat:filePath=>fsStat2(filePath),fetch:(...args)=>fetch(...args)}},conductorDoctorDeps:{env,skipDenyProbe:!0},runPlanePreflight:()=>runDefaultPlanePreflight(repoRoot,env)})}async function runConductorReadinessCommand(argv,deps={}){let sinks=deps.sinks??{stdout:line=>console.log(line),stderr:line=>console.error(line)},parsed=parseReadinessArgs(argv);if("error"in parsed)return sinks.stderr(`Error: ${parsed.error}`),1;if(parsed.help)return sinks.stdout(getReadinessUsage()),0;let cwd=deps.cwd??process.cwd(),env=deps.env??process.env,report=await(deps.collect??(repoRoot=>collectProductionReport(repoRoot,env)))(cwd);return report.unavailableSources.length>0&&sinks.stderr(READINESS_COLLECTION_NOTICE),sinks.stdout(parsed.json?JSON.stringify(report):formatConductorReadinessGateReport(report)),0}var READINESS_COLLECTION_NOTICE,init_readiness_cli=__esm({"src/conductor/readiness-cli.ts"(){"use strict";init_readiness();init_bridge_api_client();init_claude_review_workflow();init_cli2();READINESS_COLLECTION_NOTICE="one or more readiness sources could not be collected; the affected prerequisites are reported as failures."}});var recovery_operations_exports={};__export(recovery_operations_exports,{RECOVERY_TICKET_RETRY_LIMIT:()=>RECOVERY_TICKET_RETRY_LIMIT,abandonEpicRunRecovery:()=>abandonEpicRunRecovery,adoptCurrentHeadAndUnparkWithRetry:()=>adoptCurrentHeadAndUnparkWithRetry,dispatchRemediationRepair:()=>dispatchRemediationRepair,mergeChildRepair:()=>mergeChildRepair,scopeReparseRepair:()=>scopeReparseRepair,stopEpicRunRecovery:()=>stopEpicRunRecovery,unparkEpicTicketWithRetry:()=>unparkEpicTicketWithRetry});import{randomUUID as randomUUID2}from"crypto";async function stopEpicRunRecovery(access,options){try{return(await stopEpicRun(access,{epicRunId:options.epicRunId,reason:options.reason})).committed?{ok:!0,kind:"committed",epicRunId:options.epicRunId}:{ok:!0,kind:"already-stopped",epicRunId:options.epicRunId}}catch(err){if(err instanceof ConductorBridgeApiError&&err.status===409&&err.errorCode==="RUN_TERMINAL"){let status=await readTerminalRunStatus(access,options.epicRunId);return{ok:!1,kind:"terminal",epicRunId:options.epicRunId,status}}return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,message:safeDiagnosticMessage(err,"stop request failed")}}}async function readTerminalRunStatus(access,epicRunId){try{return(await fetchEpicRunState(access,epicRunId)).epic_run.status}catch{return"terminal"}}async function abandonEpicRunRecovery(access,options){let state;try{state=await fetchEpicRunState(access,options.epicRunId)}catch(err){return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,message:safeDiagnosticMessage(err,"could not read run state")}}let currentStatus=state.epic_run.status;if(currentStatus==="abandoned")return{ok:!0,kind:"already-abandoned",epicRunId:options.epicRunId};try{return await updateEpicRunStatus(access,{epicKey:options.epicRunId,status:"abandoned",expectedStatus:currentStatus}),{ok:!0,kind:"abandoned",epicRunId:options.epicRunId}}catch(err){return err instanceof ConductorBridgeApiError&&err.status===400?{ok:!1,kind:"concurrent-change",epicRunId:options.epicRunId,message:"the run's status changed concurrently; re-check its state and retry"}:{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,message:safeDiagnosticMessage(err,"abandon request failed")}}}async function ticketRecoveryWithRetry(access,options,mutate){let idempotencyKey=randomUUID2();for(let attempt=0;attempt<RECOVERY_TICKET_RETRY_LIMIT;attempt+=1){let state;try{state=await fetchEpicRunState(access,options.epicRunId)}catch(err){return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,ticketKey:options.ticketKey,message:safeDiagnosticMessage(err,"could not read run state")}}let ticket=state.ticket_statuses.find(t=>t.ticket_key===options.ticketKey);if(!ticket)return{ok:!1,kind:"ticket-not-found",epicRunId:options.epicRunId,ticketKey:options.ticketKey};let result;try{result=await mutate(access,{epicRunId:options.epicRunId,ticketKey:options.ticketKey,expectedRowVersion:ticket.row_version,idempotencyKey,reason:options.reason})}catch(err){return{ok:!1,kind:"unavailable",epicRunId:options.epicRunId,ticketKey:options.ticketKey,message:safeDiagnosticMessage(err,"recovery request failed")}}if(result.ok)return{ok:!0,kind:"unparked",epicRunId:options.epicRunId,ticketKey:options.ticketKey,status:result.ticket_status.status}}return{ok:!1,kind:"concurrent-change-exhausted",epicRunId:options.epicRunId,ticketKey:options.ticketKey}}async function unparkEpicTicketWithRetry(access,options){return ticketRecoveryWithRetry(access,options,(a,args)=>unparkEpicTicket(a,args))}async function adoptCurrentHeadAndUnparkWithRetry(access,options){return ticketRecoveryWithRetry(access,options,(a,args)=>adoptCurrentHeadAndUnparkTicket(a,args))}function classifyRepairError(err,fallback){return err instanceof ConductorBridgeApiError&&typeof err.status=="number"&&err.errorCode?{ok:!1,kind:"refused",code:err.errorCode,status:err.status,message:err.bodyPreview??err.errorCode}:{ok:!1,kind:"unavailable",message:safeDiagnosticMessage(err,fallback)}}async function scopeReparseRepair(access,options,deps={}){try{return{ok:!0,result:await(deps.scopeReparse??scopeReparse)(access,options)}}catch(err){return classifyRepairError(err,"scope-reparse request failed")}}async function dispatchRemediationRepair(access,options,deps={}){try{return{ok:!0,result:await(deps.dispatchRemediation??dispatchRemediation)(access,options)}}catch(err){return classifyRepairError(err,"dispatch-remediation request failed")}}function boundedLocalMergeReason(reason){return typeof reason=="string"&&LOCAL_MERGE_REASON_RE.test(reason)?reason:"gh_merge_failed"}async function mergeChildRepair(access,options,deps={}){let approval;try{approval=await(deps.mergeChild??mergeChild)(access,options)}catch(err){return classifyRepairError(err,"merge-child request failed")}let{local_execution:local,...serverResult}=approval;if(local===null)return{ok:!0,result:serverResult};let runLocal=deps.runLocalMerge??runApprovedLocalMerge,succeeded=!1,alreadyMerged=!1,failureReason="gh_merge_failed";try{let localResult=await runLocal({repo_name:access.repoName,pr_number:options.prNumber,expected_head_sha:local.expected_head_sha,gate:{name:DEFAULT_GATE_NAME},action_key:`merge-child:${options.epicRunId}:${options.prNumber}`},{method:resolveLocalMergeMethod(local.merge_method)},{env:deps.env??process.env});succeeded=localResult.status==="succeeded",alreadyMerged=succeeded&&localResult.reason==="already_merged",failureReason=boundedLocalMergeReason(localResult.reason)}catch{succeeded=!1}try{let completion=await(deps.completeMergeChild??completeMergeChild)(access,{epicRunId:options.epicRunId,prNumber:options.prNumber,result:succeeded?alreadyMerged?"already_merged":"merged":"failed",...succeeded?{}:{reason:failureReason}}),{local_execution:_ignored,...completed}=completion;return{ok:!0,result:completed}}catch(err){return succeeded?{ok:!1,kind:"unavailable",message:`the pull request was merged by your local gh, but the server could not record it (${safeDiagnosticMessage(err,"completion request failed")}); re-run merge-child to record it \u2014 a merged pull request is answered as already_merged`}:classifyRepairError(err,"merge-child completion failed")}}var RECOVERY_TICKET_RETRY_LIMIT,LOCAL_MERGE_REASON_RE,init_recovery_operations=__esm({"src/conductor/recovery-operations.ts"(){"use strict";init_bridge_api_client();init_git_ci_types();init_local_merge();RECOVERY_TICKET_RETRY_LIMIT=3;LOCAL_MERGE_REASON_RE=/^[a-z0-9_.:-]{1,200}$/}});var recovery_cli_exports={};__export(recovery_cli_exports,{decodeDriverContextFile:()=>decodeDriverContextFile,parseDispatchRemediationArgs:()=>parseDispatchRemediationArgs,parseMergeChildArgs:()=>parseMergeChildArgs,parseScopeReparseArgs:()=>parseScopeReparseArgs,runAbandonRunCommand:()=>runAbandonRunCommand,runAdoptCurrentHeadAndUnparkCommand:()=>runAdoptCurrentHeadAndUnparkCommand,runDispatchRemediationCommand:()=>runDispatchRemediationCommand,runMergeChildCommand:()=>runMergeChildCommand,runScopeReparseCommand:()=>runScopeReparseCommand,runStopRunCommand:()=>runStopRunCommand,runUnparkCommand:()=>runUnparkCommand});import{readFile as readFile3}from"node:fs/promises";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}".`);if(values.has(name))throw new ConductorValidationError(`Flag "${name}" may be given only once.`);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}}function requireFlag(values,flag){let value=values.get(flag);if(value===void 0||value.trim().length===0)throw new ConductorValidationError(`Flag "${flag}" is required and must be non-empty.`);return value.trim()}function parseScopeReparseArgs(argv){let{values,bools}=tokenizeRecoveryFlags(argv,SCOPE_REPARSE_VALUE_FLAGS,RECOVERY_BOOL_FLAGS);return bools.has("--help")?{epicRunId:"",scopeId:"",json:bools.has("--json"),help:!0}:{epicRunId:requireFlag(values,"--epic-run-id"),scopeId:requireFlag(values,"--scope-id"),json:bools.has("--json"),help:!1}}function parseDispatchRemediationArgs(argv){let{values,bools}=tokenizeRecoveryFlags(argv,DISPATCH_REMEDIATION_VALUE_FLAGS,RECOVERY_BOOL_FLAGS);return bools.has("--help")?{epicRunId:"",ticketKey:"",contextFile:"",json:bools.has("--json"),help:!0}:{epicRunId:requireFlag(values,"--epic-run-id"),ticketKey:requireFlag(values,"--ticket-key"),contextFile:requireFlag(values,"--context-file"),json:bools.has("--json"),help:!1}}function parseMergeChildArgs(argv){let{values,bools}=tokenizeRecoveryFlags(argv,MERGE_CHILD_VALUE_FLAGS,RECOVERY_BOOL_FLAGS);if(bools.has("--help"))return{epicRunId:"",prNumber:0,json:bools.has("--json"),help:!0};let epicRunId=requireFlag(values,"--epic-run-id"),rawPr=requireFlag(values,"--pr"),prNumber=/^[1-9][0-9]*$/.test(rawPr)?Number(rawPr):NaN;if(!Number.isSafeInteger(prNumber))throw new ConductorValidationError('Flag "--pr" must be a positive integer pull-request number.');return{epicRunId,prNumber,json:bools.has("--json"),help:!1}}function decodeDriverContextFile(bytes){if(bytes.byteLength>DRIVER_CONTEXT_MAX_BYTES)throw new ConductorValidationError(`--context-file is ${bytes.byteLength} bytes, over DRIVER_CONTEXT_MAX_BYTES (${DRIVER_CONTEXT_MAX_BYTES} UTF-8 bytes). Shorten it and retry; nothing was sent.`);let text;try{text=new TextDecoder("utf-8",{fatal:!0}).decode(bytes)}catch{throw new ConductorValidationError("--context-file must be valid UTF-8 text; nothing was sent.")}if(text.trim().length===0)throw new ConductorValidationError("--context-file is empty or whitespace-only; driver context must say something. Nothing was sent.");return text}function renderRepairResult(outcome,input,json,extraLines=()=>[]){if(outcome.ok&&outcome.result.committed&&!outcome.result.event_recorded&&console.error(`Warning: ${input.verb} on run ${input.epicRunId} (${input.targetLabel}) COMMITTED, but its operator_verb_applied audit event was not recorded. The action stands and is not rolled back. You ran it, so you own reconciling the missing audit record (the server also reported it to Sentry).`),json)return outcome.ok?(console.log(JSON.stringify(outcome.result)),0):(console.log(JSON.stringify(outcome.kind==="refused"?{ok:!1,kind:"refused",code:outcome.code,message:outcome.message}:{ok:!1,kind:"unavailable",message:outcome.message})),1);if(!outcome.ok)return outcome.kind==="refused"?console.error(`Error: ${input.verb} refused on run ${input.epicRunId} (${input.targetLabel}) \u2014 ${outcome.code}: ${outcome.message}`):console.error(`Error: ${input.verb} could not complete on run ${input.epicRunId} (${input.targetLabel}) \u2014 ${outcome.message}.`),1;let result=outcome.result,lines=[`${input.verb} \u2014 run ${input.epicRunId}`,` target: ${input.targetLabel}`,` ${input.stateLabel}: ${result.before??"none"} \u2192 ${result.after??"none"}`,...extraLines(result),` committed: ${result.committed}${result.committed?"":" (already in this state; no change made)"}`,` event recorded: ${result.event_recorded}`];return console.log(lines.join(`
|