@ornexus/neocortex 4.60.58 → 4.60.60
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 +241 -82
- package/install.ps1 +1 -1
- package/install.sh +1 -1
- package/package.json +6 -2
- package/packages/client/dist/cli.js +37 -4
- package/packages/client/dist/commands/architecture-answers.d.ts +26 -0
- package/packages/client/dist/commands/architecture-answers.js +7 -0
- package/packages/client/dist/commands/architecture-memory-terminal.d.ts +21 -0
- package/packages/client/dist/commands/architecture-memory-terminal.js +2 -0
- package/packages/client/dist/commands/architecture-root-binding.d.ts +2 -0
- package/packages/client/dist/commands/architecture-root-binding.js +1 -0
- package/packages/client/dist/commands/invoke.d.ts +43 -2
- package/packages/client/dist/commands/invoke.js +98 -70
- package/packages/client/dist/commands/legacy-story-branch.d.ts +10 -0
- package/packages/client/dist/commands/legacy-story-branch.js +1 -0
- package/packages/client/dist/commands/legacy-story-pr.d.ts +18 -0
- package/packages/client/dist/commands/legacy-story-pr.js +1 -0
- package/packages/client/dist/commands/planning-diagnosis.d.ts +4 -0
- package/packages/client/dist/commands/planning-diagnosis.js +1 -0
- package/packages/client/dist/commands/planning-generation.d.ts +2 -0
- package/packages/client/dist/commands/planning-generation.js +1 -0
- package/packages/client/dist/commands/planning-research.d.ts +3 -0
- package/packages/client/dist/commands/planning-research.js +1 -0
- package/packages/client/dist/commands/refresh-memory.d.ts +10 -0
- package/packages/client/dist/commands/refresh-memory.js +3 -1
- package/packages/client/dist/commands/story-checkpoint.d.ts +1 -1
- package/packages/client/dist/commands/story-checkpoint.js +1 -1
- package/packages/client/dist/config/profile-directory.d.ts +2 -0
- package/packages/client/dist/config/profile-directory.js +1 -0
- package/packages/client/dist/config/secure-config.js +5 -5
- package/packages/client/dist/continuity/runner-bootstrap-policy.d.ts +1 -1
- package/packages/client/dist/continuity/runner-bootstrap-policy.js +1 -1
- package/packages/client/dist/generated/command-registry.generated.d.ts +11 -11
- package/packages/client/dist/generated/command-registry.generated.js +1 -1
- package/packages/client/dist/generated/public-projections.generated.d.ts +20 -20
- package/packages/client/dist/generated/public-projections.generated.js +1 -1
- package/packages/client/dist/git/direct-yolo-checkpoint.d.ts +9 -0
- package/packages/client/dist/git/direct-yolo-checkpoint.js +4 -4
- package/packages/client/dist/git/git-lifecycle-step-ids.d.ts +5 -0
- package/packages/client/dist/git/git-lifecycle-step-ids.js +1 -1
- package/packages/client/dist/git/git-lifecycle-store.d.ts +16 -0
- package/packages/client/dist/git/git-lifecycle-store.js +9 -4
- package/packages/client/dist/git/legacy-story-branch-checkpoint.d.ts +38 -0
- package/packages/client/dist/git/legacy-story-branch-checkpoint.js +9 -0
- package/packages/client/dist/git/legacy-story-branch-setup.d.ts +56 -0
- package/packages/client/dist/git/legacy-story-branch-setup.js +4 -0
- package/packages/client/dist/git/legacy-story-pr.d.ts +514 -0
- package/packages/client/dist/git/legacy-story-pr.js +62 -0
- package/packages/client/dist/git/secure-filesystem-boundary.d.ts +2 -0
- package/packages/client/dist/git/secure-filesystem-boundary.js +34 -7
- package/packages/client/dist/machine/fingerprint.js +2 -2
- package/packages/client/dist/memory/project-memory-writer.js +17 -17
- package/packages/client/dist/memory/shared-project-memory-types.d.ts +23 -13
- package/packages/client/dist/memory/shared-project-memory-types.js +2 -2
- package/packages/client/dist/migrations/state-json.d.ts +23 -1
- package/packages/client/dist/migrations/state-json.js +4 -4
- package/packages/client/dist/private-execution/delivery.d.ts +131 -3
- package/packages/client/dist/private-execution/delivery.js +2 -2
- package/packages/client/dist/private-execution/isolated-admission.d.ts +28 -1
- package/packages/client/dist/private-execution/isolated-admission.js +11 -2
- package/packages/client/dist/private-execution/isolated-session.js +2 -2
- package/packages/client/dist/private-execution/isolated-workspace.d.ts +8 -0
- package/packages/client/dist/private-execution/isolated-workspace.js +1 -1
- package/packages/client/dist/private-execution/pact-consumer-runtime.d.ts +19 -0
- package/packages/client/dist/private-execution/pact-consumer-runtime.js +3 -0
- package/packages/client/dist/private-execution/pact-test-source.d.ts +9 -0
- package/packages/client/dist/private-execution/pact-test-source.js +1 -0
- package/packages/client/dist/private-execution/pact-toolchain.d.ts +37 -0
- package/packages/client/dist/private-execution/pact-toolchain.js +3 -0
- package/packages/client/dist/private-execution/pact-write-set.d.ts +24 -0
- package/packages/client/dist/private-execution/pact-write-set.js +1 -0
- package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.d.ts +38 -0
- package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.js +5 -0
- package/packages/client/dist/private-execution/planning-generation-checkpoint.d.ts +34 -0
- package/packages/client/dist/private-execution/planning-generation-checkpoint.js +4 -0
- package/packages/client/dist/private-execution/planning-research-checkpoint.d.ts +38 -0
- package/packages/client/dist/private-execution/planning-research-checkpoint.js +4 -0
- package/packages/client/dist/private-execution/ux-source-validation.d.ts +2 -0
- package/packages/client/dist/private-execution/ux-source-validation.js +1 -0
- package/packages/client/dist/private-execution/ux-write-set.d.ts +30 -0
- package/packages/client/dist/private-execution/ux-write-set.js +2 -0
- package/packages/client/dist/resolvers/remote-resolver.d.ts +5 -22
- package/packages/client/dist/resolvers/remote-resolver.js +1 -1
- package/packages/client/dist/runner/project-identity.js +1 -1
- package/packages/client/dist/runner/scheduler.d.ts +20 -0
- package/packages/client/dist/runner/scheduler.js +7 -7
- package/packages/client/dist/state/project-state-snapshot.js +1 -1
- package/packages/client/dist/yolo/change-evidence-collector.d.ts +8 -0
- package/packages/client/dist/yolo/change-evidence-collector.js +1 -1
- package/packages/client/dist/yolo/spec-envelope-collector.d.ts +2 -0
- package/packages/client/dist/yolo/spec-envelope-collector.js +3 -3
- package/packages/client/dist/yoloop/invoke-hooks.js +7 -7
- package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +15 -1
- package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +5 -1
- package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -1
- package/packages/shared/dist/generated/command-registry.generated.js +12 -10
- package/packages/shared/dist/generated/invocation-schema.generated.js +14 -6
- package/packages/shared/dist/generated/public-projections.generated.js +18 -18
- package/packages/shared/dist/invocation/index.d.ts +1 -1
- package/packages/shared/dist/merge-readiness/c12-remote-observation.js +80 -0
- package/packages/shared/dist/planning/diagnosis-state.js +143 -0
- package/packages/shared/dist/yoloop/branch-unit.js +23 -1
- 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
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
type Result<T> = {
|
|
2
|
+
readonly ok: true;
|
|
3
|
+
readonly value: T;
|
|
4
|
+
} | {
|
|
5
|
+
readonly ok: false;
|
|
6
|
+
readonly reasonCode: string;
|
|
7
|
+
};
|
|
8
|
+
type Issue = {
|
|
9
|
+
readonly number: number;
|
|
10
|
+
readonly title: string;
|
|
11
|
+
readonly state: string;
|
|
12
|
+
readonly url: string;
|
|
13
|
+
};
|
|
14
|
+
type IssueVerifier = (repository: string, number: number) => Promise<Issue>;
|
|
15
|
+
export interface LegacyStoryC01CheckpointReceipt {
|
|
16
|
+
readonly schemaVersion: 1;
|
|
17
|
+
readonly kind: 'legacy-story-c01-checkpoint';
|
|
18
|
+
readonly storyId: string;
|
|
19
|
+
readonly epicId: string;
|
|
20
|
+
readonly branch: string;
|
|
21
|
+
readonly issueNumber: number;
|
|
22
|
+
readonly repository: string;
|
|
23
|
+
readonly stateSha256: string;
|
|
24
|
+
readonly storySha256: string;
|
|
25
|
+
readonly reused: boolean;
|
|
26
|
+
readonly checkpointAccepted: true;
|
|
27
|
+
readonly localOnly: true;
|
|
28
|
+
}
|
|
29
|
+
export declare function acceptLegacyStoryBranchC01(options: {
|
|
30
|
+
readonly projectRoot: string;
|
|
31
|
+
readonly storyId: string;
|
|
32
|
+
readonly issueNumber: number;
|
|
33
|
+
/** Test seam; the productive CLI always uses authenticated gh readback. */
|
|
34
|
+
readonly verifyIssue?: IssueVerifier;
|
|
35
|
+
readonly afterStatePersist?: () => Promise<void>;
|
|
36
|
+
readonly afterStoryPersist?: () => Promise<void>;
|
|
37
|
+
}): Promise<Result<LegacyStoryC01CheckpointReceipt>>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{execFileSync as O}from"node:child_process";import{createHash as K,randomBytes as R}from"node:crypto";import{closeSync as G,constants as L,existsSync as Z,fstatSync as q,openSync as T,readFileSync as V,realpathSync as B}from"node:fs";import{join as k,resolve as Y}from"node:path";import{parseDocument as M}from"yaml";import{resolveBranchUnit as U}from"../../../shared/dist/yoloop/branch-unit.js";import{acquireGitLifecyclePhysicalIntegrationLock as Q,assertGitLifecyclePrivateFile as j,ensureGitLifecyclePrivateChildDirectory as X,gitLifecycleRuntimeDirectory as tt,releaseGitLifecyclePhysicalIntegrationLock as et}from"./git-lifecycle-store.js";import{GIT_LIFECYCLE_SETUP_BRANCH_STEP_ID as v}from"./git-lifecycle-step-ids.js";import{anchoredAtomicWriteFile as rt,anchoredCompareAndSwapFile as D}from"./secure-filesystem-boundary.js";import{readCompletedLegacyStoryBranchPlan as st}from"./legacy-story-branch-setup.js";function p(t){return{ok:!1,reasonCode:t}}function g(t){return K("sha256").update(t).digest("hex")}function S(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}function l(t,c){return O("git",[...c],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","pipe"],maxBuffer:4*1024*1024}).trim()}function C(t,c){return O("git",[...c],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","pipe"],maxBuffer:4*1024*1024})}function $(t){const c=T(t,L.O_RDONLY|(L.O_NOFOLLOW??0));try{const e=q(c);if(!e.isFile()||e.size>2*1024*1024)throw new Error("legacy-branch-checkpoint-file-unsafe");return V(c,"utf8")}finally{G(c)}}function ct(t){const e=l(t,["remote","get-url","origin"]).match(/^(?:https:\/\/github\.com\/|git@github\.com:)([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+?)(?:\.git)?$/);if(!e||e[1].includes("..")||e[2].includes(".."))throw new Error("legacy-branch-issue-repository-invalid");return`${e[1]}/${e[2]}`}async function nt(t,c){const e=O("gh",["issue","view",String(c),"--repo",t,"--json","number,title,state,url"],{encoding:"utf8",timeout:15e3,stdio:["ignore","pipe","pipe"],maxBuffer:16384});return JSON.parse(e)}function ot(t,c,e,s,r){if(t.number!==s||t.title!==`[YOLO] Story ${e} - Workflow Run`||t.state!=="OPEN"&&!(r&&t.state==="CLOSED")||t.url.toLowerCase()!==`https://github.com/${c}/issues/${s}`.toLowerCase())throw new Error("legacy-branch-issue-evidence-invalid")}function at(t,c){const e=t.worktreePath,s=C(e,["show","HEAD:.neocortex/state.json"]);if(g(s)!==t.stateSha256)throw new Error("legacy-branch-checkpoint-base-state-mismatch");const r=S(JSON.parse(s)),h=S(r?.stories),o=S(r?.epics),a=S(h?.[t.storyId]),f=S(o?.[t.epicId]),i=Object.entries(h??{}).flatMap(([d,z])=>{const P=S(z);return P?.epic_id===t.epicId?[{...P,id:d}]:[]});if(!f||f.id!==t.epicId||f.branch_mode==="epic"||U(f,i).mode!=="story"||!a||a.id!==t.storyId||a.epic_id!==t.epicId||a.status!=="backlog"&&a.status!=="ready_to_start"||!Array.isArray(a.steps_completed)||a.steps_completed.length!==0||a.branch_name||a.issue_number||a.last_step)throw new Error("legacy-branch-checkpoint-state-conflict");a.status="branch-ready",a.steps_completed=[v],a.last_step=v,a.branch_name=t.branch,a.issue_number=c;const u=`${JSON.stringify(r,null,2)}
|
|
2
|
+
`,b=`docs/stories/${t.storyId}.story.md`,y=C(e,["show",`HEAD:${b}`]),I=y.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);if(!I)throw new Error("legacy-branch-checkpoint-frontmatter-invalid");const n=M(I[1],{strict:!0,uniqueKeys:!0});if(n.errors.length>0||n.get("id")!==t.storyId||(n.get("epic_id")??n.get("epic"))!==t.epicId)throw new Error("legacy-branch-checkpoint-frontmatter-invalid");const w=S(n.toJS()),m=["stepsCompleted","steps_completed"].filter(d=>n.has(d)),A=["branchName","branch_name"].filter(d=>n.has(d)),_=["lastStep","last_step"].filter(d=>n.has(d)),N=["issueNumber","issue_number"].filter(d=>n.has(d));if(m.length>1||A.length>1||_.length>1||N.length>1||n.has("status")&&!["backlog","ready","ready_to_start"].includes(String(n.get("status")))||n.has("currentStatus")&&!["backlog","ready","ready_to_start"].includes(String(w?.currentStatus))||m.length===1&&(!Array.isArray(w?.[m[0]])||(w?.[m[0]]).length!==0)||A.length===1&&w?.[A[0]]!=null||_.length===1&&w?.[_[0]]!=null||N.length===1&&w?.[N[0]]!=null)throw new Error("legacy-branch-checkpoint-frontmatter-conflict");n.set("status","branch-ready"),n.has("currentStatus")&&n.set("currentStatus","branch-ready"),n.set(m[0]??"stepsCompleted",[v]),n.set(_[0]??"lastStep",v),n.set(A[0]??"branchName",t.branch),n.set(N[0]??"issueNumber",c);const F=`---
|
|
3
|
+
${n.toString({lineWidth:0})}---
|
|
4
|
+
${y.slice(I[0].length)}`;return{storyPath:b,stateBefore:s,stateAfter:u,storyBefore:y,storyAfter:F}}function E(t,c,e){const s=B(t.worktreePath);if(t.epicId!==t.storyId.split(".")[0]||t.branch!==`story/${t.epicId}/${t.storyId}`||!/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(t.epicId)||!l(c,["check-ref-format","--branch",t.branch])||!l(c,["check-ref-format","--branch",t.baseBranch]))throw new Error("legacy-branch-checkpoint-plan-invalid");const r=i=>B(Y(i,l(i,["rev-parse","--git-common-dir"]))),h=l(c,["worktree","list","--porcelain"]).split(/\n\n+/).filter(i=>i.split(`
|
|
5
|
+
`).includes(`branch refs/heads/${t.branch}`));if(s!==t.worktreePath||h.length!==1||!h[0].split(`
|
|
6
|
+
`).includes(`worktree ${s}`)||h[0].split(`
|
|
7
|
+
`).some(i=>i.startsWith("locked")||i.startsWith("prunable"))||r(s)!==r(c)||B(l(s,["rev-parse","--show-toplevel"]))!==s||l(s,["symbolic-ref","--quiet","--short","HEAD"])!==t.branch||l(s,["rev-parse","HEAD"])!==t.baseHeadSha||l(s,["rev-parse",`refs/heads/${t.branch}`])!==t.baseHeadSha||l(s,["rev-parse",`refs/remotes/origin/${t.baseBranch}`])!==t.baseHeadSha)throw new Error("legacy-branch-checkpoint-physical-mismatch");const o=$(k(s,".neocortex/state.json")),a=$(k(s,e.storyPath));if(![e.stateBefore,e.stateAfter].includes(o)||![e.storyBefore,e.storyAfter].includes(a))throw new Error("legacy-branch-checkpoint-preimage-conflict");if(C(s,["status","--porcelain=v1","-uall"]).split(`
|
|
8
|
+
`).filter(Boolean).some(i=>{if(!i.startsWith(" M "))return!0;const u=i.slice(3);return u!==".neocortex/state.json"&&u!==e.storyPath}))throw new Error("legacy-branch-checkpoint-worktree-dirty");return{stateCurrent:o,storyCurrent:a}}async function it(t){return X(await tt(t),"legacy-story-branch-intents")}function x(t){return`${g(t)}.c01.json`}function J(t){return`${g(t)}.c01.accepted.json`}async function H(t,c){const e=k(t,c);if(!Z(e))return null;await j(e,t);const s=$(e);if(s.length>4096)throw new Error("legacy-branch-checkpoint-journal-invalid");return JSON.parse(s)}async function W(t,c,e){await rt(t,c,`${JSON.stringify(e)}
|
|
9
|
+
`),await j(k(t,c),t)}async function wt(t){if(!Number.isSafeInteger(t.issueNumber)||t.issueNumber<=0)return p("legacy-branch-issue-number-invalid");const c=`legacy-c01-${R(16).toString("hex")}`,e=await Q(t.projectRoot,{kind:"direct",storyId:t.storyId,sessionId:c,idempotencyKey:c,expiresAt:new Date(Date.now()+5*6e4).toISOString(),persistent:!1});if(!e.ok)return p(e.reasonCode);try{const s=await st(t);if(!s.ok)return s;const r=s.value,h=B(t.projectRoot),o=at(r,t.issueNumber),a=E(r,h,o),f=ct(h),i=await it(h),u={schemaVersion:1,kind:"legacy-story-c01-acceptance-intent",storyId:r.storyId,planDigest:g(JSON.stringify(r)),repository:f,issueNumber:t.issueNumber,stateBefore:g(o.stateBefore),stateAfter:g(o.stateAfter),storyBefore:g(o.storyBefore),storyAfter:g(o.storyAfter)},b=await H(i,x(r.storyId));if(b&&JSON.stringify(b)!==JSON.stringify(u))return p("legacy-branch-checkpoint-journal-conflict");if(!b&&(a.stateCurrent!==o.stateBefore||a.storyCurrent!==o.storyBefore))return p("legacy-branch-checkpoint-unjournaled-drift");const y=await H(i,J(r.storyId));if(y&&JSON.stringify(y)!==JSON.stringify(u))return p("legacy-branch-checkpoint-accepted-conflict");const I=await(t.verifyIssue??nt)(f,t.issueNumber);ot(I,f,r.storyId,t.issueNumber,!!y),b||await W(i,x(r.storyId),u);const n=E(r,h,o);if(y&&(n.stateCurrent!==o.stateAfter||n.storyCurrent!==o.storyAfter))return p("legacy-branch-checkpoint-accepted-physical-mismatch");n.stateCurrent===o.stateBefore&&(await D(k(r.worktreePath,".neocortex"),"state.json",o.stateAfter,u.stateBefore),await t.afterStatePersist?.()),E(r,h,o).storyCurrent===o.storyBefore&&(await D(k(r.worktreePath,"docs/stories"),`${r.storyId}.story.md`,o.storyAfter,u.storyBefore),await t.afterStoryPersist?.());const m=E(r,h,o);return m.stateCurrent!==o.stateAfter||m.storyCurrent!==o.storyAfter?p("legacy-branch-checkpoint-post-write-mismatch"):(y||await W(i,J(r.storyId),u),{ok:!0,value:Object.freeze({schemaVersion:1,kind:"legacy-story-c01-checkpoint",storyId:r.storyId,epicId:r.epicId,branch:r.branch,issueNumber:t.issueNumber,repository:f,stateSha256:u.stateAfter,storySha256:u.storyAfter,reused:!!y,checkpointAccepted:!0,localOnly:!0})})}catch(s){const r=s instanceof Error?s.message:"";return p(r.startsWith("legacy-branch-")?r:r.includes("secure-filesystem-cas-conflict")?"legacy-branch-checkpoint-write-raced":"legacy-branch-checkpoint-failed")}finally{await et(e.path,e.owner).catch(()=>{})}}export{wt as acceptLegacyStoryBranchC01};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license FSL-1.1
|
|
3
|
+
* Copyright (c) 2026 OrNexus AI
|
|
4
|
+
*
|
|
5
|
+
* Root-owned physical branch preparation for projects that recorded the
|
|
6
|
+
* legacy story-branch topology. It deliberately leaves state and story
|
|
7
|
+
* checkpoint acceptance to a separate root transaction.
|
|
8
|
+
*/
|
|
9
|
+
export type LegacyStoryBranchSetupResult<T> = {
|
|
10
|
+
readonly ok: true;
|
|
11
|
+
readonly value: T;
|
|
12
|
+
} | {
|
|
13
|
+
readonly ok: false;
|
|
14
|
+
readonly reasonCode: string;
|
|
15
|
+
};
|
|
16
|
+
export interface LegacyStoryBranchPlan {
|
|
17
|
+
readonly schemaVersion: 1;
|
|
18
|
+
readonly kind: 'legacy-story-branch-plan';
|
|
19
|
+
readonly storyId: string;
|
|
20
|
+
readonly epicId: string;
|
|
21
|
+
readonly worktreePath: string;
|
|
22
|
+
readonly branch: string;
|
|
23
|
+
readonly baseBranch: string;
|
|
24
|
+
readonly baseHeadSha: string;
|
|
25
|
+
readonly currentHeadSha: string;
|
|
26
|
+
readonly existingBranchHeadSha: string | null;
|
|
27
|
+
readonly stateSha256: string;
|
|
28
|
+
/** Contains a local worktree path; never forward this receipt to invoke. */
|
|
29
|
+
readonly localOnly: true;
|
|
30
|
+
}
|
|
31
|
+
export interface LegacyStoryBranchSetupReceipt extends Omit<LegacyStoryBranchPlan, 'kind'> {
|
|
32
|
+
readonly kind: 'legacy-story-branch-setup-receipt';
|
|
33
|
+
readonly headSha: string;
|
|
34
|
+
readonly reused: boolean;
|
|
35
|
+
readonly checkpointAccepted: false;
|
|
36
|
+
}
|
|
37
|
+
/** Read-only physical planning; no fetch, checkout, issue creation or state write. */
|
|
38
|
+
export declare function planLegacyStoryBranchSetup(options: {
|
|
39
|
+
readonly projectRoot: string;
|
|
40
|
+
readonly storyId: string;
|
|
41
|
+
}): LegacyStoryBranchSetupResult<LegacyStoryBranchPlan>;
|
|
42
|
+
/** Local-only completion record; callers must still recompute physical truth. */
|
|
43
|
+
export declare function readCompletedLegacyStoryBranchPlan(options: {
|
|
44
|
+
readonly projectRoot: string;
|
|
45
|
+
readonly storyId: string;
|
|
46
|
+
}): Promise<LegacyStoryBranchSetupResult<LegacyStoryBranchPlan>>;
|
|
47
|
+
/** Proves a switched branch against the private intent durably written before switch. */
|
|
48
|
+
export declare function verifyLegacyStoryBranchSetup(options: {
|
|
49
|
+
readonly projectRoot: string;
|
|
50
|
+
readonly storyId: string;
|
|
51
|
+
}): Promise<LegacyStoryBranchSetupResult<LegacyStoryBranchSetupReceipt>>;
|
|
52
|
+
/** Switches only the proven epic worktree; root checkpoint acceptance is separate. */
|
|
53
|
+
export declare function prepareLegacyStoryBranchSetup(options: {
|
|
54
|
+
readonly projectRoot: string;
|
|
55
|
+
readonly storyId: string;
|
|
56
|
+
}): Promise<LegacyStoryBranchSetupResult<LegacyStoryBranchSetupReceipt>>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{execFileSync as T}from"node:child_process";import{createHash as w,randomBytes as V}from"node:crypto";import{closeSync as G,constants as B,existsSync as L,fstatSync as U,openSync as M,readFileSync as Y,realpathSync as y}from"node:fs";import{join as d,resolve as O}from"node:path";import{resolveBranchUnit as K}from"../../../shared/dist/yoloop/branch-unit.js";import{acquireGitLifecyclePhysicalIntegrationLock as Q,assertGitLifecyclePrivateFile as S,ensureGitLifecyclePrivateChildDirectory as X,gitLifecycleRuntimeDirectory as ee,releaseGitLifecyclePhysicalIntegrationLock as re}from"./git-lifecycle-store.js";import{GIT_LIFECYCLE_SETUP_BRANCH_STEP_ID as te}from"./git-lifecycle-step-ids.js";import{anchoredAtomicWriteFile as N}from"./secure-filesystem-boundary.js";const ae="legacy-story-branch-intents";function x(r){return`${w("sha256").update(r).digest("hex")}.json`}function _(r){return`${w("sha256").update(r).digest("hex")}.completed.json`}function P(r){return w("sha256").update(JSON.stringify(r)).digest("hex")}async function k(r){return X(await ee(r),ae)}function ne(r,e){const t=f(r);if(!t||Object.keys(t).sort().join(",")!==["baseBranch","baseHeadSha","branch","currentHeadSha","epicId","existingBranchHeadSha","kind","localOnly","schemaVersion","stateSha256","storyId","worktreePath"].sort().join(",")||t.schemaVersion!==1||t.kind!=="legacy-story-branch-plan"||t.storyId!==e||t.localOnly!==!0||t.existingBranchHeadSha!==null||typeof t.epicId!="string"||typeof t.branch!="string"||typeof t.baseBranch!="string"||typeof t.worktreePath!="string"||![t.baseHeadSha,t.currentHeadSha,t.stateSha256].every(a=>typeof a=="string"&&/^[0-9a-f]{40,64}$/.test(a)))throw new Error("legacy-branch-intent-invalid");return t}async function R(r,e){const t=await k(r),a=d(t,x(e));if(!L(a))return null;await S(a,t);const c=b(a);if(c.length>4096)throw new Error("legacy-branch-intent-invalid");return ne(JSON.parse(c),e)}async function ce(r,e){const t=await k(r),a=await R(r,e.storyId);if(a){if(JSON.stringify(a)!==JSON.stringify(e))throw new Error("legacy-branch-intent-conflict");return}await N(t,x(e.storyId),`${JSON.stringify(e)}
|
|
2
|
+
`),await S(d(t,x(e.storyId)),t)}async function z(r,e){const t=await k(r),a=d(t,_(e.storyId));if(!L(a))return!1;await S(a,t);const c=b(a);if(c.length>512)throw new Error("legacy-branch-completion-invalid");const n=f(JSON.parse(c));if(!n||Object.keys(n).sort().join(",")!=="kind,planDigest,schemaVersion,storyId"||n.schemaVersion!==1||n.kind!=="legacy-story-branch-switch-completed"||n.storyId!==e.storyId||n.planDigest!==P(e))throw new Error("legacy-branch-completion-invalid");return!0}async function oe(r,e){if(await z(r,e))return;const t=await k(r);await N(t,_(e.storyId),`${JSON.stringify({schemaVersion:1,kind:"legacy-story-branch-switch-completed",storyId:e.storyId,planDigest:P(e)})}
|
|
3
|
+
`),await S(d(t,_(e.storyId)),t)}function i(r){return{ok:!1,reasonCode:r}}function A(r,e){return T("git",[...e],{cwd:r,encoding:"utf8",stdio:["ignore","pipe","pipe"],maxBuffer:4*1024*1024})}function o(r,e){return A(r,e).trim()}function H(r,e){try{return o(r,e),!0}catch{return!1}}function f(r){return r&&typeof r=="object"&&!Array.isArray(r)?r:null}function m(r,e){return e.length>0&&e.length<=200&&!e.startsWith("-")&&!e.includes("..")&&!e.includes("@{")&&H(r,["check-ref-format","--branch",e])}function b(r){const e=M(r,B.O_RDONLY|(B.O_NOFOLLOW??0));try{const t=U(e);if(!t.isFile()||t.size>2*1024*1024)throw new Error("legacy-branch-state-unsafe");return Y(e,"utf8")}finally{G(e)}}function W(r){return o(r,["worktree","list","--porcelain"]).split(/\n\n+/).flatMap(e=>{const t=e.split(`
|
|
4
|
+
`),a=t.find(n=>n.startsWith("worktree ")),c=t.find(n=>n.startsWith("branch refs/heads/"));return!a||!c?[]:[{path:a.slice(9),branch:c.slice(18),unsafe:t.some(n=>n.startsWith("prunable")||n.startsWith("locked"))}]})}function se(r){const e=y(r.projectRoot);if(!/^[A-Za-z0-9][A-Za-z0-9_-]*\.[A-Za-z0-9._-]+$/.test(r.storyId))throw new Error("legacy-branch-story-id-invalid");if(y(o(e,["rev-parse","--show-toplevel"]))!==e)throw new Error("legacy-branch-project-root-invalid");const t=d(e,".neocortex/state.json"),a=b(t),c=f(JSON.parse(a)),n=f(c?.stories),u=f(c?.epics),h=f(n?.[r.storyId]),s=h?.epic_id,g=typeof s=="string"?f(u?.[s]):null;if(!h||h.id!==r.storyId||typeof s!="string"||!/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(s)||!g||g.id!==s)throw new Error("legacy-branch-story-state-invalid");const J=Object.entries(n??{}).flatMap(([p,q])=>{const D=f(q);return D?.epic_id===s?[{...D,id:p}]:[]});if(K(g,J).mode!=="story"||g.branch_mode==="epic")throw new Error("legacy-branch-mode-invalid");if(h.status!=="backlog"&&h.status!=="ready_to_start")throw new Error("legacy-branch-story-status-invalid");if(!Array.isArray(h.steps_completed)||h.steps_completed.includes(te)||h.branch_name)throw new Error("legacy-branch-story-already-started");const v=f(c?.config)?.default_branch,I=`story/${s}/${r.storyId}`;if(typeof v!="string"||!m(e,v)||!m(e,I)||!m(e,`epic/${s}`))throw new Error("legacy-branch-ref-invalid");const E=W(e).filter(p=>p.branch===`epic/${s}`);if(E.length!==1||E[0].unsafe)throw new Error("legacy-branch-epic-worktree-unavailable");const l=y(E[0].path);if(typeof g.worktree_path=="string"&&y(O(e,g.worktree_path))!==l)throw new Error("legacy-branch-epic-worktree-mismatch");const $=p=>y(O(p,o(p,["rev-parse","--git-common-dir"])));if($(l)!==$(e)||y(o(l,["rev-parse","--show-toplevel"]))!==l||o(l,["symbolic-ref","--quiet","--short","HEAD"])!==`epic/${s}`)throw new Error("legacy-branch-worktree-identity-invalid");const Z=d(l,".neocortex/state.json");if(b(Z)!==a)throw new Error("legacy-branch-worktree-state-mismatch");if(o(l,["status","--porcelain=v1","-uall"])!=="")throw new Error("legacy-branch-worktree-dirty");const j=`refs/remotes/origin/${v}`;if(!H(l,["show-ref","--verify","--quiet",j]))throw new Error("legacy-branch-origin-ref-missing");if(A(l,["show",`${j}:.neocortex/state.json`])!==a)throw new Error("legacy-branch-origin-state-mismatch");const F=`refs/heads/${I}`;if(H(l,["show-ref","--verify","--quiet",F]))throw new Error("legacy-branch-existing-ref-needs-review");return Object.freeze({schemaVersion:1,kind:"legacy-story-branch-plan",storyId:r.storyId,epicId:s,worktreePath:l,branch:I,baseBranch:v,baseHeadSha:o(l,["rev-parse",j]),currentHeadSha:o(l,["rev-parse","HEAD"]),existingBranchHeadSha:null,stateSha256:w("sha256").update(a).digest("hex"),localOnly:!0})}function C(r){try{return{ok:!0,value:se(r)}}catch(e){return i(e instanceof Error&&e.message.startsWith("legacy-branch-")?e.message:"legacy-branch-preflight-failed")}}async function ie(r){try{const e=y(r.projectRoot);if(y(o(e,["rev-parse","--show-toplevel"]))!==e||!/^[A-Za-z0-9][A-Za-z0-9_-]*\.[A-Za-z0-9._-]+$/.test(r.storyId))return i("legacy-branch-project-root-invalid");const t=await R(e,r.storyId);return t?await z(e,t)?{ok:!0,value:t}:i("legacy-branch-completion-missing"):i("legacy-branch-intent-missing")}catch(e){return i(e instanceof Error&&e.message.startsWith("legacy-branch-")?e.message:"legacy-branch-completion-read-failed")}}async function he(r){try{const e=y(r.projectRoot),t=await ie(r);if(!t.ok)return t;const a=t.value;if(a.epicId!==r.storyId.split(".")[0]||a.branch!==`story/${a.epicId}/${r.storyId}`||!m(e,a.branch)||!m(e,a.baseBranch)||y(a.worktreePath)!==a.worktreePath)return i("legacy-branch-intent-invalid");const c=W(e).filter(s=>s.branch===a.branch);if(c.length!==1||c[0].unsafe||y(c[0].path)!==a.worktreePath)return i("legacy-branch-story-worktree-mismatch");const n=a.worktreePath,u=s=>y(O(s,o(s,["rev-parse","--git-common-dir"])));if(u(n)!==u(e)||y(o(n,["rev-parse","--show-toplevel"]))!==n||o(n,["symbolic-ref","--quiet","--short","HEAD"])!==a.branch||o(n,["rev-parse","HEAD"])!==a.baseHeadSha||o(n,["rev-parse",`refs/heads/${a.branch}`])!==a.baseHeadSha||o(n,["rev-parse",`refs/remotes/origin/${a.baseBranch}`])!==a.baseHeadSha)return i("legacy-branch-physical-identity-mismatch");const h=b(d(n,".neocortex/state.json"));return w("sha256").update(h).digest("hex")!==a.stateSha256||A(n,["show","HEAD:.neocortex/state.json"])!==h||o(n,["status","--porcelain=v1","-uall"])!==""?i("legacy-branch-physical-state-mismatch"):{ok:!0,value:Object.freeze({...a,kind:"legacy-story-branch-setup-receipt",headSha:a.baseHeadSha,reused:!0,checkpointAccepted:!1})}}catch(e){return i(e instanceof Error&&e.message.startsWith("legacy-branch-")?e.message:"legacy-branch-verification-failed")}}async function ve(r){const e=C(r);if(!e.ok){if(e.reasonCode==="legacy-branch-epic-worktree-unavailable"){const c=await he(r);return c.ok?c:e}return e}const t=`legacy-setup-${V(16).toString("hex")}`,a=await Q(r.projectRoot,{kind:"direct",storyId:r.storyId,sessionId:t,idempotencyKey:t,expiresAt:new Date(Date.now()+5*6e4).toISOString(),persistent:!1});if(!a.ok)return i(a.reasonCode);try{const c=C(r);if(!c.ok||JSON.stringify(c.value)!==JSON.stringify(e.value))return i("legacy-branch-preflight-raced");const{worktreePath:n,branch:u,baseBranch:h}=c.value;await ce(r.projectRoot,c.value),o(n,["switch","-c",u,`refs/remotes/origin/${h}`]);const s=o(n,["rev-parse","HEAD"]);return o(n,["symbolic-ref","--quiet","--short","HEAD"])!==u||s!==c.value.baseHeadSha||o(n,["status","--porcelain=v1","-uall"])!==""||w("sha256").update(b(d(n,".neocortex/state.json"))).digest("hex")!==c.value.stateSha256?i("legacy-branch-post-switch-invalid"):(await oe(r.projectRoot,c.value),{ok:!0,value:Object.freeze({...c.value,kind:"legacy-story-branch-setup-receipt",headSha:s,reused:!1,checkpointAccepted:!1})})}catch(c){return i(c instanceof Error&&c.message.startsWith("legacy-branch-")?c.message:"legacy-branch-switch-failed")}finally{await re(a.path,a.owner).catch(()=>{})}}export{C as planLegacyStoryBranchSetup,ve as prepareLegacyStoryBranchSetup,ie as readCompletedLegacyStoryBranchPlan,he as verifyLegacyStoryBranchSetup};
|
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import { type C12RemoteObservation, type C12RemoteReasonCode } from '../../../shared/dist/merge-readiness/c12-remote-observation.js';
|
|
2
|
+
type Result<T> = {
|
|
3
|
+
readonly ok: true;
|
|
4
|
+
readonly value: T;
|
|
5
|
+
} | {
|
|
6
|
+
readonly ok: false;
|
|
7
|
+
readonly reasonCode: string;
|
|
8
|
+
};
|
|
9
|
+
type Pr = {
|
|
10
|
+
readonly number: number;
|
|
11
|
+
readonly state: string;
|
|
12
|
+
readonly headRefName: string;
|
|
13
|
+
readonly headRefOid: string;
|
|
14
|
+
readonly baseRefName: string;
|
|
15
|
+
readonly url: string;
|
|
16
|
+
};
|
|
17
|
+
export interface LegacyStoryPrPlan {
|
|
18
|
+
readonly schemaVersion: 1;
|
|
19
|
+
readonly kind: 'legacy-story-pr-plan';
|
|
20
|
+
readonly storyId: string;
|
|
21
|
+
readonly epicId: string;
|
|
22
|
+
readonly repository: string;
|
|
23
|
+
readonly branch: string;
|
|
24
|
+
readonly baseBranch: string;
|
|
25
|
+
readonly headSha: string;
|
|
26
|
+
readonly baseSha: string;
|
|
27
|
+
readonly qaAuthority: 'root-review-required';
|
|
28
|
+
readonly localOnly: true;
|
|
29
|
+
}
|
|
30
|
+
export interface LegacyStorySyncPlan {
|
|
31
|
+
readonly schemaVersion: 1;
|
|
32
|
+
readonly kind: 'legacy-story-c09-sync-plan';
|
|
33
|
+
readonly storyId: string;
|
|
34
|
+
readonly epicId: string;
|
|
35
|
+
readonly repository: string;
|
|
36
|
+
readonly branch: string;
|
|
37
|
+
readonly baseBranch: string;
|
|
38
|
+
readonly headSha: string;
|
|
39
|
+
readonly baseSha: string;
|
|
40
|
+
readonly mergeBaseSha: string;
|
|
41
|
+
readonly stateSha256: string;
|
|
42
|
+
readonly storySha256: string;
|
|
43
|
+
readonly baseAlreadyAncestor: boolean;
|
|
44
|
+
readonly physicalSync: false;
|
|
45
|
+
readonly checkpointAccepted: false;
|
|
46
|
+
readonly localOnly: true;
|
|
47
|
+
}
|
|
48
|
+
export interface LegacyStoryCommitPlan {
|
|
49
|
+
readonly schemaVersion: 1;
|
|
50
|
+
readonly kind: 'legacy-story-c08-commit-plan';
|
|
51
|
+
readonly storyId: string;
|
|
52
|
+
readonly epicId: string;
|
|
53
|
+
readonly repository: string;
|
|
54
|
+
readonly branch: string;
|
|
55
|
+
readonly baseBranch: string;
|
|
56
|
+
readonly headSha: string;
|
|
57
|
+
readonly remoteHeadSha: null;
|
|
58
|
+
readonly baseSha: string;
|
|
59
|
+
readonly indexDigestSha256: string;
|
|
60
|
+
readonly stagedPatchSha256: string;
|
|
61
|
+
readonly changedPaths: readonly string[];
|
|
62
|
+
readonly stateSha256: string;
|
|
63
|
+
readonly storySha256: string;
|
|
64
|
+
readonly stateIndexBlobSha: string;
|
|
65
|
+
readonly storyIndexBlobSha: string;
|
|
66
|
+
readonly physicalCommit: false;
|
|
67
|
+
readonly checkpointAccepted: false;
|
|
68
|
+
readonly localOnly: true;
|
|
69
|
+
}
|
|
70
|
+
export interface LegacyStoryPrReceipt {
|
|
71
|
+
readonly schemaVersion: 1;
|
|
72
|
+
readonly kind: 'legacy-story-pr-provider-receipt';
|
|
73
|
+
readonly storyId: string;
|
|
74
|
+
readonly epicId: string;
|
|
75
|
+
readonly repository: string;
|
|
76
|
+
readonly branch: string;
|
|
77
|
+
readonly baseBranch: string;
|
|
78
|
+
readonly headSha: string;
|
|
79
|
+
readonly number: number;
|
|
80
|
+
readonly url: string;
|
|
81
|
+
readonly reused: boolean;
|
|
82
|
+
readonly checkpointAccepted: false;
|
|
83
|
+
readonly publicSafe: true;
|
|
84
|
+
}
|
|
85
|
+
export interface LegacyStoryPrProvider {
|
|
86
|
+
list(repository: string, branch: string, baseBranch: string): Promise<readonly Pr[]>;
|
|
87
|
+
create(repository: string, branch: string, baseBranch: string, title: string, bodyFile: string): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
export interface LegacyStoryPrMergeObservation {
|
|
90
|
+
readonly number: number;
|
|
91
|
+
readonly state: string;
|
|
92
|
+
readonly headRefName: string;
|
|
93
|
+
readonly headRefOid: string;
|
|
94
|
+
readonly baseRefName: string;
|
|
95
|
+
readonly baseRefOid: string;
|
|
96
|
+
readonly isDraft: boolean;
|
|
97
|
+
readonly mergeable: string;
|
|
98
|
+
readonly mergeCommit: {
|
|
99
|
+
readonly oid: string;
|
|
100
|
+
} | null;
|
|
101
|
+
readonly statusCheckRollup: readonly unknown[];
|
|
102
|
+
readonly url: string;
|
|
103
|
+
}
|
|
104
|
+
export interface LegacyStoryPrMergeProvider {
|
|
105
|
+
view(repository: string, prNumber: number): Promise<LegacyStoryPrMergeObservation>;
|
|
106
|
+
/** Immediate merge with a provider-enforced expected PR head, never auto-merge. */
|
|
107
|
+
merge(repository: string, prNumber: number, expectedHeadSha: string): Promise<void>;
|
|
108
|
+
}
|
|
109
|
+
export interface LegacyStoryIssueProvider {
|
|
110
|
+
view(repository: string, issueNumber: number): Promise<{
|
|
111
|
+
readonly number: number;
|
|
112
|
+
readonly title: string;
|
|
113
|
+
readonly state: string;
|
|
114
|
+
readonly url: string;
|
|
115
|
+
}>;
|
|
116
|
+
}
|
|
117
|
+
export interface LegacyStoryIssueCloser extends LegacyStoryIssueProvider {
|
|
118
|
+
close(repository: string, issueNumber: number): Promise<void>;
|
|
119
|
+
}
|
|
120
|
+
/** Root-owned C08 basis. Only a cleanly staged, same-story write set may
|
|
121
|
+
* cross into a future physical commit. This plan neither commits nor pushes. */
|
|
122
|
+
export declare function planLegacyStoryCommitC08(options: {
|
|
123
|
+
readonly projectRoot: string;
|
|
124
|
+
readonly storyId: string;
|
|
125
|
+
}): Result<LegacyStoryCommitPlan>;
|
|
126
|
+
export interface LegacyStoryCommitReceipt {
|
|
127
|
+
readonly schemaVersion: 1;
|
|
128
|
+
readonly kind: 'legacy-story-c08-commit-accepted';
|
|
129
|
+
readonly storyId: string;
|
|
130
|
+
readonly epicId: string;
|
|
131
|
+
readonly branch: string;
|
|
132
|
+
readonly checkpointHeadSha: string;
|
|
133
|
+
readonly qaSha256: string;
|
|
134
|
+
readonly reused: boolean;
|
|
135
|
+
readonly physicalCommit: true;
|
|
136
|
+
readonly checkpointAccepted: true;
|
|
137
|
+
readonly publicSafe: true;
|
|
138
|
+
}
|
|
139
|
+
/** Root-owned C08 effect: one locally committed story checkpoint, full P205 on
|
|
140
|
+
* that immutable HEAD, then a first non-force remote push and exact readback. */
|
|
141
|
+
export declare function acceptLegacyStoryCommitC08(options: {
|
|
142
|
+
readonly projectRoot: string;
|
|
143
|
+
readonly storyId: string;
|
|
144
|
+
readonly authorize: boolean;
|
|
145
|
+
/** Synthetic seams; the productive CLI uses durable C01 proof and complete P205. */
|
|
146
|
+
readonly verifyC01?: () => Promise<boolean>;
|
|
147
|
+
readonly verifyQa?: (headSha: string) => Promise<string>;
|
|
148
|
+
readonly afterStateWrite?: () => Promise<void>;
|
|
149
|
+
readonly afterCommit?: () => Promise<void>;
|
|
150
|
+
readonly afterPush?: () => Promise<void>;
|
|
151
|
+
}): Promise<Result<LegacyStoryCommitReceipt>>;
|
|
152
|
+
/** Read-only C09 basis. A merge-base observation is not a synchronized story:
|
|
153
|
+
* only a later root-owned Git/state checkpoint may turn C08 into C09. */
|
|
154
|
+
export declare function planLegacyStorySyncC09(options: {
|
|
155
|
+
readonly projectRoot: string;
|
|
156
|
+
readonly storyId: string;
|
|
157
|
+
}): Result<LegacyStorySyncPlan>;
|
|
158
|
+
export interface LegacyStorySyncReceipt {
|
|
159
|
+
readonly schemaVersion: 1;
|
|
160
|
+
readonly kind: 'legacy-story-c09-sync-accepted';
|
|
161
|
+
readonly storyId: string;
|
|
162
|
+
readonly epicId: string;
|
|
163
|
+
readonly branch: string;
|
|
164
|
+
readonly baseSha: string;
|
|
165
|
+
readonly checkpointHeadSha: string;
|
|
166
|
+
readonly qaSha256: string;
|
|
167
|
+
readonly reused: boolean;
|
|
168
|
+
readonly physicalSync: true;
|
|
169
|
+
readonly checkpointAccepted: true;
|
|
170
|
+
readonly publicSafe: true;
|
|
171
|
+
}
|
|
172
|
+
/** Root-only C09 physical sync. The merge and checkpoint are prepared in a
|
|
173
|
+
* detached private worktree; the live story branch moves only after candidate
|
|
174
|
+
* QA and an exact non-force remote readback. An interrupted push is reconciled
|
|
175
|
+
* from the private intent rather than replaying the merge. */
|
|
176
|
+
export declare function acceptLegacyStorySyncC09(options: {
|
|
177
|
+
readonly projectRoot: string;
|
|
178
|
+
readonly storyId: string;
|
|
179
|
+
readonly authorize: boolean;
|
|
180
|
+
/** Synthetic seam; productive CLI always runs the complete P205 gate. */
|
|
181
|
+
readonly verifyQa?: (plan: LegacyStoryPrPlan) => Promise<string>;
|
|
182
|
+
readonly afterCommit?: () => Promise<void>;
|
|
183
|
+
readonly afterPush?: () => Promise<void>;
|
|
184
|
+
}): Promise<Result<LegacyStorySyncReceipt>>;
|
|
185
|
+
export declare function planLegacyStoryPr(options: {
|
|
186
|
+
readonly projectRoot: string;
|
|
187
|
+
readonly storyId: string;
|
|
188
|
+
}): Result<LegacyStoryPrPlan>;
|
|
189
|
+
export declare function createLegacyStoryPr(options: {
|
|
190
|
+
readonly projectRoot: string;
|
|
191
|
+
readonly storyId: string;
|
|
192
|
+
readonly bodyFile: string;
|
|
193
|
+
readonly authorize: boolean;
|
|
194
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
195
|
+
/** Synthetic test seam. The productive CLI always executes the P205 complete gate. */
|
|
196
|
+
readonly verifyQa?: (plan: LegacyStoryPrPlan) => Promise<string>;
|
|
197
|
+
}): Promise<Result<LegacyStoryPrReceipt>>;
|
|
198
|
+
export interface LegacyStoryC10CheckpointReceipt {
|
|
199
|
+
readonly schemaVersion: 1;
|
|
200
|
+
readonly kind: 'legacy-story-c10-checkpoint';
|
|
201
|
+
readonly storyId: string;
|
|
202
|
+
readonly epicId: string;
|
|
203
|
+
readonly branch: string;
|
|
204
|
+
readonly repository: string;
|
|
205
|
+
readonly number: number;
|
|
206
|
+
readonly url: string;
|
|
207
|
+
readonly headSha: string;
|
|
208
|
+
readonly stateSha256: string;
|
|
209
|
+
readonly storySha256: string;
|
|
210
|
+
readonly reused: boolean;
|
|
211
|
+
readonly checkpointAccepted: true;
|
|
212
|
+
readonly localOnly: true;
|
|
213
|
+
}
|
|
214
|
+
/** Accepts only an exact, still-open provider PR after physical local QA. */
|
|
215
|
+
export declare function acceptLegacyStoryPrC10(options: {
|
|
216
|
+
readonly projectRoot: string;
|
|
217
|
+
readonly storyId: string;
|
|
218
|
+
readonly prNumber: number;
|
|
219
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
220
|
+
/** Synthetic test seam. The productive CLI always executes the P205 complete gate. */
|
|
221
|
+
readonly verifyQa?: (plan: LegacyStoryPrPlan) => Promise<string>;
|
|
222
|
+
readonly afterStatePersist?: () => Promise<void>;
|
|
223
|
+
readonly afterStoryPersist?: () => Promise<void>;
|
|
224
|
+
}): Promise<Result<LegacyStoryC10CheckpointReceipt>>;
|
|
225
|
+
/** Read-only C10 predecessor for the root-owned C11 review. */
|
|
226
|
+
export declare function readAcceptedLegacyStoryPrC10(options: {
|
|
227
|
+
readonly projectRoot: string;
|
|
228
|
+
readonly storyId: string;
|
|
229
|
+
readonly prNumber: number;
|
|
230
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
231
|
+
}): Promise<Result<{
|
|
232
|
+
readonly plan: LegacyStoryPrPlan;
|
|
233
|
+
readonly receipt: LegacyStoryC10CheckpointReceipt;
|
|
234
|
+
}>>;
|
|
235
|
+
export interface LegacyStoryPrReviewPlan {
|
|
236
|
+
readonly schemaVersion: 1;
|
|
237
|
+
readonly kind: 'legacy-story-pr-review-plan';
|
|
238
|
+
readonly storyId: string;
|
|
239
|
+
readonly epicId: string;
|
|
240
|
+
readonly repository: string;
|
|
241
|
+
readonly branch: string;
|
|
242
|
+
readonly baseBranch: string;
|
|
243
|
+
readonly baseSha: string;
|
|
244
|
+
readonly headSha: string;
|
|
245
|
+
readonly prNumber: number;
|
|
246
|
+
readonly diffSha256: string;
|
|
247
|
+
readonly changedPaths: readonly string[];
|
|
248
|
+
readonly checkpointAccepted: false;
|
|
249
|
+
readonly localOnly: true;
|
|
250
|
+
}
|
|
251
|
+
export interface LegacyStoryC11CheckpointReceipt {
|
|
252
|
+
readonly schemaVersion: 1;
|
|
253
|
+
readonly kind: 'legacy-story-c11-checkpoint';
|
|
254
|
+
readonly storyId: string;
|
|
255
|
+
readonly epicId: string;
|
|
256
|
+
readonly branch: string;
|
|
257
|
+
readonly prNumber: number;
|
|
258
|
+
readonly headSha: string;
|
|
259
|
+
readonly reviewSha256: string;
|
|
260
|
+
readonly qaSha256: string;
|
|
261
|
+
readonly stateSha256: string;
|
|
262
|
+
readonly storySha256: string;
|
|
263
|
+
readonly reused: boolean;
|
|
264
|
+
readonly checkpointAccepted: true;
|
|
265
|
+
readonly localOnly: true;
|
|
266
|
+
}
|
|
267
|
+
export declare function planLegacyStoryPrReview(options: {
|
|
268
|
+
readonly projectRoot: string;
|
|
269
|
+
readonly storyId: string;
|
|
270
|
+
readonly prNumber: number;
|
|
271
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
272
|
+
}): Promise<Result<LegacyStoryPrReviewPlan>>;
|
|
273
|
+
/** Root-only C11 acceptance. The caller supplies an independently reviewed,
|
|
274
|
+
* public-safe report; neither the server selection nor a sandbox return can
|
|
275
|
+
* approve this checkpoint. It never commits, pushes, or merges the PR. */
|
|
276
|
+
export declare function acceptLegacyStoryPrReviewC11(options: {
|
|
277
|
+
readonly projectRoot: string;
|
|
278
|
+
readonly storyId: string;
|
|
279
|
+
readonly prNumber: number;
|
|
280
|
+
readonly reportFile: string;
|
|
281
|
+
readonly authorize: boolean;
|
|
282
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
283
|
+
/** Synthetic seam; the productive CLI always executes the P205 complete gate. */
|
|
284
|
+
readonly verifyQa?: (plan: LegacyStoryPrPlan) => Promise<string>;
|
|
285
|
+
readonly afterStatePersist?: () => Promise<void>;
|
|
286
|
+
readonly afterStoryPersist?: () => Promise<void>;
|
|
287
|
+
}): Promise<Result<LegacyStoryC11CheckpointReceipt>>;
|
|
288
|
+
/** Independent readback for the eventual C12 integration boundary. A saved
|
|
289
|
+
* status or provider PR alone is never a review verdict. */
|
|
290
|
+
export declare function readAcceptedLegacyStoryPrReviewC11(options: {
|
|
291
|
+
readonly projectRoot: string;
|
|
292
|
+
readonly storyId: string;
|
|
293
|
+
readonly prNumber: number;
|
|
294
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
295
|
+
}): Promise<Result<{
|
|
296
|
+
readonly plan: LegacyStoryPrReviewPlan;
|
|
297
|
+
readonly receipt: LegacyStoryC11CheckpointReceipt;
|
|
298
|
+
}>>;
|
|
299
|
+
export interface LegacyStoryPrMergePlan {
|
|
300
|
+
readonly schemaVersion: 1;
|
|
301
|
+
readonly kind: 'legacy-story-pr-merge-plan';
|
|
302
|
+
readonly storyId: string;
|
|
303
|
+
readonly epicId: string;
|
|
304
|
+
readonly repository: string;
|
|
305
|
+
readonly branch: string;
|
|
306
|
+
readonly baseBranch: string;
|
|
307
|
+
readonly baseSha: string;
|
|
308
|
+
readonly originalHeadSha: string;
|
|
309
|
+
readonly prNumber: number;
|
|
310
|
+
readonly reviewArtifactPath: string;
|
|
311
|
+
readonly reviewArtifactSha256: string;
|
|
312
|
+
readonly reviewSha256: string;
|
|
313
|
+
readonly qaSha256: string;
|
|
314
|
+
readonly stateSha256: string;
|
|
315
|
+
readonly storySha256: string;
|
|
316
|
+
readonly nextAuthority: 'root-review-commit-and-new-head-qa-required';
|
|
317
|
+
readonly physicalMerge: false;
|
|
318
|
+
readonly localOnly: true;
|
|
319
|
+
}
|
|
320
|
+
/** Plan only: the old PR is not ready for physical merge while C10/C11 remain
|
|
321
|
+
* uncommitted. This validates the exact review artifact to integrate next. */
|
|
322
|
+
export declare function planLegacyStoryPrMergeC12(options: {
|
|
323
|
+
readonly projectRoot: string;
|
|
324
|
+
readonly storyId: string;
|
|
325
|
+
readonly prNumber: number;
|
|
326
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
327
|
+
}): Promise<Result<LegacyStoryPrMergePlan>>;
|
|
328
|
+
export interface LegacyStoryPrPreparedReceipt {
|
|
329
|
+
readonly schemaVersion: 1;
|
|
330
|
+
readonly kind: 'legacy-story-c12-prepared';
|
|
331
|
+
readonly storyId: string;
|
|
332
|
+
readonly epicId: string;
|
|
333
|
+
readonly branch: string;
|
|
334
|
+
readonly prNumber: number;
|
|
335
|
+
readonly originalHeadSha: string;
|
|
336
|
+
readonly candidateHeadSha: string;
|
|
337
|
+
readonly qaSha256: string;
|
|
338
|
+
readonly reused: boolean;
|
|
339
|
+
readonly physicalMerge: false;
|
|
340
|
+
readonly localOnly: true;
|
|
341
|
+
}
|
|
342
|
+
/** Commit only the reviewed C10/C11 metadata and public review artifact to
|
|
343
|
+
* the existing PR branch, then run P205 on that new immutable HEAD and push
|
|
344
|
+
* without force. This prepares C12; it does not merge or close the story. */
|
|
345
|
+
export declare function prepareLegacyStoryPrMergeC12(options: {
|
|
346
|
+
readonly projectRoot: string;
|
|
347
|
+
readonly storyId: string;
|
|
348
|
+
readonly prNumber: number;
|
|
349
|
+
readonly authorize: boolean;
|
|
350
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
351
|
+
/** Synthetic seam; the productive CLI always executes the P205 complete gate. */
|
|
352
|
+
readonly verifyQa?: (plan: LegacyStoryPrPlan) => Promise<string>;
|
|
353
|
+
readonly afterCommit?: () => Promise<void>;
|
|
354
|
+
readonly afterPush?: () => Promise<void>;
|
|
355
|
+
}): Promise<Result<LegacyStoryPrPreparedReceipt>>;
|
|
356
|
+
export interface LegacyStoryPrMergedReceipt {
|
|
357
|
+
readonly schemaVersion: 1;
|
|
358
|
+
readonly kind: 'legacy-story-c12-merged';
|
|
359
|
+
readonly storyId: string;
|
|
360
|
+
readonly epicId: string;
|
|
361
|
+
readonly prNumber: number;
|
|
362
|
+
readonly branch: string;
|
|
363
|
+
readonly candidateHeadSha: string;
|
|
364
|
+
readonly mergeCommitSha: string;
|
|
365
|
+
readonly baseHeadSha: string;
|
|
366
|
+
readonly qaSha256: string;
|
|
367
|
+
readonly remoteObservationDigest: string;
|
|
368
|
+
readonly reused: boolean;
|
|
369
|
+
readonly physicalMerge: true;
|
|
370
|
+
readonly checkpointAccepted: false;
|
|
371
|
+
readonly localOnly: true;
|
|
372
|
+
}
|
|
373
|
+
/** Narrow root review gate until the scoped-CI debt adapter is integrated.
|
|
374
|
+
* Non-blocking remote findings cannot be silently omitted or treated as green. */
|
|
375
|
+
export interface LegacyStoryPrRootMergeDecision {
|
|
376
|
+
readonly schemaVersion: 1;
|
|
377
|
+
readonly kind: 'legacy-story-c12-root-merge-decision';
|
|
378
|
+
readonly storyId: string;
|
|
379
|
+
readonly epicId: string;
|
|
380
|
+
readonly prNumber: number;
|
|
381
|
+
readonly candidateHeadSha: string;
|
|
382
|
+
readonly baseSha: string;
|
|
383
|
+
readonly reviewSha256: string;
|
|
384
|
+
readonly remoteObservationDigest: string;
|
|
385
|
+
readonly canMerge: true;
|
|
386
|
+
readonly blockingChecks: readonly [];
|
|
387
|
+
readonly nonBlockingChecks: readonly [];
|
|
388
|
+
readonly followUpDebt: readonly [];
|
|
389
|
+
}
|
|
390
|
+
export interface LegacyStoryPrRemoteDebtPlan {
|
|
391
|
+
readonly schemaVersion: 1;
|
|
392
|
+
readonly kind: 'legacy-story-c12-remote-debt-required';
|
|
393
|
+
readonly storyId: string;
|
|
394
|
+
readonly epicId: string;
|
|
395
|
+
readonly prNumber: number;
|
|
396
|
+
readonly candidateHeadSha: string;
|
|
397
|
+
readonly baseSha: string;
|
|
398
|
+
readonly reviewSha256: string;
|
|
399
|
+
readonly remoteObservationDigest: string;
|
|
400
|
+
readonly reasonCodes: readonly C12RemoteReasonCode[];
|
|
401
|
+
readonly reasonCounts: C12RemoteObservation['reasonCounts'];
|
|
402
|
+
readonly canMerge: false;
|
|
403
|
+
readonly publicSafe: true;
|
|
404
|
+
}
|
|
405
|
+
export interface LegacyStoryPrRemoteDebtReceipt {
|
|
406
|
+
readonly schemaVersion: 1;
|
|
407
|
+
readonly kind: 'legacy-story-c12-remote-debt-journaled';
|
|
408
|
+
readonly storyId: string;
|
|
409
|
+
readonly epicId: string;
|
|
410
|
+
readonly prNumber: number;
|
|
411
|
+
readonly candidateHeadSha: string;
|
|
412
|
+
readonly remoteObservationDigest: string;
|
|
413
|
+
readonly reasonCodes: readonly C12RemoteReasonCode[];
|
|
414
|
+
readonly reasonCounts: C12RemoteObservation['reasonCounts'];
|
|
415
|
+
readonly reused: boolean;
|
|
416
|
+
readonly durableObservation: true;
|
|
417
|
+
readonly registryRecorded: false;
|
|
418
|
+
readonly canMerge: false;
|
|
419
|
+
readonly publicSafe: true;
|
|
420
|
+
}
|
|
421
|
+
/** Root-only readback of the prepared PR candidate. This produces a closed
|
|
422
|
+
* decision only for a categorized clean rollup, otherwise a non-authorizing
|
|
423
|
+
* debt plan. It neither persists debt, runs QA nor merges. */
|
|
424
|
+
export declare function planLegacyStoryPrMergeDecisionC12(options: {
|
|
425
|
+
readonly projectRoot: string;
|
|
426
|
+
readonly storyId: string;
|
|
427
|
+
readonly prNumber: number;
|
|
428
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
429
|
+
readonly mergeProvider?: LegacyStoryPrMergeProvider;
|
|
430
|
+
}): Promise<Result<LegacyStoryPrRootMergeDecision | LegacyStoryPrRemoteDebtPlan>>;
|
|
431
|
+
/** Persist an exact categorized remote observation before any C12 effect.
|
|
432
|
+
* This is a private replay-safe evidence journal, not the canonical scoped-CI
|
|
433
|
+
* registry writer and never merge authorization. */
|
|
434
|
+
export declare function recordLegacyStoryPrRemoteDebtC12(options: {
|
|
435
|
+
readonly projectRoot: string;
|
|
436
|
+
readonly storyId: string;
|
|
437
|
+
readonly prNumber: number;
|
|
438
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
439
|
+
readonly mergeProvider?: LegacyStoryPrMergeProvider;
|
|
440
|
+
}): Promise<Result<LegacyStoryPrRemoteDebtReceipt>>;
|
|
441
|
+
/** One root-owned immediate provider merge attempt. An uncertain effect is
|
|
442
|
+
* never retried automatically; later calls only reconcile physical truth. */
|
|
443
|
+
export declare function mergeLegacyStoryPrC12(options: {
|
|
444
|
+
readonly projectRoot: string;
|
|
445
|
+
readonly storyId: string;
|
|
446
|
+
readonly prNumber: number;
|
|
447
|
+
readonly authorize: boolean;
|
|
448
|
+
readonly provider?: LegacyStoryPrProvider;
|
|
449
|
+
readonly mergeProvider?: LegacyStoryPrMergeProvider;
|
|
450
|
+
readonly rootDecision?: LegacyStoryPrRootMergeDecision;
|
|
451
|
+
/** Synthetic seam; the productive CLI always executes the complete P205 gate. */
|
|
452
|
+
readonly verifyQa?: (plan: LegacyStoryPrPlan) => Promise<string>;
|
|
453
|
+
readonly afterMerge?: () => Promise<void>;
|
|
454
|
+
}): Promise<Result<LegacyStoryPrMergedReceipt>>;
|
|
455
|
+
export interface LegacyStoryPrPostMergePlan {
|
|
456
|
+
readonly schemaVersion: 1;
|
|
457
|
+
readonly kind: 'legacy-story-c12-post-merge-plan';
|
|
458
|
+
readonly storyId: string;
|
|
459
|
+
readonly epicId: string;
|
|
460
|
+
readonly repository: string;
|
|
461
|
+
readonly baseBranch: string;
|
|
462
|
+
readonly prNumber: number;
|
|
463
|
+
readonly issueNumber: number;
|
|
464
|
+
readonly candidateHeadSha: string;
|
|
465
|
+
readonly mergeCommitSha: string;
|
|
466
|
+
readonly stateSha256: string;
|
|
467
|
+
readonly storySha256: string;
|
|
468
|
+
readonly nextAuthority: 'root-state-checkpoint-and-issue-closure-required';
|
|
469
|
+
readonly checkpointAccepted: false;
|
|
470
|
+
readonly localOnly: true;
|
|
471
|
+
}
|
|
472
|
+
/** A provider's MERGED flag is not the C12 state checkpoint. This read-only
|
|
473
|
+
* preflight requires the exact merge commit at the current base HEAD, the
|
|
474
|
+
* accepted C11 bytes, and the still-open same-story issue before any write. */
|
|
475
|
+
export declare function planLegacyStoryPrPostMergeC12(options: {
|
|
476
|
+
readonly projectRoot: string;
|
|
477
|
+
readonly storyId: string;
|
|
478
|
+
readonly prNumber: number;
|
|
479
|
+
readonly mergeProvider?: LegacyStoryPrMergeProvider;
|
|
480
|
+
readonly issueProvider?: LegacyStoryIssueProvider;
|
|
481
|
+
}): Promise<Result<LegacyStoryPrPostMergePlan>>;
|
|
482
|
+
export interface LegacyStoryPrPostMergeReceipt {
|
|
483
|
+
readonly schemaVersion: 1;
|
|
484
|
+
readonly kind: 'legacy-story-c12-post-merge-accepted';
|
|
485
|
+
readonly storyId: string;
|
|
486
|
+
readonly epicId: string;
|
|
487
|
+
readonly prNumber: number;
|
|
488
|
+
readonly issueNumber: number;
|
|
489
|
+
readonly mergeCommitSha: string;
|
|
490
|
+
readonly checkpointHeadSha: string;
|
|
491
|
+
readonly qaSha256: string;
|
|
492
|
+
readonly reused: boolean;
|
|
493
|
+
readonly physicalMerge: true;
|
|
494
|
+
readonly issueClosed: true;
|
|
495
|
+
readonly checkpointAccepted: true;
|
|
496
|
+
readonly publicSafe: true;
|
|
497
|
+
}
|
|
498
|
+
/** Root-owned C12 terminal checkpoint. The private intent precedes issue close,
|
|
499
|
+
* which is re-read on replay. A story becomes done only after an exact two-file
|
|
500
|
+
* base commit, fresh P205, non-force push and provider/issue readback. */
|
|
501
|
+
export declare function acceptLegacyStoryPrPostMergeC12(options: {
|
|
502
|
+
readonly projectRoot: string;
|
|
503
|
+
readonly storyId: string;
|
|
504
|
+
readonly prNumber: number;
|
|
505
|
+
readonly authorize: boolean;
|
|
506
|
+
readonly mergeProvider?: LegacyStoryPrMergeProvider;
|
|
507
|
+
readonly issueProvider?: LegacyStoryIssueCloser;
|
|
508
|
+
/** Synthetic seam; the productive CLI always runs P205 on checkpoint HEAD. */
|
|
509
|
+
readonly verifyQa?: (plan: LegacyStoryPrPlan) => Promise<string>;
|
|
510
|
+
readonly afterIssueClose?: () => Promise<void>;
|
|
511
|
+
readonly afterCommit?: () => Promise<void>;
|
|
512
|
+
readonly afterPush?: () => Promise<void>;
|
|
513
|
+
}): Promise<Result<LegacyStoryPrPostMergeReceipt>>;
|
|
514
|
+
export {};
|