@ornexus/neocortex 4.60.55 → 4.60.56
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 +23 -23
- package/install.ps1 +1 -1
- package/install.sh +1 -1
- package/package.json +5 -2
- package/packages/client/dist/commands/invoke.d.ts +32 -0
- package/packages/client/dist/commands/invoke.js +69 -60
- package/packages/client/dist/git/direct-yolo-checkpoint.d.ts +6 -0
- package/packages/client/dist/git/direct-yolo-checkpoint.js +4 -4
- package/packages/client/dist/private-execution/clean-baseline.d.ts +12 -0
- package/packages/client/dist/private-execution/clean-baseline.js +2 -0
- package/packages/client/dist/private-execution/codex-executor.d.ts +65 -0
- package/packages/client/dist/private-execution/codex-executor.js +2 -0
- package/packages/client/dist/private-execution/delivery.d.ts +74 -0
- package/packages/client/dist/private-execution/delivery.js +3 -0
- package/packages/client/dist/private-execution/isolated-admission.d.ts +13 -0
- package/packages/client/dist/private-execution/isolated-admission.js +2 -0
- package/packages/client/dist/private-execution/isolated-session.d.ts +41 -0
- package/packages/client/dist/private-execution/isolated-session.js +2 -0
- package/packages/client/dist/private-execution/isolated-workspace.d.ts +13 -0
- package/packages/client/dist/private-execution/isolated-workspace.js +1 -0
- package/packages/client/dist/private-execution/root-checkpoint.d.ts +15 -0
- package/packages/client/dist/private-execution/root-checkpoint.js +1 -0
- package/packages/client/dist/resolvers/remote-resolver.js +1 -1
- package/packages/client/dist/yolo/change-evidence-collector.d.ts +6 -0
- package/packages/client/dist/yolo/change-evidence-collector.js +1 -0
- package/packages/client/dist/yolo/spec-envelope-collector.d.ts +11 -0
- package/packages/client/dist/yolo/spec-envelope-collector.js +5 -0
- package/packages/shared/dist/frontmatter-context-contract.js +326 -0
- package/packages/shared/dist/yolo/change-evidence.js +44 -0
- package/packages/shared/dist/yolo/spec-envelope.js +161 -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 +1 -1
- 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
|
@@ -83,3 +83,9 @@ export declare function finalizeDirectYoloStoryCheckpoint(options: DirectYoloChe
|
|
|
83
83
|
export declare function recoverLegacyDirectYoloStoryCheckpoint(options: DirectYoloCheckpointOptions & {
|
|
84
84
|
readonly commitSha: string;
|
|
85
85
|
}): Promise<DirectYoloCheckpointResult<StoryCommitCheckpoint>>;
|
|
86
|
+
/** Physical observation for a private YOLO agent step; this is not actor attribution. */
|
|
87
|
+
export declare function captureDirectYoloCheckoutEvidence(projectRootInput: string): Promise<{
|
|
88
|
+
readonly headSha: string;
|
|
89
|
+
readonly branch: string;
|
|
90
|
+
readonly payloadDigest: string;
|
|
91
|
+
}>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{execFile as xe}from"node:child_process";import{createHash as De,randomBytes as oe,timingSafeEqual as be}from"node:crypto";import{readFile as ie}from"node:fs/promises";import{join as ne,resolve as ae}from"node:path";import{promisify as Ae}from"node:util";import{acquireGitLifecyclePhysicalIntegrationLock as N,applyGitLifecycleRuntimeOverlay as je,computeImmutableStoryQaEvidenceDigest as Ee,computeGitLifecyclePhysicalIntegrationLockOwnerDigest as se,computeP205StoryQaEvidenceDigest as Be,computeLegacyDirectYoloRecoveryReceiptRef as _e,ensureRuntimeEpic as z,ensureRuntimeStory as Le,ensureGitLifecyclePrivateChildDirectory as qe,executeP205TransientAuthority as $e,projectP205TransientExecutionEvidence as Ce,LEGACY_DIRECT_YOLO_RECOVERY_COMMITS as ze,mutateGitLifecycleRuntime as H,P205_COMPLETE_COMMAND as He,readGitLifecycleRuntime as q,gitLifecycleRuntimeDirectory as Oe,assertGitLifecyclePrivateFile as ce,releaseGitLifecyclePhysicalIntegrationLock as V,releaseGitLifecyclePhysicalIntegrationLockForCheckpoint as Pe,verifyGitLifecyclePhysicalIntegrationLock as Y,verifyAcceptedGitLifecycleStoryCheckpoint as de}from"./git-lifecycle-store.js";import{anchoredAtomicWriteFile as Ne}from"./secure-filesystem-boundary.js";import{GIT_LIFECYCLE_COMMIT_PUSH_STEP_ID as Ve,GIT_LIFECYCLE_REVIEW_PR_STEP_ID as fe}from"./git-lifecycle-step-ids.js";const M=Ae(xe);async function it(e){try{const t=await he(e.projectRoot,e.storyId),o=P(e.nowIso),r=Date.parse(o),i=await w(t.projectRoot,["symbolic-ref","--quiet","--short","HEAD"]),n=await w(t.projectRoot,["rev-parse","HEAD"]),u=await q(t.projectRoot,{required:!0}),s=R(u.epics[t.epicId]),d=R(s?.branch_lease),a=d&&Number.isFinite(Date.parse(String(d.expiresAt)))&&Date.parse(String(d.expiresAt))>r;if(a&&d?.ownerStoryId!==e.storyId)return f("direct-yolo-writer-active");let c=Re(s?.origin_binding,t.executionBranch,t.originBranch);if(i===t.executionBranch){if(!c)return f("direct-yolo-origin-binding-invalid")}else{if(i!==t.originBranch)return f("direct-yolo-current-branch-mismatch");if(c&&c.originHeadSha!==n)return f("direct-yolo-origin-binding-conflict");if(c??={schemaVersion:1,originBranch:t.originBranch,originHeadSha:n,executionBranch:t.executionBranch,capturedFromCurrentCheckout:!0,capturedAt:o},(await Me(t.projectRoot)).some(g=>g.branch===t.executionBranch&&ae(g.path)!==t.projectRoot))return f("direct-yolo-execution-branch-checked-out-elsewhere");const p=await Se(t.projectRoot),h=`refs/heads/${t.executionBranch}`;if(await C(t.projectRoot,["show-ref","--verify","--quiet",h])){const g=await w(t.projectRoot,["rev-parse",h]);if(g!==n){if(!await C(t.projectRoot,["merge-base","--is-ancestor",g,n]))return f("direct-yolo-execution-branch-diverged");await w(t.projectRoot,["update-ref",h,n,g])}await w(t.projectRoot,["switch",t.executionBranch])}else await w(t.projectRoot,["switch","-c",t.executionBranch]);if(await Se(t.projectRoot)!==p)return f("direct-yolo-checkout-payload-raced")}const l=await w(t.projectRoot,["symbolic-ref","--quiet","--short","HEAD"]),S=await w(t.projectRoot,["rev-parse","HEAD"]);if(l!==t.executionBranch)return f("direct-yolo-current-branch-mismatch");if(a&&d?.ownerStoryId===e.storyId)return{ok:!0,value:ve(t,c,String(d.expiresAt),!0)};const m=o,y=new Date(r+3600*1e3).toISOString(),k=`setup-${oe(32).toString("hex")}`,E=await q(t.projectRoot,{required:!0});return await H(t.projectRoot,A=>{const p=z(A,t.epicId),h=R(p.branch_lease);if(h&&Date.parse(String(h.expiresAt))>r&&h.ownerStoryId!==e.storyId)throw new Error("direct-yolo-writer-active");const g=Re(p.origin_binding,t.executionBranch,t.originBranch);if(p.origin_binding&&!g)throw new Error("direct-yolo-origin-binding-conflict");if(g&&JSON.stringify(g)!==JSON.stringify(c))throw new Error("direct-yolo-origin-binding-conflict");p.branch_mode="epic",p.execution_branch=t.executionBranch,p.origin_branch=t.originBranch,p.graph_revision=t.graphRevision,p.origin_binding=c,p.branch_lease={schemaVersion:1,ownerStoryId:e.storyId,sessionId:k,idempotencyKey:k,acquiredAt:m,expiresAt:y}},{expectedRevision:E.revision,preCommit:async()=>{if(await w(t.projectRoot,["symbolic-ref","--quiet","--short","HEAD"])!==t.executionBranch||await w(t.projectRoot,["rev-parse","HEAD"])!==S)throw new Error("direct-yolo-setup-physical-state-raced")}}),{ok:!0,value:ve(t,c,y,!1)}}catch(t){return f(T(t,"direct-yolo-setup-failed"))}}async function nt(e){try{const t=await G(e.projectRoot,e.storyId),o=$(await b(t.projectRoot,["diff","--cached","--name-only","-z"])),r=W(o,t.authorizedWriteSet,e.storyId);if(!r.ok)return f(r.reasonCode);if($(await b(t.projectRoot,["diff","--name-only","-z"])).some(x=>o.includes(x)))return f("direct-yolo-user-overlap");const n=await b(t.projectRoot,["diff","--cached","--binary","--full-index"]);if(!n)return f("direct-yolo-staged-diff-empty");const u=D(n),s=D([...t.authorizedWriteSet].sort().join("\0")),d=P(e.nowIso),a=await q(t.projectRoot,{required:!0}),c=R(a.epics[t.epicId]?.branch_lease);if(!pe(c,e.storyId,d))return f("direct-yolo-setup-handoff-owner-invalid");const l=String(c.sessionId),S=String(c.expiresAt),m=new Date(Math.min(Date.parse(S),Date.parse(d)+300*1e3)).toISOString(),y=await O(t.projectRoot,e.storyId),k=y?.state==="issued"&&y.fromSessionId===l&&y.bundleDigest===u&&y.claimRevision===s&&Date.parse(y.expiresAt)>Date.parse(d),E=k?y.expiresAt:m,A=k?y.token:oe(32).toString("base64url"),p=D(A),h=Object.freeze({schemaVersion:1,kind:"direct-yolo-setup-handoff",storyId:e.storyId,fromSessionId:l,tokenDigest:p,bundleDigest:u,claimRevision:s,expiresAt:E}),g=D(JSON.stringify(h)),I=await N(t.projectRoot,{kind:"direct",storyId:e.storyId,sessionId:l,idempotencyKey:l,expiresAt:E,persistent:!1,createdAt:d});if(!I.ok)return f(I.reasonCode==="git-lifecycle-integration-backpressure"?"direct-yolo-integration-backpressure":"direct-yolo-integration-lock-failed");try{await Z(t.projectRoot,{schemaVersion:1,kind:"direct-yolo-setup-handoff-token",state:"issued",storyId:e.storyId,fromSessionId:l,token:A,tokenDigest:p,bundleDigest:u,claimRevision:s,grantDigest:g,expiresAt:E}),await H(t.projectRoot,x=>{const v=R(z(x,t.epicId).branch_lease);if(!pe(v,e.storyId,d)||v?.sessionId!==l||v.idempotencyKey!==l)throw new Error("direct-yolo-setup-handoff-owner-raced");v.handoffGrant=h},{expectedRevision:a.revision,preCommit:async()=>{if(!await Y(I.path,I.owner))throw new Error("direct-yolo-integration-lock-raced");const x=await O(t.projectRoot,e.storyId);if(!x||x.state!=="issued"||x.grantDigest!==g||x.tokenDigest!==p)throw new Error("direct-yolo-setup-handoff-token-raced")}})}finally{await V(I.path,I.owner).catch(()=>{})}return{ok:!0,value:Object.freeze({schemaVersion:1,kind:"direct-yolo-setup-handoff-receipt",storyId:e.storyId,sessionId:l,bundleDigest:u,claimRevision:s,grantDigest:g,expiresAt:E,reused:k,publicSafe:!0})}}catch(t){return f(t instanceof Error&&/^direct-yolo-/.test(t.message)?t.message:"direct-yolo-setup-handoff-failed")}}async function at(e){try{const t=await G(e.projectRoot,e.storyId),o=await w(t.projectRoot,["rev-parse","HEAD"]),r=$(await b(t.projectRoot,["diff","--cached","--name-only","-z"])),i=W(r,t.authorizedWriteSet,e.storyId);if(!i.ok)return f(i.reasonCode);if($(await b(t.projectRoot,["diff","--name-only","-z"])).some(h=>r.includes(h)))return f("direct-yolo-user-overlap");const u=await b(t.projectRoot,["diff","--cached","--binary","--full-index"]);if(!u)return f("direct-yolo-staged-diff-empty");const s=D(u),d=D([...t.authorizedWriteSet].sort().join("\0")),a=D(["direct-yolo-commit-v1",e.storyId,t.epicId,t.executionBranch,o,s,t.graphRevision,d].join("\0")),c=P(e.nowIso);let l=e.setupLeaseHandoff??await We(t.projectRoot,e.storyId,s,d,c);const S=await q(t.projectRoot,{required:!0}),m=R(S.epics[t.epicId]?.branch_lease),y=m?.ownerStoryId===e.storyId&&m.sessionId===a&&m.idempotencyKey===a&&typeof m.expiresAt=="string"&&Date.parse(m.expiresAt)>Date.parse(c)?m:void 0;if(y&&e.setupLeaseHandoff)return f("direct-yolo-setup-handoff-replayed");const k=R(y?.handoffConsumption);if(k){const h=await O(t.projectRoot,e.storyId);if(!h||!["consuming","consumed"].includes(h.state)||h.fromSessionId!==k.fromSessionId||h.tokenDigest!==k.tokenDigest||h.bundleDigest!==s||h.claimRevision!==d||k.bundleDigest!==s||k.claimRevision!==d||h.consumedBySessionId!==a||k.consumedBySessionId!==a)return f("direct-yolo-setup-handoff-consume-invalid");if(h.state==="consuming"){if(!h.token||D(h.token)!==h.tokenDigest)return f("direct-yolo-setup-handoff-consume-invalid");l={sessionId:h.fromSessionId,token:h.token}}}const E=y?String(y.expiresAt):new Date(Date.parse(c)+1800*1e3).toISOString(),A=await N(t.projectRoot,{kind:"direct",storyId:e.storyId,sessionId:a,idempotencyKey:a,expiresAt:E,persistent:!0,createdAt:y&&typeof y.acquiredAt=="string"?y.acquiredAt:c});if(!A.ok)return f(A.reasonCode==="git-lifecycle-integration-backpressure"?"direct-yolo-integration-backpressure":"direct-yolo-integration-lock-failed");try{l&&e.setupLeaseHandoff===void 0&&(await Ge(t.projectRoot,e.storyId,l.sessionId,l.token,a,c),await e.setupHandoffFault?.("after-consuming-persisted")),await H(t.projectRoot,h=>{const g=z(h,t.epicId),I=R(g.branch_lease),x=I&&Date.parse(String(I.expiresAt))>Date.parse(c),v=I?.ownerStoryId===e.storyId&&I.sessionId===a&&I.idempotencyKey===a,j=I?.ownerStoryId===e.storyId&&I.sessionId===I.idempotencyKey&&typeof I.idempotencyKey=="string"&&/^setup-[a-f0-9]{64}$/.test(I.idempotencyKey),B=x&&j&&Fe({current:I,handoff:l,storyId:e.storyId,bundleDigest:s,claimRevision:d,nowIso:c});if(l&&x&&!v&&!B)throw new Error("direct-yolo-setup-handoff-invalid");if(x&&!v&&!B)throw new Error("direct-yolo-writer-active");const _=B?R(I?.handoffGrant):void 0,L=_?{schemaVersion:1,kind:"direct-yolo-setup-handoff-consumption",state:"consumed",storyId:e.storyId,fromSessionId:String(I?.sessionId),tokenDigest:String(_.tokenDigest),bundleDigest:s,claimRevision:d,consumedBySessionId:a,consumedAt:c}:void 0;g.branch_mode="epic",g.execution_branch=t.executionBranch,g.origin_branch=t.originBranch,g.graph_revision=t.graphRevision,g.branch_lease=x&&v?I:{schemaVersion:1,ownerStoryId:e.storyId,sessionId:a,idempotencyKey:a,acquiredAt:c,expiresAt:E,...L?{handoffConsumption:L}:{}}},{expectedRevision:S.revision,preCommit:async()=>{if(!await Y(A.path,A.owner))throw new Error("direct-yolo-integration-lock-raced")}})}catch(h){throw await V(A.path,A.owner).catch(()=>{}),h}l&&e.setupLeaseHandoff===void 0&&(await e.setupHandoffFault?.("before-consumed-persist"),await Ke(t.projectRoot,t.epicId,e.storyId,l.sessionId,l.token,s,d,a,c));const p=Object.freeze([`Neocortex-Story: ${e.storyId}`,`Neocortex-Epic: ${t.epicId}`,`Neocortex-Execution-Branch: ${t.executionBranch}`,`Neocortex-Prepared-Base: ${o}`,`Neocortex-Bundle-Digest: ${s}`,`Neocortex-Graph-Revision: ${t.graphRevision}`,`Neocortex-Claim-Revision: ${d}`]);return{ok:!0,value:Object.freeze({schemaVersion:1,storyId:e.storyId,epicId:t.epicId,executionBranch:t.executionBranch,baseSha:o,bundleDigest:s,graphRevision:t.graphRevision,claimRevision:d,idempotencyKey:a,changedPaths:Object.freeze(r),trailers:p})}}catch(t){return f(T(t,"direct-yolo-begin-failed"))}}async function st(e){let t,o,r;try{const i=await G(e.projectRoot,e.storyId);t=i;const n=await w(i.projectRoot,["rev-parse","HEAD"]);let u=await q(i.projectRoot,{required:!0});const s=R(u.stories[e.storyId]?.checkpoint);if(s){const j=typeof s.headSha=="string"?s.headSha:"",B=typeof s.graphRevision=="string"?s.graphRevision:"",_=/^[a-f0-9]{40,64}$/.test(j)?$(await b(i.projectRoot,["diff-tree","--no-commit-id","--name-only","-r","-z",j])):[],L=W(_,i.authorizedWriteSet,e.storyId);if(!(/^[a-f0-9]{40,64}$/.test(j)&&await C(i.projectRoot,["merge-base","--is-ancestor",j,n]))||!/^[a-f0-9]{64}$/.test(B)||!L.ok)return f("direct-yolo-replay-invalid");const ke=await U(e,i.projectRoot,n,B);if(!await de(i.projectRoot,s,e.storyId,i.epicId,i.executionBranch,ke.transientAuthority,i.authorizedWriteSet))return f("direct-yolo-replay-invalid");if(!await X(i.projectRoot,i.executionBranch,n,_))return f("direct-yolo-replay-head-raced");if(e.push&&!await ye(i.projectRoot,e.remote??"origin",i.executionBranch,j))return f("direct-yolo-remote-head-mismatch");const te=Array.isArray(s.receiptRefs)?s.receiptRefs.find(re=>typeof re=="string"&&/^physical-lock-owner:[a-f0-9]{64}$/.test(re)):void 0;return te&&typeof s.idempotencyKey=="string"&&await Pe(i.projectRoot,{storyId:e.storyId,idempotencyKey:s.idempotencyKey,ownerDigest:te.slice(20)}),{ok:!0,value:s}}const d=n,a=await w(i.projectRoot,["rev-parse",`${d}^`]),c=await b(i.projectRoot,["show","--no-patch","--format=%B",d]),l=$(await b(i.projectRoot,["diff-tree","--no-commit-id","--name-only","-r","-z",d])),S=W(l,i.authorizedWriteSet,e.storyId);if(!S.ok)return f(S.reasonCode);const m=F(c,"Neocortex-Bundle-Digest"),y=F(c,"Neocortex-Graph-Revision"),k=F(c,"Neocortex-Claim-Revision"),E=new Map([["Neocortex-Story",e.storyId],["Neocortex-Epic",i.epicId],["Neocortex-Execution-Branch",i.executionBranch],["Neocortex-Prepared-Base",a],["Neocortex-Graph-Revision",i.graphRevision],["Neocortex-Claim-Revision",D([...i.authorizedWriteSet].sort().join("\0"))]]);if(!m||!/^[a-f0-9]{64}$/.test(m)||!y||!k||[...E].some(([j,B])=>F(c,j)!==B))return f("direct-yolo-trailers-invalid");const A=D(await b(i.projectRoot,["diff","--binary","--full-index",`${a}..${d}`]));if(m!==A)return f("direct-yolo-bundle-digest-mismatch");const p=D(["direct-yolo-commit-v1",e.storyId,i.epicId,i.executionBranch,a,m,y,k].join("\0")),h=R(u.epics[i.epicId]?.branch_lease),g=P(e.nowIso),I=h?.ownerStoryId===e.storyId&&h.idempotencyKey===p&&h.sessionId===p&&Date.parse(String(h.expiresAt))>Date.now()?h:void 0;if(h&&Date.parse(String(h.expiresAt))>Date.now()&&!I)return f("direct-yolo-writer-active");const x=I??{schemaVersion:1,ownerStoryId:e.storyId,sessionId:p,idempotencyKey:p,acquiredAt:g,expiresAt:new Date(Date.parse(g)+1800*1e3).toISOString()},v=await N(i.projectRoot,{kind:"direct",storyId:e.storyId,sessionId:p,idempotencyKey:p,expiresAt:String(x.expiresAt),persistent:!0,createdAt:String(x.acquiredAt)});if(!v.ok)return f(v.reasonCode==="git-lifecycle-integration-backpressure"?"direct-yolo-integration-backpressure":"direct-yolo-integration-lock-failed");r=v,I||(u=(await H(i.projectRoot,B=>{const _=z(B,i.epicId),L=R(_.branch_lease);if(L&&Date.parse(String(L.expiresAt))>Date.parse(g))throw new Error("direct-yolo-writer-active");if(_.graph_revision!==i.graphRevision)throw new Error("direct-yolo-graph-revision-raced");_.branch_lease=x},{expectedRevision:u.revision})).document),o=x;{const j=await U(e,i.projectRoot,d,i.graphRevision);if(!await X(i.projectRoot,i.executionBranch,d,l))return f("direct-yolo-head-raced");if(e.push){const L=K(e.remote??"origin");if(await w(i.projectRoot,["push",L,i.executionBranch]),!await me(i.projectRoot,L,i.executionBranch,d))return f("direct-yolo-remote-head-mismatch")}const B=await ue({projectRoot:i.projectRoot,storyId:e.storyId,epicId:i.epicId,executionBranch:i.executionBranch,baseSha:a,headSha:d,bundleDigest:m,graphRevision:y,claimRevision:k,idempotencyKey:p,qaExecution:j,physicalLockOwnerDigest:se(v.owner),nowIso:P(e.nowIso),legacyReceiptRef:void 0});return await e.beforeCheckpointPersist?.(),await le({projectRoot:i.projectRoot,checkpoint:B,remote:e.push?e.remote??"origin":void 0,expectedRevision:u.revision,expectedLease:x,expectedGraphRevision:i.graphRevision,physicalLockPath:v.path,physicalLockOwner:v.owner,transientAuthority:j.transientAuthority,authorizedWriteSet:i.authorizedWriteSet})?(await e.afterCheckpointPersist?.(),{ok:!0,value:B}):f("direct-yolo-checkpoint-persist-failed")}}catch(i){return f(T(i,"direct-yolo-finalize-failed"))}finally{r&&await V(r.path,r.owner).catch(()=>{}),t&&o?await Q(t.projectRoot,t.epicId,o).catch(()=>{}):t&&await Ye(t,e.storyId).catch(()=>{})}}async function ct(e){try{const t=await G(e.projectRoot,e.storyId);if(!/^[a-f0-9]{40,64}$/.test(e.commitSha))return f("direct-yolo-recovery-commit-invalid");const o=await w(t.projectRoot,["rev-parse",e.commitSha]);if(ze[e.storyId]!==o)return f("direct-yolo-recovery-not-allowlisted");if(await w(t.projectRoot,["rev-parse","HEAD"])!==o)return f("direct-yolo-recovery-head-mismatch");await w(t.projectRoot,["merge-base","--is-ancestor",o,`refs/heads/${t.executionBranch}`]);const r=await w(t.projectRoot,["rev-parse",`${o}^`]),i=await b(t.projectRoot,["diff","--binary","--full-index",`${r}..${o}`]),n=$(await b(t.projectRoot,["diff-tree","--no-commit-id","--name-only","-r","-z",o]));if(!W(n,t.authorizedWriteSet.length>0?t.authorizedWriteSet:n,e.storyId).ok)return f("direct-yolo-recovery-write-set-invalid");const s=D(i),d=D([...n].sort().join("\0")),a=D(["legacy-direct-yolo-recovery-v1",e.storyId,o].join("\0")),c=P(e.nowIso),l=new Date(Date.parse(c)+1800*1e3).toISOString(),S=await q(t.projectRoot,{required:!0}),m=await N(t.projectRoot,{kind:"direct",storyId:e.storyId,sessionId:a,idempotencyKey:a,expiresAt:l,persistent:!0,createdAt:c});if(!m.ok)return f(m.reasonCode==="git-lifecycle-integration-backpressure"?"direct-yolo-recovery-integration-backpressure":"direct-yolo-recovery-integration-lock-failed");const y={schemaVersion:1,ownerStoryId:e.storyId,sessionId:a,idempotencyKey:a,acquiredAt:c,expiresAt:l};let k=!1;try{const E=await H(t.projectRoot,x=>{const v=z(x,t.epicId),j=R(v.branch_lease);if(j&&Date.parse(String(j.expiresAt))>Date.parse(c)&&!J(j,y))throw new Error("direct-yolo-recovery-writer-active");if(v.graph_revision!==t.graphRevision)throw new Error("direct-yolo-recovery-graph-raced");v.branch_mode="epic",v.execution_branch=t.executionBranch,v.origin_branch=t.originBranch,v.branch_lease=y},{expectedRevision:S.revision});k=!0;const A=await U(e,t.projectRoot,o,t.graphRevision);if(!await X(t.projectRoot,t.executionBranch,o,n))return f("direct-yolo-recovery-head-raced");if(e.push){const x=K(e.remote??"origin"),v=(await w(t.projectRoot,["ls-remote","--heads",x,`refs/heads/${t.executionBranch}`])).split(/\s+/)[0];if(!v||!await C(t.projectRoot,["merge-base","--is-ancestor",o,v]))return f("direct-yolo-recovery-remote-proof-missing")}const p=await ue({projectRoot:t.projectRoot,storyId:e.storyId,epicId:t.epicId,executionBranch:t.executionBranch,baseSha:r,headSha:o,bundleDigest:s,graphRevision:t.graphRevision,claimRevision:d,idempotencyKey:a,qaExecution:A,physicalLockOwnerDigest:se(m.owner),nowIso:c,legacyReceiptRef:void 0}),h=await _e(t.projectRoot,{storyId:e.storyId,epicId:t.epicId,executionBranch:t.executionBranch,baseSha:r,headSha:o,bundleDigest:s,graphRevision:t.graphRevision});if(!h)return f("direct-yolo-recovery-evidence-invalid");const g=Object.freeze({...p,receiptRefs:Object.freeze([...p.receiptRefs,h])});return await le({projectRoot:t.projectRoot,checkpoint:g,remote:e.push?e.remote??"origin":void 0,remotePolicy:"ancestor-recovery",expectedRevision:E.document.revision,expectedLease:y,expectedGraphRevision:t.graphRevision,physicalLockPath:m.path,physicalLockOwner:m.owner,transientAuthority:A.transientAuthority,authorizedWriteSet:t.authorizedWriteSet})?{ok:!0,value:g}:f("direct-yolo-recovery-persist-failed")}finally{await V(m.path,m.owner).catch(()=>{}),k&&await Q(t.projectRoot,t.epicId,y).catch(()=>{})}}catch(t){return f(T(t,"direct-yolo-recovery-failed"))}}async function he(e,t){if(!/^[A-Za-z][A-Za-z0-9_-]*\.[A-Za-z0-9._-]+$/.test(t))throw new Error("direct-yolo-story-id-invalid");const o=ae(e),r=R(JSON.parse(await ie(ne(o,".neocortex/state.json"),"utf8"))),i=await q(o,{required:!0}),n=je(r,i),u=R(n.stories),s=R(n.epics),d=R(u?.[t]),a=String(d?.epic_id??t.split(".")[0]),c=R(s?.[a]),l=String(c?.execution_branch??""),S=String(c?.origin_branch??""),m=String(c?.graph_revision??""),y=Array.isArray(d?.files_to_modify)?[...new Set(d.files_to_modify.filter(k=>typeof k=="string"&&ee(k)))].sort():[];if(!d)throw new Error("direct-yolo-story-state-missing");if(c?.branch_mode!=="epic")throw new Error("direct-yolo-branch-mode-invalid");if(!Ie(l)||!await C(o,["check-ref-format","--branch",l]))throw new Error("direct-yolo-execution-branch-invalid");if(!Ie(S)||!await C(o,["check-ref-format","--branch",S]))throw new Error("direct-yolo-origin-branch-invalid");if(!/^[a-f0-9]{64}$/.test(m))throw new Error("direct-yolo-graph-revision-invalid");return{projectRoot:o,storyId:t,story:d,epicId:a,executionBranch:l,originBranch:S,graphRevision:m,authorizedWriteSet:y}}async function G(e,t){const o=await he(e,t);if(await w(o.projectRoot,["symbolic-ref","--quiet","--short","HEAD"])!==o.executionBranch)throw new Error("direct-yolo-current-branch-mismatch");return o}async function ue(e){const t=e.nowIso,o=await b(e.projectRoot,["show","--no-patch","--format=%H%n%P%n%B",e.headSha]),r=$(await b(e.projectRoot,["diff-tree","--no-commit-id","--name-only","-r","-z",e.headSha])),i=Ee({storyId:e.storyId,baseSha:e.baseSha,headSha:e.headSha,bundleDigest:e.bundleDigest,graphRevision:e.graphRevision,commitBody:o,changedPaths:r}),n=Be({gitEvidenceDigest:i,headSha:e.headSha,graphRevision:e.graphRevision,manifestDigest:e.qaExecution.manifestDigest,gateIds:e.qaExecution.gateIds,resultDigest:e.qaExecution.resultDigest}),u=`story-qa:${n}`,s=Object.freeze({schemaVersion:1,kind:"story_qa_evidence",producer:"local-yolo-tdd",evidenceVersion:"p205-execution-v2",storyId:e.storyId,epicId:e.epicId,baseSha:e.baseSha,headSha:e.headSha,bundleDigest:e.bundleDigest,graphRevision:e.graphRevision,contract:e.qaExecution.contract,command:e.qaExecution.command,manifestDigest:e.qaExecution.manifestDigest,gateIds:e.qaExecution.gateIds,resultDigest:e.qaExecution.resultDigest,sourceEvidenceDigest:n,verdict:"passed",checkedAt:t,receiptRef:u}),d=D(["root-commit-range-review-v1",e.storyId,e.baseSha,e.headSha,e.bundleDigest,e.graphRevision,u,D(o),[...r].sort().join(",")].join("\0")),a=`story-review:${d}`,c=Object.freeze({schemaVersion:1,kind:"story_review_evidence",producer:"root-commit-range-review",storyId:e.storyId,epicId:e.epicId,baseSha:e.baseSha,headSha:e.headSha,bundleDigest:e.bundleDigest,graphRevision:e.graphRevision,sourceEvidenceDigest:d,qaReceiptRef:u,verdict:"approved",reviewedAt:t,receiptRef:a}),l=[`.neocortex/stories/${e.storyId}/qa-gate-result.json`,`.neocortex/stories/${e.storyId}/validation-evidence.md`,u,a,...e.physicalLockOwnerDigest?[`physical-lock-owner:${e.physicalLockOwnerDigest}`]:[],...e.legacyReceiptRef?[e.legacyReceiptRef]:[]];return Object.freeze({schemaVersion:1,storyId:e.storyId,epicId:e.epicId,branch:e.executionBranch,baseSha:e.baseSha,headSha:e.headSha,commits:Object.freeze([e.headSha]),idempotencyKey:e.idempotencyKey,bundleDigest:e.bundleDigest,graphRevision:e.graphRevision,claimRevision:e.claimRevision,receiptRefs:Object.freeze(l),qaVerdict:"passed",reviewVerdict:"approved",qaReceipt:s,reviewReceipt:c,recordedAt:t})}async function le(e){const{projectRoot:t,checkpoint:o,remote:r}=e;let i=!1;return await H(t,n=>{const u=z(n,o.epicId);if(e.expectedLease){const c=R(u.branch_lease);if(!J(c,e.expectedLease))throw new Error("direct-yolo-runtime-revision-conflict");if(Date.parse(String(c?.expiresAt))<=Date.now())throw new Error("direct-yolo-writer-lease-expired");if(u.graph_revision!==e.expectedGraphRevision||o.graphRevision!==e.expectedGraphRevision)throw new Error("direct-yolo-graph-revision-raced")}const s=Le(n,o.storyId),d=R(s.checkpoint);if(d&&d.headSha!==o.headSha){i=!0;return}s.checkpoint=o,s.status="done",s.last_step=fe;const a=Array.isArray(s.steps_completed)?s.steps_completed.filter(c=>typeof c=="string"):[];s.steps_completed=[...new Set([...a,Ve,fe])],u.branch_lease=null},{expectedRevision:e.expectedRevision,preCommit:async()=>{if(i)throw new Error("direct-yolo-checkpoint-conflict");if(await w(t,["symbolic-ref","--quiet","--short","HEAD"])!==o.branch||await w(t,["rev-parse","HEAD"])!==o.headSha)throw new Error("direct-yolo-checkpoint-head-raced");if(!await de(t,o,o.storyId,o.epicId,o.branch,e.transientAuthority,e.authorizedWriteSet))throw new Error("direct-yolo-checkpoint-physical-invalid");if(e.physicalLockPath&&e.physicalLockOwner&&!await Y(e.physicalLockPath,e.physicalLockOwner))throw new Error("direct-yolo-integration-lock-raced");if(r&&!(e.remotePolicy==="ancestor-recovery"?await ye(t,r,o.branch,o.headSha):await me(t,r,o.branch,o.headSha)))throw new Error("direct-yolo-checkpoint-remote-raced")}}),!i}async function ye(e,t,o,r){const i=K(t),n=(await w(e,["ls-remote","--heads",i,`refs/heads/${o}`])).split(/\s+/)[0];return!!(n&&await C(e,["merge-base","--is-ancestor",r,n]))}function pe(e,t,o){return!!(e?.ownerStoryId===t&&e.sessionId===e.idempotencyKey&&typeof e.idempotencyKey=="string"&&/^setup-[a-f0-9]{64}$/.test(e.idempotencyKey)&&typeof e.expiresAt=="string"&&Date.parse(e.expiresAt)>Date.parse(o))}async function ge(e,t){const o=await Oe(e),r=await qe(o,"handoffs"),i=`direct-${D(t)}.json`;return{parent:r,name:i,path:ne(r,i)}}async function Z(e,t){const o=await ge(e,t.storyId);await Ne(o.parent,o.name,`${JSON.stringify(t,null,2)}
|
|
2
|
-
`),await
|
|
3
|
-
`).map(i=>i.trim()).filter(i=>i.startsWith(o)).map(i=>i.slice(o.length));return r.length===1?r[0]:void 0}function D(e){return De("sha256").update(e).digest("hex")}function
|
|
4
|
-
`))r.startsWith("worktree ")?(o={path:r.slice(9)},t.push(o)):o&&r.startsWith("branch refs/heads/")&&(o.branch=r.slice(18));return t}function T(e,t){return e instanceof Error&&e.message==="git-lifecycle-runtime-revision-conflict"?"direct-yolo-runtime-revision-conflict":e instanceof Error&&/^direct-yolo-[a-z0-9-]+$/.test(e.message)?e.message:t}function f(e){return{ok:!1,reasonCode:e}}async function
|
|
1
|
+
import{execFile as xe}from"node:child_process";import{createHash as De,randomBytes as ne,timingSafeEqual as be}from"node:crypto";import{readFile as ae}from"node:fs/promises";import{join as se,resolve as Y}from"node:path";import{promisify as Ae}from"node:util";import{acquireGitLifecyclePhysicalIntegrationLock as N,applyGitLifecycleRuntimeOverlay as je,computeImmutableStoryQaEvidenceDigest as Ee,computeGitLifecyclePhysicalIntegrationLockOwnerDigest as ce,computeP205StoryQaEvidenceDigest as Be,computeLegacyDirectYoloRecoveryReceiptRef as _e,ensureRuntimeEpic as C,ensureRuntimeStory as Le,ensureGitLifecyclePrivateChildDirectory as qe,executeP205TransientAuthority as He,projectP205TransientExecutionEvidence as $e,LEGACY_DIRECT_YOLO_RECOVERY_COMMITS as Ce,mutateGitLifecycleRuntime as z,P205_COMPLETE_COMMAND as ze,readGitLifecycleRuntime as q,gitLifecycleRuntimeDirectory as Oe,assertGitLifecyclePrivateFile as de,releaseGitLifecyclePhysicalIntegrationLock as V,releaseGitLifecyclePhysicalIntegrationLockForCheckpoint as Pe,verifyGitLifecyclePhysicalIntegrationLock as M,verifyAcceptedGitLifecycleStoryCheckpoint as fe}from"./git-lifecycle-store.js";import{anchoredAtomicWriteFile as Ne}from"./secure-filesystem-boundary.js";import{GIT_LIFECYCLE_COMMIT_PUSH_STEP_ID as Ve,GIT_LIFECYCLE_REVIEW_PR_STEP_ID as he}from"./git-lifecycle-step-ids.js";const Z=Ae(xe);async function it(e){try{const t=await ue(e.projectRoot,e.storyId),o=P(e.nowIso),r=Date.parse(o),i=await y(t.projectRoot,["symbolic-ref","--quiet","--short","HEAD"]),n=await y(t.projectRoot,["rev-parse","HEAD"]),u=await q(t.projectRoot,{required:!0}),s=v(u.epics[t.epicId]),d=v(s?.branch_lease),a=d&&Number.isFinite(Date.parse(String(d.expiresAt)))&&Date.parse(String(d.expiresAt))>r;if(a&&d?.ownerStoryId!==e.storyId)return f("direct-yolo-writer-active");let c=Re(s?.origin_binding,t.executionBranch,t.originBranch);if(i===t.executionBranch){if(!c)return f("direct-yolo-origin-binding-invalid")}else{if(i!==t.originBranch)return f("direct-yolo-current-branch-mismatch");if(c&&c.originHeadSha!==n)return f("direct-yolo-origin-binding-conflict");if(c??={schemaVersion:1,originBranch:t.originBranch,originHeadSha:n,executionBranch:t.executionBranch,capturedFromCurrentCheckout:!0,capturedAt:o},(await Me(t.projectRoot)).some(m=>m.branch===t.executionBranch&&Y(m.path)!==t.projectRoot))return f("direct-yolo-execution-branch-checked-out-elsewhere");const g=await re(t.projectRoot),h=`refs/heads/${t.executionBranch}`;if(await $(t.projectRoot,["show-ref","--verify","--quiet",h])){const m=await y(t.projectRoot,["rev-parse",h]);if(m!==n){if(!await $(t.projectRoot,["merge-base","--is-ancestor",m,n]))return f("direct-yolo-execution-branch-diverged");await y(t.projectRoot,["update-ref",h,n,m])}await y(t.projectRoot,["switch",t.executionBranch])}else await y(t.projectRoot,["switch","-c",t.executionBranch]);if(await re(t.projectRoot)!==g)return f("direct-yolo-checkout-payload-raced")}const l=await y(t.projectRoot,["symbolic-ref","--quiet","--short","HEAD"]),S=await y(t.projectRoot,["rev-parse","HEAD"]);if(l!==t.executionBranch)return f("direct-yolo-current-branch-mismatch");if(a&&d?.ownerStoryId===e.storyId)return{ok:!0,value:Se(t,c,String(d.expiresAt),!0)};const w=o,p=new Date(r+3600*1e3).toISOString(),k=`setup-${ne(32).toString("hex")}`,E=await q(t.projectRoot,{required:!0});return await z(t.projectRoot,A=>{const g=C(A,t.epicId),h=v(g.branch_lease);if(h&&Date.parse(String(h.expiresAt))>r&&h.ownerStoryId!==e.storyId)throw new Error("direct-yolo-writer-active");const m=Re(g.origin_binding,t.executionBranch,t.originBranch);if(g.origin_binding&&!m)throw new Error("direct-yolo-origin-binding-conflict");if(m&&JSON.stringify(m)!==JSON.stringify(c))throw new Error("direct-yolo-origin-binding-conflict");g.branch_mode="epic",g.execution_branch=t.executionBranch,g.origin_branch=t.originBranch,g.graph_revision=t.graphRevision,g.origin_binding=c,g.branch_lease={schemaVersion:1,ownerStoryId:e.storyId,sessionId:k,idempotencyKey:k,acquiredAt:w,expiresAt:p}},{expectedRevision:E.revision,preCommit:async()=>{if(await y(t.projectRoot,["symbolic-ref","--quiet","--short","HEAD"])!==t.executionBranch||await y(t.projectRoot,["rev-parse","HEAD"])!==S)throw new Error("direct-yolo-setup-physical-state-raced")}}),{ok:!0,value:Se(t,c,p,!1)}}catch(t){return f(T(t,"direct-yolo-setup-failed"))}}async function nt(e){try{const t=await G(e.projectRoot,e.storyId),o=H(await b(t.projectRoot,["diff","--cached","--name-only","-z"])),r=W(o,t.authorizedWriteSet,e.storyId);if(!r.ok)return f(r.reasonCode);if(H(await b(t.projectRoot,["diff","--name-only","-z"])).some(x=>o.includes(x)))return f("direct-yolo-user-overlap");const n=await b(t.projectRoot,["diff","--cached","--binary","--full-index"]);if(!n)return f("direct-yolo-staged-diff-empty");const u=D(n),s=D([...t.authorizedWriteSet].sort().join("\0")),d=P(e.nowIso),a=await q(t.projectRoot,{required:!0}),c=v(a.epics[t.epicId]?.branch_lease);if(!ge(c,e.storyId,d))return f("direct-yolo-setup-handoff-owner-invalid");const l=String(c.sessionId),S=String(c.expiresAt),w=new Date(Math.min(Date.parse(S),Date.parse(d)+300*1e3)).toISOString(),p=await O(t.projectRoot,e.storyId),k=p?.state==="issued"&&p.fromSessionId===l&&p.bundleDigest===u&&p.claimRevision===s&&Date.parse(p.expiresAt)>Date.parse(d),E=k?p.expiresAt:w,A=k?p.token:ne(32).toString("base64url"),g=D(A),h=Object.freeze({schemaVersion:1,kind:"direct-yolo-setup-handoff",storyId:e.storyId,fromSessionId:l,tokenDigest:g,bundleDigest:u,claimRevision:s,expiresAt:E}),m=D(JSON.stringify(h)),I=await N(t.projectRoot,{kind:"direct",storyId:e.storyId,sessionId:l,idempotencyKey:l,expiresAt:E,persistent:!1,createdAt:d});if(!I.ok)return f(I.reasonCode==="git-lifecycle-integration-backpressure"?"direct-yolo-integration-backpressure":"direct-yolo-integration-lock-failed");try{await J(t.projectRoot,{schemaVersion:1,kind:"direct-yolo-setup-handoff-token",state:"issued",storyId:e.storyId,fromSessionId:l,token:A,tokenDigest:g,bundleDigest:u,claimRevision:s,grantDigest:m,expiresAt:E}),await z(t.projectRoot,x=>{const R=v(C(x,t.epicId).branch_lease);if(!ge(R,e.storyId,d)||R?.sessionId!==l||R.idempotencyKey!==l)throw new Error("direct-yolo-setup-handoff-owner-raced");R.handoffGrant=h},{expectedRevision:a.revision,preCommit:async()=>{if(!await M(I.path,I.owner))throw new Error("direct-yolo-integration-lock-raced");const x=await O(t.projectRoot,e.storyId);if(!x||x.state!=="issued"||x.grantDigest!==m||x.tokenDigest!==g)throw new Error("direct-yolo-setup-handoff-token-raced")}})}finally{await V(I.path,I.owner).catch(()=>{})}return{ok:!0,value:Object.freeze({schemaVersion:1,kind:"direct-yolo-setup-handoff-receipt",storyId:e.storyId,sessionId:l,bundleDigest:u,claimRevision:s,grantDigest:m,expiresAt:E,reused:k,publicSafe:!0})}}catch(t){return f(t instanceof Error&&/^direct-yolo-/.test(t.message)?t.message:"direct-yolo-setup-handoff-failed")}}async function at(e){try{const t=await G(e.projectRoot,e.storyId),o=await y(t.projectRoot,["rev-parse","HEAD"]),r=H(await b(t.projectRoot,["diff","--cached","--name-only","-z"])),i=W(r,t.authorizedWriteSet,e.storyId);if(!i.ok)return f(i.reasonCode);if(H(await b(t.projectRoot,["diff","--name-only","-z"])).some(h=>r.includes(h)))return f("direct-yolo-user-overlap");const u=await b(t.projectRoot,["diff","--cached","--binary","--full-index"]);if(!u)return f("direct-yolo-staged-diff-empty");const s=D(u),d=D([...t.authorizedWriteSet].sort().join("\0")),a=D(["direct-yolo-commit-v1",e.storyId,t.epicId,t.executionBranch,o,s,t.graphRevision,d].join("\0")),c=P(e.nowIso);let l=e.setupLeaseHandoff??await We(t.projectRoot,e.storyId,s,d,c);const S=await q(t.projectRoot,{required:!0}),w=v(S.epics[t.epicId]?.branch_lease),p=w?.ownerStoryId===e.storyId&&w.sessionId===a&&w.idempotencyKey===a&&typeof w.expiresAt=="string"&&Date.parse(w.expiresAt)>Date.parse(c)?w:void 0;if(p&&e.setupLeaseHandoff)return f("direct-yolo-setup-handoff-replayed");const k=v(p?.handoffConsumption);if(k){const h=await O(t.projectRoot,e.storyId);if(!h||!["consuming","consumed"].includes(h.state)||h.fromSessionId!==k.fromSessionId||h.tokenDigest!==k.tokenDigest||h.bundleDigest!==s||h.claimRevision!==d||k.bundleDigest!==s||k.claimRevision!==d||h.consumedBySessionId!==a||k.consumedBySessionId!==a)return f("direct-yolo-setup-handoff-consume-invalid");if(h.state==="consuming"){if(!h.token||D(h.token)!==h.tokenDigest)return f("direct-yolo-setup-handoff-consume-invalid");l={sessionId:h.fromSessionId,token:h.token}}}const E=p?String(p.expiresAt):new Date(Date.parse(c)+1800*1e3).toISOString(),A=await N(t.projectRoot,{kind:"direct",storyId:e.storyId,sessionId:a,idempotencyKey:a,expiresAt:E,persistent:!0,createdAt:p&&typeof p.acquiredAt=="string"?p.acquiredAt:c});if(!A.ok)return f(A.reasonCode==="git-lifecycle-integration-backpressure"?"direct-yolo-integration-backpressure":"direct-yolo-integration-lock-failed");try{l&&e.setupLeaseHandoff===void 0&&(await Ge(t.projectRoot,e.storyId,l.sessionId,l.token,a,c),await e.setupHandoffFault?.("after-consuming-persisted")),await z(t.projectRoot,h=>{const m=C(h,t.epicId),I=v(m.branch_lease),x=I&&Date.parse(String(I.expiresAt))>Date.parse(c),R=I?.ownerStoryId===e.storyId&&I.sessionId===a&&I.idempotencyKey===a,j=I?.ownerStoryId===e.storyId&&I.sessionId===I.idempotencyKey&&typeof I.idempotencyKey=="string"&&/^setup-[a-f0-9]{64}$/.test(I.idempotencyKey),B=x&&j&&Fe({current:I,handoff:l,storyId:e.storyId,bundleDigest:s,claimRevision:d,nowIso:c});if(l&&x&&!R&&!B)throw new Error("direct-yolo-setup-handoff-invalid");if(x&&!R&&!B)throw new Error("direct-yolo-writer-active");const _=B?v(I?.handoffGrant):void 0,L=_?{schemaVersion:1,kind:"direct-yolo-setup-handoff-consumption",state:"consumed",storyId:e.storyId,fromSessionId:String(I?.sessionId),tokenDigest:String(_.tokenDigest),bundleDigest:s,claimRevision:d,consumedBySessionId:a,consumedAt:c}:void 0;m.branch_mode="epic",m.execution_branch=t.executionBranch,m.origin_branch=t.originBranch,m.graph_revision=t.graphRevision,m.branch_lease=x&&R?I:{schemaVersion:1,ownerStoryId:e.storyId,sessionId:a,idempotencyKey:a,acquiredAt:c,expiresAt:E,...L?{handoffConsumption:L}:{}}},{expectedRevision:S.revision,preCommit:async()=>{if(!await M(A.path,A.owner))throw new Error("direct-yolo-integration-lock-raced")}})}catch(h){throw await V(A.path,A.owner).catch(()=>{}),h}l&&e.setupLeaseHandoff===void 0&&(await e.setupHandoffFault?.("before-consumed-persist"),await Ke(t.projectRoot,t.epicId,e.storyId,l.sessionId,l.token,s,d,a,c));const g=Object.freeze([`Neocortex-Story: ${e.storyId}`,`Neocortex-Epic: ${t.epicId}`,`Neocortex-Execution-Branch: ${t.executionBranch}`,`Neocortex-Prepared-Base: ${o}`,`Neocortex-Bundle-Digest: ${s}`,`Neocortex-Graph-Revision: ${t.graphRevision}`,`Neocortex-Claim-Revision: ${d}`]);return{ok:!0,value:Object.freeze({schemaVersion:1,storyId:e.storyId,epicId:t.epicId,executionBranch:t.executionBranch,baseSha:o,bundleDigest:s,graphRevision:t.graphRevision,claimRevision:d,idempotencyKey:a,changedPaths:Object.freeze(r),trailers:g})}}catch(t){return f(T(t,"direct-yolo-begin-failed"))}}async function st(e){let t,o,r;try{const i=await G(e.projectRoot,e.storyId);t=i;const n=await y(i.projectRoot,["rev-parse","HEAD"]);let u=await q(i.projectRoot,{required:!0});const s=v(u.stories[e.storyId]?.checkpoint);if(s){const j=typeof s.headSha=="string"?s.headSha:"",B=typeof s.graphRevision=="string"?s.graphRevision:"",_=/^[a-f0-9]{40,64}$/.test(j)?H(await b(i.projectRoot,["diff-tree","--no-commit-id","--name-only","-r","-z",j])):[],L=W(_,i.authorizedWriteSet,e.storyId);if(!(/^[a-f0-9]{40,64}$/.test(j)&&await $(i.projectRoot,["merge-base","--is-ancestor",j,n]))||!/^[a-f0-9]{64}$/.test(B)||!L.ok)return f("direct-yolo-replay-invalid");const ke=await X(e,i.projectRoot,n,B);if(!await fe(i.projectRoot,s,e.storyId,i.epicId,i.executionBranch,ke.transientAuthority,i.authorizedWriteSet))return f("direct-yolo-replay-invalid");if(!await ee(i.projectRoot,i.executionBranch,n,_))return f("direct-yolo-replay-head-raced");if(e.push&&!await pe(i.projectRoot,e.remote??"origin",i.executionBranch,j))return f("direct-yolo-remote-head-mismatch");const oe=Array.isArray(s.receiptRefs)?s.receiptRefs.find(ie=>typeof ie=="string"&&/^physical-lock-owner:[a-f0-9]{64}$/.test(ie)):void 0;return oe&&typeof s.idempotencyKey=="string"&&await Pe(i.projectRoot,{storyId:e.storyId,idempotencyKey:s.idempotencyKey,ownerDigest:oe.slice(20)}),{ok:!0,value:s}}const d=n,a=await y(i.projectRoot,["rev-parse",`${d}^`]),c=await b(i.projectRoot,["show","--no-patch","--format=%B",d]),l=H(await b(i.projectRoot,["diff-tree","--no-commit-id","--name-only","-r","-z",d])),S=W(l,i.authorizedWriteSet,e.storyId);if(!S.ok)return f(S.reasonCode);const w=F(c,"Neocortex-Bundle-Digest"),p=F(c,"Neocortex-Graph-Revision"),k=F(c,"Neocortex-Claim-Revision"),E=new Map([["Neocortex-Story",e.storyId],["Neocortex-Epic",i.epicId],["Neocortex-Execution-Branch",i.executionBranch],["Neocortex-Prepared-Base",a],["Neocortex-Graph-Revision",i.graphRevision],["Neocortex-Claim-Revision",D([...i.authorizedWriteSet].sort().join("\0"))]]);if(!w||!/^[a-f0-9]{64}$/.test(w)||!p||!k||[...E].some(([j,B])=>F(c,j)!==B))return f("direct-yolo-trailers-invalid");const A=D(await b(i.projectRoot,["diff","--binary","--full-index",`${a}..${d}`]));if(w!==A)return f("direct-yolo-bundle-digest-mismatch");const g=D(["direct-yolo-commit-v1",e.storyId,i.epicId,i.executionBranch,a,w,p,k].join("\0")),h=v(u.epics[i.epicId]?.branch_lease),m=P(e.nowIso),I=h?.ownerStoryId===e.storyId&&h.idempotencyKey===g&&h.sessionId===g&&Date.parse(String(h.expiresAt))>Date.now()?h:void 0;if(h&&Date.parse(String(h.expiresAt))>Date.now()&&!I)return f("direct-yolo-writer-active");const x=I??{schemaVersion:1,ownerStoryId:e.storyId,sessionId:g,idempotencyKey:g,acquiredAt:m,expiresAt:new Date(Date.parse(m)+1800*1e3).toISOString()},R=await N(i.projectRoot,{kind:"direct",storyId:e.storyId,sessionId:g,idempotencyKey:g,expiresAt:String(x.expiresAt),persistent:!0,createdAt:String(x.acquiredAt)});if(!R.ok)return f(R.reasonCode==="git-lifecycle-integration-backpressure"?"direct-yolo-integration-backpressure":"direct-yolo-integration-lock-failed");r=R,I||(u=(await z(i.projectRoot,B=>{const _=C(B,i.epicId),L=v(_.branch_lease);if(L&&Date.parse(String(L.expiresAt))>Date.parse(m))throw new Error("direct-yolo-writer-active");if(_.graph_revision!==i.graphRevision)throw new Error("direct-yolo-graph-revision-raced");_.branch_lease=x},{expectedRevision:u.revision})).document),o=x;{const j=await X(e,i.projectRoot,d,i.graphRevision);if(!await ee(i.projectRoot,i.executionBranch,d,l))return f("direct-yolo-head-raced");if(e.push){const L=K(e.remote??"origin");if(await y(i.projectRoot,["push",L,i.executionBranch]),!await we(i.projectRoot,L,i.executionBranch,d))return f("direct-yolo-remote-head-mismatch")}const B=await le({projectRoot:i.projectRoot,storyId:e.storyId,epicId:i.epicId,executionBranch:i.executionBranch,baseSha:a,headSha:d,bundleDigest:w,graphRevision:p,claimRevision:k,idempotencyKey:g,qaExecution:j,physicalLockOwnerDigest:ce(R.owner),nowIso:P(e.nowIso),legacyReceiptRef:void 0});return await e.beforeCheckpointPersist?.(),await ye({projectRoot:i.projectRoot,checkpoint:B,remote:e.push?e.remote??"origin":void 0,expectedRevision:u.revision,expectedLease:x,expectedGraphRevision:i.graphRevision,physicalLockPath:R.path,physicalLockOwner:R.owner,transientAuthority:j.transientAuthority,authorizedWriteSet:i.authorizedWriteSet})?(await e.afterCheckpointPersist?.(),{ok:!0,value:B}):f("direct-yolo-checkpoint-persist-failed")}}catch(i){return f(T(i,"direct-yolo-finalize-failed"))}finally{r&&await V(r.path,r.owner).catch(()=>{}),t&&o?await U(t.projectRoot,t.epicId,o).catch(()=>{}):t&&await Ye(t,e.storyId).catch(()=>{})}}async function ct(e){try{const t=await G(e.projectRoot,e.storyId);if(!/^[a-f0-9]{40,64}$/.test(e.commitSha))return f("direct-yolo-recovery-commit-invalid");const o=await y(t.projectRoot,["rev-parse",e.commitSha]);if(Ce[e.storyId]!==o)return f("direct-yolo-recovery-not-allowlisted");if(await y(t.projectRoot,["rev-parse","HEAD"])!==o)return f("direct-yolo-recovery-head-mismatch");await y(t.projectRoot,["merge-base","--is-ancestor",o,`refs/heads/${t.executionBranch}`]);const r=await y(t.projectRoot,["rev-parse",`${o}^`]),i=await b(t.projectRoot,["diff","--binary","--full-index",`${r}..${o}`]),n=H(await b(t.projectRoot,["diff-tree","--no-commit-id","--name-only","-r","-z",o]));if(!W(n,t.authorizedWriteSet.length>0?t.authorizedWriteSet:n,e.storyId).ok)return f("direct-yolo-recovery-write-set-invalid");const s=D(i),d=D([...n].sort().join("\0")),a=D(["legacy-direct-yolo-recovery-v1",e.storyId,o].join("\0")),c=P(e.nowIso),l=new Date(Date.parse(c)+1800*1e3).toISOString(),S=await q(t.projectRoot,{required:!0}),w=await N(t.projectRoot,{kind:"direct",storyId:e.storyId,sessionId:a,idempotencyKey:a,expiresAt:l,persistent:!0,createdAt:c});if(!w.ok)return f(w.reasonCode==="git-lifecycle-integration-backpressure"?"direct-yolo-recovery-integration-backpressure":"direct-yolo-recovery-integration-lock-failed");const p={schemaVersion:1,ownerStoryId:e.storyId,sessionId:a,idempotencyKey:a,acquiredAt:c,expiresAt:l};let k=!1;try{const E=await z(t.projectRoot,x=>{const R=C(x,t.epicId),j=v(R.branch_lease);if(j&&Date.parse(String(j.expiresAt))>Date.parse(c)&&!Q(j,p))throw new Error("direct-yolo-recovery-writer-active");if(R.graph_revision!==t.graphRevision)throw new Error("direct-yolo-recovery-graph-raced");R.branch_mode="epic",R.execution_branch=t.executionBranch,R.origin_branch=t.originBranch,R.branch_lease=p},{expectedRevision:S.revision});k=!0;const A=await X(e,t.projectRoot,o,t.graphRevision);if(!await ee(t.projectRoot,t.executionBranch,o,n))return f("direct-yolo-recovery-head-raced");if(e.push){const x=K(e.remote??"origin"),R=(await y(t.projectRoot,["ls-remote","--heads",x,`refs/heads/${t.executionBranch}`])).split(/\s+/)[0];if(!R||!await $(t.projectRoot,["merge-base","--is-ancestor",o,R]))return f("direct-yolo-recovery-remote-proof-missing")}const g=await le({projectRoot:t.projectRoot,storyId:e.storyId,epicId:t.epicId,executionBranch:t.executionBranch,baseSha:r,headSha:o,bundleDigest:s,graphRevision:t.graphRevision,claimRevision:d,idempotencyKey:a,qaExecution:A,physicalLockOwnerDigest:ce(w.owner),nowIso:c,legacyReceiptRef:void 0}),h=await _e(t.projectRoot,{storyId:e.storyId,epicId:t.epicId,executionBranch:t.executionBranch,baseSha:r,headSha:o,bundleDigest:s,graphRevision:t.graphRevision});if(!h)return f("direct-yolo-recovery-evidence-invalid");const m=Object.freeze({...g,receiptRefs:Object.freeze([...g.receiptRefs,h])});return await ye({projectRoot:t.projectRoot,checkpoint:m,remote:e.push?e.remote??"origin":void 0,remotePolicy:"ancestor-recovery",expectedRevision:E.document.revision,expectedLease:p,expectedGraphRevision:t.graphRevision,physicalLockPath:w.path,physicalLockOwner:w.owner,transientAuthority:A.transientAuthority,authorizedWriteSet:t.authorizedWriteSet})?{ok:!0,value:m}:f("direct-yolo-recovery-persist-failed")}finally{await V(w.path,w.owner).catch(()=>{}),k&&await U(t.projectRoot,t.epicId,p).catch(()=>{})}}catch(t){return f(T(t,"direct-yolo-recovery-failed"))}}async function ue(e,t){if(!/^[A-Za-z][A-Za-z0-9_-]*\.[A-Za-z0-9._-]+$/.test(t))throw new Error("direct-yolo-story-id-invalid");const o=Y(e),r=v(JSON.parse(await ae(se(o,".neocortex/state.json"),"utf8"))),i=await q(o,{required:!0}),n=je(r,i),u=v(n.stories),s=v(n.epics),d=v(u?.[t]),a=String(d?.epic_id??t.split(".")[0]),c=v(s?.[a]),l=String(c?.execution_branch??""),S=String(c?.origin_branch??""),w=String(c?.graph_revision??""),p=Array.isArray(d?.files_to_modify)?[...new Set(d.files_to_modify.filter(k=>typeof k=="string"&&te(k)))].sort():[];if(!d)throw new Error("direct-yolo-story-state-missing");if(c?.branch_mode!=="epic")throw new Error("direct-yolo-branch-mode-invalid");if(!ve(l)||!await $(o,["check-ref-format","--branch",l]))throw new Error("direct-yolo-execution-branch-invalid");if(!ve(S)||!await $(o,["check-ref-format","--branch",S]))throw new Error("direct-yolo-origin-branch-invalid");if(!/^[a-f0-9]{64}$/.test(w))throw new Error("direct-yolo-graph-revision-invalid");return{projectRoot:o,storyId:t,story:d,epicId:a,executionBranch:l,originBranch:S,graphRevision:w,authorizedWriteSet:p}}async function G(e,t){const o=await ue(e,t);if(await y(o.projectRoot,["symbolic-ref","--quiet","--short","HEAD"])!==o.executionBranch)throw new Error("direct-yolo-current-branch-mismatch");return o}async function le(e){const t=e.nowIso,o=await b(e.projectRoot,["show","--no-patch","--format=%H%n%P%n%B",e.headSha]),r=H(await b(e.projectRoot,["diff-tree","--no-commit-id","--name-only","-r","-z",e.headSha])),i=Ee({storyId:e.storyId,baseSha:e.baseSha,headSha:e.headSha,bundleDigest:e.bundleDigest,graphRevision:e.graphRevision,commitBody:o,changedPaths:r}),n=Be({gitEvidenceDigest:i,headSha:e.headSha,graphRevision:e.graphRevision,manifestDigest:e.qaExecution.manifestDigest,gateIds:e.qaExecution.gateIds,resultDigest:e.qaExecution.resultDigest}),u=`story-qa:${n}`,s=Object.freeze({schemaVersion:1,kind:"story_qa_evidence",producer:"local-yolo-tdd",evidenceVersion:"p205-execution-v2",storyId:e.storyId,epicId:e.epicId,baseSha:e.baseSha,headSha:e.headSha,bundleDigest:e.bundleDigest,graphRevision:e.graphRevision,contract:e.qaExecution.contract,command:e.qaExecution.command,manifestDigest:e.qaExecution.manifestDigest,gateIds:e.qaExecution.gateIds,resultDigest:e.qaExecution.resultDigest,sourceEvidenceDigest:n,verdict:"passed",checkedAt:t,receiptRef:u}),d=D(["root-commit-range-review-v1",e.storyId,e.baseSha,e.headSha,e.bundleDigest,e.graphRevision,u,D(o),[...r].sort().join(",")].join("\0")),a=`story-review:${d}`,c=Object.freeze({schemaVersion:1,kind:"story_review_evidence",producer:"root-commit-range-review",storyId:e.storyId,epicId:e.epicId,baseSha:e.baseSha,headSha:e.headSha,bundleDigest:e.bundleDigest,graphRevision:e.graphRevision,sourceEvidenceDigest:d,qaReceiptRef:u,verdict:"approved",reviewedAt:t,receiptRef:a}),l=[`.neocortex/stories/${e.storyId}/qa-gate-result.json`,`.neocortex/stories/${e.storyId}/validation-evidence.md`,u,a,...e.physicalLockOwnerDigest?[`physical-lock-owner:${e.physicalLockOwnerDigest}`]:[],...e.legacyReceiptRef?[e.legacyReceiptRef]:[]];return Object.freeze({schemaVersion:1,storyId:e.storyId,epicId:e.epicId,branch:e.executionBranch,baseSha:e.baseSha,headSha:e.headSha,commits:Object.freeze([e.headSha]),idempotencyKey:e.idempotencyKey,bundleDigest:e.bundleDigest,graphRevision:e.graphRevision,claimRevision:e.claimRevision,receiptRefs:Object.freeze(l),qaVerdict:"passed",reviewVerdict:"approved",qaReceipt:s,reviewReceipt:c,recordedAt:t})}async function ye(e){const{projectRoot:t,checkpoint:o,remote:r}=e;let i=!1;return await z(t,n=>{const u=C(n,o.epicId);if(e.expectedLease){const c=v(u.branch_lease);if(!Q(c,e.expectedLease))throw new Error("direct-yolo-runtime-revision-conflict");if(Date.parse(String(c?.expiresAt))<=Date.now())throw new Error("direct-yolo-writer-lease-expired");if(u.graph_revision!==e.expectedGraphRevision||o.graphRevision!==e.expectedGraphRevision)throw new Error("direct-yolo-graph-revision-raced")}const s=Le(n,o.storyId),d=v(s.checkpoint);if(d&&d.headSha!==o.headSha){i=!0;return}s.checkpoint=o,s.status="done",s.last_step=he;const a=Array.isArray(s.steps_completed)?s.steps_completed.filter(c=>typeof c=="string"):[];s.steps_completed=[...new Set([...a,Ve,he])],u.branch_lease=null},{expectedRevision:e.expectedRevision,preCommit:async()=>{if(i)throw new Error("direct-yolo-checkpoint-conflict");if(await y(t,["symbolic-ref","--quiet","--short","HEAD"])!==o.branch||await y(t,["rev-parse","HEAD"])!==o.headSha)throw new Error("direct-yolo-checkpoint-head-raced");if(!await fe(t,o,o.storyId,o.epicId,o.branch,e.transientAuthority,e.authorizedWriteSet))throw new Error("direct-yolo-checkpoint-physical-invalid");if(e.physicalLockPath&&e.physicalLockOwner&&!await M(e.physicalLockPath,e.physicalLockOwner))throw new Error("direct-yolo-integration-lock-raced");if(r&&!(e.remotePolicy==="ancestor-recovery"?await pe(t,r,o.branch,o.headSha):await we(t,r,o.branch,o.headSha)))throw new Error("direct-yolo-checkpoint-remote-raced")}}),!i}async function pe(e,t,o,r){const i=K(t),n=(await y(e,["ls-remote","--heads",i,`refs/heads/${o}`])).split(/\s+/)[0];return!!(n&&await $(e,["merge-base","--is-ancestor",r,n]))}function ge(e,t,o){return!!(e?.ownerStoryId===t&&e.sessionId===e.idempotencyKey&&typeof e.idempotencyKey=="string"&&/^setup-[a-f0-9]{64}$/.test(e.idempotencyKey)&&typeof e.expiresAt=="string"&&Date.parse(e.expiresAt)>Date.parse(o))}async function me(e,t){const o=await Oe(e),r=await qe(o,"handoffs"),i=`direct-${D(t)}.json`;return{parent:r,name:i,path:se(r,i)}}async function J(e,t){const o=await me(e,t.storyId);await Ne(o.parent,o.name,`${JSON.stringify(t,null,2)}
|
|
2
|
+
`),await de(o.path,o.parent)}async function O(e,t){try{const o=await me(e,t);await de(o.path,o.parent);const r=JSON.parse(await ae(o.path,"utf8")),i=r.state==="issued"?["schemaVersion","kind","state","storyId","fromSessionId","token","tokenDigest","bundleDigest","claimRevision","grantDigest","expiresAt"]:r.state==="consuming"?["schemaVersion","kind","state","storyId","fromSessionId","token","tokenDigest","bundleDigest","claimRevision","grantDigest","expiresAt","consumedBySessionId","consumeStartedAt"]:["schemaVersion","kind","state","storyId","fromSessionId","tokenDigest","bundleDigest","claimRevision","grantDigest","expiresAt","consumedBySessionId","consumedAt"];return Object.keys(r).sort().join("\0")!==[...i].sort().join("\0")||r.schemaVersion!==1||r.kind!=="direct-yolo-setup-handoff-token"||r.state!=="issued"&&r.state!=="consuming"&&r.state!=="consumed"||r.storyId!==t||typeof r.fromSessionId!="string"||!/^setup-[a-f0-9]{64}$/.test(r.fromSessionId)||![r.tokenDigest,r.bundleDigest,r.claimRevision,r.grantDigest].every(n=>typeof n=="string"&&/^[a-f0-9]{64}$/.test(n))||typeof r.expiresAt!="string"||!Number.isFinite(Date.parse(r.expiresAt))||(r.state==="issued"||r.state==="consuming")&&(typeof r.token!="string"||!/^[A-Za-z0-9_-]{32,256}$/.test(r.token))||r.state==="consuming"&&(typeof r.consumedBySessionId!="string"||!/^[a-f0-9]{64}$/.test(r.consumedBySessionId)||typeof r.consumeStartedAt!="string"||!Number.isFinite(Date.parse(r.consumeStartedAt)))||r.state==="consumed"&&(typeof r.consumedBySessionId!="string"||!/^[a-f0-9]{64}$/.test(r.consumedBySessionId)||typeof r.consumedAt!="string"||!Number.isFinite(Date.parse(r.consumedAt)))?void 0:r}catch{return}}async function We(e,t,o,r,i){const n=await O(e,t);if(!(!n||n.state==="consumed"||!n.token||n.bundleDigest!==o||n.claimRevision!==r||Date.parse(n.expiresAt)<=Date.parse(i)||D(n.token)!==n.tokenDigest))return{sessionId:n.fromSessionId,token:n.token}}async function Ge(e,t,o,r,i,n){const u=await O(e,t);if(!u||u.state==="consumed"||u.fromSessionId!==o||u.token!==r||u.tokenDigest!==D(r))throw new Error("direct-yolo-setup-handoff-consume-invalid");if(u.state==="consuming"){if(u.consumedBySessionId!==i)throw new Error("direct-yolo-setup-handoff-consume-raced");return}await J(e,{...u,state:"consuming",consumedBySessionId:i,consumeStartedAt:n})}async function Ke(e,t,o,r,i,n,u,s,d){const a=await O(e,o);if(a?.state==="consumed"&&a.fromSessionId===r&&a.consumedBySessionId===s)return;const c=await q(e,{required:!0}),l=v(c.epics[t]?.branch_lease),S=v(l?.handoffConsumption);if(!a||a.state!=="consuming"||a.fromSessionId!==r||a.token!==i||a.tokenDigest!==D(i)||a.bundleDigest!==n||a.claimRevision!==u||a.consumedBySessionId!==s||l?.ownerStoryId!==o||l.sessionId!==s||S?.kind!=="direct-yolo-setup-handoff-consumption"||S.state!=="consumed"||S.fromSessionId!==r||S.tokenDigest!==a.tokenDigest||S.bundleDigest!==n||S.claimRevision!==u||S.consumedBySessionId!==s)throw new Error("direct-yolo-setup-handoff-consume-invalid");try{await J(e,{schemaVersion:1,kind:a.kind,state:"consumed",storyId:o,fromSessionId:r,tokenDigest:a.tokenDigest,bundleDigest:a.bundleDigest,claimRevision:a.claimRevision,grantDigest:a.grantDigest,expiresAt:a.expiresAt,consumedBySessionId:s,consumedAt:d})}catch{throw new Error("direct-yolo-setup-handoff-consume-persist-failed")}}function Fe(e){const t=v(e.current?.handoffGrant),o=e.handoff?.token,r=typeof o=="string"&&/^[A-Za-z0-9_-]{32,256}$/.test(o)?D(o):void 0;return!!(t&&r&&e.handoff&&e.handoff.sessionId===e.current?.sessionId&&t.schemaVersion===1&&t.kind==="direct-yolo-setup-handoff"&&t.storyId===e.storyId&&t.fromSessionId===e.current?.sessionId&&t.bundleDigest===e.bundleDigest&&t.claimRevision===e.claimRevision&&typeof t.expiresAt=="string"&&Date.parse(t.expiresAt)>Date.parse(e.nowIso)&&typeof t.tokenDigest=="string"&&/^[a-f0-9]{64}$/.test(t.tokenDigest)&&Te(t.tokenDigest,r))}function Te(e,t){const o=Buffer.from(e,"hex"),r=Buffer.from(t,"hex");return o.length===32&&r.length===32&&be(o,r)}function Q(e,t){return!!(e&&["schemaVersion","ownerStoryId","sessionId","idempotencyKey","acquiredAt","expiresAt"].every(o=>e[o]===t[o]))}async function U(e,t,o){await z(e,r=>{const i=C(r,t),n=v(i.branch_lease);Q(n,o)&&(i.branch_lease=null)})}async function Ye(e,t){const o=await q(e.projectRoot,{required:!0}),r=v(o.epics[e.epicId]?.branch_lease);if(!r||r.ownerStoryId!==t||!Ie(r.sessionId)||!Ie(r.idempotencyKey)||!Number.isFinite(Date.parse(String(r.acquiredAt)))||!Number.isFinite(Date.parse(String(r.expiresAt))))return;const i=await N(e.projectRoot,{kind:"direct",storyId:t,sessionId:String(r.sessionId),idempotencyKey:String(r.idempotencyKey),createdAt:String(r.acquiredAt),expiresAt:String(r.expiresAt),persistent:!0});if(!i.ok)return;await V(i.path,i.owner)&&await U(e.projectRoot,e.epicId,r)}async function X(e,t,o,r){const i=await He(t,{headSha:o,graphRevision:r,nowIso:e.nowIso});await e.qaRunner?.({projectRoot:t,storyId:e.storyId,headSha:o});const n=$e(i);if(!n)throw new Error("p205-transient-authority-invalid");return{contract:"P205-CI-02",command:ze,manifestDigest:n.manifestDigest,gateIds:n.gateIds,resultDigest:n.resultDigest,transientAuthority:i}}async function ee(e,t,o,r){return await y(e,["rev-parse","HEAD"])!==o||await y(e,["symbolic-ref","--quiet","--short","HEAD"])!==t||!await $(e,["diff","--cached","--quiet"])?!1:$(e,["diff","--quiet","HEAD","--",...r])}async function we(e,t,o,r){const i=K(t);return(await y(e,["ls-remote","--heads",i,`refs/heads/${o}`])).split(/\s+/)[0]===r}function W(e,t,o){if(e.length===0||e.some(i=>!te(i)))return{ok:!1,reasonCode:"direct-yolo-write-set-invalid"};const r=[".neocortex/state.json",`docs/stories/${o}.story.md`,`.neocortex/stories/${o}/qa-gate-result.json`,`.neocortex/stories/${o}/validation-evidence.md`,`.neocortex/stories/${o}/review.md`];return!r.every(i=>e.includes(i))||!r.every(i=>t.includes(i))?{ok:!1,reasonCode:"direct-yolo-write-set-invalid"}:e.some(i=>!t.includes(i))?{ok:!1,reasonCode:"direct-yolo-write-set-unauthorized"}:{ok:!0}}function te(e){return e.length>0&&e.length<=1024&&!e.startsWith("/")&&!e.includes("\\")&&!e.split("/").includes("..")&&!e.startsWith(".git/")&&!e.includes("\0")}function Ie(e){return typeof e=="string"&&e.length>0&&e.length<=512&&/^[A-Za-z0-9._:@/+\-=]+$/.test(e)}function ve(e){return e.length>0&&e.length<=240&&!e.startsWith("-")&&!/[\s~^:?*[\\]/.test(e)&&!e.includes("..")}function K(e){if(!/^[A-Za-z0-9._-]{1,128}$/.test(e))throw new Error("direct-yolo-remote-invalid");return e}function F(e,t){const o=`${t}: `,r=e.split(`
|
|
3
|
+
`).map(i=>i.trim()).filter(i=>i.startsWith(o)).map(i=>i.slice(o.length));return r.length===1?r[0]:void 0}function D(e){return De("sha256").update(e).digest("hex")}function H(e){return e.split("\0").filter(Boolean)}function P(e){return e&&Number.isFinite(Date.parse(e))?new Date(Date.parse(e)).toISOString():new Date().toISOString()}function v(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function Re(e,t,o){const r=v(e);if(!(!r||r.schemaVersion!==1||r.originBranch!==o||r.executionBranch!==t||r.capturedFromCurrentCheckout!==!0||typeof r.originHeadSha!="string"||!/^[a-f0-9]{40,64}$/.test(r.originHeadSha)||typeof r.capturedAt!="string"||!Number.isFinite(Date.parse(r.capturedAt))))return r}function Se(e,t,o,r){return Object.freeze({schemaVersion:1,kind:"direct-yolo-setup-receipt",storyId:e.storyId,epicId:e.epicId,executionBranch:e.executionBranch,originBranch:e.originBranch,originHeadSha:t.originHeadSha,leaseExpiresAt:o,reused:r,publicSafe:!0})}async function re(e){const t=H(await b(e,["ls-files","--others","--exclude-standard","-z"])).sort(),o=await Promise.all(t.map(async r=>{if(!te(r))throw new Error("direct-yolo-checkout-payload-invalid");return`${r}\0${await y(e,["hash-object","--no-filters","--",r])}`}));return D([await b(e,["diff","--cached","--binary","--full-index"]),await b(e,["diff","--binary","--full-index"]),await b(e,["status","--porcelain=v1","-z","--untracked-files=all"]),...o].join("\0"))}async function dt(e){const t=Y(e),o=await y(t,["rev-parse","HEAD"]),r=await y(t,["symbolic-ref","--quiet","--short","HEAD"]),i=await re(t);if(await y(t,["rev-parse","HEAD"])!==o||await y(t,["symbolic-ref","--quiet","--short","HEAD"])!==r)throw new Error("direct-yolo-checkout-observation-raced");return Object.freeze({headSha:o,branch:r,payloadDigest:i})}async function Me(e){const t=[];let o;for(const r of(await b(e,["worktree","list","--porcelain"])).split(`
|
|
4
|
+
`))r.startsWith("worktree ")?(o={path:r.slice(9)},t.push(o)):o&&r.startsWith("branch refs/heads/")&&(o.branch=r.slice(18));return t}function T(e,t){return e instanceof Error&&e.message==="git-lifecycle-runtime-revision-conflict"?"direct-yolo-runtime-revision-conflict":e instanceof Error&&/^direct-yolo-[a-z0-9-]+$/.test(e.message)?e.message:t}function f(e){return{ok:!1,reasonCode:e}}async function y(e,t){return String((await Z("git",[...t],{cwd:e,encoding:"utf8",maxBuffer:32*1024*1024})).stdout).trim()}async function b(e,t){return String((await Z("git",[...t],{cwd:e,encoding:"utf8",maxBuffer:32*1024*1024})).stdout)}async function $(e,t){try{return await Z("git",[...t],{cwd:e,maxBuffer:8*1024*1024}),!0}catch{return!1}}export{at as beginDirectYoloStoryCommit,dt as captureDirectYoloCheckoutEvidence,st as finalizeDirectYoloStoryCheckpoint,nt as issueDirectYoloSetupLeaseHandoff,it as prepareDirectYoloSetup,ct as recoverLegacyDirectYoloStoryCheckpoint};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DirectYoloSetupReceipt } from '../git/direct-yolo-checkpoint.js';
|
|
2
|
+
/** Call immediately before root C01 setup; a dirty or ambiguous checkout fails closed. */
|
|
3
|
+
export declare function capturePrivateYoloCleanHead(projectRoot: string): string;
|
|
4
|
+
/** Persist only after physical setup succeeded without changing the clean HEAD. */
|
|
5
|
+
export declare function recordPrivateYoloCleanBaseline(projectRoot: string, setup: DirectYoloSetupReceipt, cleanHeadSha: string): Promise<void>;
|
|
6
|
+
export declare function verifyPrivateYoloCleanBaseline(projectRoot: string, storyId: string, executionBranch: string, expectedGraphRevision?: string): Promise<void>;
|
|
7
|
+
/** Read the exact C01 claim only after its physical session and graph still verify. */
|
|
8
|
+
export declare function readPrivateYoloFrozenWriteSet(projectRoot: string, storyId: string, executionBranch: string, graphRevision: string): Promise<readonly string[]>;
|
|
9
|
+
/** Used only while the root reconciles a server-persisted successor graph. */
|
|
10
|
+
export declare function readPrivateYoloFrozenWriteSetForTransition(projectRoot: string, storyId: string, executionBranch: string, initialGraphRevision: string, nextGraphRevision: string): Promise<readonly string[]>;
|
|
11
|
+
/** A clone may advance step state, but cannot rewrite the frozen C01 path claim. */
|
|
12
|
+
export declare function verifyPrivateYoloCandidateWriteSet(stateText: string, storyId: string, frozenPaths: readonly string[]): void;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{execFileSync as j}from"node:child_process";import{createHash as y}from"node:crypto";import{existsSync as D,lstatSync as W,readFileSync as w}from"node:fs";import{join as v,resolve as f}from"node:path";import{assertGitLifecyclePrivateFile as S,ensureGitLifecyclePrivateChildDirectory as x,gitLifecycleRuntimeDirectory as E,readGitLifecycleRuntimeSync as g}from"../git/git-lifecycle-store.js";import{anchoredAtomicWriteFile as z}from"../git/secure-filesystem-boundary.js";function d(i,e){const t=JSON.parse(i);if(!t||typeof t!="object"||Array.isArray(t))throw new Error("private-execution-clean-baseline-write-set-invalid");const r=t.stories,o=r&&typeof r=="object"&&!Array.isArray(r)?r[e]:void 0,n=o&&typeof o=="object"&&!Array.isArray(o)?o.files_to_modify:void 0;if(n!==void 0&&(!Array.isArray(n)||n.length>1024||n.some(c=>typeof c!="string"||c.length===0||c.length>1024||c.startsWith("/")||c.includes("\\")||c.includes("\0")||c.startsWith(".git/")||c.split("/").includes(".."))))throw new Error("private-execution-clean-baseline-write-set-invalid");if(!o)throw new Error("private-execution-clean-baseline-write-set-invalid");return[...new Set(n??[])].sort()}function m(i,e){const t=d(i,e);return y("sha256").update("private-yolo-authorized-write-set-v1\0").update(JSON.stringify(t)).digest("hex")}function I(i,e){const t=v(i,".neocortex","state.json"),r=W(t);if(!r.isFile()||r.isSymbolicLink())throw new Error("private-execution-clean-baseline-write-set-invalid");return m(w(t,"utf8"),e)}function b(i,e){return m(p(i,["show","HEAD:.neocortex/state.json"],16*1024*1024).toString("utf8"),e)}function p(i,e,t=1024*1024){const r={...process.env};for(const o of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete r[o];return j("git",[...e],{cwd:i,env:r,stdio:["ignore","pipe","pipe"],timeout:15e3,maxBuffer:t})}function l(i){return p(i,["rev-parse","HEAD"]).toString("utf8").trim()}function A(i){return p(i,["symbolic-ref","--quiet","--short","HEAD"]).toString("utf8").trim()}function _(i,e,t){const o=g(i,{required:!0}).epics[e]?.branch_lease,n=o&&typeof o=="object"&&!Array.isArray(o)?o:void 0,c=n?.ownerStoryId===t?n.sessionId:void 0;if(typeof c!="string"||!/^setup-[a-f0-9]{64}$/.test(c)||c!==n?.idempotencyKey||typeof n?.expiresAt!="string"||!Number.isFinite(Date.parse(n.expiresAt))||Date.parse(n.expiresAt)<=Date.now())throw new Error("private-execution-clean-baseline-lease-invalid");return c}async function R(i,e){const t=await E(i),r=await x(t,"private-execution"),o=`baseline-${y("sha256").update(e).digest("hex")}.json`;return{parent:r,name:o,path:v(r,o)}}async function O(i,e,t,r){try{const o=await E(i),n=await x(o,"private-execution"),c=`session-${y("sha256").update(e).digest("hex")}.json`,h=v(n,c);if(!D(h))return!1;await S(h,n);const s=JSON.parse(w(h,"utf8"));if(!s||typeof s!="object"||Array.isArray(s))return!1;const a=s,u=a.workspace&&typeof a.workspace=="object"&&!Array.isArray(a.workspace)?a.workspace:void 0;return a.schemaVersion===1&&a.kind==="private-yolo-isolated-session"&&a.storyId===e&&a.initialGraphRevision===t.graphRevision&&a.graphRevision===r&&a.setupSessionId===t.setupSessionId&&Array.isArray(a.graphHistory)&&a.graphHistory.length>1&&a.graphHistory.length<=65&&a.graphHistory[0]===t.graphRevision&&a.graphHistory[a.graphHistory.length-1]===r&&new Set(a.graphHistory).size===a.graphHistory.length&&Number.isSafeInteger(a.sequence)&&Number(a.sequence)>0&&typeof a.snapshotSha=="string"&&/^[a-f0-9]{40,64}$/.test(a.snapshotSha)&&u?.sourceRoot===i&&u.baseSha===t.headSha&&u.executionBranch===t.executionBranch}catch{return!1}}function L(i){const e=f(i);try{const t=l(e);if(p(e,["status","--porcelain=v1","-z","--untracked-files=all"]).byteLength!==0)throw new Error("private-execution-checkout-dirty");if(l(e)!==t)throw new Error("private-execution-checkout-raced");return t}catch(t){throw t instanceof Error&&/^private-execution-[a-z-]+$/.test(t.message)?t:new Error("private-execution-checkout-unverified")}}async function $(i,e,t){const r=f(i);if(!/^[a-f0-9]{40,64}$/.test(t)||e.kind!=="direct-yolo-setup-receipt"||e.originHeadSha!==t||l(r)!==t||A(r)!==e.executionBranch||p(r,["status","--porcelain=v1","-z","--untracked-files=all"]).byteLength!==0)throw new Error("private-execution-clean-baseline-raced");const o=b(r,e.storyId);if(o!==I(r,e.storyId)||l(r)!==t)throw new Error("private-execution-clean-baseline-raced");const n=g(r,{required:!0}).epics[e.epicId]?.graph_revision;if(typeof n!="string"||!/^[a-f0-9]{64}$/.test(n))throw new Error("private-execution-clean-baseline-graph-invalid");const c=Object.freeze({schemaVersion:3,kind:"private-yolo-clean-baseline",storyId:e.storyId,epicId:e.epicId,executionBranch:e.executionBranch,headSha:t,setupSessionId:_(r,e.epicId,e.storyId),graphRevision:n,authorizedWriteSetSha256:o}),h=await R(r,e.storyId);await z(h.parent,h.name,`${JSON.stringify(c)}
|
|
2
|
+
`)}async function k(i,e,t,r,o){const n=f(i);try{const c=await R(n,e);await S(c.path,c.parent);const h=JSON.parse(w(c.path,"utf8"));if(!h||typeof h!="object"||Array.isArray(h))throw new Error("private-execution-clean-baseline-invalid");const s=h,a=g(n,{required:!0}).epics[s.epicId]?.graph_revision,u=a===s.graphRevision||o===s.graphRevision&&a===r||typeof a=="string"&&await O(n,e,s,a);if(Object.keys(s).sort().join(",")!==["schemaVersion","kind","storyId","epicId","executionBranch","headSha","setupSessionId","graphRevision","authorizedWriteSetSha256"].sort().join(",")||s.schemaVersion!==3||s.kind!=="private-yolo-clean-baseline"||s.storyId!==e||s.executionBranch!==t||s.epicId!==e.split(".")[0]||typeof s.headSha!="string"||!/^[a-f0-9]{40,64}$/.test(s.headSha)||typeof s.authorizedWriteSetSha256!="string"||!/^[a-f0-9]{64}$/.test(s.authorizedWriteSetSha256)||typeof s.graphRevision!="string"||!/^[a-f0-9]{64}$/.test(s.graphRevision)||r!==void 0&&a!==r||!u||s.authorizedWriteSetSha256!==b(n,e)||s.authorizedWriteSetSha256!==I(n,e)||s.setupSessionId!==_(n,s.epicId,e)||l(n)!==s.headSha||A(n)!==t)throw new Error("private-execution-clean-baseline-invalid")}catch{throw new Error("private-execution-clean-baseline-unverified")}}async function T(i,e,t,r){return k(i,e,t,r)}async function P(i,e,t,r){await T(i,e,t,r);try{const o=d(p(f(i),["show","HEAD:.neocortex/state.json"],16777216).toString("utf8"),e);if(o.length===0)throw new Error("write-set-empty");return Object.freeze([...o])}catch{throw new Error("private-execution-clean-baseline-unverified")}}async function Y(i,e,t,r,o){await k(i,e,t,o,r);try{const n=d(p(f(i),["show","HEAD:.neocortex/state.json"],16777216).toString("utf8"),e);if(n.length===0)throw new Error("write-set-empty");return Object.freeze([...n])}catch{throw new Error("private-execution-clean-baseline-unverified")}}function J(i,e,t){try{const r=d(i,e);if(r.length!==t.length||r.some((o,n)=>o!==t[n]))throw new Error("write-set-drift")}catch{throw new Error("private-execution-clean-baseline-write-set-unverified")}}export{L as capturePrivateYoloCleanHead,P as readPrivateYoloFrozenWriteSet,Y as readPrivateYoloFrozenWriteSetForTransition,$ as recordPrivateYoloCleanBaseline,J as verifyPrivateYoloCandidateWriteSet,T as verifyPrivateYoloCleanBaseline};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export interface PrivateCodexPreflightV5 {
|
|
2
|
+
readonly schemaVersion: 5;
|
|
3
|
+
readonly hostKind: 'codex-cli';
|
|
4
|
+
readonly hostVersion: string;
|
|
5
|
+
readonly projectRoot: string;
|
|
6
|
+
readonly observedAtMs: number;
|
|
7
|
+
readonly authIsolation: 'passed';
|
|
8
|
+
readonly workspaceWrite: 'passed';
|
|
9
|
+
readonly gitControlWriteDenied: 'passed';
|
|
10
|
+
readonly gitLifecycleReadDenied: 'passed';
|
|
11
|
+
readonly mcpIsolation: 'passed';
|
|
12
|
+
readonly environmentIsolation: 'passed';
|
|
13
|
+
readonly networkDenied: 'passed';
|
|
14
|
+
readonly credentialKind: 'chatgpt-subscription';
|
|
15
|
+
}
|
|
16
|
+
export interface PrivateCodexExecutionReceiptV1 {
|
|
17
|
+
readonly schemaVersion: 1;
|
|
18
|
+
readonly outcome: 'executor-returned-unverified';
|
|
19
|
+
readonly exitCode: 0;
|
|
20
|
+
readonly stdoutSha256: string;
|
|
21
|
+
readonly stderrSha256: string;
|
|
22
|
+
readonly stdoutBytes: number;
|
|
23
|
+
readonly stderrBytes: number;
|
|
24
|
+
readonly publicSafe: true;
|
|
25
|
+
}
|
|
26
|
+
interface BoundedProcessResult {
|
|
27
|
+
readonly exitCode: number | null;
|
|
28
|
+
readonly stdout: Buffer;
|
|
29
|
+
readonly stderr: Buffer;
|
|
30
|
+
readonly timedOut: boolean;
|
|
31
|
+
readonly outputExceeded: boolean;
|
|
32
|
+
}
|
|
33
|
+
export type PrivateCodexRunner = (args: readonly string[], options: {
|
|
34
|
+
readonly cwd: string;
|
|
35
|
+
readonly stdin?: string;
|
|
36
|
+
readonly timeoutMs: number;
|
|
37
|
+
readonly maxOutputBytes: number;
|
|
38
|
+
}) => Promise<BoundedProcessResult>;
|
|
39
|
+
/** The CLI needs its login location and executable path, not host secrets. */
|
|
40
|
+
export declare function privateCodexEnvironment(source: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
41
|
+
export declare function runBoundedCodexProcess(args: readonly string[], options: {
|
|
42
|
+
readonly cwd: string;
|
|
43
|
+
readonly stdin?: string;
|
|
44
|
+
readonly timeoutMs: number;
|
|
45
|
+
readonly maxOutputBytes: number;
|
|
46
|
+
}): Promise<BoundedProcessResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Probe the exact default sandbox configuration used by `codex exec`. This
|
|
49
|
+
* intentionally does not elevate P127 task delegation or attest remote code.
|
|
50
|
+
*/
|
|
51
|
+
export declare function preflightPrivateCodexExecutor(projectRoot: string, options?: {
|
|
52
|
+
readonly runner?: PrivateCodexRunner;
|
|
53
|
+
readonly platform?: NodeJS.Platform;
|
|
54
|
+
readonly codexHome?: string;
|
|
55
|
+
readonly userHome?: string;
|
|
56
|
+
readonly now?: () => number;
|
|
57
|
+
readonly networkProbe?: (root: string, runner: PrivateCodexRunner) => Promise<boolean>;
|
|
58
|
+
}): Promise<PrivateCodexPreflightV5>;
|
|
59
|
+
export declare function runPrivateCodexStep(material: string, preflight: PrivateCodexPreflightV5, options?: {
|
|
60
|
+
readonly runner?: PrivateCodexRunner;
|
|
61
|
+
readonly now?: () => number;
|
|
62
|
+
readonly requireWorkspaceEffect?: boolean;
|
|
63
|
+
readonly expectedExecutionBranch?: string;
|
|
64
|
+
}): Promise<PrivateCodexExecutionReceiptV1>;
|
|
65
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{execFileSync as P,spawn as A}from"node:child_process";import{createHash as _,randomBytes as C}from"node:crypto";import{connect as N,createServer as G}from"node:net";import{accessSync as O,lstatSync as x,mkdtempSync as j,readFileSync as H,realpathSync as K,rmdirSync as g,unlinkSync as T,constants as I}from"node:fs";import{homedir as V}from"node:os";import{join as w,resolve as S}from"node:path";import{gitLifecycleRuntimeDirectory as $}from"../git/git-lifecycle-store.js";import{captureDirectYoloCheckoutEvidence as R}from"../git/direct-yolo-checkpoint.js";const W=3e4,u=16*1024,F=1024*1024,X=256*1024,b=/^codex-cli\s+(\d+\.\d+\.\d+)\s*$/,p="p222-isolated",Y=["PATH","HOME","LANG","LC_ALL","TERM","CODEX_HOME"],q=["-c","features.hooks=false","-c","analytics.enabled=false","-c",'history.persistence="none"',"-c",'otel.exporter="none"',"-c",'otel.metrics_exporter="none"',"-c",'otel.trace_exporter="none"',"-c","otel.log_user_prompt=false","-c","notify=[]"];function J(r){const e={};for(const t of Y)typeof r[t]=="string"&&(e[t]=r[t]);return e}async function k(r,e){return new Promise((t,o)=>{const n=J(process.env),s=A("codex",[...r],{cwd:e.cwd,stdio:["pipe","pipe","pipe"],env:n}),i=[],c=[];let a=0,d=0,y=!1,m=!1;const h=setTimeout(()=>{y=!0,s.kill("SIGKILL")},e.timeoutMs);s.stdout.on("data",l=>{a+=l.byteLength,a+d>e.maxOutputBytes?(m=!0,s.kill("SIGKILL")):i.push(l)}),s.stderr.on("data",l=>{d+=l.byteLength,a+d>e.maxOutputBytes?(m=!0,s.kill("SIGKILL")):c.push(l)}),s.on("error",l=>{clearTimeout(h),o(l)}),s.on("close",l=>{clearTimeout(h),t({exitCode:l,stdout:Buffer.concat(i),stderr:Buffer.concat(c),timedOut:y,outputExceeded:m})}),s.stdin.on("error",()=>{}),s.stdin.end(e.stdin)})}function f(r){return r.exitCode===0&&!r.timedOut&&!r.outputExceeded}async function B(r,e){const t=await e(["-c","features.plugins=false","plugin","list","--json"],{cwd:r,timeoutMs:1e4,maxOutputBytes:u}),o=await e(["mcp","list","--json"],{cwd:r,timeoutMs:1e4,maxOutputBytes:u});if(!f(t)||!f(o))return!1;try{const n=JSON.parse(t.stdout.toString("utf8")),s=JSON.parse(o.stdout.toString("utf8"));return!!(n&&typeof n=="object"&&!Array.isArray(n)&&Array.isArray(n.installed)&&n.installed.length===0&&Array.isArray(s)&&s.length===0)}catch{return!1}}async function D(r,e){const t=await e(["-c","features.hooks=false","features","list"],{cwd:r,timeoutMs:1e4,maxOutputBytes:u});if(!f(t))return!1;const o=t.stdout.toString("utf8").split(/\r?\n/).filter(n=>/^hooks\s+\S+\s+(?:true|false)\s*$/.test(n));return o.length===1&&/^hooks\s+\S+\s+false\s*$/.test(o[0])}function U(r){const e=x(r);if(!e.isFile()||e.isSymbolicLink())throw new Error("private-codex-auth-unavailable");O(r,I.R_OK)}function z(r){const e={...process.env};for(const t of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete e[t];try{const t=n=>P("git",[...n],{cwd:r,env:e,encoding:"utf8",timeout:5e3,maxBuffer:u,stdio:["ignore","pipe","ignore"]}).trim(),o=[t(["rev-parse","--git-dir"]),t(["rev-parse","--git-common-dir"])].map(n=>K(S(r,n)));if(o.some(n=>!x(n).isDirectory()))throw new Error("git-control-invalid");return[...new Set(o)]}catch{throw new Error("private-codex-git-control-unavailable")}}async function Q(r,e){const t=await e(["sandbox","-P",p,"--","git","rev-parse","--git-dir"],{cwd:r,timeoutMs:1e4,maxOutputBytes:u});if(!f(t))return!1;for(const o of z(r)){const n=w(o,`.neocortex-git-probe-${C(16).toString("hex")}`),s=await e(["sandbox","-P",p,"--","sh","-c",'mkdir "$1"',"sh",n],{cwd:r,timeoutMs:1e4,maxOutputBytes:u});let i=!1,c=!1;try{const a=x(n);i=!0,c=a.isDirectory()}catch(a){if(a.code!=="ENOENT")return!1}if(i&&(c?g(n):T(n)),s.exitCode!==1||s.timedOut||s.outputExceeded||i)return!1}return!0}async function Z(r,e,t){if(!x(e).isDirectory())return!1;O(e,I.R_OK);const o=await t(["sandbox","-P",p,"--","sh","-c",'if test -r "$1"; then exit 42; else exit 43; fi',"sh",e],{cwd:r,timeoutMs:1e4,maxOutputBytes:u});return o.exitCode===43&&!o.timedOut&&!o.outputExceeded}async function ee(r,e){const t=G(o=>o.end());await new Promise((o,n)=>{t.once("error",n),t.listen(0,"127.0.0.1",()=>o())});try{const o=t.address();if(!o||typeof o=="string")return!1;const n='const s=require("node:net").connect(Number(process.argv[1]),"127.0.0.1");s.setTimeout(1500);s.on("connect",()=>{s.end();process.exit(0)});s.on("error",()=>process.exit(1));s.on("timeout",()=>process.exit(1))';if(!await new Promise(a=>{const d=N(o.port,"127.0.0.1");d.setTimeout(1500),d.once("connect",()=>{d.end(),a(!0)}),d.once("error",()=>a(!1)),d.once("timeout",()=>{d.destroy(),a(!1)})}))return!1;const i=await e(["sandbox","-P",p,"--","node","--version"],{cwd:r,timeoutMs:5e3,maxOutputBytes:u});if(!f(i))return!1;const c=await e(["sandbox","-P",p,"--","node","-e",n,String(o.port)],{cwd:r,timeoutMs:5e3,maxOutputBytes:u});return c.exitCode===1&&!c.timedOut&&!c.outputExceeded}finally{t.close()}}async function fe(r,e={}){if((e.platform??process.platform)!=="linux")throw new Error("private-codex-platform-unsupported");const t=S(r),o=e.runner??k,n=e.userHome??V(),s=e.codexHome??process.env.CODEX_HOME??w(n,".codex"),i=w(s,"auth.json");try{U(i)}catch{throw new Error("private-codex-auth-unavailable")}const c=await o(["--version"],{cwd:t,timeoutMs:5e3,maxOutputBytes:u}),a=f(c)?b.exec(c.stdout.toString("utf8").trim()):null;if(!a)throw new Error("private-codex-version-unavailable");const d=await o(["login","status"],{cwd:t,timeoutMs:5e3,maxOutputBytes:u});if(!f(d)||!/Logged in using ChatGPT/i.test(Buffer.concat([d.stdout,d.stderr]).toString("utf8")))throw new Error("private-codex-subscription-required");if(!await B(t,o).catch(()=>!1))throw new Error("private-codex-mcp-isolation-unproven");if(!await D(t,o).catch(()=>!1))throw new Error("private-codex-hook-isolation-unproven");const h=await $(t).catch(()=>{throw new Error("private-codex-git-lifecycle-read-isolation-unproven")}),l=w(n,".ssh"),L=await o(["sandbox","-P",p,"--","sh","-c",'test ! -r "$1" && test ! -r "$2"',"sh",i,l],{cwd:t,timeoutMs:1e4,maxOutputBytes:u});if(!f(L))throw new Error("private-codex-auth-isolation-unproven");const v=j(w(t,".private-codex-probe-")),E=w(v,"receipt");try{const M=await o(["sandbox","-P",p,"--","sh","-c",'printf "P222_PROBE\\n" > "$1"',"sh",E],{cwd:t,timeoutMs:1e4,maxOutputBytes:u});if(!f(M)||H(E,"utf8")!==`P222_PROBE
|
|
2
|
+
`)throw new Error("private-codex-workspace-write-unproven")}catch{throw new Error("private-codex-workspace-write-unproven")}finally{try{T(E)}catch{}g(v)}if(!await Q(t,o).catch(()=>!1))throw new Error("private-codex-git-control-isolation-unproven");if(!await Z(t,h,o).catch(()=>!1))throw new Error("private-codex-git-lifecycle-read-isolation-unproven");if(!await(e.networkProbe??ee)(t,o))throw new Error("private-codex-network-isolation-unproven");return Object.freeze({schemaVersion:5,hostKind:"codex-cli",hostVersion:a[1],projectRoot:t,observedAtMs:(e.now??Date.now)(),authIsolation:"passed",workspaceWrite:"passed",gitControlWriteDenied:"passed",gitLifecycleReadDenied:"passed",mcpIsolation:"passed",environmentIsolation:"passed",networkDenied:"passed",credentialKind:"chatgpt-subscription"})}async function pe(r,e,t={}){const o=(t.now??Date.now)();if(e.schemaVersion!==5||e.hostKind!=="codex-cli"||e.authIsolation!=="passed"||e.workspaceWrite!=="passed"||e.gitControlWriteDenied!=="passed"||e.gitLifecycleReadDenied!=="passed"||e.mcpIsolation!=="passed"||e.environmentIsolation!=="passed"||e.networkDenied!=="passed"||e.credentialKind!=="chatgpt-subscription"||o<e.observedAtMs||o-e.observedAtMs>W||typeof r!="string"||Buffer.byteLength(r,"utf8")<1||Buffer.byteLength(r,"utf8")>X)throw new Error("private-codex-preflight-stale");const n=t.runner??k,s=await n(["--version"],{cwd:e.projectRoot,timeoutMs:5e3,maxOutputBytes:u});if(!f(s)||b.exec(s.stdout.toString("utf8").trim())?.[1]!==e.hostVersion)throw new Error("private-codex-version-drift");const i=t.requireWorkspaceEffect?await R(e.projectRoot).catch(()=>{throw new Error("private-codex-workspace-effect-unverified")}):void 0;if(i&&t.expectedExecutionBranch!==void 0&&i.branch!==t.expectedExecutionBranch)throw new Error("private-codex-workspace-effect-unverified");if(!await D(e.projectRoot,n).catch(()=>!1))throw new Error("private-codex-hook-isolation-unproven");if(!await B(e.projectRoot,n).catch(()=>!1))throw new Error("private-codex-mcp-isolation-unproven");const c=await n(["exec","--ephemeral","--json","--strict-config","-c","features.plugins=false",...q,"-c","shell_environment_policy.ignore_default_excludes=false","-c",'shell_environment_policy.include_only=["PATH","HOME","LANG","LC_ALL","TERM"]',"-c",`default_permissions="${p}"`,"-C",e.projectRoot,"-"],{cwd:e.projectRoot,stdin:r,timeoutMs:10*6e4,maxOutputBytes:F});if(!f(c))throw new Error("private-codex-execution-unverified");if(i){const a=await R(e.projectRoot).catch(()=>{throw new Error("private-codex-workspace-effect-unverified")});if(a.headSha!==i.headSha||a.branch!==i.branch||a.payloadDigest===i.payloadDigest)throw new Error("private-codex-workspace-effect-unverified")}return Object.freeze({schemaVersion:1,outcome:"executor-returned-unverified",exitCode:0,stdoutSha256:_("sha256").update(c.stdout).digest("hex"),stderrSha256:_("sha256").update(c.stderr).digest("hex"),stdoutBytes:c.stdout.byteLength,stderrBytes:c.stderr.byteLength,publicSafe:!0})}export{fe as preflightPrivateCodexExecutor,J as privateCodexEnvironment,k as runBoundedCodexProcess,pe as runPrivateCodexStep};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export declare const PRIVATE_EXECUTION_PUBLIC_INSTRUCTION_V1 = "# Neocortex private execution pending\n\nThe authorized Codex CLI executor must consume the one-time delivery and produce a physical receipt.";
|
|
2
|
+
export interface PrivateExecutionSetupRootActionV1 {
|
|
3
|
+
readonly schemaVersion: 1;
|
|
4
|
+
readonly action: 'prepare-epic-checkout';
|
|
5
|
+
readonly storyId: string;
|
|
6
|
+
readonly executionBranch: string;
|
|
7
|
+
readonly graphRevision: string;
|
|
8
|
+
readonly publicSafe: true;
|
|
9
|
+
}
|
|
10
|
+
export interface PrivateExecutionCheckpointRootActionV1 {
|
|
11
|
+
readonly schemaVersion: 1;
|
|
12
|
+
readonly action: 'checkpoint-epic-story';
|
|
13
|
+
readonly storyId: string;
|
|
14
|
+
readonly executionBranch: string;
|
|
15
|
+
readonly graphRevision: string;
|
|
16
|
+
readonly stepId: string;
|
|
17
|
+
readonly publicSafe: true;
|
|
18
|
+
}
|
|
19
|
+
export type PrivateExecutionRootActionV1 = PrivateExecutionSetupRootActionV1 | PrivateExecutionCheckpointRootActionV1;
|
|
20
|
+
/** Reject a prompt-shaped server regression before any CLI output or writeback. */
|
|
21
|
+
export declare function isPrivateExecutionPublicEnvelope(value: unknown): boolean;
|
|
22
|
+
export interface PrivateExecutionPublicBindingV1 {
|
|
23
|
+
readonly projectId: string;
|
|
24
|
+
readonly commandId: string;
|
|
25
|
+
readonly stepId: string;
|
|
26
|
+
readonly graphRevision: string;
|
|
27
|
+
readonly generationId: string;
|
|
28
|
+
readonly inputSha256: string;
|
|
29
|
+
readonly hostKind: 'codex-cli';
|
|
30
|
+
readonly hostVersion: string;
|
|
31
|
+
}
|
|
32
|
+
export interface PrivateExecutionPublicStepBindingV2 {
|
|
33
|
+
readonly schemaVersion: 2;
|
|
34
|
+
readonly authorityKind: 'state-snapshot';
|
|
35
|
+
readonly projectId: string;
|
|
36
|
+
readonly commandId: string;
|
|
37
|
+
readonly stepId: string;
|
|
38
|
+
readonly storyId: string;
|
|
39
|
+
readonly stateSnapshotSha256: string;
|
|
40
|
+
readonly generationId: string;
|
|
41
|
+
readonly inputSha256: string;
|
|
42
|
+
readonly hostKind: 'codex-cli';
|
|
43
|
+
readonly hostVersion: string;
|
|
44
|
+
}
|
|
45
|
+
export type PrivateExecutionPublicBinding = PrivateExecutionPublicBindingV1 | PrivateExecutionPublicStepBindingV2;
|
|
46
|
+
export interface PrivateExecutionDescriptorV1 {
|
|
47
|
+
readonly schemaVersion: 1;
|
|
48
|
+
readonly leaseId: string;
|
|
49
|
+
readonly materialSha256: string;
|
|
50
|
+
readonly byteLength: number;
|
|
51
|
+
readonly expiresAt: string;
|
|
52
|
+
readonly delivery: 'private-one-time';
|
|
53
|
+
readonly publicSafe: true;
|
|
54
|
+
readonly binding: PrivateExecutionPublicBindingV1;
|
|
55
|
+
}
|
|
56
|
+
export interface PrivateExecutionDescriptorV2 extends Omit<PrivateExecutionDescriptorV1, 'schemaVersion' | 'binding'> {
|
|
57
|
+
readonly schemaVersion: 2;
|
|
58
|
+
readonly binding: PrivateExecutionPublicStepBindingV2;
|
|
59
|
+
}
|
|
60
|
+
export type PrivateExecutionDescriptor = PrivateExecutionDescriptorV1 | PrivateExecutionDescriptorV2;
|
|
61
|
+
export declare function privateExecutionStateSnapshotSha256(stateSnapshot: unknown): string;
|
|
62
|
+
export declare function parsePrivateExecutionDescriptor(value: unknown, expected?: Partial<PrivateExecutionPublicBindingV1 & PrivateExecutionPublicStepBindingV2>): PrivateExecutionDescriptor;
|
|
63
|
+
export declare function verifyPrivateExecutionMaterial(descriptor: PrivateExecutionDescriptor, material: unknown, nowMs?: number): string;
|
|
64
|
+
export interface PrivateExecutionDeliveryResponseV1 {
|
|
65
|
+
readonly schemaVersion: 1;
|
|
66
|
+
readonly material: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The transport implementation must keep request and response bodies in memory.
|
|
70
|
+
* No retry is safe after a one-time lease may have been consumed.
|
|
71
|
+
*/
|
|
72
|
+
export declare function consumePrivateExecutionDelivery(rawDescriptor: unknown, expected: Partial<PrivateExecutionPublicBindingV1 & PrivateExecutionPublicStepBindingV2>, postOnce: (body: {
|
|
73
|
+
readonly leaseId: string;
|
|
74
|
+
} & PrivateExecutionPublicBinding) => Promise<unknown>, nowMs?: number): Promise<string>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{createHash as h}from"node:crypto";const u=`# Neocortex private execution pending
|
|
2
|
+
|
|
3
|
+
The authorized Codex CLI executor must consume the one-time delivery and produce a physical receipt.`;function I(i){if(!i||typeof i!="object"||Array.isArray(i))return!1;const o=i,t=o.metadata;if(Object.keys(o).sort().join(",")!=="instructions,metadata"||o.instructions!==u||!t||typeof t!="object"||Array.isArray(t))return!1;const e=t,s=e.privateExecution;let r;try{r=y(s)}catch{return!1}if(r.schemaVersion===2)return Object.keys(e).sort().join(",")===["mode","storyId","stepId","resolvedTrigger","privateExecution"].sort().join(",")&&(e.mode==="step"&&e.resolvedTrigger==="research"&&r.binding.commandId==="research"||e.mode==="pipeline"&&e.resolvedTrigger==="exec"&&r.binding.commandId==="exec")&&e.storyId===r.binding.storyId&&e.stepId===r.binding.stepId;const a=e.privateExecutionRootAction,c=["mode","storyId","stepId","resolvedTrigger","gitLifecycleGraphAuthority","privateExecution",...a===void 0?[]:["privateExecutionRootAction"]],p=e.gitLifecycleGraphAuthority,d=p&&typeof p=="object"&&!Array.isArray(p)?p:void 0,n=a&&typeof a=="object"&&!Array.isArray(a)?a:void 0;return Object.keys(e).sort().join(",")===c.sort().join(",")&&e.mode==="yolo"&&e.resolvedTrigger==="yolo"&&typeof e.storyId=="string"&&typeof e.stepId=="string"&&!!d&&d.storyId===e.storyId&&d.graphRevision===r.binding.graphRevision&&r.binding.commandId==="yolo"&&r.binding.stepId===e.stepId&&(a===void 0||!!n&&Object.keys(n).sort().join(",")===["schemaVersion","action","storyId","executionBranch","graphRevision","publicSafe",...n.action==="checkpoint-epic-story"?["stepId"]:[]].sort().join(",")&&n.schemaVersion===1&&(n.action==="prepare-epic-checkout"||n.action==="checkpoint-epic-story")&&(n.action!=="checkpoint-epic-story"||n.stepId===e.stepId)&&n.publicSafe===!0&&n.storyId===e.storyId&&n.storyId===d.storyId&&n.executionBranch===d.executionBranch&&n.graphRevision===d.graphRevision)}function m(i){return h("sha256").update("private-step-state-v1\0").update(JSON.stringify(i)).digest("hex")}function y(i,o){if(!i||typeof i!="object"||Array.isArray(i))throw new Error("private-execution-descriptor-invalid");const t=i,e=t.binding,s=t.schemaVersion===2,r=s?["schemaVersion","authorityKind","projectId","commandId","stepId","storyId","stateSnapshotSha256","generationId","inputSha256","hostKind","hostVersion"]:["commandId","generationId","graphRevision","hostKind","hostVersion","inputSha256","projectId","stepId"];if(Object.keys(t).sort().join(",")!==["schemaVersion","leaseId","materialSha256","byteLength","expiresAt","delivery","publicSafe","binding"].sort().join(",")||t.schemaVersion!==1&&!s||t.delivery!=="private-one-time"||t.publicSafe!==!0||typeof t.leaseId!="string"||!/^px_[a-f0-9]{48}$/.test(t.leaseId)||typeof t.materialSha256!="string"||!/^[a-f0-9]{64}$/.test(t.materialSha256)||!Number.isSafeInteger(t.byteLength)||t.byteLength<1||t.byteLength>256*1024||typeof t.expiresAt!="string"||!Number.isFinite(Date.parse(t.expiresAt))||!e||Object.keys(e).sort().join(",")!==r.sort().join(",")||Object.entries(e).some(([a,c])=>a!=="schemaVersion"&&(typeof c!="string"||c.length<1||c.length>256))||!/^[a-f0-9]{64}$/.test(String(e.inputSha256))||e.hostKind!=="codex-cli"||s&&(e.schemaVersion!==2||e.authorityKind!=="state-snapshot"||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(String(e.storyId))||!/^[a-f0-9]{64}$/.test(String(e.stateSnapshotSha256)))||o&&Object.entries(o).some(([a,c])=>e[a]!==c))throw new Error("private-execution-descriptor-invalid");return t}function g(i,o,t=Date.now()){if(typeof o!="string"||t>=Date.parse(i.expiresAt)||Buffer.byteLength(o,"utf8")!==i.byteLength||h("sha256").update(o,"utf8").digest("hex")!==i.materialSha256)throw new Error("private-execution-material-invalid");return o}async function l(i,o,t,e=Date.now()){const s=y(i,o);if(e>=Date.parse(s.expiresAt))throw new Error("private-execution-material-expired");const r=await t({leaseId:s.leaseId,...s.binding});if(!r||typeof r!="object"||Array.isArray(r)||Object.keys(r).sort().join(",")!=="material,schemaVersion"||r.schemaVersion!==1)throw new Error("private-execution-delivery-invalid");return g(s,r.material,Math.max(e,Date.now()))}export{u as PRIVATE_EXECUTION_PUBLIC_INSTRUCTION_V1,l as consumePrivateExecutionDelivery,I as isPrivateExecutionPublicEnvelope,y as parsePrivateExecutionDescriptor,m as privateExecutionStateSnapshotSha256,g as verifyPrivateExecutionMaterial};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PrivateYoloIsolatedWorkspaceV1 } from './isolated-workspace.js';
|
|
2
|
+
export interface PrivateYoloIsolatedAdmissionV1 {
|
|
3
|
+
readonly schemaVersion: 1;
|
|
4
|
+
readonly outcome: 'admitted-unverified';
|
|
5
|
+
readonly baseSha: string;
|
|
6
|
+
readonly executionBranch: string;
|
|
7
|
+
readonly changedPaths: readonly string[];
|
|
8
|
+
readonly patchSha256: string;
|
|
9
|
+
}
|
|
10
|
+
/** A persisted snapshot must still match both physical checkouts before reuse. */
|
|
11
|
+
export declare function verifyPrivateYoloSnapshotBoundary(workspace: PrivateYoloIsolatedWorkspaceV1, frozenPaths: readonly string[], snapshotSha: string): void;
|
|
12
|
+
/** Bind one-shot admission to the physically verified C01 claim and graph. */
|
|
13
|
+
export declare function admitPrivateYoloFrozenWorkspace(workspace: PrivateYoloIsolatedWorkspaceV1, storyId: string, graphRevision: string, snapshotSha?: string): Promise<PrivateYoloIsolatedAdmissionV1>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{execFileSync as I,spawnSync as T}from"node:child_process";import{createHash as N}from"node:crypto";import{existsSync as O,lstatSync as u,readFileSync as y,realpathSync as v}from"node:fs";import{isAbsolute as E,join as f,relative as b,sep as A}from"node:path";import{readPrivateYoloFrozenWriteSet as H,verifyPrivateYoloCandidateWriteSet as F,verifyPrivateYoloCleanBaseline as p}from"./clean-baseline.js";const l=16*1024*1024,g=1024;function S(){const t={...process.env};for(const e of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete t[e];return t}function h(t,e){return I("git",[...e],{cwd:t,env:S(),stdio:["ignore","pipe","pipe"],timeout:3e4,maxBuffer:l})}function a(t,e){return h(t,e).toString("utf8").trim()}function d(t,e=!1){return h(t,["status","--porcelain=v1","-z","--untracked-files=all",...e?["--ignored=matching"]:[]])}function x(t){return!!t&&!E(t)&&!t.includes("\\")&&!t.includes("\0")&&!t.split("/").some(e=>!e||e==="."||e===".."||e===".git")}function D(t,e){const r=e.split("/");let o=t;for(const n of r.slice(0,-1)){o=f(o,n);try{const i=u(o);if(!i.isDirectory()||i.isSymbolicLink())throw new Error("path-boundary")}catch(i){if(i.code==="ENOENT")return;throw i}}try{const n=u(f(t,e));if(!n.isFile()||n.isSymbolicLink()||n.size>l)throw new Error("path-boundary")}catch(n){if(n.code!=="ENOENT")throw n}}function B(t,e=!1){const r=[],o=[];for(const n of t.toString("utf8").split("\0").filter(Boolean)){if(n.length<4||n[2]!==" ")throw new Error("status-invalid");const i=n.slice(0,2),s=n.slice(3);if(!x(s)||i!=="??"&&i!==" M"&&i!==" D")throw new Error("status-invalid");r.push(s),i==="??"&&o.push(s)}if(!e&&r.length===0||r.length>g||new Set(r).size!==r.length)throw new Error("status-invalid");return{paths:r.sort(),untracked:o.sort()}}function C(t,e,r,o){const n=h(e,["ls-tree","-z",r,"--",o]).toString("utf8");if(!n)try{return u(f(t,o)),!1}catch(s){return s.code==="ENOENT"}const i=/^([0-7]{6}) blob [a-f0-9]{40,64}\t([^\0]+)\0$/.exec(n);if(!i||i[2]!==o||!["100644","100755"].includes(i[1]))return!1;try{const s=u(f(t,o));return!s.isFile()||s.isSymbolicLink()||s.size>l||!!(s.mode&73)!=(i[1]==="100755")?!1:y(f(t,o)).equals(h(e,["show",`${r}:${o}`]))}catch{return!1}}function R(t,e,r,o){const n=new Set(o);return B(d(t),!0).paths.every(s=>n.has(s))&&o.every(s=>C(t,e,r,s))}function L(t,e){const r=T("git",["diff","--no-index","--binary","--no-ext-diff","--","/dev/null",e],{cwd:t,env:S(),encoding:"buffer",timeout:3e4,maxBuffer:l});if(r.error||r.status!==1||!Buffer.isBuffer(r.stdout)||r.stdout.byteLength===0)throw new Error("patch-invalid");return r.stdout}function _(t,e,r){const o=T("git",["apply",...r?["--check"]:[],"--binary","-"],{cwd:t,env:S(),input:e,encoding:"buffer",timeout:3e4,maxBuffer:l});if(o.error||o.status!==0)throw new Error("apply-failed")}function w(t,e,r){const o=f(t,r),n=f(e,r);try{const i=u(o),s=u(n);return i.isFile()&&s.isFile()&&(i.mode&73)===(s.mode&73)&&y(o).equals(y(n))}catch(i){if(i.code!=="ENOENT")return!1;try{return u(o),!1}catch(s){if(s.code!=="ENOENT")return!1}try{return u(n),!1}catch(s){return s.code==="ENOENT"}}}function V(t,e,r){try{if(process.platform!=="linux"||t.schemaVersion!==1||!E(t.sourceRoot)||!E(t.workspacePath)||v(t.sourceRoot)!==t.sourceRoot||v(t.workspacePath)!==t.workspacePath||!u(t.workspacePath).isDirectory()||(u(t.workspacePath).mode&63)!==0||b(t.sourceRoot,t.workspacePath)===""||b(t.sourceRoot,t.workspacePath).split(A)[0]!==".."||!/^[a-f0-9]{40,64}$/.test(t.baseSha)||!/^[a-f0-9]{40,64}$/.test(r)||a(t.sourceRoot,["rev-parse","--show-toplevel"])!==t.sourceRoot||a(t.workspacePath,["rev-parse","--show-toplevel"])!==t.workspacePath||a(t.sourceRoot,["rev-parse","HEAD"])!==t.baseSha||a(t.workspacePath,["rev-parse","HEAD"])!==r||a(t.sourceRoot,["symbolic-ref","--short","HEAD"])!==t.executionBranch||a(t.workspacePath,["symbolic-ref","--short","HEAD"])!==t.executionBranch||O(f(t.workspacePath,".git","objects","info","alternates"))||d(t.workspacePath,!0).byteLength!==0||e.length===0||e.length>g||e.some(o=>!x(o))||new Set(e).size!==e.length)throw new Error("boundary-invalid");if(h(t.workspacePath,["merge-base","--is-ancestor",t.baseSha,r]),!R(t.sourceRoot,t.workspacePath,r,e))throw new Error("boundary-raced")}catch{throw new Error("private-execution-isolated-snapshot-unverified")}}function G(t,e,r){try{if(process.platform!=="linux"||t.schemaVersion!==1||!E(t.sourceRoot)||!E(t.workspacePath)||v(t.sourceRoot)!==t.sourceRoot||v(t.workspacePath)!==t.workspacePath||!u(t.workspacePath).isDirectory()||(u(t.workspacePath).mode&63)!==0||b(t.sourceRoot,t.workspacePath)===""||b(t.sourceRoot,t.workspacePath).split(A)[0]!==".."||a(t.sourceRoot,["rev-parse","--show-toplevel"])!==t.sourceRoot||a(t.workspacePath,["rev-parse","--show-toplevel"])!==t.workspacePath||a(t.sourceRoot,["rev-parse","HEAD"])!==t.baseSha||!/^[a-f0-9]{40,64}$/.test(r)||a(t.workspacePath,["rev-parse","HEAD"])!==r||a(t.sourceRoot,["symbolic-ref","--short","HEAD"])!==t.executionBranch||a(t.workspacePath,["symbolic-ref","--short","HEAD"])!==t.executionBranch||e.length===0||e.length>g||e.some(c=>!x(c))||new Set(e).size!==e.length)throw new Error("authority-invalid");if(h(t.workspacePath,["merge-base","--is-ancestor",t.baseSha,r]),!R(t.sourceRoot,t.workspacePath,r,e))throw new Error("source-snapshot-mismatch");const o=d(t.workspacePath,!0),n=B(o),i=new Set(e);if(n.paths.some(c=>!i.has(c)))throw new Error("path-unclaimed");for(const c of n.paths)D(t.workspacePath,c),D(t.sourceRoot,c);const P=[h(t.workspacePath,["diff","--binary","--no-ext-diff","--no-textconv","HEAD","--"]),...n.untracked.map(c=>L(t.workspacePath,c))],m=Buffer.concat(P.map(c=>Buffer.concat([c,Buffer.from(`
|
|
2
|
+
`)])));if(m.byteLength===0||m.byteLength>l||!d(t.workspacePath,!0).equals(o)||!R(t.sourceRoot,t.workspacePath,r,e))throw new Error("patch-raced");if(_(t.sourceRoot,m,!0),!d(t.workspacePath,!0).equals(o)||!R(t.sourceRoot,t.workspacePath,r,e))throw new Error("patch-raced");if(_(t.sourceRoot,m,!1),B(d(t.sourceRoot),!0).paths.some(c=>!i.has(c))||e.some(c=>!w(t.workspacePath,t.sourceRoot,c))||a(t.sourceRoot,["rev-parse","HEAD"])!==t.baseSha||a(t.sourceRoot,["symbolic-ref","--short","HEAD"])!==t.executionBranch)throw new Error("admission-raced");return Object.freeze({schemaVersion:1,outcome:"admitted-unverified",baseSha:t.baseSha,executionBranch:t.executionBranch,changedPaths:Object.freeze([...n.paths]),patchSha256:N("sha256").update(m).digest("hex")})}catch{throw new Error("private-execution-isolated-admission-unverified")}}async function X(t,e,r,o=t.baseSha){try{const n=await H(t.sourceRoot,e,t.executionBranch,r),i=f(t.workspacePath,".neocortex","state.json"),s=u(i);if(!s.isFile()||s.isSymbolicLink()||s.size>l)throw new Error("candidate-state-invalid");F(y(i,"utf8"),e,n);const P=G(t,n,o);return await p(t.sourceRoot,e,t.executionBranch,r),P}catch{throw new Error("private-execution-isolated-admission-unverified")}}export{X as admitPrivateYoloFrozenWorkspace,V as verifyPrivateYoloSnapshotBoundary};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type PrivateYoloIsolatedAdmissionV1 } from './isolated-admission.js';
|
|
2
|
+
import { type PrivateYoloIsolatedWorkspaceV1 } from './isolated-workspace.js';
|
|
3
|
+
export interface PrivateYoloIsolatedSessionV1 {
|
|
4
|
+
readonly schemaVersion: 1;
|
|
5
|
+
readonly kind: 'private-yolo-isolated-session';
|
|
6
|
+
readonly storyId: string;
|
|
7
|
+
readonly initialGraphRevision: string;
|
|
8
|
+
readonly graphRevision: string;
|
|
9
|
+
readonly graphHistory: readonly string[];
|
|
10
|
+
readonly setupSessionId: string;
|
|
11
|
+
readonly workspace: PrivateYoloIsolatedWorkspaceV1;
|
|
12
|
+
readonly snapshotSha: string;
|
|
13
|
+
readonly sequence: number;
|
|
14
|
+
readonly lastPatchSha256: string | null;
|
|
15
|
+
}
|
|
16
|
+
/** Reserve one clone for the exact C01 session, without launching an agent. */
|
|
17
|
+
export declare function beginPrivateYoloIsolatedSession(workspace: PrivateYoloIsolatedWorkspaceV1, storyId: string, graphRevision: string): Promise<PrivateYoloIsolatedSessionV1>;
|
|
18
|
+
/** Require a previously admitted patch before accepting a new server graph. */
|
|
19
|
+
export declare function reconcilePrivateYoloIsolatedSession(projectRoot: string, storyId: string, graphRevision: string): Promise<PrivateYoloIsolatedSessionV1>;
|
|
20
|
+
/** Reuse the pinned clone, or create it once after the physical C01 setup. */
|
|
21
|
+
export declare function ensurePrivateYoloIsolatedSession(projectRoot: string, storyId: string, graphRevision: string, workspaceParent?: string): Promise<PrivateYoloIsolatedSessionV1>;
|
|
22
|
+
/** Resume only the same private clone, snapshot and live C01 graph/session. */
|
|
23
|
+
export declare function resumePrivateYoloIsolatedSession(projectRoot: string, storyId: string, graphRevision: string): Promise<PrivateYoloIsolatedSessionV1>;
|
|
24
|
+
/** Admit one agent delta and durably pin the clone's next root-owned snapshot. */
|
|
25
|
+
export declare function admitPrivateYoloIsolatedSessionStep(projectRoot: string, storyId: string, graphRevision: string): Promise<{
|
|
26
|
+
readonly session: PrivateYoloIsolatedSessionV1;
|
|
27
|
+
readonly admission: PrivateYoloIsolatedAdmissionV1;
|
|
28
|
+
}>;
|
|
29
|
+
export interface PrivateYoloStagedBundleV1 {
|
|
30
|
+
readonly schemaVersion: 1;
|
|
31
|
+
readonly outcome: 'staged-unverified';
|
|
32
|
+
readonly snapshotSha: string;
|
|
33
|
+
readonly bundleSha256: string;
|
|
34
|
+
readonly changedPaths: readonly string[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Root-owned C08 staging. The agent never gets index authority: the source
|
|
38
|
+
* must still equal the pinned clone, and the staged bytes must equal its
|
|
39
|
+
* immutable base-to-snapshot patch. QA and checkpoint remain separate gates.
|
|
40
|
+
*/
|
|
41
|
+
export declare function stagePrivateYoloIsolatedSessionBundle(projectRoot: string, storyId: string, graphRevision: string): Promise<PrivateYoloStagedBundleV1>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{execFileSync as k,spawnSync as A}from"node:child_process";import{createHash as x}from"node:crypto";import{existsSync as q,mkdirSync as C,readFileSync as D}from"node:fs";import{homedir as z}from"node:os";import{join as T,resolve as p}from"node:path";import{acquireGitLifecyclePhysicalIntegrationLock as N,assertGitLifecyclePrivateFile as B,ensureGitLifecyclePrivateChildDirectory as j,gitLifecycleRuntimeDirectory as H,readGitLifecycleRuntimeSync as L,releaseGitLifecyclePhysicalIntegrationLock as $}from"../git/git-lifecycle-store.js";import{anchoredAtomicWriteFile as Y}from"../git/secure-filesystem-boundary.js";import{readPrivateYoloFrozenWriteSet as d,readPrivateYoloFrozenWriteSetForTransition as F}from"./clean-baseline.js";import{admitPrivateYoloFrozenWorkspace as M,verifyPrivateYoloSnapshotBoundary as m}from"./isolated-admission.js";import{preparePrivateYoloIsolatedWorkspace as J}from"./isolated-workspace.js";function l(n,t){const e={...process.env};for(const s of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete e[s];return k("git",[...t],{cwd:n,env:e,encoding:"utf8",stdio:["ignore","pipe","pipe"],timeout:3e4,maxBuffer:16*1024*1024}).trim()}function y(n,t){const e={...process.env};for(const s of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete e[s];return k("git",[...t],{cwd:n,env:e,stdio:["ignore","pipe","pipe"],timeout:3e4,maxBuffer:16*1024*1024})}function b(n,t){const e={...process.env};for(const i of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete e[i];const s=A("git",[...t],{cwd:n,env:e,stdio:"ignore",timeout:3e4});if(s.error||s.signal)throw new Error("git-unverified");return s.status===0}async function P(n,t){const e=await H(n),s=await j(e,"private-execution"),i=`session-${x("sha256").update(t).digest("hex")}.json`;return{parent:s,name:i,path:T(s,i)}}function h(n,t){const e=t.split(".")[0],i=L(n,{required:!0}).epics[e]?.branch_lease,o=i&&typeof i=="object"&&!Array.isArray(i)?i:void 0,r=o?.sessionId;if(o?.ownerStoryId!==t||typeof r!="string"||!/^setup-[a-f0-9]{64}$/.test(r)||r!==o.idempotencyKey)throw new Error("session-lease-invalid");return r}function W(n){const t=JSON.parse(n);if(!t||typeof t!="object"||Array.isArray(t))throw new Error("session-invalid");const e=t,s=e.workspace;if(Object.keys(e).sort().join(",")!==["schemaVersion","kind","storyId","initialGraphRevision","graphRevision","graphHistory","setupSessionId","workspace","snapshotSha","sequence","lastPatchSha256"].sort().join(",")||e.schemaVersion!==1||e.kind!=="private-yolo-isolated-session"||typeof e.storyId!="string"||!/^[A-Za-z][A-Za-z0-9_-]*\.[A-Za-z0-9._-]+$/.test(e.storyId)||typeof e.initialGraphRevision!="string"||!/^[a-f0-9]{64}$/.test(e.initialGraphRevision)||typeof e.graphRevision!="string"||!/^[a-f0-9]{64}$/.test(e.graphRevision)||!Array.isArray(e.graphHistory)||e.graphHistory.length<1||e.graphHistory.length>65||e.graphHistory.some(o=>typeof o!="string"||!/^[a-f0-9]{64}$/.test(o))||new Set(e.graphHistory).size!==e.graphHistory.length||e.graphHistory[0]!==e.initialGraphRevision||e.graphHistory[e.graphHistory.length-1]!==e.graphRevision||typeof e.setupSessionId!="string"||!/^setup-[a-f0-9]{64}$/.test(e.setupSessionId)||typeof e.snapshotSha!="string"||!/^[a-f0-9]{40,64}$/.test(e.snapshotSha)||!Number.isSafeInteger(e.sequence)||Number(e.sequence)<0||Number(e.sequence)>64||Number(e.sequence)===0&&e.initialGraphRevision!==e.graphRevision||Number(e.sequence)===0&&e.lastPatchSha256!==null||Number(e.sequence)>0&&e.lastPatchSha256===null||e.lastPatchSha256!==null&&(typeof e.lastPatchSha256!="string"||!/^[a-f0-9]{64}$/.test(e.lastPatchSha256))||!s||typeof s!="object"||Array.isArray(s))throw new Error("session-invalid");const i=s;if(Object.keys(i).sort().join(",")!==["schemaVersion","sourceRoot","workspacePath","baseSha","executionBranch"].sort().join(",")||i.schemaVersion!==1||typeof i.sourceRoot!="string"||typeof i.workspacePath!="string"||typeof i.baseSha!="string"||!/^[a-f0-9]{40,64}$/.test(i.baseSha)||typeof i.executionBranch!="string"||!i.executionBranch)throw new Error("session-invalid");return e}async function f(n,t){const e=await P(n,t);if(q(e.path))return await B(e.path,e.parent),W(D(e.path,"utf8"))}async function v(n,t){const e=await P(n,t.storyId);await Y(e.parent,e.name,`${JSON.stringify(t)}
|
|
2
|
+
`)}async function E(n,t,e,s){const i=await N(n,{kind:"direct",storyId:t,sessionId:e,idempotencyKey:e,expiresAt:new Date(Date.now()+3e5).toISOString(),persistent:!1});if(!i.ok)throw new Error("private-execution-isolated-session-backpressure");try{return await s()}finally{if(!await $(i.path,i.owner))throw new Error("private-execution-isolated-session-lock-unverified")}}async function g(n,t,e,s){G(n,t,e,s);const i=await d(t,e,n.workspace.executionBranch,s);m(n.workspace,i,n.snapshotSha)}function G(n,t,e,s){if(n.storyId!==e||n.graphRevision!==s||n.workspace.sourceRoot!==t||n.setupSessionId!==h(t,e)||n.sequence===0&&n.snapshotSha!==n.workspace.baseSha||n.sequence>0&&n.snapshotSha===n.workspace.baseSha)throw new Error("session-binding-invalid")}async function ie(n,t,e){const s=p(n.sourceRoot);try{const i=h(s,t);return await E(s,t,i,async()=>{const o=await f(s,t);if(o){if(await g(o,s,t,e),o.workspace.workspacePath!==n.workspacePath)throw new Error("session-replacement-denied");return o}const r=await d(s,t,n.executionBranch,e);m(n,r,n.baseSha);const c=Object.freeze({schemaVersion:1,kind:"private-yolo-isolated-session",storyId:t,initialGraphRevision:e,graphRevision:e,graphHistory:[e],setupSessionId:i,workspace:n,snapshotSha:n.baseSha,sequence:0,lastPatchSha256:null});return await v(s,c),c})}catch{throw new Error("private-execution-isolated-session-unverified")}}async function R(n,t,e,s){if(n.graphRevision===s)return await g(n,t,e,s),n;if(n.storyId!==e||n.workspace.sourceRoot!==t||n.setupSessionId!==h(t,e)||n.sequence===0||n.lastPatchSha256===null||n.graphHistory.includes(s)||n.graphHistory.length>=65)throw new Error("session-graph-transition-invalid");const i=await F(t,e,n.workspace.executionBranch,n.initialGraphRevision,s);m(n.workspace,i,n.snapshotSha);const o=Object.freeze({...n,graphRevision:s,graphHistory:Object.freeze([...n.graphHistory,s])});return await v(t,o),await g(o,t,e,s),o}async function oe(n,t,e){const s=p(n);try{const i=h(s,t);return await E(s,t,i,async()=>{const o=await f(s,t);if(!o)throw new Error("session-missing");return R(o,s,t,e)})}catch{throw new Error("private-execution-isolated-session-unverified")}}async function ae(n,t,e,s){const i=p(n);try{const o=h(i,t);return await E(i,t,o,async()=>{const r=await f(i,t);if(r)return R(r,i,t,e);const c=s??T(z(),".local","share","neocortex","private-yolo-workspaces");s===void 0&&C(c,{recursive:!0,mode:448});const a=J(i,c),u=await d(i,t,a.executionBranch,e);m(a,u,a.baseSha);const w=Object.freeze({schemaVersion:1,kind:"private-yolo-isolated-session",storyId:t,initialGraphRevision:e,graphRevision:e,graphHistory:[e],setupSessionId:o,workspace:a,snapshotSha:a.baseSha,sequence:0,lastPatchSha256:null});return await v(i,w),w})}catch{throw new Error("private-execution-isolated-session-unverified")}}async function re(n,t,e){const s=p(n);try{const i=await f(s,t);if(!i)throw new Error("session-missing");return await g(i,s,t,e),i}catch{throw new Error("private-execution-isolated-session-unverified")}}async function ce(n,t,e){const s=p(n);try{const i=h(s,t);return await E(s,t,i,async()=>{const o=await f(s,t);if(!o)throw new Error("session-missing");G(o,s,t,e);const r=await M(o.workspace,t,e,o.snapshotSha);l(o.workspace.workspacePath,["add","-A","--",...r.changedPaths]),l(o.workspace.workspacePath,["-c","core.hooksPath=/dev/null","-c","commit.gpgsign=false","-c","user.name=Neocortex Private Session","-c","user.email=private-session@neocortex.invalid","commit","-q","-m",`private snapshot ${t} ${o.sequence+1}`]);const c=l(o.workspace.workspacePath,["rev-parse","HEAD"]),a=await d(s,t,o.workspace.executionBranch,e);m(o.workspace,a,c);const u=Object.freeze({...o,snapshotSha:c,sequence:o.sequence+1,lastPatchSha256:r.patchSha256});return await v(s,u),{session:u,admission:r}})}catch{throw new Error("private-execution-isolated-session-unverified")}}async function he(n,t,e){const s=p(n);try{const i=h(s,t);return await E(s,t,i,async()=>{const o=await f(s,t);if(!o||o.sequence<1)throw new Error("session-incomplete");await g(o,s,t,e);const r=await d(s,t,o.workspace.executionBranch,e),c=o.workspace.workspacePath,a=y(c,["diff","--name-only","-z",o.workspace.baseSha,o.snapshotSha]).toString("utf8").split("\0").filter(Boolean).sort(),u=[".neocortex/state.json",`docs/stories/${t}.story.md`,`.neocortex/stories/${t}/qa-gate-result.json`,`.neocortex/stories/${t}/validation-evidence.md`,`.neocortex/stories/${t}/review.md`];if(a.length===0||a.length>1024||new Set(a).size!==a.length||a.some(S=>!r.includes(S))||u.some(S=>!a.includes(S)))throw new Error("bundle-incomplete");if(!b(s,["diff","--cached","--quiet"])||y(s,["ls-files","-u","-z"]).byteLength!==0)throw new Error("index-not-clean");const w=y(c,["diff","--binary","--full-index",o.workspace.baseSha,o.snapshotSha]);if(w.byteLength===0)throw new Error("bundle-empty");l(s,["add","-A","--",...a]);const I=y(s,["diff","--cached","--binary","--full-index"]),_=y(s,["diff","--cached","--name-only","-z"]).toString("utf8").split("\0").filter(Boolean).sort();if(!I.equals(w)||_.length!==a.length||_.some((S,O)=>S!==a[O])||!b(s,["diff","--quiet"])||l(s,["rev-parse","HEAD"])!==o.workspace.baseSha||l(s,["symbolic-ref","--quiet","--short","HEAD"])!==o.workspace.executionBranch)throw new Error("bundle-raced");return Object.freeze({schemaVersion:1,outcome:"staged-unverified",snapshotSha:o.snapshotSha,bundleSha256:x("sha256").update(I).digest("hex"),changedPaths:Object.freeze(a)})})}catch{throw new Error("private-execution-root-stage-unverified")}}export{ce as admitPrivateYoloIsolatedSessionStep,ie as beginPrivateYoloIsolatedSession,ae as ensurePrivateYoloIsolatedSession,oe as reconcilePrivateYoloIsolatedSession,re as resumePrivateYoloIsolatedSession,he as stagePrivateYoloIsolatedSessionBundle};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface PrivateYoloIsolatedWorkspaceV1 {
|
|
2
|
+
readonly schemaVersion: 1;
|
|
3
|
+
readonly sourceRoot: string;
|
|
4
|
+
readonly workspacePath: string;
|
|
5
|
+
readonly baseSha: string;
|
|
6
|
+
readonly executionBranch: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Build a separate object store and index from a clean, committed checkout.
|
|
10
|
+
* The caller must retain the workspace until its bytes are independently
|
|
11
|
+
* admitted into the root; this function never stages, commits, or deletes it.
|
|
12
|
+
*/
|
|
13
|
+
export declare function preparePrivateYoloIsolatedWorkspace(projectRoot: string, workspaceParent: string): PrivateYoloIsolatedWorkspaceV1;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{execFileSync as m}from"node:child_process";import{chmodSync as I,existsSync as y,lstatSync as p,mkdtempSync as d,realpathSync as u}from"node:fs";import{isAbsolute as l,join as f,resolve as E}from"node:path";function a(t,i){const e={...process.env};for(const r of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete e[r];return m("git",[...i],{cwd:t,env:e,stdio:["ignore","pipe","pipe"],timeout:3e4,maxBuffer:16*1024*1024})}function n(t,i){return a(t,i).toString("utf8").trim()}function h(t,i,e){return n(t,["rev-parse","HEAD"])===i&&n(t,["symbolic-ref","--quiet","--short","HEAD"])===e&&a(t,["status","--porcelain=v1","-z","--untracked-files=all"]).byteLength===0}function D(t,i){let e,r;try{if(process.platform!=="linux"||typeof process.getuid!="function"||!l(t)||!l(i))throw new Error("path-invalid");if(e=E(t),r=E(i),u(e)!==e||!p(e).isDirectory()||u(r)!==r||!p(r).isDirectory()||p(r).uid!==process.getuid()||(p(r).mode&18)!==0||n(e,["rev-parse","--show-toplevel"])!==e)throw new Error("path-invalid");const s=n(e,["rev-parse","HEAD"]),c=n(e,["symbolic-ref","--quiet","--short","HEAD"]);if(!/^[a-f0-9]{40,64}$/.test(s)||!c||!h(e,s,c))throw new Error("source-dirty");const o=d(f(r,"p222-private-yolo-"));if(I(o,448),a(o,["init","-q"]),a(o,["fetch","-q","--no-tags","--depth=1",e,s]),a(o,["checkout","-q","-b",c,"FETCH_HEAD"]),!h(e,s,c)||n(o,["rev-parse","HEAD"])!==s||n(o,["symbolic-ref","--quiet","--short","HEAD"])!==c||a(o,["status","--porcelain=v1","-z","--untracked-files=all"]).byteLength!==0||y(f(o,".git","objects","info","alternates")))throw new Error("physical-mismatch");return Object.freeze({schemaVersion:1,sourceRoot:e,workspacePath:o,baseSha:s,executionBranch:c})}catch{throw new Error("private-execution-isolated-workspace-unverified")}}export{D as preparePrivateYoloIsolatedWorkspace};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PrivateExecutionCheckpointRootActionV1 } from './delivery.js';
|
|
2
|
+
export interface PrivateRootCheckpointReceiptV1 {
|
|
3
|
+
readonly schemaVersion: 1;
|
|
4
|
+
readonly outcome: 'checkpoint-validated';
|
|
5
|
+
readonly storyId: string;
|
|
6
|
+
readonly headSha: string;
|
|
7
|
+
readonly publicSafe: true;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The agent cannot write `.git`. The root stages only the exact frozen C01
|
|
11
|
+
* claim admitted from the pinned clone, then uses the existing two-phase
|
|
12
|
+
* physical checkpoint authority. A failed post-commit checkpoint is never
|
|
13
|
+
* silently recovered.
|
|
14
|
+
*/
|
|
15
|
+
export declare function runPrivateYoloRootCheckpoint(projectRoot: string, action: PrivateExecutionCheckpointRootActionV1): Promise<PrivateRootCheckpointReceiptV1>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{execFileSync as l}from"node:child_process";import{createHash as h}from"node:crypto";import{resolve as I}from"node:path";import{beginDirectYoloStoryCommit as m,finalizeDirectYoloStoryCheckpoint as v,issueDirectYoloSetupLeaseHandoff as y}from"../git/direct-yolo-checkpoint.js";import{verifyPrivateYoloCleanBaseline as E}from"./clean-baseline.js";import{stagePrivateYoloIsolatedSessionBundle as g}from"./isolated-session.js";function n(a,e){const t={...process.env};for(const i of["GIT_DIR","GIT_WORK_TREE","GIT_INDEX_FILE","GIT_OBJECT_DIRECTORY","GIT_ALTERNATE_OBJECT_DIRECTORIES","GIT_COMMON_DIR","GIT_NAMESPACE","GIT_CEILING_DIRECTORIES"])delete t[i];return l("git",[...e],{cwd:a,env:t,stdio:["ignore","pipe","pipe"],timeout:3e4,maxBuffer:16*1024*1024})}async function T(a,e){const t=I(a);if(e.schemaVersion!==1||e.action!=="checkpoint-epic-story"||!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(e.storyId)||!/^[a-f0-9]{64}$/.test(e.graphRevision)||e.stepId!==`step-${h("sha256").update("step-c-08-commit-push").digest("hex").slice(0,8)}`||!/^[A-Za-z0-9][A-Za-z0-9._/-]{0,127}$/.test(e.executionBranch)||e.executionBranch.includes("..")||e.publicSafe!==!0)throw new Error("private-execution-root-checkpoint-invalid");await E(t,e.storyId,e.executionBranch,e.graphRevision);const i=await g(t,e.storyId,e.graphRevision),s=await y({projectRoot:t,storyId:e.storyId});if(!s.ok||s.value.bundleDigest!==i.bundleSha256)throw new Error("private-execution-root-checkpoint-handoff-denied");const o=await m({projectRoot:t,storyId:e.storyId});if(!o.ok)throw new Error("private-execution-root-checkpoint-begin-denied");if(o.value.graphRevision!==e.graphRevision||o.value.executionBranch!==e.executionBranch)throw new Error("private-execution-root-checkpoint-authority-drift");try{const r=n(t,["rev-parse","HEAD"]).toString("utf8").trim(),p=n(t,["symbolic-ref","--quiet","--short","HEAD"]).toString("utf8").trim(),u=n(t,["diff","--cached","--binary","--full-index"]),d=h("sha256").update(u).digest("hex");if(r!==o.value.baseSha||p!==o.value.executionBranch||d!==o.value.bundleDigest||d!==i.bundleSha256)throw new Error("private-execution-root-checkpoint-bundle-drift");n(t,["commit","-m",`fix(${e.storyId}): checkpoint direct yolo`,...o.value.trailers.flatMap(f=>["-m",f])])}catch(r){throw r instanceof Error&&r.message==="private-execution-root-checkpoint-bundle-drift"?r:new Error("private-execution-root-checkpoint-commit-failed")}const c=await v({projectRoot:t,storyId:e.storyId,push:!0});if(!c.ok)throw new Error("private-execution-root-checkpoint-finalize-denied");return Object.freeze({schemaVersion:1,outcome:"checkpoint-validated",storyId:e.storyId,headSha:c.value.headSha,publicSafe:!0})}export{T as runPrivateYoloRootCheckpoint};
|