@ornexus/neocortex 4.60.41 → 4.60.43
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/dist/sbom.cdx.json +31 -31
- package/install.ps1 +1 -1
- package/install.sh +1 -1
- package/package.json +14 -2
- package/packages/client/dist/commands/invoke.js +57 -56
- package/packages/client/dist/generated/command-registry.generated.d.ts +66 -23
- package/packages/client/dist/generated/command-registry.generated.js +1 -1
- package/packages/client/dist/generated/public-projections.generated.d.ts +100 -0
- package/packages/client/dist/generated/public-projections.generated.js +1 -0
- package/packages/client/dist/git/git-lifecycle-store.d.ts +17 -0
- package/packages/client/dist/git/git-lifecycle-store.js +4 -4
- package/packages/client/dist/index.d.ts +1 -0
- package/packages/client/dist/index.js +1 -1
- package/packages/client/dist/migrations/project-identity.js +7 -7
- package/packages/client/dist/migrations/state-json.d.ts +14 -0
- package/packages/client/dist/migrations/state-json.js +4 -0
- package/packages/client/dist/runner/headless/epic-git-reconciliation-inventory.d.ts +2 -0
- package/packages/client/dist/runner/headless/epic-git-reconciliation-inventory.js +1 -1
- package/packages/client/dist/runner/headless/epic-terminal-git-cli-adapter.js +8 -8
- package/packages/client/dist/runner/headless/run-yoloop.d.ts +7 -1
- package/packages/client/dist/runner/headless/run-yoloop.js +2 -2
- package/packages/client/dist/state/project-state-snapshot.js +1 -1
- package/packages/client/dist/state/state-json-repair.js +3 -3
- package/packages/client/dist/yoloop/invoke-hooks.d.ts +2 -3
- package/packages/client/dist/yoloop/invoke-hooks.js +9 -8
- package/packages/client/dist/yoloop/shared-discover-epics.d.ts +3 -3
- package/packages/client/dist/yoloop/shared-discover-epics.js +1 -1
- package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +87 -1
- package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +27 -3
- package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -1
- package/packages/shared/dist/command-registry-contract.js +38 -0
- package/packages/shared/dist/continuity/goal-operation-authority.js +48 -0
- package/packages/shared/dist/executable-graph-catalog/contracts.js +935 -0
- package/packages/shared/dist/generated/command-registry.generated.js +82 -23
- package/packages/shared/dist/generated/invocation-schema.generated.js +12 -4
- package/packages/shared/dist/generated/public-projections.generated.js +149 -0
- package/packages/shared/dist/invocation/executable-policy-recovery.d.ts +83 -0
- package/packages/shared/dist/invocation/executable-policy-recovery.js +272 -0
- package/packages/shared/dist/invocation/index.d.ts +3 -1
- package/packages/shared/dist/invocation/index.js +40 -1
- package/packages/shared/dist/invocation/recovery-route-compiler.d.ts +56 -0
- package/packages/shared/dist/invocation/recovery-route-compiler.js +214 -0
- package/packages/shared/dist/state/index.d.ts +1 -0
- package/packages/shared/dist/state/index.js +1 -0
- package/packages/shared/dist/state/state-migration.d.ts +58 -0
- package/packages/shared/dist/state/state-migration.js +404 -0
- package/packages/shared/dist/yoloop/canonical.js +15 -0
- package/packages/shared/dist/yoloop/operational-budget.js +164 -0
- package/packages/shared/dist/yoloop/recovery-types.js +39 -0
- package/targets-stubs/antigravity/gemini.md +1 -1
- package/targets-stubs/antigravity/skill/SKILL.md +1 -1
- package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
- package/targets-stubs/claude-code/neocortex-root.md +2 -2
- package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
- package/targets-stubs/claude-code/neocortex.md +2 -2
- package/targets-stubs/codex/AGENTS.md +11 -2
- package/targets-stubs/codex/README.md +7 -4
- package/targets-stubs/codex/neocortex.toml +53 -6
- package/targets-stubs/cursor/agent.md +2 -2
- package/targets-stubs/gemini-cli/agent.md +2 -2
- package/targets-stubs/opencode/neocortex-root.md +1 -1
- package/targets-stubs/vscode/neocortex.agent.md +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
const I=2048;function
|
|
1
|
+
const I=2048,S=1e3;function N(e){const s=new Map,u=new Set,f=Object.entries(e.epics??{}),b=Object.entries(e.stories??{});if(f.length+b.length>1e4)throw new Error("git-reconciliation-state-inventory-limit");const _=t=>{!t.branch||!t.origin||s.set(t.branch,[...s.get(t.branch)??[],t])};for(const[t,r]of f){const i=c(r.execution_branch),o=c(r.origin_branch);o&&u.add(o);const n=d(r.terminal_git_receipt),a=n?.physicalStatus==="pushed"&&n.epicId===t&&n.executionBranch===i&&n.originBranch===o&&p(n.executionHeadSha)&&p(n.mergeSha)&&p(n.pushedSha),h=m(r.branch_lease)||(r.status===void 0?!a:!g(r.status));_({epicId:t,branch:i,origin:o,active:h,proofs:a?[{head:c(n.executionHeadSha),evidence:["terminal_receipt","canonical_convention","managed_metadata"],mergeSha:c(n.mergeSha),pushedSha:c(n.pushedSha)}]:[],prNumbers:l(r.pr_number)})}for(const[t,r]of b){const i=c(r.epic_id)||t.split(".")[0],o=e.epics?.[i],n=d(r.checkpoint),a=c(r.branch_name)||c(n?.branch);if(!o||a===c(o.execution_branch))continue;const h=n?.branch===a&&p(n.headSha);_({epicId:i,branch:a,origin:c(o.origin_branch),active:!g(r.status)||m(r.branch_lease),proofs:h?[{head:c(n.headSha),evidence:["state_reference","canonical_convention","managed_metadata"]}]:[],prNumbers:l(r.pr_number)})}for(const[t,r]of s)s.set(t,r.map(i=>({...i,proofs:i.proofs.map(o=>({...o,evidence:o.evidence.filter(n=>n!=="canonical_convention"||t===`epic/${i.epicId}`||t.startsWith(`epic/${i.epicId}/`)||t.startsWith(`story/${i.epicId}.`)||t.startsWith(`story/${i.epicId}/`))}))})));return{claims:s,origins:u}}function c(e){return typeof e=="string"?e:""}function d(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function p(e){return typeof e=="string"&&/^[a-f0-9]{40,64}$/.test(e)}function g(e){return["done","completed","merged","superseded","cancelled","archived","rolled-back"].includes(c(e))}function m(e){const s=d(e);return!!(s&&Date.parse(c(s.expiresAt))>Date.now())}function l(e){return Number.isSafeInteger(e)&&Number(e)>0?[Number(e)]:[]}export{S as GIT_INVENTORY_PR_LIMIT,I as GIT_INVENTORY_REF_LIMIT,N as collectGitResourceOwnership};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{execFile as pe}from"node:child_process";import{createHash as I}from"node:crypto";import{readFile as te}from"node:fs/promises";import{join as me}from"node:path";import{promisify as ye}from"node:util";import{classifyGitReconciliationCandidate as ae,reconcileTerminalReceipt as we}from"../../../../shared/dist/yoloop/epic-terminal-git.js";import{collectGitResourceOwnership as be,GIT_INVENTORY_REF_LIMIT as L}from"./epic-git-reconciliation-inventory.js";import{executeEpicMergeCandidateQa as ie,verifiedEpicMergeCandidateReceipt as W}from"./epic-merge-candidate-qa.js";import{applyGitLifecycleRuntimeOverlay as Se,ensureRuntimeEpic as T,executeP205TransientAuthority as _e,P205_COMPLETE_COMMAND as Q,projectP205TransientExecutionEvidence as xe,verifyAcceptedGitLifecycleStoryCheckpoint as ne,mutateGitLifecycleRuntime as J,readGitLifecycleRuntime as ve}from"../../git/git-lifecycle-store.js";const Re=ye(pe);function We(r,a={}){const c=me(r,".neocortex","state.json"),t=a.gitRunner??((...e)=>se("git",e,r)),d=a.providerRunner??((...e)=>se("gh",e,r)),g=new Map;return{async prepareLifecycleEvidence(e){try{try{await te(c,"utf8")}catch(y){if(Ee(y,"ENOENT"))return{ok:!0,originBindingCaptured:!1,aggregateQaRecorded:!1};throw y}const n=(await D(r,c)).epics?.[e.epicId];if(!n)return o("epic-state-missing",!1,!1);if(_(n.branch_mode)!=="epic")return{ok:!0,originBindingCaptured:!1,aggregateQaRecorded:!1};const s=_(n.execution_branch),u=_(n.origin_branch);if(!s||!A(s))return o("epic-execution-branch-missing",!1,!1);let h=await t("symbolic-ref","--quiet","--short","HEAD").catch(()=>""),f=await t("rev-parse","HEAD"),p=S(n.origin_binding)?n.origin_binding:null,l=!1;if(p){if(p.executionBranch!==s||p.originBranch!==u||h!==s&&h!==p.originBranch||!await U(t,p.originHeadSha)||!await R(t,p.originHeadSha,f))return o("epic-origin-binding-physical-drift",!1,!1)}else{if(!h||h===s||!A(h))return o("epic-origin-binding-capture-window-missed",!1,!1);if(u&&u!==h)return o("epic-origin-binding-recorded-origin-drift",!1,!1);p={schemaVersion:1,originBranch:h,originHeadSha:f,executionBranch:s,capturedFromCurrentCheckout:!0,capturedAt:e.nowIso},await J(r,y=>{const v=T(y,e.epicId);if(v.origin_binding&&JSON.stringify(v.origin_binding)!==JSON.stringify(p))throw new Error("origin-binding-cas-conflict");v.origin_branch=h,v.origin_binding=p}),l=!0}if(h!==s){const y=await ue(t,`refs/heads/${s}`);try{if(y){if(!await R(t,p.originHeadSha,y))return o("epic-execution-branch-origin-drift",!1,!1);await t("switch",s)}else await t("switch","-c",s,p.originHeadSha)}catch{const v=await t("status","--porcelain","--untracked-files=normal").catch(()=>"");return o(v?"epic-execution-branch-switch-blocked-by-user-changes":"epic-execution-branch-switch-failed",!0,!1)}if(h=await t("symbolic-ref","--quiet","--short","HEAD"),f=await t("rev-parse","HEAD"),h!==s)return o("epic-execution-branch-switch-unverified",!0,!1)}const m=await D(r,c,!0),w=m.epics?.[e.epicId];if(!w)return o("epic-state-missing",!1,!1);const x=j(w),b=await Promise.all(x.map(y=>ne(r,m.stories?.[y]?.checkpoint,y,e.epicId,s).then(v=>v&&le(m.stories?.[y]?.checkpoint))));if(!(x.length>0&&b.every(Boolean)))return{ok:!0,originBindingCaptured:l,aggregateQaRecorded:!1};if(h!==s)return o("epic-aggregate-qa-execution-checkout-required",!0,!1);const $=_(w.graph_revision);if(!/^[a-f0-9]{64}$/i.test($))return o("epic-aggregate-qa-graph-required",!1,!1);if(await fe(t))return o("epic-aggregate-qa-checkout-dirty",!0,!1);const q=await _e(r,{headSha:f,graphRevision:$,nowIso:e.nowIso}),B=xe(q);if(!B)return o("epic-aggregate-qa-authority-invalid",!1,!1);if(await a.aggregateQaRunner?.({projectRoot:r,gateIds:B.gateIds}),await t("rev-parse","HEAD")!==f||await fe(t))return o("epic-aggregate-qa-head-raced",!0,!1);const M=`local-yolo-tdd:${I("sha256").update(["epic-aggregate-p205-execution-v2",Q,f,$,B.manifestDigest,B.gateIds.join(","),B.resultDigest].join("\0")).digest("hex")}`,G={schemaVersion:1,evidenceVersion:"p205-execution-v2",producer:"local-yolo-tdd",contract:"P205-CI-02",command:Q,verdict:"passed",executionHeadSha:f,graphRevision:$,manifestDigest:B.manifestDigest,resultDigest:B.resultDigest,checkedAt:B.executedAt,receiptRef:M,gateIds:B.gateIds};return await J(r,y=>{const v=T(y,e.epicId);v.aggregate_qa_receipt=G}),{ok:!0,originBindingCaptured:l,aggregateQaRecorded:!0,p205Authority:q}}catch{return o("epic-lifecycle-evidence-production-failed",!0,!1)}},async inspect(e){try{const i=await D(r,c,!0),n=i.epics?.[e.epicId];if(!n)return o("epic-state-missing",!1,!1);if(_(n.execution_branch)!==e.executionBranch||_(n.origin_branch)!==e.originBranch)return o("epic-branch-boundary-drift",!1,!1);const s=await t("rev-parse",`refs/heads/${e.executionBranch}`),u=await N(t,e.originBranch);await P(t,e.originBranch,u);const h=await Y(r,i,n,e.epicId,e.executionBranch);let f=S(n.terminal_git_receipt)?n.terminal_git_receipt:null;f?.physicalStatus==="pushed"&&(f.pushedSha&&await R(t,f.executionHeadSha,f.pushedSha)&&await R(t,f.pushedSha,u)||(f=null)),f||(f=await Ne({directive:e,executionHeadSha:s,originHeadSha:u,git:t}));const p=new Set((Array.isArray(n.git_reconciliation_receipts)?n.git_reconciliation_receipts:[]).filter(S).filter(z).map(H=>_(H.resourceId)).filter(Boolean)),l=await t("symbolic-ref","--quiet","--short","HEAD").catch(()=>""),m=e.reconcile.enabled?await oe({state:i,epic:n,directive:e,currentBranch:l,originHeadSha:u,receiptIds:p,git:t,gh:d}):[],w=S(n.origin_binding)?n.origin_binding:null,x=w&&w.originBranch===e.originBranch&&w.executionBranch===e.executionBranch&&await U(t,w.originHeadSha)&&await R(t,w.originHeadSha,s)?w:null;return{ok:!0,snapshot:{executionHeadSha:s,originHeadSha:u,..._(n.graph_revision)?{graphRevision:_(n.graph_revision)}:{},writerLeaseActive:ee(n.branch_lease),acceptedCheckpointIds:h,existingReceipt:f,aggregateQaReceipt:S(n.aggregate_qa_receipt)?n.aggregate_qa_receipt:null,originBinding:x,reconciliationCandidates:m}}}catch(i){return o(ce(i)??"epic-terminal-inspection-failed",!0,!1)}},async prepareMergeObject(e){let i;try{const n=await t("merge-tree","--write-tree",e.originHeadSha,e.executionHeadSha);i=await t("commit-tree",n,"-p",e.originHeadSha,"-p",e.executionHeadSha,"-m",e.message)}catch{return o("epic-terminal-merge-conflict",!1,!1)}try{const n=await ie(r,{mergeSha:i,originHeadSha:e.originHeadSha,executionHeadSha:e.executionHeadSha,graphRevision:e.graphRevision},e.nowIso);return g.set(i,n.candidateAuthority),{ok:!0,mergeSha:i,...n}}catch{return o("epic-merge-candidate-qa-failed",!0,!1)}},async inspectReconciliation(e){try{const i=await D(r,c,!0),n=i.epics?.[e.epicId];if(!n)return o("epic-state-missing",!1,!1);if(_(n.execution_branch)!==e.executionBranch||_(n.origin_branch)!==e.originBranch)return o("epic-branch-boundary-drift",!1,!1);const s=await N(t,e.originBranch);await P(t,e.originBranch,s);const u=new Set((Array.isArray(n.git_reconciliation_receipts)?n.git_reconciliation_receipts:[]).filter(S).filter(z).map(p=>_(p.resourceId)).filter(Boolean)),h=await t("symbolic-ref","--quiet","--short","HEAD").catch(()=>"");return{ok:!0,candidates:await oe({state:i,epic:n,directive:e,currentBranch:h,originHeadSha:s,receiptIds:u,git:t,gh:d})}}catch(i){return o(ce(i)??"git-reconciliation-inspection-failed",!0,!1)}},async pushMergeObject(e){try{if(!W(e.candidateAuthority,{mergeSha:e.mergeSha,originHeadSha:e.expectedOriginSha,executionHeadSha:e.executionHeadSha,graphRevision:e.graphRevision}))return o("epic-merge-candidate-authority-required",!1,!1);const n=await D(r,c,!0),s=n.epics?.[e.epicId];if(!s||s.execution_branch!==e.executionBranch||s.origin_branch!==e.originBranch||s.graph_revision!==e.graphRevision||ee(s.branch_lease)||await t("rev-parse",`refs/heads/${e.executionBranch}`)!==e.executionHeadSha)return o("epic-merge-candidate-authority-raced",!0,!1);const u=await Y(r,n,s,e.epicId,e.executionBranch);if(!X(u,e.storyCheckpointIds)||!X(j(s),e.storyCheckpointIds))return o("epic-checkpoint-set-revalidation-drift",!0,!1);const h=S(s.aggregate_qa_receipt)?s.aggregate_qa_receipt:null;if(!de(h,e.executionHeadSha,e.graphRevision,e.nowIso)||h.receiptRef!==e.aggregateQaReceipt.receiptRef)return o("epic-terminal-aggregate-qa-revalidation-drift",!0,!1);if(await N(t,e.originBranch)!==e.expectedOriginSha)return o("epic-origin-head-raced",!0,!1);await t("push","--porcelain","origin",`${e.mergeSha}:refs/heads/${e.originBranch}`);const p=await N(t,e.originBranch);return p!==e.mergeSha?o("epic-terminal-push-unverified",!0,!1):{ok:!0,pushedSha:p}}catch(i){return re(i)?o("epic-terminal-remote-policy-denied",!0,!0):o("epic-terminal-push-failed",!0,!1)}},async ensureSingleEpicPullRequest(e){try{const i=W(e.candidateAuthority,{mergeSha:e.expectedPullRequestHeadSha,originHeadSha:e.candidateQa.originHeadSha,executionHeadSha:e.expectedStoryHeadSha,graphRevision:e.candidateQa.graphRevision});if(!i||i!==e.candidateQa||!await R(t,e.candidateQa.originHeadSha,e.expectedPullRequestHeadSha)||!await R(t,e.expectedStoryHeadSha,e.expectedPullRequestHeadSha))return o("epic-merge-candidate-authority-required",!1,!1);const n=await O(t,d);if(!n)return o("git-resource-provider-repository-unverified",!0,!0);const s=`https://github.com/${n.nameWithOwner}`,u=await C(t,e.executionBranch);if(u&&u!==e.expectedPullRequestHeadSha){if(await P(t,e.executionBranch,u),!await R(t,u,e.expectedPullRequestHeadSha))return o("epic-terminal-execution-remote-head-drift",!0,!0);await t("push","--porcelain","origin",`${e.expectedPullRequestHeadSha}:refs/heads/${e.executionBranch}`)}if(u||await t("push","--porcelain","origin",`${e.expectedPullRequestHeadSha}:refs/heads/${e.executionBranch}`),await N(t,e.executionBranch)!==e.expectedPullRequestHeadSha)return o("epic-terminal-execution-publish-unverified",!0,!0);const h=await d("pr","list","--repo",s,"--state","all","--head",e.executionBranch,"--base",e.originBranch,"--json","number,state,headRefName,headRefOid,baseRefName,mergeCommit","--limit","100"),f=JSON.parse(h),p=f.filter(b=>b.headRefName===e.executionBranch&&b.baseRefName===e.originBranch&&b.headRefOid===e.expectedPullRequestHeadSha&&(b.state==="OPEN"||b.state==="MERGED"));if(p.length>1)return o("epic-terminal-duplicate-prs",!1,!0);if(typeof p[0]?.number=="number")return{ok:!0,prNumber:p[0].number};if(f.some(b=>b.state==="OPEN"))return o("epic-terminal-stale-pr",!1,!0);const m=(await d("pr","create","--repo",s,"--head",e.executionBranch,"--base",e.originBranch,"--title",`[${e.epicId}] Terminal epic integration`,"--body",`Autonomous terminal integration receipt: ${e.idempotencyKey}`)).match(/\/(\d+)(?:\s*)$/);if(!m)return o("epic-terminal-pr-number-unverified",!0,!0);const w=Number(m[1]),x=await K(d,n.nameWithOwner,w);return!x||x.state!=="OPEN"||x.headRefName!==e.executionBranch||x.baseRefName!==e.originBranch||x.headRefOid!==e.expectedPullRequestHeadSha?o("epic-terminal-pr-create-unverified",!0,!0):{ok:!0,prNumber:w}}catch(i){return o("epic-terminal-pr-create-denied",!0,re(i))}},async mergeEpicPullRequest(e){try{const i=await O(t,d);if(!i)return o("git-resource-provider-repository-unverified",!0,!0);const n=e.candidateQa&&W(e.candidateAuthority,{mergeSha:e.expectedPullRequestHeadSha,graphRevision:e.candidateQa.graphRevision,originHeadSha:e.expectedOriginHeadSha,executionHeadSha:e.expectedStoryHeadSha});if(!n||n!==e.candidateQa)return o("epic-merge-candidate-authority-required",!1,!1);const s=await K(d,i.nameWithOwner,e.prNumber),u=await C(t,e.executionBranch),h=await N(t,e.originBranch);if(!s||s.headRefName!==e.executionBranch||s.baseRefName!==e.originBranch||s.headRefOid!==e.expectedPullRequestHeadSha||u&&u!==e.expectedPullRequestHeadSha||!await R(t,e.expectedOriginHeadSha,e.expectedPullRequestHeadSha)||!await R(t,e.expectedStoryHeadSha,e.expectedPullRequestHeadSha))return o("epic-terminal-pr-revalidation-drift",!0,!0);if(s.state==="OPEN"&&h!==e.expectedOriginHeadSha)return o("epic-terminal-pr-origin-raced",!0,!0);let f;if(s.state==="OPEN"){const b=await $e(d,i.nameWithOwner,e.originBranch,e.expectedPullRequestHeadSha,e.expectedOriginHeadSha,e.nowIso);if(!b.ok)return o(b.reasonCode,!0,!0);if(f=b.receipt,await N(t,e.originBranch)!==e.expectedOriginHeadSha)return o("epic-terminal-pr-origin-raced",!0,!0);await d("pr","merge",String(e.prNumber),"--repo",`https://github.com/${i.nameWithOwner}`,"--merge","--match-head-commit",e.expectedPullRequestHeadSha)}else{if(s.state!=="MERGED")return o("epic-terminal-pr-not-open-or-merged",!1,!0);f={schemaVersion:1,provider:"github",mode:"recovered_exact_tree",source:"physical_recovery",prHeadSha:e.expectedPullRequestHeadSha,originHeadSha:e.expectedOriginHeadSha,checkedAt:e.nowIso,publicSafe:!0}}const p=await K(d,i.nameWithOwner,e.prNumber),l=p?.mergeCommit?.oid;if(p?.state!=="MERGED"||!l)return o("epic-terminal-pr-merge-unverified",!0,!0);const m=await N(t,e.originBranch);if(await P(t,e.originBranch,m),!await R(t,e.expectedStoryHeadSha,m)||!await R(t,e.expectedPullRequestHeadSha,m)||!await R(t,l,m))return o("epic-terminal-pr-merge-ancestry-unproven",!0,!0);const[w,x]=await Promise.all([t("rev-parse",`${e.expectedPullRequestHeadSha}^{tree}`),t("rev-parse",`${l}^{tree}`)]);return w!==e.candidateQa.treeSha||x!==w?o("epic-terminal-pr-merged-tree-mismatch",!1,!0):{ok:!0,mergeSha:e.expectedPullRequestHeadSha,pushedSha:l,providerGuard:f}}catch(i){return o("epic-terminal-pr-merge-denied",!0,re(i))}},async verifyTerminalReceipt(e,i,n){try{if(i.physicalStatus!=="pushed"||!i.pushedSha||!i.mergeSha)return o("epic-terminal-physical-revalidation-required",!0,!1);const s=await D(r,c,!0),u=s.epics?.[e.epicId];if(!u||_(u.execution_branch)!==e.executionBranch||_(u.origin_branch)!==e.originBranch||_(u.graph_revision)!==e.graphRevision)return o("epic-terminal-state-revalidation-drift",!0,!1);const h=await t("rev-parse",`refs/heads/${e.executionBranch}`);if(h!==e.expectedExecutionHeadSha||i.executionHeadSha!==h)return o("epic-terminal-execution-revalidation-drift",!0,!1);const f=S(u.origin_binding)?u.origin_binding:null;if(!f||f.originBranch!==e.originBranch||f.executionBranch!==e.executionBranch||!await U(t,f.originHeadSha)||!await R(t,f.originHeadSha,h))return o("epic-origin-binding-revalidation-drift",!0,!1);const p=await Y(r,s,u,e.epicId,e.executionBranch);if(ee(u.branch_lease)||!X(p,e.storyCheckpointIds))return o("epic-checkpoint-set-revalidation-drift",!0,!1);const l=S(u.aggregate_qa_receipt)?u.aggregate_qa_receipt:null;if(!de(l,h,e.graphRevision,n)||l?.receiptRef!==e.localGates.aggregateQaReceipt.receiptRef)return o("epic-terminal-aggregate-qa-revalidation-drift",!0,!1);const m=await N(t,e.originBranch);if(await P(t,e.originBranch,m),!await R(t,h,m)||!await R(t,i.mergeSha,m)||!await R(t,i.pushedSha,m))return o("epic-terminal-physical-ancestry-unproven",!0,!1);const w={originHeadSha:i.baseSha,executionHeadSha:h,mergeSha:i.mergeSha,graphRevision:e.graphRevision};let x=g.get(i.mergeSha),b=W(x,w);if(!b){const $=await ie(r,w,n);x=$.candidateAuthority,b=$.candidateQa,g.set(i.mergeSha,x)}if(i.candidateQa&&(i.candidateQa.originHeadSha!==b.originHeadSha||i.candidateQa.executionHeadSha!==b.executionHeadSha||i.candidateQa.graphRevision!==b.graphRevision||i.candidateQa.treeSha!==b.treeSha))return o("epic-merge-candidate-receipt-drift",!0,!1);let H=i.providerGuard;if(i.strategy==="single_pr"){if(!i.prNumber)return o("epic-terminal-pr-merge-unverified",!0,!1);if(await t("rev-parse",`${i.pushedSha}^{tree}`)!==b.treeSha)return o("epic-terminal-pr-merged-tree-mismatch",!1,!1);if(H&&!qe(H,i))return o("epic-terminal-pr-base-guard-unverifiable",!1,!1);H??={schemaVersion:1,provider:"github",mode:"recovered_exact_tree",source:"physical_recovery",prHeadSha:i.mergeSha,originHeadSha:i.baseSha,checkedAt:n,publicSafe:!0}}else if(H)return o("epic-terminal-pr-base-guard-unverifiable",!1,!1);return{ok:!0,candidateQa:b,candidateAuthority:x,...H?{providerGuard:H}:{}}}catch{return o("epic-terminal-physical-revalidation-failed",!0,!1)}},async applyReconciliation(e,i,n){if(i.action==="preserve")return o("git-reconciliation-preserve-not-actionable",!1,!1);if(n)return{ok:!0,outcome:"dry_run"};if(i.action==="no_op")return{ok:!0,outcome:"already_absent"};if(i.action==="delete_remote_branch")return He(e,i,t,d);try{const s=await F({candidate:e,decision:i,git:t,gh:d});if(!s.ok)return o(s.reasonCode,!0,!1);if(s.alreadyAbsent)return{ok:!0,outcome:"already_absent"};if(i.action==="delete_local_branch")await t("update-ref","-d",`refs/heads/${e.branchName}`,e.headSha);else if(i.action==="close_pull_request"){if(!e.prNumber)return o("git-reconciliation-pr-number-missing",!1,!1);const u=await O(t,d);if(!u)return o("git-resource-provider-repository-unverified",!0,!0);const h=`https://github.com/${u.nameWithOwner}`,f=`neocortex-reconciliation:${I("sha256").update(e.resourceId).digest("hex")}`,p=JSON.parse(await d("pr","view",String(e.prNumber),"--repo",h,"--json","comments"));if(!S(p)||!Array.isArray(p.comments)||p.comments.length>1e3||p.comments.some(w=>!S(w)||typeof w.body!="string"))return o("git-reconciliation-pr-comments-unverified",!0,!0);p.comments.some(w=>String(w.body).includes(f))||await d("pr","comment",String(e.prNumber),"--repo",h,"--body",`Neocortex reconciliation verified managed ownership and integrated content; requesting closure. [${f}]`);const l=await F({candidate:e,decision:i,git:t,gh:d});if(!l.ok)return o(l.reasonCode,!0,!1);if(l.alreadyAbsent)return{ok:!0,outcome:"already_absent"};await d("pr","close",String(e.prNumber),"--repo",h);const m=await F({candidate:e,decision:i,git:t,gh:d});if(!m.ok)return o(m.reasonCode,!0,!1);if(!m.alreadyAbsent)return o("git-reconciliation-pr-close-unverified",!0,!0)}return{ok:!0,outcome:"applied"}}catch{return o("git-reconciliation-effect-failed",!0,!1)}},async persist(e){try{let i;return await J(r,n=>{const s=T(n,e.terminalReceipt.epicId),u=Array.isArray(s.git_reconciliation_receipts)?s.git_reconciliation_receipts.filter(S):[],h=new Map(u.map(l=>[l.idempotencyKey,l]));for(const l of e.reconciliationReceipts)z(h.get(l.idempotencyKey))||h.set(l.idempotencyKey,l);const f=S(s.terminal_git_receipt)?s.terminal_git_receipt:null,p=we(f,e.terminalReceipt);if(p.kind==="blocked"){i=p.reasonCode;return}s.terminal_git_receipt=p.receipt,s.git_reconciliation_receipts=[...h.values()],s.physicalMergeStatus=e.terminalReceipt.physicalStatus==="pushed"?"merged":e.terminalReceipt.physicalStatus,s.pr_number=e.terminalReceipt.prNumber??s.pr_number??null,s.git_reconciliation_debt=ge(s.git_reconciliation_debt,e.preservedDecisions)}),i?o(i,!1,!1):{ok:!0}}catch{return o("epic-terminal-state-persist-failed",!0,!1)}},async persistReconciliation(e){try{return await J(r,i=>{const n=T(i,e.epicId),s=Array.isArray(n.git_reconciliation_receipts)?n.git_reconciliation_receipts.filter(S):[],u=new Map(s.map(h=>[h.idempotencyKey,h]));for(const h of e.reconciliationReceipts)z(u.get(h.idempotencyKey))||u.set(h.idempotencyKey,h);n.git_reconciliation_receipts=[...u.values()],n.git_reconciliation_debt=ge(n.git_reconciliation_debt,e.preservedDecisions)}),{ok:!0}}catch{return o("git-reconciliation-state-persist-failed",!0,!1)}}}}async function O(r,a){try{const c=await r("remote","get-url","origin"),t=c.match(/^https:\/\/github\.com\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?\/?$/)?.[1]??c.match(/^git@github\.com:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?$/)?.[1];if(!t)return null;const d=JSON.parse(await a("repo","view",`https://github.com/${t}`,"--json","id,nameWithOwner,url"));return d.nameWithOwner!==t||d.url!==`https://github.com/${t}`||typeof d.id!="string"||!/^[A-Za-z0-9_=-]{1,256}$/.test(d.id)?null:{id:d.id,nameWithOwner:t}}catch{return null}}async function He(r,a,c,t){try{if(r.kind!=="remote_branch"||a.resourceId!==r.resourceId||!r.baseBranch||r.baseBranch===r.branchName||!A(r.branchName)||!A(r.baseBranch)||!/^[a-f0-9]{40}$/.test(r.headSha)||!/^[a-f0-9]{40}$/.test(r.integrationHeadSha))return o("git-reconciliation-candidate-no-longer-safe",!1,!1);const d=await O(c,t);if(!d)return o("git-resource-remote-delete-cas-unavailable",!1,!1);if(!await C(c,r.branchName))return{ok:!0,outcome:"already_absent"};const e=await F({candidate:r,decision:a,git:c,gh:t});if(!e.ok)return o(e.reasonCode,!0,!1);if((await O(c,t))?.id!==d.id)return o("git-resource-provider-repository-raced",!0,!1);const n=I("sha256").update(["managed-remote-delete-v1",d.id,r.branchName,r.headSha,r.baseBranch,r.integrationHeadSha].join("\0")).digest("hex"),s=(f,p,l)=>`{name:${JSON.stringify(`refs/heads/${f}`)},beforeOid:${JSON.stringify(p)},afterOid:${JSON.stringify(l)},force:false}`,u=`mutation{updateRefs(input:{repositoryId:${JSON.stringify(d.id)},clientMutationId:${JSON.stringify(n)},refUpdates:[`+s(r.branchName,r.headSha,"0".repeat(40))+","+s(r.baseBranch,r.integrationHeadSha,r.integrationHeadSha)+"]}){clientMutationId}}",h=JSON.parse(await t("api","graphql","--hostname","github.com","-f",`query=${u}`));return h.errors||h.data?.updateRefs?.clientMutationId!==n?o("git-resource-remote-delete-cas-unverified",!0,!0):await C(c,r.branchName)?o("git-resource-remote-delete-recreated-or-unverified",!0,!1):{ok:!0,outcome:"applied"}}catch{return o("git-resource-remote-delete-cas-rejected",!0,!0)}}async function F(r){const{candidate:a,decision:c,git:t,gh:d}=r;if(!c.managed||!a.providerVerified||a.current||a.origin||a.protected||a.lifecycle==="active"||a.hasExclusiveCommits||a.worktreeActive)return{ok:!1,reasonCode:"git-reconciliation-candidate-no-longer-safe"};const g=await t("symbolic-ref","--quiet","--short","HEAD").catch(()=>""),e=await he(t);if(g===a.branchName||e.has(a.branchName))return{ok:!1,reasonCode:"git-resource-worktree-active"};if(a.kind==="local_branch"){const u=await ue(t,`refs/heads/${a.branchName}`);return u?u!==a.headSha?{ok:!1,reasonCode:"git-resource-expected-oid-raced"}:!a.baseBranch||await N(t,a.baseBranch)!==a.integrationHeadSha||!await R(t,u,a.integrationHeadSha)?{ok:!1,reasonCode:"git-resource-integration-unproven"}:{ok:!0}:{ok:!0,alreadyAbsent:!0}}if(a.kind==="remote_branch"){const u=await C(t,a.branchName);if(!u)return{ok:!0};if(u!==a.headSha)return{ok:!1,reasonCode:"git-resource-expected-oid-raced"};const h=await O(t,d);return h?await Z(d,h.nameWithOwner,a.branchName)!=="unprotected"?{ok:!1,reasonCode:"git-resource-protected"}:!a.baseBranch||await N(t,a.baseBranch)!==a.integrationHeadSha?{ok:!1,reasonCode:"git-resource-integration-unproven"}:(await t("fetch","--quiet","--no-tags","origin",`refs/heads/${a.branchName}`),await t("rev-parse","FETCH_HEAD")!==a.headSha||!await R(t,a.headSha,a.integrationHeadSha)?{ok:!1,reasonCode:"git-resource-integration-unproven"}:{ok:!0}):{ok:!1,reasonCode:"git-resource-provider-repository-unverified"}}if(!a.prNumber||!a.baseBranch)return{ok:!1,reasonCode:"git-reconciliation-pr-proof-missing"};const i=await O(t,d);if(!i)return{ok:!1,reasonCode:"git-resource-provider-repository-unverified"};const n=await K(d,i.nameWithOwner,a.prNumber);if(!n||n.headRefName!==a.branchName||n.baseRefName!==a.baseBranch||n.headRefOid!==a.headSha)return{ok:!1,reasonCode:"git-resource-expected-oid-raced"};if(n.state==="CLOSED"||n.state==="MERGED")return{ok:!0,alreadyAbsent:!0};if(await Z(d,i.nameWithOwner,a.branchName)!=="unprotected")return{ok:!1,reasonCode:"git-resource-protected"};const s=await C(t,a.branchName);return!n||n.state!=="OPEN"||n.headRefName!==a.branchName||n.baseRefName!==a.baseBranch||n.headRefOid!==a.headSha||s!==a.headSha?{ok:!1,reasonCode:"git-resource-expected-oid-raced"}:(await t("fetch","--quiet","--no-tags","origin",`refs/heads/${a.branchName}`),await t("rev-parse","FETCH_HEAD")!==a.headSha||await N(t,a.baseBranch)!==a.integrationHeadSha||!await R(t,a.headSha,a.integrationHeadSha)?{ok:!1,reasonCode:"git-resource-integration-unproven"}:{ok:!0})}async function oe(r){const a=[],c=await he(r.git),t=be(r.state),d=await O(r.git,r.gh),g=l=>{const m=l.split(`
|
|
2
|
-
`).filter(Boolean).map(
|
|
3
|
-
`).filter(s=>/^[a-f0-9]{40,64}$/i.test(s));if(a.length!==1)return null;const c=a[0],t=(await
|
|
4
|
-
`),
|
|
5
|
-
`).map(s=>s.trim()));for(const s of[`Neocortex-Epic: ${
|
|
6
|
-
`).filter(Boolean).map(
|
|
7
|
-
`))t.startsWith("branch refs/heads/")&&a.add(t.slice(18));return a}function o(
|
|
8
|
-
`).filter(Boolean).some(c=>!c.startsWith("?? ")||!a.has(c.slice(3)))}function
|
|
1
|
+
import{execFile as ye}from"node:child_process";import{createHash as O}from"node:crypto";import{readFile as ae}from"node:fs/promises";import{join as we}from"node:path";import{promisify as be}from"node:util";import{classifyGitReconciliationCandidate as ie,reconcileTerminalReceipt as Se}from"../../../../shared/dist/yoloop/epic-terminal-git.js";import{collectGitResourceOwnership as _e,GIT_INVENTORY_PR_LIMIT as ne,GIT_INVENTORY_REF_LIMIT as Z}from"./epic-git-reconciliation-inventory.js";import{executeEpicMergeCandidateQa as oe,verifiedEpicMergeCandidateReceipt as W}from"./epic-merge-candidate-qa.js";import{applyGitLifecycleRuntimeOverlay as xe,ensureRuntimeEpic as z,executeP205TransientAuthority as ve,P205_COMPLETE_COMMAND as Q,projectP205TransientExecutionEvidence as Re,verifyAcceptedGitLifecycleStoryCheckpoint as ce,mutateGitLifecycleRuntime as J,readGitLifecycleRuntime as He}from"../../git/git-lifecycle-store.js";const ke=be(ye);function ze(e,a={}){const c=we(e,".neocortex","state.json"),t=a.gitRunner??((...r)=>ue("git",r,e)),u=a.providerRunner??((...r)=>ue("gh",r,e)),m=new Map;return{async prepareLifecycleEvidence(r){try{try{await ae(c,"utf8")}catch(k){if(Oe(k,"ENOENT"))return{ok:!0,originBindingCaptured:!1,aggregateQaRecorded:!1};throw k}const n=(await D(e,c)).epics?.[r.epicId];if(!n)return o("epic-state-missing",!1,!1);if(S(n.branch_mode)!=="epic")return{ok:!0,originBindingCaptured:!1,aggregateQaRecorded:!1};const s=S(n.execution_branch),d=S(n.origin_branch);if(!s||!E(s))return o("epic-execution-branch-missing",!1,!1);let l=await t("symbolic-ref","--quiet","--short","HEAD").catch(()=>""),f=await t("rev-parse","HEAD"),h=_(n.origin_binding)?n.origin_binding:null,b=!1;if(h){if(h.executionBranch!==s||h.originBranch!==d||l!==s&&l!==h.originBranch||!await j(t,h.originHeadSha)||!await v(t,h.originHeadSha,f))return o("epic-origin-binding-physical-drift",!1,!1)}else{if(!l||l===s||!E(l))return o("epic-origin-binding-capture-window-missed",!1,!1);if(d&&d!==l)return o("epic-origin-binding-recorded-origin-drift",!1,!1);h={schemaVersion:1,originBranch:l,originHeadSha:f,executionBranch:s,capturedFromCurrentCheckout:!0,capturedAt:r.nowIso},await J(e,k=>{const y=z(k,r.epicId);if(y.origin_binding&&JSON.stringify(y.origin_binding)!==JSON.stringify(h))throw new Error("origin-binding-cas-conflict");y.origin_branch=l,y.origin_binding=h}),b=!0}if(l!==s){const k=await le(t,`refs/heads/${s}`);try{if(k){if(!await v(t,h.originHeadSha,k))return o("epic-execution-branch-origin-drift",!1,!1);await t("switch",s)}else await t("switch","-c",s,h.originHeadSha)}catch{const y=await t("status","--porcelain","--untracked-files=normal").catch(()=>"");return o(y?"epic-execution-branch-switch-blocked-by-user-changes":"epic-execution-branch-switch-failed",!0,!1)}if(l=await t("symbolic-ref","--quiet","--short","HEAD"),f=await t("rev-parse","HEAD"),l!==s)return o("epic-execution-branch-switch-unverified",!0,!1)}const g=await D(e,c,!0),p=g.epics?.[r.epicId];if(!p)return o("epic-state-missing",!1,!1);const x=Y(p),w=await Promise.all(x.map(k=>ce(e,g.stories?.[k]?.checkpoint,k,r.epicId,s).then(y=>y&&ge(g.stories?.[k]?.checkpoint))));if(!(x.length>0&&w.every(Boolean)))return{ok:!0,originBindingCaptured:b,aggregateQaRecorded:!1};if(l!==s)return o("epic-aggregate-qa-execution-checkout-required",!0,!1);const H=S(p.graph_revision);if(!/^[a-f0-9]{64}$/i.test(H))return o("epic-aggregate-qa-graph-required",!1,!1);if(await pe(t))return o("epic-aggregate-qa-checkout-dirty",!0,!1);const G=await ve(e,{headSha:f,graphRevision:H,nowIso:r.nowIso}),B=Re(G);if(!B)return o("epic-aggregate-qa-authority-invalid",!1,!1);if(await a.aggregateQaRunner?.({projectRoot:e,gateIds:B.gateIds}),await t("rev-parse","HEAD")!==f||await pe(t))return o("epic-aggregate-qa-head-raced",!0,!1);const M=`local-yolo-tdd:${O("sha256").update(["epic-aggregate-p205-execution-v2",Q,f,H,B.manifestDigest,B.gateIds.join(","),B.resultDigest].join("\0")).digest("hex")}`,T={schemaVersion:1,evidenceVersion:"p205-execution-v2",producer:"local-yolo-tdd",contract:"P205-CI-02",command:Q,verdict:"passed",executionHeadSha:f,graphRevision:H,manifestDigest:B.manifestDigest,resultDigest:B.resultDigest,checkedAt:B.executedAt,receiptRef:M,gateIds:B.gateIds};return await J(e,k=>{const y=z(k,r.epicId);y.aggregate_qa_receipt=T}),{ok:!0,originBindingCaptured:b,aggregateQaRecorded:!0,p205Authority:G}}catch{return o("epic-lifecycle-evidence-production-failed",!0,!1)}},async inspect(r){try{const i=await D(e,c,!0),n=i.epics?.[r.epicId];if(!n)return o("epic-state-missing",!1,!1);if(S(n.execution_branch)!==r.executionBranch||S(n.origin_branch)!==r.originBranch)return o("epic-branch-boundary-drift",!1,!1);const s=await t("rev-parse",`refs/heads/${r.executionBranch}`),d=await A(t,r.originBranch);await P(t,r.originBranch,d);const l=await X(e,i,n,r.epicId,r.executionBranch);let f=_(n.terminal_git_receipt)?n.terminal_git_receipt:null;f?.physicalStatus==="pushed"&&(f.pushedSha&&await v(t,f.executionHeadSha,f.pushedSha)&&await v(t,f.pushedSha,d)||(f=null)),f||(f=await Ae({directive:r,executionHeadSha:s,originHeadSha:d,git:t}));const h=new Set((Array.isArray(n.git_reconciliation_receipts)?n.git_reconciliation_receipts:[]).filter(_).filter(K).map(R=>S(R.resourceId)).filter(Boolean)),b=await t("symbolic-ref","--quiet","--short","HEAD").catch(()=>""),g=r.reconcile.enabled?await se({state:i,epic:n,directive:r,currentBranch:b,originHeadSha:d,receiptIds:h,git:t,gh:u}):[],p=_(n.origin_binding)?n.origin_binding:null,x=p&&p.originBranch===r.originBranch&&p.executionBranch===r.executionBranch&&await j(t,p.originHeadSha)&&await v(t,p.originHeadSha,s)?p:null;return{ok:!0,snapshot:{executionHeadSha:s,originHeadSha:d,...S(n.graph_revision)?{graphRevision:S(n.graph_revision)}:{},writerLeaseActive:re(n.branch_lease),acceptedCheckpointIds:l,existingReceipt:f,aggregateQaReceipt:_(n.aggregate_qa_receipt)?n.aggregate_qa_receipt:null,originBinding:x,reconciliationCandidates:g}}}catch(i){return o(de(i)??"epic-terminal-inspection-failed",!0,!1)}},async prepareMergeObject(r){let i;try{const n=await t("merge-tree","--write-tree",r.originHeadSha,r.executionHeadSha);i=await t("commit-tree",n,"-p",r.originHeadSha,"-p",r.executionHeadSha,"-m",r.message)}catch{return o("epic-terminal-merge-conflict",!1,!1)}try{const n=await oe(e,{mergeSha:i,originHeadSha:r.originHeadSha,executionHeadSha:r.executionHeadSha,graphRevision:r.graphRevision},r.nowIso);return m.set(i,n.candidateAuthority),{ok:!0,mergeSha:i,...n}}catch{return o("epic-merge-candidate-qa-failed",!0,!1)}},async inspectReconciliation(r){try{const i=await D(e,c,!0),n=i.epics?.[r.epicId];if(!n)return o("epic-state-missing",!1,!1);if(S(n.execution_branch)!==r.executionBranch||S(n.origin_branch)!==r.originBranch)return o("epic-branch-boundary-drift",!1,!1);const s=await A(t,r.originBranch);await P(t,r.originBranch,s);const d=new Set((Array.isArray(n.git_reconciliation_receipts)?n.git_reconciliation_receipts:[]).filter(_).filter(K).map(h=>S(h.resourceId)).filter(Boolean)),l=await t("symbolic-ref","--quiet","--short","HEAD").catch(()=>"");return{ok:!0,candidates:await se({state:i,epic:n,directive:r,currentBranch:l,originHeadSha:s,receiptIds:d,git:t,gh:u})}}catch(i){return o(de(i)??"git-reconciliation-inspection-failed",!0,!1)}},async pushMergeObject(r){try{if(!W(r.candidateAuthority,{mergeSha:r.mergeSha,originHeadSha:r.expectedOriginSha,executionHeadSha:r.executionHeadSha,graphRevision:r.graphRevision}))return o("epic-merge-candidate-authority-required",!1,!1);const n=await D(e,c,!0),s=n.epics?.[r.epicId];if(!s||s.execution_branch!==r.executionBranch||s.origin_branch!==r.originBranch||s.graph_revision!==r.graphRevision||re(s.branch_lease)||await t("rev-parse",`refs/heads/${r.executionBranch}`)!==r.executionHeadSha)return o("epic-merge-candidate-authority-raced",!0,!1);const d=await X(e,n,s,r.epicId,r.executionBranch);if(!ee(d,r.storyCheckpointIds)||!ee(Y(s),r.storyCheckpointIds))return o("epic-checkpoint-set-revalidation-drift",!0,!1);const l=_(s.aggregate_qa_receipt)?s.aggregate_qa_receipt:null;if(!he(l,r.executionHeadSha,r.graphRevision,r.nowIso)||l.receiptRef!==r.aggregateQaReceipt.receiptRef)return o("epic-terminal-aggregate-qa-revalidation-drift",!0,!1);if(await A(t,r.originBranch)!==r.expectedOriginSha)return o("epic-origin-head-raced",!0,!1);await t("push","--porcelain","origin",`${r.mergeSha}:refs/heads/${r.originBranch}`);const h=await A(t,r.originBranch);return h!==r.mergeSha?o("epic-terminal-push-unverified",!0,!1):{ok:!0,pushedSha:h}}catch(i){return te(i)?o("epic-terminal-remote-policy-denied",!0,!0):o("epic-terminal-push-failed",!0,!1)}},async ensureSingleEpicPullRequest(r){try{const i=W(r.candidateAuthority,{mergeSha:r.expectedPullRequestHeadSha,originHeadSha:r.candidateQa.originHeadSha,executionHeadSha:r.expectedStoryHeadSha,graphRevision:r.candidateQa.graphRevision});if(!i||i!==r.candidateQa||!await v(t,r.candidateQa.originHeadSha,r.expectedPullRequestHeadSha)||!await v(t,r.expectedStoryHeadSha,r.expectedPullRequestHeadSha))return o("epic-merge-candidate-authority-required",!1,!1);const n=await I(t,u);if(!n)return o("git-resource-provider-repository-unverified",!0,!0);const s=`https://github.com/${n.nameWithOwner}`,d=await C(t,r.executionBranch);if(d&&d!==r.expectedPullRequestHeadSha){if(await P(t,r.executionBranch,d),!await v(t,d,r.expectedPullRequestHeadSha))return o("epic-terminal-execution-remote-head-drift",!0,!0);await t("push","--porcelain","origin",`${r.expectedPullRequestHeadSha}:refs/heads/${r.executionBranch}`)}if(d||await t("push","--porcelain","origin",`${r.expectedPullRequestHeadSha}:refs/heads/${r.executionBranch}`),await A(t,r.executionBranch)!==r.expectedPullRequestHeadSha)return o("epic-terminal-execution-publish-unverified",!0,!0);const l=await u("pr","list","--repo",s,"--state","all","--head",r.executionBranch,"--base",r.originBranch,"--json","number,state,headRefName,headRefOid,baseRefName,mergeCommit","--limit","100"),f=JSON.parse(l),h=f.filter(w=>w.headRefName===r.executionBranch&&w.baseRefName===r.originBranch&&w.headRefOid===r.expectedPullRequestHeadSha&&(w.state==="OPEN"||w.state==="MERGED"));if(h.length>1)return o("epic-terminal-duplicate-prs",!1,!0);if(typeof h[0]?.number=="number")return{ok:!0,prNumber:h[0].number};if(f.some(w=>w.state==="OPEN"))return o("epic-terminal-stale-pr",!1,!0);const g=(await u("pr","create","--repo",s,"--head",r.executionBranch,"--base",r.originBranch,"--title",`[${r.epicId}] Terminal epic integration`,"--body",`Autonomous terminal integration receipt: ${r.idempotencyKey}`)).match(/\/(\d+)(?:\s*)$/);if(!g)return o("epic-terminal-pr-number-unverified",!0,!0);const p=Number(g[1]),x=await L(u,n.nameWithOwner,p);return!x||x.state!=="OPEN"||x.headRefName!==r.executionBranch||x.baseRefName!==r.originBranch||x.headRefOid!==r.expectedPullRequestHeadSha?o("epic-terminal-pr-create-unverified",!0,!0):{ok:!0,prNumber:p}}catch(i){return o("epic-terminal-pr-create-denied",!0,te(i))}},async mergeEpicPullRequest(r){try{const i=await I(t,u);if(!i)return o("git-resource-provider-repository-unverified",!0,!0);const n=r.candidateQa&&W(r.candidateAuthority,{mergeSha:r.expectedPullRequestHeadSha,graphRevision:r.candidateQa.graphRevision,originHeadSha:r.expectedOriginHeadSha,executionHeadSha:r.expectedStoryHeadSha});if(!n||n!==r.candidateQa)return o("epic-merge-candidate-authority-required",!1,!1);const s=await L(u,i.nameWithOwner,r.prNumber),d=await C(t,r.executionBranch),l=await A(t,r.originBranch);if(!s||s.headRefName!==r.executionBranch||s.baseRefName!==r.originBranch||s.headRefOid!==r.expectedPullRequestHeadSha||d&&d!==r.expectedPullRequestHeadSha||!await v(t,r.expectedOriginHeadSha,r.expectedPullRequestHeadSha)||!await v(t,r.expectedStoryHeadSha,r.expectedPullRequestHeadSha))return o("epic-terminal-pr-revalidation-drift",!0,!0);if(s.state==="OPEN"&&l!==r.expectedOriginHeadSha)return o("epic-terminal-pr-origin-raced",!0,!0);let f;if(s.state==="OPEN"){const w=await Ee(u,i.nameWithOwner,r.originBranch,r.expectedPullRequestHeadSha,r.expectedOriginHeadSha,r.nowIso);if(!w.ok)return o(w.reasonCode,!0,!0);if(f=w.receipt,await A(t,r.originBranch)!==r.expectedOriginHeadSha)return o("epic-terminal-pr-origin-raced",!0,!0);await u("pr","merge",String(r.prNumber),"--repo",`https://github.com/${i.nameWithOwner}`,"--merge","--match-head-commit",r.expectedPullRequestHeadSha)}else{if(s.state!=="MERGED")return o("epic-terminal-pr-not-open-or-merged",!1,!0);f={schemaVersion:1,provider:"github",mode:"recovered_exact_tree",source:"physical_recovery",prHeadSha:r.expectedPullRequestHeadSha,originHeadSha:r.expectedOriginHeadSha,checkedAt:r.nowIso,publicSafe:!0}}const h=await L(u,i.nameWithOwner,r.prNumber),b=h?.mergeCommit?.oid;if(h?.state!=="MERGED"||!b)return o("epic-terminal-pr-merge-unverified",!0,!0);const g=await A(t,r.originBranch);if(await P(t,r.originBranch,g),!await v(t,r.expectedStoryHeadSha,g)||!await v(t,r.expectedPullRequestHeadSha,g)||!await v(t,b,g))return o("epic-terminal-pr-merge-ancestry-unproven",!0,!0);const[p,x]=await Promise.all([t("rev-parse",`${r.expectedPullRequestHeadSha}^{tree}`),t("rev-parse",`${b}^{tree}`)]);return p!==r.candidateQa.treeSha||x!==p?o("epic-terminal-pr-merged-tree-mismatch",!1,!0):{ok:!0,mergeSha:r.expectedPullRequestHeadSha,pushedSha:b,providerGuard:f}}catch(i){return o("epic-terminal-pr-merge-denied",!0,te(i))}},async verifyTerminalReceipt(r,i,n){try{if(i.physicalStatus!=="pushed"||!i.pushedSha||!i.mergeSha)return o("epic-terminal-physical-revalidation-required",!0,!1);const s=await D(e,c,!0),d=s.epics?.[r.epicId];if(!d||S(d.execution_branch)!==r.executionBranch||S(d.origin_branch)!==r.originBranch||S(d.graph_revision)!==r.graphRevision)return o("epic-terminal-state-revalidation-drift",!0,!1);const l=await t("rev-parse",`refs/heads/${r.executionBranch}`);if(l!==r.expectedExecutionHeadSha||i.executionHeadSha!==l)return o("epic-terminal-execution-revalidation-drift",!0,!1);const f=_(d.origin_binding)?d.origin_binding:null;if(!f||f.originBranch!==r.originBranch||f.executionBranch!==r.executionBranch||!await j(t,f.originHeadSha)||!await v(t,f.originHeadSha,l))return o("epic-origin-binding-revalidation-drift",!0,!1);const h=await X(e,s,d,r.epicId,r.executionBranch);if(re(d.branch_lease)||!ee(h,r.storyCheckpointIds))return o("epic-checkpoint-set-revalidation-drift",!0,!1);const b=_(d.aggregate_qa_receipt)?d.aggregate_qa_receipt:null;if(!he(b,l,r.graphRevision,n)||b?.receiptRef!==r.localGates.aggregateQaReceipt.receiptRef)return o("epic-terminal-aggregate-qa-revalidation-drift",!0,!1);const g=await A(t,r.originBranch);if(await P(t,r.originBranch,g),!await v(t,l,g)||!await v(t,i.mergeSha,g)||!await v(t,i.pushedSha,g))return o("epic-terminal-physical-ancestry-unproven",!0,!1);const p={originHeadSha:i.baseSha,executionHeadSha:l,mergeSha:i.mergeSha,graphRevision:r.graphRevision};let x=m.get(i.mergeSha),w=W(x,p);if(!w){const H=await oe(e,p,n);x=H.candidateAuthority,w=H.candidateQa,m.set(i.mergeSha,x)}if(i.candidateQa&&(i.candidateQa.originHeadSha!==w.originHeadSha||i.candidateQa.executionHeadSha!==w.executionHeadSha||i.candidateQa.graphRevision!==w.graphRevision||i.candidateQa.treeSha!==w.treeSha))return o("epic-merge-candidate-receipt-drift",!0,!1);let R=i.providerGuard;if(i.strategy==="single_pr"){if(!i.prNumber)return o("epic-terminal-pr-merge-unverified",!0,!1);if(await t("rev-parse",`${i.pushedSha}^{tree}`)!==w.treeSha)return o("epic-terminal-pr-merged-tree-mismatch",!1,!1);if(R&&!Ie(R,i))return o("epic-terminal-pr-base-guard-unverifiable",!1,!1);R??={schemaVersion:1,provider:"github",mode:"recovered_exact_tree",source:"physical_recovery",prHeadSha:i.mergeSha,originHeadSha:i.baseSha,checkedAt:n,publicSafe:!0}}else if(R)return o("epic-terminal-pr-base-guard-unverifiable",!1,!1);return{ok:!0,candidateQa:w,candidateAuthority:x,...R?{providerGuard:R}:{}}}catch{return o("epic-terminal-physical-revalidation-failed",!0,!1)}},async applyReconciliation(r,i,n){if(i.action==="preserve")return o("git-reconciliation-preserve-not-actionable",!1,!1);if(n)return{ok:!0,outcome:"dry_run"};if(i.action==="no_op")return{ok:!0,outcome:"already_absent"};if(i.action==="delete_remote_branch")return Be(r,i,t,u);try{const s=await F({candidate:r,decision:i,git:t,gh:u});if(!s.ok)return o(s.reasonCode,!0,!1);if(s.alreadyAbsent)return{ok:!0,outcome:"already_absent"};if(i.action==="delete_local_branch")await t("update-ref","-d",`refs/heads/${r.branchName}`,r.headSha);else if(i.action==="close_pull_request"){if(!r.prNumber)return o("git-reconciliation-pr-number-missing",!1,!1);const d=await I(t,u);if(!d)return o("git-resource-provider-repository-unverified",!0,!0);const l=`https://github.com/${d.nameWithOwner}`,f=`neocortex-reconciliation:${O("sha256").update(r.resourceId).digest("hex")}`,h=JSON.parse(await u("pr","view",String(r.prNumber),"--repo",l,"--json","comments"));if(!_(h)||!Array.isArray(h.comments)||h.comments.length>1e3||h.comments.some(p=>!_(p)||typeof p.body!="string"))return o("git-reconciliation-pr-comments-unverified",!0,!0);h.comments.some(p=>String(p.body).includes(f))||await u("pr","comment",String(r.prNumber),"--repo",l,"--body",`Neocortex reconciliation verified managed ownership and integrated content; requesting closure. [${f}]`);const b=await F({candidate:r,decision:i,git:t,gh:u});if(!b.ok)return o(b.reasonCode,!0,!1);if(b.alreadyAbsent)return{ok:!0,outcome:"already_absent"};await u("pr","close",String(r.prNumber),"--repo",l);const g=await F({candidate:r,decision:i,git:t,gh:u});if(!g.ok)return o(g.reasonCode,!0,!1);if(!g.alreadyAbsent)return o("git-reconciliation-pr-close-unverified",!0,!0)}return{ok:!0,outcome:"applied"}}catch{return o("git-reconciliation-effect-failed",!0,!1)}},async persist(r){try{let i;return await J(e,n=>{const s=z(n,r.terminalReceipt.epicId),d=Array.isArray(s.git_reconciliation_receipts)?s.git_reconciliation_receipts.filter(_):[],l=new Map(d.map(b=>[b.idempotencyKey,b]));for(const b of r.reconciliationReceipts)K(l.get(b.idempotencyKey))||l.set(b.idempotencyKey,b);const f=_(s.terminal_git_receipt)?s.terminal_git_receipt:null,h=Se(f,r.terminalReceipt);if(h.kind==="blocked"){i=h.reasonCode;return}s.terminal_git_receipt=h.receipt,s.git_reconciliation_receipts=[...l.values()],s.physicalMergeStatus=r.terminalReceipt.physicalStatus==="pushed"?"merged":r.terminalReceipt.physicalStatus,s.pr_number=r.terminalReceipt.prNumber??s.pr_number??null,s.git_reconciliation_debt=me(s.git_reconciliation_debt,r.preservedDecisions)}),i?o(i,!1,!1):{ok:!0}}catch{return o("epic-terminal-state-persist-failed",!0,!1)}},async persistReconciliation(r){try{return await J(e,i=>{const n=z(i,r.epicId),s=Array.isArray(n.git_reconciliation_receipts)?n.git_reconciliation_receipts.filter(_):[],d=new Map(s.map(l=>[l.idempotencyKey,l]));for(const l of r.reconciliationReceipts)K(d.get(l.idempotencyKey))||d.set(l.idempotencyKey,l);n.git_reconciliation_receipts=[...d.values()],n.git_reconciliation_debt=me(n.git_reconciliation_debt,r.preservedDecisions)}),{ok:!0}}catch{return o("git-reconciliation-state-persist-failed",!0,!1)}}}}async function I(e,a){try{const c=await e("remote","get-url","origin"),t=c.match(/^https:\/\/github\.com\/([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?\/?$/)?.[1]??c.match(/^git@github\.com:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?$/)?.[1];if(!t)return null;const u=JSON.parse(await a("repo","view",`https://github.com/${t}`,"--json","id,nameWithOwner,url"));return u.nameWithOwner!==t||u.url!==`https://github.com/${t}`||typeof u.id!="string"||!/^[A-Za-z0-9_=-]{1,256}$/.test(u.id)?null:{id:u.id,nameWithOwner:t}}catch{return null}}async function Be(e,a,c,t){try{if(e.kind!=="remote_branch"||a.resourceId!==e.resourceId||!e.baseBranch||e.baseBranch===e.branchName||!E(e.branchName)||!E(e.baseBranch)||!/^[a-f0-9]{40}$/.test(e.headSha)||!/^[a-f0-9]{40}$/.test(e.integrationHeadSha))return o("git-reconciliation-candidate-no-longer-safe",!1,!1);const u=await I(c,t);if(!u)return o("git-resource-remote-delete-cas-unavailable",!1,!1);if(!await C(c,e.branchName))return{ok:!0,outcome:"already_absent"};const r=await F({candidate:e,decision:a,git:c,gh:t});if(!r.ok)return o(r.reasonCode,!0,!1);if((await I(c,t))?.id!==u.id)return o("git-resource-provider-repository-raced",!0,!1);const n=O("sha256").update(["managed-remote-delete-v1",u.id,e.branchName,e.headSha,e.baseBranch,e.integrationHeadSha].join("\0")).digest("hex"),s=(f,h,b)=>`{name:${JSON.stringify(`refs/heads/${f}`)},beforeOid:${JSON.stringify(h)},afterOid:${JSON.stringify(b)},force:false}`,d=`mutation{updateRefs(input:{repositoryId:${JSON.stringify(u.id)},clientMutationId:${JSON.stringify(n)},refUpdates:[`+s(e.branchName,e.headSha,"0".repeat(40))+","+s(e.baseBranch,e.integrationHeadSha,e.integrationHeadSha)+"]}){clientMutationId}}",l=JSON.parse(await t("api","graphql","--hostname","github.com","-f",`query=${d}`));return l.errors||l.data?.updateRefs?.clientMutationId!==n?o("git-resource-remote-delete-cas-unverified",!0,!0):await C(c,e.branchName)?o("git-resource-remote-delete-recreated-or-unverified",!0,!1):{ok:!0,outcome:"applied"}}catch{return o("git-resource-remote-delete-cas-rejected",!0,!0)}}async function F(e){const{candidate:a,decision:c,git:t,gh:u}=e;if(!c.managed||!a.providerVerified||a.current||a.origin||a.protected||a.lifecycle==="active"||a.hasExclusiveCommits||a.worktreeActive)return{ok:!1,reasonCode:"git-reconciliation-candidate-no-longer-safe"};const m=await t("symbolic-ref","--quiet","--short","HEAD").catch(()=>""),r=await fe(t);if(m===a.branchName||r.has(a.branchName))return{ok:!1,reasonCode:"git-resource-worktree-active"};if(a.kind==="local_branch"){const d=await le(t,`refs/heads/${a.branchName}`);return d?d!==a.headSha?{ok:!1,reasonCode:"git-resource-expected-oid-raced"}:!a.baseBranch||await A(t,a.baseBranch)!==a.integrationHeadSha||!await v(t,d,a.integrationHeadSha)?{ok:!1,reasonCode:"git-resource-integration-unproven"}:{ok:!0}:{ok:!0,alreadyAbsent:!0}}if(a.kind==="remote_branch"){const d=await C(t,a.branchName);if(!d)return{ok:!0};if(d!==a.headSha)return{ok:!1,reasonCode:"git-resource-expected-oid-raced"};const l=await I(t,u);return l?await U(u,l.nameWithOwner,a.branchName)!=="unprotected"?{ok:!1,reasonCode:"git-resource-protected"}:!a.baseBranch||await A(t,a.baseBranch)!==a.integrationHeadSha?{ok:!1,reasonCode:"git-resource-integration-unproven"}:(await t("fetch","--quiet","--no-tags","origin",`refs/heads/${a.branchName}`),await t("rev-parse","FETCH_HEAD")!==a.headSha||!await v(t,a.headSha,a.integrationHeadSha)?{ok:!1,reasonCode:"git-resource-integration-unproven"}:{ok:!0}):{ok:!1,reasonCode:"git-resource-provider-repository-unverified"}}if(!a.prNumber||!a.baseBranch)return{ok:!1,reasonCode:"git-reconciliation-pr-proof-missing"};const i=await I(t,u);if(!i)return{ok:!1,reasonCode:"git-resource-provider-repository-unverified"};const n=await L(u,i.nameWithOwner,a.prNumber);if(!n||n.headRefName!==a.branchName||n.baseRefName!==a.baseBranch||n.headRefOid!==a.headSha)return{ok:!1,reasonCode:"git-resource-expected-oid-raced"};if(n.state==="CLOSED"||n.state==="MERGED")return{ok:!0,alreadyAbsent:!0};if(await U(u,i.nameWithOwner,a.branchName)!=="unprotected")return{ok:!1,reasonCode:"git-resource-protected"};const s=await C(t,a.branchName);return!n||n.state!=="OPEN"||n.headRefName!==a.branchName||n.baseRefName!==a.baseBranch||n.headRefOid!==a.headSha||s!==a.headSha?{ok:!1,reasonCode:"git-resource-expected-oid-raced"}:(await t("fetch","--quiet","--no-tags","origin",`refs/heads/${a.branchName}`),await t("rev-parse","FETCH_HEAD")!==a.headSha||await A(t,a.baseBranch)!==a.integrationHeadSha||!await v(t,a.headSha,a.integrationHeadSha)?{ok:!1,reasonCode:"git-resource-integration-unproven"}:{ok:!0})}async function se(e){const a=[],c=await fe(e.git),t=_e(e.state),u=await I(e.git,e.gh),m=g=>{const p=g.split(`
|
|
2
|
+
`).filter(Boolean).map(w=>w.split(/\s+/));if(p.length>Z)throw new Error("git-reconciliation-ref-inventory-limit");const x=new Map;for(const[w,R]of p){const H=R?.replace(/^refs\/heads\//,"");if(!H||!E(H)||!/^[a-f0-9]{40,64}$/.test(w??"")||x.has(H))throw new Error("git-reconciliation-ref-inventory-invalid");x.set(H,w)}return x},r=m(await e.git("for-each-ref",`--count=${Z+1}`,"--format=%(objectname) %(refname)","refs/heads")),i=m(await e.git("ls-remote","--heads","origin")),n=new Set([...t.claims.keys()].filter(E)),s=u?await $e(e.gh,u.nameWithOwner,n):[],d=new Map([[e.directive.originBranch,e.originHeadSha]]),l=async g=>{if(d.has(g))return d.get(g);const p=i.get(g);return p?(await P(e.git,g,p),d.set(g,p),p):""},f=new Map,h=async(g,p)=>{const x=`${g}:${p}`;return f.has(x)||f.set(x,!!(g&&p)&&await v(e.git,g,p)),f.get(x)},b=new Set([...r.keys(),...i.keys(),...t.claims.keys()]);if(b.size>Z)throw new Error("git-reconciliation-ref-inventory-limit");for(const g of[...b].sort()){if(!E(g))continue;const p=t.claims.get(g)??[],x=new Set(p.map(y=>`${y.epicId}:${y.origin}`)),w=x.size===1?p[0].origin:e.directive.originBranch,R=await l(w),H=p.length===0||p.some(y=>y.active),G=r.get(g),B=i.get(g);B&&await P(e.git,g,B);const M=u&&B?await U(e.gh,u.nameWithOwner,g):"unknown",T=async y=>{if(x.size!==1)return[];const $=new Set;for(const q of p)for(const N of q.proofs)N.head===y&&(N.mergeSha&&(!N.pushedSha||!await h(y,N.mergeSha)||!await h(N.mergeSha,N.pushedSha)||!await h(N.pushedSha,R))||N.evidence.forEach(V=>$.add(V)));return[...$]},k={schemaVersion:1,branchName:g,baseBranch:w,integrationHeadSha:R,lifecycle:H?"active":"integrated",current:g===e.currentBranch,origin:t.origins.has(g)||g===e.directive.originBranch,worktreeActive:c.has(g),contentEquivalent:!1,publicSafe:!0};for(const[y,$]of[["local_branch",G],["remote_branch",B]]){if(!$)continue;const q=`${y}:${O("sha256").update(g).digest("hex")}:${$}`,N=await h($,R);a.push({...k,resourceId:q,kind:y,headSha:$,ownershipEvidence:await T($),protected:!!B&&M!=="unprotected",providerVerified:y==="local_branch"?!0:!!u&&M!=="unknown",...y==="remote_branch"&&u?{remoteDeletionCas:"github-update-refs-v1"}:{},commitsReachable:N,hasExclusiveCommits:!N,previouslyReconciled:e.receiptIds.has(q)})}for(const y of s.filter($=>$.headRefName===g)){const $=y.baseRefName===w&&y.sameRepository,q=await T(y.headRefOid);$&&q.includes("managed_metadata")&&q.push("pr_head_base_match");const N=`pr:${y.number}:${y.headRefOid}:${O("sha256").update(y.baseRefName).digest("hex")}`,V=await h(y.headRefOid,R);a.push({...k,resourceId:N,kind:"pull_request",prNumber:y.number,headSha:y.headRefOid,lifecycle:y.state!=="OPEN"?"already_absent":H?"active":"superseded",ownershipEvidence:q,providerVerified:$,protected:M!=="unprotected",commitsReachable:V,hasExclusiveCommits:!V,previouslyReconciled:e.receiptIds.has(N)})}}return Ne(e.epic,a),a}function Ne(e,a){const c=new Set((Array.isArray(e.git_reconciliation_receipts)?e.git_reconciliation_receipts:[]).filter(_).map(m=>S(m.idempotencyKey))),t=new Set((Array.isArray(e.git_reconciliation_debt)?e.git_reconciliation_debt:[]).filter(_).map(m=>S(m.resourceId))),u=new Set(a.filter(m=>m.kind==="pull_request"&&ie(m).action==="close_pull_request").map(m=>m.branchName));for(const m of a){const r=ie(m);r.action==="preserve"?t.add(m.resourceId):(c.add(`reconciliation:v2:${O("sha256").update([m.resourceId,r.action].join("\0")).digest("hex")}`),m.kind!=="pull_request"&&u.has(m.branchName)&&t.add(m.resourceId))}if(c.size>1024)throw new Error("git-reconciliation-receipt-capacity");if(t.size>1024)throw new Error("git-reconciliation-debt-capacity")}function de(e){const a=new Set(["git-reconciliation-state-inventory-limit","git-reconciliation-ref-inventory-limit","git-reconciliation-ref-inventory-invalid","git-reconciliation-pr-inventory-limit","git-reconciliation-pr-inventory-invalid","git-reconciliation-receipt-capacity","git-reconciliation-debt-capacity"]);return e instanceof Error&&a.has(e.message)?e.message:void 0}async function $e(e,a,c){const t=a.split("/")[0];if(!t||!/^[A-Za-z0-9_.-]+$/.test(t))throw new Error("git-reconciliation-pr-inventory-invalid");const u=[],m=new Set,r=100,i=Math.floor(ne/r)+1;for(const n of[...c].sort()){if(!E(n))throw new Error("git-reconciliation-pr-inventory-invalid");const s=encodeURIComponent(`${t}:${n}`);for(let d=1;d<=i;d+=1){const l=`repos/${a}/pulls?state=all&head=${s}&per_page=${r}&page=${d}`,f=JSON.parse(await e("api",l,"--hostname","github.com"));if(!Array.isArray(f)||f.length>r)throw new Error("git-reconciliation-pr-inventory-limit");for(const h of f){if(!_(h)||!Number.isSafeInteger(h.number)||Number(h.number)<=0||m.has(Number(h.number))||!_(h.head)||!_(h.base)||S(h.head.ref)!==n||!E(S(h.head.ref))||!E(S(h.base.ref))||!/^[a-f0-9]{40,64}$/.test(S(h.head.sha))||!["open","closed"].includes(S(h.state)))throw new Error("git-reconciliation-pr-inventory-invalid");if(m.add(Number(h.number)),u.push({number:Number(h.number),state:S(h.state).toUpperCase(),headRefName:S(h.head.ref),headRefOid:S(h.head.sha),baseRefName:S(h.base.ref),sameRepository:_(h.head.repo)&&_(h.base.repo)&&h.head.repo.full_name===a&&h.base.repo.full_name===a}),u.length>ne)throw new Error("git-reconciliation-pr-inventory-limit")}if(f.length<r)break}}return u}function K(e){return _(e)&&(e.outcome==="applied"||e.outcome==="already_absent")}async function Ae(e){try{const a=(await e.git("log",e.originHeadSha,"--format=%H","--fixed-strings",`--grep=Neocortex-Idempotency: ${e.directive.idempotencyKey}`)).split(`
|
|
3
|
+
`).filter(s=>/^[a-f0-9]{40,64}$/i.test(s));if(a.length!==1)return null;const c=a[0],t=(await e.git("rev-list","--parents","-n","1",c)).split(/\s+/),u=await e.git("show","-s","--format=%B",c),[m]=u.split(`
|
|
4
|
+
`),r=`merge(${e.directive.epicId}): integrate ${e.directive.executionBranch} into ${e.directive.originBranch}`;if(t.length!==3||t[2]!==e.executionHeadSha||m!==r)return null;const i=new Set(u.split(`
|
|
5
|
+
`).map(s=>s.trim()));for(const s of[`Neocortex-Epic: ${e.directive.epicId}`,`Neocortex-Origin-Branch: ${e.directive.originBranch}`,`Neocortex-Execution-Branch: ${e.directive.executionBranch}`,`Neocortex-Execution-Head: ${e.executionHeadSha}`,`Neocortex-Origin-Base: ${t[1]}`,`Neocortex-Graph-Revision: ${e.directive.graphRevision}`,`Neocortex-Aggregate-QA: ${e.directive.localGates.aggregateQaReceipt.receiptRef}`,`Neocortex-Idempotency: ${e.directive.idempotencyKey}`])if(!i.has(s))return null;const n=await e.git("show","-s","--format=%cI",c);return{schemaVersion:1,epicId:e.directive.epicId,executionBranch:e.directive.executionBranch,originBranch:e.directive.originBranch,baseSha:t[1],executionHeadSha:e.executionHeadSha,mergeSha:c,pushedSha:c,strategy:"direct",physicalStatus:"pushed",localGateReceiptRefs:e.directive.localGates.receiptRefs,idempotencyKey:e.directive.idempotencyKey,attemptStartedAt:n,completedAt:n,retryEligible:!1,reasonCodes:["epic-terminal-recovered-physical-push"],publicSafe:!0}}catch{return null}}async function U(e,a,c){try{if(!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(a))return"unknown";const t=await e("api",`repos/${a}/branches/${encodeURIComponent(c)}`,"--hostname","github.com","--jq",".protected");return t==="false"?"unprotected":t==="true"?"protected":"unknown"}catch{return"unknown"}}async function L(e,a,c){try{const t=JSON.parse(await e("pr","view",String(c),"--repo",`https://github.com/${a}`,"--json","state,headRefName,headRefOid,baseRefName,mergeCommit"));return[t.state,t.headRefName,t.headRefOid,t.baseRefName].every(u=>typeof u=="string")?t:null}catch{return null}}async function Ee(e,a,c,t,u,m){if(!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(a)||!E(c)||!/^[a-f0-9]{40,64}$/i.test(t)||!/^[a-f0-9]{40,64}$/i.test(u)||Number.isNaN(Date.parse(m)))return{ok:!1,reasonCode:"epic-terminal-pr-base-guard-unverifiable"};let r;try{const d=JSON.parse(await e("api",`repos/${a}/rules/branches/${encodeURIComponent(c)}`,"--hostname","github.com","--paginate","--slurp")),l=Array.isArray(d)&&d.every(Array.isArray)?d.flat():d;if(!Array.isArray(l)||l.length>256||l.some(f=>!_(f)))return{ok:!1,reasonCode:"epic-terminal-pr-base-guard-unverifiable"};r=l}catch{return{ok:!1,reasonCode:"epic-terminal-pr-base-guard-unverifiable"}}if(r.some(d=>d.type==="merge_queue"))return{ok:!1,reasonCode:"epic-terminal-pr-merge-queue-local-gate-required"};const i=r.some(d=>d.type==="required_status_checks"&&_(d.parameters)&&d.parameters.strict_required_status_checks_policy===!0);let n=!1;try{const d=JSON.parse(await e("api",`repos/${a}/branches/${encodeURIComponent(c)}/protection/required_status_checks`,"--hostname","github.com"));if(!_(d)||typeof d.strict!="boolean")return{ok:!1,reasonCode:"epic-terminal-pr-base-guard-unverifiable"};n=d.strict}catch(d){if(!qe(d))return{ok:!1,reasonCode:"epic-terminal-pr-base-guard-unverifiable"}}return!i&&!n?{ok:!1,reasonCode:"epic-terminal-pr-strict-base-guard-required"}:{ok:!0,receipt:{schemaVersion:1,provider:"github",mode:"strict_up_to_date_expected_head",source:i&&n?"branch_protection_and_ruleset":i?"ruleset":"branch_protection",prHeadSha:t,originHeadSha:u,checkedAt:m,publicSafe:!0}}}function qe(e){return e instanceof Error&&/(?:HTTP\s*)?404\b|not found/i.test(e.message)}function Ie(e,a){const c=e.mode==="recovered_exact_tree"?e.source==="physical_recovery":e.mode==="strict_up_to_date_expected_head"&&["branch_protection","ruleset","branch_protection_and_ruleset"].includes(e.source);return e.schemaVersion===1&&e.provider==="github"&&c&&e.publicSafe===!0&&!Number.isNaN(Date.parse(e.checkedAt))&&e.prHeadSha===a.mergeSha&&e.originHeadSha===a.baseSha}async function ue(e,a,c){return(await ke(e,[...a],{cwd:c,encoding:"utf8",maxBuffer:16777216})).stdout.trim()}async function D(e,a,c=!1){const t=JSON.parse(await ae(a,"utf8"));return xe(t,await He(e,{required:c}))}function he(e,a,c,t){if(!e||e.schemaVersion!==1||e.evidenceVersion!=="p205-execution-v2"||e.producer!=="local-yolo-tdd"||e.contract!=="P205-CI-02"||e.command!==Q||e.verdict!=="passed"||e.executionHeadSha!==a||e.graphRevision!==c||!/^[a-f0-9]{64}$/i.test(e.manifestDigest??"")||!/^[a-f0-9]{64}$/i.test(e.resultDigest??"")||e.gateIds.length===0)return!1;const u=`local-yolo-tdd:${O("sha256").update(["epic-aggregate-p205-execution-v2",Q,a,c,e.manifestDigest,e.gateIds.join(","),e.resultDigest].join("\0")).digest("hex")}`;if(e.receiptRef!==u)return!1;const m=Date.parse(e.checkedAt),r=Date.parse(t);return Number.isFinite(m)&&Number.isFinite(r)&&r-m<=1800*1e3&&m-r<=300*1e3}async function A(e,a){const c=await C(e,a);if(!c)throw new Error("origin-ref-missing");return c}async function C(e,a){if(!E(a))throw new Error("branch-ref-invalid");const t=(await e("ls-remote","--heads","origin",`refs/heads/${a}`)).split(`
|
|
6
|
+
`).filter(Boolean).map(u=>u.split(/\s+/));if(t.length!==0){if(t.length!==1||t[0].length!==2||t[0][1]!==`refs/heads/${a}`||!/^[a-f0-9]{40,64}$/i.test(t[0][0]??""))throw new Error("remote-ref-query-invalid");return t[0][0]}}async function P(e,a,c){if(await e("fetch","--quiet","--no-tags","origin",`refs/heads/${a}`),await e("rev-parse","FETCH_HEAD")!==c)throw new Error("remote-head-raced")}async function le(e,a){try{return await e("rev-parse","--verify",a)}catch{return}}async function v(e,a,c){try{return await e("merge-base","--is-ancestor",a,c),!0}catch{return!1}}async function j(e,a){if(!/^[a-f0-9]{40,64}$/i.test(a))return!1;try{return await e("cat-file","-t",a)==="commit"}catch{return!1}}async function fe(e){const a=new Set,c=await e("worktree","list","--porcelain");for(const t of c.split(`
|
|
7
|
+
`))t.startsWith("branch refs/heads/")&&a.add(t.slice(18));return a}function o(e,a,c){return{ok:!1,reasonCode:e,retryEligible:a,externalPolicy:c}}function S(e){return typeof e=="string"?e.trim():""}function E(e){return e.length>0&&e.length<=240&&!e.startsWith("-")&&!e.startsWith("/")&&!e.endsWith("/")&&!e.endsWith(".lock")&&!e.includes("..")&&!e.includes("\\")&&!e.includes("@{")&&!e.includes("//")&&/^[A-Za-z0-9._/-]+$/.test(e)}function _(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Oe(e,a){return e instanceof Error&&"code"in e&&e.code===a}function Y(e){return(Array.isArray(e.stories)?e.stories:Array.isArray(e.story_ids)?e.story_ids:[]).filter(c=>typeof c=="string")}async function X(e,a,c,t,u){const m=Y(c),r=await Promise.all(m.map(i=>ce(e,a.stories?.[i]?.checkpoint,i,t,u).then(n=>n&&ge(a.stories?.[i]?.checkpoint))));return m.filter((i,n)=>r[n])}function ge(e){const a=_(e)?e:void 0,c=a&&_(a.qaReceipt)?a.qaReceipt:void 0;return!!(c&&c.evidenceVersion==="p205-execution-v2"&&c.producer==="local-yolo-tdd"&&c.contract==="P205-CI-02"&&c.command===Q&&/^[a-f0-9]{64}$/i.test(S(c.manifestDigest))&&/^[a-f0-9]{64}$/i.test(S(c.resultDigest))&&Array.isArray(c.gateIds)&&c.gateIds.length>0)}function ee(e,a){return e.length===a.length&&[...e].sort().every((c,t)=>c===[...a].sort()[t])}function re(e){return _(e)&&typeof e.expiresAt=="string"&&e.expiresAt>new Date().toISOString()}async function pe(e){const a=new Set([".neocortex/yoloop.lock",".neocortex/yoloop-state.json",".neocortex/continuity/continuity.sqlite",".neocortex/continuity/continuity.sqlite-shm",".neocortex/continuity/continuity.sqlite-wal"]);return(await e("status","--porcelain","--untracked-files=all")).split(`
|
|
8
|
+
`).filter(Boolean).some(c=>!c.startsWith("?? ")||!a.has(c.slice(3)))}function te(e){const a=e instanceof Error?e.message:"";return/protected branch|branch protection|required pull request|GH006|GH013|ruleset|review required/i.test(a)}function me(e,a){const c=Array.isArray(e)?e.filter(_):[],t=new Map(c.map(u=>[S(u.resourceId),u]));for(const u of a)t.set(u.resourceId,u);return[...t.values()]}export{ze as createCliEpicTerminalGitAdapter};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* P190.06 -- runner root-owned execution plane for run_yoloop directives.
|
|
6
6
|
*/
|
|
7
|
+
import type { InvokeOptions, InvokeResult } from '../../commands/invoke.js';
|
|
7
8
|
import { type ContinuityHeadlessExecutionAttemptStatus, type ContinuitySqliteStore } from '../../continuity/sqlite-store.js';
|
|
8
9
|
import { HeadlessAdapterRegistry } from './adapters.js';
|
|
9
10
|
import { type HeadlessAdapterExecutionOptions, type HeadlessAdapterId, type HeadlessRedactionEvidence } from './types.js';
|
|
@@ -41,6 +42,11 @@ export interface RunYoloopRootInvokeResult {
|
|
|
41
42
|
readonly publicSafe?: true;
|
|
42
43
|
}
|
|
43
44
|
export type RunYoloopRootInvoker = (input: RunYoloopRootInvokeInput) => Promise<RunYoloopRootInvokeResult>;
|
|
45
|
+
export interface RunYoloopRootInvokeBoundary {
|
|
46
|
+
readonly projectRoot: string;
|
|
47
|
+
readonly timeoutMs: number;
|
|
48
|
+
}
|
|
49
|
+
export type RunYoloopRootInvokeTransport = (options: InvokeOptions, boundary: RunYoloopRootInvokeBoundary) => Promise<InvokeResult>;
|
|
44
50
|
export interface RunYoloopExecutionPhaseOptions {
|
|
45
51
|
readonly store: ContinuitySqliteStore;
|
|
46
52
|
readonly projectRoot: string;
|
|
@@ -116,5 +122,5 @@ export interface RunYoloopExecutionPhaseSummary {
|
|
|
116
122
|
readonly publicSafe: true;
|
|
117
123
|
}
|
|
118
124
|
export declare function isCanonicalDelegatedStoryPrompt(prompt: string): boolean;
|
|
119
|
-
export declare function defaultYoloopRootInvoker(input: RunYoloopRootInvokeInput): Promise<RunYoloopRootInvokeResult>;
|
|
125
|
+
export declare function defaultYoloopRootInvoker(input: RunYoloopRootInvokeInput, invokeTransport?: RunYoloopRootInvokeTransport): Promise<RunYoloopRootInvokeResult>;
|
|
120
126
|
export declare function runYoloopExecutionPhase(options: RunYoloopExecutionPhaseOptions): Promise<RunYoloopExecutionPhaseSummary>;
|