@ornexus/neocortex 4.60.49 → 4.60.51

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.
Files changed (38) hide show
  1. package/dist/sbom.cdx.json +23 -23
  2. package/install.ps1 +1 -1
  3. package/install.sh +1 -1
  4. package/package.json +2 -2
  5. package/packages/client/dist/adapters/platform-detector.d.ts +9 -0
  6. package/packages/client/dist/adapters/platform-detector.js +1 -1
  7. package/packages/client/dist/cli.js +3 -2
  8. package/packages/client/dist/commands/invoke.d.ts +4 -0
  9. package/packages/client/dist/commands/invoke.js +49 -49
  10. package/packages/client/dist/commands/native-agent.d.ts +1 -0
  11. package/packages/client/dist/commands/native-agent.js +2 -0
  12. package/packages/client/dist/continuity/migrations/006-native-agent-dispatches.d.ts +9 -0
  13. package/packages/client/dist/continuity/migrations/006-native-agent-dispatches.js +48 -0
  14. package/packages/client/dist/continuity/native-agent-store.d.ts +13 -0
  15. package/packages/client/dist/continuity/native-agent-store.js +1 -0
  16. package/packages/client/dist/continuity/native-agent-types.d.ts +54 -0
  17. package/packages/client/dist/continuity/native-agent-types.js +1 -0
  18. package/packages/client/dist/continuity/sqlite-store.d.ts +43 -2
  19. package/packages/client/dist/continuity/sqlite-store.js +88 -62
  20. package/packages/client/dist/index.d.ts +1 -0
  21. package/packages/client/dist/index.js +1 -1
  22. package/packages/client/dist/yoloop/invoke-hooks.d.ts +4 -3
  23. package/packages/client/dist/yoloop/invoke-hooks.js +11 -11
  24. package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +21 -1
  25. package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +17 -1
  26. package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -1
  27. package/targets-stubs/antigravity/gemini.md +1 -1
  28. package/targets-stubs/antigravity/skill/SKILL.md +1 -1
  29. package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
  30. package/targets-stubs/claude-code/neocortex-root.md +2 -2
  31. package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
  32. package/targets-stubs/claude-code/neocortex.md +2 -2
  33. package/targets-stubs/codex/AGENTS.md +35 -2
  34. package/targets-stubs/codex/neocortex.toml +6 -0
  35. package/targets-stubs/cursor/agent.md +2 -2
  36. package/targets-stubs/gemini-cli/agent.md +2 -2
  37. package/targets-stubs/opencode/neocortex-root.md +1 -1
  38. package/targets-stubs/vscode/neocortex.agent.md +2 -2
@@ -53,6 +53,7 @@ export { ClientCircuitBreaker, type CircuitState, type CircuitBreakerConfig, typ
53
53
  export { OfflineTelemetryQueue, type TelemetryEvent, type QueueConfig, type QueueStats, type FlushResult, } from './telemetry/index.js';
54
54
  export { getCacheStatus, formatCacheStatus, type CacheStatusInfo, type CacheStatusOptions, } from './commands/cache-status.js';
55
55
  export { getSubagentApprovalPolicy, ensureManagedSubagentApprovalPolicy, setSubagentApprovalMode, resetSubagentApprovalMode, ApprovalPolicyConfigError, type ApprovalPolicyConfigOptions, type ApprovalPolicyConfigResult, } from './config.js';
56
+ export { deriveOpaqueNativeAgentHandle, openNativeAgentPrivateStore, resolveNativeAgentPrivateRuntimePaths, } from './continuity/native-agent-store.js';
56
57
  export { configCliHandler, type ConfigCliDependencies, } from './commands/config.js';
57
58
  export { storyCheckpointCliHandler, parseStoryCheckpointArgs, } from './commands/story-checkpoint.js';
58
59
  export { beginDirectYoloStoryCommit, finalizeDirectYoloStoryCheckpoint, issueDirectYoloSetupLeaseHandoff, prepareDirectYoloSetup, recoverLegacyDirectYoloStoryCheckpoint, type DirectYoloCheckpointOptions, type DirectYoloCheckpointResult, type DirectYoloCommitPlan, type DirectYoloSetupReceipt, type DirectYoloSetupHandoffReceipt, } from './git/direct-yolo-checkpoint.js';
@@ -1 +1 @@
1
- import{ResolverMode as o,NoOpCache as t}from"./types/index.js";import{PUBLIC_PROJECTION_BUNDLE as i,PUBLIC_PROJECTION_GENERATION_ID as p,PUBLIC_PROJECTION_BUNDLE_HASH as n}from"./generated/public-projections.generated.js";import{LocalResolver as c}from"./resolvers/local-resolver.js";import{RemoteResolver as s,RemoteResolverError as C}from"./resolvers/remote-resolver.js";import{EncryptedCache as d}from"./cache/index.js";import{createResolver as x,selectResolver as A}from"./config/resolver-selection.js";import{collectContext as S}from"./context/context-collector.js";import{sanitizeValue as u,sanitizeRecord as T,sanitizeObject as v}from"./context/context-sanitizer.js";import{getMachineFingerprint as E}from"./machine/index.js";import{LicenseClient as I}from"./license/index.js";import{ClaudeCodeAdapter as P,CursorAdapter as _,VSCodeAdapter as M,GeminiAdapter as h,CodexAdapter as L,AntigravityAdapter as k,AdapterRegistry as F,UnknownTargetError as b,createDefaultRegistry as B,detectPlatform as H,isValidTargetId as U}from"./adapters/index.js";import{ClientCircuitBreaker as G,DegradationManager as Y,DegradationLevel as w,FreshnessIndicator as z,RecoveryDetector as J}from"./resilience/index.js";import{OfflineTelemetryQueue as Q}from"./telemetry/index.js";import{getCacheStatus as K,formatCacheStatus as W}from"./commands/cache-status.js";import{getSubagentApprovalPolicy as Z,ensureManagedSubagentApprovalPolicy as $,setSubagentApprovalMode as ee,resetSubagentApprovalMode as re,ApprovalPolicyConfigError as oe}from"./config.js";import{configCliHandler as ae}from"./commands/config.js";import{storyCheckpointCliHandler as pe,parseStoryCheckpointArgs as ne}from"./commands/story-checkpoint.js";import{beginDirectYoloStoryCommit as ce,finalizeDirectYoloStoryCheckpoint as me,issueDirectYoloSetupLeaseHandoff as se,prepareDirectYoloSetup as Ce,recoverLegacyDirectYoloStoryCheckpoint as fe}from"./git/direct-yolo-checkpoint.js";import{FRONTMATTER_DIAGNOSTIC_CATEGORIES as ge,FRONTMATTER_DIAGNOSTIC_REASON_CODES as xe,getFrontmatterDiagnostic as Ae,formatFrontmatterDiagnostic as Re}from"./errors/frontmatter-diagnostics.js";import{invoke as ye,invokeCliHandler as ue,collectStateSnapshot as Te}from"./commands/invoke.js";import{TierAwareClient as De}from"./tier/index.js";import{buildProjectMemoryContent as Oe,createNodeProjectMemoryFs as Ie,writeProjectMemory as Ne,writeProjectMemoryTargetFiles as Pe}from"./memory/project-memory-writer.js";export{F as AdapterRegistry,k as AntigravityAdapter,oe as ApprovalPolicyConfigError,P as ClaudeCodeAdapter,G as ClientCircuitBreaker,L as CodexAdapter,_ as CursorAdapter,w as DegradationLevel,Y as DegradationManager,d as EncryptedCache,ge as FRONTMATTER_DIAGNOSTIC_CATEGORIES,xe as FRONTMATTER_DIAGNOSTIC_REASON_CODES,z as FreshnessIndicator,h as GeminiAdapter,I as LicenseClient,c as LocalResolver,t as NoOpCache,Q as OfflineTelemetryQueue,i as PUBLIC_PROJECTION_BUNDLE,n as PUBLIC_PROJECTION_BUNDLE_HASH,p as PUBLIC_PROJECTION_GENERATION_ID,J as RecoveryDetector,s as RemoteResolver,C as RemoteResolverError,o as ResolverMode,De as TierAwareClient,b as UnknownTargetError,M as VSCodeAdapter,ce as beginDirectYoloStoryCommit,Oe as buildProjectMemoryContent,S as collectContext,Te as collectStateSnapshot,ae as configCliHandler,B as createDefaultRegistry,Ie as createNodeProjectMemoryFs,x as createResolver,H as detectPlatform,$ as ensureManagedSubagentApprovalPolicy,me as finalizeDirectYoloStoryCheckpoint,W as formatCacheStatus,Re as formatFrontmatterDiagnostic,K as getCacheStatus,Ae as getFrontmatterDiagnostic,E as getMachineFingerprint,Z as getSubagentApprovalPolicy,ye as invoke,ue as invokeCliHandler,U as isValidTargetId,se as issueDirectYoloSetupLeaseHandoff,ne as parseStoryCheckpointArgs,Ce as prepareDirectYoloSetup,fe as recoverLegacyDirectYoloStoryCheckpoint,re as resetSubagentApprovalMode,v as sanitizeObject,T as sanitizeRecord,u as sanitizeValue,A as selectResolver,ee as setSubagentApprovalMode,pe as storyCheckpointCliHandler,Ne as writeProjectMemory,Pe as writeProjectMemoryTargetFiles};
1
+ import{ResolverMode as o,NoOpCache as t}from"./types/index.js";import{PUBLIC_PROJECTION_BUNDLE as i,PUBLIC_PROJECTION_GENERATION_ID as n,PUBLIC_PROJECTION_BUNDLE_HASH as p}from"./generated/public-projections.generated.js";import{LocalResolver as c}from"./resolvers/local-resolver.js";import{RemoteResolver as s,RemoteResolverError as f}from"./resolvers/remote-resolver.js";import{EncryptedCache as d}from"./cache/index.js";import{createResolver as A,selectResolver as x}from"./config/resolver-selection.js";import{collectContext as R}from"./context/context-collector.js";import{sanitizeValue as u,sanitizeRecord as y,sanitizeObject as O}from"./context/context-sanitizer.js";import{getMachineFingerprint as D}from"./machine/index.js";import{LicenseClient as N}from"./license/index.js";import{ClaudeCodeAdapter as I,CursorAdapter as _,VSCodeAdapter as h,GeminiAdapter as M,CodexAdapter as L,AntigravityAdapter as k,AdapterRegistry as F,UnknownTargetError as b,createDefaultRegistry as H,detectPlatform as B,isValidTargetId as U}from"./adapters/index.js";import{ClientCircuitBreaker as G,DegradationManager as Y,DegradationLevel as w,FreshnessIndicator as z,RecoveryDetector as J}from"./resilience/index.js";import{OfflineTelemetryQueue as q}from"./telemetry/index.js";import{getCacheStatus as K,formatCacheStatus as W}from"./commands/cache-status.js";import{getSubagentApprovalPolicy as Z,ensureManagedSubagentApprovalPolicy as $,setSubagentApprovalMode as ee,resetSubagentApprovalMode as re,ApprovalPolicyConfigError as oe}from"./config.js";import{deriveOpaqueNativeAgentHandle as ae,openNativeAgentPrivateStore as ie,resolveNativeAgentPrivateRuntimePaths as ne}from"./continuity/native-agent-store.js";import{configCliHandler as le}from"./commands/config.js";import{storyCheckpointCliHandler as me,parseStoryCheckpointArgs as se}from"./commands/story-checkpoint.js";import{beginDirectYoloStoryCommit as Ce,finalizeDirectYoloStoryCheckpoint as de,issueDirectYoloSetupLeaseHandoff as ge,prepareDirectYoloSetup as Ae,recoverLegacyDirectYoloStoryCheckpoint as xe}from"./git/direct-yolo-checkpoint.js";import{FRONTMATTER_DIAGNOSTIC_CATEGORIES as Re,FRONTMATTER_DIAGNOSTIC_REASON_CODES as Se,getFrontmatterDiagnostic as ue,formatFrontmatterDiagnostic as ye}from"./errors/frontmatter-diagnostics.js";import{invoke as Te,invokeCliHandler as De,collectStateSnapshot as Ee}from"./commands/invoke.js";import{TierAwareClient as Pe}from"./tier/index.js";import{buildProjectMemoryContent as _e,createNodeProjectMemoryFs as he,writeProjectMemory as Me,writeProjectMemoryTargetFiles as Le}from"./memory/project-memory-writer.js";export{F as AdapterRegistry,k as AntigravityAdapter,oe as ApprovalPolicyConfigError,I as ClaudeCodeAdapter,G as ClientCircuitBreaker,L as CodexAdapter,_ as CursorAdapter,w as DegradationLevel,Y as DegradationManager,d as EncryptedCache,Re as FRONTMATTER_DIAGNOSTIC_CATEGORIES,Se as FRONTMATTER_DIAGNOSTIC_REASON_CODES,z as FreshnessIndicator,M as GeminiAdapter,N as LicenseClient,c as LocalResolver,t as NoOpCache,q as OfflineTelemetryQueue,i as PUBLIC_PROJECTION_BUNDLE,p as PUBLIC_PROJECTION_BUNDLE_HASH,n as PUBLIC_PROJECTION_GENERATION_ID,J as RecoveryDetector,s as RemoteResolver,f as RemoteResolverError,o as ResolverMode,Pe as TierAwareClient,b as UnknownTargetError,h as VSCodeAdapter,Ce as beginDirectYoloStoryCommit,_e as buildProjectMemoryContent,R as collectContext,Ee as collectStateSnapshot,le as configCliHandler,H as createDefaultRegistry,he as createNodeProjectMemoryFs,A as createResolver,ae as deriveOpaqueNativeAgentHandle,B as detectPlatform,$ as ensureManagedSubagentApprovalPolicy,de as finalizeDirectYoloStoryCheckpoint,W as formatCacheStatus,ye as formatFrontmatterDiagnostic,K as getCacheStatus,ue as getFrontmatterDiagnostic,D as getMachineFingerprint,Z as getSubagentApprovalPolicy,Te as invoke,De as invokeCliHandler,U as isValidTargetId,ge as issueDirectYoloSetupLeaseHandoff,ie as openNativeAgentPrivateStore,se as parseStoryCheckpointArgs,Ae as prepareDirectYoloSetup,xe as recoverLegacyDirectYoloStoryCheckpoint,re as resetSubagentApprovalMode,ne as resolveNativeAgentPrivateRuntimePaths,O as sanitizeObject,y as sanitizeRecord,u as sanitizeValue,x as selectResolver,ee as setSubagentApprovalMode,me as storyCheckpointCliHandler,Me as writeProjectMemory,Le as writeProjectMemoryTargetFiles};
@@ -7,7 +7,7 @@
7
7
  * Returns undefined (no-op) for non-yoloop invocations to avoid I/O.
8
8
  * - `persistYoloopFromResponse(metadata, projectRoot)` — post-response;
9
9
  * if the server returned `yoloopStateUpdate`, apply operations locally.
10
- * Authoritative rollover failures are returned to the invoke boundary;
10
+ * Authoritative rollover/successor-transition failures are returned to the invoke boundary;
11
11
  * auxiliary legacy updates retain bounded fail-soft compatibility.
12
12
  *
13
13
  * Trigger detection is regex-based over the first token of `args`, aligned
@@ -87,8 +87,9 @@ export declare function readYoloopForRequest(args: string, projectRoot: string,
87
87
  /**
88
88
  * Post-response hook: apply server-provided operations to local state.
89
89
  * Safe to call for any response — no-op if no yoloopStateUpdate present.
90
- * A `rollover_session` update is authoritative: failure is returned to the
91
- * caller so instructions cannot be released before durable state exists.
90
+ * A `rollover_session` or `commit_successor_transition` update is
91
+ * authoritative: failure is returned to the caller so instructions cannot be
92
+ * released before durable state exists.
92
93
  * Non-rollover legacy operations retain fail-soft compatibility.
93
94
  */
94
95
  export declare function persistYoloopFromResponse(metadata: Record<string, unknown> | undefined, projectRoot: string, nowIso?: string): Promise<YoloopPersistenceResult>;
@@ -1,12 +1,12 @@
1
- import{statSync as G}from"node:fs";import{join as q}from"node:path";import{YoloopClientStateStore as D}from"./yoloop-client-state-store.js";import{isYoloopInvocation as J}from"./target-normalization.js";import{applyStateMigration as X,StateMigrationApplyError as Q}from"../migrations/state-json.js";function ee(e){return J(e)}const j=Object.freeze({stateReadFailed:"YOLOOP_STATE_READ_FAILED",authoritativeWritebackFailed:"YOLOOP_AUTHORITATIVE_WRITEBACK_FAILED",auxiliaryWritebackFailed:"YOLOOP_AUXILIARY_WRITEBACK_FAILED"});class te extends Error{reasonCode;constructor(o){super(o),this.reasonCode=o,this.name="YoloopStateReadError"}}function W(e,o){return(e instanceof Error?e.message:String(e)).match(/\bYOLOOP_[A-Z0-9_]+\b/)?.[0]??o}const oe=/^\s*\*?(yoloop|auto-yolo|epic-runner|story-runner|loop-yolo|auto-epic)\b/i;function ue(e){if(typeof e.args!="string"||e.args.length===0)return;const o=e.args.match(oe);if(!o)return;const i=o[0];if(e.args.slice(i.length).trim()!=="")return;let a=!1;try{const t=q(e.projectRoot,"docs","epics");a=G(t).isDirectory()}catch(t){const s=t instanceof Error?t.message:String(t);e.logger?.warn?.(`[Neocortex] Zero-config *yoloop hook (P121.05): could not stat docs/epics/: ${s}. Proceeding with raw args.`);return}a&&(e.args=`${i} @docs/epics/`,e.logger?.info?.("[Neocortex] Zero-config *yoloop (P121.05): auto-resolved empty args to @docs/epics/"))}async function ye(e,o,i){if(ee(e))try{return await new D(o).readAll(i)}catch(r){const a=W(r,j.stateReadFailed);throw process.stderr.write(`[yoloop] ${a}. Local yoloop authority was not read; no request was sent.
2
- `),new te(a)}}async function fe(e,o,i){if(!e)return{ok:!0,authoritative:!1,reasonCodes:[]};const r=e.yoloopStateUpdate;if(!r||!Array.isArray(r.operations)||r.operations.length===0)return{ok:!0,authoritative:!1,reasonCodes:[]};const a=r.operations.some(t=>t.type==="rollover_session");try{return await new D(o).applyUpdate(r,i),{ok:!0,authoritative:a,reasonCodes:[]}}catch(t){const s=W(t,a?j.authoritativeWritebackFailed:j.auxiliaryWritebackFailed);return a?(process.stderr.write(`[yoloop] ${s}. Authoritative rollover was not persisted; no continuation instructions were released.
3
- `),{ok:!1,authoritative:!0,reasonCodes:[s]}):(process.stderr.write(`[yoloop] ${s}. Auxiliary state update was not persisted; retry the same command.
4
- `),{ok:!0,authoritative:!1,reasonCodes:[s]})}}function n(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function L(e,o){return Array.isArray(e)&&e.length<=o&&e.every(i=>typeof i=="string"&&i.length>0&&i.length<=160&&/^[A-Za-z0-9_.:+-]+$/.test(i))}function U(e){return n(e.scope)?e.scope.kind==="projected"||typeof e.scope.omittedStoryCount=="number"&&e.scope.omittedStoryCount>0||typeof e.scope.omittedEpicCount=="number"&&e.scope.omittedEpicCount>0:!1}function ie(e){const o={...e};return delete o.scope,delete o.stateSummary,delete o.graphRetrieval,delete o.runnerBootstrap,delete o.projectEvidence,delete o.continuity,delete o.implementCheckpoint,o}function re(e){return typeof e=="string"&&["done","completed","merged"].includes(e.trim().toLowerCase())}function ne(e){return/^[A-Za-z0-9][A-Za-z0-9._/-]{0,119}$/.test(e)&&!e.includes("..")&&!e.includes("//")&&!e.includes("@{")&&!e.endsWith("/")&&!e.endsWith(".")&&!e.endsWith(".lock")}async function ae(e,o){const i=e.syntheticStory;if(!n(i))return{applied:!1,blocking:!0,reasonCode:"inline-yolo-mutation-missing"};const r=i.schemaVersion,a=i.epicId,t=i.storyId,s=i.storyPath,m=i.deterministicKey,b=i.storyContent,A=i.storyContentSha256,p=i.lifecycle;if(r!==2||typeof a!="string"||!/^P9\d{18}$/.test(a)||typeof t!="string"||t!==`${a}.01.000001`||typeof s!="string"||s!==`docs/stories/${t}.story.md`||typeof m!="string"||!/^[a-f0-9]{16}$/.test(m)||typeof A!="string"||!/^[a-f0-9]{64}$/.test(A)||typeof b!="string"||b.length===0||b.length>131072||!n(p)||p.branchMode!=="epic"||p.executionBranch!==`epic/${a}`||typeof p.originBranch!="string"||!ne(p.originBranch)||typeof p.graphRevision!="string"||!/^[a-f0-9]{64}$/.test(p.graphRevision)||p.isolatedSyntheticEpic!==!0||i.publicSafe!==!0||i.sanitized!==!0)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-mutation-invalid"};const d=await import("node:fs/promises"),h=await import("node:path"),I=await import("node:crypto");if(I.createHash("sha256").update(b).digest("hex")!==A)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-story-content-integrity-invalid"};const C=h.join(o,".neocortex"),O=h.join(C,"state.json"),w=h.join(o,...s.split("/"));let R;try{R=await d.readFile(O,"utf8")}catch{return{applied:!1,blocking:!0,reasonCode:"inline-yolo-state-missing"}}const v=I.createHash("sha256").update(R).digest("hex");let u;try{u=JSON.parse(R)}catch{return{applied:!1,blocking:!0,reasonCode:"inline-yolo-state-corrupt"}}if(!n(u)||!n(u.stories)||!n(u.epics)||U(u))return{applied:!1,blocking:!0,reasonCode:"inline-yolo-state-not-full"};if(!n(u.config)||u.config.default_branch!==p.originBranch)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-origin-branch-conflict"};const l=u.stories[t];if(l!==void 0&&(!n(l)||l.epic_id!==a||l.story_file!==s||!n(l.inlineYolo)||l.inlineYolo.deterministicKey!==m))return{applied:!1,blocking:!0,reasonCode:"inline-yolo-story-conflict"};const y=u.epics[a];if(y!==void 0&&(!n(y)||y.id!==a||y.source!=="inline-yolo-materialization"||y.branch_mode!=="epic"||y.execution_branch!==p.executionBranch||y.origin_branch!==p.originBranch||y.graph_revision!==p.graphRevision||!n(y.inlineYoloLifecycle)||y.inlineYoloLifecycle.deterministicKey!==m||y.inlineYoloLifecycle.isolatedSyntheticEpic!==!0||!Array.isArray(y.stories)))return{applied:!1,blocking:!0,reasonCode:"inline-yolo-epic-conflict"};const E=n(y)?y:{},S=Array.isArray(E.stories)?E.stories:[];if(S.some(c=>typeof c!="string")||new Set(S).size!==S.length)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-epic-story-list-invalid"};for(const c of S){const f=u.stories[c];if(!n(f)||f.id!==c||f.epic_id!==a)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-epic-ownership-conflict"}}try{const c=await d.readFile(w,"utf8"),f=c.includes(`id: ${t}`)&&c.includes(`synthetic_key: ${m}`);if(c!==b&&!f)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-story-file-conflict"}}catch(c){if(c.code!=="ENOENT")return{applied:!1,blocking:!0,reasonCode:"inline-yolo-story-file-unreadable"}}const k=S.includes(t)?[...S]:[...S,t],P={...u.stories,[t]:{...n(l)?l:{},id:t,epic_id:a,title:"Synthetic inline USER STORY for yolo",status:n(l)&&typeof l.status=="string"?l.status:"backlog",steps_completed:n(l)&&Array.isArray(l.steps_completed)?l.steps_completed:[],last_step:n(l)?l.last_step??null:null,branch_name:n(l)?l.branch_name??null:null,story_file:s,source:"inline-yolo-materialization",inlineYolo:{...n(l)&&n(l.inlineYolo)?l.inlineYolo:{},schemaVersion:2,deterministicKey:m,publicSafe:!0,sanitized:!0,materializedBeforeExecution:!0,ephemeralExecutionForbidden:!0}}},z=k.filter(c=>n(P[c])&&re(P[c].status)).length,x=n(u.inlineYolo)?u.inlineYolo:{},K=n(x.materializations)?x.materializations:{},Z=ie({...u,stories:P,epics:{...u.epics,[a]:{...E,id:a,title:typeof E.title=="string"?E.title:"Isolated synthetic inline yolo lifecycle",status:z===k.length&&k.length>0?"done":"in-progress",source:"inline-yolo-materialization",branch_mode:"epic",execution_branch:p.executionBranch,origin_branch:p.originBranch,graph_revision:p.graphRevision,stories:k,total_stories:k.length,completed_stories:z,...z===k.length&&k.length>0?{}:{completed_at:null},inlineYoloLifecycle:{schemaVersion:2,deterministicKey:m,isolatedSyntheticEpic:!0}}},inlineYolo:{...x,schemaVersion:2,materializations:{...K,[t]:{schemaVersion:2,epicId:a,storyId:t,storyPath:s,deterministicKey:m,storyContentSha256:A,sourceStateSha256:v,lifecycle:p,publicSafe:!0,sanitized:!0,materializedBeforeExecution:!0,ephemeralExecutionForbidden:!0,pipelineTrigger:`*yolo @${s}`,reasonCodes:Array.isArray(i.reasonCodes)?i.reasonCodes:[]}}},last_updated:new Date().toISOString()}),N=`${Date.now()}-${I.randomBytes(6).toString("hex")}`,Y=h.join(C,`state.json.tmp.${N}`),T=`${w}.tmp.${N}`,F=h.join(C,`state.json.backup-${new Date().toISOString().replace(/[:.]/g,"-")}`),H=h.join(C,"state.json.inline-yolo.lock");let M=!1,_;const V=async c=>{let f;try{f=await d.open(c,"r"),await f.sync()}catch(g){const $=g.code;if(!["EINVAL","ENOTSUP","EPERM","EISDIR"].includes($??""))throw g}finally{await f?.close().catch(()=>{})}},B=async(c,f)=>{const g=await d.open(c,"wx",384);try{await g.writeFile(f,"utf8"),await g.sync()}finally{await g.close()}};try{await d.mkdir(C,{recursive:!0}),await d.mkdir(h.dirname(w),{recursive:!0});try{_=await d.open(H,"wx",384),await _.writeFile(`${process.pid}
5
- ${v}
6
- `,"utf8"),await _.sync()}catch($){if($.code==="EEXIST")return{applied:!1,blocking:!0,reasonCode:"inline-yolo-writeback-locked"};throw $}const c=await d.readFile(O,"utf8");if(I.createHash("sha256").update(c).digest("hex")!==v)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-state-cas-conflict"};try{await d.access(w)}catch{await B(T,b),await d.rename(T,w),await V(h.dirname(w)),M=!0}await d.copyFile(O,F);const g=await d.open(F,"r");try{await g.sync()}finally{await g.close()}return await B(Y,JSON.stringify(Z,null,2)),await d.rename(Y,O),await V(C),process.stderr.write(`[Neocortex] inline yolo story materialized with bounded full-state merge; story=${t}; backup=${h.basename(F)}.
7
- `),{applied:!0,blocking:!1,reasonCode:"inline-yolo-materialized"}}catch(c){await Promise.allSettled([d.unlink(Y),d.unlink(T)]),M&&await d.readFile(w,"utf8").catch(()=>{})===b&&await d.unlink(w).catch(()=>{});const f=c.message??String(c);return process.stderr.write(`[Neocortex] inline yolo materialization failed: ${f}.
8
- `),{applied:!1,blocking:!0,reasonCode:"inline-yolo-persistence-failed"}}finally{await _?.close().catch(()=>{}),_&&await d.unlink(H).catch(()=>{})}}async function ge(e,o){if(!e||e.stateMutated!==!0)return{applied:!1,blocking:!1,reasonCode:"state-writeback-not-requested"};if(e.stateMutationStrategy==="merge-inline-yolo-v2"||e.stateMutationReason==="inline-yolo-materialized-synthetic-story")return ae(e,o);if(e.stateMutationStrategy==="state-migration-v1"||e.stateMigrationPlan!==void 0){const r=e.stateMigrationPlan,a=new Set(["schemaVersion","operationId","sourceSchemaVersion","targetSchemaVersion","sourceCanonicalHash","targetCanonicalHash","steps","migratedEpicIds","migratedStoryIds","preservedUnknownFieldCount","reasonCodes"]);if(!n(r)||Object.keys(r).some(t=>!a.has(t))||r.schemaVersion!=="StateMigrationPlan/1.0"||typeof r.operationId!="string"||!/^smig_[a-f0-9]{32}$/.test(r.operationId)||typeof r.sourceCanonicalHash!="string"||!/^[a-f0-9]{64}$/.test(r.sourceCanonicalHash)||typeof r.targetCanonicalHash!="string"||!/^[a-f0-9]{64}$/.test(r.targetCanonicalHash)||![0,1,"absent"].includes(r.sourceSchemaVersion)||r.targetSchemaVersion!==1||!Array.isArray(r.steps)||r.steps.length>8192||r.steps.some(t=>!n(t)||Object.keys(t).some(s=>!["kind","source","target"].includes(s))||!["initialize-collection","merge-epic","merge-story","preserve-legacy","remove-legacy","set-schema-version"].includes(String(t.kind))||typeof t.target!="string"||t.target.length>512||!/^[A-Za-z0-9_.:[\]-]+$/.test(t.target)||t.source!==void 0&&(typeof t.source!="string"||t.source.length>512||!/^[A-Za-z0-9_.:[\]-]+$/.test(t.source)))||!L(r.migratedEpicIds,4096)||!L(r.migratedStoryIds,4096)||!L(r.reasonCodes,32)||!Number.isSafeInteger(r.preservedUnknownFieldCount)||r.preservedUnknownFieldCount<0)return{applied:!1,blocking:!0,reasonCode:"state-migration-plan-missing-or-invalid"};try{const t=X(o,r),s=`.neocortex/state.json.migration-backup-${t.operationId}`;return process.stderr.write(`[P220-EV-STATE-MIGRATION] outcome=${t.outcome}; operation=${t.operationId}; backup=${t.backupHash?s:"none"}.
9
- `),{applied:t.outcome==="applied",blocking:!1,reasonCode:t.outcome==="applied"?"state-migration-applied":"state-migration-replay-verified"}}catch(t){const s=t instanceof Q?t.reasonCode:"state-migration-apply-failed";return process.stderr.write(`[P220-EV-STATE-MIGRATION] blocked=${s}.
10
- `),{applied:!1,blocking:!0,reasonCode:s}}}const i=e.migratedState;return!i||typeof i!="object"||Array.isArray(i)?{applied:!1,blocking:!0,reasonCode:"state-writeback-payload-missing"}:U(i)?(process.stderr.write(`[Neocortex] Refused projected/partial state replacement; canonical state was not modified.
1
+ import{statSync as q}from"node:fs";import{join as J}from"node:path";import{YoloopClientStateStore as U}from"./yoloop-client-state-store.js";import{isYoloopInvocation as X}from"./target-normalization.js";import{applyStateMigration as Q,StateMigrationApplyError as ee}from"../migrations/state-json.js";function te(e){return X(e)}const N=Object.freeze({stateReadFailed:"YOLOOP_STATE_READ_FAILED",authoritativeWritebackFailed:"YOLOOP_AUTHORITATIVE_WRITEBACK_FAILED",auxiliaryWritebackFailed:"YOLOOP_AUXILIARY_WRITEBACK_FAILED"});class oe extends Error{reasonCode;constructor(o){super(o),this.reasonCode=o,this.name="YoloopStateReadError"}}function L(e,o){return(e instanceof Error?e.message:String(e)).match(/\bYOLOOP_[A-Z0-9_]+\b/)?.[0]??o}const W=new Set(["YOLOOP_RUN_REVISION_CONFLICT","YOLOOP_RUN_SNAPSHOT_CONFLICT","YOLOOP_SUCCESSOR_TRANSITION_STATE_CONFLICT","EAGAIN","EBUSY","EMFILE","ENFILE"]);function re(e){const o=L(e,"");if(W.has(o))return!0;const r=e?.code;return typeof r=="string"&&W.has(r)}const ie=/^\s*\*?(yoloop|auto-yolo|epic-runner|story-runner|loop-yolo|auto-epic)\b/i;function ye(e){if(typeof e.args!="string"||e.args.length===0)return;const o=e.args.match(ie);if(!o)return;const r=o[0];if(e.args.slice(r.length).trim()!=="")return;let n=!1;try{const t=J(e.projectRoot,"docs","epics");n=q(t).isDirectory()}catch(t){const l=t instanceof Error?t.message:String(t);e.logger?.warn?.(`[Neocortex] Zero-config *yoloop hook (P121.05): could not stat docs/epics/: ${l}. Proceeding with raw args.`);return}n&&(e.args=`${r} @docs/epics/`,e.logger?.info?.("[Neocortex] Zero-config *yoloop (P121.05): auto-resolved empty args to @docs/epics/"))}async function ge(e,o,r){if(te(e))try{return await new U(o).readAll(r)}catch(i){const n=L(i,N.stateReadFailed);throw process.stderr.write(`[yoloop] ${n}. Local yoloop authority was not read; no request was sent.
2
+ `),new oe(n)}}async function he(e,o,r){if(!e)return{ok:!0,authoritative:!1,reasonCodes:[]};const i=e.yoloopStateUpdate;if(!i||!Array.isArray(i.operations)||i.operations.length===0)return{ok:!0,authoritative:!1,reasonCodes:[]};const n=i.operations.some(p=>p.type==="rollover_session"||p.type==="commit_successor_transition");let t;const l=n?3:1;for(let p=0;p<l;p+=1)try{return await new U(o).applyUpdate(i,r),{ok:!0,authoritative:n,reasonCodes:[]}}catch(u){if(t=u,!n||p+1>=l||!re(u))break}{const u=L(t,n?N.authoritativeWritebackFailed:N.auxiliaryWritebackFailed);return n?(process.stderr.write(`[yoloop] ${u}. Authoritative yoloop transition was not persisted; no continuation instructions were released.
3
+ `),{ok:!1,authoritative:!0,reasonCodes:[u]}):(process.stderr.write(`[yoloop] ${u}. Auxiliary state update was not persisted; retry the same command.
4
+ `),{ok:!0,authoritative:!1,reasonCodes:[u]})}}function a(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function j(e,o){return Array.isArray(e)&&e.length<=o&&e.every(r=>typeof r=="string"&&r.length>0&&r.length<=160&&/^[A-Za-z0-9_.:+-]+$/.test(r))}function G(e){return a(e.scope)?e.scope.kind==="projected"||typeof e.scope.omittedStoryCount=="number"&&e.scope.omittedStoryCount>0||typeof e.scope.omittedEpicCount=="number"&&e.scope.omittedEpicCount>0:!1}function ne(e){const o={...e};return delete o.scope,delete o.stateSummary,delete o.graphRetrieval,delete o.runnerBootstrap,delete o.projectEvidence,delete o.continuity,delete o.implementCheckpoint,o}function ae(e){return typeof e=="string"&&["done","completed","merged"].includes(e.trim().toLowerCase())}function se(e){return/^[A-Za-z0-9][A-Za-z0-9._/-]{0,119}$/.test(e)&&!e.includes("..")&&!e.includes("//")&&!e.includes("@{")&&!e.endsWith("/")&&!e.endsWith(".")&&!e.endsWith(".lock")}async function ce(e,o){const r=e.syntheticStory;if(!a(r))return{applied:!1,blocking:!0,reasonCode:"inline-yolo-mutation-missing"};const i=r.schemaVersion,n=r.epicId,t=r.storyId,l=r.storyPath,p=r.deterministicKey,u=r.storyContent,A=r.storyContentSha256,f=r.lifecycle;if(i!==2||typeof n!="string"||!/^P9\d{18}$/.test(n)||typeof t!="string"||t!==`${n}.01.000001`||typeof l!="string"||l!==`docs/stories/${t}.story.md`||typeof p!="string"||!/^[a-f0-9]{16}$/.test(p)||typeof A!="string"||!/^[a-f0-9]{64}$/.test(A)||typeof u!="string"||u.length===0||u.length>131072||!a(f)||f.branchMode!=="epic"||f.executionBranch!==`epic/${n}`||typeof f.originBranch!="string"||!se(f.originBranch)||typeof f.graphRevision!="string"||!/^[a-f0-9]{64}$/.test(f.graphRevision)||f.isolatedSyntheticEpic!==!0||r.publicSafe!==!0||r.sanitized!==!0)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-mutation-invalid"};const d=await import("node:fs/promises"),S=await import("node:path"),O=await import("node:crypto");if(O.createHash("sha256").update(u).digest("hex")!==A)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-story-content-integrity-invalid"};const C=S.join(o,".neocortex"),I=S.join(C,"state.json"),w=S.join(o,...l.split("/"));let P;try{P=await d.readFile(I,"utf8")}catch{return{applied:!1,blocking:!0,reasonCode:"inline-yolo-state-missing"}}const $=O.createHash("sha256").update(P).digest("hex");let y;try{y=JSON.parse(P)}catch{return{applied:!1,blocking:!0,reasonCode:"inline-yolo-state-corrupt"}}if(!a(y)||!a(y.stories)||!a(y.epics)||G(y))return{applied:!1,blocking:!0,reasonCode:"inline-yolo-state-not-full"};if(!a(y.config)||y.config.default_branch!==f.originBranch)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-origin-branch-conflict"};const c=y.stories[t];if(c!==void 0&&(!a(c)||c.epic_id!==n||c.story_file!==l||!a(c.inlineYolo)||c.inlineYolo.deterministicKey!==p))return{applied:!1,blocking:!0,reasonCode:"inline-yolo-story-conflict"};const g=y.epics[n];if(g!==void 0&&(!a(g)||g.id!==n||g.source!=="inline-yolo-materialization"||g.branch_mode!=="epic"||g.execution_branch!==f.executionBranch||g.origin_branch!==f.originBranch||g.graph_revision!==f.graphRevision||!a(g.inlineYoloLifecycle)||g.inlineYoloLifecycle.deterministicKey!==p||g.inlineYoloLifecycle.isolatedSyntheticEpic!==!0||!Array.isArray(g.stories)))return{applied:!1,blocking:!0,reasonCode:"inline-yolo-epic-conflict"};const E=a(g)?g:{},b=Array.isArray(E.stories)?E.stories:[];if(b.some(s=>typeof s!="string")||new Set(b).size!==b.length)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-epic-story-list-invalid"};for(const s of b){const h=y.stories[s];if(!a(h)||h.id!==s||h.epic_id!==n)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-epic-ownership-conflict"}}try{const s=await d.readFile(w,"utf8"),h=s.includes(`id: ${t}`)&&s.includes(`synthetic_key: ${p}`);if(s!==u&&!h)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-story-file-conflict"}}catch(s){if(s.code!=="ENOENT")return{applied:!1,blocking:!0,reasonCode:"inline-yolo-story-file-unreadable"}}const k=b.includes(t)?[...b]:[...b,t],T={...y.stories,[t]:{...a(c)?c:{},id:t,epic_id:n,title:"Synthetic inline USER STORY for yolo",status:a(c)&&typeof c.status=="string"?c.status:"backlog",steps_completed:a(c)&&Array.isArray(c.steps_completed)?c.steps_completed:[],last_step:a(c)?c.last_step??null:null,branch_name:a(c)?c.branch_name??null:null,story_file:l,source:"inline-yolo-materialization",inlineYolo:{...a(c)&&a(c.inlineYolo)?c.inlineYolo:{},schemaVersion:2,deterministicKey:p,publicSafe:!0,sanitized:!0,materializedBeforeExecution:!0,ephemeralExecutionForbidden:!0}}},v=k.filter(s=>a(T[s])&&ae(T[s].status)).length,Y=a(y.inlineYolo)?y.inlineYolo:{},K=a(Y.materializations)?Y.materializations:{},Z=ne({...y,stories:T,epics:{...y.epics,[n]:{...E,id:n,title:typeof E.title=="string"?E.title:"Isolated synthetic inline yolo lifecycle",status:v===k.length&&k.length>0?"done":"in-progress",source:"inline-yolo-materialization",branch_mode:"epic",execution_branch:f.executionBranch,origin_branch:f.originBranch,graph_revision:f.graphRevision,stories:k,total_stories:k.length,completed_stories:v,...v===k.length&&k.length>0?{}:{completed_at:null},inlineYoloLifecycle:{schemaVersion:2,deterministicKey:p,isolatedSyntheticEpic:!0}}},inlineYolo:{...Y,schemaVersion:2,materializations:{...K,[t]:{schemaVersion:2,epicId:n,storyId:t,storyPath:l,deterministicKey:p,storyContentSha256:A,sourceStateSha256:$,lifecycle:f,publicSafe:!0,sanitized:!0,materializedBeforeExecution:!0,ephemeralExecutionForbidden:!0,pipelineTrigger:`*yolo @${l}`,reasonCodes:Array.isArray(r.reasonCodes)?r.reasonCodes:[]}}},last_updated:new Date().toISOString()}),V=`${Date.now()}-${O.randomBytes(6).toString("hex")}`,z=S.join(C,`state.json.tmp.${V}`),x=`${w}.tmp.${V}`,F=S.join(C,`state.json.backup-${new Date().toISOString().replace(/[:.]/g,"-")}`),H=S.join(C,"state.json.inline-yolo.lock");let M=!1,_;const B=async s=>{let h;try{h=await d.open(s,"r"),await h.sync()}catch(m){const R=m.code;if(!["EINVAL","ENOTSUP","EPERM","EISDIR"].includes(R??""))throw m}finally{await h?.close().catch(()=>{})}},D=async(s,h)=>{const m=await d.open(s,"wx",384);try{await m.writeFile(h,"utf8"),await m.sync()}finally{await m.close()}};try{await d.mkdir(C,{recursive:!0}),await d.mkdir(S.dirname(w),{recursive:!0});try{_=await d.open(H,"wx",384),await _.writeFile(`${process.pid}
5
+ ${$}
6
+ `,"utf8"),await _.sync()}catch(R){if(R.code==="EEXIST")return{applied:!1,blocking:!0,reasonCode:"inline-yolo-writeback-locked"};throw R}const s=await d.readFile(I,"utf8");if(O.createHash("sha256").update(s).digest("hex")!==$)return{applied:!1,blocking:!0,reasonCode:"inline-yolo-state-cas-conflict"};try{await d.access(w)}catch{await D(x,u),await d.rename(x,w),await B(S.dirname(w)),M=!0}await d.copyFile(I,F);const m=await d.open(F,"r");try{await m.sync()}finally{await m.close()}return await D(z,JSON.stringify(Z,null,2)),await d.rename(z,I),await B(C),process.stderr.write(`[Neocortex] inline yolo story materialized with bounded full-state merge; story=${t}; backup=${S.basename(F)}.
7
+ `),{applied:!0,blocking:!1,reasonCode:"inline-yolo-materialized"}}catch(s){await Promise.allSettled([d.unlink(z),d.unlink(x)]),M&&await d.readFile(w,"utf8").catch(()=>{})===u&&await d.unlink(w).catch(()=>{});const h=s.message??String(s);return process.stderr.write(`[Neocortex] inline yolo materialization failed: ${h}.
8
+ `),{applied:!1,blocking:!0,reasonCode:"inline-yolo-persistence-failed"}}finally{await _?.close().catch(()=>{}),_&&await d.unlink(H).catch(()=>{})}}async function me(e,o){if(!e||e.stateMutated!==!0)return{applied:!1,blocking:!1,reasonCode:"state-writeback-not-requested"};if(e.stateMutationStrategy==="merge-inline-yolo-v2"||e.stateMutationReason==="inline-yolo-materialized-synthetic-story")return ce(e,o);if(e.stateMutationStrategy==="state-migration-v1"||e.stateMigrationPlan!==void 0){const i=e.stateMigrationPlan,n=new Set(["schemaVersion","operationId","sourceSchemaVersion","targetSchemaVersion","sourceCanonicalHash","targetCanonicalHash","steps","migratedEpicIds","migratedStoryIds","preservedUnknownFieldCount","reasonCodes"]);if(!a(i)||Object.keys(i).some(t=>!n.has(t))||i.schemaVersion!=="StateMigrationPlan/1.0"||typeof i.operationId!="string"||!/^smig_[a-f0-9]{32}$/.test(i.operationId)||typeof i.sourceCanonicalHash!="string"||!/^[a-f0-9]{64}$/.test(i.sourceCanonicalHash)||typeof i.targetCanonicalHash!="string"||!/^[a-f0-9]{64}$/.test(i.targetCanonicalHash)||![0,1,"absent"].includes(i.sourceSchemaVersion)||i.targetSchemaVersion!==1||!Array.isArray(i.steps)||i.steps.length>8192||i.steps.some(t=>!a(t)||Object.keys(t).some(l=>!["kind","source","target"].includes(l))||!["initialize-collection","merge-epic","merge-story","preserve-legacy","remove-legacy","set-schema-version"].includes(String(t.kind))||typeof t.target!="string"||t.target.length>512||!/^[A-Za-z0-9_.:[\]-]+$/.test(t.target)||t.source!==void 0&&(typeof t.source!="string"||t.source.length>512||!/^[A-Za-z0-9_.:[\]-]+$/.test(t.source)))||!j(i.migratedEpicIds,4096)||!j(i.migratedStoryIds,4096)||!j(i.reasonCodes,32)||!Number.isSafeInteger(i.preservedUnknownFieldCount)||i.preservedUnknownFieldCount<0)return{applied:!1,blocking:!0,reasonCode:"state-migration-plan-missing-or-invalid"};try{const t=Q(o,i),l=`.neocortex/state.json.migration-backup-${t.operationId}`;return process.stderr.write(`[P220-EV-STATE-MIGRATION] outcome=${t.outcome}; operation=${t.operationId}; backup=${t.backupHash?l:"none"}.
9
+ `),{applied:t.outcome==="applied",blocking:!1,reasonCode:t.outcome==="applied"?"state-migration-applied":"state-migration-replay-verified"}}catch(t){const l=t instanceof ee?t.reasonCode:"state-migration-apply-failed";return process.stderr.write(`[P220-EV-STATE-MIGRATION] blocked=${l}.
10
+ `),{applied:!1,blocking:!0,reasonCode:l}}}const r=e.migratedState;return!r||typeof r!="object"||Array.isArray(r)?{applied:!1,blocking:!0,reasonCode:"state-writeback-payload-missing"}:G(r)?(process.stderr.write(`[Neocortex] Refused projected/partial state replacement; canonical state was not modified.
11
11
  `),{applied:!1,blocking:!0,reasonCode:"state-writeback-partial-rejected"}):(process.stderr.write(`[P220-EV-STATE-MIGRATION] blocked=state-migration-plan-missing-or-invalid; canonical state was not modified.
12
- `),{applied:!1,blocking:!0,reasonCode:"state-migration-plan-missing-or-invalid"})}async function he(e){if(!e.featureFlag)return{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:"flag off"};try{return await(await import("./discovery-hook.js")).runDiscoveryHook(e)}catch(o){const i=o instanceof Error?o.message:String(o);return e.logger?.warn?.(`[neocortex] discovery hook (lazy load) failed: ${i}. Proceeding without enrichment.`),{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:`lazy load error: ${i}`}}}async function me(e){if(!e.featureFlag)return{applied:!1,reason:"flag_off"};try{return await(await import("../graph-retrieval/pre-command-hook.js")).runGraphRetrievalHook(e)}catch(o){const i=o instanceof Error?o.message:String(o);return e.logger?.warn?.(`[neocortex] graph retrieval hook (lazy load) failed: ${i}. Proceeding without enrichment.`),{applied:!1,reason:"hook_error",warning:i}}}export{j as YOLOOP_PERSISTENCE_REASON_CODES,te as YoloopStateReadError,ee as isYoloopTrigger,ue as maybeAutoResolveYoloopArgs,he as maybeRunDiscoveryHook,me as maybeRunGraphRetrievalHook,ge as persistMigratedStateFromResponse,fe as persistYoloopFromResponse,ye as readYoloopForRequest};
12
+ `),{applied:!1,blocking:!0,reasonCode:"state-migration-plan-missing-or-invalid"})}async function Se(e){if(!e.featureFlag)return{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:"flag off"};try{return await(await import("./discovery-hook.js")).runDiscoveryHook(e)}catch(o){const r=o instanceof Error?o.message:String(o);return e.logger?.warn?.(`[neocortex] discovery hook (lazy load) failed: ${r}. Proceeding without enrichment.`),{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:`lazy load error: ${r}`}}}async function we(e){if(!e.featureFlag)return{applied:!1,reason:"flag_off"};try{return await(await import("../graph-retrieval/pre-command-hook.js")).runGraphRetrievalHook(e)}catch(o){const r=o instanceof Error?o.message:String(o);return e.logger?.warn?.(`[neocortex] graph retrieval hook (lazy load) failed: ${r}. Proceeding without enrichment.`),{applied:!1,reason:"hook_error",warning:r}}}export{N as YOLOOP_PERSISTENCE_REASON_CODES,oe as YoloopStateReadError,te as isYoloopTrigger,ye as maybeAutoResolveYoloopArgs,Se as maybeRunDiscoveryHook,we as maybeRunGraphRetrievalHook,me as persistMigratedStateFromResponse,he as persistYoloopFromResponse,ge as readYoloopForRequest};
@@ -27,7 +27,7 @@ export type YoloopSessionMode = 'directory' | 'epic-file' | 'epic-id';
27
27
  export type YoloopLockOwnerKind = 'client' | 'server';
28
28
  export type YoloopLockOwnerPidState = 'live' | 'stale' | 'unknown';
29
29
  export type YoloopLockLeaseState = 'active' | 'expired' | 'unknown';
30
- export type YoloopPersistenceCapability = 'rollover-session-v1';
30
+ export type YoloopPersistenceCapability = 'rollover-session-v1' | 'successor-transition-v1';
31
31
  /** Lock file payload. Mirrors server-internal `LockMetadata` (v1.1 schema). */
32
32
  export interface YoloopPersistedLock {
33
33
  readonly pid: number;
@@ -300,6 +300,26 @@ export type YoloopStateOperation = {
300
300
  readonly expectedSnapshotHash: string | null;
301
301
  readonly payloadHash: string;
302
302
  readonly next: YoloopRunControlV1;
303
+ } | {
304
+ /**
305
+ * Recoverable CAS envelope for the successor boundary. The client
306
+ * journals this operation before replacing the exhausted run, consuming
307
+ * the completed-story authority and reserving the next authority.
308
+ */
309
+ readonly type: 'commit_successor_transition';
310
+ readonly operationId: string;
311
+ readonly idempotencyKey: string;
312
+ readonly payloadHash: string;
313
+ readonly successor: Extract<YoloopStateOperation, {
314
+ readonly type: 'start_successor_run';
315
+ }>;
316
+ readonly state: YoloopPersistedCounters;
317
+ readonly acknowledgement?: Extract<YoloopStateOperation, {
318
+ readonly type: 'acknowledge_continuation_authority';
319
+ }>;
320
+ readonly reservation?: Extract<YoloopStateOperation, {
321
+ readonly type: 'reserve_continuation_authority';
322
+ }>;
303
323
  } | {
304
324
  readonly type: 'rollover_session';
305
325
  readonly runId: string;
@@ -23,10 +23,13 @@
23
23
  * setSecureFilePermissions helper from secure-config.ts.
24
24
  */
25
25
  import type { YoloopPersistedCounters, YoloopPersistedState, YoloopRecoveryAttemptRef, YoloopRunControlV1, YoloopRunTransitionReceiptV1, YoloopStateOperation, YoloopStateUpdate } from './shared-yoloop-types.js';
26
- export declare const YOLOOP_PERSISTENCE_CAPABILITIES: readonly ["rollover-session-v1"];
26
+ export declare const YOLOOP_PERSISTENCE_CAPABILITIES: readonly ["rollover-session-v1", "successor-transition-v1"];
27
27
  type YoloopSessionRolloverOperation = Extract<YoloopStateOperation, {
28
28
  readonly type: 'rollover_session';
29
29
  }>;
30
+ type YoloopSuccessorTransitionOperation = Extract<YoloopStateOperation, {
31
+ readonly type: 'commit_successor_transition';
32
+ }>;
30
33
  /** Minimal Pino-compatible logger subset. */
31
34
  export interface ClientYoloopLogger {
32
35
  warn(payload: object, msg?: string): void;
@@ -43,6 +46,7 @@ export declare class YoloopClientStateStore {
43
46
  private readonly lockPath;
44
47
  private readonly mutationLockPath;
45
48
  private readonly rolloverManifestPath;
49
+ private readonly successorTransitionManifestPath;
46
50
  private readonly logger;
47
51
  constructor(projectRoot: string, logger?: ClientYoloopLogger);
48
52
  /**
@@ -119,6 +123,17 @@ export declare class YoloopClientStateStore {
119
123
  private recoverSessionRolloverIfPresent;
120
124
  private readRolloverManifest;
121
125
  private writeRolloverManifest;
126
+ /**
127
+ * Journal the predecessor replacement, completed-story acknowledgement and
128
+ * next authority reservation as one recoverable logical CAS transition.
129
+ * Individual state-file renames remain atomic; the prepared/applied manifest
130
+ * closes every crash window between them.
131
+ */
132
+ private commitSuccessorTransition;
133
+ private completePreparedSuccessorTransition;
134
+ private recoverSuccessorTransitionIfPresent;
135
+ private readSuccessorTransitionManifest;
136
+ private writeSuccessorTransitionManifest;
122
137
  /**
123
138
  * Advance to next epic: read-modify-write on currentSession.currentEpicIndex.
124
139
  * Fail-open if no active session (logs warn; subsequent *yoloop will
@@ -158,6 +173,7 @@ export declare function buildYoloopSessionRolloverPayloadHash(operation: Omit<Yo
158
173
  export declare function buildYoloopSuccessorRunPayloadHash(operation: Omit<Extract<YoloopStateOperation, {
159
174
  readonly type: 'start_successor_run';
160
175
  }>, 'type' | 'payloadHash'>): string;
176
+ export declare function buildYoloopSuccessorTransitionPayloadHash(operation: Omit<YoloopSuccessorTransitionOperation, 'type' | 'payloadHash'>): string;
161
177
  export declare function buildYoloopRunTransitionPayloadHash(input: {
162
178
  readonly runId: string;
163
179
  readonly operationId: string;
@@ -1 +1 @@
1
- import{promises as u}from"node:fs";import{createHash as D}from"node:crypto";import{join as _,dirname as U}from"node:path";import{hostname as I}from"node:os";import{setSecureFilePermissions as F,setSecureDirPermissions as K}from"../config/secure-config.js";import{RECOVERY_HISTORY_CAP as g}from"./shared-yoloop-types.js";const b=".neocortex",m="yoloop-state.json",V="yoloop.lock",M="yoloop-state.mutation.lock",T="yoloop-session-rollover.json",q=360*60*1e3,$=3e4,B=200,C=Object.freeze(["rollover-session-v1"]),J={warn:()=>{},info:()=>{},error:()=>{}};function S(t){const e=t.slice(0,10);return{version:"1.1",lastResetAt:t,storiesRunToday:0,iterationsToday:0,iterationsTodayDate:e,tokensUsedToday:0,lastRunAt:null,coolDownUntil:null,totalRunsAllTime:0,totalStoriesAllTime:0,currentSession:null,continuationPolicy:"p205-finite-resume-v2",pendingContinuationAuthorities:[],continuationReceipts:[],continuationRecoveryReceipts:[]}}function ue(t){return{lock:null,state:S(t),capabilities:C}}class he{stateDir;statePath;lockPath;mutationLockPath;rolloverManifestPath;logger;constructor(e,n=J){this.stateDir=_(e,b),this.statePath=_(this.stateDir,m),this.lockPath=_(this.stateDir,V),this.mutationLockPath=_(this.stateDir,M),this.rolloverManifestPath=_(this.stateDir,T),this.logger=n}async readAll(e){const n=e??new Date().toISOString();await this.cleanupOrphanTempFiles(),await this.recoverSessionRolloverIfPresent(n);const[r,s]=await Promise.all([this.readLock(),this.readState(n)]);return{lock:await this.prepareLockForSnapshot(r,n),state:s,capabilities:C}}async applyUpdate(e,n){const r=n??new Date().toISOString();await this.ensureDir(),await this.recoverSessionRolloverIfPresent(r);for(const s of e.operations)await this.applyOperation(s,r)}async requestRunTransition(e,n){const r=n??new Date().toISOString();return await this.ensureDir(),this.withMutationLock(()=>this.transitionRun(e,r))}async requestLifecycleAction(e,n={},r){const s=r??new Date().toISOString();return await this.ensureDir(),this.withMutationLock(async()=>{const i=(await this.readState(s)).runControl;if(!i)throw new Error("YOLOOP_RUN_TRANSITION_INVALID");const a=Date.parse(s).toString(36),c=n.operationId??`op-${e}-${a}`,l=n.idempotencyKey??`idem-${e}-${a}`,h=i.receipts.find(O=>O.operationId===c||O.idempotencyKey===l);if(h){if(h.operationId===c&&h.idempotencyKey===l)return h;throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}const y=Z(i.status,e);if(!y)throw new Error(R.has(i.status)?"YOLOOP_RUN_TERMINAL":"YOLOOP_RUN_TRANSITION_INVALID");return this.transitionRun(ee({current:i,action:e,target:y,operationId:c,idempotencyKey:l,occurredAt:s}),s)})}async applyOperation(e,n){switch(e.type){case"acquire_lock":await this.acquireLock(e.lock,n);return;case"release_lock":await this.releaseLock(e);return;case"write_state":await this.withMutationLock(async()=>{const r=await this.readState(n),{runControl:s,...o}=e.state;await this.writeState({...o,...r.runControl?{version:"1.2",runControl:r.runControl}:{}})});return;case"advance_epic":await this.advanceEpic(e.nextEpicIndex,e.nextEpicId,n);return;case"no_op":this.logger.info({event:"yoloop_noop"},"yoloop server sent no-op");return;case"reserve_continuation_authority":await this.reserveContinuationAuthority(e.authority,n);return;case"acknowledge_continuation_authority":await this.acknowledgeContinuationAuthority(e.idempotencyKey,e.receipt,n);return;case"repair_continuation_authority":await this.repairContinuationAuthority(e.beforeHash,e.authority,e.receipt,n);return;case"switch_continuation_policy":await this.switchContinuationPolicy(e.policy,e.session,n);return;case"transition_run":await this.requestRunTransition(e,n);return;case"start_successor_run":await this.withMutationLock(()=>this.startSuccessorRun(e,n));return;case"rollover_session":await this.withMutationLock(()=>this.rolloverSession(e,n));return;case"recovery_attempted":await this.appendRecoveryAttempt(e.attempt,n);return;case"recovery_resolved":await this.resolveRecoveryAttempt(e.attempt_id,e.outcome,n);return;default:{const r=e;throw this.logger.error({event:"yoloop_unknown_op",op:r},"unknown yoloop operation rejected"),new Error("YOLOOP_STATE_OPERATION_UNSUPPORTED")}}}async reserveContinuationAuthority(e,n){const r=await this.readState(n),s=r.pendingContinuationAuthorities??[],o=typeof e.idempotencyKey=="string"?e.idempotencyKey:"";if(!o)throw new Error("YOLOOP_CONTINUATION_AUTHORITY_INVALID");const i=s.find(a=>a.idempotencyKey===o);if(i){if(d(i)===d(e))return;throw new Error("YOLOOP_CONTINUATION_AUTHORITY_CONFLICT")}if(s.length>=64)throw new Error("YOLOOP_PENDING_AUTHORITY_CAPACITY_EXCEEDED");await this.writeState({...r,pendingContinuationAuthorities:[...s,e]})}async acknowledgeContinuationAuthority(e,n,r){const s=await this.readState(r),o=s.pendingContinuationAuthorities??[],i=o.findIndex(h=>h.idempotencyKey===e);if(i<0)throw new Error("YOLOOP_CONTINUATION_RECEIPT_ORPHAN");const a=o[i];if(n.idempotencyKey!==e||n.sessionId!==a.sessionId||JSON.stringify(n.storyIds)!==JSON.stringify(a.storyIds))throw new Error("YOLOOP_CONTINUATION_RECEIPT_MISMATCH");const c=o.filter((h,y)=>y!==i),l=s.continuationReceipts??[];await this.writeState({...s,pendingContinuationAuthorities:c,continuationReceipts:[...l.slice(-63),n]})}async repairContinuationAuthority(e,n,r,s){const o=await this.readState(s),i=o.pendingContinuationAuthorities??[],a=o.continuationRecoveryReceipts??[],c=typeof r.idempotencyKey=="string"?r.idempotencyKey:"",l=a.find(O=>O.idempotencyKey===c);if(l){if(d(l)===d(r))return;throw new Error("YOLOOP_CONTINUATION_RECOVERY_RECEIPT_CONFLICT")}if(i.length!==1||p("p208-legacy-authority-before-v1",i[0])!==e)throw new Error("YOLOOP_CONTINUATION_RECOVERY_BEFORE_MISMATCH");const h=p("p208-legacy-authority-after-v1",n);if(r.beforeHash!==e||r.afterHash!==h)throw new Error("YOLOOP_CONTINUATION_RECOVERY_HASH_MISMATCH");const y={...r};if(delete y.idempotencyKey,!c||p("p208-legacy-authority-recovery-receipt-v1",y)!==c)throw new Error("YOLOOP_CONTINUATION_RECOVERY_RECEIPT_INVALID");await this.writeState({...o,pendingContinuationAuthorities:[n],continuationRecoveryReceipts:[...a.slice(-63),r]})}async switchContinuationPolicy(e,n,r){const s=await this.readState(r);if(s.currentSession||(s.pendingContinuationAuthorities?.length??0)>0)throw new Error("YOLOOP_POLICY_SWITCH_ACTIVE");try{await u.copyFile(this.statePath,`${this.statePath}.policy-backup`)}catch(o){if(o.code!=="ENOENT")throw o}await this.writeState({...s,continuationPolicy:e,continuationSession:n})}async appendRecoveryAttempt(e,n){const r=await this.readState(n),s=r.recovery_history??[];if(s.some(c=>c.attempted_at===e.attempted_at&&c.story_id===e.story_id)){this.logger.warn({event:"recovery_attempted_duplicate",story_id:e.story_id},"duplicate recovery_attempted op; skipping");return}const i=H([...s,e]),a={...r,recovery_history:i};await this.writeState(a),this.logger.info({event:"recovery_attempted_persisted",story_id:e.story_id,history_size:i.length},"recovery attempt persisted")}async resolveRecoveryAttempt(e,n,r){const s=await this.readState(r),o=s.recovery_history??[],i=o.findIndex(h=>h.recovery_step_id_tokenized===e);if(i===-1){this.logger.warn({event:"recovery_resolve_orphan",attempt_id:e},"recovery_resolved op had no matching attempt; skipping");return}const a=o[i];if(a.outcome===n&&a.finished_at){this.logger.info({event:"recovery_resolved_duplicate",attempt_id:e,outcome:n},"duplicate recovery_resolved op; skipping");return}const c=o.slice();c[i]={...a,outcome:n,finished_at:r};const l={...s,recovery_history:c};await this.writeState(l),this.logger.info({event:"recovery_resolved_persisted",attempt_id:e,outcome:n},"recovery attempt resolved")}async acquireLock(e,n){const r={...e,pid:process.pid,hostname:I(),ownerKind:"client",startedAt:e.startedAt||n,leaseId:e.leaseId??ne(e.sessionId,n),leaseState:"active",leaseAcquiredAt:e.leaseAcquiredAt??n,leaseDurationMs:e.leaseDurationMs??q,leaseExpiresAt:e.leaseExpiresAt??e.ttlExpiresAt},s=JSON.stringify(r,null,2);try{const o=await u.open(this.lockPath,"wx");try{await o.writeFile(s,"utf8")}finally{await o.close()}this.trySetFilePerms(this.lockPath),this.logger.info({event:"yoloop_lock_acquired",pid:r.pid,sessionId:r.sessionId},"yoloop lock acquired");return}catch(o){const i=o;if(i.code!=="EEXIST")throw this.logger.error({event:"yoloop_lock_acquire_error",err:i.message},"failed to acquire yoloop lock"),o;const a=await this.readLock();if(a&&this.isSameClientSessionLock(a,r)){this.logger.info({event:"yoloop_lock_acquire_duplicate",sessionId:r.sessionId},"duplicate acquire_lock for current yoloop session; treating as no-op");return}if(!await this.maybeRecoverOrphanLock(n))throw this.logger.warn({event:"yoloop_lock_held"},"yoloop lock held by another live process"),o;const l=await u.open(this.lockPath,"wx");try{await l.writeFile(s,"utf8")}finally{await l.close()}this.trySetFilePerms(this.lockPath),this.logger.info({event:"yoloop_lock_acquired_after_recovery",pid:r.pid},"yoloop lock acquired after orphan recovery")}}async releaseLock(e){const n=await this.readState(new Date().toISOString()),r=await this.readLock();if(n.runControl){if(!e.expectedRunId||!e.expectedSessionId||!e.expectedLeaseId)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if(e.expectedRunId!==n.runControl.runId)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if(!r||e.expectedSessionId!==r.sessionId||e.expectedLeaseId!==r.leaseId)throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}try{await u.unlink(this.lockPath),this.logger.info({event:"yoloop_lock_released"},"yoloop lock released")}catch(s){const o=s;if(o.code==="ENOENT"){this.logger.info({event:"yoloop_lock_release_noop"},"yoloop lock release noop (file absent)");return}this.logger.warn({event:"yoloop_lock_release_error",err:o.message},"unexpected error releasing yoloop lock")}}async readLock(){try{const e=await u.readFile(this.lockPath,"utf8"),n=JSON.parse(e),r=n.currentEpicId??n.epicId??"";return{pid:n.pid??0,hostname:n.hostname??"",...n.ownerKind?{ownerKind:n.ownerKind}:{},...n.ownerPidState?{ownerPidState:n.ownerPidState}:{},...typeof n.leaseId=="string"?{leaseId:n.leaseId}:{},...n.leaseState?{leaseState:n.leaseState}:{},...typeof n.leaseAcquiredAt=="string"?{leaseAcquiredAt:n.leaseAcquiredAt}:{},...typeof n.leaseDurationMs=="number"?{leaseDurationMs:n.leaseDurationMs}:{},...typeof n.leaseExpiresAt=="string"?{leaseExpiresAt:n.leaseExpiresAt}:{},startedAt:n.startedAt??"",sessionId:n.sessionId??"",mode:n.mode??"epic-id",inputPath:n.inputPath??"",epicQueue:n.epicQueue??(r?[r]:[]),currentEpicIndex:n.currentEpicIndex??0,currentEpicId:r,ttlExpiresAt:n.ttlExpiresAt??"",epicId:n.epicId??r}}catch{return null}}async readState(e){try{const n=await u.readFile(this.statePath,"utf8"),r=JSON.parse(n);return re(r,e)}catch(n){const r=n;return r.code!=="ENOENT"&&this.logger.warn({event:"yoloop_state_read_error",err:r.message},"yoloop state file unreadable; using defaults"),S(e)}}async writeState(e){const n=`${this.statePath}.tmp.${process.pid}.${Date.now()}`,r=JSON.stringify(e,null,2);try{const s=await u.open(n,"w",384);try{await s.writeFile(r,"utf8"),await s.sync()}finally{await s.close()}this.trySetFilePerms(n),await u.rename(n,this.statePath),await this.syncStateDirectory()}catch(s){const o=s;this.logger.error({event:"yoloop_state_write_error",err:o.message},"failed to write yoloop state");try{await u.unlink(n)}catch{}throw s}}async rolloverSession(e,n){f(e);const r=await this.readRolloverManifest();if(r){if(G(r.operation,e)){if(r.operation.payloadHash!==e.payloadHash)throw new Error("YOLOOP_SESSION_ROLLOVER_CONFLICT");if(r.phase==="applied")return;await this.completePreparedSessionRollover(r.operation,n);return}else if(r.phase==="prepared")throw new Error("YOLOOP_SESSION_ROLLOVER_CONFLICT")}const s=await this.readState(n),o=await this.readLock();P(e,s,o),await this.writeRolloverManifest({schemaVersion:"YoloopSessionRolloverManifest/1.0",phase:"prepared",operation:e}),await this.completePreparedSessionRollover(e,n)}async completePreparedSessionRollover(e,n){const r=await this.readState(n);let s=d(r)===d(e.next);if(!s){const i=await this.readLock();P(e,r,i),await this.writeState(e.next),s=!0}const o=await this.readLock();if(e.expectedSessionId===null||e.expectedLeaseId===null){if(e.expectedSessionId!==null||e.expectedLeaseId!==null||o)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT")}else if(o){if(o.sessionId!==e.expectedSessionId||o.leaseId!==e.expectedLeaseId)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT");await u.unlink(this.lockPath),await this.syncStateDirectory()}else if(!s)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT");await this.writeRolloverManifest({schemaVersion:"YoloopSessionRolloverManifest/1.0",phase:"applied",operation:e}),this.logger.info({event:"yoloop_session_rollover_applied",runId:e.runId,operationId:e.operationId,coolDownUntil:e.coolDownUntil},"yoloop per-run-cap session rollover applied")}async recoverSessionRolloverIfPresent(e){try{await u.access(this.rolloverManifestPath)}catch(n){if(n.code==="ENOENT")return;throw n}await this.ensureDir(),await this.withMutationLock(async()=>{const n=await this.readRolloverManifest();n?.phase==="prepared"&&await this.completePreparedSessionRollover(n.operation,e)})}async readRolloverManifest(){try{const e=JSON.parse(await u.readFile(this.rolloverManifestPath,"utf8"));if(e.schemaVersion!=="YoloopSessionRolloverManifest/1.0"||e.phase!=="prepared"&&e.phase!=="applied"||!e.operation||e.operation.type!=="rollover_session")throw new Error("YOLOOP_SESSION_ROLLOVER_MANIFEST_CORRUPT");return f(e.operation),e}catch(e){if(e.code==="ENOENT")return null;throw e.message==="YOLOOP_SESSION_ROLLOVER_MANIFEST_CORRUPT"?e:new Error("YOLOOP_SESSION_ROLLOVER_MANIFEST_CORRUPT")}}async writeRolloverManifest(e){const n=`${this.rolloverManifestPath}.tmp.${process.pid}.${Date.now()}`,r=await u.open(n,"w",384);try{await r.writeFile(JSON.stringify(e,null,2),"utf8"),await r.sync()}finally{await r.close()}this.trySetFilePerms(n),await u.rename(n,this.rolloverManifestPath),await this.syncStateDirectory()}async advanceEpic(e,n,r){const s=await this.readState(r);if(!s.currentSession){this.logger.warn({event:"yoloop_advance_no_session",nextEpicId:n},"advance_epic with no active session; skipping");return}const o={...s,currentSession:{...s.currentSession,currentEpicIndex:e}};await this.writeState(o),this.logger.info({event:"yoloop_epic_advance",nextEpicId:n,nextIndex:e},"yoloop advanced to next epic")}async ensureDir(){try{await u.mkdir(this.stateDir,{recursive:!0}),this.trySetDirPerms(this.stateDir)}catch(e){const n=e;throw this.logger.error({event:"yoloop_mkdir_error",err:n.message,path:this.stateDir},"failed to ensure .neocortex/ directory"),e}}async syncStateDirectory(){try{const e=await u.open(this.stateDir,"r");try{await e.sync()}finally{await e.close()}}catch(e){const n=e.code;if(n!=="EINVAL"&&n!=="EISDIR"&&n!=="ENOTSUP"&&n!=="EPERM")throw e}}async withMutationLock(e){let n=null;for(let r=0;r<B;r+=1)try{n=await u.open(this.mutationLockPath,"wx",384),await n.writeFile(JSON.stringify({pid:process.pid,acquiredAt:new Date().toISOString()})),await n.sync();break}catch(s){if(s.code!=="EEXIST")throw s;try{const o=await u.stat(this.mutationLockPath);if(Date.now()-o.mtimeMs>$){await u.unlink(this.mutationLockPath);continue}}catch{continue}await new Promise(o=>setTimeout(o,5))}if(!n)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");try{return await e()}finally{await n.close().catch(()=>{}),await u.unlink(this.mutationLockPath).catch(()=>{})}}async transitionRun(e,n){v(e);const r=await this.readState(n),s=r.runControl,o=s?.receipts.find(l=>l.operationId===e.operationId||l.idempotencyKey===e.idempotencyKey);if(o){if(o.operationId===e.operationId&&o.idempotencyKey===e.idempotencyKey&&o.payloadHash===e.payloadHash)return o;throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}if(s&&s.runId!==e.runId)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if((s?.revision??0)!==e.expectedRevision)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if((s?.latestSnapshotHash??null)!==e.expectedSnapshotHash)throw new Error("YOLOOP_RUN_SNAPSHOT_CONFLICT");E(s,e);const c=e.next.receipts.at(-1);if(!c)throw new Error("YOLOOP_RUN_OPERATION_CONFLICT");return await this.writeState({...r,version:"1.2",runControl:e.next}),this.logger.info({event:"yoloop_run_transition_committed",runId:e.runId,operationId:e.operationId,revision:c.revision,status:c.status},"yoloop run transition committed"),c}async startSuccessorRun(e,n){X(e);const r=await this.readState(n),s=r.runControl,o={schemaVersion:"YoloopRunPredecessor/1.0",runId:e.previousRunId,revision:e.expectedRevision,snapshotHash:e.expectedSnapshotHash,successorOperationId:e.operationId,publicSafe:!0},i=s?.receipts.find(l=>l.operationId===e.operationId||l.idempotencyKey===e.idempotencyKey);if(i){if(i.operationId===e.operationId&&i.idempotencyKey===e.idempotencyKey&&e.next.receipts.at(-1)?.payloadHash===i.payloadHash&&d(s?.predecessor)===d(o))return i;throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}if(!s||s.runId!==e.previousRunId||s.status!=="exhausted"||s.revision!==e.expectedRevision||s.latestSnapshotHash!==e.expectedSnapshotHash||r.currentSession!==null)throw new Error("YOLOOP_RUN_SUCCESSOR_CONFLICT");const a=e.next.receipts.at(-1);if(!a||d(e.next.predecessor)!==d(o))throw new Error("YOLOOP_RUN_SUCCESSOR_CONFLICT");const c={type:"transition_run",runId:e.runId,operationId:e.operationId,idempotencyKey:e.idempotencyKey,expectedRevision:0,expectedSnapshotHash:null,payloadHash:a.payloadHash,next:e.next};return v(c),E(void 0,c),await this.writeState({...r,version:"1.2",runControl:e.next}),a}trySetFilePerms(e){try{F(e)}catch{}}trySetDirPerms(e){try{K(e)}catch{}}async prepareLockForSnapshot(e,n){if(!e)return null;if(e.ownerKind!=="client")return e;const r=k(e,n),s={...e,leaseState:r};if(r==="expired")return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_client_lock_recovered",reason:"lease_expired"},"expired client-owned yoloop lock lease recovered before snapshot echo"),null;if(!s.pid||s.pid<=0)return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_client_lock_recovered",reason:"invalid_pid"},"invalid PID in client-owned yoloop lock; recovered"),null;if(s.hostname&&s.hostname!==I())return{...s,ownerPidState:"unknown"};try{return process.kill(s.pid,0),{...s,ownerPidState:"live"}}catch{return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_client_lock_recovered",reason:"dead_pid"},"stale client-owned yoloop lock recovered before snapshot echo"),null}}async maybeRecoverOrphanLock(e){const n=await this.readLock();if(!n)return!0;if(k(n,e)==="expired")return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_orphan_lock_recovered",reason:"lease_expired"},"expired yoloop lock lease recovered"),!0;if(!n.pid||n.pid<=0)return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_orphan_lock_recovered",reason:"invalid_pid"},"invalid PID in lock file; recovered"),!0;if(n.hostname&&n.hostname!==I())return this.logger.warn({event:"yoloop_lock_remote_host",ownerKind:n.ownerKind??"server",ownerPidState:"unknown"},"lock held by a remote host; honoring"),!1;try{return process.kill(n.pid,0),!1}catch{return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_orphan_lock_recovered",reason:"dead_pid"},"orphan yoloop lock recovered"),!0}}async deleteLockBestEffort(){try{await u.unlink(this.lockPath)}catch{}}isSameClientSessionLock(e,n){return e.ownerKind==="client"&&e.sessionId===n.sessionId&&e.pid===process.pid&&e.hostname===I()}async cleanupOrphanTempFiles(){try{const e=U(this.statePath),n=await u.readdir(e),r=[`${m}.tmp.`,`${T}.tmp.`],s=n.filter(o=>r.some(i=>o.startsWith(i)));for(const o of s)try{await u.unlink(_(e,o))}catch{}}catch{}}}function d(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?`[${t.map(d).join(",")}]`:`{${Object.entries(t).filter(([,e])=>e!==void 0).sort(([e],[n])=>e.localeCompare(n)).map(([e,n])=>`${JSON.stringify(e)}:${d(n)}`).join(",")}}`}function p(t,e){return D("sha256").update(`${t}\0${d(e)}`).digest("hex")}function j(t){return p("p9390812898200217364-yoloop-session-v1",t)}function z(t){return p("p9390812898200217364-yoloop-rollover-v1",t)}function W(t){return p("p9390812898200217364-yoloop-successor-run-v1",t)}function G(t,e){return t.operationId===e.operationId&&t.idempotencyKey===e.idempotencyKey}function f(t){const e=/^[A-Za-z0-9._:-]{1,128}$/,n={runId:t.runId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,expectedRevision:t.expectedRevision,expectedSnapshotHash:t.expectedSnapshotHash,expectedSessionId:t.expectedSessionId,expectedSessionFingerprint:t.expectedSessionFingerprint,expectedLeaseId:t.expectedLeaseId,coolDownUntil:t.coolDownUntil,reason:t.reason,exhaustedRun:t.exhaustedRun,next:t.next};if(!e.test(t.runId)||!e.test(t.operationId)||!e.test(t.idempotencyKey)||!/^[a-f0-9]{64}$/.test(t.expectedSessionFingerprint)||!/^[a-f0-9]{64}$/.test(t.payloadHash)||!Number.isSafeInteger(t.expectedRevision)||t.expectedRevision<0||!Number.isFinite(Date.parse(t.coolDownUntil))||!["YOLOOP_PER_RUN_CAP_REACHED","YOLOOP_SESSION_TIMEOUT"].includes(t.reason)||t.payloadHash!==z(n)||t.receipt.schemaVersion!=="YoloopSessionRolloverReceipt/1.0"||t.receipt.runId!==t.runId||t.receipt.operationId!==t.operationId||t.receipt.idempotencyKey!==t.idempotencyKey||t.receipt.payloadHash!==t.payloadHash||t.receipt.coolDownUntil!==t.coolDownUntil||t.receipt.revision!==(t.exhaustedRun?.revision??0)||t.receipt.snapshotHash!==(t.exhaustedRun?.latestSnapshotHash??null)||t.receipt.status!=="exhausted"||t.receipt.publicSafe!==!0)throw new Error("YOLOOP_SESSION_ROLLOVER_CONFLICT");if(t.expectedSessionId===null!=(t.expectedLeaseId===null)||t.expectedSessionId!==null&&!e.test(t.expectedSessionId)||t.expectedLeaseId!==null&&!e.test(t.expectedLeaseId))throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT")}function X(t){const e=/^[A-Za-z0-9._:-]{1,128}$/,n={runId:t.runId,previousRunId:t.previousRunId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,expectedRevision:t.expectedRevision,expectedSnapshotHash:t.expectedSnapshotHash,next:t.next};if(!e.test(t.runId)||!e.test(t.previousRunId)||t.runId===t.previousRunId||!e.test(t.operationId)||!e.test(t.idempotencyKey)||!/^[a-f0-9]{64}$/.test(t.payloadHash)||!Number.isSafeInteger(t.expectedRevision)||t.expectedRevision<1||t.payloadHash!==W(n))throw new Error("YOLOOP_RUN_SUCCESSOR_CONFLICT")}function P(t,e,n){f(t);const r=e.currentSession;if(!r||j(r)!==t.expectedSessionFingerprint)throw new Error("YOLOOP_SESSION_ROLLOVER_SESSION_CONFLICT");const s=e.runControl;if((s?.revision??0)!==t.expectedRevision||(s?.latestSnapshotHash??null)!==t.expectedSnapshotHash||s&&s.runId!==t.runId)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if(t.expectedSessionId===null||t.expectedLeaseId===null){if(n)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT")}else if(!n||n.sessionId!==t.expectedSessionId||n.leaseId!==t.expectedLeaseId)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT");const o=t.exhaustedRun;if(s)if(s.status==="exhausted"){if(d(o)!==d(s))throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT")}else{if(!o||o.status!=="exhausted")throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT");const a=o.receipts.at(-1);if(!a)throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT");const c={type:"transition_run",runId:s.runId,operationId:a.operationId,idempotencyKey:a.idempotencyKey,expectedRevision:s.revision,expectedSnapshotHash:s.latestSnapshotHash,payloadHash:a.payloadHash,next:o};v(c),E(s,c)}else{const a=o?.receipts[0],c=o?.receipts[1];if(o&&(o.runId!==t.runId||o.status!=="exhausted"||o.revision!==2||o.events.length!==2||o.progressSnapshots.length!==4||o.receipts.length!==2||a?.runId!==t.runId||a.revision!==1||a.status!=="created"||c?.runId!==t.runId||c.revision!==2||c.status!=="exhausted"||c.operationId!==`${t.operationId}:run`||c.idempotencyKey!==`${t.idempotencyKey}:run`||o.latestSnapshotHash!==c.snapshotHash||o.predecessor!==void 0))throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT")}const i={...e,version:"1.2",coolDownUntil:t.coolDownUntil,currentSession:null,...o?{runControl:o}:{}};if(d(i)!==d(t.next))throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT")}function x(t){const{receipts:e,...n}=t.next;return p("p220-yoloop-run-transition-payload-v1",{runId:t.runId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,expectedRevision:t.expectedRevision,expectedSnapshotHash:t.expectedSnapshotHash,next:n})}const R=new Set(["success","partial","blocked","failure","exhausted","cancelled"]),Q={created:["running","cancelling","exhausted"],running:["pausing","cancelling","success","partial","blocked","failure","exhausted"],pausing:["paused","cancelling","failure","exhausted"],paused:["resuming","cancelling","exhausted"],resuming:["running","cancelling","failure","exhausted"],cancelling:["cancelled","failure","exhausted"]};function Z(t,e){return e==="pause"?t==="running"?"pausing":null:e==="resume"?t==="paused"?"resuming":null:R.has(t)||t==="cancelling"?null:"cancelling"}function ee(t){const e=t.current.revision+1,n=t.action==="cancel"?["YOLOOP_RUN_CANCEL_REQUESTED"]:[],r={schemaVersion:"YoloopOperationalBudgetSummary/1.0",limits:t.current.operationalBudget.limits,usage:t.current.usage,exhaustedDimension:null},s={schemaVersion:"ProgressSnapshot/1.0",runId:t.current.runId,sequence:t.current.progressSnapshots.length+1,revision:e,operationId:t.operationId,boundary:t.action,phase:"before",status:t.current.status,occurredAt:t.occurredAt,parentSnapshotHash:t.current.latestSnapshotHash,budget:r,reasonCodes:n,publicSafe:!0},o=p("p220-yoloop-progress-snapshot-id-v1",{runId:s.runId,operationId:s.operationId,sequence:s.sequence,phase:s.phase}),i={...s,snapshotId:o,snapshotHash:p("p220-yoloop-progress-snapshot-v1",{...s,snapshotId:o})},a={...s,sequence:i.sequence+1,phase:"after",status:t.target,parentSnapshotHash:i.snapshotHash},c=p("p220-yoloop-progress-snapshot-id-v1",{runId:a.runId,operationId:a.operationId,sequence:a.sequence,phase:a.phase}),l={...a,snapshotId:c,snapshotHash:p("p220-yoloop-progress-snapshot-v1",{...a,snapshotId:c})},h={schemaVersion:"YoloopRunEvent/1.0",runId:t.current.runId,operationId:t.operationId,kind:"intent",sequence:t.current.events.length+1,revision:e,occurredAt:t.occurredAt,fromStatus:t.current.status,toStatus:t.target,reasonCodes:n,budgetDimension:null,parentEventHash:t.current.events.at(-1)?.eventHash??null,publicSafe:!0},y=p("p220-yoloop-run-event-id-v1",{runId:h.runId,operationId:h.operationId,sequence:h.sequence}),O={...h,eventId:y,eventHash:p("p220-yoloop-run-event-v1",{...h,eventId:y})},w={...t.current,revision:e,status:t.target,events:[...t.current.events,O],progressSnapshots:[...t.current.progressSnapshots,i,l],latestSnapshotHash:l.snapshotHash,receipts:[...t.current.receipts]},L={runId:t.current.runId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,expectedRevision:t.current.revision,expectedSnapshotHash:t.current.latestSnapshotHash,next:w},N=x(L),Y={schemaVersion:"YoloopRunTransitionReceipt/1.0",runId:t.current.runId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,payloadHash:N,revision:e,snapshotHash:l.snapshotHash,status:t.target};return{type:"transition_run",...L,payloadHash:N,next:{...w,receipts:[...w.receipts,Y]}}}function v(t){const e=/^[A-Za-z0-9._:-]{1,128}$/;if(!e.test(t.runId)||!e.test(t.operationId)||!e.test(t.idempotencyKey)||!/^[a-f0-9]{64}$/.test(t.payloadHash)||!Number.isSafeInteger(t.expectedRevision)||t.expectedRevision<0)throw new Error("YOLOOP_RUN_OPERATION_CONFLICT");if(t.payloadHash!==x(t))throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}function E(t,e){const n=e.next,r=t?.events??[],s=t?.progressSnapshots??[],o=t?.receipts??[];if(n.schemaVersion!=="YoloopRunControl/1.0"||n.runId!==e.runId||n.revision!==e.expectedRevision+1||n.events.length!==r.length+1||n.progressSnapshots.length!==s.length+2||n.receipts.length!==o.length+1||d(n.events.slice(0,r.length))!==d(r)||d(n.progressSnapshots.slice(0,s.length))!==d(s)||d(n.receipts.slice(0,o.length))!==d(o))throw new Error("YOLOOP_RUN_TRANSITION_INVALID");if(t){if(R.has(t.status))throw new Error("YOLOOP_RUN_TERMINAL");const h=n.progressSnapshots.at(-2)?.boundary,y=t.status===n.status&&(h==="budget"||h==="retry");if(!(Q[t.status]??[]).includes(n.status)&&!y)throw new Error("YOLOOP_RUN_TRANSITION_INVALID");if(t.startedAt!==n.startedAt||t.deadlineAt!==n.deadlineAt)throw new Error("YOLOOP_RUN_TRANSITION_INVALID");if(d(t.predecessor)!==d(n.predecessor))throw new Error("YOLOOP_RUN_TRANSITION_INVALID")}else if(n.status!=="created")throw new Error("YOLOOP_RUN_TRANSITION_INVALID");const i=n.progressSnapshots.at(-2),a=n.progressSnapshots.at(-1),c=n.events.at(-1),l=n.receipts.at(-1);if(!i||!a||!c||!l||i.phase!=="before"||a.phase!=="after"||i.operationId!==e.operationId||a.operationId!==e.operationId||c.operationId!==e.operationId||i.runId!==e.runId||a.runId!==e.runId||c.runId!==e.runId||i.revision!==n.revision||a.revision!==n.revision||c.revision!==n.revision||i.parentSnapshotHash!==(t?.latestSnapshotHash??null)||a.parentSnapshotHash!==i.snapshotHash||n.latestSnapshotHash!==a.snapshotHash||l.schemaVersion!=="YoloopRunTransitionReceipt/1.0"||l.runId!==e.runId||l.operationId!==e.operationId||l.idempotencyKey!==e.idempotencyKey||l.payloadHash!==e.payloadHash||l.revision!==n.revision||l.snapshotHash!==n.latestSnapshotHash||l.status!==n.status||Date.parse(n.deadlineAt)<=Date.parse(n.startedAt))throw new Error("YOLOOP_RUN_TRANSITION_INVALID");A(i),A(a),te(c,r.at(-1)?.eventHash??null)}function A(t){const{snapshotHash:e,...n}=t;if(e!==p("p220-yoloop-progress-snapshot-v1",n))throw new Error("YOLOOP_RUN_SNAPSHOT_CONFLICT")}function te(t,e){const{eventHash:n,...r}=t;if(t.parentEventHash!==e||n!==p("p220-yoloop-run-event-v1",r))throw new Error("YOLOOP_RUN_SNAPSHOT_CONFLICT")}function ne(t,e){return`lease-${se(`${t}:${e}`)}`}function se(t){let e=2166136261;for(let n=0;n<t.length;n+=1)e^=t.charCodeAt(n),e=Math.imul(e,16777619)>>>0;return e.toString(36).padStart(7,"0")}function k(t,e){const n=t.leaseExpiresAt??t.ttlExpiresAt,r=Date.parse(n),s=Date.parse(e);return!Number.isFinite(r)||!Number.isFinite(s)?"unknown":r<=s?"expired":"active"}function re(t,e){const n=S(e);return{...t,version:t.version==="1.2"?"1.2":"1.1",lastResetAt:t.lastResetAt??n.lastResetAt,storiesRunToday:t.storiesRunToday??0,iterationsToday:t.iterationsToday??0,iterationsTodayDate:t.iterationsTodayDate??n.iterationsTodayDate,tokensUsedToday:t.tokensUsedToday??0,lastRunAt:t.lastRunAt??null,coolDownUntil:t.coolDownUntil??null,totalRunsAllTime:t.totalRunsAllTime??0,totalStoriesAllTime:t.totalStoriesAllTime??0,currentSession:t.currentSession??null,...t.runControl!==void 0?{runControl:t.runControl}:{},...t.continuationPolicy!==void 0?{continuationPolicy:t.continuationPolicy}:{},...t.continuationSession!==void 0?{continuationSession:t.continuationSession}:{},...t.pendingContinuationAuthorities!==void 0?{pendingContinuationAuthorities:t.pendingContinuationAuthorities}:{},...t.continuationReceipts!==void 0?{continuationReceipts:t.continuationReceipts}:{},...t.continuationRecoveryReceipts!==void 0?{continuationRecoveryReceipts:t.continuationRecoveryReceipts}:{},recovery_history:Array.isArray(t.recovery_history)?H(t.recovery_history):[]}}function H(t){return t.length<=g?t:t.slice(t.length-g)}export{C as YOLOOP_PERSISTENCE_CAPABILITIES,he as YoloopClientStateStore,x as buildYoloopRunTransitionPayloadHash,z as buildYoloopSessionRolloverPayloadHash,W as buildYoloopSuccessorRunPayloadHash,H as capRecoveryHistory,S as createDefaultCounters,ue as createDefaultState,j as fingerprintYoloopSession};
1
+ import{promises as u}from"node:fs";import{createHash as b}from"node:crypto";import{join as _,dirname as V}from"node:path";import{hostname as S}from"node:os";import{setSecureFilePermissions as $,setSecureDirPermissions as q}from"../config/secure-config.js";import{RECOVERY_HISTORY_CAP as C}from"./shared-yoloop-types.js";const B=".neocortex",g="yoloop-state.json",j="yoloop.lock",J="yoloop-state.mutation.lock",P="yoloop-session-rollover.json",A="yoloop-successor-transition.json",z=360*60*1e3,W=3e4,G=200,x=Object.freeze(["rollover-session-v1","successor-transition-v1"]),X={warn:()=>{},info:()=>{},error:()=>{}};function w(t){const e=t.slice(0,10);return{version:"1.1",lastResetAt:t,storiesRunToday:0,iterationsToday:0,iterationsTodayDate:e,tokensUsedToday:0,lastRunAt:null,coolDownUntil:null,totalRunsAllTime:0,totalStoriesAllTime:0,currentSession:null,continuationPolicy:"p205-finite-resume-v2",pendingContinuationAuthorities:[],continuationReceipts:[],continuationRecoveryReceipts:[]}}function we(t){return{lock:null,state:w(t),capabilities:x}}class fe{stateDir;statePath;lockPath;mutationLockPath;rolloverManifestPath;successorTransitionManifestPath;logger;constructor(e,s=X){this.stateDir=_(e,B),this.statePath=_(this.stateDir,g),this.lockPath=_(this.stateDir,j),this.mutationLockPath=_(this.stateDir,J),this.rolloverManifestPath=_(this.stateDir,P),this.successorTransitionManifestPath=_(this.stateDir,A),this.logger=s}async readAll(e){const s=e??new Date().toISOString();await this.cleanupOrphanTempFiles(),await this.recoverSessionRolloverIfPresent(s),await this.recoverSuccessorTransitionIfPresent(s);const[n,r]=await Promise.all([this.readLock(),this.readState(s)]);return{lock:await this.prepareLockForSnapshot(n,s),state:r,capabilities:x}}async applyUpdate(e,s){const n=s??new Date().toISOString();await this.ensureDir(),await this.recoverSessionRolloverIfPresent(n),await this.recoverSuccessorTransitionIfPresent(n);for(const r of e.operations)await this.applyOperation(r,n)}async requestRunTransition(e,s){const n=s??new Date().toISOString();return await this.ensureDir(),this.withMutationLock(()=>this.transitionRun(e,n))}async requestLifecycleAction(e,s={},n){const r=n??new Date().toISOString();return await this.ensureDir(),this.withMutationLock(async()=>{const i=(await this.readState(r)).runControl;if(!i)throw new Error("YOLOOP_RUN_TRANSITION_INVALID");const a=Date.parse(r).toString(36),c=s.operationId??`op-${e}-${a}`,l=s.idempotencyKey??`idem-${e}-${a}`,h=i.receipts.find(O=>O.operationId===c||O.idempotencyKey===l);if(h){if(h.operationId===c&&h.idempotencyKey===l)return h;throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}const y=ae(i.status,e);if(!y)throw new Error(E.has(i.status)?"YOLOOP_RUN_TERMINAL":"YOLOOP_RUN_TRANSITION_INVALID");return this.transitionRun(ce({current:i,action:e,target:y,operationId:c,idempotencyKey:l,occurredAt:r}),r)})}async applyOperation(e,s){switch(e.type){case"acquire_lock":await this.acquireLock(e.lock,s);return;case"release_lock":await this.releaseLock(e);return;case"write_state":await this.withMutationLock(async()=>{const n=await this.readState(s),{runControl:r,...o}=e.state;await this.writeState({...o,...n.runControl?{version:"1.2",runControl:n.runControl}:{}})});return;case"advance_epic":await this.advanceEpic(e.nextEpicIndex,e.nextEpicId,s);return;case"no_op":this.logger.info({event:"yoloop_noop"},"yoloop server sent no-op");return;case"reserve_continuation_authority":await this.reserveContinuationAuthority(e.authority,s);return;case"acknowledge_continuation_authority":await this.acknowledgeContinuationAuthority(e.idempotencyKey,e.receipt,s);return;case"repair_continuation_authority":await this.repairContinuationAuthority(e.beforeHash,e.authority,e.receipt,s);return;case"switch_continuation_policy":await this.switchContinuationPolicy(e.policy,e.session,s);return;case"transition_run":await this.requestRunTransition(e,s);return;case"start_successor_run":await this.withMutationLock(()=>this.startSuccessorRun(e,s));return;case"commit_successor_transition":await this.withMutationLock(()=>this.commitSuccessorTransition(e,s));return;case"rollover_session":await this.withMutationLock(()=>this.rolloverSession(e,s));return;case"recovery_attempted":await this.appendRecoveryAttempt(e.attempt,s);return;case"recovery_resolved":await this.resolveRecoveryAttempt(e.attempt_id,e.outcome,s);return;default:{const n=e;throw this.logger.error({event:"yoloop_unknown_op",op:n},"unknown yoloop operation rejected"),new Error("YOLOOP_STATE_OPERATION_UNSUPPORTED")}}}async reserveContinuationAuthority(e,s){const n=await this.readState(s),r=n.pendingContinuationAuthorities??[],o=typeof e.idempotencyKey=="string"?e.idempotencyKey:"";if(!o)throw new Error("YOLOOP_CONTINUATION_AUTHORITY_INVALID");const i=r.find(a=>a.idempotencyKey===o);if(i){if(d(i)===d(e))return;throw new Error("YOLOOP_CONTINUATION_AUTHORITY_CONFLICT")}if(r.length>=64)throw new Error("YOLOOP_PENDING_AUTHORITY_CAPACITY_EXCEEDED");await this.writeState({...n,pendingContinuationAuthorities:[...r,e]})}async acknowledgeContinuationAuthority(e,s,n){const r=await this.readState(n),o=r.pendingContinuationAuthorities??[],i=o.findIndex(h=>h.idempotencyKey===e);if(i<0)throw new Error("YOLOOP_CONTINUATION_RECEIPT_ORPHAN");const a=o[i];if(s.idempotencyKey!==e||s.sessionId!==a.sessionId||JSON.stringify(s.storyIds)!==JSON.stringify(a.storyIds))throw new Error("YOLOOP_CONTINUATION_RECEIPT_MISMATCH");const c=o.filter((h,y)=>y!==i),l=r.continuationReceipts??[];await this.writeState({...r,pendingContinuationAuthorities:c,continuationReceipts:[...l.slice(-63),s]})}async repairContinuationAuthority(e,s,n,r){const o=await this.readState(r),i=o.pendingContinuationAuthorities??[],a=o.continuationRecoveryReceipts??[],c=typeof n.idempotencyKey=="string"?n.idempotencyKey:"",l=a.find(O=>O.idempotencyKey===c);if(l){if(d(l)===d(n))return;throw new Error("YOLOOP_CONTINUATION_RECOVERY_RECEIPT_CONFLICT")}if(i.length!==1||p("p208-legacy-authority-before-v1",i[0])!==e)throw new Error("YOLOOP_CONTINUATION_RECOVERY_BEFORE_MISMATCH");const h=p("p208-legacy-authority-after-v1",s);if(n.beforeHash!==e||n.afterHash!==h)throw new Error("YOLOOP_CONTINUATION_RECOVERY_HASH_MISMATCH");const y={...n};if(delete y.idempotencyKey,!c||p("p208-legacy-authority-recovery-receipt-v1",y)!==c)throw new Error("YOLOOP_CONTINUATION_RECOVERY_RECEIPT_INVALID");await this.writeState({...o,pendingContinuationAuthorities:[s],continuationRecoveryReceipts:[...a.slice(-63),n]})}async switchContinuationPolicy(e,s,n){const r=await this.readState(n);if(r.currentSession||(r.pendingContinuationAuthorities?.length??0)>0)throw new Error("YOLOOP_POLICY_SWITCH_ACTIVE");try{await u.copyFile(this.statePath,`${this.statePath}.policy-backup`)}catch(o){if(o.code!=="ENOENT")throw o}await this.writeState({...r,continuationPolicy:e,continuationSession:s})}async appendRecoveryAttempt(e,s){const n=await this.readState(s),r=n.recovery_history??[];if(r.some(c=>c.attempted_at===e.attempted_at&&c.story_id===e.story_id)){this.logger.warn({event:"recovery_attempted_duplicate",story_id:e.story_id},"duplicate recovery_attempted op; skipping");return}const i=K([...r,e]),a={...n,recovery_history:i};await this.writeState(a),this.logger.info({event:"recovery_attempted_persisted",story_id:e.story_id,history_size:i.length},"recovery attempt persisted")}async resolveRecoveryAttempt(e,s,n){const r=await this.readState(n),o=r.recovery_history??[],i=o.findIndex(h=>h.recovery_step_id_tokenized===e);if(i===-1){this.logger.warn({event:"recovery_resolve_orphan",attempt_id:e},"recovery_resolved op had no matching attempt; skipping");return}const a=o[i];if(a.outcome===s&&a.finished_at){this.logger.info({event:"recovery_resolved_duplicate",attempt_id:e,outcome:s},"duplicate recovery_resolved op; skipping");return}const c=o.slice();c[i]={...a,outcome:s,finished_at:n};const l={...r,recovery_history:c};await this.writeState(l),this.logger.info({event:"recovery_resolved_persisted",attempt_id:e,outcome:s},"recovery attempt resolved")}async acquireLock(e,s){const n={...e,pid:process.pid,hostname:S(),ownerKind:"client",startedAt:e.startedAt||s,leaseId:e.leaseId??le(e.sessionId,s),leaseState:"active",leaseAcquiredAt:e.leaseAcquiredAt??s,leaseDurationMs:e.leaseDurationMs??z,leaseExpiresAt:e.leaseExpiresAt??e.ttlExpiresAt},r=JSON.stringify(n,null,2);try{const o=await u.open(this.lockPath,"wx");try{await o.writeFile(r,"utf8")}finally{await o.close()}this.trySetFilePerms(this.lockPath),this.logger.info({event:"yoloop_lock_acquired",pid:n.pid,sessionId:n.sessionId},"yoloop lock acquired");return}catch(o){const i=o;if(i.code!=="EEXIST")throw this.logger.error({event:"yoloop_lock_acquire_error",err:i.message},"failed to acquire yoloop lock"),o;const a=await this.readLock();if(a&&this.isSameClientSessionLock(a,n)){this.logger.info({event:"yoloop_lock_acquire_duplicate",sessionId:n.sessionId},"duplicate acquire_lock for current yoloop session; treating as no-op");return}if(!await this.maybeRecoverOrphanLock(s))throw this.logger.warn({event:"yoloop_lock_held"},"yoloop lock held by another live process"),o;const l=await u.open(this.lockPath,"wx");try{await l.writeFile(r,"utf8")}finally{await l.close()}this.trySetFilePerms(this.lockPath),this.logger.info({event:"yoloop_lock_acquired_after_recovery",pid:n.pid},"yoloop lock acquired after orphan recovery")}}async releaseLock(e){const s=await this.readState(new Date().toISOString()),n=await this.readLock();if(s.runControl){if(!e.expectedRunId||!e.expectedSessionId||!e.expectedLeaseId)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if(e.expectedRunId!==s.runControl.runId)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if(!n||e.expectedSessionId!==n.sessionId||e.expectedLeaseId!==n.leaseId)throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}try{await u.unlink(this.lockPath),this.logger.info({event:"yoloop_lock_released"},"yoloop lock released")}catch(r){const o=r;if(o.code==="ENOENT"){this.logger.info({event:"yoloop_lock_release_noop"},"yoloop lock release noop (file absent)");return}this.logger.warn({event:"yoloop_lock_release_error",err:o.message},"unexpected error releasing yoloop lock")}}async readLock(){try{const e=await u.readFile(this.lockPath,"utf8"),s=JSON.parse(e),n=s.currentEpicId??s.epicId??"";return{pid:s.pid??0,hostname:s.hostname??"",...s.ownerKind?{ownerKind:s.ownerKind}:{},...s.ownerPidState?{ownerPidState:s.ownerPidState}:{},...typeof s.leaseId=="string"?{leaseId:s.leaseId}:{},...s.leaseState?{leaseState:s.leaseState}:{},...typeof s.leaseAcquiredAt=="string"?{leaseAcquiredAt:s.leaseAcquiredAt}:{},...typeof s.leaseDurationMs=="number"?{leaseDurationMs:s.leaseDurationMs}:{},...typeof s.leaseExpiresAt=="string"?{leaseExpiresAt:s.leaseExpiresAt}:{},startedAt:s.startedAt??"",sessionId:s.sessionId??"",mode:s.mode??"epic-id",inputPath:s.inputPath??"",epicQueue:s.epicQueue??(n?[n]:[]),currentEpicIndex:s.currentEpicIndex??0,currentEpicId:n,ttlExpiresAt:s.ttlExpiresAt??"",epicId:s.epicId??n}}catch{return null}}async readState(e){try{const s=await u.readFile(this.statePath,"utf8"),n=JSON.parse(s);return he(n,e)}catch(s){const n=s;return n.code!=="ENOENT"&&this.logger.warn({event:"yoloop_state_read_error",err:n.message},"yoloop state file unreadable; using defaults"),w(e)}}async writeState(e){const s=`${this.statePath}.tmp.${process.pid}.${Date.now()}`,n=JSON.stringify(e,null,2);try{const r=await u.open(s,"w",384);try{await r.writeFile(n,"utf8"),await r.sync()}finally{await r.close()}this.trySetFilePerms(s),await u.rename(s,this.statePath),await this.syncStateDirectory()}catch(r){const o=r;this.logger.error({event:"yoloop_state_write_error",err:o.message},"failed to write yoloop state");try{await u.unlink(s)}catch{}throw r}}async rolloverSession(e,s){v(e);const n=await this.readRolloverManifest();if(n){if(oe(n.operation,e)){if(n.operation.payloadHash!==e.payloadHash)throw new Error("YOLOOP_SESSION_ROLLOVER_CONFLICT");if(n.phase==="applied")return;await this.completePreparedSessionRollover(n.operation,s);return}else if(n.phase==="prepared")throw new Error("YOLOOP_SESSION_ROLLOVER_CONFLICT")}const r=await this.readState(s),o=await this.readLock();H(e,r,o),await this.writeRolloverManifest({schemaVersion:"YoloopSessionRolloverManifest/1.0",phase:"prepared",operation:e}),await this.completePreparedSessionRollover(e,s)}async completePreparedSessionRollover(e,s){const n=await this.readState(s);let r=d(n)===d(e.next);if(!r){const i=await this.readLock();H(e,n,i),await this.writeState(e.next),r=!0}const o=await this.readLock();if(e.expectedSessionId===null||e.expectedLeaseId===null){if(e.expectedSessionId!==null||e.expectedLeaseId!==null||o)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT")}else if(o){if(o.sessionId!==e.expectedSessionId||o.leaseId!==e.expectedLeaseId)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT");await u.unlink(this.lockPath),await this.syncStateDirectory()}else if(!r)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT");await this.writeRolloverManifest({schemaVersion:"YoloopSessionRolloverManifest/1.0",phase:"applied",operation:e}),this.logger.info({event:"yoloop_session_rollover_applied",runId:e.runId,operationId:e.operationId,coolDownUntil:e.coolDownUntil},"yoloop per-run-cap session rollover applied")}async recoverSessionRolloverIfPresent(e){try{await u.access(this.rolloverManifestPath)}catch(s){if(s.code==="ENOENT")return;throw s}await this.ensureDir(),await this.withMutationLock(async()=>{const s=await this.readRolloverManifest();s?.phase==="prepared"&&await this.completePreparedSessionRollover(s.operation,e)})}async readRolloverManifest(){try{const e=JSON.parse(await u.readFile(this.rolloverManifestPath,"utf8"));if(e.schemaVersion!=="YoloopSessionRolloverManifest/1.0"||e.phase!=="prepared"&&e.phase!=="applied"||!e.operation||e.operation.type!=="rollover_session")throw new Error("YOLOOP_SESSION_ROLLOVER_MANIFEST_CORRUPT");return v(e.operation),e}catch(e){if(e.code==="ENOENT")return null;throw e.message==="YOLOOP_SESSION_ROLLOVER_MANIFEST_CORRUPT"?e:new Error("YOLOOP_SESSION_ROLLOVER_MANIFEST_CORRUPT")}}async writeRolloverManifest(e){const s=`${this.rolloverManifestPath}.tmp.${process.pid}.${Date.now()}`,n=await u.open(s,"w",384);try{await n.writeFile(JSON.stringify(e,null,2),"utf8"),await n.sync()}finally{await n.close()}this.trySetFilePerms(s),await u.rename(s,this.rolloverManifestPath),await this.syncStateDirectory()}async commitSuccessorTransition(e,s){f(e);const n=await this.readSuccessorTransitionManifest();if(n){if(se(n.operation,e)){if(n.operation.payloadHash!==e.payloadHash)throw new Error("YOLOOP_SUCCESSOR_TRANSITION_CONFLICT");if(n.phase==="applied")return;await this.completePreparedSuccessorTransition(n.operation,s);return}if(n.phase==="prepared")throw new Error("YOLOOP_SUCCESSOR_TRANSITION_CONFLICT")}const r=await this.readState(s);if(R(e,r)){await this.writeSuccessorTransitionManifest({schemaVersion:"YoloopSuccessorTransitionManifest/1.0",phase:"applied",operation:e});return}k(e,r),await this.writeSuccessorTransitionManifest({schemaVersion:"YoloopSuccessorTransitionManifest/1.0",phase:"prepared",operation:e}),await this.completePreparedSuccessorTransition(e,s)}async completePreparedSuccessorTransition(e,s){let n=await this.readState(s);if(!R(e,n)){d(n.runControl)===d(e.successor.next)||(await this.startSuccessorRun(e.successor,s),n=await this.readState(s));const o=re(e,n);await this.writeState(o),n=await this.readState(s)}if(!R(e,n))throw new Error("YOLOOP_SUCCESSOR_TRANSITION_STATE_CONFLICT");await this.writeSuccessorTransitionManifest({schemaVersion:"YoloopSuccessorTransitionManifest/1.0",phase:"applied",operation:e}),this.logger.info({event:"yoloop_successor_transition_applied",runId:e.successor.runId,operationId:e.operationId},"yoloop successor transition applied")}async recoverSuccessorTransitionIfPresent(e){try{await u.access(this.successorTransitionManifestPath)}catch(s){if(s.code==="ENOENT")return;throw s}await this.ensureDir(),await this.withMutationLock(async()=>{const s=await this.readSuccessorTransitionManifest();s?.phase==="prepared"&&await this.completePreparedSuccessorTransition(s.operation,e)})}async readSuccessorTransitionManifest(){try{const e=JSON.parse(await u.readFile(this.successorTransitionManifestPath,"utf8"));if(e.schemaVersion!=="YoloopSuccessorTransitionManifest/1.0"||e.phase!=="prepared"&&e.phase!=="applied"||!e.operation||e.operation.type!=="commit_successor_transition")throw new Error("YOLOOP_SUCCESSOR_TRANSITION_MANIFEST_CORRUPT");return f(e.operation),e}catch(e){if(e.code==="ENOENT")return null;throw e.message==="YOLOOP_SUCCESSOR_TRANSITION_MANIFEST_CORRUPT"?e:new Error("YOLOOP_SUCCESSOR_TRANSITION_MANIFEST_CORRUPT")}}async writeSuccessorTransitionManifest(e){const s=`${this.successorTransitionManifestPath}.tmp.${process.pid}.${Date.now()}`,n=await u.open(s,"w",384);try{await n.writeFile(JSON.stringify(e,null,2),"utf8"),await n.sync()}finally{await n.close()}this.trySetFilePerms(s),await u.rename(s,this.successorTransitionManifestPath),await this.syncStateDirectory()}async advanceEpic(e,s,n){const r=await this.readState(n);if(!r.currentSession){this.logger.warn({event:"yoloop_advance_no_session",nextEpicId:s},"advance_epic with no active session; skipping");return}const o={...r,currentSession:{...r.currentSession,currentEpicIndex:e}};await this.writeState(o),this.logger.info({event:"yoloop_epic_advance",nextEpicId:s,nextIndex:e},"yoloop advanced to next epic")}async ensureDir(){try{await u.mkdir(this.stateDir,{recursive:!0}),this.trySetDirPerms(this.stateDir)}catch(e){const s=e;throw this.logger.error({event:"yoloop_mkdir_error",err:s.message,path:this.stateDir},"failed to ensure .neocortex/ directory"),e}}async syncStateDirectory(){try{const e=await u.open(this.stateDir,"r");try{await e.sync()}finally{await e.close()}}catch(e){const s=e.code;if(s!=="EINVAL"&&s!=="EISDIR"&&s!=="ENOTSUP"&&s!=="EPERM")throw e}}async withMutationLock(e){let s=null;for(let n=0;n<G;n+=1)try{s=await u.open(this.mutationLockPath,"wx",384),await s.writeFile(JSON.stringify({pid:process.pid,acquiredAt:new Date().toISOString()})),await s.sync();break}catch(r){if(r.code!=="EEXIST")throw r;try{const o=await u.stat(this.mutationLockPath);if(Date.now()-o.mtimeMs>W){await u.unlink(this.mutationLockPath);continue}}catch{continue}await new Promise(o=>setTimeout(o,5))}if(!s)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");try{return await e()}finally{await s.close().catch(()=>{}),await u.unlink(this.mutationLockPath).catch(()=>{})}}async transitionRun(e,s){T(e);const n=await this.readState(s),r=n.runControl,o=r?.receipts.find(l=>l.operationId===e.operationId||l.idempotencyKey===e.idempotencyKey);if(o){if(o.operationId===e.operationId&&o.idempotencyKey===e.idempotencyKey&&o.payloadHash===e.payloadHash)return o;throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}if(r&&r.runId!==e.runId)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if((r?.revision??0)!==e.expectedRevision)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if((r?.latestSnapshotHash??null)!==e.expectedSnapshotHash)throw new Error("YOLOOP_RUN_SNAPSHOT_CONFLICT");L(r,e);const c=e.next.receipts.at(-1);if(!c)throw new Error("YOLOOP_RUN_OPERATION_CONFLICT");return await this.writeState({...n,version:"1.2",runControl:e.next}),this.logger.info({event:"yoloop_run_transition_committed",runId:e.runId,operationId:e.operationId,revision:c.revision,status:c.status},"yoloop run transition committed"),c}async startSuccessorRun(e,s){Y(e);const n=await this.readState(s),r=n.runControl,o={schemaVersion:"YoloopRunPredecessor/1.0",runId:e.previousRunId,revision:e.expectedRevision,snapshotHash:e.expectedSnapshotHash,successorOperationId:e.operationId,publicSafe:!0},i=r?.receipts.find(l=>l.operationId===e.operationId||l.idempotencyKey===e.idempotencyKey);if(i){if(i.operationId===e.operationId&&i.idempotencyKey===e.idempotencyKey&&e.next.receipts.at(-1)?.payloadHash===i.payloadHash&&d(r?.predecessor)===d(o))return i;throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}if(!r||r.runId!==e.previousRunId||r.status!=="exhausted"||r.revision!==e.expectedRevision||r.latestSnapshotHash!==e.expectedSnapshotHash||n.currentSession!==null)throw new Error("YOLOOP_RUN_SUCCESSOR_CONFLICT");const a=e.next.receipts.at(-1);if(!a||d(e.next.predecessor)!==d(o))throw new Error("YOLOOP_RUN_SUCCESSOR_CONFLICT");const c={type:"transition_run",runId:e.runId,operationId:e.operationId,idempotencyKey:e.idempotencyKey,expectedRevision:0,expectedSnapshotHash:null,payloadHash:a.payloadHash,next:e.next};return T(c),L(void 0,c),await this.writeState({...n,version:"1.2",runControl:e.next}),a}trySetFilePerms(e){try{$(e)}catch{}}trySetDirPerms(e){try{q(e)}catch{}}async prepareLockForSnapshot(e,s){if(!e)return null;if(e.ownerKind!=="client")return e;const n=F(e,s),r={...e,leaseState:n};if(n==="expired")return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_client_lock_recovered",reason:"lease_expired"},"expired client-owned yoloop lock lease recovered before snapshot echo"),null;if(!r.pid||r.pid<=0)return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_client_lock_recovered",reason:"invalid_pid"},"invalid PID in client-owned yoloop lock; recovered"),null;if(r.hostname&&r.hostname!==S())return{...r,ownerPidState:"unknown"};try{return process.kill(r.pid,0),{...r,ownerPidState:"live"}}catch{return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_client_lock_recovered",reason:"dead_pid"},"stale client-owned yoloop lock recovered before snapshot echo"),null}}async maybeRecoverOrphanLock(e){const s=await this.readLock();if(!s)return!0;if(F(s,e)==="expired")return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_orphan_lock_recovered",reason:"lease_expired"},"expired yoloop lock lease recovered"),!0;if(!s.pid||s.pid<=0)return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_orphan_lock_recovered",reason:"invalid_pid"},"invalid PID in lock file; recovered"),!0;if(s.hostname&&s.hostname!==S())return this.logger.warn({event:"yoloop_lock_remote_host",ownerKind:s.ownerKind??"server",ownerPidState:"unknown"},"lock held by a remote host; honoring"),!1;try{return process.kill(s.pid,0),!1}catch{return await this.deleteLockBestEffort(),this.logger.warn({event:"yoloop_orphan_lock_recovered",reason:"dead_pid"},"orphan yoloop lock recovered"),!0}}async deleteLockBestEffort(){try{await u.unlink(this.lockPath)}catch{}}isSameClientSessionLock(e,s){return e.ownerKind==="client"&&e.sessionId===s.sessionId&&e.pid===process.pid&&e.hostname===S()}async cleanupOrphanTempFiles(){try{const e=V(this.statePath),s=await u.readdir(e),n=[`${g}.tmp.`,`${P}.tmp.`,`${A}.tmp.`],r=s.filter(o=>n.some(i=>o.startsWith(i)));for(const o of r)try{await u.unlink(_(e,o))}catch{}}catch{}}}function d(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?`[${t.map(d).join(",")}]`:`{${Object.entries(t).filter(([,e])=>e!==void 0).sort(([e],[s])=>e.localeCompare(s)).map(([e,s])=>`${JSON.stringify(e)}:${d(s)}`).join(",")}}`}function p(t,e){return b("sha256").update(`${t}\0${d(e)}`).digest("hex")}function Z(t){return p("p9390812898200217364-yoloop-session-v1",t)}function Q(t){return p("p9390812898200217364-yoloop-rollover-v1",t)}function ee(t){return p("p9390812898200217364-yoloop-successor-run-v1",t)}function te(t){return p("p9046281030721413419-yoloop-successor-transition-v1",t)}function se(t,e){return t.operationId===e.operationId&&t.idempotencyKey===e.idempotencyKey}function f(t){const e=/^[A-Za-z0-9._:-]{1,128}$/;Y(t.successor);const s={operationId:t.operationId,idempotencyKey:t.idempotencyKey,successor:t.successor,state:t.state,...t.acknowledgement?{acknowledgement:t.acknowledgement}:{},...t.reservation?{reservation:t.reservation}:{}},n=t.acknowledgement?.idempotencyKey,r=t.acknowledgement?.receipt.idempotencyKey,o=t.reservation?.authority.idempotencyKey;if(t.successor.type!=="start_successor_run"||!e.test(t.operationId)||!e.test(t.idempotencyKey)||t.operationId!==t.successor.operationId||t.idempotencyKey!==t.successor.idempotencyKey||!/^[a-f0-9]{64}$/.test(t.payloadHash)||t.payloadHash!==te(s)||Buffer.byteLength(d(s),"utf8")>1048576||t.acknowledgement!==void 0&&(t.acknowledgement.type!=="acknowledge_continuation_authority"||typeof n!="string"||!e.test(n)||r!==n)||t.reservation!==void 0&&(t.reservation.type!=="reserve_continuation_authority"||typeof o!="string"||!e.test(o))||n!==void 0&&o===n)throw new Error("YOLOOP_SUCCESSOR_TRANSITION_CONFLICT")}function k(t,e){if(f(t),!(d(e.runControl)===d(t.successor.next))){const n=e.runControl;if(!n||n.runId!==t.successor.previousRunId||n.status!=="exhausted"||n.revision!==t.successor.expectedRevision||n.latestSnapshotHash!==t.successor.expectedSnapshotHash||e.currentSession!==null)throw new Error("YOLOOP_SUCCESSOR_TRANSITION_STATE_CONFLICT")}ne(t,e)}function ne(t,e){const s=e.pendingContinuationAuthorities??[],n=e.continuationReceipts??[],r=t.acknowledgement;if(r){const l=s.find(O=>O.idempotencyKey===r.idempotencyKey);if(!l||r.receipt.sessionId!==l.sessionId||d(r.receipt.storyIds)!==d(l.storyIds))throw new Error("YOLOOP_SUCCESSOR_TRANSITION_AUTHORITY_CONFLICT");const h=s.filter(O=>O.idempotencyKey!==r.idempotencyKey),y=[...n.slice(-63),r.receipt];if(d(t.state.pendingContinuationAuthorities??[])!==d(h)||d(t.state.continuationReceipts??[])!==d(y))throw new Error("YOLOOP_SUCCESSOR_TRANSITION_AUTHORITY_CONFLICT")}else if(d(t.state.pendingContinuationAuthorities??[])!==d(s)||d(t.state.continuationReceipts??[])!==d(n))throw new Error("YOLOOP_SUCCESSOR_TRANSITION_AUTHORITY_CONFLICT");const o=t.reservation?.authority;if(!o)return;const i=String(o.idempotencyKey??""),a=t.state.pendingContinuationAuthorities??[],c=a.find(l=>l.idempotencyKey===i);if(c&&d(c)!==d(o))throw new Error("YOLOOP_SUCCESSOR_TRANSITION_AUTHORITY_CONFLICT");if(!c&&a.length>=64)throw new Error("YOLOOP_PENDING_AUTHORITY_CAPACITY_EXCEEDED")}function re(t,e){k(t,e);const s=t.reservation?.authority,n=[...t.state.pendingContinuationAuthorities??[]];return s&&!n.some(r=>r.idempotencyKey===s.idempotencyKey)&&n.push(s),{...t.state,version:"1.2",runControl:t.successor.next,...s||t.state.pendingContinuationAuthorities!==void 0?{pendingContinuationAuthorities:n}:{}}}function R(t,e){const s=t.reservation?.authority,n=[...t.state.pendingContinuationAuthorities??[]];s&&!n.some(o=>o.idempotencyKey===s.idempotencyKey)&&n.push(s);const r={...t.state,version:"1.2",runControl:t.successor.next,...s||t.state.pendingContinuationAuthorities!==void 0?{pendingContinuationAuthorities:n}:{}};return d(e)===d(r)}function oe(t,e){return t.operationId===e.operationId&&t.idempotencyKey===e.idempotencyKey}function v(t){const e=/^[A-Za-z0-9._:-]{1,128}$/,s={runId:t.runId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,expectedRevision:t.expectedRevision,expectedSnapshotHash:t.expectedSnapshotHash,expectedSessionId:t.expectedSessionId,expectedSessionFingerprint:t.expectedSessionFingerprint,expectedLeaseId:t.expectedLeaseId,coolDownUntil:t.coolDownUntil,reason:t.reason,exhaustedRun:t.exhaustedRun,next:t.next};if(!e.test(t.runId)||!e.test(t.operationId)||!e.test(t.idempotencyKey)||!/^[a-f0-9]{64}$/.test(t.expectedSessionFingerprint)||!/^[a-f0-9]{64}$/.test(t.payloadHash)||!Number.isSafeInteger(t.expectedRevision)||t.expectedRevision<0||!Number.isFinite(Date.parse(t.coolDownUntil))||!["YOLOOP_PER_RUN_CAP_REACHED","YOLOOP_SESSION_TIMEOUT"].includes(t.reason)||t.payloadHash!==Q(s)||t.receipt.schemaVersion!=="YoloopSessionRolloverReceipt/1.0"||t.receipt.runId!==t.runId||t.receipt.operationId!==t.operationId||t.receipt.idempotencyKey!==t.idempotencyKey||t.receipt.payloadHash!==t.payloadHash||t.receipt.coolDownUntil!==t.coolDownUntil||t.receipt.revision!==(t.exhaustedRun?.revision??0)||t.receipt.snapshotHash!==(t.exhaustedRun?.latestSnapshotHash??null)||t.receipt.status!=="exhausted"||t.receipt.publicSafe!==!0)throw new Error("YOLOOP_SESSION_ROLLOVER_CONFLICT");if(t.expectedSessionId===null!=(t.expectedLeaseId===null)||t.expectedSessionId!==null&&!e.test(t.expectedSessionId)||t.expectedLeaseId!==null&&!e.test(t.expectedLeaseId))throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT")}function Y(t){const e=/^[A-Za-z0-9._:-]{1,128}$/,s={runId:t.runId,previousRunId:t.previousRunId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,expectedRevision:t.expectedRevision,expectedSnapshotHash:t.expectedSnapshotHash,next:t.next};if(!e.test(t.runId)||!e.test(t.previousRunId)||t.runId===t.previousRunId||!e.test(t.operationId)||!e.test(t.idempotencyKey)||!/^[a-f0-9]{64}$/.test(t.payloadHash)||!Number.isSafeInteger(t.expectedRevision)||t.expectedRevision<1||t.payloadHash!==ee(s))throw new Error("YOLOOP_RUN_SUCCESSOR_CONFLICT")}function H(t,e,s){v(t);const n=e.currentSession;if(!n||Z(n)!==t.expectedSessionFingerprint)throw new Error("YOLOOP_SESSION_ROLLOVER_SESSION_CONFLICT");const r=e.runControl;if((r?.revision??0)!==t.expectedRevision||(r?.latestSnapshotHash??null)!==t.expectedSnapshotHash||r&&r.runId!==t.runId)throw new Error("YOLOOP_RUN_REVISION_CONFLICT");if(t.expectedSessionId===null||t.expectedLeaseId===null){if(s)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT")}else if(!s||s.sessionId!==t.expectedSessionId||s.leaseId!==t.expectedLeaseId)throw new Error("YOLOOP_SESSION_ROLLOVER_LOCK_CONFLICT");const o=t.exhaustedRun;if(r)if(r.status==="exhausted"){if(d(o)!==d(r))throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT")}else{if(!o||o.status!=="exhausted")throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT");const a=o.receipts.at(-1);if(!a)throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT");const c={type:"transition_run",runId:r.runId,operationId:a.operationId,idempotencyKey:a.idempotencyKey,expectedRevision:r.revision,expectedSnapshotHash:r.latestSnapshotHash,payloadHash:a.payloadHash,next:o};T(c),L(r,c)}else{const a=o?.receipts[0],c=o?.receipts[1];if(o&&(o.runId!==t.runId||o.status!=="exhausted"||o.revision!==2||o.events.length!==2||o.progressSnapshots.length!==4||o.receipts.length!==2||a?.runId!==t.runId||a.revision!==1||a.status!=="created"||c?.runId!==t.runId||c.revision!==2||c.status!=="exhausted"||c.operationId!==`${t.operationId}:run`||c.idempotencyKey!==`${t.idempotencyKey}:run`||o.latestSnapshotHash!==c.snapshotHash||o.predecessor!==void 0))throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT")}const i={...e,version:"1.2",coolDownUntil:t.coolDownUntil,currentSession:null,...o?{runControl:o}:{}};if(d(i)!==d(t.next))throw new Error("YOLOOP_SESSION_ROLLOVER_STATE_CONFLICT")}function U(t){const{receipts:e,...s}=t.next;return p("p220-yoloop-run-transition-payload-v1",{runId:t.runId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,expectedRevision:t.expectedRevision,expectedSnapshotHash:t.expectedSnapshotHash,next:s})}const E=new Set(["success","partial","blocked","failure","exhausted","cancelled"]),ie={created:["running","cancelling","exhausted"],running:["pausing","cancelling","success","partial","blocked","failure","exhausted"],pausing:["paused","cancelling","failure","exhausted"],paused:["resuming","cancelling","exhausted"],resuming:["running","cancelling","failure","exhausted"],cancelling:["cancelled","failure","exhausted"]};function ae(t,e){return e==="pause"?t==="running"?"pausing":null:e==="resume"?t==="paused"?"resuming":null:E.has(t)||t==="cancelling"?null:"cancelling"}function ce(t){const e=t.current.revision+1,s=t.action==="cancel"?["YOLOOP_RUN_CANCEL_REQUESTED"]:[],n={schemaVersion:"YoloopOperationalBudgetSummary/1.0",limits:t.current.operationalBudget.limits,usage:t.current.usage,exhaustedDimension:null},r={schemaVersion:"ProgressSnapshot/1.0",runId:t.current.runId,sequence:t.current.progressSnapshots.length+1,revision:e,operationId:t.operationId,boundary:t.action,phase:"before",status:t.current.status,occurredAt:t.occurredAt,parentSnapshotHash:t.current.latestSnapshotHash,budget:n,reasonCodes:s,publicSafe:!0},o=p("p220-yoloop-progress-snapshot-id-v1",{runId:r.runId,operationId:r.operationId,sequence:r.sequence,phase:r.phase}),i={...r,snapshotId:o,snapshotHash:p("p220-yoloop-progress-snapshot-v1",{...r,snapshotId:o})},a={...r,sequence:i.sequence+1,phase:"after",status:t.target,parentSnapshotHash:i.snapshotHash},c=p("p220-yoloop-progress-snapshot-id-v1",{runId:a.runId,operationId:a.operationId,sequence:a.sequence,phase:a.phase}),l={...a,snapshotId:c,snapshotHash:p("p220-yoloop-progress-snapshot-v1",{...a,snapshotId:c})},h={schemaVersion:"YoloopRunEvent/1.0",runId:t.current.runId,operationId:t.operationId,kind:"intent",sequence:t.current.events.length+1,revision:e,occurredAt:t.occurredAt,fromStatus:t.current.status,toStatus:t.target,reasonCodes:s,budgetDimension:null,parentEventHash:t.current.events.at(-1)?.eventHash??null,publicSafe:!0},y=p("p220-yoloop-run-event-id-v1",{runId:h.runId,operationId:h.operationId,sequence:h.sequence}),O={...h,eventId:y,eventHash:p("p220-yoloop-run-event-v1",{...h,eventId:y})},I={...t.current,revision:e,status:t.target,events:[...t.current.events,O],progressSnapshots:[...t.current.progressSnapshots,i,l],latestSnapshotHash:l.snapshotHash,receipts:[...t.current.receipts]},N={runId:t.current.runId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,expectedRevision:t.current.revision,expectedSnapshotHash:t.current.latestSnapshotHash,next:I},m=U(N),M={schemaVersion:"YoloopRunTransitionReceipt/1.0",runId:t.current.runId,operationId:t.operationId,idempotencyKey:t.idempotencyKey,payloadHash:m,revision:e,snapshotHash:l.snapshotHash,status:t.target};return{type:"transition_run",...N,payloadHash:m,next:{...I,receipts:[...I.receipts,M]}}}function T(t){const e=/^[A-Za-z0-9._:-]{1,128}$/;if(!e.test(t.runId)||!e.test(t.operationId)||!e.test(t.idempotencyKey)||!/^[a-f0-9]{64}$/.test(t.payloadHash)||!Number.isSafeInteger(t.expectedRevision)||t.expectedRevision<0)throw new Error("YOLOOP_RUN_OPERATION_CONFLICT");if(t.payloadHash!==U(t))throw new Error("YOLOOP_RUN_OPERATION_CONFLICT")}function L(t,e){const s=e.next,n=t?.events??[],r=t?.progressSnapshots??[],o=t?.receipts??[];if(s.schemaVersion!=="YoloopRunControl/1.0"||s.runId!==e.runId||s.revision!==e.expectedRevision+1||s.events.length!==n.length+1||s.progressSnapshots.length!==r.length+2||s.receipts.length!==o.length+1||d(s.events.slice(0,n.length))!==d(n)||d(s.progressSnapshots.slice(0,r.length))!==d(r)||d(s.receipts.slice(0,o.length))!==d(o))throw new Error("YOLOOP_RUN_TRANSITION_INVALID");if(t){if(E.has(t.status))throw new Error("YOLOOP_RUN_TERMINAL");const h=s.progressSnapshots.at(-2)?.boundary,y=t.status===s.status&&(h==="budget"||h==="retry");if(!(ie[t.status]??[]).includes(s.status)&&!y)throw new Error("YOLOOP_RUN_TRANSITION_INVALID");if(t.startedAt!==s.startedAt||t.deadlineAt!==s.deadlineAt)throw new Error("YOLOOP_RUN_TRANSITION_INVALID");if(d(t.predecessor)!==d(s.predecessor))throw new Error("YOLOOP_RUN_TRANSITION_INVALID")}else if(s.status!=="created")throw new Error("YOLOOP_RUN_TRANSITION_INVALID");const i=s.progressSnapshots.at(-2),a=s.progressSnapshots.at(-1),c=s.events.at(-1),l=s.receipts.at(-1);if(!i||!a||!c||!l||i.phase!=="before"||a.phase!=="after"||i.operationId!==e.operationId||a.operationId!==e.operationId||c.operationId!==e.operationId||i.runId!==e.runId||a.runId!==e.runId||c.runId!==e.runId||i.revision!==s.revision||a.revision!==s.revision||c.revision!==s.revision||i.parentSnapshotHash!==(t?.latestSnapshotHash??null)||a.parentSnapshotHash!==i.snapshotHash||s.latestSnapshotHash!==a.snapshotHash||l.schemaVersion!=="YoloopRunTransitionReceipt/1.0"||l.runId!==e.runId||l.operationId!==e.operationId||l.idempotencyKey!==e.idempotencyKey||l.payloadHash!==e.payloadHash||l.revision!==s.revision||l.snapshotHash!==s.latestSnapshotHash||l.status!==s.status||Date.parse(s.deadlineAt)<=Date.parse(s.startedAt))throw new Error("YOLOOP_RUN_TRANSITION_INVALID");D(i),D(a),de(c,n.at(-1)?.eventHash??null)}function D(t){const{snapshotHash:e,...s}=t;if(e!==p("p220-yoloop-progress-snapshot-v1",s))throw new Error("YOLOOP_RUN_SNAPSHOT_CONFLICT")}function de(t,e){const{eventHash:s,...n}=t;if(t.parentEventHash!==e||s!==p("p220-yoloop-run-event-v1",n))throw new Error("YOLOOP_RUN_SNAPSHOT_CONFLICT")}function le(t,e){return`lease-${ue(`${t}:${e}`)}`}function ue(t){let e=2166136261;for(let s=0;s<t.length;s+=1)e^=t.charCodeAt(s),e=Math.imul(e,16777619)>>>0;return e.toString(36).padStart(7,"0")}function F(t,e){const s=t.leaseExpiresAt??t.ttlExpiresAt,n=Date.parse(s),r=Date.parse(e);return!Number.isFinite(n)||!Number.isFinite(r)?"unknown":n<=r?"expired":"active"}function he(t,e){const s=w(e);return{...t,version:t.version==="1.2"?"1.2":"1.1",lastResetAt:t.lastResetAt??s.lastResetAt,storiesRunToday:t.storiesRunToday??0,iterationsToday:t.iterationsToday??0,iterationsTodayDate:t.iterationsTodayDate??s.iterationsTodayDate,tokensUsedToday:t.tokensUsedToday??0,lastRunAt:t.lastRunAt??null,coolDownUntil:t.coolDownUntil??null,totalRunsAllTime:t.totalRunsAllTime??0,totalStoriesAllTime:t.totalStoriesAllTime??0,currentSession:t.currentSession??null,...t.runControl!==void 0?{runControl:t.runControl}:{},...t.continuationPolicy!==void 0?{continuationPolicy:t.continuationPolicy}:{},...t.continuationSession!==void 0?{continuationSession:t.continuationSession}:{},...t.pendingContinuationAuthorities!==void 0?{pendingContinuationAuthorities:t.pendingContinuationAuthorities}:{},...t.continuationReceipts!==void 0?{continuationReceipts:t.continuationReceipts}:{},...t.continuationRecoveryReceipts!==void 0?{continuationRecoveryReceipts:t.continuationRecoveryReceipts}:{},recovery_history:Array.isArray(t.recovery_history)?K(t.recovery_history):[]}}function K(t){return t.length<=C?t:t.slice(t.length-C)}export{x as YOLOOP_PERSISTENCE_CAPABILITIES,fe as YoloopClientStateStore,U as buildYoloopRunTransitionPayloadHash,Q as buildYoloopSessionRolloverPayloadHash,ee as buildYoloopSuccessorRunPayloadHash,te as buildYoloopSuccessorTransitionPayloadHash,K as capRecoveryHistory,w as createDefaultCounters,we as createDefaultState,Z as fingerprintYoloopSession};
@@ -1,4 +1,4 @@
1
- # 🧠 Neocortex v4.60.49 | OrNexus Team
1
+ # 🧠 Neocortex v4.60.51 | OrNexus Team
2
2
 
3
3
  This project uses Neocortex, a Development Orchestrator.
4
4
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.60.49 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.60.51 | OrNexus Team"
4
4
  ---
5
5
 
6
6
  <!--
@@ -4,7 +4,7 @@ agent:
4
4
  name: 'Neocortex Root Agent'
5
5
  title: 'Development Orchestrator (Root)'
6
6
  icon: '>'
7
- version: '4.60.49'
7
+ version: '4.60.51'
8
8
  architecture: 'thin-client'
9
9
  module: stand-alone
10
10
  hasSidecar: false
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex-root
3
- description: "🧠 Neocortex Root Agent v4.60.49 | OrNexus Team"
3
+ description: "🧠 Neocortex Root Agent v4.60.51 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  tools:
@@ -108,7 +108,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
108
108
  ┌────────────────────────────────────────────────────────────┐
109
109
  │ │
110
110
  │ ####### N E O C O R T E X │
111
- │ ### ######## v4.60.49 │
111
+ │ ### ######## v4.60.51 │
112
112
  │ ######### ##### │
113
113
  │ ## ############## Development Orchestrator │
114
114
  │ ## ### ###### ## OrNexus Team │
@@ -4,7 +4,7 @@ agent:
4
4
  name: 'Neocortex'
5
5
  title: 'Development Orchestrator'
6
6
  icon: '>'
7
- version: '4.60.49'
7
+ version: '4.60.51'
8
8
  architecture: 'thin-client'
9
9
  module: stand-alone
10
10
  hasSidecar: false
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.60.49 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.60.51 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  permissionMode: bypassPermissions
@@ -104,7 +104,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
104
104
  ┌────────────────────────────────────────────────────────────┐
105
105
  │ │
106
106
  │ ####### N E O C O R T E X │
107
- │ ### ######## v4.60.49 │
107
+ │ ### ######## v4.60.51 │
108
108
  │ ######### ##### │
109
109
  │ ## ############## Development Orchestrator │
110
110
  │ ## ### ###### ## OrNexus Team │
@@ -28,7 +28,7 @@ Codex built-in commands or actions.
28
28
 
29
29
  <!-- END: Plugin Conflict Prevention -->
30
30
 
31
- # Neocortex v4.60.49 | OrNexus Team
31
+ # Neocortex v4.60.51 | OrNexus Team
32
32
 
33
33
  You are a Development Orchestrator. All orchestration logic is delivered by the remote Neocortex server.
34
34
 
@@ -160,7 +160,12 @@ Root agent runtime flow:
160
160
  3. **When `kind: 'task'` directive is present**, I may delegate one isolated
161
161
  child `neocortex` execution per authorized story (respecting
162
162
  `agents.max_depth=1`). This is child task delegation, not transfer of yoloop
163
- ownership.
163
+ ownership. For per-story yoloop delegation, before asking the host to spawn,
164
+ I also require all three public gates:
165
+ `platformCapabilities.supportsTaskDelegation === true`,
166
+ `taskDelegationCapability === 'native_safe'`, and a closed
167
+ `dispatchBinding` for the same story and current graph revision. A legacy or
168
+ mismatched directive remains inline; local host capability never elevates it.
164
169
  4. **When NO `kind: 'task'` directive is present** (only `kind: 'skill'`), I do
165
170
  NOT create a child execution. I use `/loop` inline or the shell-loop fallback
166
171
  documented below to keep ownership in this root.
@@ -183,6 +188,34 @@ operator remediation according to the server response.
183
188
  (`neocortex.toml`), not a Neocortex server trigger. Never pass
184
189
  `@neocortex *yoloop ...` or `*yoloop ...` to a child execution.
185
190
 
191
+ ### Native child observation
192
+
193
+ For an authorized graph-bound per-story task, the root reserves before spawn.
194
+ It passes only public gate fields, binding and host attestation to
195
+ `neocortex-client native-agent reserve --project-root ...` as bounded stdin JSON.
196
+ `action=spawn-once` authorizes one spawn. `action=reconcile-existing` forbids a
197
+ replacement: enumerate or wait on the host tree and reconcile that agent first.
198
+
199
+ The host runtime remains the only liveness authority. After a real host event,
200
+ list or bounded wait result, the root records the transition with
201
+ `neocortex-client native-agent observe --project-root ...` using stdin JSON.
202
+ The client accepts the raw host identifier only on stdin, converts it to an
203
+ opaque `agt_` digest locally and never prints or persists the raw identifier.
204
+ Do not place raw handles in commentary, prompts, tracked state or server args.
205
+
206
+ Use the lifecycle `requested -> spawned -> running -> completed|failed|interrupted`.
207
+ An unavailable event stream or exhausted bounded polling budget becomes
208
+ `unknown`, never `running`. A fresh authoritative host listing that omits a
209
+ previously observed child becomes `lost`; neither state authorizes an automatic
210
+ replacement. Query `neocortex-client native-agent status --dispatch-key ...`
211
+ to resume after restart or compaction. Prefer host events, otherwise use at most
212
+ 30 cancelable polls with one poll in flight per dispatch key.
213
+
214
+ Tell the user only when the lifecycle state changes, a stale/unknown heartbeat
215
+ becomes relevant, a terminal result arrives, or user action is required.
216
+ Unchanged polls stay silent. `native-agent`, `headless-process` and `inline` are
217
+ distinct topologies; none promises a sidebar entry.
218
+
186
219
  ### Architecture continuation ownership
187
220
 
188
221
  For `*arch-plan`, the root consumes `metadata.archPlan.execution` as the sole
@@ -98,4 +98,10 @@ or injects a successor, replays the outer *arch-plan command, or assumes pipelin
98
98
  ownership. Child depth is bounded to one; any nested task directive is a
99
99
  fail-closed recursion violation. The root handles an explicit inline fallback
100
100
  when native task delegation is unavailable.
101
+
102
+ Native child reservation, host-handle observation, status polling and yoloop
103
+ continuation are root-only responsibilities. This child must never invoke the
104
+ `native-agent` bridge, enumerate or spawn another agent, persist a host handle,
105
+ or infer liveness from silence. It returns only its terminal per-story result to
106
+ the root.
101
107
  """
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.60.49 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.60.51 | OrNexus Team"
4
4
  model: inherit
5
5
  readonly: false
6
6
  is_background: false
@@ -64,7 +64,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
64
64
  ┌────────────────────────────────────────────────────────────┐
65
65
  │ │
66
66
  │ ####### N E O C O R T E X │
67
- │ ### ######## v4.60.49 │
67
+ │ ### ######## v4.60.51 │
68
68
  │ ######### ##### │
69
69
  │ ## ############## Development Orchestrator │
70
70
  │ ## ### ###### ## OrNexus Team │