@ornexus/neocortex 4.59.3 → 4.59.4

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.
@@ -3,9 +3,9 @@
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.5",
5
5
  "version": 1,
6
- "serialNumber": "urn:uuid:60f55e62-7029-4bc4-b8e3-f0bd7dc385fa",
6
+ "serialNumber": "urn:uuid:6fc05a3f-c761-4fca-bbb4-d8ad50c4f3e7",
7
7
  "metadata": {
8
- "timestamp": "2026-06-23T23:41:38.960Z",
8
+ "timestamp": "2026-06-24T05:21:07.061Z",
9
9
  "tools": {
10
10
  "components": [
11
11
  {
@@ -83,10 +83,10 @@
83
83
  "type": "application",
84
84
  "name": "neocortex",
85
85
  "group": "@ornexus",
86
- "version": "4.59.3",
87
- "bom-ref": "@ornexus/neocortex@4.59.3",
86
+ "version": "4.59.4",
87
+ "bom-ref": "@ornexus/neocortex@4.59.4",
88
88
  "author": "OrNexus Team",
89
- "description": "Neocortex v4.59.3 - Orquestrador de Desenvolvimento de Epics & Stories para Claude Code",
89
+ "description": "Neocortex v4.59.4 - Orquestrador de Desenvolvimento de Epics & Stories para Claude Code",
90
90
  "licenses": [
91
91
  {
92
92
  "license": {
@@ -94,7 +94,7 @@
94
94
  }
95
95
  }
96
96
  ],
97
- "purl": "pkg:npm/%40ornexus/neocortex@4.59.3?vcs_url=git%2Bhttps%3A%2F%2Fgithub.com%2FOrNexus-AI%2Fneocortex.git",
97
+ "purl": "pkg:npm/%40ornexus/neocortex@4.59.4?vcs_url=git%2Bhttps%3A%2F%2Fgithub.com%2FOrNexus-AI%2Fneocortex.git",
98
98
  "externalReferences": [
99
99
  {
100
100
  "url": "git+https://github.com/OrNexus-AI/neocortex.git",
@@ -3819,9 +3819,9 @@
3819
3819
  "type": "library",
3820
3820
  "name": "client",
3821
3821
  "group": "@neocortex",
3822
- "version": "4.59.3",
3823
- "bom-ref": "@neocortex/client@4.59.3",
3824
- "purl": "pkg:npm/%40neocortex/client@4.59.3",
3822
+ "version": "4.59.4",
3823
+ "bom-ref": "@neocortex/client@4.59.4",
3824
+ "purl": "pkg:npm/%40neocortex/client@4.59.4",
3825
3825
  "properties": [
3826
3826
  {
3827
3827
  "name": "cdx:npm:package:path",
@@ -3837,9 +3837,9 @@
3837
3837
  "type": "library",
3838
3838
  "name": "shared",
3839
3839
  "group": "@neocortex",
3840
- "version": "4.59.3",
3841
- "bom-ref": "@neocortex/shared@4.59.3",
3842
- "purl": "pkg:npm/%40neocortex/shared@4.59.3",
3840
+ "version": "4.59.4",
3841
+ "bom-ref": "@neocortex/shared@4.59.4",
3842
+ "purl": "pkg:npm/%40neocortex/shared@4.59.4",
3843
3843
  "properties": [
3844
3844
  {
3845
3845
  "name": "cdx:npm:package:path",
@@ -6222,13 +6222,13 @@
6222
6222
  ],
6223
6223
  "dependencies": [
6224
6224
  {
6225
- "ref": "@ornexus/neocortex@4.59.3",
6225
+ "ref": "@ornexus/neocortex@4.59.4",
6226
6226
  "dependsOn": [
6227
6227
  "@clack/prompts@1.0.1",
6228
6228
  "@modelcontextprotocol/sdk@1.26.0",
6229
- "@neocortex/client@4.59.3",
6229
+ "@neocortex/client@4.59.4",
6230
6230
  "@neocortex/core@0.1.0",
6231
- "@neocortex/shared@4.59.3",
6231
+ "@neocortex/shared@4.59.4",
6232
6232
  "better-sqlite3@12.11.1",
6233
6233
  "execa@9.6.1",
6234
6234
  "node-cache@5.1.2",
@@ -6765,16 +6765,16 @@
6765
6765
  "ref": "zod@4.3.6"
6766
6766
  },
6767
6767
  {
6768
- "ref": "@neocortex/client@4.59.3",
6768
+ "ref": "@neocortex/client@4.59.4",
6769
6769
  "dependsOn": [
6770
- "@neocortex/shared@4.59.3",
6770
+ "@neocortex/shared@4.59.4",
6771
6771
  "better-sqlite3@12.11.1",
6772
6772
  "jose@6.2.2",
6773
6773
  "keytar@7.9.0"
6774
6774
  ]
6775
6775
  },
6776
6776
  {
6777
- "ref": "@neocortex/shared@4.59.3"
6777
+ "ref": "@neocortex/shared@4.59.4"
6778
6778
  },
6779
6779
  {
6780
6780
  "ref": "better-sqlite3@12.11.1",
@@ -6813,7 +6813,7 @@
6813
6813
  {
6814
6814
  "ref": "@neocortex/core@0.1.0",
6815
6815
  "dependsOn": [
6816
- "@neocortex/shared@4.59.3"
6816
+ "@neocortex/shared@4.59.4"
6817
6817
  ]
6818
6818
  },
6819
6819
  {
package/install.ps1 CHANGED
@@ -17,7 +17,7 @@ param(
17
17
  [string]$ServerUrl = "https://api.neocortex.sh"
18
18
  )
19
19
 
20
- $VERSION = "4.59.3"
20
+ $VERSION = "4.59.4"
21
21
 
22
22
  # =============================================================================
23
23
  # CONFIGURACOES
package/install.sh CHANGED
@@ -4,7 +4,7 @@
4
4
  # Development Orchestrator
5
5
 
6
6
  # Versao do instalador
7
- VERSION="4.59.3"
7
+ VERSION="4.59.4"
8
8
 
9
9
  # Flags
10
10
  MIGRATION_DETECTED=false
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ornexus/neocortex",
3
- "version": "4.59.3",
4
- "description": "Neocortex v4.59.3 - Orquestrador de Desenvolvimento de Epics & Stories para Claude Code",
3
+ "version": "4.59.4",
4
+ "description": "Neocortex v4.59.4 - Orquestrador de Desenvolvimento de Epics & Stories para Claude Code",
5
5
  "keywords": [
6
6
  "claude",
7
7
  "claude-code",
@@ -1,14 +1,14 @@
1
- import{createHash as L}from"node:crypto";import{existsSync as C,readFileSync as N,unlinkSync as se,writeFileSync as ie,mkdirSync as ae,statSync as ce}from"node:fs";import{join as E}from"node:path";import{homedir as b}from"node:os";import{LicenseClient as ue}from"../license/license-client.js";import{EncryptedCache as $}from"../cache/encrypted-cache.js";import{NoOpCache as de}from"../types/index.js";import{resolveClientPreFlightTrigger as le,TierAwareClient as pe}from"../tier/tier-aware-client.js";import{loadSecureConfig as fe}from"../config/secure-config.js";import{DEFAULT_SERVER_URL as me}from"../constants.js";import{detectFirstRunLocale as ge,renderFirstRunMessage as he}from"../i18n/first-run.js";import{humanizeError as U,formatHumanizedError as F,detectErrorLocale as M}from"../errors/error-messages.js";import{projectStateSnapshotForInvoke as _e}from"../state/project-state-snapshot.js";import{maybeRepairStateJsonBeforeInvoke as ye,StateRepairHardStopError as Ee}from"../state/state-json-repair.js";import{bootstrapArchitectureMemory as Se}from"../memory/project-memory-writer.js";import{RUNNER_BOOTSTRAP_POLICY_REASON_CODES as Re,classifyRunnerBootstrapPolicyFromArgs as we}from"../continuity/runner-bootstrap-policy.js";import{RUNNER_SCHEDULER_BOOTSTRAP_REASON_CODES as Ce,ensureRunnerSchedulerBootstrap as Te}from"../runner/scheduler.js";const I=E(b(),".neocortex"),j=E(I,"cache"),B=E(j,"menu-cache.json"),Y=1440*60*1e3,K=3e4,S="3.9.62",z=256*1024,Ae=.8,w="[REDACTED]",Ne=1e5,O=2e3,Ie=200,Oe=200,be=12,ke=/(?:promptBody|workflow|workflowGraph|stepBody|privateUrl|rawLog|secret|credential|licenseKey|apiKey|internalRouting|serverOnly|proprietary|protected)/i,xe=/(?:PRIVATE|PROTECTED|SERVER_ONLY)[-_\s]*(?:PROMPT|PROMPT_BODY|WORKFLOW|WORKFLOW_GRAPH|STEP_BODY|STEP|ROUTING)\s*[:=][^\n\r]*/gi,V=Math.floor(z*Ae),H=E(I,".first-run-shown"),Pe="<!-- NEOCORTEX-MEMORY-START -->";function De(e){return/^\s*\*?init(?:\s|$)/i.test(e)}function ve(e){const t=E(e,"NEOCORTEX.md"),r=C(t)?N(t,"utf8"):void 0,o=r===void 0?["missing_canonical_memory"]:[r.includes(Pe)?void 0:"missing_managed_memory_block",r.length>18e3?"canonical_memory_over_budget":void 0,/api[-_ ]?key|license[-_ ]?key|password\s*[:=]|secret\s*[:=]/i.test(r)?"possible_secret_shape_detected":void 0].filter(u=>!!u),a=["AGENTS.md","CLAUDE.md","GEMINI.md",".opencode/AGENTS.md",".cursor/rules/neocortex.mdc",".github/copilot-instructions.md"].filter(u=>C(E(e,u))),c=o.includes("possible_secret_shape_detected")?"low":o.length===0?"high":a.length>0?"medium":"low",l=Se(e);return{canonical:{path:"NEOCORTEX.md",exists:r!==void 0,incompleteReasons:o,confidence:c},permittedSources:{packageBuildFiles:l.repositoryMap?.find(u=>u.startsWith("Package/build files:"))?.split(",").length??0,architectureReadmeDocs:l.architectureReferences?.length??0,runtimeConfigTemplates:l.environmentPractices?.[0]?.startsWith("Runtime/config templates:")?l.environmentPractices[0].split(",").length:0,platformWrappers:a.length},wrapperFiles:a,recommendedPreviewCommand:'neocortex-client refresh-memory --dry-run --project-root "$PROJECT_ROOT"',recommendedRefreshCommand:'neocortex-client refresh-memory --project-root "$PROJECT_ROOT"',guardrails:["Use only permitted bootstrap sources; never read real .env files or credentials into memory.","Preserve human-authored wrapper content outside Neocortex managed blocks.","Do not reset .neocortex/state.json or depend on legacy planning.current during init bootstrap."]}}function Le(){try{if(C(H))return;const e=ge(),t=he(e);process.stderr.write(t);try{ae(I,{recursive:!0}),ie(H,new Date().toISOString(),"utf-8")}catch{}}catch{}}function $e(e,t=process.cwd()){return e&&e.trim().length>0?e:t}function Ue(e){return e.replace(/[\w.+-]+@[\w-]+\.[\w.-]+/g,w).replace(/(?:sk|pk|whsec|nxk)[-_](?:test|live|ant|proj|pro|free|enterprise)?[-_]?[A-Za-z0-9_-]{16,}/g,w).replace(/NX-[FPE]-[a-f0-9]{24}-[a-f0-9]{4}/g,w).replace(/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,w).replace(xe,w)}function T(e,t){const r=Ue(e);return r.length<=t?r:`${r.slice(0,t)}\u2026[TRUNCATED:${r.length-t}]`}function k(e,t=0,r=new WeakSet){if(t>be)return"[MAX_DEPTH]";if(e==null)return e;if(typeof e=="string")return T(e,O);if(typeof e=="number")return Number.isFinite(e)?e:null;if(typeof e=="boolean")return e;if(typeof e=="bigint")return String(e);if(typeof e=="function"||typeof e=="symbol"||typeof e!="object")return;if(r.has(e))return"[CIRCULAR]";if(r.add(e),Array.isArray(e))return e.slice(0,Ie).map(i=>k(i,t+1,r));const o={};for(const[i,a]of Object.entries(e).slice(0,Oe)){if(ke.test(i)){o[i]=w;continue}const c=k(a,t+1,r);c!==void 0&&(o[i]=c)}return o}function x(e,t){return{instructions:T(e??"",Ne),metadata:t?k(t):void 0}}class y extends Error{code;constructor(t,r){super(r),this.name="InvokeCliInputError",this.code=t}}let P=!1;function Fe(e){const t=[];if(!e||typeof e!="object")return t;const r=e,o=r.planning;if(o&&(o.current!==void 0||Array.isArray(o.history))&&t.push({code:"PLANNING_LEGACY",message:"legacy `planning.current`/`planning.history` detected (not read by v1 orchestrator)"}),Array.isArray(r.stories)&&t.push({code:"STORIES_AS_ARRAY",message:"`stories` is an Array (expected Object keyed by story ID)"}),r.epics&&typeof r.epics=="object"&&!Array.isArray(r.epics))for(const[a,c]of Object.entries(r.epics)){const l=c;if(l&&l.stories!==void 0&&!Array.isArray(l.stories)){t.push({code:"EPIC_STORIES_NOT_ARRAY",message:`epic "${a}" has non-array \`stories\` field (expected string[] of story IDs)`});break}}const i=r.epics&&typeof r.epics=="object"&&Object.keys(r.epics).length>0||r.stories&&typeof r.stories=="object"&&!Array.isArray(r.stories)&&Object.keys(r.stories).length>0||Array.isArray(r.stories)||o&&o.current!==void 0;return r.schema_version===void 0?i&&t.push({code:"SCHEMA_VERSION_MISSING",message:"`schema_version` field missing (expected: `schema_version: 1`)"}):r.schema_version!==1&&t.push({code:"SCHEMA_VERSION_OUTDATED",message:`schema_version=${String(r.schema_version)} (expected: 1)`}),t}function Me(e){if(!(P||e.length===0)){P=!0;try{const t=e.map(r=>` - ${r.message}`).join(`
1
+ import{createHash as $}from"node:crypto";import{existsSync as C,readFileSync as N,unlinkSync as se,writeFileSync as ie,mkdirSync as ae,statSync as ce}from"node:fs";import{join as E}from"node:path";import{homedir as k}from"node:os";import{LicenseClient as ue}from"../license/license-client.js";import{EncryptedCache as U}from"../cache/encrypted-cache.js";import{NoOpCache as de}from"../types/index.js";import{resolveClientPreFlightTrigger as le,TierAwareClient as pe}from"../tier/tier-aware-client.js";import{loadSecureConfig as fe}from"../config/secure-config.js";import{DEFAULT_SERVER_URL as me}from"../constants.js";import{detectFirstRunLocale as ge,renderFirstRunMessage as he}from"../i18n/first-run.js";import{humanizeError as F,formatHumanizedError as M,detectErrorLocale as j}from"../errors/error-messages.js";import{projectStateSnapshotForInvoke as _e}from"../state/project-state-snapshot.js";import{maybeRepairStateJsonBeforeInvoke as ye,StateRepairHardStopError as Ee}from"../state/state-json-repair.js";import{bootstrapArchitectureMemory as Se}from"../memory/project-memory-writer.js";import{RUNNER_BOOTSTRAP_POLICY_REASON_CODES as we,classifyRunnerBootstrapPolicyFromArgs as Re}from"../continuity/runner-bootstrap-policy.js";import{RUNNER_SCHEDULER_BOOTSTRAP_REASON_CODES as Ce,ensureRunnerSchedulerBootstrap as Te}from"../runner/scheduler.js";const I=E(k(),".neocortex"),B=E(I,"cache"),Y=E(B,"menu-cache.json"),K=1440*60*1e3,z=3e4,S="3.9.62",V=256*1024,Ae=.8,R="[REDACTED]",Ne=1e5,O=2e3,Ie=200,Oe=200,be=12,ke=/(?:promptBody|workflow|workflowGraph|stepBody|privateUrl|rawLog|secret|credential|licenseKey|apiKey|internalRouting|serverOnly|proprietary|protected)/i,xe=/(?:PRIVATE|PROTECTED|SERVER_ONLY)[-_\s]*(?:PROMPT|PROMPT_BODY|WORKFLOW|WORKFLOW_GRAPH|STEP_BODY|STEP|ROUTING)\s*[:=][^\n\r]*/gi,H=Math.floor(V*Ae),G=E(I,".first-run-shown"),Pe="<!-- NEOCORTEX-MEMORY-START -->";function De(e){return/^\s*\*?init(?:\s|$)/i.test(e)}function ve(e){const t=E(e,"NEOCORTEX.md"),r=C(t)?N(t,"utf8"):void 0,o=r===void 0?["missing_canonical_memory"]:[r.includes(Pe)?void 0:"missing_managed_memory_block",r.length>18e3?"canonical_memory_over_budget":void 0,/api[-_ ]?key|license[-_ ]?key|password\s*[:=]|secret\s*[:=]/i.test(r)?"possible_secret_shape_detected":void 0].filter(u=>!!u),a=["AGENTS.md","CLAUDE.md","GEMINI.md",".opencode/AGENTS.md",".cursor/rules/neocortex.mdc",".github/copilot-instructions.md"].filter(u=>C(E(e,u))),c=o.includes("possible_secret_shape_detected")?"low":o.length===0?"high":a.length>0?"medium":"low",l=Se(e);return{canonical:{path:"NEOCORTEX.md",exists:r!==void 0,incompleteReasons:o,confidence:c},permittedSources:{packageBuildFiles:l.repositoryMap?.find(u=>u.startsWith("Package/build files:"))?.split(",").length??0,architectureReadmeDocs:l.architectureReferences?.length??0,runtimeConfigTemplates:l.environmentPractices?.[0]?.startsWith("Runtime/config templates:")?l.environmentPractices[0].split(",").length:0,platformWrappers:a.length},wrapperFiles:a,recommendedPreviewCommand:'neocortex-client refresh-memory --dry-run --project-root "$PROJECT_ROOT"',recommendedRefreshCommand:'neocortex-client refresh-memory --project-root "$PROJECT_ROOT"',guardrails:["Use only permitted bootstrap sources; never read real .env files or credentials into memory.","Preserve human-authored wrapper content outside Neocortex managed blocks.","Do not reset .neocortex/state.json or depend on legacy planning.current during init bootstrap."]}}function Le(){try{if(C(G))return;const e=ge(),t=he(e);process.stderr.write(t);try{ae(I,{recursive:!0}),ie(G,new Date().toISOString(),"utf-8")}catch{}}catch{}}function $e(e,t=process.cwd()){return e&&e.trim().length>0?e:t}function Ue(e){return e.replace(/[\w.+-]+@[\w-]+\.[\w.-]+/g,R).replace(/(?:sk|pk|whsec|nxk)[-_](?:test|live|ant|proj|pro|free|enterprise)?[-_]?[A-Za-z0-9_-]{16,}/g,R).replace(/NX-[FPE]-[a-f0-9]{24}-[a-f0-9]{4}/g,R).replace(/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,R).replace(xe,R)}function T(e,t){const r=Ue(e);return r.length<=t?r:`${r.slice(0,t)}\u2026[TRUNCATED:${r.length-t}]`}function x(e,t=0,r=new WeakSet){if(t>be)return"[MAX_DEPTH]";if(e==null)return e;if(typeof e=="string")return T(e,O);if(typeof e=="number")return Number.isFinite(e)?e:null;if(typeof e=="boolean")return e;if(typeof e=="bigint")return String(e);if(typeof e=="function"||typeof e=="symbol"||typeof e!="object")return;if(r.has(e))return"[CIRCULAR]";if(r.add(e),Array.isArray(e))return e.slice(0,Ie).map(i=>x(i,t+1,r));const o={};for(const[i,a]of Object.entries(e).slice(0,Oe)){if(ke.test(i)){o[i]=R;continue}const c=x(a,t+1,r);c!==void 0&&(o[i]=c)}return o}function P(e,t){return{instructions:T(e??"",Ne),metadata:t?x(t):void 0}}class y extends Error{code;constructor(t,r){super(r),this.name="InvokeCliInputError",this.code=t}}let D=!1;function Fe(e){const t=[];if(!e||typeof e!="object")return t;const r=e,o=r.planning;if(o&&(o.current!==void 0||Array.isArray(o.history))&&t.push({code:"PLANNING_LEGACY",message:"legacy `planning.current`/`planning.history` detected (not read by v1 orchestrator)"}),Array.isArray(r.stories)&&t.push({code:"STORIES_AS_ARRAY",message:"`stories` is an Array (expected Object keyed by story ID)"}),r.epics&&typeof r.epics=="object"&&!Array.isArray(r.epics))for(const[a,c]of Object.entries(r.epics)){const l=c;if(l&&l.stories!==void 0&&!Array.isArray(l.stories)){t.push({code:"EPIC_STORIES_NOT_ARRAY",message:`epic "${a}" has non-array \`stories\` field (expected string[] of story IDs)`});break}}const i=r.epics&&typeof r.epics=="object"&&Object.keys(r.epics).length>0||r.stories&&typeof r.stories=="object"&&!Array.isArray(r.stories)&&Object.keys(r.stories).length>0||Array.isArray(r.stories)||o&&o.current!==void 0;return r.schema_version===void 0?i&&t.push({code:"SCHEMA_VERSION_MISSING",message:"`schema_version` field missing (expected: `schema_version: 1`)"}):r.schema_version!==1&&t.push({code:"SCHEMA_VERSION_OUTDATED",message:`schema_version=${String(r.schema_version)} (expected: 1)`}),t}function Me(e){if(!(D||e.length===0)){D=!0;try{const t=e.map(r=>` - ${r.message}`).join(`
2
2
  `);process.stderr.write(`[Neocortex] state.json schema drift detected:
3
3
  ${t}
4
4
  Run \`neocortex *migrate-state --preview\` to inspect or \`neocortex *migrate-state --apply\` to migrate.
5
5
  See docs/arquitetura-software/STATE-JSON-SCHEMA.md for the schema contract.
6
- `)}catch{}}}function At(){P=!1}function G(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.length>0):[]}function je(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.length>0):[]}function Be(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function q(e){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:void 0}function R(e){if(typeof e!="string")return;const t=e.trim();if(t)return t.replace(/[^a-z0-9_.:-]+/gi,"_").slice(0,120)}function D(e,t){if(!Be(e))return;const r={};for(const o of t){const i=e[o];if(typeof i=="boolean")r[o]=i;else if(typeof i=="number"&&Number.isFinite(i))r[o]=i;else if(typeof i=="string"){const a=R(i);a&&(r[o]=a)}}return Object.keys(r).length>0?r:void 0}function Ye(e){const t=D(e.completionEvidence??e.completion_evidence,["prNumber","pr_number","prState","pr_state","pullRequestState","merged","mergedAt","issueNumber","issue_number","issueState","issue_state","closedAt"]),r=D(e.issueCloseAudit??e.issue_close_audit,["schema_version","event","storyId","epicId","issueNumber","closedAt","publicSafe","rawLogStorage"]),o=D(e.scopedCiEvidence??e.scoped_ci_evidence,["schema_version","storyId","epicId","prNumber","finalState","publicSafe","rawLogStorage"]);return{...typeof e.merged=="boolean"?{merged:e.merged}:{},...typeof e.safeToContinueYoloop=="boolean"?{safeToContinueYoloop:e.safeToContinueYoloop}:{},...typeof e.mergeBlockedRemotely=="boolean"?{mergeBlockedRemotely:e.mergeBlockedRemotely}:{},...R(e.physicalMergeStatus)?{physicalMergeStatus:R(e.physicalMergeStatus)}:{},...R(e.pr_state??e.prState??e.pull_request_state??e.pullRequestState)?{pr_state:R(e.pr_state??e.prState??e.pull_request_state??e.pullRequestState)}:{},...R(e.issue_state??e.issueState??e.workflow_issue_state)?{issue_state:R(e.issue_state??e.issueState??e.workflow_issue_state)}:{},...q(e.issue_number??e.issueNumber)?{issue_number:q(e.issue_number??e.issueNumber)}:{},...t?{completionEvidence:t}:{},...r?{issueCloseAudit:r}:{},...o?{scopedCiEvidence:o}:{}}}function Ke(e){const t=E(e,".neocortex","state.json");if(!C(t))return{config:{project_name:"unknown",default_branch:"main",language:"pt-BR"},stories:{},epics:{}};let r;try{const u=N(t,"utf-8");r=JSON.parse(u)}catch{return{config:{project_name:"unknown",default_branch:"main",language:"pt-BR"},stories:{},epics:{}}}try{const u=Fe(r);u.length>0&&Me(u)}catch{}const o=r.config??r.project??{},i=r.stories??{},a={};for(const[u,d]of Object.entries(i))a[u]={id:d.id??u,title:d.title,epic_id:d.epic_id,status:d.status??"backlog",steps_completed:d.steps_completed??[],last_step:d.last_step??null,branch_name:d.branch_name??null,pr_number:d.pr_number,workflow_issue:d.workflow_issue,...Ye(d),depends_on:G(d.depends_on),files_to_modify:je(d.files_to_modify),risk:typeof d.risk=="string"?d.risk:void 0,blast_radius:typeof d.blast_radius=="number"?d.blast_radius:void 0};const c=r.epics??{},l={};for(const[u,d]of Object.entries(c))l[u]={id:d.id??u,title:d.title,status:d.status,stories:d.stories,total_stories:d.total_stories,completed_stories:d.completed_stories,depends_on:G(d.depends_on)};return{schema_version:typeof r.schema_version=="number"?r.schema_version:void 0,config:{project_name:o.project_name??o.name??"unknown",default_branch:o.default_branch??"main",language:o.language??"pt-BR",yolo_mode:o.yolo_mode,user_name:o.user_name,worktree_base:o.worktree_base,max_parallel_stories:o.max_parallel_stories},stories:a,epics:l}}function Nt(e,t){return{kind:"full",trigger:e,targetEpicId:null,targetStoryId:null,includedStoryCount:Object.keys(t.stories).length,omittedStoryCount:0,omittedEpicCount:0,reason:"full-state"}}const J="neocortex:menu:cache";async function ze(e){try{const t=await e.get(J);if(!t)return null;const r=JSON.parse(t);return r.version!==S||Date.now()-r.cachedAt>Y?null:r}catch{return null}}async function Ve(e,t,r){try{const o={instructions:t,metadata:r,cachedAt:Date.now(),version:S};await e.set(J,JSON.stringify(o),Y),He()}catch{}}function He(){try{C(B)&&se(B)}catch{}}function Ge(){return fe()}async function qe(e,t){try{let r;if(t){const c=E(I,"cache");r=new $({cacheDir:c,passphrase:t})}else process.stderr.write(`[neocortex] Warning: No license key in config. Run "neocortex activate" to re-authenticate.
7
- `),r=new de;const o=new ue({serverUrl:e,licenseKey:t??"",cacheProvider:r}),i=await o.getToken();if(!i)return null;const a=new pe({cacheProvider:r,licenseClient:o});return{token:i,client:o,tierClient:a}}catch{return null}}let W=!1;function X(e){return L("sha256").update(e).digest("hex")}function Je(){const e=Number(process.env.NEOCORTEX_INVOKE_CHUNK_BYTES??"49152");return Number.isFinite(e)&&e>=1024&&e<=98304?Math.floor(e):49152}function We(e,t,r){return`args-${L("sha256").update("invoke-materialization:v1").update(e).update(String(t)).update(JSON.stringify(r)).digest("hex")}`}async function Q(e,t,r,o){const i=await fetch(`${e}${t}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`,"X-Client-Version":S},body:JSON.stringify(r)}),a=await i.text().catch(()=>""),c=(()=>{try{return a?JSON.parse(a):{}}catch{return{}}})();if(!i.ok){const l=typeof c.error_code=="string"?c.error_code:`HTTP_${i.status}`,u=typeof c.message=="string"?c.message:"materialization upload failed";throw new Error(`${l}: ${u}`)}return c}async function Xe(e,t,r){const o=Buffer.from(t,"utf8"),i=Je(),a=[];for(let f=0,h=0;f<o.byteLength;f+=i,h++){const _=o.subarray(f,Math.min(f+i,o.byteLength));a.push({index:h,sha256:X(_),byteLength:_.byteLength})}const c=X(o),l=We(c,o.byteLength,a),u=Number(process.env.NEOCORTEX_INVOKE_CHUNK_TTL_SECONDS??"900");for(const f of a){const h=f.index*i,_=o.subarray(h,h+f.byteLength);await Q(e,"/api/v1/invoke/materialization/chunks",{manifestId:l,index:f.index,sha256:f.sha256,byteLength:f.byteLength,contentBase64:_.toString("base64"),ttlSeconds:u,idempotencyKey:`${l}:${f.index}:${f.sha256}`},r)}const m=(await Q(e,"/api/v1/invoke/materialization/manifests",{manifestId:l,sha256:c,byteLength:o.byteLength,chunkCount:a.length,chunks:a,ttlSeconds:u,retry:{attempt:1,budget:3,idempotencyKey:l}},r)).argsRef;if(!m?.manifestId)throw new Error("MATERIALIZATION_RESPONSE_INVALID: missing argsRef");return{argsRef:m,chunks:a}}function Qe(e){return Buffer.byteLength(JSON.stringify(e),"utf8")}function Ze(e){return re(e)??e.trim().split(/\s+/,1)[0]?.slice(0,80)??"(empty)"}function et(e){return e.args!==void 0?Ze(e.args):`argsRef:${e.argsRef.manifestId.slice(0,80)}`}function Z(e){const t=Qe(e);if(t<V)return t;const r=e.stateSnapshot.scope,o=Object.keys(e.stateSnapshot.stories).length,i=r?.kind??"full",a=r?.includedStoryCount??o,c=r?.omittedStoryCount??0;return process.stderr.write(`[Neocortex] invoke payload near server limit: trigger=${et(e)} scope=${i} bytes=${t} limit=${z} includedStories=${a} omittedStories=${c}
8
- `),t}async function tt(e){const t=we(e.args,{platformTarget:e.platformTarget,environment:e.environment??process.env});if(t.action==="skipped")return{shouldContinue:!0,attachToRequest:rt(t),metadata:ee(t)};const r=e.bootstrapper??Te;let o;try{o=await r({projectRoot:e.projectRoot,env:e.environment??process.env})}catch{o={ok:!1,attempted:!0,installed:!1,started:!1,cached:!1,projectKey:"unknown",reasonCodes:[Ce.UNEXPECTED_ERROR],publicSummary:"runner scheduler bootstrap stopped unexpectedly.",publicSafe:!0}}const i=ee(t,o);if(o.ok)return{shouldContinue:!0,attachToRequest:!0,metadata:i};const a=i.reasonCodes.slice(0,5).join(",");return t.failurePolicy==="fail-open"?{shouldContinue:!0,attachToRequest:!0,metadata:{...i,failOpenWarning:!0},warning:`Runner auto-bootstrap warning (${a}); continuing fail-open for operator command.`}:{shouldContinue:!1,attachToRequest:!1,metadata:i,errorCode:"RUNNER_BOOTSTRAP_REQUIRED_FAILED",error:`Runner auto-bootstrap required but failed (${a}). Run neocortex-runner doctor or retry after resolving scheduler setup.`,exitCode:1}}function rt(e){return!e.reasonCodes.includes(Re.SKIPPED_NON_CONTINUITY_COMMAND)}function ee(e,t){return{schemaVersion:1,action:e.action,failurePolicy:e.failurePolicy,command:e.command,operation:e.operation,attempted:t?.attempted??!1,ok:t?.ok??!0,cached:t?.cached??!1,installed:t?.installed??!1,started:t?.started??!1,...t?.projectKey?{projectKey:t.projectKey}:{},reasonCodes:nt([...e.reasonCodes,...t?.reasonCodes??[]]),publicSummary:t?.publicSummary??e.publicSummary,publicSafe:!0}}function nt(e){return Array.from(new Set(e.map(t=>t.slice(0,120))))}async function te(e,t,r){const o=`${e}/api/v1/invoke`,i=new AbortController,a=setTimeout(()=>i.abort(),K);try{const c=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`,"X-Client-Version":S},body:JSON.stringify(t),signal:i.signal});if(clearTimeout(a),!c.ok){const d=await c.text().catch(()=>"Unknown error");let m;try{m=JSON.parse(d)}catch{}return{ok:!1,status:c.status,error:m?`${m.error_code??"ERROR"}: ${m.message??d}`:`HTTP ${c.status}: ${d}`,errorBody:m}}const l=await c.json(),u=c.headers.get("X-Client-Version-Warning");return u&&!W&&(W=!0,process.stderr.write(`
6
+ `)}catch{}}}function At(){D=!1}function q(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.length>0):[]}function je(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.length>0):[]}function Be(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function b(e){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:void 0}function w(e){if(typeof e!="string")return;const t=e.trim();if(t)return t.replace(/[^a-z0-9_.:-]+/gi,"_").slice(0,120)}function v(e,t){if(!Be(e))return;const r={};for(const o of t){const i=e[o];if(typeof i=="boolean")r[o]=i;else if(typeof i=="number"&&Number.isFinite(i))r[o]=i;else if(typeof i=="string"){const a=w(i);a&&(r[o]=a)}}return Object.keys(r).length>0?r:void 0}function Ye(e){const t=v(e.completionEvidence??e.completion_evidence,["prNumber","pr_number","prState","pr_state","pullRequestState","merged","mergedAt","issueNumber","issue_number","issueState","issue_state","closedAt"]),r=v(e.issueCloseAudit??e.issue_close_audit,["schema_version","event","storyId","epicId","issueNumber","closedAt","publicSafe","rawLogStorage"]),o=v(e.scopedCiEvidence??e.scoped_ci_evidence,["schema_version","storyId","epicId","prNumber","finalState","publicSafe","rawLogStorage"]);return{...typeof e.merged=="boolean"?{merged:e.merged}:{},...typeof e.safeToContinueYoloop=="boolean"?{safeToContinueYoloop:e.safeToContinueYoloop}:{},...typeof e.mergeBlockedRemotely=="boolean"?{mergeBlockedRemotely:e.mergeBlockedRemotely}:{},...w(e.physicalMergeStatus)?{physicalMergeStatus:w(e.physicalMergeStatus)}:{},...w(e.pr_state??e.prState??e.pull_request_state??e.pullRequestState)?{pr_state:w(e.pr_state??e.prState??e.pull_request_state??e.pullRequestState)}:{},...w(e.issue_state??e.issueState??e.workflow_issue_state)?{issue_state:w(e.issue_state??e.issueState??e.workflow_issue_state)}:{},...b(e.issue_number??e.issueNumber)?{issue_number:b(e.issue_number??e.issueNumber)}:{},...t?{completionEvidence:t}:{},...r?{issueCloseAudit:r}:{},...o?{scopedCiEvidence:o}:{}}}function Ke(e){const t=E(e,".neocortex","state.json");if(!C(t))return{config:{project_name:"unknown",default_branch:"main",language:"pt-BR"},stories:{},epics:{}};let r;try{const u=N(t,"utf-8");r=JSON.parse(u)}catch{return{config:{project_name:"unknown",default_branch:"main",language:"pt-BR"},stories:{},epics:{}}}try{const u=Fe(r);u.length>0&&Me(u)}catch{}const o=r.config??r.project??{},i=r.stories??{},a={};for(const[u,d]of Object.entries(i))a[u]={id:d.id??u,title:d.title,epic_id:d.epic_id,status:d.status??"backlog",steps_completed:d.steps_completed??[],last_step:d.last_step??null,branch_name:d.branch_name??null,pr_number:d.pr_number,...b(d.workflow_issue)?{workflow_issue:b(d.workflow_issue)}:{},...Ye(d),depends_on:q(d.depends_on),files_to_modify:je(d.files_to_modify),risk:typeof d.risk=="string"?d.risk:void 0,blast_radius:typeof d.blast_radius=="number"?d.blast_radius:void 0};const c=r.epics??{},l={};for(const[u,d]of Object.entries(c))l[u]={id:d.id??u,title:d.title,status:d.status,stories:d.stories,total_stories:d.total_stories,completed_stories:d.completed_stories,depends_on:q(d.depends_on)};return{schema_version:typeof r.schema_version=="number"?r.schema_version:void 0,config:{project_name:o.project_name??o.name??"unknown",default_branch:o.default_branch??"main",language:o.language??"pt-BR",yolo_mode:o.yolo_mode,user_name:o.user_name,worktree_base:o.worktree_base,max_parallel_stories:o.max_parallel_stories},stories:a,epics:l}}function Nt(e,t){return{kind:"full",trigger:e,targetEpicId:null,targetStoryId:null,includedStoryCount:Object.keys(t.stories).length,omittedStoryCount:0,omittedEpicCount:0,reason:"full-state"}}const J="neocortex:menu:cache";async function ze(e){try{const t=await e.get(J);if(!t)return null;const r=JSON.parse(t);return r.version!==S||Date.now()-r.cachedAt>K?null:r}catch{return null}}async function Ve(e,t,r){try{const o={instructions:t,metadata:r,cachedAt:Date.now(),version:S};await e.set(J,JSON.stringify(o),K),He()}catch{}}function He(){try{C(Y)&&se(Y)}catch{}}function Ge(){return fe()}async function qe(e,t){try{let r;if(t){const c=E(I,"cache");r=new U({cacheDir:c,passphrase:t})}else process.stderr.write(`[neocortex] Warning: No license key in config. Run "neocortex activate" to re-authenticate.
7
+ `),r=new de;const o=new ue({serverUrl:e,licenseKey:t??"",cacheProvider:r}),i=await o.getToken();if(!i)return null;const a=new pe({cacheProvider:r,licenseClient:o});return{token:i,client:o,tierClient:a}}catch{return null}}let W=!1;function X(e){return $("sha256").update(e).digest("hex")}function Je(){const e=Number(process.env.NEOCORTEX_INVOKE_CHUNK_BYTES??"49152");return Number.isFinite(e)&&e>=1024&&e<=98304?Math.floor(e):49152}function We(e,t,r){return`args-${$("sha256").update("invoke-materialization:v1").update(e).update(String(t)).update(JSON.stringify(r)).digest("hex")}`}async function Q(e,t,r,o){const i=await fetch(`${e}${t}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`,"X-Client-Version":S},body:JSON.stringify(r)}),a=await i.text().catch(()=>""),c=(()=>{try{return a?JSON.parse(a):{}}catch{return{}}})();if(!i.ok){const l=typeof c.error_code=="string"?c.error_code:`HTTP_${i.status}`,u=typeof c.message=="string"?c.message:"materialization upload failed";throw new Error(`${l}: ${u}`)}return c}async function Xe(e,t,r){const o=Buffer.from(t,"utf8"),i=Je(),a=[];for(let f=0,h=0;f<o.byteLength;f+=i,h++){const _=o.subarray(f,Math.min(f+i,o.byteLength));a.push({index:h,sha256:X(_),byteLength:_.byteLength})}const c=X(o),l=We(c,o.byteLength,a),u=Number(process.env.NEOCORTEX_INVOKE_CHUNK_TTL_SECONDS??"900");for(const f of a){const h=f.index*i,_=o.subarray(h,h+f.byteLength);await Q(e,"/api/v1/invoke/materialization/chunks",{manifestId:l,index:f.index,sha256:f.sha256,byteLength:f.byteLength,contentBase64:_.toString("base64"),ttlSeconds:u,idempotencyKey:`${l}:${f.index}:${f.sha256}`},r)}const m=(await Q(e,"/api/v1/invoke/materialization/manifests",{manifestId:l,sha256:c,byteLength:o.byteLength,chunkCount:a.length,chunks:a,ttlSeconds:u,retry:{attempt:1,budget:3,idempotencyKey:l}},r)).argsRef;if(!m?.manifestId)throw new Error("MATERIALIZATION_RESPONSE_INVALID: missing argsRef");return{argsRef:m,chunks:a}}function Qe(e){return Buffer.byteLength(JSON.stringify(e),"utf8")}function Ze(e){return re(e)??e.trim().split(/\s+/,1)[0]?.slice(0,80)??"(empty)"}function et(e){return e.args!==void 0?Ze(e.args):`argsRef:${e.argsRef.manifestId.slice(0,80)}`}function Z(e){const t=Qe(e);if(t<H)return t;const r=e.stateSnapshot.scope,o=Object.keys(e.stateSnapshot.stories).length,i=r?.kind??"full",a=r?.includedStoryCount??o,c=r?.omittedStoryCount??0;return process.stderr.write(`[Neocortex] invoke payload near server limit: trigger=${et(e)} scope=${i} bytes=${t} limit=${V} includedStories=${a} omittedStories=${c}
8
+ `),t}async function tt(e){const t=Re(e.args,{platformTarget:e.platformTarget,environment:e.environment??process.env});if(t.action==="skipped")return{shouldContinue:!0,attachToRequest:rt(t),metadata:ee(t)};const r=e.bootstrapper??Te;let o;try{o=await r({projectRoot:e.projectRoot,env:e.environment??process.env})}catch{o={ok:!1,attempted:!0,installed:!1,started:!1,cached:!1,projectKey:"unknown",reasonCodes:[Ce.UNEXPECTED_ERROR],publicSummary:"runner scheduler bootstrap stopped unexpectedly.",publicSafe:!0}}const i=ee(t,o);if(o.ok)return{shouldContinue:!0,attachToRequest:!0,metadata:i};const a=i.reasonCodes.slice(0,5).join(",");return t.failurePolicy==="fail-open"?{shouldContinue:!0,attachToRequest:!0,metadata:{...i,failOpenWarning:!0},warning:`Runner auto-bootstrap warning (${a}); continuing fail-open for operator command.`}:{shouldContinue:!1,attachToRequest:!1,metadata:i,errorCode:"RUNNER_BOOTSTRAP_REQUIRED_FAILED",error:`Runner auto-bootstrap required but failed (${a}). Run neocortex-runner doctor or retry after resolving scheduler setup.`,exitCode:1}}function rt(e){return!e.reasonCodes.includes(we.SKIPPED_NON_CONTINUITY_COMMAND)}function ee(e,t){return{schemaVersion:1,action:e.action,failurePolicy:e.failurePolicy,command:e.command,operation:e.operation,attempted:t?.attempted??!1,ok:t?.ok??!0,cached:t?.cached??!1,installed:t?.installed??!1,started:t?.started??!1,...t?.projectKey?{projectKey:t.projectKey}:{},reasonCodes:nt([...e.reasonCodes,...t?.reasonCodes??[]]),publicSummary:t?.publicSummary??e.publicSummary,publicSafe:!0}}function nt(e){return Array.from(new Set(e.map(t=>t.slice(0,120))))}async function te(e,t,r){const o=`${e}/api/v1/invoke`,i=new AbortController,a=setTimeout(()=>i.abort(),z);try{const c=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`,"X-Client-Version":S},body:JSON.stringify(t),signal:i.signal});if(clearTimeout(a),!c.ok){const d=await c.text().catch(()=>"Unknown error");let m;try{m=JSON.parse(d)}catch{}return{ok:!1,status:c.status,error:m?`${m.error_code??"ERROR"}: ${m.message??d}`:`HTTP ${c.status}: ${d}`,errorBody:m}}const l=await c.json(),u=c.headers.get("X-Client-Version-Warning");return u&&!W&&(W=!0,process.stderr.write(`
9
9
  [Neocortex] ${u}
10
10
 
11
- `)),{ok:!0,status:c.status,data:l}}catch(c){clearTimeout(a);const l=c instanceof Error?c.message:String(c);return{ok:!1,status:0,error:l.includes("abort")?`Request timeout after ${K/1e3}s`:`Network error: ${l}`}}}async function ot(e){const t=$e(e.projectRoot),r=e.platformTarget??"claude-code";Le();const o=Ge(),i=(e.serverUrl??o?.serverUrl??me).replace(/\/+$/,"");try{ye(t)}catch(n){if(n instanceof Ee)return process.stderr.write(`${n.message}
11
+ `)),{ok:!0,status:c.status,data:l}}catch(c){clearTimeout(a);const l=c instanceof Error?c.message:String(c);return{ok:!1,status:0,error:l.includes("abort")?`Request timeout after ${z/1e3}s`:`Network error: ${l}`}}}async function ot(e){const t=$e(e.projectRoot),r=e.platformTarget??"claude-code";Le();const o=Ge(),i=(e.serverUrl??o?.serverUrl??me).replace(/\/+$/,"");try{ye(t)}catch(n){if(n instanceof Ee)return process.stderr.write(`${n.message}
12
12
  `),{success:!1,error:n.message,exitCode:1};const s=n instanceof Error?n.message:String(n);return process.stderr.write(`[Neocortex] state.json repair stopped unexpectedly: ${s}. No request was sent; inspect .neocortex/state.json and rerun.
13
13
  `),{success:!1,error:s,exitCode:1}}const a=Ke(t);try{const{maybeAutoResolveYoloopArgs:n}=await import("../yoloop/invoke-hooks.js"),s={args:e.args,projectRoot:t,logger:{info:g=>process.stderr.write(`${g}
14
14
  `),warn:g=>process.stderr.write(`${g}
@@ -18,11 +18,11 @@ ${t}
18
18
  `)}try{const{readArchitecturePolicy:n}=await import("../policy/architecture-policy.js"),s=await n(t);s&&(a.architecture_policy=s)}catch(n){const s=n instanceof Error?n.message:String(n);console.warn(`[Neocortex] architecture-policy hook failed: ${s}. Proceeding without policy.`)}try{const n=/^(1|true|on|yes)$/i.test(process.env.NEOCORTEX_GRAPH_RETRIEVAL??""),{maybeRunGraphRetrievalHook:s}=await import("../yoloop/invoke-hooks.js"),g=await s({args:e.args,projectRoot:t,featureFlag:n,logger:{warn:A=>process.stderr.write(`${A}
19
19
  `)}});g.applied&&g.metadata&&(a.graphRetrieval=g.metadata)}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] graph retrieval hook failed: ${s}. Proceeding without enrichment.
20
20
  `)}try{const{readAndConsumeCheckpoint:n}=await import("../checkpoint/index.js"),s=await n(t);s&&(a.implementCheckpoint=s)}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] checkpoint hook failed: ${s}. Proceeding without checkpoint.
21
- `)}const c=o?.licenseKey?new $({cacheDir:j,passphrase:o.licenseKey}):null,l=e.args.trim();if(De(l))try{a.projectMemoryBootstrap=ve(t)}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] project-memory bootstrap diagnosis failed: ${s}. Proceeding without local memory snapshot.
22
- `)}if(!l&&c){const n=await ze(c);if(n)return{success:!0,instructions:n.instructions,metadata:n.metadata,exitCode:0}}const u=await qe(i,o?.licenseKey);if(!u){const n=o&&!o.licenseKey?" This may be caused by a machine fingerprint change (e.g., hardware or hostname change).":"";try{const s=M(),g=U("NOT_CONFIGURED",s);g&&process.stderr.write(F(g,s))}catch{}return{success:!1,error:`Not authenticated.${n} Visit https://neocortex.sh/portal/login to get your license key, then run: neocortex activate YOUR-LICENSE-KEY`,exitCode:2}}const d=re(l);if(d)try{const n=await u.tierClient.preFlightCheck(d);if(!n.allowed)return process.stderr.write(`[neocortex] ${n.message}
21
+ `)}const c=o?.licenseKey?new U({cacheDir:B,passphrase:o.licenseKey}):null,l=e.args.trim();if(De(l))try{a.projectMemoryBootstrap=ve(t)}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] project-memory bootstrap diagnosis failed: ${s}. Proceeding without local memory snapshot.
22
+ `)}if(!l&&c){const n=await ze(c);if(n)return{success:!0,instructions:n.instructions,metadata:n.metadata,exitCode:0}}const u=await qe(i,o?.licenseKey);if(!u){const n=o&&!o.licenseKey?" This may be caused by a machine fingerprint change (e.g., hardware or hostname change).":"";try{const s=j(),g=F("NOT_CONFIGURED",s);g&&process.stderr.write(M(g,s))}catch{}return{success:!1,error:`Not authenticated.${n} Visit https://neocortex.sh/portal/login to get your license key, then run: neocortex activate YOUR-LICENSE-KEY`,exitCode:2}}const d=re(l);if(d)try{const n=await u.tierClient.preFlightCheck(d);if(!n.allowed)return process.stderr.write(`[neocortex] ${n.message}
23
23
  `),{success:!1,error:n.message??"Trigger not available on your plan",exitCode:1}}catch{}const m=await tt({args:l,projectRoot:t,platformTarget:r,environment:e.environment??process.env,bootstrapper:e.runnerBootstrapper});if(m.attachToRequest&&(a.runnerBootstrap=m.metadata),m.warning&&process.stderr.write(`[Neocortex] ${m.warning}
24
24
  `),!m.shouldContinue)return m.error&&process.stderr.write(`[Neocortex] ${m.error}
25
- `),{success:!1,error:m.error??"Runner auto-bootstrap required but failed.",errorCode:m.errorCode,exitCode:m.exitCode??1};const f=_e(l,a);let h={args:l,projectRoot:t.replace(b(),"~"),stateSnapshot:f,platformTarget:r};const _=Z(h);if(e.inputSource&&e.inputSource!=="args"&&_>=V)try{h={argsRef:(await Xe(i,l,u.token)).argsRef,projectRoot:t.replace(b(),"~"),stateSnapshot:f,platformTarget:r},Z(h)}catch(n){return{success:!1,error:`INVOKE_MATERIALIZATION_FAILED: ${n instanceof Error?n.message:String(n)}`,errorCode:"INVOKE_MATERIALIZATION_FAILED",exitCode:1}}let p=await te(i,h,u.token);if(!p.ok&&p.status===401){const n=p.errorBody?.fallback_action;if(n==="refresh_token"||n==="re_authenticate"){const s=await u.client.forceRefresh();s&&(p=await te(i,h,s))}}if(!p.ok&&p.status===426){const n=p.errorBody,s=n?.upgrade_command??"npm install -g @ornexus/neocortex@latest",g=n?.min_version??"unknown";return process.stderr.write(`
25
+ `),{success:!1,error:m.error??"Runner auto-bootstrap required but failed.",errorCode:m.errorCode,exitCode:m.exitCode??1};const f=_e(l,a);let h={args:l,projectRoot:t.replace(k(),"~"),stateSnapshot:f,platformTarget:r};const _=Z(h);if(e.inputSource&&e.inputSource!=="args"&&_>=H)try{h={argsRef:(await Xe(i,l,u.token)).argsRef,projectRoot:t.replace(k(),"~"),stateSnapshot:f,platformTarget:r},Z(h)}catch(n){return{success:!1,error:`INVOKE_MATERIALIZATION_FAILED: ${n instanceof Error?n.message:String(n)}`,errorCode:"INVOKE_MATERIALIZATION_FAILED",exitCode:1}}let p=await te(i,h,u.token);if(!p.ok&&p.status===401){const n=p.errorBody?.fallback_action;if(n==="refresh_token"||n==="re_authenticate"){const s=await u.client.forceRefresh();s&&(p=await te(i,h,s))}}if(!p.ok&&p.status===426){const n=p.errorBody,s=n?.upgrade_command??"npm install -g @ornexus/neocortex@latest",g=n?.min_version??"unknown";return process.stderr.write(`
26
26
  `),process.stderr.write(`==================================================
27
27
  `),process.stderr.write(` UPGRADE REQUIRED
28
28
  `),process.stderr.write(`==================================================
@@ -37,7 +37,7 @@ ${t}
37
37
  `),process.stderr.write(` After updating, re-run your command.
38
38
  `),process.stderr.write(`==================================================
39
39
 
40
- `),{success:!1,error:`UPGRADE_REQUIRED: Client version ${S} is below minimum ${g}. Run: ${s}`,exitCode:3}}if(!p.ok||!p.data){const n=p.status===401?2:(p.status===429||p.status>=500,1);try{const s=p.errorBody?.error_code??(p.status===429?"RATE_LIMITED":p.status>=500?"SERVER_ERROR":void 0);if(s){const g=M(),A=U(s,g);A&&process.stderr.write(F(A,g))}}catch{}return{success:!1,error:T(p.error??"Unknown error from server",O),exitCode:n}}if(!l&&p.data.metadata?.mode==="menu"&&c&&Ve(c,p.data.instructions,p.data.metadata).catch(()=>{}),p.data.metadata&&u.tierClient.updateQuotaFromResponse(p.data.metadata).catch(()=>{}),p.data.metadata?.mode==="error"&&p.data.metadata?.errorCode==="CLIENT_UPGRADE_REQUIRED")return process.stderr.write(`
40
+ `),{success:!1,error:`UPGRADE_REQUIRED: Client version ${S} is below minimum ${g}. Run: ${s}`,exitCode:3}}if(!p.ok||!p.data){const n=p.status===401?2:(p.status===429||p.status>=500,1);try{const s=p.errorBody?.error_code??(p.status===429?"RATE_LIMITED":p.status>=500?"SERVER_ERROR":void 0);if(s){const g=j(),A=F(s,g);A&&process.stderr.write(M(A,g))}}catch{}return{success:!1,error:T(p.error??"Unknown error from server",O),exitCode:n}}if(!l&&p.data.metadata?.mode==="menu"&&c&&Ve(c,p.data.instructions,p.data.metadata).catch(()=>{}),p.data.metadata&&u.tierClient.updateQuotaFromResponse(p.data.metadata).catch(()=>{}),p.data.metadata?.mode==="error"&&p.data.metadata?.errorCode==="CLIENT_UPGRADE_REQUIRED")return process.stderr.write(`
41
41
  `),process.stderr.write(`==================================================
42
42
  `),process.stderr.write(` YOLOOP CLIENT UPGRADE REQUIRED
43
43
  `),process.stderr.write(`==================================================
@@ -57,9 +57,9 @@ ${t}
57
57
  `),{success:!1,error:`CONTINUITY_PERSISTENCE_FAILED: ${T(s,O)}`,errorCode:"CONTINUITY_PERSISTENCE_FAILED",exitCode:1}}if(p.data.metadata?.stateMutated===!0)try{const{persistMigratedStateFromResponse:n}=await import("../yoloop/invoke-hooks.js");await n(p.data.metadata,t)}catch{}if(p.data.metadata?.tier_changed){const n=p.data.metadata.current_tier;try{await u.client.forceRefresh()?(await u.tierClient.invalidateTierCache(),process.stderr.write(`[Neocortex] Token atualizado automaticamente para tier ${n}
58
58
  `)):process.stderr.write(`[Neocortex] Seu tier foi atualizado para ${n}! Execute "neocortex activate" para obter um token atualizado.
59
59
  `)}catch{process.stderr.write(`[Neocortex] Seu tier foi atualizado para ${n}! Execute "neocortex activate" para obter um token atualizado.
60
- `)}}const v=x(p.data.instructions,p.data.metadata);return{success:!0,instructions:v.instructions,metadata:v.metadata,exitCode:0}}function re(e){const[t]=e.trim().split(/\s+/,1);return t?/^@?epic-[a-z0-9][a-z0-9._-]*$/i.test(t)?"epic":le(t):null}const ne="Provide exactly one invoke input source: --args <string>, --stdin, or --args-file <path>.";function oe(e){return new y("INVOKE_INPUT_VALUE_MISSING",`${e} requires a value. ${ne}`)}function st(e){try{if(!ce(e).isFile())throw new y("INVOKE_ARGS_FILE_NOT_FILE","--args-file must point to a readable UTF-8 text file.");return N(e,"utf8")}catch(t){throw t instanceof y?t:new y("INVOKE_ARGS_FILE_READ_FAILED","--args-file could not be read as UTF-8 text. Check the path and permissions.")}}function it(){try{if(process.stdin.isTTY)throw new y("INVOKE_STDIN_EMPTY","--stdin requires piped UTF-8 text, for example: neocortex-client invoke --stdin < synthetic.story.md");return N(0,"utf8")}catch(e){throw e instanceof y?e:new y("INVOKE_STDIN_READ_FAILED","--stdin could not be read as UTF-8 text. Pipe command text into stdin and retry.")}}function at(e,t={}){let r,o=!1,i,a,c="plain",l;for(let f=0;f<e.length;f++)switch(e[f]){case"--args":{const _=e[++f];if(_===void 0)throw oe("--args");r=_;break}case"--stdin":o=!0;break;case"--args-file":{const _=e[++f];if(_===void 0)throw oe("--args-file");i=_;break}case"--project-root":a=e[++f];break;case"--format":c=e[++f]??"plain";break;case"--server-url":l=e[++f];break}const u=[r!==void 0?"args":void 0,o?"stdin":void 0,i!==void 0?"args-file":void 0].filter(f=>f!==void 0);if(u.length===0)throw new y("INVOKE_INPUT_SOURCE_MISSING",ne);if(u.length>1)throw new y("INVOKE_INPUT_SOURCE_CONFLICT",`Choose only one invoke input source; received ${u.join(", ")}.`);const d=u[0];return{args:d==="args"?r:d==="stdin"?(t.readStdin??it)():(t.readArgsFile??st)(i),inputSource:d,projectRoot:a,format:c,serverUrl:l}}async function It(e){let t;try{t=at(e)}catch(o){if(o instanceof y)return process.stderr.write(JSON.stringify({error_code:o.code,message:o.message})+`
60
+ `)}}const L=P(p.data.instructions,p.data.metadata);return{success:!0,instructions:L.instructions,metadata:L.metadata,exitCode:0}}function re(e){const[t]=e.trim().split(/\s+/,1);return t?/^@?epic-[a-z0-9][a-z0-9._-]*$/i.test(t)?"epic":le(t):null}const ne="Provide exactly one invoke input source: --args <string>, --stdin, or --args-file <path>.";function oe(e){return new y("INVOKE_INPUT_VALUE_MISSING",`${e} requires a value. ${ne}`)}function st(e){try{if(!ce(e).isFile())throw new y("INVOKE_ARGS_FILE_NOT_FILE","--args-file must point to a readable UTF-8 text file.");return N(e,"utf8")}catch(t){throw t instanceof y?t:new y("INVOKE_ARGS_FILE_READ_FAILED","--args-file could not be read as UTF-8 text. Check the path and permissions.")}}function it(){try{if(process.stdin.isTTY)throw new y("INVOKE_STDIN_EMPTY","--stdin requires piped UTF-8 text, for example: neocortex-client invoke --stdin < synthetic.story.md");return N(0,"utf8")}catch(e){throw e instanceof y?e:new y("INVOKE_STDIN_READ_FAILED","--stdin could not be read as UTF-8 text. Pipe command text into stdin and retry.")}}function at(e,t={}){let r,o=!1,i,a,c="plain",l;for(let f=0;f<e.length;f++)switch(e[f]){case"--args":{const _=e[++f];if(_===void 0)throw oe("--args");r=_;break}case"--stdin":o=!0;break;case"--args-file":{const _=e[++f];if(_===void 0)throw oe("--args-file");i=_;break}case"--project-root":a=e[++f];break;case"--format":c=e[++f]??"plain";break;case"--server-url":l=e[++f];break}const u=[r!==void 0?"args":void 0,o?"stdin":void 0,i!==void 0?"args-file":void 0].filter(f=>f!==void 0);if(u.length===0)throw new y("INVOKE_INPUT_SOURCE_MISSING",ne);if(u.length>1)throw new y("INVOKE_INPUT_SOURCE_CONFLICT",`Choose only one invoke input source; received ${u.join(", ")}.`);const d=u[0];return{args:d==="args"?r:d==="stdin"?(t.readStdin??it)():(t.readArgsFile??st)(i),inputSource:d,projectRoot:a,format:c,serverUrl:l}}async function It(e){let t;try{t=at(e)}catch(o){if(o instanceof y)return process.stderr.write(JSON.stringify({error_code:o.code,message:o.message})+`
61
61
  `),1;throw o}const r=await ot({args:t.args,inputSource:t.inputSource,projectRoot:t.projectRoot,format:t.format,serverUrl:t.serverUrl});if(!r.success)return process.stderr.write(JSON.stringify({error_code:r.errorCode??(r.exitCode===2?"NOT_CONFIGURED":"INVOKE_ERROR"),message:T(r.error??"",O)})+`
62
- `),r.exitCode;if(t.format==="json"){const o=x(r.instructions,r.metadata);process.stdout.write(JSON.stringify({instructions:o.instructions,metadata:o.metadata})+`
63
- `)}else{const o=x(r.instructions,r.metadata);process.stdout.write(o.instructions+`
62
+ `),r.exitCode;if(t.format==="json"){const o=P(r.instructions,r.metadata);process.stdout.write(JSON.stringify({instructions:o.instructions,metadata:o.metadata})+`
63
+ `)}else{const o=P(r.instructions,r.metadata);process.stdout.write(o.instructions+`
64
64
  `),o.metadata&&process.stderr.write(JSON.stringify(o.metadata)+`
65
- `)}return 0}export{V as INVOKE_PAYLOAD_WARNING_THRESHOLD_BYTES,y as InvokeCliInputError,At as __resetSchemaDriftWarnedForTests,ve as collectInitProjectMemoryBootstrapSnapshot,Ke as collectStateSnapshot,Qe as computeInvokeRequestBodySizeBytes,Nt as createFullStateSnapshotScope,Fe as detectStateSchemaDrift,re as extractPreFlightTrigger,ot as invoke,It as invokeCliHandler,De as isInitTrigger,Z as maybeEmitInvokePayloadSizeWarning,tt as maybeRunInvokeRunnerAutoBootstrap,at as parseInvokeCliOptions,$e as resolveInvokeProjectRoot,x as sanitizeInvokeCliOutput};
65
+ `)}return 0}export{H as INVOKE_PAYLOAD_WARNING_THRESHOLD_BYTES,y as InvokeCliInputError,At as __resetSchemaDriftWarnedForTests,ve as collectInitProjectMemoryBootstrapSnapshot,Ke as collectStateSnapshot,Qe as computeInvokeRequestBodySizeBytes,Nt as createFullStateSnapshotScope,Fe as detectStateSchemaDrift,re as extractPreFlightTrigger,ot as invoke,It as invokeCliHandler,De as isInitTrigger,Z as maybeEmitInvokePayloadSizeWarning,tt as maybeRunInvokeRunnerAutoBootstrap,at as parseInvokeCliOptions,$e as resolveInvokeProjectRoot,P as sanitizeInvokeCliOutput};
@@ -9,7 +9,7 @@ export declare const CONTINUITY_SQLITE_FILENAME: "continuity.sqlite";
9
9
  export declare const CONTINUITY_SQLITE_SCHEMA_VERSION: 1;
10
10
  export declare const DEFAULT_CONTINUITY_SQLITE_BUSY_TIMEOUT_MS = 5000;
11
11
  export declare const SQLITE_ADAPTER_INSTALL_GUIDANCE = "Install the optional Enterprise continuity SQLite adapter with `npm install --workspace packages/client better-sqlite3 --include=optional` or reinstall Neocortex with optional dependencies enabled.";
12
- export type ContinuitySqliteStoreErrorCode = 'sqlite-adapter-unavailable' | 'sqlite-integrity-failed' | 'sqlite-migration-failed' | 'sqlite-migration-conflict' | 'sqlite-foreign-key-failed' | 'sqlite-public-safety-rejected' | 'sqlite-mutation-blocked';
12
+ export type ContinuitySqliteStoreErrorCode = 'sqlite-adapter-unavailable' | 'sqlite-integrity-failed' | 'sqlite-migration-failed' | 'sqlite-migration-conflict' | 'sqlite-mutation-failed' | 'sqlite-foreign-key-failed' | 'sqlite-public-safety-rejected' | 'sqlite-mutation-blocked';
13
13
  export declare class ContinuitySqliteStoreError extends Error {
14
14
  readonly code: ContinuitySqliteStoreErrorCode;
15
15
  readonly reasonCode: ContinuitySqliteStoreErrorCode;
@@ -31,13 +31,16 @@ export interface ContinuitySqliteStatement {
31
31
  get(...params: readonly unknown[]): unknown;
32
32
  all(...params: readonly unknown[]): readonly unknown[];
33
33
  }
34
+ export type ContinuitySqliteTransaction<T extends (...args: never[]) => unknown> = T & {
35
+ readonly immediate?: T;
36
+ };
34
37
  export interface ContinuitySqliteDatabase {
35
38
  pragma(source: string, options?: {
36
39
  readonly simple?: boolean;
37
40
  }): unknown;
38
41
  exec(source: string): void;
39
42
  prepare(source: string): ContinuitySqliteStatement;
40
- transaction<T extends (...args: never[]) => unknown>(fn: T): T;
43
+ transaction<T extends (...args: never[]) => unknown>(fn: T): ContinuitySqliteTransaction<T>;
41
44
  close(): void;
42
45
  }
43
46
  export interface ContinuitySqliteAdapter {
@@ -1,52 +1,52 @@
1
- import{createHash as T}from"node:crypto";import{chmodSync as b,existsSync as C,mkdirSync as N}from"node:fs";import{join as y}from"node:path";import{INITIAL_CONTINUITY_SQLITE_MIGRATION as O}from"./migrations/001-initial-schema.js";const f=".neocortex/continuity",A="continuity.sqlite",K=1,j=5e3,I="Install the optional Enterprise continuity SQLite adapter with `npm install --workspace packages/client better-sqlite3 --include=optional` or reinstall Neocortex with optional dependencies enabled.";class i extends Error{code;reasonCode;guidance;mutationBlocked;cause;constructor(e,t,a={}){super(t),this.name="ContinuitySqliteStoreError",this.code=e,this.reasonCode=e,this.guidance=a.guidance,this.cause=a.cause,this.mutationBlocked=a.mutationBlocked??e==="sqlite-integrity-failed"}}const R=[O],L=Object.freeze(["continuity_migrations","jobs","job_leases","job_events","job_receipts","goal_campaigns","goal_ledger_items","goal_verifiers","goal_review_gates","loop_jobs","artifacts","state_snapshots","runner_config","outbox"]),w=/(raw[_-]?logs?|prompt(?:[_-]?(?:body|text))?|private[_-]?urls?|secret|token|password|protected(?:[_-]?(?:field|body|internals))?|workflow(?:[_-]?body)?|step(?:[_-]?body)?|customer(?:[_-]?(?:pii|data))?|authorization|api[_-]?key|license[_-]?key)/i,S=/(https?:\/\/\S+|ghp_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]+|-----BEGIN [A-Z ]*PRIVATE KEY-----|authorization\s*:|password\s*=|token\s*=|api[_-]?key\s*=|license[_-]?key\s*=|raw[_-]?log|transcript|stack trace|stderr:|stdout:|system prompt|workflow body|step body|PROTECTED_|PRIVATE_INTERNALS|CUSTOMER_PII|VENDOR_CORPUS|P180[_-]?SYNTHETIC[_-]?CONTINUITY)/i,k=/(corrupt|malformed|not a database|file is not a database|database disk image is malformed)/i,x=/(foreign key constraint failed|SQLITE_CONSTRAINT_FOREIGNKEY)/i;function M(r){return new Function("specifier","return import(specifier)")(r)}function v(r){return`sha256:${T("sha256").update(r).digest("hex")}`}function _(r){return typeof r=="object"&&r!==null&&!Array.isArray(r)}function U(r){return r instanceof Error?r.message:String(r)}function q(r){return _(r)&&typeof r.code=="string"?r.code:void 0}function n(r,e){if(r instanceof i)return r;const t=U(r),a=q(r);return a==="SQLITE_CORRUPT"||a==="SQLITE_NOTADB"||k.test(t)?new i("sqlite-integrity-failed","Continuity SQLite integrity check failed; durable mutation is blocked until the store is repaired or rebuilt.",{cause:r,mutationBlocked:!0}):a==="SQLITE_CONSTRAINT_FOREIGNKEY"||x.test(t)?new i("sqlite-foreign-key-failed","Continuity SQLite foreign-key validation failed; mutation was rejected.",{cause:r}):new i(e,t,{cause:r})}function g(r,e){if(typeof r=="string"){if(S.test(r))throw new i("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsafe value at ${e}.`);return}if(!(r===null||typeof r=="number"||typeof r=="boolean")){if(Array.isArray(r)){r.forEach((t,a)=>g(t,`${e}[${a}]`));return}if(_(r)){for(const[t,a]of Object.entries(r)){if(w.test(t))throw new i("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsafe key at ${e}.${t}.`);g(a,`${e}.${t}`)}return}throw new i("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsupported value at ${e}.`)}}function c(r,e){if(r!==void 0&&S.test(r))throw new i("sqlite-public-safety-rejected",`Continuity SQLite text rejected unsafe value at ${e}.`)}function l(r){return r?(g(r,"metadata"),JSON.stringify(r)):null}function p(r){if(Array.isArray(r)){const e=r[0];return _(e)?Object.values(e)[0]:e}return _(r)?Object.values(r)[0]:r}function D(r){return L.includes(r)}function F(r){return Array.from(new Set(r))}function W(r){const e=_(r)&&"default"in r?r.default:r;if(typeof e!="function")throw new i("sqlite-adapter-unavailable","Optional better-sqlite3 adapter did not export a database constructor.",{guidance:I});const t=e;return{adapterName:"better-sqlite3",open(a,s){return new t(a,s)}}}async function P(r=M){try{const e=await r("better-sqlite3");return{ok:!0,adapter:W(e)}}catch(e){return e instanceof i?{ok:!1,error:e}:{ok:!1,error:new i("sqlite-adapter-unavailable","Optional Enterprise continuity SQLite adapter better-sqlite3 is unavailable.",{cause:e,guidance:I})}}}function H(r){return y(r,f,A)}function B(r){const e=y(r,f);N(e,{recursive:!0,mode:448});try{b(e,448)}catch{}return e}async function z(r){const e=r.adapter??await J(r.adapterLoader);B(r.projectRoot);const t=H(r.projectRoot);let a;try{a=e.open(t)}catch(o){throw n(o,"sqlite-integrity-failed")}const s=new Q({db:a,filePath:t,adapterName:e.adapterName,busyTimeoutMs:r.busyTimeoutMs??j,integrityCheck:r.integrityCheck??!0,now:r.now??(()=>new Date().toISOString())});try{if(s.initialize(),C(t))try{b(t,384)}catch{}return s}catch(o){try{a.close()}catch{}throw o}}async function J(r){const e=r?await r():await P();if(!e.ok)throw e.error;return e.adapter}class Q{filePath;adapterName;db;busyTimeoutMs;integrityCheck;now;mutationBlocked=!1;constructor(e){this.db=e.db,this.filePath=e.filePath,this.adapterName=e.adapterName,this.busyTimeoutMs=e.busyTimeoutMs,this.integrityCheck=e.integrityCheck,this.now=e.now}initialize(){try{this.configureConnection(),this.integrityCheck&&this.runIntegrityCheck(),this.ensureMigrationTable(),this.applyMigrations(),this.integrityCheck&&this.runIntegrityCheck()}catch(e){throw n(e,"sqlite-migration-failed")}}close(){this.db.close()}pragmaValue(e){return p(this.db.pragma(e,{simple:!0}))}runIntegrityCheck(){try{if(String(p(this.db.pragma("integrity_check",{simple:!0}))??"").toLowerCase()!=="ok")throw this.mutationBlocked=!0,new i("sqlite-integrity-failed","Continuity SQLite integrity check failed; durable mutation is blocked until the store is repaired or rebuilt.",{mutationBlocked:!0})}catch(e){throw this.mutationBlocked=!0,n(e,"sqlite-integrity-failed")}}getSchemaVersion(){const e=this.db.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM continuity_migrations").get();return _(e)&&typeof e.version=="number"?e.version:0}countRows(e){if(!D(e))throw new i("sqlite-public-safety-rejected","Unknown continuity table name.");const t=this.db.prepare(`SELECT COUNT(*) AS count FROM ${e}`).get();return _(t)&&typeof t.count=="number"?t.count:0}recordJob(e){this.assertCanMutate(),c(e.summary,"jobs.summary");const t=l(e.metadata);try{const a=this.db.prepare(`
1
+ import{createHash as T}from"node:crypto";import{chmodSync as y,existsSync as C,mkdirSync as N}from"node:fs";import{join as g}from"node:path";import{INITIAL_CONTINUITY_SQLITE_MIGRATION as O}from"./migrations/001-initial-schema.js";const f=".neocortex/continuity",A="continuity.sqlite",K=1,j=5e3,I="Install the optional Enterprise continuity SQLite adapter with `npm install --workspace packages/client better-sqlite3 --include=optional` or reinstall Neocortex with optional dependencies enabled.";class i extends Error{code;reasonCode;guidance;mutationBlocked;cause;constructor(e,t,a={}){super(t),this.name="ContinuitySqliteStoreError",this.code=e,this.reasonCode=e,this.guidance=a.guidance,this.cause=a.cause,this.mutationBlocked=a.mutationBlocked??e==="sqlite-integrity-failed"}}const R=[O],L=Object.freeze(["continuity_migrations","jobs","job_leases","job_events","job_receipts","goal_campaigns","goal_ledger_items","goal_verifiers","goal_review_gates","loop_jobs","artifacts","state_snapshots","runner_config","outbox"]),w=/(raw[_-]?logs?|prompt(?:[_-]?(?:body|text))?|private[_-]?urls?|secret|token|password|protected(?:[_-]?(?:field|body|internals))?|workflow(?:[_-]?body)?|step(?:[_-]?body)?|customer(?:[_-]?(?:pii|data))?|authorization|api[_-]?key|license[_-]?key)/i,S=/(https?:\/\/\S+|ghp_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]+|-----BEGIN [A-Z ]*PRIVATE KEY-----|authorization\s*:|password\s*=|token\s*=|api[_-]?key\s*=|license[_-]?key\s*=|raw[_-]?log|transcript|stack trace|stderr:|stdout:|system prompt|workflow body|step body|PROTECTED_|PRIVATE_INTERNALS|CUSTOMER_PII|VENDOR_CORPUS|P180[_-]?SYNTHETIC[_-]?CONTINUITY)/i,k=/(corrupt|malformed|not a database|file is not a database|database disk image is malformed)/i,x=/(foreign key constraint failed|SQLITE_CONSTRAINT_FOREIGNKEY)/i;function M(r){return new Function("specifier","return import(specifier)")(r)}function v(r){return`sha256:${T("sha256").update(r).digest("hex")}`}function _(r){return typeof r=="object"&&r!==null&&!Array.isArray(r)}function U(r){return r instanceof Error?r.message:String(r)}function q(r){return _(r)&&typeof r.code=="string"?r.code:void 0}function n(r,e){if(r instanceof i)return r;const t=U(r),a=q(r);return a==="SQLITE_CORRUPT"||a==="SQLITE_NOTADB"||k.test(t)?new i("sqlite-integrity-failed","Continuity SQLite integrity check failed; durable mutation is blocked until the store is repaired or rebuilt.",{cause:r,mutationBlocked:!0}):a==="SQLITE_CONSTRAINT_FOREIGNKEY"||x.test(t)?new i("sqlite-foreign-key-failed","Continuity SQLite foreign-key validation failed; mutation was rejected.",{cause:r}):new i(e,t,{cause:r})}function b(r,e){if(typeof r=="string"){if(S.test(r))throw new i("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsafe value at ${e}.`);return}if(!(r===null||typeof r=="number"||typeof r=="boolean")){if(Array.isArray(r)){r.forEach((t,a)=>b(t,`${e}[${a}]`));return}if(_(r)){for(const[t,a]of Object.entries(r)){if(w.test(t))throw new i("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsafe key at ${e}.${t}.`);b(a,`${e}.${t}`)}return}throw new i("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsupported value at ${e}.`)}}function c(r,e){if(r!==void 0&&S.test(r))throw new i("sqlite-public-safety-rejected",`Continuity SQLite text rejected unsafe value at ${e}.`)}function l(r){return r?(b(r,"metadata"),JSON.stringify(r)):null}function p(r){if(Array.isArray(r)){const e=r[0];return _(e)?Object.values(e)[0]:e}return _(r)?Object.values(r)[0]:r}function D(r){return L.includes(r)}function F(r){return Array.from(new Set(r))}function W(r){const e=_(r)&&"default"in r?r.default:r;if(typeof e!="function")throw new i("sqlite-adapter-unavailable","Optional better-sqlite3 adapter did not export a database constructor.",{guidance:I});const t=e;return{adapterName:"better-sqlite3",open(a,s){return new t(a,s)}}}async function P(r=M){try{const e=await r("better-sqlite3");return{ok:!0,adapter:W(e)}}catch(e){return e instanceof i?{ok:!1,error:e}:{ok:!1,error:new i("sqlite-adapter-unavailable","Optional Enterprise continuity SQLite adapter better-sqlite3 is unavailable.",{cause:e,guidance:I})}}}function H(r){return g(r,f,A)}function B(r){const e=g(r,f);N(e,{recursive:!0,mode:448});try{y(e,448)}catch{}return e}async function z(r){const e=r.adapter??await J(r.adapterLoader);B(r.projectRoot);const t=H(r.projectRoot);let a;try{a=e.open(t)}catch(o){throw n(o,"sqlite-integrity-failed")}const s=new Q({db:a,filePath:t,adapterName:e.adapterName,busyTimeoutMs:r.busyTimeoutMs??j,integrityCheck:r.integrityCheck??!0,now:r.now??(()=>new Date().toISOString())});try{if(s.initialize(),C(t))try{y(t,384)}catch{}return s}catch(o){try{a.close()}catch{}throw o}}async function J(r){const e=r?await r():await P();if(!e.ok)throw e.error;return e.adapter}class Q{filePath;adapterName;db;busyTimeoutMs;integrityCheck;now;mutationBlocked=!1;constructor(e){this.db=e.db,this.filePath=e.filePath,this.adapterName=e.adapterName,this.busyTimeoutMs=e.busyTimeoutMs,this.integrityCheck=e.integrityCheck,this.now=e.now}initialize(){try{this.configureConnection(),this.integrityCheck&&this.runIntegrityCheck(),this.ensureMigrationTable(),this.applyMigrations(),this.integrityCheck&&this.runIntegrityCheck()}catch(e){throw n(e,"sqlite-migration-failed")}}close(){this.db.close()}pragmaValue(e){return p(this.db.pragma(e,{simple:!0}))}runIntegrityCheck(){try{if(String(p(this.db.pragma("integrity_check",{simple:!0}))??"").toLowerCase()!=="ok")throw this.mutationBlocked=!0,new i("sqlite-integrity-failed","Continuity SQLite integrity check failed; durable mutation is blocked until the store is repaired or rebuilt.",{mutationBlocked:!0})}catch(e){throw this.mutationBlocked=!0,n(e,"sqlite-integrity-failed")}}getSchemaVersion(){const e=this.db.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM continuity_migrations").get();return _(e)&&typeof e.version=="number"?e.version:0}countRows(e){if(!D(e))throw new i("sqlite-public-safety-rejected","Unknown continuity table name.");const t=this.db.prepare(`SELECT COUNT(*) AS count FROM ${e}`).get();return _(t)&&typeof t.count=="number"?t.count:0}recordJob(e){this.assertCanMutate(),c(e.summary,"jobs.summary");const t=l(e.metadata);try{const a=this.db.prepare(`
2
2
  INSERT OR IGNORE INTO jobs (
3
3
  job_id, kind, status, summary, reason_code, created_at, updated_at,
4
4
  next_run_at, goal_id, loop_id, campaign_id, operation_id,
5
5
  idempotency_key, metadata_json
6
6
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
7
- `).run(e.jobId,e.kind,e.status,e.summary??null,e.reasonCode??null,e.createdAt,e.updatedAt,e.nextRunAt??null,e.goalId??null,e.loopId??null,e.campaignId??null,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-migration-failed")}}appendEvent(e){this.assertCanMutate(),c(e.summary,"job_events.summary");const t=l(e.metadata);try{const a=this.db.prepare(`
7
+ `).run(e.jobId,e.kind,e.status,e.summary??null,e.reasonCode??null,e.createdAt,e.updatedAt,e.nextRunAt??null,e.goalId??null,e.loopId??null,e.campaignId??null,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-mutation-failed")}}appendEvent(e){this.assertCanMutate(),c(e.summary,"job_events.summary");const t=l(e.metadata);try{const a=this.db.prepare(`
8
8
  INSERT OR IGNORE INTO job_events (
9
9
  event_id, job_id, operation_id, idempotency_key, event_sequence,
10
10
  type, summary, reason_code, created_at, metadata_json
11
11
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
12
- `).run(e.eventId,e.jobId,e.operationId,e.idempotencyKey??null,e.sequence??null,e.type,e.summary,e.reasonCode??null,e.createdAt,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-migration-failed")}}appendReceipt(e){this.assertCanMutate();const t=l(e.metadata);try{const a=this.db.prepare(`
12
+ `).run(e.eventId,e.jobId,e.operationId,e.idempotencyKey??null,e.sequence??null,e.type,e.summary,e.reasonCode??null,e.createdAt,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-mutation-failed")}}appendReceipt(e){this.assertCanMutate();const t=l(e.metadata);try{const a=this.db.prepare(`
13
13
  INSERT OR IGNORE INTO job_receipts (
14
14
  receipt_id, job_id, operation_id, idempotency_key, status, reason_code,
15
15
  applied_operation_ids_json, ignored_operation_ids_json, created_at, metadata_json
16
16
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
17
- `).run(e.receiptId,e.jobId,e.operationId??null,e.idempotencyKey??null,e.status,e.reasonCode??null,e.appliedOperationIds?JSON.stringify(e.appliedOperationIds):null,e.ignoredOperationIds?JSON.stringify(e.ignoredOperationIds):null,e.createdAt,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-migration-failed")}}updateJobStatus(e){this.assertCanMutate();try{const t=this.db.prepare(`
17
+ `).run(e.receiptId,e.jobId,e.operationId??null,e.idempotencyKey??null,e.status,e.reasonCode??null,e.appliedOperationIds?JSON.stringify(e.appliedOperationIds):null,e.ignoredOperationIds?JSON.stringify(e.ignoredOperationIds):null,e.createdAt,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-mutation-failed")}}updateJobStatus(e){this.assertCanMutate();try{const t=this.db.prepare(`
18
18
  UPDATE jobs
19
19
  SET status = ?,
20
20
  reason_code = COALESCE(?, reason_code),
21
21
  updated_at = ?,
22
22
  next_run_at = COALESCE(?, next_run_at)
23
23
  WHERE job_id = ?
24
- `).run(e.status,e.reasonCode??null,e.updatedAt,e.nextRunAt??null,e.jobId);if(t.changes===0)throw new i("sqlite-foreign-key-failed",`Continuity SQLite job ${e.jobId} was not found for status update.`);return this.toWriteResult(t)}catch(t){throw n(t,"sqlite-migration-failed")}}scheduleNextTick(e){return this.updateJobStatus({jobId:e.jobId,status:"active",updatedAt:e.updatedAt,reasonCode:e.reasonCode,nextRunAt:e.scheduledAt})}acquireLease(e){this.assertCanMutate();const t=l(e.metadata);try{const a=this.db.prepare(`
24
+ `).run(e.status,e.reasonCode??null,e.updatedAt,e.nextRunAt??null,e.jobId);if(t.changes===0)throw new i("sqlite-foreign-key-failed",`Continuity SQLite job ${e.jobId} was not found for status update.`);return this.toWriteResult(t)}catch(t){throw n(t,"sqlite-mutation-failed")}}scheduleNextTick(e){return this.updateJobStatus({jobId:e.jobId,status:"active",updatedAt:e.updatedAt,reasonCode:e.reasonCode,nextRunAt:e.scheduledAt})}acquireLease(e){this.assertCanMutate();const t=l(e.metadata);try{const a=this.db.prepare(`
25
25
  INSERT OR IGNORE INTO job_leases (
26
26
  lease_id, job_id, runner_id, status, acquired_at, expires_at,
27
27
  operation_id, idempotency_key, metadata_json
28
28
  ) VALUES (?, ?, ?, 'acquired', ?, ?, ?, ?, ?)
29
- `).run(e.leaseId,e.jobId,e.runnerId,e.acquiredAt,e.expiresAt,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-migration-failed")}}releaseLease(e){this.assertCanMutate();try{const t=this.db.prepare(`
29
+ `).run(e.leaseId,e.jobId,e.runnerId,e.acquiredAt,e.expiresAt,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-mutation-failed")}}releaseLease(e){this.assertCanMutate();try{const t=this.db.prepare(`
30
30
  UPDATE job_leases
31
31
  SET status = 'released', released_at = ?
32
32
  WHERE lease_id = ? AND released_at IS NULL
33
- `).run(e.releasedAt,e.leaseId);if(t.changes===0)throw new i("sqlite-foreign-key-failed",`Continuity SQLite lease ${e.leaseId} was not found for release.`);return this.toWriteResult(t)}catch(t){throw n(t,"sqlite-migration-failed")}}recordStateSnapshot(e){this.assertCanMutate(),c(e.summary,"state_snapshots.summary"),c(e.relativePath,"state_snapshots.relative_path");const t=l(e.metadata);try{const a=this.db.prepare(`
33
+ `).run(e.releasedAt,e.leaseId);if(t.changes===0)throw new i("sqlite-foreign-key-failed",`Continuity SQLite lease ${e.leaseId} was not found for release.`);return this.toWriteResult(t)}catch(t){throw n(t,"sqlite-mutation-failed")}}recordStateSnapshot(e){this.assertCanMutate(),c(e.summary,"state_snapshots.summary"),c(e.relativePath,"state_snapshots.relative_path");const t=l(e.metadata);try{const a=this.db.prepare(`
34
34
  INSERT OR IGNORE INTO state_snapshots (
35
35
  snapshot_id, job_id, kind, relative_path, sha256, summary, captured_at,
36
36
  operation_id, idempotency_key, metadata_json
37
37
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
38
- `).run(e.snapshotId,e.jobId??null,e.kind,e.relativePath??null,e.sha256??null,e.summary??null,e.capturedAt,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-migration-failed")}}recordArtifact(e){this.assertCanMutate(),c(e.kind,"artifacts.kind"),c(e.relativePath,"artifacts.relative_path"),c(e.summary,"artifacts.summary");const t=l(e.metadata);try{const a=this.db.prepare(`
38
+ `).run(e.snapshotId,e.jobId??null,e.kind,e.relativePath??null,e.sha256??null,e.summary??null,e.capturedAt,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-mutation-failed")}}recordArtifact(e){this.assertCanMutate(),c(e.kind,"artifacts.kind"),c(e.relativePath,"artifacts.relative_path"),c(e.summary,"artifacts.summary");const t=l(e.metadata);try{const a=this.db.prepare(`
39
39
  INSERT OR IGNORE INTO artifacts (
40
40
  artifact_id, job_id, kind, relative_path, sha256, summary,
41
41
  operation_id, idempotency_key, created_at, metadata_json
42
42
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
43
- `).run(e.artifactId,e.jobId??null,e.kind,e.relativePath,e.sha256??null,e.summary??null,e.operationId??null,e.idempotencyKey??null,e.createdAt,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-migration-failed")}}enqueueOutbox(e){this.assertCanMutate();const t=l(e.payload);try{const a=this.db.prepare(`
43
+ `).run(e.artifactId,e.jobId??null,e.kind,e.relativePath,e.sha256??null,e.summary??null,e.operationId??null,e.idempotencyKey??null,e.createdAt,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-mutation-failed")}}enqueueOutbox(e){this.assertCanMutate();const t=l(e.payload);try{const a=this.db.prepare(`
44
44
  INSERT OR IGNORE INTO outbox (
45
45
  outbox_id, job_id, operation_id, idempotency_key, type, status,
46
46
  payload_json, retry_count, next_attempt_at, last_error_code,
47
47
  created_at, updated_at
48
48
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
49
- `).run(e.outboxId,e.jobId??null,e.operationId,e.idempotencyKey??null,e.type,e.status??"pending",t??"{}",e.retryCount??0,e.nextAttemptAt??null,e.lastErrorCode??null,e.createdAt,e.updatedAt);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-migration-failed")}}retryOutboxEntries(e){this.assertCanMutate();const t=Math.max(1,Math.min(100,Math.floor(e.limit))),a=F(e.statuses?.length?e.statuses:["failed","dead_letter"]),s=e.reasonCode??"backoff-scheduled";c(s,"outbox.last_error_code"),c(e.nextAttemptAt,"outbox.next_attempt_at");try{return this.runInTransaction(()=>{const o=a.map(()=>"?").join(", "),d=this.db.prepare(`
49
+ `).run(e.outboxId,e.jobId??null,e.operationId,e.idempotencyKey??null,e.type,e.status??"pending",t??"{}",e.retryCount??0,e.nextAttemptAt??null,e.lastErrorCode??null,e.createdAt,e.updatedAt);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-mutation-failed")}}retryOutboxEntries(e){this.assertCanMutate();const t=Math.max(1,Math.min(100,Math.floor(e.limit))),a=F(e.statuses?.length?e.statuses:["failed","dead_letter"]),s=e.reasonCode??"backoff-scheduled";c(s,"outbox.last_error_code"),c(e.nextAttemptAt,"outbox.next_attempt_at");try{return this.runInTransaction(()=>{const o=a.map(()=>"?").join(", "),d=this.db.prepare(`
50
50
  SELECT outbox_id
51
51
  FROM outbox
52
52
  WHERE status IN (${o})
@@ -60,7 +60,7 @@ import{createHash as T}from"node:crypto";import{chmodSync as b,existsSync as C,m
60
60
  last_error_code = ?,
61
61
  updated_at = ?
62
62
  WHERE outbox_id IN (${h})
63
- `).run(e.nextAttemptAt??e.nowIso,s,e.nowIso,...d);return{retriedOutboxIds:d,changes:E.changes,reasonCode:s,publicSafe:!0}})}catch(o){throw n(o,"sqlite-migration-failed")}}upsertGoalCampaign(e){this.assertCanMutate(),c(e.title,"goal_campaigns.title"),c(e.publicSummary,"goal_campaigns.public_summary");const t=l(e.metadata);try{const a=this.db.prepare(`
63
+ `).run(e.nextAttemptAt??e.nowIso,s,e.nowIso,...d);return{retriedOutboxIds:d,changes:E.changes,reasonCode:s,publicSafe:!0}})}catch(o){throw n(o,"sqlite-mutation-failed")}}upsertGoalCampaign(e){this.assertCanMutate(),c(e.title,"goal_campaigns.title"),c(e.publicSummary,"goal_campaigns.public_summary");const t=l(e.metadata);try{const a=this.db.prepare(`
64
64
  INSERT INTO goal_campaigns (
65
65
  campaign_id, job_id, status, title, public_summary, reason_code,
66
66
  created_at, updated_at, operation_id, idempotency_key, metadata_json
@@ -74,7 +74,7 @@ import{createHash as T}from"node:crypto";import{chmodSync as b,existsSync as C,m
74
74
  operation_id = excluded.operation_id,
75
75
  idempotency_key = excluded.idempotency_key,
76
76
  metadata_json = excluded.metadata_json
77
- `).run(e.campaignId,e.jobId,e.status,e.title??null,e.publicSummary??null,e.reasonCode??null,e.createdAt,e.updatedAt,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-migration-failed")}}upsertGoalLedgerItem(e){this.assertCanMutate(),c(e.summary,"goal_ledger_items.summary");const t=l(e.metadata);try{this.ensureGoalCampaign(e.campaignId,e.jobId,e.createdAt,e.updatedAt);const a=this.db.prepare(`
77
+ `).run(e.campaignId,e.jobId,e.status,e.title??null,e.publicSummary??null,e.reasonCode??null,e.createdAt,e.updatedAt,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-mutation-failed")}}upsertGoalLedgerItem(e){this.assertCanMutate(),c(e.summary,"goal_ledger_items.summary");const t=l(e.metadata);try{this.ensureGoalCampaign(e.campaignId,e.jobId,e.createdAt,e.updatedAt);const a=this.db.prepare(`
78
78
  INSERT INTO goal_ledger_items (
79
79
  item_id, campaign_id, operation_id, idempotency_key, item_type, status,
80
80
  summary, reason_code, created_at, updated_at, metadata_json
@@ -85,7 +85,7 @@ import{createHash as T}from"node:crypto";import{chmodSync as b,existsSync as C,m
85
85
  reason_code = excluded.reason_code,
86
86
  updated_at = excluded.updated_at,
87
87
  metadata_json = excluded.metadata_json
88
- `).run(e.itemId,e.campaignId,e.operationId??null,e.idempotencyKey??null,e.itemType,e.status,e.summary,e.reasonCode??null,e.createdAt,e.updatedAt,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-migration-failed")}}upsertGoalVerifier(e){this.assertCanMutate(),c(e.summary,"goal_verifiers.summary");const t=l(e.metadata);try{const a=e.lastCheckedAt??this.now();this.ensureGoalCampaign(e.campaignId,e.jobId,a,a);const s=this.db.prepare(`
88
+ `).run(e.itemId,e.campaignId,e.operationId??null,e.idempotencyKey??null,e.itemType,e.status,e.summary,e.reasonCode??null,e.createdAt,e.updatedAt,t);return this.toWriteResult(a)}catch(a){throw n(a,"sqlite-mutation-failed")}}upsertGoalVerifier(e){this.assertCanMutate(),c(e.summary,"goal_verifiers.summary");const t=l(e.metadata);try{const a=e.lastCheckedAt??this.now();this.ensureGoalCampaign(e.campaignId,e.jobId,a,a);const s=this.db.prepare(`
89
89
  INSERT INTO goal_verifiers (
90
90
  verifier_id, campaign_id, kind, status, summary, reason_code,
91
91
  last_checked_at, operation_id, idempotency_key, metadata_json
@@ -96,7 +96,7 @@ import{createHash as T}from"node:crypto";import{chmodSync as b,existsSync as C,m
96
96
  reason_code = excluded.reason_code,
97
97
  last_checked_at = excluded.last_checked_at,
98
98
  metadata_json = excluded.metadata_json
99
- `).run(e.verifierId,e.campaignId,e.kind,e.status,e.summary??null,e.reasonCode??null,e.lastCheckedAt??null,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(s)}catch(a){throw n(a,"sqlite-migration-failed")}}upsertGoalReviewGate(e){this.assertCanMutate(),c(e.summary,"goal_review_gates.summary");const t=l(e.metadata);try{const a=this.now();this.ensureGoalCampaign(e.campaignId,e.jobId,a,a);const s=this.db.prepare(`
99
+ `).run(e.verifierId,e.campaignId,e.kind,e.status,e.summary??null,e.reasonCode??null,e.lastCheckedAt??null,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(s)}catch(a){throw n(a,"sqlite-mutation-failed")}}upsertGoalReviewGate(e){this.assertCanMutate(),c(e.summary,"goal_review_gates.summary");const t=l(e.metadata);try{const a=this.now();this.ensureGoalCampaign(e.campaignId,e.jobId,a,a);const s=this.db.prepare(`
100
100
  INSERT INTO goal_review_gates (
101
101
  gate_id, campaign_id, status, summary, required, reason_code,
102
102
  operation_id, idempotency_key, metadata_json
@@ -107,7 +107,7 @@ import{createHash as T}from"node:crypto";import{chmodSync as b,existsSync as C,m
107
107
  required = excluded.required,
108
108
  reason_code = excluded.reason_code,
109
109
  metadata_json = excluded.metadata_json
110
- `).run(e.gateId,e.campaignId,e.status,e.summary??null,e.required?1:0,e.reasonCode??null,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(s)}catch(a){throw n(a,"sqlite-migration-failed")}}recordOperationAudit(e){return this.appendReceipt(e)}hasOperationRef(e,t){this.assertCanMutate();const a=["jobs","job_leases","job_events","job_receipts","goal_campaigns","goal_ledger_items","goal_verifiers","goal_review_gates","loop_jobs","artifacts","state_snapshots","runner_config","outbox"],s=a.map(d=>`SELECT 1 AS found FROM ${d} WHERE operation_id = ?${t?" OR idempotency_key = ?":""}`),o=a.flatMap(()=>t?[e,t]:[e]);return!!this.db.prepare(`${s.join(" UNION ALL ")} LIMIT 1`).get(...o)}jobExists(e){return!!this.db.prepare("SELECT 1 AS found FROM jobs WHERE job_id = ? LIMIT 1").get(e)}runInTransaction(e){this.assertCanMutate();const t=this.db.transaction(e);try{return t()}catch(a){throw n(a,"sqlite-migration-failed")}}collectSnapshotRows(e){const t=(o,...m)=>{const d=this.db.prepare(o).get(...m);return _(d)&&typeof d.count=="number"?d.count:0},a=this.db.prepare(`
110
+ `).run(e.gateId,e.campaignId,e.status,e.summary??null,e.required?1:0,e.reasonCode??null,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(s)}catch(a){throw n(a,"sqlite-mutation-failed")}}recordOperationAudit(e){return this.appendReceipt(e)}hasOperationRef(e,t){this.assertCanMutate();const a=["jobs","job_leases","job_events","job_receipts","goal_campaigns","goal_ledger_items","goal_verifiers","goal_review_gates","loop_jobs","artifacts","state_snapshots","runner_config","outbox"],s=a.map(d=>`SELECT 1 AS found FROM ${d} WHERE operation_id = ?${t?" OR idempotency_key = ?":""}`),o=a.flatMap(()=>t?[e,t]:[e]);return!!this.db.prepare(`${s.join(" UNION ALL ")} LIMIT 1`).get(...o)}jobExists(e){return!!this.db.prepare("SELECT 1 AS found FROM jobs WHERE job_id = ? LIMIT 1").get(e)}runInTransaction(e){this.assertCanMutate();const t=this.db.transaction(e);try{return typeof t.immediate=="function"?t.immediate():t()}catch(a){throw n(a,"sqlite-mutation-failed")}}collectSnapshotRows(e){const t=(o,...m)=>{const d=this.db.prepare(o).get(...m);return _(d)&&typeof d.count=="number"?d.count:0},a=this.db.prepare(`
111
111
  SELECT status, COUNT(*) AS count FROM outbox GROUP BY status
112
112
  `).all(),s={};for(const o of a)typeof o.status=="string"&&typeof o.count=="number"&&(s[o.status]=o.count);return{schemaVersion:this.getSchemaVersion(),jobs:this.db.prepare(`
113
113
  SELECT job_id, kind, status, summary, reason_code, created_at, updated_at,
@@ -212,7 +212,7 @@ import{createHash as T}from"node:crypto";import{chmodSync as b,existsSync as C,m
212
212
  SET status = 'expired', released_at = ?
213
213
  WHERE released_at IS NULL
214
214
  AND lease_id IN (${h})
215
- `).run(e.nowIso,...d);return{recoveredLeaseIds:d,safeExpiredAtOrBefore:o,changes:E.changes}})}catch(m){throw n(m,"sqlite-migration-failed")}}ensureGoalCampaign(e,t,a,s){this.db.prepare(`
215
+ `).run(e.nowIso,...d);return{recoveredLeaseIds:d,safeExpiredAtOrBefore:o,changes:E.changes}})}catch(m){throw n(m,"sqlite-mutation-failed")}}ensureGoalCampaign(e,t,a,s){this.db.prepare(`
216
216
  INSERT OR IGNORE INTO goal_campaigns (
217
217
  campaign_id, job_id, status, public_summary, created_at, updated_at
218
218
  ) VALUES (?, ?, 'active', 'Public goal campaign summary unavailable', ?, ?)
@@ -1,7 +1,7 @@
1
- import{spawnSync as ce}from"node:child_process";import{createHash as le}from"node:crypto";import{existsSync as j,mkdirSync as ue,readFileSync as ie,writeFileSync as de}from"node:fs";import{delimiter as me,dirname as pe,isAbsolute as F,join as c,resolve as Q}from"node:path";import{checkRunnerBinaryTrust as fe,resolveTrustedRunnerBinary as J}from"./binary.js";const i=Object.freeze({OK:"continuity-ok",SCHEDULER_INSTALL_UNSAFE:"scheduler-install-unsafe",PRIMARY_USER_SCHEDULER_UNAVAILABLE:"primary-user-scheduler-unavailable",CRON_FALLBACK_SELECTED:"cron-fallback-selected",CRON_FALLBACK_NOT_ALLOWED:"cron-fallback-primary-scheduler-available",SCHEDULER_UNAVAILABLE:"scheduler-unavailable",SCHEDULER_COMMAND_FAILED:"scheduler-command-failed",RUNNER_BINARY_UNTRUSTED:"runner-binary-untrusted",LEGACY_GLOBAL_SCHEDULER_DETECTED:"legacy-global-scheduler-detected",LEGACY_GLOBAL_SCHEDULER_AMBIGUOUS:"legacy-global-scheduler-ambiguous",LEGACY_GLOBAL_SCHEDULER_OTHER_PROJECT:"legacy-global-scheduler-other-project"}),A=Object.freeze({OK:"runner-bootstrap-ok",ALREADY_ACTIVE:"runner-bootstrap-already-active",BINARY_UNAVAILABLE:"runner-bootstrap-binary-unavailable",INSTALL_FAILED:"runner-bootstrap-install-failed",START_FAILED:"runner-bootstrap-start-failed",UNEXPECTED_ERROR:"runner-bootstrap-unexpected-error"}),$="neocortex-runner",he=`${$}.service`,N=`${$}.timer`,B="com.ornexus.neocortex.runner",ye=`${B}.plist`,M="NeocortexRunner",Ee="neocortex-runner-task.xml",ge="runner.cron",Se=12,Ce=24,Le=60,H=new Map;function K(e){const r=g(e)??Q(e||"."),t=We(r),n=le("sha256").update(t).digest("hex").slice(0,Se),s=Qe(ze(t)),o=`${s}-${n}`,a=`${$}-${o}`,d=`com.ornexus.neocortex.runner.${o}`;return{projectKey:o,projectBasename:s,systemdServiceName:`${a}.service`,systemdTimerName:`${a}.timer`,systemdServiceFile:`${a}.service`,systemdTimerFile:`${a}.timer`,launchdLabel:d,launchdFile:`${d}.plist`,windowsTaskName:`NeocortexRunner-${o}`,windowsXmlFile:`${a}-task.xml`,cronFile:`runner-${o}.cron`,cronMarkerStart:`# BEGIN neocortex-runner:${o}`,cronMarkerEnd:`# END neocortex-runner:${o}`,publicSafe:!0}}function or(){H.clear()}async function ar(e={}){const r=e.platform??process.platform,t=g(e.projectRoot??process.cwd())??process.cwd(),n=K(t),s=`${r}:${n.projectKey}`,o=H.get(s);if(o?.ok)return{...o,attempted:!1,installed:!1,started:!1,cached:!0,reasonCodes:S([...o.reasonCodes,A.ALREADY_ACTIVE]),publicSummary:"runner scheduler bootstrap already active for project key.",publicSafe:!0};try{const a=e.binaryResolver??J,d=g(e.executablePath??process.argv[1])??process.argv[1],y=a({from:d,platform:r});if(!y.ok)return w({projectKey:n.projectKey,reasonCodes:[A.BINARY_UNAVAILABLE,...y.reasonCodes],publicSummary:"runner scheduler bootstrap could not resolve a trusted runner binary."});const u=Re(e.env??process.env),E={...e,projectRoot:t,executablePath:y.executablePath,platform:r,env:u,binaryResolver:()=>y},p=await q({...E,command:"install"});if(!p.ok)return w({projectKey:n.projectKey,strategy:p.strategy,reasonCodes:[A.INSTALL_FAILED,...p.reasonCodes],publicSummary:"runner scheduler bootstrap install failed.",attempted:!0});const f=await q({...E,command:"start"});if(!f.ok)return w({projectKey:n.projectKey,strategy:f.strategy??p.strategy,reasonCodes:[A.START_FAILED,...f.reasonCodes],publicSummary:"runner scheduler bootstrap start failed.",attempted:!0,installed:p.applied||p.ok});const L={ok:!0,attempted:!0,installed:p.applied||p.ok,started:f.applied||f.ok,cached:!1,projectKey:n.projectKey,strategy:f.strategy??p.strategy,reasonCodes:S([A.OK,...p.reasonCodes,...f.reasonCodes]),publicSummary:"runner scheduler bootstrap completed for project key.",publicSafe:!0};return H.set(s,L),L}catch{return w({projectKey:n.projectKey,reasonCodes:[A.UNEXPECTED_ERROR],publicSummary:"runner scheduler bootstrap stopped unexpectedly."})}}function w(e){return{ok:!1,attempted:e.attempted??!1,installed:e.installed??!1,started:!1,cached:!1,projectKey:e.projectKey,strategy:e.strategy,reasonCodes:S(e.reasonCodes),publicSummary:e.publicSummary,publicSafe:!0}}function Re(e){return{...e,NEOCORTEX_RUNNER_BOOTSTRAP_IN_PROGRESS:"1",NEOCORTEX_BOOTSTRAP_IN_PROGRESS:"1"}}async function q(e){const r=e.env??process.env,t=e.platform??process.platform,n=e.dryRun===!0,s=g(e.projectRoot??process.cwd()),o=g(e.executablePath??process.argv[1]),a=Xe(e,o,t),d=a.runnerCommand,y=d?.executablePath??o,u=K(s??process.cwd()),E=e.commandAvailable??(h=>ne(h,r)),p=qe(e.intervalSeconds??Le,10,1440*60),f=ke({platform:t,env:r,strategy:e.strategy,allowCronFallback:e.allowCronFallback,commandAvailable:E,uid:e.uid}),L=Ve(e,y,a.resolution),R=[...f.blockers];if((!s||!d)&&R.push(i.SCHEDULER_INSTALL_UNSAFE),!L.trusted){const h=L.reasonCodes&&L.reasonCodes.length>0?L.reasonCodes:[L.reasonCode??i.RUNNER_BINARY_UNTRUSTED];R.push(i.SCHEDULER_INSTALL_UNSAFE,i.RUNNER_BINARY_UNTRUSTED,...h)}const m=f.selectedStrategy;m||R.push(i.SCHEDULER_UNAVAILABLE);const k=m?be(m,r,u):void 0,b=m&&s&&Be(e.command)?Me({strategy:m,env:r,projectRoot:s}):[],ae=b.flatMap(h=>h.reasonCodes),v=(e.command==="install"||e.command==="start"||e.command==="stop")&&R.length>0,X=S([...f.reasonCodes,...R,...ae,v?i.SCHEDULER_INSTALL_UNSAFE:i.OK]);if(v||!m||!k||!s||!d)return{ok:!v&&!!m,command:e.command,platform:t,strategy:m,dryRun:n,manifestPaths:[],manifests:[],identity:u,legacyEntries:b,controlCommands:[],uninstallGuidance:m&&k?ee(m,k,u):[],capability:se(f,R),reasonCodes:X,applied:!1,publicSafe:!0};const T=e.command==="install"?Ae({strategy:m,paths:k,projectRoot:s,executablePath:d.command,runnerCommand:d,intervalSeconds:p,identity:u}):[],U=_e(e.command,m,k,u,b,r);let I=!1,x=!0;const V=[];if(e.command==="install"&&!n){for(const h of T)ue(pe(h.path),{recursive:!0}),de(h.path,h.content,"utf8");I=T.length>0}if(!n&&U.length>0){const h=e.commandRunner??Je;for(const W of U){if(W.manualOnly)continue;const z=h(W);z.ok?I=!0:(x=!1,V.push(z.reasonCode??i.SCHEDULER_COMMAND_FAILED))}}return{ok:x,command:e.command,platform:t,strategy:m,dryRun:n,manifestPaths:T.map(h=>h.path),manifests:T,identity:u,legacyEntries:b,controlCommands:U,uninstallGuidance:[...ee(m,k,u),...Ue(m,b)],capability:se(f,R),reasonCodes:S([...X,...V,x?i.OK:i.SCHEDULER_COMMAND_FAILED]),applied:I,publicSafe:!0}}function ke(e={}){const r=e.env??process.env,t=e.platform??process.platform,n=e.commandAvailable??(p=>ne(p,r)),s=Ye(t,r,e.uid),o=Ge(t),a=o?re(o,n):!1,d=t!=="win32"&&n("crontab"),y=e.allowCronFallback!==!1;let u=e.strategy;const E=[];return u||(o&&a?u=o:y&&d&&(u="cron-fallback",E.push(i.PRIMARY_USER_SCHEDULER_UNAVAILABLE,i.CRON_FALLBACK_SELECTED))),u==="cron-fallback"&&a&&(u=void 0,E.push(i.CRON_FALLBACK_NOT_ALLOWED)),u&&!re(u,n)&&(u!=="cron-fallback"||!d)&&(u=void 0),u||E.push(i.SCHEDULER_UNAVAILABLE),s.length>0&&E.push(...s),E.length===0&&E.push(i.OK),{platform:t,primaryStrategy:o,selectedStrategy:u,fallbackStrategy:d?"cron-fallback":void 0,primaryAvailable:a,cronFallbackAvailable:d,safeToInstall:s.length===0,blockers:s,reasonCodes:S(E),publicSafe:!0}}function Ae(e){const r=e.identity??K(e.projectRoot),t=e.runnerCommand??{command:e.executablePath,args:[],executablePath:e.executablePath,publicSafe:!0};switch(e.strategy){case"systemd-user":return[{kind:"systemd-service",path:e.paths.systemdServicePath,content:Ie(t,e.projectRoot,r),publicSafe:!0},{kind:"systemd-timer",path:e.paths.systemdTimerPath,content:xe(e.intervalSeconds,r),publicSafe:!0}];case"launchd-user":return[{kind:"launchd-plist",path:e.paths.launchdPlistPath,content:je(t,e.projectRoot,e.intervalSeconds,r),publicSafe:!0}];case"windows-task-scheduler":return[{kind:"windows-task-xml",path:e.paths.windowsTaskXmlPath,content:Fe(t,e.projectRoot,e.intervalSeconds,r),publicSafe:!0}];case"cron-fallback":return[{kind:"cron-snippet",path:e.paths.cronSnippetPath,content:$e(t,e.projectRoot,r),publicSafe:!0}]}}function be(e,r,t){const n=te(r),s=g(r.XDG_CONFIG_HOME)??c(n,".config"),o=c(s,"systemd","user"),a=c(n,"Library","LaunchAgents"),d=g(r.APPDATA)??c(g(r.USERPROFILE)??n,"AppData","Roaming"),y=c(d,"Neocortex","Runner"),u=c(s,"neocortex");return{systemdServicePath:c(o,t.systemdServiceFile),systemdTimerPath:c(o,t.systemdTimerFile),launchdPlistPath:c(a,t.launchdFile),windowsTaskXmlPath:c(y,t.windowsXmlFile),cronSnippetPath:c(u,t.cronFile)}}function Z(e,r){const t=te(r),n=g(r.XDG_CONFIG_HOME)??c(t,".config"),s=c(n,"systemd","user"),o=c(t,"Library","LaunchAgents"),a=g(r.APPDATA)??c(g(r.USERPROFILE)??t,"AppData","Roaming"),d=c(a,"Neocortex","Runner"),y=c(n,"neocortex");return{systemdServicePath:c(s,he),systemdTimerPath:c(s,N),launchdPlistPath:c(o,ye),windowsTaskXmlPath:c(d,Ee),cronSnippetPath:c(y,ge)}}function _e(e,r,t,n,s,o){return e==="doctor"?[]:[...e==="install"?Te(r,t,n):e==="start"?Ne(r,t,n):e==="stop"?we(r,t,n):De(r,t,n),...Pe(e,r,s,o)]}function Te(e,r,t){switch(e){case"systemd-user":return[l("systemctl",["--user","daemon-reload"]),l("systemctl",["--user","enable","--now",t.systemdTimerName])];case"launchd-user":return[l("launchctl",["load","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[l("schtasks",["/Create","/TN",t.windowsTaskName,"/XML",r.windowsTaskXmlPath,"/F"])];case"cron-fallback":return[l("crontab",["-l","# append snippet from",r.cronSnippetPath],!0)]}}function Ne(e,r,t){switch(e){case"systemd-user":return[l("systemctl",["--user","start",t.systemdTimerName])];case"launchd-user":return[l("launchctl",["load","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[l("schtasks",["/Run","/TN",t.windowsTaskName])];case"cron-fallback":return[l("crontab",["-l","# ensure snippet from",r.cronSnippetPath,"is installed"],!0)]}}function we(e,r,t){switch(e){case"systemd-user":return[l("systemctl",["--user","stop",t.systemdTimerName])];case"launchd-user":return[l("launchctl",["unload","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[l("schtasks",["/End","/TN",t.windowsTaskName])];case"cron-fallback":return[l("crontab",["-l","# remove scoped neocortex-runner snippet"],!0)]}}function De(e,r,t){switch(e){case"systemd-user":return[l("systemctl",["--user","status",t.systemdTimerName,"--no-pager"])];case"launchd-user":return[l("launchctl",["list",t.launchdLabel])];case"windows-task-scheduler":return[l("schtasks",["/Query","/TN",t.windowsTaskName,"/FO","LIST"])];case"cron-fallback":return[l("crontab",["-l","# look for neocortex-runner snippet from",r.cronSnippetPath],!0)]}}function ee(e,r,t){switch(e){case"systemd-user":return[`systemctl --user disable --now ${t.systemdTimerName}`,`rm ${r.systemdServicePath}`,`rm ${r.systemdTimerPath}`];case"launchd-user":return[`launchctl unload -w ${r.launchdPlistPath}`,`rm ${r.launchdPlistPath}`];case"windows-task-scheduler":return[`schtasks /Delete /TN ${t.windowsTaskName} /F`,`Remove-Item ${r.windowsTaskXmlPath}`];case"cron-fallback":return[`Remove the ${t.cronMarkerStart} block from the user crontab.`,`rm ${r.cronSnippetPath}`]}}function Pe(e,r,t,n){if(!t.some(a=>a.relation==="current-project")||e!=="status"&&e!=="stop")return[];const o=Z(r,n);return e==="status"?Oe(r,o):ve(r,o)}function Oe(e,r){switch(e){case"systemd-user":return[l("systemctl",["--user","status",N,"--no-pager"])];case"launchd-user":return[l("launchctl",["list",B])];case"windows-task-scheduler":return[l("schtasks",["/Query","/TN",M,"/FO","LIST"])];case"cron-fallback":return[l("crontab",["-l","# look for legacy neocortex-runner snippet from",r.cronSnippetPath],!0)]}}function ve(e,r){switch(e){case"systemd-user":return[l("systemctl",["--user","stop",N])];case"launchd-user":return[l("launchctl",["unload","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[l("schtasks",["/End","/TN",M])];case"cron-fallback":return[l("crontab",["-l","# remove legacy neocortex-runner snippet"],!0)]}}function Ue(e,r){if(r.length===0)return[];const t=r.filter(a=>a.relation==="current-project"),n=r.filter(a=>a.relation==="ambiguous"),s=r.filter(a=>a.relation==="other-project"),o=[];return t.length>0&&o.push(`Legacy global ${e} scheduler matches this project; stop it before relying on project-scoped runner scheduling.`),n.length>0&&o.push(`Legacy global ${e} scheduler ownership is ambiguous; inspect it manually before removal.`),s.length>0&&o.push(`Legacy global ${e} scheduler appears to belong to another project; leave it unchanged.`),o}function Ie(e,r,t){const n=[e.command,...e.args,"tick","--project-root",r].map(G).join(" ");return["[Unit]",`Description=Neocortex Enterprise Continuity Runner (${t.projectKey}, user scope)`,`# Managed by Neocortex runner for project ${t.projectKey}`,"After=network-online.target","","[Service]","Type=oneshot",`WorkingDirectory=${G(r)}`,`ExecStart=${n}`,"","[Install]","WantedBy=default.target",""].join(`
2
- `)}function xe(e,r){return["[Unit]",`Description=Run Neocortex Enterprise Continuity Runner periodically (${r.projectKey}, user scope)`,`# Managed by Neocortex runner for project ${r.projectKey}`,"","[Timer]","OnBootSec=60s",`OnUnitActiveSec=${e}s`,`Unit=${r.systemdServiceName}`,"","[Install]","WantedBy=timers.target",""].join(`
3
- `)}function je(e,r,t,n){const s=[e.command,...e.args,"tick","--project-root",r];return['<?xml version="1.0" encoding="UTF-8"?>','<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">','<plist version="1.0">',"<dict>",` <!-- Managed by Neocortex runner for project ${C(n.projectKey)} -->`," <key>Label</key>",` <string>${C(n.launchdLabel)}</string>`," <key>ProgramArguments</key>"," <array>",...s.map(o=>` <string>${C(o)}</string>`)," </array>"," <key>WorkingDirectory</key>",` <string>${C(r)}</string>`," <key>StartInterval</key>",` <integer>${t}</integer>`," <key>RunAtLoad</key>"," <true/>","</dict>","</plist>",""].join(`
4
- `)}function Fe(e,r,t,n){const s=[...e.args,"tick","--project-root",r].map(oe).join(" ");return['<?xml version="1.0" encoding="UTF-16"?>','<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">'," <RegistrationInfo>",` <Description>Neocortex Enterprise Continuity Runner (${C(n.projectKey)}, user scope)</Description>`," </RegistrationInfo>"," <Triggers>"," <TimeTrigger>"," <Repetition>",` <Interval>PT${t}S</Interval>`," <StopAtDurationEnd>false</StopAtDurationEnd>"," </Repetition>"," <Enabled>true</Enabled>"," </TimeTrigger>"," </Triggers>"," <Principals>",' <Principal id="Author">'," <LogonType>InteractiveToken</LogonType>"," <RunLevel>LeastPrivilege</RunLevel>"," </Principal>"," </Principals>"," <Settings>"," <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>"," <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>"," <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>"," <Enabled>true</Enabled>"," </Settings>",' <Actions Context="Author">'," <Exec>",` <Command>${C(e.command)}</Command>`,` <Arguments>${C(s)}</Arguments>`,` <WorkingDirectory>${C(r)}</WorkingDirectory>`," </Exec>"," </Actions>","</Task>",""].join(`
5
- `)}function $e(e,r,t){const n=[e.command,...e.args,"tick","--project-root",r].map(Y).join(" ");return[t.cronMarkerStart,`# neocortex-runner user-scope cron fallback for project ${t.projectKey}`,"# Reason: primary-user-scheduler-unavailable",`* * * * * ${n} # neocortex-runner:${t.projectKey}`,t.cronMarkerEnd,""].join(`
6
- `)}function Be(e){return e==="status"||e==="stop"||e==="doctor"}function Me(e){const r=Z(e.strategy,e.env);switch(e.strategy){case"systemd-user":{const t=_(r.systemdServicePath),n=_(r.systemdTimerPath),s=t?O(t):!1,o=n?Ke(n):!1;if(!s&&!o)return[];const a=P([t,n].filter(Boolean).join(`
7
- `),e.projectRoot,s);return[D(e.strategy,"systemd-timer",N,a)]}case"launchd-user":{const t=_(r.launchdPlistPath);return!t||!O(t)?[]:[D(e.strategy,"launchd-plist",B,P(t,e.projectRoot,!0))]}case"windows-task-scheduler":{const t=_(r.windowsTaskXmlPath);return!t||!O(t)?[]:[D(e.strategy,"windows-task-xml",M,P(t,e.projectRoot,!0))]}case"cron-fallback":{const t=_(r.cronSnippetPath);return!t||!O(t)?[]:[D(e.strategy,"cron-snippet","# neocortex-runner",P(t,e.projectRoot,!0))]}}}function D(e,r,t,n){const s=n==="current-project"?i.LEGACY_GLOBAL_SCHEDULER_DETECTED:n==="ambiguous"?i.LEGACY_GLOBAL_SCHEDULER_AMBIGUOUS:i.LEGACY_GLOBAL_SCHEDULER_OTHER_PROJECT;return{strategy:e,kind:r,name:t,relation:n,reasonCodes:[s],remediation:n==="current-project"?"stop-safe":n==="ambiguous"?"manual-review-only":"report-only",publicSafe:!0}}function P(e,r,t){return He(e,r)?"current-project":t&&/--project-root|WorkingDirectory=|<key>WorkingDirectory<\/key>|<Arguments>[^<]*--project-root/i.test(e)?"other-project":"ambiguous"}function He(e,r){return S([r,G(r),Y(r),oe(r),C(r)].filter(Boolean)).some(n=>e.includes(n))}function O(e){return/neocortex-runner|com\.ornexus\.neocortex\.runner|NeocortexRunner|Neocortex Enterprise Continuity Runner/i.test(e)&&/tick|--project-root|StartInterval|OnUnitActiveSec|InteractiveToken|primary-user-scheduler-unavailable/i.test(e)}function Ke(e){return/neocortex-runner\.service|Neocortex Enterprise Continuity Runner|OnUnitActiveSec/i.test(e)}function _(e){try{return ie(e,"utf8")}catch{return null}}function Ge(e){if(e==="linux")return"systemd-user";if(e==="darwin")return"launchd-user";if(e==="win32")return"windows-task-scheduler"}function re(e,r){switch(e){case"systemd-user":return r("systemctl");case"launchd-user":return r("launchctl");case"windows-task-scheduler":return r("schtasks")||r("schtasks.exe");case"cron-fallback":return r("crontab")}}function Ye(e,r,t){const n=[],s=t??(typeof process.getuid=="function"?process.getuid():null);e!=="win32"&&s===0&&n.push(i.SCHEDULER_INSTALL_UNSAFE),e!=="win32"&&(r.SUDO_USER||r.SUDO_UID||r.SUDO_COMMAND)&&n.push(i.SCHEDULER_INSTALL_UNSAFE);const o=r.HOME??r.USERPROFILE;return(!o||!F(o)||!g(o))&&n.push(i.SCHEDULER_INSTALL_UNSAFE),S(n)}function Xe(e,r,t){if(e.trustCheck===!1||e.trustChecker)return{runnerCommand:r?{command:r,args:[],executablePath:r,publicSafe:!0}:void 0};const s=(e.binaryResolver??J)({from:r??process.argv[1],platform:t});return s.ok?{runnerCommand:{command:s.command,args:s.args,executablePath:s.executablePath,provenance:s.provenance,publicSafe:!0},resolution:s}:{runnerCommand:r?{command:r,args:[],executablePath:r,provenance:s.provenance,publicSafe:!0}:void 0,resolution:s}}function Ve(e,r,t){return e.trustCheck===!1?{trusted:!0,executablePath:r??void 0,publicSafe:!0}:e.trustChecker?e.trustChecker(r??void 0):t?t.ok?{trusted:!0,packageName:t.packageName,packageVersion:t.packageVersion,packageRoot:t.packageRoot,executablePath:t.executablePath,expectedRelativePath:t.expectedRelativePath,provenance:t.provenance,reasonCodes:t.reasonCodes,publicSafe:!0}:{trusted:!1,reasonCode:t.reasonCode,reasonCodes:t.reasonCodes,packageName:t.packageName,packageVersion:t.packageVersion,packageRoot:t.packageRoot,executablePath:t.executablePath??r??void 0,expectedRelativePath:t.expectedRelativePath,provenance:t.provenance,publicSafe:!0}:fe(r??void 0)}function te(e){return e.HOME??e.USERPROFILE??process.env.HOME??process.cwd()}function We(e){let r=e.replace(/\\/g,"/").replace(/\/+$/g,"");return r||(r="/"),r=r.replace(/^([A-Z]):\//,(t,n)=>`${n.toLowerCase()}:/`),r}function ze(e){const r=e.split("/").filter(Boolean);return r[r.length-1]??"project"}function Qe(e){return e.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,Ce).replace(/-+$/g,"")||"project"}function g(e){if(!e||/[\r\n\0]/.test(e))return null;const r=F(e)?e:Q(e);return F(r)?r:null}function l(e,r,t=!1){return{command:e,args:r,preview:[e,...r.map(Y)].join(" "),safeUserScope:!0,...t?{manualOnly:!0}:{}}}function Je(e){const r=ce(e.command,[...e.args],{stdio:"ignore",shell:!1});return{ok:r.status===0,code:r.status,signal:r.signal,reasonCode:r.status===0?i.OK:i.SCHEDULER_COMMAND_FAILED}}function ne(e,r){const t=r.PATH??process.env.PATH??"",n=(r.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean),s=t.split(me).filter(Boolean);for(const o of s){const a=c(o,e);if(j(a))return!0;for(const d of n)if(j(c(o,`${e}${d.toLowerCase()}`))||j(c(o,`${e}${d.toUpperCase()}`)))return!0}return!1}function se(e,r){const t=S([...e.blockers,...r]);return{...e,safeToInstall:t.length===0,blockers:t,reasonCodes:S([...e.reasonCodes,...t])}}function G(e){return/[\s"'\\]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e}function Y(e){return/^[A-Za-z0-9_./:=@%+-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}function oe(e){return/[\s"]/.test(e)?`"${e.replace(/"/g,'\\"')}"`:e}function C(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function qe(e,r,t){return Number.isFinite(e)?Math.max(r,Math.min(t,Math.floor(e))):r}function S(e){return Array.from(new Set(e))}export{A as RUNNER_SCHEDULER_BOOTSTRAP_REASON_CODES,i as SCHEDULER_REASON_CODES,or as __resetRunnerSchedulerBootstrapCacheForTests,K as createRunnerSchedulerIdentity,ke as detectSchedulerCapability,ar as ensureRunnerSchedulerBootstrap,Ae as renderSchedulerManifests,q as runRunnerSchedulerCommand};
1
+ import{Buffer as le}from"node:buffer";import{spawnSync as ie}from"node:child_process";import{createHash as de}from"node:crypto";import{existsSync as j,mkdirSync as me,readFileSync as pe,writeFileSync as fe}from"node:fs";import{delimiter as he,dirname as ye,isAbsolute as $,join as c,resolve as z}from"node:path";import{checkRunnerBinaryTrust as Ee,resolveTrustedRunnerBinary as Q}from"./binary.js";const i=Object.freeze({OK:"continuity-ok",SCHEDULER_INSTALL_UNSAFE:"scheduler-install-unsafe",PRIMARY_USER_SCHEDULER_UNAVAILABLE:"primary-user-scheduler-unavailable",CRON_FALLBACK_SELECTED:"cron-fallback-selected",CRON_FALLBACK_NOT_ALLOWED:"cron-fallback-primary-scheduler-available",SCHEDULER_UNAVAILABLE:"scheduler-unavailable",SCHEDULER_COMMAND_FAILED:"scheduler-command-failed",RUNNER_BINARY_UNTRUSTED:"runner-binary-untrusted",LEGACY_GLOBAL_SCHEDULER_DETECTED:"legacy-global-scheduler-detected",LEGACY_GLOBAL_SCHEDULER_AMBIGUOUS:"legacy-global-scheduler-ambiguous",LEGACY_GLOBAL_SCHEDULER_OTHER_PROJECT:"legacy-global-scheduler-other-project"}),R=Object.freeze({OK:"runner-bootstrap-ok",ALREADY_ACTIVE:"runner-bootstrap-already-active",BINARY_UNAVAILABLE:"runner-bootstrap-binary-unavailable",INSTALL_FAILED:"runner-bootstrap-install-failed",START_FAILED:"runner-bootstrap-start-failed",UNEXPECTED_ERROR:"runner-bootstrap-unexpected-error"}),F="neocortex-runner",ge=`${F}.service`,N=`${F}.timer`,B="com.ornexus.neocortex.runner",Se=`${B}.plist`,M="NeocortexRunner",Ce="neocortex-runner-task.xml",Le="runner.cron",Ae=12,ke=24,Re=60,H=new Map;function K(e){const r=g(e)??z(e||"."),t=Je(r),n=de("sha256").update(t).digest("hex").slice(0,Ae),s=Ze(qe(t)),a=`${s}-${n}`,o=`${F}-${a}`,d=`com.ornexus.neocortex.runner.${a}`;return{projectKey:a,projectBasename:s,systemdServiceName:`${o}.service`,systemdTimerName:`${o}.timer`,systemdServiceFile:`${o}.service`,systemdTimerFile:`${o}.timer`,launchdLabel:d,launchdFile:`${d}.plist`,windowsTaskName:`NeocortexRunner-${a}`,windowsXmlFile:`${o}-task.xml`,cronFile:`runner-${a}.cron`,cronMarkerStart:`# BEGIN neocortex-runner:${a}`,cronMarkerEnd:`# END neocortex-runner:${a}`,publicSafe:!0}}function ir(){H.clear()}async function dr(e={}){const r=e.platform??process.platform,t=g(e.projectRoot??process.cwd())??process.cwd(),n=K(t),s=`${r}:${n.projectKey}`,a=H.get(s);if(a?.ok)return{...a,attempted:!1,installed:!1,started:!1,cached:!0,reasonCodes:S([...a.reasonCodes,R.ALREADY_ACTIVE]),publicSummary:"runner scheduler bootstrap already active for project key.",publicSafe:!0};try{const o=e.binaryResolver??Q,d=g(e.executablePath??process.argv[1])??process.argv[1],y=o({from:d,platform:r});if(!y.ok)return w({projectKey:n.projectKey,reasonCodes:[R.BINARY_UNAVAILABLE,...y.reasonCodes],publicSummary:"runner scheduler bootstrap could not resolve a trusted runner binary."});const l=be(e.env??process.env),E={...e,projectRoot:t,executablePath:y.executablePath,platform:r,env:l,binaryResolver:()=>y},p=await J({...E,command:"install"});if(!p.ok)return w({projectKey:n.projectKey,strategy:p.strategy,reasonCodes:[R.INSTALL_FAILED,...p.reasonCodes],publicSummary:"runner scheduler bootstrap install failed.",attempted:!0});const f=await J({...E,command:"start"});if(!f.ok)return w({projectKey:n.projectKey,strategy:f.strategy??p.strategy,reasonCodes:[R.START_FAILED,...f.reasonCodes],publicSummary:"runner scheduler bootstrap start failed.",attempted:!0,installed:p.applied||p.ok});const L={ok:!0,attempted:!0,installed:p.applied||p.ok,started:f.applied||f.ok,cached:!1,projectKey:n.projectKey,strategy:f.strategy??p.strategy,reasonCodes:S([R.OK,...p.reasonCodes,...f.reasonCodes]),publicSummary:"runner scheduler bootstrap completed for project key.",publicSafe:!0};return H.set(s,L),L}catch{return w({projectKey:n.projectKey,reasonCodes:[R.UNEXPECTED_ERROR],publicSummary:"runner scheduler bootstrap stopped unexpectedly."})}}function w(e){return{ok:!1,attempted:e.attempted??!1,installed:e.installed??!1,started:!1,cached:!1,projectKey:e.projectKey,strategy:e.strategy,reasonCodes:S(e.reasonCodes),publicSummary:e.publicSummary,publicSafe:!0}}function be(e){return{...e,NEOCORTEX_RUNNER_BOOTSTRAP_IN_PROGRESS:"1",NEOCORTEX_BOOTSTRAP_IN_PROGRESS:"1"}}async function J(e){const r=e.env??process.env,t=e.platform??process.platform,n=e.dryRun===!0,s=g(e.projectRoot??process.cwd()),a=g(e.executablePath??process.argv[1]),o=ze(e,a,t),d=o.runnerCommand,y=d?.executablePath??a,l=K(s??process.cwd()),E=e.commandAvailable??(h=>te(h,r)),p=tr(e.intervalSeconds??Re,10,1440*60),f=_e({platform:t,env:r,strategy:e.strategy,allowCronFallback:e.allowCronFallback,commandAvailable:E,uid:e.uid}),L=Qe(e,y,o.resolution),A=[...f.blockers];if((!s||!d)&&A.push(i.SCHEDULER_INSTALL_UNSAFE),!L.trusted){const h=L.reasonCodes&&L.reasonCodes.length>0?L.reasonCodes:[L.reasonCode??i.RUNNER_BINARY_UNTRUSTED];A.push(i.SCHEDULER_INSTALL_UNSAFE,i.RUNNER_BINARY_UNTRUSTED,...h)}const m=f.selectedStrategy;m||A.push(i.SCHEDULER_UNAVAILABLE);const k=m?Ne(m,r,l):void 0,b=m&&s&&Ke(e.command)?Ge({strategy:m,env:r,projectRoot:s}):[],ue=b.flatMap(h=>h.reasonCodes),v=(e.command==="install"||e.command==="start"||e.command==="stop")&&A.length>0,Y=S([...f.reasonCodes,...A,...ue,v?i.SCHEDULER_INSTALL_UNSAFE:i.OK]);if(v||!m||!k||!s||!d)return{ok:!v&&!!m,command:e.command,platform:t,strategy:m,dryRun:n,manifestPaths:[],manifests:[],identity:l,legacyEntries:b,controlCommands:[],uninstallGuidance:m&&k?Z(m,k,l):[],capability:ne(f,A),reasonCodes:Y,applied:!1,publicSafe:!0};const T=e.command==="install"?Te({strategy:m,paths:k,projectRoot:s,executablePath:d.command,runnerCommand:d,intervalSeconds:p,identity:l}):[],U=we(e.command,m,k,l,b,r);let I=!1,x=!0;const X=[];if(e.command==="install"&&!n){for(const h of T)me(ye(h.path),{recursive:!0}),fe(h.path,h.content,"utf8");I=T.length>0}if(!n&&U.length>0){const h=e.commandRunner??er;for(const V of U){if(V.manualOnly)continue;const W=h(V);W.ok?I=!0:(x=!1,X.push(W.reasonCode??i.SCHEDULER_COMMAND_FAILED))}}return{ok:x,command:e.command,platform:t,strategy:m,dryRun:n,manifestPaths:T.map(h=>h.path),manifests:T,identity:l,legacyEntries:b,controlCommands:U,uninstallGuidance:[...Z(m,k,l),...je(m,b)],capability:ne(f,A),reasonCodes:S([...Y,...X,x?i.OK:i.SCHEDULER_COMMAND_FAILED]),applied:I,publicSafe:!0}}function _e(e={}){const r=e.env??process.env,t=e.platform??process.platform,n=e.commandAvailable??(p=>te(p,r)),s=We(t,r,e.uid),a=Ve(t),o=a?ee(a,n):!1,d=t!=="win32"&&n("crontab"),y=e.allowCronFallback!==!1;let l=e.strategy;const E=[];return l||(a&&o?l=a:y&&d&&(l="cron-fallback",E.push(i.PRIMARY_USER_SCHEDULER_UNAVAILABLE,i.CRON_FALLBACK_SELECTED))),l==="cron-fallback"&&o&&(l=void 0,E.push(i.CRON_FALLBACK_NOT_ALLOWED)),l&&!ee(l,n)&&(l!=="cron-fallback"||!d)&&(l=void 0),l||E.push(i.SCHEDULER_UNAVAILABLE),s.length>0&&E.push(...s),E.length===0&&E.push(i.OK),{platform:t,primaryStrategy:a,selectedStrategy:l,fallbackStrategy:d?"cron-fallback":void 0,primaryAvailable:o,cronFallbackAvailable:d,safeToInstall:s.length===0,blockers:s,reasonCodes:S(E),publicSafe:!0}}function Te(e){const r=e.identity??K(e.projectRoot),t=e.runnerCommand??{command:e.executablePath,args:[],executablePath:e.executablePath,publicSafe:!0};switch(e.strategy){case"systemd-user":return[{kind:"systemd-service",path:e.paths.systemdServicePath,content:$e(t,e.projectRoot,r),publicSafe:!0},{kind:"systemd-timer",path:e.paths.systemdTimerPath,content:Fe(e.intervalSeconds,r),publicSafe:!0}];case"launchd-user":return[{kind:"launchd-plist",path:e.paths.launchdPlistPath,content:Be(t,e.projectRoot,e.intervalSeconds,r),publicSafe:!0}];case"windows-task-scheduler":return[{kind:"windows-task-xml",path:e.paths.windowsTaskXmlPath,content:Me(t,e.projectRoot,e.intervalSeconds,r),publicSafe:!0}];case"cron-fallback":return[{kind:"cron-snippet",path:e.paths.cronSnippetPath,content:He(t,e.projectRoot,r),publicSafe:!0}]}}function Ne(e,r,t){const n=re(r),s=g(r.XDG_CONFIG_HOME)??c(n,".config"),a=c(s,"systemd","user"),o=c(n,"Library","LaunchAgents"),d=g(r.APPDATA)??c(g(r.USERPROFILE)??n,"AppData","Roaming"),y=c(d,"Neocortex","Runner"),l=c(s,"neocortex");return{systemdServicePath:c(a,t.systemdServiceFile),systemdTimerPath:c(a,t.systemdTimerFile),launchdPlistPath:c(o,t.launchdFile),windowsTaskXmlPath:c(y,t.windowsXmlFile),cronSnippetPath:c(l,t.cronFile)}}function q(e,r){const t=re(r),n=g(r.XDG_CONFIG_HOME)??c(t,".config"),s=c(n,"systemd","user"),a=c(t,"Library","LaunchAgents"),o=g(r.APPDATA)??c(g(r.USERPROFILE)??t,"AppData","Roaming"),d=c(o,"Neocortex","Runner"),y=c(n,"neocortex");return{systemdServicePath:c(s,ge),systemdTimerPath:c(s,N),launchdPlistPath:c(a,Se),windowsTaskXmlPath:c(d,Ce),cronSnippetPath:c(y,Le)}}function we(e,r,t,n,s,a){return e==="doctor"?[]:[...e==="install"?De(r,t,n):e==="start"?Pe(r,t,n):e==="stop"?Oe(r,t,n):ve(r,t,n),...Ue(e,r,s,a)]}function De(e,r,t){switch(e){case"systemd-user":return[u("systemctl",["--user","daemon-reload"]),u("systemctl",["--user","enable","--now",t.systemdTimerName])];case"launchd-user":return[u("launchctl",["load","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[u("schtasks",["/Create","/TN",t.windowsTaskName,"/XML",r.windowsTaskXmlPath,"/F"])];case"cron-fallback":return[u("crontab",["-l","# append snippet from",r.cronSnippetPath],!0)]}}function Pe(e,r,t){switch(e){case"systemd-user":return[u("systemctl",["--user","start",t.systemdTimerName])];case"launchd-user":return[u("launchctl",["load","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[u("schtasks",["/Run","/TN",t.windowsTaskName])];case"cron-fallback":return[u("crontab",["-l","# ensure snippet from",r.cronSnippetPath,"is installed"],!0)]}}function Oe(e,r,t){switch(e){case"systemd-user":return[u("systemctl",["--user","stop",t.systemdTimerName])];case"launchd-user":return[u("launchctl",["unload","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[u("schtasks",["/End","/TN",t.windowsTaskName])];case"cron-fallback":return[u("crontab",["-l","# remove scoped neocortex-runner snippet"],!0)]}}function ve(e,r,t){switch(e){case"systemd-user":return[u("systemctl",["--user","status",t.systemdTimerName,"--no-pager"])];case"launchd-user":return[u("launchctl",["list",t.launchdLabel])];case"windows-task-scheduler":return[u("schtasks",["/Query","/TN",t.windowsTaskName,"/FO","LIST"])];case"cron-fallback":return[u("crontab",["-l","# look for neocortex-runner snippet from",r.cronSnippetPath],!0)]}}function Z(e,r,t){switch(e){case"systemd-user":return[`systemctl --user disable --now ${t.systemdTimerName}`,`rm ${r.systemdServicePath}`,`rm ${r.systemdTimerPath}`];case"launchd-user":return[`launchctl unload -w ${r.launchdPlistPath}`,`rm ${r.launchdPlistPath}`];case"windows-task-scheduler":return[`schtasks /Delete /TN ${t.windowsTaskName} /F`,`Remove-Item ${r.windowsTaskXmlPath}`];case"cron-fallback":return[`Remove the ${t.cronMarkerStart} block from the user crontab.`,`rm ${r.cronSnippetPath}`]}}function Ue(e,r,t,n){if(!t.some(o=>o.relation==="current-project")||e!=="status"&&e!=="stop")return[];const a=q(r,n);return e==="status"?Ie(r,a):xe(r,a)}function Ie(e,r){switch(e){case"systemd-user":return[u("systemctl",["--user","status",N,"--no-pager"])];case"launchd-user":return[u("launchctl",["list",B])];case"windows-task-scheduler":return[u("schtasks",["/Query","/TN",M,"/FO","LIST"])];case"cron-fallback":return[u("crontab",["-l","# look for legacy neocortex-runner snippet from",r.cronSnippetPath],!0)]}}function xe(e,r){switch(e){case"systemd-user":return[u("systemctl",["--user","stop",N])];case"launchd-user":return[u("launchctl",["unload","-w",r.launchdPlistPath])];case"windows-task-scheduler":return[u("schtasks",["/End","/TN",M])];case"cron-fallback":return[u("crontab",["-l","# remove legacy neocortex-runner snippet"],!0)]}}function je(e,r){if(r.length===0)return[];const t=r.filter(o=>o.relation==="current-project"),n=r.filter(o=>o.relation==="ambiguous"),s=r.filter(o=>o.relation==="other-project"),a=[];return t.length>0&&a.push(`Legacy global ${e} scheduler matches this project; stop it before relying on project-scoped runner scheduling.`),n.length>0&&a.push(`Legacy global ${e} scheduler ownership is ambiguous; inspect it manually before removal.`),s.length>0&&a.push(`Legacy global ${e} scheduler appears to belong to another project; leave it unchanged.`),a}function $e(e,r,t){const n=[e.command,...e.args,"tick","--project-root",r].map(se).join(" ");return["[Unit]",`Description=Neocortex Enterprise Continuity Runner (${t.projectKey}, user scope)`,`# Managed by Neocortex runner for project ${t.projectKey}`,"After=network-online.target","","[Service]","Type=oneshot",`WorkingDirectory=${oe(r)}`,`ExecStart=${n}`,"","[Install]","WantedBy=default.target",""].join(`
2
+ `)}function Fe(e,r){return["[Unit]",`Description=Run Neocortex Enterprise Continuity Runner periodically (${r.projectKey}, user scope)`,`# Managed by Neocortex runner for project ${r.projectKey}`,"","[Timer]","OnBootSec=60s",`OnUnitActiveSec=${e}s`,`Unit=${r.systemdServiceName}`,"","[Install]","WantedBy=timers.target",""].join(`
3
+ `)}function Be(e,r,t,n){const s=[e.command,...e.args,"tick","--project-root",r];return['<?xml version="1.0" encoding="UTF-8"?>','<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">','<plist version="1.0">',"<dict>",` <!-- Managed by Neocortex runner for project ${C(n.projectKey)} -->`," <key>Label</key>",` <string>${C(n.launchdLabel)}</string>`," <key>ProgramArguments</key>"," <array>",...s.map(a=>` <string>${C(a)}</string>`)," </array>"," <key>WorkingDirectory</key>",` <string>${C(r)}</string>`," <key>StartInterval</key>",` <integer>${t}</integer>`," <key>RunAtLoad</key>"," <true/>","</dict>","</plist>",""].join(`
4
+ `)}function Me(e,r,t,n){const s=[...e.args,"tick","--project-root",r].map(ce).join(" ");return['<?xml version="1.0" encoding="UTF-16"?>','<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">'," <RegistrationInfo>",` <Description>Neocortex Enterprise Continuity Runner (${C(n.projectKey)}, user scope)</Description>`," </RegistrationInfo>"," <Triggers>"," <TimeTrigger>"," <Repetition>",` <Interval>PT${t}S</Interval>`," <StopAtDurationEnd>false</StopAtDurationEnd>"," </Repetition>"," <Enabled>true</Enabled>"," </TimeTrigger>"," </Triggers>"," <Principals>",' <Principal id="Author">'," <LogonType>InteractiveToken</LogonType>"," <RunLevel>LeastPrivilege</RunLevel>"," </Principal>"," </Principals>"," <Settings>"," <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>"," <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>"," <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>"," <Enabled>true</Enabled>"," </Settings>",' <Actions Context="Author">'," <Exec>",` <Command>${C(e.command)}</Command>`,` <Arguments>${C(s)}</Arguments>`,` <WorkingDirectory>${C(r)}</WorkingDirectory>`," </Exec>"," </Actions>","</Task>",""].join(`
5
+ `)}function He(e,r,t){const n=[e.command,...e.args,"tick","--project-root",r].map(G).join(" ");return[t.cronMarkerStart,`# neocortex-runner user-scope cron fallback for project ${t.projectKey}`,"# Reason: primary-user-scheduler-unavailable",`* * * * * ${n} # neocortex-runner:${t.projectKey}`,t.cronMarkerEnd,""].join(`
6
+ `)}function Ke(e){return e==="status"||e==="stop"||e==="doctor"}function Ge(e){const r=q(e.strategy,e.env);switch(e.strategy){case"systemd-user":{const t=_(r.systemdServicePath),n=_(r.systemdTimerPath),s=t?O(t):!1,a=n?Xe(n):!1;if(!s&&!a)return[];const o=P([t,n].filter(Boolean).join(`
7
+ `),e.projectRoot,s);return[D(e.strategy,"systemd-timer",N,o)]}case"launchd-user":{const t=_(r.launchdPlistPath);return!t||!O(t)?[]:[D(e.strategy,"launchd-plist",B,P(t,e.projectRoot,!0))]}case"windows-task-scheduler":{const t=_(r.windowsTaskXmlPath);return!t||!O(t)?[]:[D(e.strategy,"windows-task-xml",M,P(t,e.projectRoot,!0))]}case"cron-fallback":{const t=_(r.cronSnippetPath);return!t||!O(t)?[]:[D(e.strategy,"cron-snippet","# neocortex-runner",P(t,e.projectRoot,!0))]}}}function D(e,r,t,n){const s=n==="current-project"?i.LEGACY_GLOBAL_SCHEDULER_DETECTED:n==="ambiguous"?i.LEGACY_GLOBAL_SCHEDULER_AMBIGUOUS:i.LEGACY_GLOBAL_SCHEDULER_OTHER_PROJECT;return{strategy:e,kind:r,name:t,relation:n,reasonCodes:[s],remediation:n==="current-project"?"stop-safe":n==="ambiguous"?"manual-review-only":"report-only",publicSafe:!0}}function P(e,r,t){return Ye(e,r)?"current-project":t&&/--project-root|WorkingDirectory=|<key>WorkingDirectory<\/key>|<Arguments>[^<]*--project-root/i.test(e)?"other-project":"ambiguous"}function Ye(e,r){return S([r,se(r),rr(r),oe(r),G(r),ce(r),C(r)].filter(Boolean)).some(n=>e.includes(n))}function O(e){return/neocortex-runner|com\.ornexus\.neocortex\.runner|NeocortexRunner|Neocortex Enterprise Continuity Runner/i.test(e)&&/tick|--project-root|StartInterval|OnUnitActiveSec|InteractiveToken|primary-user-scheduler-unavailable/i.test(e)}function Xe(e){return/neocortex-runner\.service|Neocortex Enterprise Continuity Runner|OnUnitActiveSec/i.test(e)}function _(e){try{return pe(e,"utf8")}catch{return null}}function Ve(e){if(e==="linux")return"systemd-user";if(e==="darwin")return"launchd-user";if(e==="win32")return"windows-task-scheduler"}function ee(e,r){switch(e){case"systemd-user":return r("systemctl");case"launchd-user":return r("launchctl");case"windows-task-scheduler":return r("schtasks")||r("schtasks.exe");case"cron-fallback":return r("crontab")}}function We(e,r,t){const n=[],s=t??(typeof process.getuid=="function"?process.getuid():null);e!=="win32"&&s===0&&n.push(i.SCHEDULER_INSTALL_UNSAFE),e!=="win32"&&(r.SUDO_USER||r.SUDO_UID||r.SUDO_COMMAND)&&n.push(i.SCHEDULER_INSTALL_UNSAFE);const a=r.HOME??r.USERPROFILE;return(!a||!$(a)||!g(a))&&n.push(i.SCHEDULER_INSTALL_UNSAFE),S(n)}function ze(e,r,t){if(e.trustCheck===!1||e.trustChecker)return{runnerCommand:r?{command:r,args:[],executablePath:r,publicSafe:!0}:void 0};const s=(e.binaryResolver??Q)({from:r??process.argv[1],platform:t});return s.ok?{runnerCommand:{command:s.command,args:s.args,executablePath:s.executablePath,provenance:s.provenance,publicSafe:!0},resolution:s}:{runnerCommand:r?{command:r,args:[],executablePath:r,provenance:s.provenance,publicSafe:!0}:void 0,resolution:s}}function Qe(e,r,t){return e.trustCheck===!1?{trusted:!0,executablePath:r??void 0,publicSafe:!0}:e.trustChecker?e.trustChecker(r??void 0):t?t.ok?{trusted:!0,packageName:t.packageName,packageVersion:t.packageVersion,packageRoot:t.packageRoot,executablePath:t.executablePath,expectedRelativePath:t.expectedRelativePath,provenance:t.provenance,reasonCodes:t.reasonCodes,publicSafe:!0}:{trusted:!1,reasonCode:t.reasonCode,reasonCodes:t.reasonCodes,packageName:t.packageName,packageVersion:t.packageVersion,packageRoot:t.packageRoot,executablePath:t.executablePath??r??void 0,expectedRelativePath:t.expectedRelativePath,provenance:t.provenance,publicSafe:!0}:Ee(r??void 0)}function re(e){return e.HOME??e.USERPROFILE??process.env.HOME??process.cwd()}function Je(e){let r=e.replace(/\\/g,"/").replace(/\/+$/g,"");return r||(r="/"),r=r.replace(/^([A-Z]):\//,(t,n)=>`${n.toLowerCase()}:/`),r}function qe(e){const r=e.split("/").filter(Boolean);return r[r.length-1]??"project"}function Ze(e){return e.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,ke).replace(/-+$/g,"")||"project"}function g(e){if(!e||/[\r\n\0]/.test(e))return null;const r=$(e)?e:z(e);return $(r)?r:null}function u(e,r,t=!1){return{command:e,args:r,preview:[e,...r.map(G)].join(" "),safeUserScope:!0,...t?{manualOnly:!0}:{}}}function er(e){const r=ie(e.command,[...e.args],{stdio:"ignore",shell:!1});return{ok:r.status===0,code:r.status,signal:r.signal,reasonCode:r.status===0?i.OK:i.SCHEDULER_COMMAND_FAILED}}function te(e,r){const t=r.PATH??process.env.PATH??"",n=(r.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean),s=t.split(he).filter(Boolean);for(const a of s){const o=c(a,e);if(j(o))return!0;for(const d of n)if(j(c(a,`${e}${d.toLowerCase()}`))||j(c(a,`${e}${d.toUpperCase()}`)))return!0}return!1}function ne(e,r){const t=S([...e.blockers,...r]);return{...e,safeToInstall:t.length===0,blockers:t,reasonCodes:S([...e.reasonCodes,...t])}}function se(e){return ae(e,!0)}function rr(e){return ae(e,!1)}function ae(e,r){const t=e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/%/g,r?"%%":"%");return/[\s"'\\]/.test(e)?`"${t}"`:t}function oe(e){return Array.from(e,r=>/^[A-Za-z0-9_./:@+=,-]$/.test(r)?r:r==="%"?"%%":Array.from(le.from(r,"utf8"),t=>`\\x${t.toString(16).padStart(2,"0")}`).join("")).join("")}function G(e){return/^[A-Za-z0-9_./:=@%+-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}function ce(e){return/[\s"]/.test(e)?`"${e.replace(/"/g,'\\"')}"`:e}function C(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function tr(e,r,t){return Number.isFinite(e)?Math.max(r,Math.min(t,Math.floor(e))):r}function S(e){return Array.from(new Set(e))}export{R as RUNNER_SCHEDULER_BOOTSTRAP_REASON_CODES,i as SCHEDULER_REASON_CODES,ir as __resetRunnerSchedulerBootstrapCacheForTests,K as createRunnerSchedulerIdentity,_e as detectSchedulerCapability,dr as ensureRunnerSchedulerBootstrap,Te as renderSchedulerManifests,J as runRunnerSchedulerCommand};
@@ -1,3 +1,3 @@
1
- import{existsSync as C,mkdirSync as A,readFileSync as N,renameSync as $,writeFileSync as O,copyFileSync as I}from"node:fs";import{join as b}from"node:path";import{randomBytes as R}from"node:crypto";class g extends Error{reasonCode;constructor(t,s){super(t),this.reasonCode=s,this.name="StateRepairHardStopError"}}function u(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function h(){return new Date().toISOString()}function E(){return h().replace(/[:.]/g,"-")}function w(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.length>0):[]}const x="pr_merged_issue_closed_reconciled";function m(e){return typeof e=="string"?e.trim().toLowerCase().replace(/[_\s]+/g,"-"):""}function _(e,t){const s=e[t];return u(s)?s:null}function P(e){const t=_(e,"issueCloseAudit")??_(e,"issue_close_audit");if(t){const o=m(t.event).replace(/-/g,"_"),d=t.publicSafe===!0||t.public_safe===!0,p=t.rawLogStorage==="forbidden"||t.raw_log_storage==="forbidden";if(o==="story_issue_closed"&&d&&p)return!0}const s=_(e,"completionEvidence")??_(e,"completion_evidence"),n=m(s?.issueState??s?.issue_state??s?.state);return e.issue_closed===!0||m(e.issue_state??e.issueState??e.workflow_issue_state)==="closed"||n==="closed"}function k(e){const t=_(e,"completionEvidence")??_(e,"completion_evidence"),s=_(e,"scopedCiEvidence")??_(e,"scoped_ci_evidence"),n=[e.physicalMergeStatus,e.pr_state,e.prState,e.pull_request_state,e.pullRequestState,t?.prState,t?.pr_state,t?.pullRequestState,s?.prState].map(m);return e.merged===!0||n.includes("merged")||m(s?.finalState)==="can-merge"&&e.merged===!0}function M(e){const t=_(e,"completionEvidence")??_(e,"completion_evidence"),s=[e.pr_state,e.prState,e.pull_request_state,e.pullRequestState,t?.prState,t?.pr_state,t?.pullRequestState].map(m),n=k(e),o=["denied-external-gate","denied-local-or-repo","not-attempted"].includes(m(e.physicalMergeStatus)),d=s.includes("closed")||s.includes("closed-unmerged");return n&&(e.merged===!1||o||d)||e.merged===!0&&o}function z(e,t,s){const n=`state-completion-reconciliation:${j(t)}`,o=e.filter(u).map(r=>({...r})),d={id:n,status:"open",reason:"stale_state_completion_evidence_observed",reason_codes:[x],category:"state/completion-reconciliation",story_id:j(t),public_safe:!0,raw_log_storage:"forbidden",created_at:s,last_seen_at:s,occurrences:1},p=o.findIndex(r=>r.id===n);if(p<0)return[...o,d];const i=o[p];return o[p]={...i,...d,created_at:typeof i.created_at=="string"?i.created_at:s,occurrences:Math.max(1,typeof i.occurrences=="number"?i.occurrences:1)+1},o}function J(e,t,s){const n=u(e.stories)?e.stories:null;if(!n)return;const o=[],d=h();for(const[p,i]of Object.entries(n)){if(!u(i))continue;const r=m(i.status);if(M(i))throw new g(`[Neocortex] state.json repair stopped: story "${p}" has conflicting PR merge completion evidence. Resolve .neocortex/state.json manually before invoking Neocortex.`,"conflicting_completion_evidence");if(r!=="pr-reviewed"||!k(i)||!P(i))continue;const a=typeof i.status=="string"?i.status:r,l=w(i.steps_completed);i.status="done",i.last_step="step-c-12-merge-pr",i.steps_completed=Array.from(new Set([...l,"step-c-12-merge-pr"])),i.merged=!0,i.physicalMergeStatus="merged",i.completion_reconciled_at=d,t.push(`reconciled completion evidence for story ${p}`),s.push(x),o.push({schemaVersion:1,publicSafe:!0,rawLogStorage:"forbidden",storyId:j(p),previousStatus:a,nextStatus:"done",reasonCodes:[x],reconciledAt:d}),e.state_repair_debt=z(Array.isArray(e.state_repair_debt)?e.state_repair_debt:[],p,d)}o.length>0&&(e.state_completion_reconciliations=[...Array.isArray(e.state_completion_reconciliations)?e.state_completion_reconciliations.filter(u):[],...o])}function L(e,t,s){const n=s[e];if(!u(n))return;const o=n.epic_id;if(typeof o=="string"&&o!==t)throw new g(`[Neocortex] state.json repair stopped: story "${e}" belongs to epic "${o}" but legacy planning maps it to "${t}". Resolve the conflicting IDs in .neocortex/state.json, then rerun the command.`,"conflicting_story_epic_id")}function q(e){if(Array.isArray(e.stories))throw new g("[Neocortex] state.json repair stopped: `stories` is an Array. Convert it to an object keyed by story ID or run `*migrate-state --preview` for guidance.","stories_array_ambiguous");if(u(e.epics)){for(const[r,a]of Object.entries(e.epics))if(u(a)&&a.stories!==void 0&&!Array.isArray(a.stories))throw new g(`[Neocortex] state.json repair stopped: epic "${r}" has non-array \`stories\`. Repair this ambiguous shape manually before invoking Neocortex.`,"epic_stories_not_array")}if(e.schema_version!==void 0&&e.schema_version!==1)throw new g(`[Neocortex] state.json repair stopped: schema_version=${String(e.schema_version)} is not a safe automatic downgrade target. Run \`*migrate-state --preview\` or repair the schema version manually.`,"unsupported_schema_version");const t=JSON.parse(JSON.stringify(e)),s=[],n=[];u(t.epics)||(t.epics={},s.push("initialized epics{}"),n.push("initialized_epics_object")),u(t.stories)||(t.stories={},s.push("initialized stories{}"),n.push("initialized_stories_object"));const o=t.epics,d=t.stories,p=u(t.planning)?t.planning:null;if(p&&u(p.current)){const r=p.current,a=typeof r.epic_id=="string"?r.epic_id:null;if(!a)throw new g("[Neocortex] state.json repair stopped: legacy planning.current has no epic_id. Add the missing epic_id or run `*migrate-state --preview`.","planning_current_missing_epic_id");const l=Array.isArray(r.stories)?r.stories:[],y=l.map(c=>u(c)&&typeof c.id=="string"?c.id:typeof c=="string"?c:null).filter(c=>!!c);for(const c of y)L(c,a,d);u(o[a])||(o[a]={id:a,title:typeof r.title=="string"?r.title:`Epic ${a}`,status:r.status==="done"?"done":"in-progress",stories:y,created_at:typeof r.created_at=="string"?r.created_at:h(),completed_at:typeof r.completed_at=="string"?r.completed_at:null,completed_stories:typeof r.completed_stories=="number"?r.completed_stories:0,total_stories:typeof r.total_stories=="number"?r.total_stories:y.length,source:"client-auto-repair-P156.05"},s.push(`migrated planning.current to epics["${a}"]`),n.push("legacy_planning_current_migrated"));for(const c of l)!u(c)||typeof c.id!="string"||u(d[c.id])||(d[c.id]={...c,id:c.id,epic_id:a,title:typeof c.title=="string"?c.title:c.id,status:typeof c.status=="string"?c.status:"backlog",depends_on:w(c.depends_on),created_at:typeof c.created_at=="string"?c.created_at:h()},s.push(`migrated embedded story ${c.id}`),n.push("legacy_planning_story_migrated"));const f=typeof r.status=="string"?r.status.trim().toLowerCase().replace(/[_\s]+/g,"-"):"",S=new Set(["epic_id","title","status","created_at","updated_at","completed_at","completed_stories","total_stories","stories"]),v=Object.keys(r).filter(c=>!S.has(c));f==="generated"&&v.length===0?(delete p.current,s.push("removed safe legacy planning.current generated container"),n.push("legacy_planning_current_generated_removed")):v.length>0&&(s.push(`preserved planning.current unknown keys: ${v.sort().join(", ")}`),n.push("unknown_planning_current_keys_preserved"))}if(p&&Array.isArray(p.history)){let r=!0;const a=new Set(["epic_id","title","status","created_at","completed_at","completed_stories","total_stories","stories"]);for(const l of p.history){if(!u(l)){r=!1;continue}Object.keys(l).filter(S=>!a.has(S)).length>0&&(r=!1);const f=typeof l.epic_id=="string"?l.epic_id:null;if(!f){r=!1;continue}u(o[f])||(o[f]={id:f,title:typeof l.title=="string"?l.title:`Epic ${f}`,status:"done",stories:w(l.stories),created_at:typeof l.created_at=="string"?l.created_at:h(),completed_at:typeof l.completed_at=="string"?l.completed_at:h(),completed_stories:typeof l.completed_stories=="number"?l.completed_stories:0,total_stories:typeof l.total_stories=="number"?l.total_stories:0,source:"client-auto-repair-P156.05"},s.push(`migrated planning.history to epics["${f}"]`),n.push("legacy_planning_history_migrated"))}r?(delete p.history,s.push("removed safe legacy planning.history container"),n.push("legacy_planning_history_removed")):(s.push("preserved planning.history because one or more entries were not safely removable"),n.push("legacy_planning_history_preserved"))}p&&Object.keys(p).length===0&&(delete t.planning,s.push("removed empty planning container"),n.push("empty_planning_removed")),t.schema_version!==1&&(t.schema_version=1,s.push("set schema_version=1"),n.push("schema_version_added")),J(t,s,n);const i=JSON.stringify(t)!==JSON.stringify(e);if(i){const r=h(),a=Array.from(new Set(n));t.last_updated=r,t.state_migration_repairs=[...Array.isArray(t.state_migration_repairs)?t.state_migration_repairs:[],{schemaVersion:1,action:"client_auto_repair",reasonCodes:a,repairedAt:r}],t.state_repair_debt=D(Array.isArray(t.state_repair_debt)?t.state_repair_debt:[],a,r)}return{mutated:i,state:t,reasonCodes:Array.from(new Set(n)),changes:s}}function D(e,t,s){const n=Array.from(new Set(t.map(K).filter(Boolean))).sort(),o=`state-drift-repair:${n.join("+")||"unknown"}`,d=e.filter(u).map(a=>({...a})),p={id:o,status:"open",reason:"state_json_drift_repaired",reason_codes:n,category:"state/drift-repair",created_at:s,last_seen_at:s,occurrences:1},i=d.findIndex(a=>a.id===o);if(i<0)return[...d,p];const r=d[i];return d[i]={...r,...p,created_at:typeof r.created_at=="string"?r.created_at:s,occurrences:Math.max(1,typeof r.occurrences=="number"?r.occurrences:1)+1},d}function K(e){return e.replace(/\b(sk|ghp|gho|github_pat|xoxb|AKIA)[A-Za-z0-9_-]{8,}\b/g,"[redacted]").replace(/(password|passwd|secret|token|api[_-]?key)\s*[:=]\s*[^,\s)]+/gi,"$1=[redacted]").replace(/https?:\/\/[^\s)]+/gi,"[url-redacted]").replace(/[^a-z0-9_+-]+/gi,"_").replace(/^_+|_+$/g,"").slice(0,120)}function j(e){return e.replace(/[^a-z0-9_.:-]+/gi,"_").replace(/^_+|_+$/g,"").slice(0,120)||"unknown"}function T(e){const t=b(e,".neocortex"),s=b(t,"state.json");if(!C(s))return{repaired:!1,reasonCodes:[],changes:[]};let n;try{n=JSON.parse(N(s,"utf8"))}catch(a){const l=a instanceof Error?a.message:String(a);throw new g(`[Neocortex] state.json repair stopped: invalid JSON in .neocortex/state.json (${l}). No files were overwritten. Fix the JSON or restore a backup, then rerun.`,"invalid_json")}if(!u(n))throw new g("[Neocortex] state.json repair stopped: top-level state must be a JSON object. Restore a valid .neocortex/state.json before invoking Neocortex.","state_not_object");const o=q(n);if(!o.mutated)return{repaired:!1,reasonCodes:[],changes:[]};A(t,{recursive:!0});const d=E(),p=b(t,`state.json.backup-${d}`),i=b(t,`state.json.tmp.${R(6).toString("hex")}`);I(s,p),O(i,`${JSON.stringify(o.state,null,2)}
2
- `,"utf8"),$(i,s);const r=`.neocortex/state.json.backup-${d}`;return process.stderr.write(`[Neocortex P156.05] state.json auto-repaired before invoke; backup=${r}; reasonCodes=${o.reasonCodes.join(",")}; changes=${o.changes.join("; ")}
3
- `),{repaired:!0,reasonCodes:o.reasonCodes,backupPath:r,changes:o.changes}}export{g as StateRepairHardStopError,T as maybeRepairStateJsonBeforeInvoke};
1
+ import{existsSync as A,mkdirSync as C,readFileSync as N,renameSync as O,writeFileSync as $,copyFileSync as I}from"node:fs";import{join as b}from"node:path";import{randomBytes as R}from"node:crypto";class g extends Error{reasonCode;constructor(t,s){super(t),this.reasonCode=s,this.name="StateRepairHardStopError"}}function u(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function h(){return new Date().toISOString()}function E(){return h().replace(/[:.]/g,"-")}function k(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.length>0):[]}const j="pr_merged_issue_closed_reconciled",P="invalid_workflow_issue_removed";function m(e){return typeof e=="string"?e.trim().toLowerCase().replace(/[_\s]+/g,"-"):""}function _(e,t){const s=e[t];return u(s)?s:null}function M(e){const t=_(e,"issueCloseAudit")??_(e,"issue_close_audit");if(t){const o=m(t.event).replace(/-/g,"_"),a=t.publicSafe===!0||t.public_safe===!0,l=t.rawLogStorage==="forbidden"||t.raw_log_storage==="forbidden";if(o==="story_issue_closed"&&a&&l)return!0}const s=_(e,"completionEvidence")??_(e,"completion_evidence"),n=m(s?.issueState??s?.issue_state??s?.state);return e.issue_closed===!0||m(e.issue_state??e.issueState??e.workflow_issue_state)==="closed"||n==="closed"}function x(e){const t=_(e,"completionEvidence")??_(e,"completion_evidence"),s=_(e,"scopedCiEvidence")??_(e,"scoped_ci_evidence"),n=[e.physicalMergeStatus,e.pr_state,e.prState,e.pull_request_state,e.pullRequestState,t?.prState,t?.pr_state,t?.pullRequestState,s?.prState].map(m);return e.merged===!0||n.includes("merged")||m(s?.finalState)==="can-merge"&&e.merged===!0}function z(e){const t=_(e,"completionEvidence")??_(e,"completion_evidence"),s=[e.pr_state,e.prState,e.pull_request_state,e.pullRequestState,t?.prState,t?.pr_state,t?.pullRequestState].map(m),n=x(e),o=["denied-external-gate","denied-local-or-repo","not-attempted"].includes(m(e.physicalMergeStatus)),a=s.includes("closed")||s.includes("closed-unmerged");return n&&(e.merged===!1||o||a)||e.merged===!0&&o}function J(e,t,s){const n=`state-completion-reconciliation:${w(t)}`,o=e.filter(u).map(r=>({...r})),a={id:n,status:"open",reason:"stale_state_completion_evidence_observed",reason_codes:[j],category:"state/completion-reconciliation",story_id:w(t),public_safe:!0,raw_log_storage:"forbidden",created_at:s,last_seen_at:s,occurrences:1},l=o.findIndex(r=>r.id===n);if(l<0)return[...o,a];const i=o[l];return o[l]={...i,...a,created_at:typeof i.created_at=="string"?i.created_at:s,occurrences:Math.max(1,typeof i.occurrences=="number"?i.occurrences:1)+1},o}function L(e,t,s){const n=u(e.stories)?e.stories:null;if(!n)return;const o=[],a=h();for(const[l,i]of Object.entries(n)){if(!u(i))continue;const r=m(i.status);if(z(i))throw new g(`[Neocortex] state.json repair stopped: story "${l}" has conflicting PR merge completion evidence. Resolve .neocortex/state.json manually before invoking Neocortex.`,"conflicting_completion_evidence");if(r!=="pr-reviewed"||!x(i)||!M(i))continue;const c=typeof i.status=="string"?i.status:r,d=k(i.steps_completed);i.status="done",i.last_step="step-c-12-merge-pr",i.steps_completed=Array.from(new Set([...d,"step-c-12-merge-pr"])),i.merged=!0,i.physicalMergeStatus="merged",i.completion_reconciled_at=a,t.push(`reconciled completion evidence for story ${l}`),s.push(j),o.push({schemaVersion:1,publicSafe:!0,rawLogStorage:"forbidden",storyId:w(l),previousStatus:c,nextStatus:"done",reasonCodes:[j],reconciledAt:a}),e.state_repair_debt=J(Array.isArray(e.state_repair_debt)?e.state_repair_debt:[],l,a)}o.length>0&&(e.state_completion_reconciliations=[...Array.isArray(e.state_completion_reconciliations)?e.state_completion_reconciliations.filter(u):[],...o])}function q(e,t,s){const n=u(e.stories)?e.stories:null;if(n)for(const[o,a]of Object.entries(n))!u(a)||!Object.prototype.hasOwnProperty.call(a,"workflow_issue")||typeof a.workflow_issue=="number"&&Number.isFinite(a.workflow_issue)||(delete a.workflow_issue,t.push(`removed invalid workflow_issue from story ${w(o)}`),s.push(P))}function D(e,t,s){const n=s[e];if(!u(n))return;const o=n.epic_id;if(typeof o=="string"&&o!==t)throw new g(`[Neocortex] state.json repair stopped: story "${e}" belongs to epic "${o}" but legacy planning maps it to "${t}". Resolve the conflicting IDs in .neocortex/state.json, then rerun the command.`,"conflicting_story_epic_id")}function F(e){if(Array.isArray(e.stories))throw new g("[Neocortex] state.json repair stopped: `stories` is an Array. Convert it to an object keyed by story ID or run `*migrate-state --preview` for guidance.","stories_array_ambiguous");if(u(e.epics)){for(const[r,c]of Object.entries(e.epics))if(u(c)&&c.stories!==void 0&&!Array.isArray(c.stories))throw new g(`[Neocortex] state.json repair stopped: epic "${r}" has non-array \`stories\`. Repair this ambiguous shape manually before invoking Neocortex.`,"epic_stories_not_array")}if(e.schema_version!==void 0&&e.schema_version!==1)throw new g(`[Neocortex] state.json repair stopped: schema_version=${String(e.schema_version)} is not a safe automatic downgrade target. Run \`*migrate-state --preview\` or repair the schema version manually.`,"unsupported_schema_version");const t=JSON.parse(JSON.stringify(e)),s=[],n=[];u(t.epics)||(t.epics={},s.push("initialized epics{}"),n.push("initialized_epics_object")),u(t.stories)||(t.stories={},s.push("initialized stories{}"),n.push("initialized_stories_object"));const o=t.epics,a=t.stories,l=u(t.planning)?t.planning:null;if(l&&u(l.current)){const r=l.current,c=typeof r.epic_id=="string"?r.epic_id:null;if(!c)throw new g("[Neocortex] state.json repair stopped: legacy planning.current has no epic_id. Add the missing epic_id or run `*migrate-state --preview`.","planning_current_missing_epic_id");const d=Array.isArray(r.stories)?r.stories:[],y=d.map(p=>u(p)&&typeof p.id=="string"?p.id:typeof p=="string"?p:null).filter(p=>!!p);for(const p of y)D(p,c,a);u(o[c])||(o[c]={id:c,title:typeof r.title=="string"?r.title:`Epic ${c}`,status:r.status==="done"?"done":"in-progress",stories:y,created_at:typeof r.created_at=="string"?r.created_at:h(),completed_at:typeof r.completed_at=="string"?r.completed_at:null,completed_stories:typeof r.completed_stories=="number"?r.completed_stories:0,total_stories:typeof r.total_stories=="number"?r.total_stories:y.length,source:"client-auto-repair-P156.05"},s.push(`migrated planning.current to epics["${c}"]`),n.push("legacy_planning_current_migrated"));for(const p of d)!u(p)||typeof p.id!="string"||u(a[p.id])||(a[p.id]={...p,id:p.id,epic_id:c,title:typeof p.title=="string"?p.title:p.id,status:typeof p.status=="string"?p.status:"backlog",depends_on:k(p.depends_on),created_at:typeof p.created_at=="string"?p.created_at:h()},s.push(`migrated embedded story ${p.id}`),n.push("legacy_planning_story_migrated"));const f=typeof r.status=="string"?r.status.trim().toLowerCase().replace(/[_\s]+/g,"-"):"",S=new Set(["epic_id","title","status","created_at","updated_at","completed_at","completed_stories","total_stories","stories"]),v=Object.keys(r).filter(p=>!S.has(p));f==="generated"&&v.length===0?(delete l.current,s.push("removed safe legacy planning.current generated container"),n.push("legacy_planning_current_generated_removed")):v.length>0&&(s.push(`preserved planning.current unknown keys: ${v.sort().join(", ")}`),n.push("unknown_planning_current_keys_preserved"))}if(l&&Array.isArray(l.history)){let r=!0;const c=new Set(["epic_id","title","status","created_at","completed_at","completed_stories","total_stories","stories"]);for(const d of l.history){if(!u(d)){r=!1;continue}Object.keys(d).filter(S=>!c.has(S)).length>0&&(r=!1);const f=typeof d.epic_id=="string"?d.epic_id:null;if(!f){r=!1;continue}u(o[f])||(o[f]={id:f,title:typeof d.title=="string"?d.title:`Epic ${f}`,status:"done",stories:k(d.stories),created_at:typeof d.created_at=="string"?d.created_at:h(),completed_at:typeof d.completed_at=="string"?d.completed_at:h(),completed_stories:typeof d.completed_stories=="number"?d.completed_stories:0,total_stories:typeof d.total_stories=="number"?d.total_stories:0,source:"client-auto-repair-P156.05"},s.push(`migrated planning.history to epics["${f}"]`),n.push("legacy_planning_history_migrated"))}r?(delete l.history,s.push("removed safe legacy planning.history container"),n.push("legacy_planning_history_removed")):(s.push("preserved planning.history because one or more entries were not safely removable"),n.push("legacy_planning_history_preserved"))}l&&Object.keys(l).length===0&&(delete t.planning,s.push("removed empty planning container"),n.push("empty_planning_removed")),t.schema_version!==1&&(t.schema_version=1,s.push("set schema_version=1"),n.push("schema_version_added")),q(t,s,n),L(t,s,n);const i=JSON.stringify(t)!==JSON.stringify(e);if(i){const r=h(),c=Array.from(new Set(n));t.last_updated=r,t.state_migration_repairs=[...Array.isArray(t.state_migration_repairs)?t.state_migration_repairs:[],{schemaVersion:1,action:"client_auto_repair",reasonCodes:c,repairedAt:r}],t.state_repair_debt=K(Array.isArray(t.state_repair_debt)?t.state_repair_debt:[],c,r)}return{mutated:i,state:t,reasonCodes:Array.from(new Set(n)),changes:s}}function K(e,t,s){const n=Array.from(new Set(t.map(B).filter(Boolean))).sort(),o=`state-drift-repair:${n.join("+")||"unknown"}`,a=e.filter(u).map(c=>({...c})),l={id:o,status:"open",reason:"state_json_drift_repaired",reason_codes:n,category:"state/drift-repair",created_at:s,last_seen_at:s,occurrences:1},i=a.findIndex(c=>c.id===o);if(i<0)return[...a,l];const r=a[i];return a[i]={...r,...l,created_at:typeof r.created_at=="string"?r.created_at:s,occurrences:Math.max(1,typeof r.occurrences=="number"?r.occurrences:1)+1},a}function B(e){return e.replace(/\b(sk|ghp|gho|github_pat|xoxb|AKIA)[A-Za-z0-9_-]{8,}\b/g,"[redacted]").replace(/(password|passwd|secret|token|api[_-]?key)\s*[:=]\s*[^,\s)]+/gi,"$1=[redacted]").replace(/https?:\/\/[^\s)]+/gi,"[url-redacted]").replace(/[^a-z0-9_+-]+/gi,"_").replace(/^_+|_+$/g,"").slice(0,120)}function w(e){return e.replace(/[^a-z0-9_.:-]+/gi,"_").replace(/^_+|_+$/g,"").slice(0,120)||"unknown"}function V(e){const t=b(e,".neocortex"),s=b(t,"state.json");if(!A(s))return{repaired:!1,reasonCodes:[],changes:[]};let n;try{n=JSON.parse(N(s,"utf8"))}catch(c){const d=c instanceof Error?c.message:String(c);throw new g(`[Neocortex] state.json repair stopped: invalid JSON in .neocortex/state.json (${d}). No files were overwritten. Fix the JSON or restore a backup, then rerun.`,"invalid_json")}if(!u(n))throw new g("[Neocortex] state.json repair stopped: top-level state must be a JSON object. Restore a valid .neocortex/state.json before invoking Neocortex.","state_not_object");const o=F(n);if(!o.mutated)return{repaired:!1,reasonCodes:[],changes:[]};C(t,{recursive:!0});const a=E(),l=b(t,`state.json.backup-${a}`),i=b(t,`state.json.tmp.${R(6).toString("hex")}`);I(s,l),$(i,`${JSON.stringify(o.state,null,2)}
2
+ `,"utf8"),O(i,s);const r=`.neocortex/state.json.backup-${a}`;return process.stderr.write(`[Neocortex P156.05] state.json auto-repaired before invoke; backup=${r}; reasonCodes=${o.reasonCodes.join(",")}; changes=${o.changes.join("; ")}
3
+ `),{repaired:!0,reasonCodes:o.reasonCodes,backupPath:r,changes:o.changes}}export{g as StateRepairHardStopError,V as maybeRepairStateJsonBeforeInvoke};
@@ -1,4 +1,4 @@
1
- # 🧠 Neocortex v4.59.3 | OrNexus Team
1
+ # 🧠 Neocortex v4.59.4 | 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.59.3 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.59.4 | 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.59.3'
7
+ version: '4.59.4'
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.59.3 | OrNexus Team"
3
+ description: "🧠 Neocortex Root Agent v4.59.4 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  tools:
@@ -103,7 +103,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
103
103
  ┌────────────────────────────────────────────────────────────┐
104
104
  │ │
105
105
  │ ####### N E O C O R T E X │
106
- │ ### ######## v4.59.3
106
+ │ ### ######## v4.59.4
107
107
  │ ######### ##### │
108
108
  │ ## ############## Development Orchestrator │
109
109
  │ ## ### ###### ## OrNexus Team │
@@ -4,7 +4,7 @@ agent:
4
4
  name: 'Neocortex'
5
5
  title: 'Development Orchestrator'
6
6
  icon: '>'
7
- version: '4.59.3'
7
+ version: '4.59.4'
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.59.3 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.59.4 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  tools:
@@ -97,7 +97,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
97
97
  ┌────────────────────────────────────────────────────────────┐
98
98
  │ │
99
99
  │ ####### N E O C O R T E X │
100
- │ ### ######## v4.59.3
100
+ │ ### ######## v4.59.4
101
101
  │ ######### ##### │
102
102
  │ ## ############## Development Orchestrator │
103
103
  │ ## ### ###### ## OrNexus Team │
@@ -23,7 +23,7 @@ Codex built-in commands or actions.
23
23
 
24
24
  <!-- END: Plugin Conflict Prevention -->
25
25
 
26
- # Neocortex v4.59.3 | OrNexus Team
26
+ # Neocortex v4.59.4 | OrNexus Team
27
27
 
28
28
  You are a Development Orchestrator. All orchestration logic is delivered by the remote Neocortex server.
29
29
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.59.3 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.59.4 | OrNexus Team"
4
4
  model: fast
5
5
  readonly: false
6
6
  is_background: false
@@ -43,7 +43,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
43
43
  ┌────────────────────────────────────────────────────────────┐
44
44
  │ │
45
45
  │ ####### N E O C O R T E X │
46
- │ ### ######## v4.59.3
46
+ │ ### ######## v4.59.4
47
47
  │ ######### ##### │
48
48
  │ ## ############## Development Orchestrator │
49
49
  │ ## ### ###### ## OrNexus Team │
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.59.3 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.59.4 | OrNexus Team"
4
4
  kind: local
5
5
  tools:
6
6
  # File operations (Gemini CLI built-ins)
@@ -60,7 +60,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
60
60
  ┌────────────────────────────────────────────────────────────┐
61
61
  │ │
62
62
  │ ####### N E O C O R T E X │
63
- │ ### ######## v4.59.3
63
+ │ ### ######## v4.59.4
64
64
  │ ######### ##### │
65
65
  │ ## ############## Development Orchestrator │
66
66
  │ ## ### ###### ## OrNexus Team │
@@ -47,7 +47,7 @@ explicit server opt-in rather than a local assumption.
47
47
  ┌────────────────────────────────────────────────────────────┐
48
48
  │ │
49
49
  │ ####### N E O C O R T E X │
50
- │ ### ######## v4.59.3
50
+ │ ### ######## v4.59.4
51
51
  │ ######### ##### │
52
52
  │ ## ############## Development Orchestrator │
53
53
  │ ## ### ###### ## OrNexus Team │
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "neocortex"
3
- description: "Neocortex v4.59.3 | OrNexus Team"
3
+ description: "Neocortex v4.59.4 | OrNexus Team"
4
4
  tools:
5
5
  # Read / Edit (built-in tool sets)
6
6
  - read
@@ -61,7 +61,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
61
61
  ┌────────────────────────────────────────────────────────────┐
62
62
  │ │
63
63
  │ ####### N E O C O R T E X │
64
- │ ### ######## v4.59.3
64
+ │ ### ######## v4.59.4
65
65
  │ ######### ##### │
66
66
  │ ## ############## Development Orchestrator │
67
67
  │ ## ### ###### ## OrNexus Team │