@ornexus/neocortex 4.60.18 → 4.60.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/sbom.cdx.json +6504 -6410
  2. package/docs/install/installer-diagnostics.md +52 -0
  3. package/install.ps1 +1 -1
  4. package/install.sh +1 -1
  5. package/package.json +27 -4
  6. package/packages/client/dist/agent/refresh-stubs.d.ts +7 -0
  7. package/packages/client/dist/agent/refresh-stubs.js +2 -2
  8. package/packages/client/dist/cache/encrypted-cache.d.ts +3 -0
  9. package/packages/client/dist/cache/encrypted-cache.js +1 -1
  10. package/packages/client/dist/checkpoint/checkpoint-client-reader.js +2 -2
  11. package/packages/client/dist/cli.js +3 -3
  12. package/packages/client/dist/commands/activate.js +7 -7
  13. package/packages/client/dist/commands/config.js +1 -1
  14. package/packages/client/dist/commands/invoke.d.ts +64 -0
  15. package/packages/client/dist/commands/invoke.js +54 -47
  16. package/packages/client/dist/config/secure-config.d.ts +9 -3
  17. package/packages/client/dist/config/secure-config.js +8 -8
  18. package/packages/client/dist/config.d.ts +1 -1
  19. package/packages/client/dist/config.js +1 -1
  20. package/packages/client/dist/continuity/continuity-client-state-store.d.ts +1 -0
  21. package/packages/client/dist/continuity/continuity-client-state-store.js +1 -1
  22. package/packages/client/dist/continuity/invoke-hooks.d.ts +2 -1
  23. package/packages/client/dist/continuity/invoke-hooks.js +1 -1
  24. package/packages/client/dist/continuity/sqlite-store.d.ts +21 -0
  25. package/packages/client/dist/continuity/sqlite-store.js +49 -49
  26. package/packages/client/dist/effects/invoke-effect-gateways.d.ts +22 -0
  27. package/packages/client/dist/effects/invoke-effect-gateways.js +1 -0
  28. package/packages/client/dist/errors/frontmatter-diagnostics.d.ts +20 -0
  29. package/packages/client/dist/errors/frontmatter-diagnostics.js +1 -0
  30. package/packages/client/dist/generated/command-registry.generated.d.ts +2836 -0
  31. package/packages/client/dist/generated/command-registry.generated.js +1 -0
  32. package/packages/client/dist/graph-retrieval/pre-command-hook.d.ts +2 -0
  33. package/packages/client/dist/graph-retrieval/pre-command-hook.js +1 -1
  34. package/packages/client/dist/index.d.ts +1 -0
  35. package/packages/client/dist/index.js +1 -1
  36. package/packages/client/dist/license/license-client.d.ts +3 -0
  37. package/packages/client/dist/license/license-client.js +1 -1
  38. package/packages/client/dist/machine/fingerprint.d.ts +3 -1
  39. package/packages/client/dist/machine/fingerprint.js +2 -2
  40. package/packages/client/dist/memory/project-memory-writer.js +19 -15
  41. package/packages/client/dist/{subagent-approval-policy.d.ts → policy/subagent-approval-policy.d.ts} +8 -3
  42. package/packages/client/dist/policy/subagent-approval-policy.js +1 -0
  43. package/packages/client/dist/resolvers/local-resolver.d.ts +3 -0
  44. package/packages/client/dist/resolvers/local-resolver.js +4 -4
  45. package/packages/client/dist/runner/cli.d.ts +1 -0
  46. package/packages/client/dist/runner/cli.js +1 -1
  47. package/packages/client/dist/runner/headless/prepared-story-bundle.d.ts +20 -0
  48. package/packages/client/dist/runner/headless/prepared-story-bundle.js +1 -0
  49. package/packages/client/dist/runner/headless/run-yoloop.d.ts +2 -0
  50. package/packages/client/dist/runner/headless/run-yoloop.js +1 -1
  51. package/packages/client/dist/runner/portal-sync-worker.js +1 -1
  52. package/packages/client/dist/runner/scheduler.d.ts +3 -0
  53. package/packages/client/dist/runner/scheduler.js +7 -7
  54. package/packages/client/dist/state/project-state-snapshot.js +1 -1
  55. package/packages/client/dist/tier/tier-aware-client.js +1 -1
  56. package/packages/client/dist/version.d.ts +3 -0
  57. package/packages/client/dist/version.js +1 -0
  58. package/packages/client/dist/yoloop/discovery-hook.js +2 -2
  59. package/packages/client/dist/yoloop/invoke-hooks.js +4 -4
  60. package/packages/client/dist/yoloop/shared-discover-epics.d.ts +9 -3
  61. package/packages/client/dist/yoloop/shared-discover-epics.js +1 -1
  62. package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +24 -0
  63. package/packages/client/dist/yoloop/target-normalization.d.ts +24 -0
  64. package/packages/client/dist/yoloop/target-normalization.js +1 -0
  65. package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +4 -0
  66. package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -1
  67. package/packages/shared/dist/command-registry-contract.js +382 -0
  68. package/packages/shared/dist/generated/command-registry.generated.js +4216 -0
  69. package/packages/shared/dist/generated/invocation-schema.generated.js +1850 -0
  70. package/packages/shared/dist/invocation/index.d.ts +175 -0
  71. package/packages/shared/dist/invocation/index.js +587 -0
  72. package/packages/shared/dist/nx-invoke-signature.js +233 -0
  73. package/packages/shared/dist/strict-readonly.js +381 -0
  74. package/packages/shared/dist/yoloop/wave-decision-receipt.js +77 -0
  75. package/targets-stubs/antigravity/gemini.md +1 -1
  76. package/targets-stubs/antigravity/skill/SKILL.md +1 -1
  77. package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
  78. package/targets-stubs/claude-code/neocortex-root.md +5 -2
  79. package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
  80. package/targets-stubs/claude-code/neocortex.md +7 -2
  81. package/targets-stubs/codex/AGENTS.md +4 -1
  82. package/targets-stubs/codex/neocortex.toml +4 -0
  83. package/targets-stubs/cursor/agent.md +2 -2
  84. package/targets-stubs/gemini-cli/agent.md +2 -2
  85. package/targets-stubs/opencode/neocortex-root.md +4 -1
  86. package/targets-stubs/opencode/neocortex.md +3 -0
  87. package/targets-stubs/vscode/neocortex.agent.md +2 -2
  88. package/packages/client/dist/subagent-approval-policy.js +0 -1
@@ -9,6 +9,58 @@ reason codes and bounded metadata only. Do not attach raw npm lifecycle logs,
9
9
  third-party onboarding output, private local paths, tokens, license keys or
10
10
  customer data to support issues.
11
11
 
12
+ ## Codex local activation diagnostics
13
+
14
+ Codex Neocortex invocations require trusted local access to the activation state
15
+ under `~/.neocortex`. When the client detects that a Codex profile or sandbox
16
+ cannot access or use that local state, it reports public error code
17
+ `CODEX_AUTH_SANDBOX` instead of asking the user to paste activation material into
18
+ a prompt or repository file.
19
+
20
+ Safe operator response:
21
+
22
+ 1. Retry from `codex --profile neocortex-local`, Codex App **Full Access** /
23
+ trusted-local mode, or a local terminal with the same activated user account.
24
+ 2. Share only the bounded error code, reason code and public path label such as
25
+ `~/.neocortex`, `~/.neocortex/config.json` or `~/.neocortex/cache`.
26
+ 3. Do not share raw auth logs, absolute home paths, machine fingerprints,
27
+ activation values, license keys, API keys, JWTs or private URLs.
28
+
29
+ Codex auth outcomes:
30
+
31
+ | Code / reason | Symptom summary | Safe next action |
32
+ | --- | --- | --- |
33
+ | `CODEX_AUTH_SANDBOX` | Codex cannot access or use existing local Neocortex activation. | Switch to the explicit local profile/Full Access/trusted-local mode or run from the local terminal; do not paste credentials into prompts. |
34
+ | `codex-config-inaccessible` | `~/.neocortex` or `~/.neocortex/config.json` is present but blocked by the Codex sandbox/profile. | Grant trusted local access or use the installed `neocortex-local` profile. |
35
+ | `codex-config-unreadable` | Config exists but cannot be parsed/read safely by this Codex runtime. | Retry from trusted local mode and attach only the bounded reason code if support is needed. |
36
+ | `codex-cache-unreadable` | Config has auth material but the local auth cache is blocked or unreadable. | Grant trusted local cache access or run from the local terminal. |
37
+ | `codex-auth-network-denied` | Activation metadata is present but Codex cannot complete auth/API access. | Allow outbound Neocortex auth/API network access in the trusted local session. |
38
+ | `codex-config-missing` / `NOT_CONFIGURED` | No activation exists in the selected environment. | Activate that environment intentionally from a trusted shell, or switch back to the already activated local profile. |
39
+
40
+ Release smoke for this path is documented in
41
+ `docs/verification/P203-codex-local-activation-smoke.md` and must remain
42
+ credential-free.
43
+
44
+ ## Managed wrapper preservation
45
+
46
+ Install and activation refreshes replace only packaged Neocortex wrapper bodies.
47
+ When an existing managed Markdown wrapper and its packaged replacement both use
48
+ leading YAML frontmatter, the installed frontmatter is retained byte-for-byte.
49
+ Tier/version patching may subsequently update its managed `description` field,
50
+ but unknown host fields and ordering remain untouched. Files outside the explicit
51
+ Neocortex stub allowlist, including user-defined agents and MCP configuration,
52
+ are never selected by this refresh path.
53
+
54
+ The bounded diagnostic summary is `frontmatter-preserved`; it does not include
55
+ frontmatter contents, absolute paths or configuration values. If a packaged file
56
+ or existing destination has no valid leading YAML envelope, the managed packaged
57
+ stub is installed normally rather than guessing from Markdown body separators.
58
+
59
+ For payload-selection, target-normalization and metadata-frontmatter reason codes,
60
+ safe examples and release smoke, see
61
+ `docs/arquitetura-software/frontmatter-target-diagnostics.md` and
62
+ `docs/deploy/P204-frontmatter-release-checklist.md`.
63
+
12
64
  ## Optional tool diagnostics
13
65
 
14
66
  Default npm lifecycle installs do not run CodeRabbit or similar third-party
package/install.ps1 CHANGED
@@ -17,7 +17,7 @@ param(
17
17
  [string]$ServerUrl = ('https://{0}.{1}.{2}' -f 'api','neocortex','sh')
18
18
  )
19
19
 
20
- $VERSION = "4.60.18"
20
+ $VERSION = "4.60.19"
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.60.18"
7
+ VERSION="4.60.19"
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.60.18",
4
- "description": "Neocortex v4.60.18 - Orquestrador de Desenvolvimento de Epics & Stories para Claude Code",
3
+ "version": "4.60.19",
4
+ "description": "Neocortex v4.60.19 - Orquestrador de Desenvolvimento de Epics & Stories para Claude Code",
5
5
  "keywords": [
6
6
  "claude",
7
7
  "claude-code",
@@ -60,6 +60,13 @@
60
60
  "docs/install/installer-diagnostics.md",
61
61
  "postinstall.js",
62
62
  "packages/client/dist/",
63
+ "packages/shared/dist/nx-invoke-signature.js",
64
+ "packages/shared/dist/command-registry-contract.js",
65
+ "packages/shared/dist/strict-readonly.js",
66
+ "packages/shared/dist/invocation/",
67
+ "packages/shared/dist/generated/command-registry.generated.js",
68
+ "packages/shared/dist/generated/invocation-schema.generated.js",
69
+ "packages/shared/dist/yoloop/wave-decision-receipt.js",
63
70
  "!packages/client/dist/**/*.js.map",
64
71
  "!packages/client/dist/**/*.d.ts.map",
65
72
  "targets-stubs/",
@@ -67,14 +74,20 @@
67
74
  ],
68
75
  "scripts": {
69
76
  "test": "node scripts/test-root.mjs",
70
- "build": "npm run build -w packages/shared && npm run build -w packages/client && node scripts/strip-source-map-comments.js && node scripts/minify-client-dist.mjs",
77
+ "build": "npm run build -w packages/shared && npm run build -w packages/client && node scripts/strip-source-map-comments.js && node scripts/minify-client-dist.mjs && node scripts/verify-compiled-invoke-signature.cjs",
71
78
  "build:clean": "rm -rf packages/shared/dist packages/client/dist && npm run build",
72
79
  "build:client": "npm run build -w packages/client",
73
80
  "build:shared": "npm run build -w packages/shared",
81
+ "command-registry:generate": "npm run build:shared && node scripts/generate-command-registry.mjs",
82
+ "command-registry:check": "npm run build:shared && node scripts/generate-command-registry.mjs --check",
83
+ "command-registry:migrate-project": "node scripts/migrate-command-registry-project-id.mjs",
84
+ "command-registry:migrate-claim-scope": "node scripts/migrate-epic-claim-scope.mjs",
85
+ "test:p205-registry": "vitest run tests/p205-registry",
74
86
  "postinstall": "node postinstall.js",
75
87
  "sync": "node sync-version.js",
76
88
  "validate": "node scripts/validate-pre-publish.js",
77
89
  "validate:pre-publish": "node scripts/validate-pre-publish.js",
90
+ "validate:client-artifacts": "node scripts/validate-client-artifacts.mjs",
78
91
  "validate:bash": "bash scripts/validate-pre-publish.sh",
79
92
  "admin:dev": "cd admin && npm run dev",
80
93
  "admin:build": "cd admin && npm run build",
@@ -86,10 +99,18 @@
86
99
  "storybook": "storybook dev -p 6006",
87
100
  "storybook:build": "storybook build --output-dir storybook-static",
88
101
  "storybook:smoke": "node scripts/storybook-smoke-a11y-check.js",
102
+ "remotion:studio": "remotion studio remotion/index.ts --public-dir=landing/public",
103
+ "remotion:typecheck": "tsc --noEmit -p remotion/tsconfig.json",
104
+ "remotion:render:release": "node scripts/render-release-reel.mjs video",
105
+ "remotion:still:release": "node scripts/render-release-reel.mjs still",
106
+ "remotion:still:release:safe-zone": "node scripts/render-release-reel.mjs safe-zone",
107
+ "remotion:render:release:all": "node scripts/render-release-reel.mjs all",
108
+ "skill:sync:release-story": "node scripts/sync-remotion-release-story-skill.mjs",
109
+ "skill:validate:release-story": "node scripts/sync-remotion-release-story-skill.mjs --check && node scripts/validate-remotion-release-story.mjs",
89
110
  "test:e2e": "bash scripts/e2e-smoke-test.sh",
90
111
  "test:tier3-stubs": "bash scripts/test-tier3-stubs.sh",
91
112
  "sbom": "bash scripts/generate-sbom.sh",
92
- "prepublishOnly": "npm run build && npm --prefix packages/server run build -- --noEmit && node scripts/validate-pre-publish.js && node sync-version.js && npm run sbom && node -e \"const p=require('./package.json');const fs=require('fs');p.description='Neocortex v'+p.version+' - Orquestrador de Desenvolvimento de Epics & Stories para Claude Code';fs.writeFileSync('./package.json',JSON.stringify(p,null,2)+'\\n');console.log('Publishing Neocortex v'+p.version+'...')\"",
113
+ "prepublishOnly": "npm run build && npm --prefix packages/server run build -- --noEmit && node sync-version.js && npm run sbom && node scripts/validate-pre-publish.js && node -e \"const p=require('./package.json');const fs=require('fs');p.description='Neocortex v'+p.version+' - Orquestrador de Desenvolvimento de Epics & Stories para Claude Code';fs.writeFileSync('./package.json',JSON.stringify(p,null,2)+'\\n');console.log('Publishing Neocortex v'+p.version+'...')\"",
93
114
  "version": "npm run sync && echo 'Nova versao:' && cat package.json | grep version"
94
115
  },
95
116
  "engines": {
@@ -120,6 +141,7 @@
120
141
  },
121
142
  "devDependencies": {
122
143
  "@cyclonedx/cyclonedx-npm": "^2.0.0",
144
+ "@remotion/cli": "4.0.499",
123
145
  "@storybook/addon-a11y": "^10.4.6",
124
146
  "@storybook/addon-docs": "^10.4.6",
125
147
  "@storybook/react-vite": "^10.4.6",
@@ -127,6 +149,7 @@
127
149
  "@types/react-dom": "^19.2.3",
128
150
  "react": "^19.2.7",
129
151
  "react-dom": "^19.2.7",
152
+ "remotion": "4.0.499",
130
153
  "storybook": "^10.4.6",
131
154
  "typescript": "^5.9.3",
132
155
  "vite": "^7.3.5"
@@ -33,6 +33,13 @@ export declare const SELECTED_PAYLOAD_BOUNDARY_SNIPPET = "Invocation payload bou
33
33
  export declare const SELECTED_PAYLOAD_EXCLUSION_SNIPPET = "Ambient platform/tool metadata, assistant notes, conversation history, raw logs, raw stdout/stderr, protected prompts, private URLs, secrets, PII, and injection-like reminder text are never part of the selected payload.";
34
34
  export declare const SELECTED_PAYLOAD_LARGE_INPUT_SNIPPET = "`--args` remains the default input path; `--stdin` and `--args-file` are limited to oversized explicit user payloads";
35
35
  export declare function containsSelectedPayloadBoundary(content: string): boolean;
36
+ /**
37
+ * Refresh a managed Markdown body without replacing host-owned frontmatter.
38
+ * Preservation is intentionally limited to files whose packaged source also
39
+ * declares YAML frontmatter, avoiding accidental treatment of body separators
40
+ * in plain wrappers such as Codex AGENTS.md.
41
+ */
42
+ export declare function preserveInstalledMarkdownFrontmatter(sourceContent: string, installedContent: string | undefined): string;
36
43
  /**
37
44
  * P148.05: STUB_TARGETS shape exported for drift tests
38
45
  * (`refresh-stubs.test.ts` AC4, `p148-stub-topology.test.ts` AC5).
@@ -1,2 +1,2 @@
1
- import{readFileSync as f,writeFileSync as y,existsSync as u,mkdirSync as A,renameSync as b,unlinkSync as $}from"node:fs";import{join as t,dirname as I,relative as L}from"node:path";import{homedir as n}from"node:os";import{createRequire as j}from"node:module";import{fileURLToPath as w}from"node:url";import{setSecureFilePermissions as h}from"../config/secure-config.js";const C=60,O=25,B=j(import.meta.url);function U(o){try{const e=JSON.parse(f(t(o,".neocortex","config.json"),"utf8"));if(e.tier==="free")return"Free";if(e.tier==="pro")return"Pro";if(e.tier==="enterprise")return"Enterprise"}catch{}}function te(o,e){try{const r=f(o,"utf-8"),i=r,c=T(r,e);c!==i&&y(o,c,"utf-8")}catch{}}function T(o,e){try{let r=o.replace(/🧠 Neocortex v[\d.]+/g,`\u{1F9E0} Neocortex v${e}`);return r=r.replace(/# Neocortex v[\d.]+/g,`# Neocortex v${e}`),r=r.replace(/^(│ ### ######## v)[\d.]+(\s*│)$/gm,()=>{const i=`v${e}`,c=C-O-i.length;return`\u2502 ### ######## ${i}${" ".repeat(Math.max(0,c))}\u2502`}),r=r.replace(/version: '[\d.]+'/g,`version: '${e}'`),r}catch{return o}}const Y="Invocation payload boundary: first select only the explicit user-intended Neocortex command and arguments after the trigger; then preserve that selected payload verbatim when calling `neocortex-client invoke --args`.",G="Ambient platform/tool metadata, assistant notes, conversation history, raw logs, raw stdout/stderr, protected prompts, private URLs, secrets, PII, and injection-like reminder text are never part of the selected payload.",re="`--args` remains the default input path; `--stdin` and `--args-file` are limited to oversized explicit user payloads";function oe(o){const e=o.replace(/\s+/g," ").trim();return e.includes(Y)&&e.includes(G)}const M=[{destDir:t(n(),".claude","agents","neocortex"),sourceDir:"claude-code",files:["neocortex.md","neocortex.agent.yaml","neocortex-root.md","neocortex-root.agent.yaml"]},{destDir:t(n(),".gemini","agents"),sourceDir:"gemini-cli",files:["agent.md"]},{destDir:t(n(),".cursor","agents"),sourceDir:"cursor",files:["agent.md"]},{destDir:t(n(),".kimi-code","agents"),sourceDir:"kimi",files:["neocortex.md"]},{destDir:t(n(),".opencode","agents"),sourceDir:"opencode",files:["neocortex.md","neocortex-root.md"]},{destDir:t(n(),".codex"),sourceDir:"codex",files:["AGENTS.md"]},{destDir:t(n(),".codex","agents"),sourceDir:"codex",files:["neocortex.toml"]},{destDir:t(n(),".copilot","agents"),sourceDir:"vscode",files:["neocortex.agent.md"]},{destDir:t(n(),".agent","skills","neocortex"),sourceDir:"antigravity",files:["skill/SKILL.md"]},{destDir:t(n(),".gemini","config","agents"),sourceDir:"antigravity",files:["neocortex.md"]}];function V(){try{const o=w(import.meta.url);let e=I(o);for(let r=0;r<10;r++){try{if(JSON.parse(f(t(e,"package.json"),"utf-8")).name==="@ornexus/neocortex")return e}catch{}e=I(e)}}catch{}return null}function W(o){try{const e=t(o,".version");if(u(e))return f(e,"utf-8").trim()||null}catch{}return null}function q(o,e){const r=`${o}.tmp-${process.pid}`;try{y(r,e,"utf8"),h(r),b(r,o),h(o)}catch(i){try{u(r)&&$(r)}catch{}throw i}}function ne(o,e){try{const r=e?.forceCreate??!1,i=e?.targetFilter,c=e?.dryRun??!1,D=n(),a=e?.homeDir??D,v=e?.packageRoot??V();if(!v)return 0;const p=t(v,"targets-stubs");if(!u(p))return 0;const E=t(p,"lib","managed-config-merge.js");if(!u(E))return 0;const N=B(E),S=t(a,".neocortex","managed-config-manifest.json"),_=U(a);try{N.applyPolicy({configFile:t(a,".neocortex","config.json"),manifestFile:S,baseDir:a,dryRun:c})}catch{}let m=0;for(const s of M)try{const l=e?.homeDir?t(a,L(D,s.destDir)):s.destDir;if(i&&s.sourceDir!==i)continue;if(!u(l)){if(r&&!c)A(l,{recursive:!0});else if(!(r&&c))continue}if(W(l)===o)continue;const P=t(p,s.sourceDir);if(!u(P))continue;let g=!1;for(const d of s.files){const k=t(P,d),R=t(l,d);if(u(k)){let x=f(k,"utf8");(d.endsWith(".md")||d.endsWith(".yaml")||d.endsWith(".yml"))&&(x=T(x,o));const F=L(a,R).split("\\").join("/");N.applyProfileBytes({id:`profile-${s.sourceDir}-${F}`,content:x,destination:R,manifestFile:S,baseDir:a,dryRun:c,allowLegacyAdoption:!0,tierLabel:_}).action!=="failed"&&(g=!0)}}if(g&&!c){const d=t(l,".version");q(d,o+`
2
- `),m++}else g&&m++}catch{}if(m>0)try{const s=t(a,".neocortex");A(s,{recursive:!0});const l=t(s,".update-check");y(l,"",{flag:"w"}),h(l)}catch{}return m}catch{return 0}}export{Y as SELECTED_PAYLOAD_BOUNDARY_SNIPPET,G as SELECTED_PAYLOAD_EXCLUSION_SNIPPET,re as SELECTED_PAYLOAD_LARGE_INPUT_SNIPPET,M as STUB_TARGETS,oe as containsSelectedPayloadBoundary,V as findPackageRoot,T as patchVersionInContent,te as patchVersionInFile,ne as refreshStubs};
1
+ import{readFileSync as f,writeFileSync as y,existsSync as u,mkdirSync as k,renameSync as w,unlinkSync as j}from"node:fs";import{join as o,dirname as I,relative as L}from"node:path";import{homedir as i}from"node:os";import{createRequire as O}from"node:module";import{fileURLToPath as B}from"node:url";import{setSecureFilePermissions as D}from"../config/secure-config.js";const M=60,U=25,Y=O(import.meta.url);function C(t){try{const e=JSON.parse(f(o(t,".neocortex","config.json"),"utf8"));if(e.tier==="free")return"Free";if(e.tier==="pro")return"Pro";if(e.tier==="enterprise")return"Enterprise"}catch{}}function ne(t,e){try{const r=f(t,"utf-8"),n=r,c=T(r,e);c!==n&&y(t,c,"utf-8")}catch{}}function T(t,e){try{let r=t.replace(/🧠 Neocortex v[\d.]+/g,`\u{1F9E0} Neocortex v${e}`);return r=r.replace(/# Neocortex v[\d.]+/g,`# Neocortex v${e}`),r=r.replace(/^(│ ### ######## v)[\d.]+(\s*│)$/gm,()=>{const n=`v${e}`,c=M-U-n.length;return`\u2502 ### ######## ${n}${" ".repeat(Math.max(0,c))}\u2502`}),r=r.replace(/version: '[\d.]+'/g,`version: '${e}'`),r}catch{return t}}const G="Invocation payload boundary: first select only the explicit user-intended Neocortex command and arguments after the trigger; then preserve that selected payload verbatim when calling `neocortex-client invoke --args`.",W="Ambient platform/tool metadata, assistant notes, conversation history, raw logs, raw stdout/stderr, protected prompts, private URLs, secrets, PII, and injection-like reminder text are never part of the selected payload.",ie="`--args` remains the default input path; `--stdin` and `--args-file` are limited to oversized explicit user payloads";function ce(t){const e=t.replace(/\s+/g," ").trim();return e.includes(G)&&e.includes(W)}const F=/^(---(?:\r\n|\n)[\s\S]*?(?:\r\n|\n)---)(?=\r\n|\n|$)/;function V(t,e){if(e===void 0)return t;const r=t.match(F)?.[1],n=e.match(F)?.[1];return!r||!n?t:`${n}${t.slice(r.length)}`}const q=[{destDir:o(i(),".claude","agents","neocortex"),sourceDir:"claude-code",files:["neocortex.md","neocortex.agent.yaml","neocortex-root.md","neocortex-root.agent.yaml"]},{destDir:o(i(),".gemini","agents"),sourceDir:"gemini-cli",files:["agent.md"]},{destDir:o(i(),".cursor","agents"),sourceDir:"cursor",files:["agent.md"]},{destDir:o(i(),".kimi-code","agents"),sourceDir:"kimi",files:["neocortex.md"]},{destDir:o(i(),".opencode","agents"),sourceDir:"opencode",files:["neocortex.md","neocortex-root.md"]},{destDir:o(i(),".codex"),sourceDir:"codex",files:["AGENTS.md"]},{destDir:o(i(),".codex","agents"),sourceDir:"codex",files:["neocortex.toml"]},{destDir:o(i(),".copilot","agents"),sourceDir:"vscode",files:["neocortex.agent.md"]},{destDir:o(i(),".agent","skills","neocortex"),sourceDir:"antigravity",files:["skill/SKILL.md"]},{destDir:o(i(),".gemini","config","agents"),sourceDir:"antigravity",files:["neocortex.md"]}];function H(){try{const t=B(import.meta.url);let e=I(t);for(let r=0;r<10;r++){try{if(JSON.parse(f(o(e,"package.json"),"utf-8")).name==="@ornexus/neocortex")return e}catch{}e=I(e)}}catch{}return null}function J(t){try{const e=o(t,".version");if(u(e))return f(e,"utf-8").trim()||null}catch{}return null}function X(t,e){const r=`${t}.tmp-${process.pid}`;try{y(r,e,"utf8"),D(r),w(r,t),D(t)}catch(n){try{u(r)&&j(r)}catch{}throw n}}function se(t,e){try{const r=e?.forceCreate??!1,n=e?.targetFilter,c=e?.dryRun??!1,v=i(),a=e?.homeDir??v,E=e?.packageRoot??H();if(!E)return 0;const h=o(E,"targets-stubs");if(!u(h))return 0;const N=o(h,"lib","managed-config-merge.js");if(!u(N))return 0;const S=Y(N),A=o(a,".neocortex","managed-config-manifest.json"),_=C(a);try{S.applyPolicy({configFile:o(a,".neocortex","config.json"),manifestFile:A,baseDir:a,dryRun:c})}catch{}let p=0;for(const s of q)try{const l=e?.homeDir?o(a,L(v,s.destDir)):s.destDir;if(n&&s.sourceDir!==n)continue;if(!u(l)){if(r&&!c)k(l,{recursive:!0});else if(!(r&&c))continue}if(J(l)===t)continue;const P=o(h,s.sourceDir);if(!u(P))continue;let x=!1;for(const d of s.files){const R=o(P,d),g=o(l,d);if(u(R)){let m=f(R,"utf8");if(d.endsWith(".md")){const b=u(g)?f(g,"utf8"):void 0;m=V(m,b)}(d.endsWith(".md")||d.endsWith(".yaml")||d.endsWith(".yml"))&&(m=T(m,t));const $=L(a,g).split("\\").join("/");S.applyProfileBytes({id:`profile-${s.sourceDir}-${$}`,content:m,destination:g,manifestFile:A,baseDir:a,dryRun:c,allowLegacyAdoption:!0,tierLabel:_}).action!=="failed"&&(x=!0)}}if(x&&!c){const d=o(l,".version");X(d,t+`
2
+ `),p++}else x&&p++}catch{}if(p>0)try{const s=o(a,".neocortex");k(s,{recursive:!0});const l=o(s,".update-check");y(l,"",{flag:"w"}),D(l)}catch{}return p}catch{return 0}}export{G as SELECTED_PAYLOAD_BOUNDARY_SNIPPET,W as SELECTED_PAYLOAD_EXCLUSION_SNIPPET,ie as SELECTED_PAYLOAD_LARGE_INPUT_SNIPPET,q as STUB_TARGETS,ce as containsSelectedPayloadBoundary,H as findPackageRoot,T as patchVersionInContent,ne as patchVersionInFile,V as preserveInstalledMarkdownFrontmatter,se as refreshStubs};
@@ -16,10 +16,13 @@ export interface EncryptedCacheOptions {
16
16
  cacheDir: string;
17
17
  /** Passphrase for encryption (typically the license key) */
18
18
  passphrase: string;
19
+ /** Read entries without cleanup, creation, overwrite or deletion. */
20
+ strictReadOnly?: boolean;
19
21
  }
20
22
  export declare class EncryptedCache implements CacheProvider {
21
23
  private readonly cacheDir;
22
24
  private readonly passphrase;
25
+ private readonly strictReadOnly;
23
26
  private initPromise;
24
27
  constructor(options: EncryptedCacheOptions);
25
28
  get(key: string): Promise<string | null>;
@@ -1 +1 @@
1
- import{mkdir as n,writeFile as o,readFile as p,rm as s,readdir as m}from"node:fs/promises";import{join as a}from"node:path";import{createHash as u}from"node:crypto";import{encrypt as l,decrypt as f}from"./crypto-utils.js";import{setSecureFilePermissions as d}from"../config/secure-config.js";import{hasProtectedCachePayloadMarker as y}from"./protected-pi-boundary.js";const c=".enc";class F{cacheDir;passphrase;initPromise=null;constructor(t){this.cacheDir=t.cacheDir,this.passphrase=t.passphrase}async get(t){try{const r=this.keyToPath(t),e=await p(r,"utf8"),i=f(e,this.passphrase);return i.expired?(s(r,{force:!0}).catch(()=>{}),null):i.plaintext}catch{return null}}async set(t,r,e){try{if(y(r))return;await this.ensureDir();const i=this.keyToPath(t),h=l(r,this.passphrase,e);await o(i,h,"utf8"),d(i)}catch{}}async clear(){try{const r=(await m(this.cacheDir).catch(()=>[])).filter(e=>e.endsWith(c)).map(e=>s(a(this.cacheDir,e),{force:!0}).catch(()=>{}));await Promise.all(r)}catch{}}keyToPath(t){const r=u("sha256").update(t).digest("hex");return a(this.cacheDir,`${r}${c}`)}ensureDir(){return this.initPromise||(this.initPromise=n(this.cacheDir,{recursive:!0}).then(()=>{}).catch(t=>{throw this.initPromise=null,t})),this.initPromise}}export{F as EncryptedCache};
1
+ import{mkdir as n,writeFile as o,readFile as l,rm as s,readdir as u}from"node:fs/promises";import{join as a}from"node:path";import{createHash as m}from"node:crypto";import{encrypt as p,decrypt as d}from"./crypto-utils.js";import{setSecureFilePermissions as f}from"../config/secure-config.js";import{hasProtectedCachePayloadMarker as y}from"./protected-pi-boundary.js";const c=".enc";class x{cacheDir;passphrase;strictReadOnly;initPromise=null;constructor(t){this.cacheDir=t.cacheDir,this.passphrase=t.passphrase,this.strictReadOnly=t.strictReadOnly??!1}async get(t){try{const r=this.keyToPath(t),e=await l(r,"utf8"),i=d(e,this.passphrase);return i.expired?(this.strictReadOnly||await s(r,{force:!0}).catch(()=>{}),null):i.plaintext}catch{return null}}async set(t,r,e){if(!this.strictReadOnly)try{if(y(r))return;await this.ensureDir();const i=this.keyToPath(t),h=p(r,this.passphrase,e);await o(i,h,"utf8"),f(i)}catch{}}async clear(){if(!this.strictReadOnly)try{const r=(await u(this.cacheDir).catch(()=>[])).filter(e=>e.endsWith(c)).map(e=>s(a(this.cacheDir,e),{force:!0}).catch(()=>{}));await Promise.all(r)}catch{}}keyToPath(t){const r=m("sha256").update(t).digest("hex");return a(this.cacheDir,`${r}${c}`)}ensureDir(){return this.initPromise||(this.initPromise=n(this.cacheDir,{recursive:!0}).then(()=>{}).catch(t=>{throw this.initPromise=null,t})),this.initPromise}}export{x as EncryptedCache};
@@ -1,2 +1,2 @@
1
- import{promises as c}from"node:fs";import f from"node:path";import{MAX_SNAPSHOT_SIZE_BYTES as d}from"./shared-checkpoint-types.js";const u=".neocortex/checkpoint-pending.json",p=1e4,a=["FASE_1","FASE_2","FASE_3","FASE_4"];function l(o){if(o===null||typeof o!="object")return{valid:!1,errors:["payload must be object"]};const e=o,t=[];return(typeof e.storyId!="string"||e.storyId.length===0)&&t.push("storyId must be non-empty string"),(typeof e.turn!="number"||!Number.isFinite(e.turn)||e.turn<0)&&t.push("turn must be non-negative finite number"),(!Array.isArray(e.filesModified)||!e.filesModified.every(n=>typeof n=="string"))&&t.push("filesModified must be string[]"),(!Array.isArray(e.testsModified)||!e.testsModified.every(n=>typeof n=="string"))&&t.push("testsModified must be string[]"),(typeof e.currentPhase!="string"||!a.includes(e.currentPhase))&&t.push(`currentPhase must be one of ${a.join("|")}`),typeof e.snapshotMd!="string"&&t.push("snapshotMd must be string"),{valid:t.length===0,errors:Object.freeze(t)}}async function y(o){const e=f.join(o,u);let t;try{t=await c.readFile(e,"utf-8")}catch(r){if(r.code==="ENOENT")return;console.warn(`[Neocortex] checkpoint read failed: ${r instanceof Error?r.message:String(r)}`);return}c.unlink(e).catch(r=>{console.warn(`[Neocortex] checkpoint unlink failed: ${r instanceof Error?r.message:String(r)}`)});const n=t.replace(/^/,"").replace(/\r\n/g,`
2
- `);if(n.length>d+p){console.warn(`[Neocortex] checkpoint oversized (${n.length} bytes), skipping`);return}let s;try{s=JSON.parse(n)}catch(r){console.warn(`[Neocortex] checkpoint malformed JSON: ${r instanceof Error?r.message:String(r)}`);return}const i=l(s);if(!i.valid){console.warn(`[Neocortex] checkpoint schema invalid: ${i.errors.join("; ")}`);return}return s}export{u as CHECKPOINT_PENDING_PATH,y as readAndConsumeCheckpoint,l as validateSnapshot};
1
+ import{promises as a}from"node:fs";import f from"node:path";import{MAX_SNAPSHOT_SIZE_BYTES as u}from"./shared-checkpoint-types.js";const d=".neocortex/checkpoint-pending.json",p=1e4,c=["FASE_1","FASE_2","FASE_3","FASE_4"];function l(o){if(o===null||typeof o!="object")return{valid:!1,errors:["payload must be object"]};const e=o,n=[];return(typeof e.storyId!="string"||e.storyId.length===0)&&n.push("storyId must be non-empty string"),(typeof e.turn!="number"||!Number.isFinite(e.turn)||e.turn<0)&&n.push("turn must be non-negative finite number"),(!Array.isArray(e.filesModified)||!e.filesModified.every(t=>typeof t=="string"))&&n.push("filesModified must be string[]"),(!Array.isArray(e.testsModified)||!e.testsModified.every(t=>typeof t=="string"))&&n.push("testsModified must be string[]"),(typeof e.currentPhase!="string"||!c.includes(e.currentPhase))&&n.push(`currentPhase must be one of ${c.join("|")}`),typeof e.snapshotMd!="string"&&n.push("snapshotMd must be string"),{valid:n.length===0,errors:Object.freeze(n)}}async function y(o){const e=f.join(o,d);let n;try{n=await a.readFile(e,"utf-8")}catch(r){if(r.code==="ENOENT")return;console.warn(`[Neocortex] checkpoint read failed: ${r instanceof Error?r.message:String(r)}`);return}try{await a.unlink(e)}catch(r){console.warn(`[Neocortex] checkpoint unlink failed: ${r instanceof Error?r.message:String(r)}`)}const t=n.replace(/^/,"").replace(/\r\n/g,`
2
+ `);if(t.length>u+p){console.warn(`[Neocortex] checkpoint oversized (${t.length} bytes), skipping`);return}let i;try{i=JSON.parse(t)}catch(r){console.warn(`[Neocortex] checkpoint malformed JSON: ${r instanceof Error?r.message:String(r)}`);return}const s=l(i);if(!s.valid){console.warn(`[Neocortex] checkpoint schema invalid: ${s.errors.join("; ")}`);return}return i}export{d as CHECKPOINT_PENDING_PATH,y as readAndConsumeCheckpoint,l as validateSnapshot};
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{readFileSync as p}from"node:fs";import{fileURLToPath as u}from"node:url";import{dirname as l,join as m}from"node:path";function g(){try{const a=u(import.meta.url);let e=l(a);for(let r=0;r<5;r++){try{const o=JSON.parse(p(m(e,"package.json"),"utf-8"));if(o.name==="@ornexus/neocortex"||o.name==="@neocortex/client")return o.version??"0.0.0"}catch{}e=l(e)}}catch{}return"0.0.0"}const d=`
2
+ import{getClientVersion as d}from"./version.js";const l=`
3
3
  neocortex-client - Neocortex Client CLI
4
4
 
5
5
  Usage:
@@ -92,5 +92,5 @@ Invocation payload boundary:
92
92
 
93
93
  License:
94
94
  Licensed under BSL-1.1 (Business Source License 1.1)
95
- `.trim(),f=new Set(["pm","install","postinstall","preinstall","prepublish","postpublish","preuninstall","postuninstall","preprepare","prepare","postprepare"]);async function h(){const a=process.argv.slice(2),e=a[0];e&&f.has(e.toLowerCase())&&process.exit(0),(!e||e==="--help"||e==="-h")&&(console.log(d),process.exit(0)),(e==="--version"||e==="-v")&&(console.log(g()),process.stderr.write(`Licensed under BSL-1.1 (Business Source License 1.1)
96
- `),process.exit(0));const r=a.slice(1);switch(e){case"invoke":{const{invokeCliHandler:o}=await import("./commands/invoke.js"),s=await o(r);process.exit(s);break}case"activate":{const{activate:o}=await import("./commands/activate.js");let s,i,c=!1;for(let t=0;t<r.length;t++){const n=r[t];n==="--server-url"?i=r[++t]:n==="--non-interactive"?c=!0:n==="--help"||n==="-h"?(console.log(d),process.exit(0)):n.startsWith("-")||(s=n)}s||(console.error("Error: License key is required."),console.error("Usage: neocortex-client activate <license-key>"),console.error("Example: neocortex-client activate NX-PRO-ABC-123"),process.exit(1));try{const t=await o({licenseKey:s,serverUrl:i,nonInteractive:c});t.success?(console.log(t.message),process.exit(0)):(console.error(t.message),process.exit(1))}catch(t){const n=t instanceof Error?t.message:String(t);console.error(`Activation failed: ${n}`),process.exit(1)}break}case"cache-status":{console.log("Cache status requires an active client session."),console.log("Use this command within a running Neocortex client context."),process.exit(0);break}case"config":{const{configCliHandler:o}=await import("./commands/config.js"),s=await o(r);process.exit(s);break}case"refresh-memory":{const{refreshMemoryCliHandler:o}=await import("./commands/refresh-memory.js"),s=await o(r);process.exit(s);break}case"update":{console.log("To update Neocortex, run:"),console.log(" neocortex update"),console.log(""),console.log("Or manually:"),console.log(" npm install -g @ornexus/neocortex@latest"),process.exit(0);break}default:console.error(`Unknown command: ${e}`),console.error('Run "neocortex-client --help" for usage information.'),process.exit(1)}}h().catch(a=>{console.error(`Fatal error: ${a instanceof Error?a.message:String(a)}`),process.exit(1)});
95
+ `.trim(),p=new Set(["pm","install","postinstall","preinstall","prepublish","postpublish","preuninstall","postuninstall","preprepare","prepare","postprepare"]);async function u(){const a=process.argv.slice(2),t=a[0];t&&p.has(t.toLowerCase())&&process.exit(0),(!t||t==="--help"||t==="-h")&&(console.log(l),process.exit(0)),(t==="--version"||t==="-v")&&(console.log(d()),process.stderr.write(`Licensed under BSL-1.1 (Business Source License 1.1)
96
+ `),process.exit(0));const n=a.slice(1);switch(t){case"invoke":{const{invokeCliHandler:s}=await import("./commands/invoke.js"),o=await s(n);process.exit(o);break}case"activate":{const{activate:s}=await import("./commands/activate.js");let o,i,c=!1;for(let e=0;e<n.length;e++){const r=n[e];r==="--server-url"?i=n[++e]:r==="--non-interactive"?c=!0:r==="--help"||r==="-h"?(console.log(l),process.exit(0)):r.startsWith("-")||(o=r)}o||(console.error("Error: License key is required."),console.error("Usage: neocortex-client activate <license-key>"),console.error("Example: neocortex-client activate NX-PRO-ABC-123"),process.exit(1));try{const e=await s({licenseKey:o,serverUrl:i,nonInteractive:c});e.success?(console.log(e.message),process.exit(0)):(console.error(e.message),process.exit(1))}catch(e){const r=e instanceof Error?e.message:String(e);console.error(`Activation failed: ${r}`),process.exit(1)}break}case"cache-status":{console.log("Cache status requires an active client session."),console.log("Use this command within a running Neocortex client context."),process.exit(0);break}case"config":{const{configCliHandler:s}=await import("./commands/config.js"),o=await s(n);process.exit(o);break}case"refresh-memory":{const{refreshMemoryCliHandler:s}=await import("./commands/refresh-memory.js"),o=await s(n);process.exit(o);break}case"update":{console.log("To update Neocortex, run:"),console.log(" neocortex update"),console.log(""),console.log("Or manually:"),console.log(" npm install -g @ornexus/neocortex@latest"),process.exit(0);break}default:console.error(`Unknown command: ${t}`),console.error('Run "neocortex-client --help" for usage information.'),process.exit(1)}}u().catch(a=>{console.error(`Fatal error: ${a instanceof Error?a.message:String(a)}`),process.exit(1)});
@@ -1,8 +1,8 @@
1
- import{existsSync as $,mkdirSync as C,writeFileSync as V,readFileSync as x}from"node:fs";import{join as a,dirname as P}from"node:path";import{homedir as Y}from"node:os";import{fileURLToPath as X}from"node:url";import{LicenseClient as M}from"../license/license-client.js";import{EncryptedCache as S}from"../cache/encrypted-cache.js";import{getMachineFingerprint as E}from"../machine/fingerprint.js";import{updateAgentDescription as N}from"../agent/update-description.js";import{refreshStubs as h}from"../agent/refresh-stubs.js";import{updateAgentYaml as _}from"../agent/update-agent-yaml.js";import{saveSecureConfig as W,setSecureDirPermissions as w}from"../config/secure-config.js";import{DEFAULT_SERVER_URL as J}from"../constants.js";function b(){try{const e=X(import.meta.url);let t=P(e);for(let r=0;r<5;r++){try{const n=JSON.parse(x(a(t,"package.json"),"utf-8"));if(n.name==="@ornexus/neocortex"||n.name==="@neocortex/client")return n.version??"0.0.0"}catch{}t=P(t)}}catch{}return"0.0.0"}const i=a(Y(),".neocortex"),c=a(i,"config.json"),B=/^NX-(F|P|E)-[a-f0-9]+-[a-f0-9]+$/i,G=/^nxk_(?:[a-z]+_)?[a-f0-9]+_[a-f0-9]+$/;function z(e){if(!e||e.trim().length===0)return{valid:!1,error:"License key cannot be empty"};const t=e.trim().toUpperCase();return t.startsWith("NX-")?B.test(t)?{valid:!0}:{valid:!1,error:"Invalid license key format. Expected: NX-{TIER}-{ID} (e.g., NX-PRO-ABC-123)"}:{valid:!1,error:'License key must start with "NX-"'}}function q(e){if(!e||e.trim().length===0)return{valid:!1,error:"API key cannot be empty"};const t=e.trim();return t.startsWith("nxk_")?t.length<20?{valid:!1,error:"API key is too short"}:G.test(t)?{valid:!0}:{valid:!1,error:"Invalid API key format. Expected: nxk_{id}_{check} (e.g., nxk_abc123def456...)"}:{valid:!1,error:'API key must start with "nxk_"'}}function pe(){try{if($(c)){const e=x(c,"utf-8");return JSON.parse(e)}}catch{}return null}function A(e){C(i,{recursive:!0}),w(i);const t=a(i,"cache");if(C(t,{recursive:!0}),w(t),e.licenseKey||e.apiKey)W({serverUrl:e.serverUrl,mode:e.mode,machineId:e.machineId,activatedAt:e.activatedAt,tier:e.tier,licenseKey:e.licenseKey??e.apiKey});else{const r={configVersion:1,...e};V(c,JSON.stringify(r,null,2)+`
2
- `,"utf-8")}}async function he(e){const{licenseKey:t,serverUrl:r=J}=e;if(!t)return{success:!1,message:["No key provided.","","Get your license key at https://neocortex.sh/portal/login","","Usage:"," neocortex activate YOUR-LICENSE-KEY"," neocortex activate YOUR-API-KEY"].join(`
3
- `)};const n=t.trim();if(n.startsWith("nxk_")){const o=q(n);if(!o.valid)return{success:!1,message:`Invalid API key: ${o.error}`};const k=n.match(/^nxk_(free|pro|ent)_/),O={free:"free",pro:"pro",ent:"enterprise"},R=k?.[1]?O[k[1]]??"unknown":"unknown",I=E(),l=b();let m;try{const s=await fetch(`${r}/api/v1/license/activate-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:n,machine_id:I,client_version:l})});if(!s.ok)return{success:!1,message:`API key activation failed: ${(await s.json().catch(()=>({}))).message??`HTTP ${s.status}`}`};m=await s.json()}catch{return{success:!1,message:["Failed to connect to IP Protection Server.","","Possible causes:",` - Server at ${r} is unreachable`," - Network connectivity issue","","Workaround: Use --local flag to run in local mode"].join(`
4
- `)}}const p=m.tier??R,T=a(i,"cache");try{await new S({cacheDir:T,passphrase:n}).set("neocortex:jwt:token",m.token,m.expires_in*1e3)}catch{}const L={serverUrl:r,mode:"remote",machineId:I,activatedAt:new Date().toISOString(),tier:p,apiKey:n};try{A(L)}catch(s){return{success:!1,message:`Failed to save configuration: ${s instanceof Error?s.message:"unknown error"}`}}const Z=h(l,{forceCreate:!0,targetFilter:"claude-code"});return h(l),N(l,p),_(l,p),{success:!0,message:["Neocortex activated successfully.","","Open your preferred platform (Claude Code, Cursor, VS Code, etc.)","and reference the Neocortex agent.","","Use *menu to see available commands or check the Docs in your Dashboard."].join(`
5
- `),tier:p,serverUrl:r,configPath:c}}const y=z(n);if(!y.valid)return{success:!1,message:`Invalid license key: ${y.error}`};const u=n,v=u.match(/^NX-(F|P|E)-/i),F={F:"free",P:"pro",E:"enterprise"},d=v?.[1]?F[v[1].toUpperCase()]??"unknown":"unknown",K=a(i,"cache"),U=new S({cacheDir:K,passphrase:u}),j=new M({serverUrl:r,licenseKey:u,cacheProvider:U});let g;try{g=await j.activate()}catch{return{success:!1,message:["Failed to connect to IP Protection Server.","","Possible causes:",` - Server at ${r} is unreachable`," - Network connectivity issue"," - Server is still being deployed","","Workaround: Use --local flag to run in local mode"].join(`
1
+ import{existsSync as V,mkdirSync as x,writeFileSync as Y,readFileSync as I}from"node:fs";import{join as o,dirname as C}from"node:path";import{homedir as X}from"node:os";import{fileURLToPath as W}from"node:url";import{LicenseClient as J}from"../license/license-client.js";import{EncryptedCache as P}from"../cache/encrypted-cache.js";import{getMachineFingerprint as S}from"../machine/fingerprint.js";import{updateAgentDescription as E}from"../agent/update-description.js";import{refreshStubs as h}from"../agent/refresh-stubs.js";import{updateAgentYaml as N}from"../agent/update-agent-yaml.js";import{saveSecureConfig as B,setSecureDirPermissions as _}from"../config/secure-config.js";import{DEFAULT_SERVER_URL as G}from"../constants.js";function b(){try{const e=W(import.meta.url);let t=C(e);for(let r=0;r<5;r++){try{const n=JSON.parse(I(o(t,"package.json"),"utf-8"));if(n.name==="@ornexus/neocortex"||n.name==="@neocortex/client")return n.version??"0.0.0"}catch{}t=C(t)}}catch{}return"0.0.0"}const i=o(X(),".neocortex"),c=o(i,"config.json"),z=/^NX-(F|P|E)-[a-f0-9]+-[a-f0-9]+$/i,q=/^nxk_(?:[a-z]+_)?[a-f0-9]+_[a-f0-9]+$/;function H(e){if(!e||e.trim().length===0)return{valid:!1,error:"License key cannot be empty"};const t=e.trim().toUpperCase();return t.startsWith("NX-")?z.test(t)?{valid:!0}:{valid:!1,error:"Invalid license key format. Expected: NX-{TIER}-{ID} (e.g., NX-PRO-ABC-123)"}:{valid:!1,error:'License key must start with "NX-"'}}function Q(e){if(!e||e.trim().length===0)return{valid:!1,error:"API key cannot be empty"};const t=e.trim();return t.startsWith("nxk_")?t.length<20?{valid:!1,error:"API key is too short"}:q.test(t)?{valid:!0}:{valid:!1,error:"Invalid API key format. Expected: nxk_{id}_{check} (e.g., nxk_abc123def456...)"}:{valid:!1,error:'API key must start with "nxk_"'}}function pe(){try{if(V(c)){const e=I(c,"utf-8");return JSON.parse(e)}}catch{}return null}function A(e){x(i,{recursive:!0}),_(i);const t=o(i,"cache");if(x(t,{recursive:!0}),_(t),e.licenseKey||e.apiKey)B({serverUrl:e.serverUrl,mode:e.mode,machineId:e.machineId,activatedAt:e.activatedAt,tier:e.tier,licenseKey:e.licenseKey??e.apiKey});else{const r={configVersion:1,...e};Y(c,JSON.stringify(r,null,2)+`
2
+ `,"utf-8")}}async function he(e){const{licenseKey:t,serverUrl:r=G}=e;if(!t)return{success:!1,message:["No key provided.","","Get your license key at https://neocortex.sh/portal/login","","Usage:"," neocortex activate YOUR-LICENSE-KEY"," neocortex activate YOUR-API-KEY"].join(`
3
+ `)};const n=t.trim();if(n.startsWith("nxk_")){const a=Q(n);if(!a.valid)return{success:!1,message:`Invalid API key: ${a.error}`};const k=n.match(/^nxk_(free|pro|ent)_/),R={free:"free",pro:"pro",ent:"enterprise"},T=k?.[1]?R[k[1]]??"unknown":"unknown",w=S(),l=b();let m;try{const s=await fetch(`${r}/api/v1/license/activate-key`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:n,machine_id:w,client_version:l})});if(!s.ok)return{success:!1,message:`API key activation failed: ${(await s.json().catch(()=>({}))).message??`HTTP ${s.status}`}`};m=await s.json()}catch{return{success:!1,message:["Failed to connect to IP Protection Server.","","Possible causes:",` - Server at ${r} is unreachable`," - Network connectivity issue","","Workaround: Use --local flag to run in local mode"].join(`
4
+ `)}}const p=m.tier??T,L=o(i,"cache");try{await new P({cacheDir:L,passphrase:n}).set("neocortex:jwt:token",m.token,m.expires_in*1e3)}catch{}const $={serverUrl:r,mode:"remote",machineId:w,activatedAt:new Date().toISOString(),tier:p,apiKey:n};try{A($)}catch(s){return{success:!1,message:`Failed to save configuration: ${s instanceof Error?s.message:"unknown error"}`}}const M=h(l,{forceCreate:!0,targetFilter:"claude-code"})+h(l);return E(l,p),N(l,p),{success:!0,message:["Neocortex activated successfully.","","Open your preferred platform (Claude Code, Cursor, VS Code, etc.)","and reference the Neocortex agent.",...M>0?["","Managed agent wrappers were refreshed while preserving existing Markdown frontmatter and unrelated platform files."]:[],"","Use *menu to see available commands or check the Docs in your Dashboard."].join(`
5
+ `),tier:p,serverUrl:r,configPath:c}}const y=H(n);if(!y.valid)return{success:!1,message:`Invalid license key: ${y.error}`};const d=n,v=d.match(/^NX-(F|P|E)-/i),F={F:"free",P:"pro",E:"enterprise"},u=v?.[1]?F[v[1].toUpperCase()]??"unknown":"unknown",K=o(i,"cache"),U=new P({cacheDir:K,passphrase:d}),j=new J({serverUrl:r,licenseKey:d,cacheProvider:U});let g;try{g=await j.activate()}catch{return{success:!1,message:["Failed to connect to IP Protection Server.","","Possible causes:",` - Server at ${r} is unreachable`," - Network connectivity issue"," - Server is still being deployed","","Workaround: Use --local flag to run in local mode"].join(`
6
6
  `)}}if(!g)return{success:!1,message:["License activation failed.","","Possible causes:"," - Invalid or expired license key"," - License already activated on another machine"," - Server rejected the activation request","","Check your license key and try again.","Contact support if the problem persists."].join(`
7
- `)};const D={serverUrl:r,mode:"remote",machineId:E(),activatedAt:new Date().toISOString(),tier:d,licenseKey:u};try{A(D)}catch(o){return{success:!1,message:`Failed to save config to ${c}: ${o instanceof Error?o.message:String(o)}`}}const f=b(),Q=h(f,{forceCreate:!0,targetFilter:"claude-code"});return h(f),N(f,d),_(f,d),{success:!0,message:["Neocortex activated successfully.","","Open your preferred platform (Claude Code, Cursor, VS Code, etc.)","and reference the Neocortex agent.","","Use *menu to see available commands or check the Docs in your Dashboard."].join(`
8
- `),tier:d,serverUrl:r,configPath:c}}export{he as activate,q as validateApiKeyFormat,z as validateLicenseKeyFormat};
7
+ `)};const D={serverUrl:r,mode:"remote",machineId:S(),activatedAt:new Date().toISOString(),tier:u,licenseKey:d};try{A(D)}catch(a){return{success:!1,message:`Failed to save config to ${c}: ${a instanceof Error?a.message:String(a)}`}}const f=b(),O=h(f,{forceCreate:!0,targetFilter:"claude-code"})+h(f);return E(f,u),N(f,u),{success:!0,message:["Neocortex activated successfully.","","Open your preferred platform (Claude Code, Cursor, VS Code, etc.)","and reference the Neocortex agent.",...O>0?["","Managed agent wrappers were refreshed while preserving existing Markdown frontmatter and unrelated platform files."]:[],"","Use *menu to see available commands or check the Docs in your Dashboard."].join(`
8
+ `),tier:u,serverUrl:r,configPath:c}}export{he as activate,Q as validateApiKeyFormat,H as validateLicenseKeyFormat};
@@ -1 +1 @@
1
- import{SUBAGENT_APPROVAL_EVIDENCE as d,deriveSubagentHostApprovalPolicy as v}from"../subagent-approval-policy.js";import{detectPlatform as m}from"../adapters/platform-detector.js";import{ApprovalPolicyConfigError as E,getSubagentApprovalPolicy as b,resetSubagentApprovalMode as y,setSubagentApprovalMode as P}from"../config.js";function $(a,r){const t={evidence:d,...a.resolution,auditEvent:a.auditEvent?.event};return r?JSON.stringify(t,null,2):[d,`requested=${t.requestedMode}`,`effective=${t.effectiveMode}`,`source=${t.source}`,`scope=${t.scope}`,`platform=${t.platformTarget}`,`reason=${t.effectiveReason}`,`fallback=${t.fallbackMode}`,`fallbackReason=${t.fallbackReasonCode??"none"}`].join(" ")}async function w(a,r={}){const t=r.stdout??console.log,n=r.stderr??console.error;let s="status",l,i=!1,f=!1;for(let e=0;e<a.length;e+=1){const o=a[e];if(o==="--json")i=!0;else if(o==="--platform-target"){if(l=a[e+1],e+=1,!l)return n("Error: --platform-target requires a value."),1}else if(!f&&(o==="status"||o==="max"||o==="standard"||o==="disabled"||o==="reset"))s=o,f=!0;else return n("Error: expected status, max, standard, disabled, or reset."),1}const p=r.env??process.env,u=m({cwd:r.cwd??process.cwd(),env:p,targetFlag:l}),g=v(u.targetId),c={configFilePath:r.configFilePath,platformTarget:u.targetId,hostPolicy:g,now:r.now};try{const e=s==="status"?b(c):s==="reset"?y(c):P(s,c);return t($(e,i)),0}catch(e){return e instanceof E?(n(`Error: ${e.reasonCode}`),1):(n("Error: approval-policy-update-failed"),1)}}export{w as configCliHandler};
1
+ import{SUBAGENT_APPROVAL_EVIDENCE as d,deriveSubagentHostApprovalPolicy as v}from"../policy/subagent-approval-policy.js";import{detectPlatform as m}from"../adapters/platform-detector.js";import{ApprovalPolicyConfigError as E,getSubagentApprovalPolicy as b,resetSubagentApprovalMode as y,setSubagentApprovalMode as P}from"../config.js";function $(a,r){const t={evidence:d,...a.resolution,auditEvent:a.auditEvent?.event};return r?JSON.stringify(t,null,2):[d,`requested=${t.requestedMode}`,`effective=${t.effectiveMode}`,`source=${t.source}`,`scope=${t.scope}`,`platform=${t.platformTarget}`,`reason=${t.effectiveReason}`,`fallback=${t.fallbackMode}`,`fallbackReason=${t.fallbackReasonCode??"none"}`].join(" ")}async function w(a,r={}){const t=r.stdout??console.log,n=r.stderr??console.error;let s="status",l,i=!1,f=!1;for(let e=0;e<a.length;e+=1){const o=a[e];if(o==="--json")i=!0;else if(o==="--platform-target"){if(l=a[e+1],e+=1,!l)return n("Error: --platform-target requires a value."),1}else if(!f&&(o==="status"||o==="max"||o==="standard"||o==="disabled"||o==="reset"))s=o,f=!0;else return n("Error: expected status, max, standard, disabled, or reset."),1}const p=r.env??process.env,u=m({cwd:r.cwd??process.cwd(),env:p,targetFlag:l}),g=v(u.targetId),c={configFilePath:r.configFilePath,platformTarget:u.targetId,hostPolicy:g,now:r.now};try{const e=s==="status"?b(c):s==="reset"?y(c):P(s,c);return t($(e,i)),0}catch(e){return e instanceof E?(n(`Error: ${e.reasonCode}`),1):(n("Error: approval-policy-update-failed"),1)}}export{w as configCliHandler};
@@ -15,8 +15,16 @@ import { type RunnerBootstrapPolicyDecision } from '../continuity/runner-bootstr
15
15
  import { type RunnerSchedulerBootstrapOptions, type RunnerSchedulerBootstrapResult } from '../runner/scheduler.js';
16
16
  import { type ContinuityProcessingSummaryCursorTarget } from '../continuity/continuity-client-state-store.js';
17
17
  import type { ProjectEvidenceEnvelope } from '../evidence/types.js';
18
+ import { type InvokeEffectContext, type StrictReadOnlyInvokeEnvelope } from '../../../shared/dist/strict-readonly.js';
19
+ import { type InvocationAdmissionResultV1 } from '../../../shared/dist/invocation/index.js';
18
20
  export declare const INVOKE_PAYLOAD_LIMIT_BYTES: number;
19
21
  export declare const INVOKE_PAYLOAD_WARNING_THRESHOLD_BYTES: number;
22
+ export declare function getOrCreatePendingEpicIdempotencyKey(projectRoot: string, args: string): {
23
+ readonly key: string;
24
+ readonly fingerprint: string;
25
+ };
26
+ export declare function clearPendingEpicIdempotencyKey(projectRoot: string, fingerprint: string): void;
27
+ export declare function recordPendingEpicReservation(projectRoot: string, fingerprint: string, claimId: string, epicId: string): void;
20
28
  interface InitProjectMemoryBootstrapSnapshot {
21
29
  readonly canonical: {
22
30
  readonly path: 'NEOCORTEX.md';
@@ -56,6 +64,8 @@ export interface InvokeOptions {
56
64
  readonly runnerBootstrapper?: InvokeRunnerSchedulerBootstrapper;
57
65
  /** Test/integration seam for recursion guard env; CLI callers leave unset. */
58
66
  readonly environment?: NodeJS.ProcessEnv;
67
+ /** P205.05 exact outer transport policy; never inferred from response metadata. */
68
+ readonly strictReadOnly?: boolean;
59
69
  }
60
70
  /**
61
71
  * Normalize the project root received from wrappers/CLI flags.
@@ -77,6 +87,8 @@ export interface InvokeResult {
77
87
  readonly errorCode?: string;
78
88
  readonly exitCode: number;
79
89
  }
90
+ /** P205.07 client parity guard. Pure and deliberately exported for driver tests. */
91
+ export declare function admitClientInvocation(args: string): InvocationAdmissionResultV1;
80
92
  type InvokeWatchFormat = 'plain' | 'json';
81
93
  interface InvokeWatchWritable {
82
94
  write(chunk: string): unknown;
@@ -95,6 +107,8 @@ export interface InvokeWatchOptions {
95
107
  readonly maxIdlePolls?: number;
96
108
  readonly maxPolls?: number;
97
109
  readonly sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
110
+ /** Keep watch polling on the physical read-only SQLite path. */
111
+ readonly strictReadOnly?: boolean;
98
112
  }
99
113
  type InvokeWatchTargetResolutionState = 'inactive' | 'pending' | 'resolved' | 'unresolved' | 'malformed' | 'ambiguous' | 'multiple' | 'unsafe' | 'unavailable';
100
114
  type InvokeWatchSnapshotStatus = 'not_requested' | 'pending' | 'available' | 'empty' | 'unavailable' | 'unsafe';
@@ -215,6 +229,7 @@ export interface InvokeRunnerAutoBootstrapOptions {
215
229
  readonly platformTarget: string;
216
230
  readonly environment?: NodeJS.ProcessEnv;
217
231
  readonly bootstrapper?: InvokeRunnerSchedulerBootstrapper;
232
+ readonly effectAuthority?: InvokeEffectContext;
218
233
  }
219
234
  export declare function sanitizeInvokeCliOutput(instructions: string | undefined, metadata: Record<string, unknown> | undefined): {
220
235
  instructions: string;
@@ -230,6 +245,7 @@ export interface InvokeCliParsedOptions {
230
245
  readonly commandLevelWatch?: InvokeCommandLevelWatchMetadata;
231
246
  readonly serverUrl?: string;
232
247
  readonly platformTarget?: string;
248
+ readonly strictReadOnly: boolean;
233
249
  }
234
250
  type InvokeCommandLevelWatchCommand = 'goal' | 'loop' | 'jobs';
235
251
  type InvokeCommandLevelWatchOperation = 'create' | 'start' | 'resume' | 'run-once' | 'watch';
@@ -351,6 +367,8 @@ export interface StateSummary {
351
367
  readonly epics: number;
352
368
  readonly storyStatus: Readonly<Record<string, number>>;
353
369
  readonly epicStatus: Readonly<Record<string, number>>;
370
+ readonly epicLifecycle?: Readonly<Record<EpicLifecycleClassification, number>>;
371
+ readonly activeEpics?: number;
354
372
  readonly blockedStories: number;
355
373
  };
356
374
  readonly active: {
@@ -367,6 +385,7 @@ export interface StateSummary {
367
385
  readonly reasonCodes: readonly string[];
368
386
  readonly publicSafe: true;
369
387
  }
388
+ export type EpicLifecycleClassification = 'active' | 'archived' | 'rolled-back' | 'synthetic' | 'orphan';
370
389
  export interface StateSnapshot {
371
390
  readonly schema_version?: number;
372
391
  readonly config: {
@@ -377,9 +396,15 @@ export interface StateSnapshot {
377
396
  readonly user_name?: string;
378
397
  readonly worktree_base?: string;
379
398
  readonly max_parallel_stories?: number;
399
+ readonly project_id?: string;
380
400
  };
381
401
  readonly stories: Record<string, Record<string, unknown>>;
382
402
  readonly epics: Record<string, Record<string, unknown>>;
403
+ /** Append-only public-safe reservations that prevent historical epic ID reuse. */
404
+ readonly epic_id_ledger?: {
405
+ readonly schema_version: 1;
406
+ readonly reserved_ids: readonly string[];
407
+ };
383
408
  readonly current_session?: StateSnapshotCurrentSession;
384
409
  /**
385
410
  * P141.01 -- request-only scope metadata. Never persisted to state.json.
@@ -425,6 +450,10 @@ export interface StateSnapshot {
425
450
  readonly projectEvidence?: ProjectEvidenceEnvelope;
426
451
  }
427
452
  export declare function shouldCollectProjectEvidenceForInvoke(args: string): boolean;
453
+ interface InvokeResponse {
454
+ readonly instructions: string;
455
+ readonly metadata: Record<string, unknown>;
456
+ }
428
457
  export interface InvokeArgsRef {
429
458
  readonly manifestId: string;
430
459
  readonly sha256?: string;
@@ -436,6 +465,11 @@ interface InvokeRequestBodyBase {
436
465
  readonly projectRoot: string;
437
466
  readonly stateSnapshot: StateSnapshot;
438
467
  readonly platformTarget?: string;
468
+ readonly projectId?: string;
469
+ readonly idempotencyKey?: string;
470
+ readonly registryVersion: string;
471
+ readonly registryChecksum: string;
472
+ readonly strictReadOnly?: StrictReadOnlyInvokeEnvelope;
439
473
  }
440
474
  export type InvokeRequestBody = InvokeRequestBodyBase & ({
441
475
  readonly args: string;
@@ -503,6 +537,28 @@ export declare function __resetSchemaDriftWarnedForTests(): void;
503
537
  */
504
538
  export declare function collectStateSnapshot(projectRoot: string): StateSnapshot;
505
539
  export declare function createFullStateSnapshotScope(trigger: string, snapshot: Pick<StateSnapshot, 'stories' | 'epics'>): FullStateSnapshotScope;
540
+ interface SendResult {
541
+ readonly ok: boolean;
542
+ readonly status: number;
543
+ readonly data?: InvokeResponse;
544
+ readonly error?: string;
545
+ readonly errorBody?: Record<string, unknown>;
546
+ }
547
+ export interface InvokePhysicalRetryOptions {
548
+ readonly refreshToken?: () => Promise<string | null>;
549
+ readonly onTokenChanged?: (token: string) => void;
550
+ readonly sleep?: (milliseconds: number) => Promise<void>;
551
+ readonly maxAttempts?: number;
552
+ readonly allowReplayRetry?: boolean;
553
+ }
554
+ export declare function buildSignedInvokeAttempt(path: string, body: Record<string, unknown>, authToken: string, options?: {
555
+ readonly nowSeconds?: number;
556
+ readonly nonceBytes?: Uint8Array;
557
+ }): {
558
+ readonly body: Buffer;
559
+ readonly headers: Record<string, string>;
560
+ };
561
+ export declare function postMaterializationJson(serverUrl: string, path: string, body: Record<string, unknown>, authToken: string, retryOptions?: InvokePhysicalRetryOptions): Promise<Record<string, unknown>>;
506
562
  export declare function computeInvokeRequestBodySizeBytes(body: InvokeRequestBody): number;
507
563
  export declare function createInvokePayloadTelemetry(body: InvokeRequestBody, payloadBytes?: number, reasonCodes?: readonly string[], options?: {
508
564
  readonly limitBytes?: number;
@@ -517,6 +573,14 @@ export declare function maybeRunInvokeRunnerAutoBootstrap(options: InvokeRunnerA
517
573
  export declare function watchContinuityProcessingSummaries(options: InvokeWatchOptions): Promise<InvokeWatchResult>;
518
574
  export declare function resolveInvokeCommandLevelWatch(args: string): InvokeCommandLevelWatchResolution;
519
575
  export declare function resolveInvokeWatchTarget(metadata: Record<string, unknown> | undefined, args: string): InvokeWatchTarget;
576
+ export declare function sendInvokeRequest(serverUrl: string, body: InvokeRequestBody, authToken: string, retryOptions?: InvokePhysicalRetryOptions): Promise<SendResult>;
577
+ export declare function sendEpicClaimAcknowledgement(serverUrl: string, authToken: string, input: {
578
+ readonly claimId: string;
579
+ readonly projectId: string;
580
+ readonly epicId: string;
581
+ readonly status: 'materialized' | 'abandoned';
582
+ }, retryOptions?: InvokePhysicalRetryOptions): Promise<boolean>;
583
+ export declare function acknowledgeMaterializedPendingEpicClaims(projectRoot: string, stateSnapshot: StateSnapshot, serverUrl: string, authToken: string, projectId: string | undefined, retryOptions?: InvokePhysicalRetryOptions): Promise<number>;
520
584
  /**
521
585
  * Execute the invoke command.
522
586
  *