@ornexus/neocortex 4.59.1

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 (197) hide show
  1. package/LICENSE +56 -0
  2. package/LICENSE-COMMERCIAL.md +70 -0
  3. package/README.md +58 -0
  4. package/dist/sbom.cdx.json +7067 -0
  5. package/docs/install/coderabbit-manual-setup.md +86 -0
  6. package/docs/install/installer-diagnostics.md +107 -0
  7. package/docs/install/linux-global-install.md +97 -0
  8. package/install.js +572 -0
  9. package/install.ps1 +2214 -0
  10. package/install.sh +2013 -0
  11. package/package.json +118 -0
  12. package/packages/client/dist/adapters/adapter-registry.d.ts +61 -0
  13. package/packages/client/dist/adapters/adapter-registry.js +1 -0
  14. package/packages/client/dist/adapters/antigravity-adapter.d.ts +18 -0
  15. package/packages/client/dist/adapters/antigravity-adapter.js +2 -0
  16. package/packages/client/dist/adapters/claude-code-adapter.d.ts +19 -0
  17. package/packages/client/dist/adapters/claude-code-adapter.js +3 -0
  18. package/packages/client/dist/adapters/codex-adapter.d.ts +19 -0
  19. package/packages/client/dist/adapters/codex-adapter.js +2 -0
  20. package/packages/client/dist/adapters/cursor-adapter.d.ts +19 -0
  21. package/packages/client/dist/adapters/cursor-adapter.js +4 -0
  22. package/packages/client/dist/adapters/gemini-adapter.d.ts +18 -0
  23. package/packages/client/dist/adapters/gemini-adapter.js +2 -0
  24. package/packages/client/dist/adapters/index.d.ts +19 -0
  25. package/packages/client/dist/adapters/index.js +1 -0
  26. package/packages/client/dist/adapters/platform-detector.d.ts +48 -0
  27. package/packages/client/dist/adapters/platform-detector.js +1 -0
  28. package/packages/client/dist/adapters/target-adapter.d.ts +70 -0
  29. package/packages/client/dist/adapters/target-adapter.js +0 -0
  30. package/packages/client/dist/adapters/vscode-adapter.d.ts +19 -0
  31. package/packages/client/dist/adapters/vscode-adapter.js +2 -0
  32. package/packages/client/dist/agent/refresh-stubs.d.ts +80 -0
  33. package/packages/client/dist/agent/refresh-stubs.js +2 -0
  34. package/packages/client/dist/agent/update-agent-yaml.d.ts +26 -0
  35. package/packages/client/dist/agent/update-agent-yaml.js +1 -0
  36. package/packages/client/dist/agent/update-description.d.ts +45 -0
  37. package/packages/client/dist/agent/update-description.js +1 -0
  38. package/packages/client/dist/cache/crypto-utils.d.ts +30 -0
  39. package/packages/client/dist/cache/crypto-utils.js +1 -0
  40. package/packages/client/dist/cache/encrypted-cache.d.ts +30 -0
  41. package/packages/client/dist/cache/encrypted-cache.js +1 -0
  42. package/packages/client/dist/cache/in-memory-asset-cache.d.ts +62 -0
  43. package/packages/client/dist/cache/in-memory-asset-cache.js +1 -0
  44. package/packages/client/dist/cache/index.d.ts +13 -0
  45. package/packages/client/dist/cache/index.js +1 -0
  46. package/packages/client/dist/cache/protected-pi-boundary.d.ts +19 -0
  47. package/packages/client/dist/cache/protected-pi-boundary.js +1 -0
  48. package/packages/client/dist/checkpoint/checkpoint-client-reader.d.ts +45 -0
  49. package/packages/client/dist/checkpoint/checkpoint-client-reader.js +2 -0
  50. package/packages/client/dist/checkpoint/index.d.ts +12 -0
  51. package/packages/client/dist/checkpoint/index.js +1 -0
  52. package/packages/client/dist/checkpoint/shared-checkpoint-types.d.ts +85 -0
  53. package/packages/client/dist/checkpoint/shared-checkpoint-types.js +1 -0
  54. package/packages/client/dist/cli.d.ts +14 -0
  55. package/packages/client/dist/cli.js +48 -0
  56. package/packages/client/dist/commands/activate.d.ts +55 -0
  57. package/packages/client/dist/commands/activate.js +8 -0
  58. package/packages/client/dist/commands/cache-status.d.ts +39 -0
  59. package/packages/client/dist/commands/cache-status.js +2 -0
  60. package/packages/client/dist/commands/invoke.d.ts +229 -0
  61. package/packages/client/dist/commands/invoke.js +63 -0
  62. package/packages/client/dist/commands/refresh-memory.d.ts +11 -0
  63. package/packages/client/dist/commands/refresh-memory.js +1 -0
  64. package/packages/client/dist/config/resolver-selection.d.ts +40 -0
  65. package/packages/client/dist/config/resolver-selection.js +1 -0
  66. package/packages/client/dist/config/secure-config.d.ts +78 -0
  67. package/packages/client/dist/config/secure-config.js +12 -0
  68. package/packages/client/dist/constants.d.ts +25 -0
  69. package/packages/client/dist/constants.js +1 -0
  70. package/packages/client/dist/context/context-collector.d.ts +28 -0
  71. package/packages/client/dist/context/context-collector.js +2 -0
  72. package/packages/client/dist/context/context-sanitizer.d.ts +28 -0
  73. package/packages/client/dist/context/context-sanitizer.js +1 -0
  74. package/packages/client/dist/continuity/continuity-client-state-store.d.ts +183 -0
  75. package/packages/client/dist/continuity/continuity-client-state-store.js +1 -0
  76. package/packages/client/dist/continuity/invoke-hooks.d.ts +18 -0
  77. package/packages/client/dist/continuity/invoke-hooks.js +1 -0
  78. package/packages/client/dist/continuity/migrations/001-initial-schema.d.ts +11 -0
  79. package/packages/client/dist/continuity/migrations/001-initial-schema.js +263 -0
  80. package/packages/client/dist/continuity/sqlite-store.d.ts +409 -0
  81. package/packages/client/dist/continuity/sqlite-store.js +226 -0
  82. package/packages/client/dist/errors/error-messages.d.ts +40 -0
  83. package/packages/client/dist/errors/error-messages.js +2 -0
  84. package/packages/client/dist/graph-retrieval/pre-command-hook.d.ts +31 -0
  85. package/packages/client/dist/graph-retrieval/pre-command-hook.js +1 -0
  86. package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.d.ts +77 -0
  87. package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +1 -0
  88. package/packages/client/dist/i18n/first-run.d.ts +23 -0
  89. package/packages/client/dist/i18n/first-run.js +2 -0
  90. package/packages/client/dist/index.d.ts +56 -0
  91. package/packages/client/dist/index.js +1 -0
  92. package/packages/client/dist/license/index.d.ts +5 -0
  93. package/packages/client/dist/license/index.js +1 -0
  94. package/packages/client/dist/license/license-client.d.ts +79 -0
  95. package/packages/client/dist/license/license-client.js +1 -0
  96. package/packages/client/dist/machine/fingerprint.d.ts +34 -0
  97. package/packages/client/dist/machine/fingerprint.js +2 -0
  98. package/packages/client/dist/machine/index.d.ts +5 -0
  99. package/packages/client/dist/machine/index.js +1 -0
  100. package/packages/client/dist/memory/project-memory-writer.d.ts +74 -0
  101. package/packages/client/dist/memory/project-memory-writer.js +36 -0
  102. package/packages/client/dist/memory/shared-project-memory-types.d.ts +370 -0
  103. package/packages/client/dist/memory/shared-project-memory-types.js +2 -0
  104. package/packages/client/dist/policy/architecture-policy.d.ts +40 -0
  105. package/packages/client/dist/policy/architecture-policy.js +2 -0
  106. package/packages/client/dist/policy/index.d.ts +8 -0
  107. package/packages/client/dist/policy/index.js +1 -0
  108. package/packages/client/dist/policy/shared-policy-types.d.ts +89 -0
  109. package/packages/client/dist/policy/shared-policy-types.js +0 -0
  110. package/packages/client/dist/resilience/circuit-breaker.d.ts +70 -0
  111. package/packages/client/dist/resilience/circuit-breaker.js +1 -0
  112. package/packages/client/dist/resilience/degradation-manager.d.ts +67 -0
  113. package/packages/client/dist/resilience/degradation-manager.js +1 -0
  114. package/packages/client/dist/resilience/freshness-indicator.d.ts +59 -0
  115. package/packages/client/dist/resilience/freshness-indicator.js +1 -0
  116. package/packages/client/dist/resilience/index.d.ts +8 -0
  117. package/packages/client/dist/resilience/index.js +1 -0
  118. package/packages/client/dist/resilience/recovery-detector.d.ts +59 -0
  119. package/packages/client/dist/resilience/recovery-detector.js +1 -0
  120. package/packages/client/dist/resolvers/asset-resolver.d.ts +79 -0
  121. package/packages/client/dist/resolvers/asset-resolver.js +0 -0
  122. package/packages/client/dist/resolvers/local-resolver.d.ts +26 -0
  123. package/packages/client/dist/resolvers/local-resolver.js +8 -0
  124. package/packages/client/dist/resolvers/remote-resolver.d.ts +91 -0
  125. package/packages/client/dist/resolvers/remote-resolver.js +1 -0
  126. package/packages/client/dist/runner/cli.d.ts +121 -0
  127. package/packages/client/dist/runner/cli.js +20 -0
  128. package/packages/client/dist/runner/scheduler.d.ts +116 -0
  129. package/packages/client/dist/runner/scheduler.js +6 -0
  130. package/packages/client/dist/runner-cli.d.ts +9 -0
  131. package/packages/client/dist/runner-cli.js +3 -0
  132. package/packages/client/dist/state/project-state-snapshot.d.ts +15 -0
  133. package/packages/client/dist/state/project-state-snapshot.js +1 -0
  134. package/packages/client/dist/state/state-json-repair.d.ts +17 -0
  135. package/packages/client/dist/state/state-json-repair.js +3 -0
  136. package/packages/client/dist/telemetry/index.d.ts +5 -0
  137. package/packages/client/dist/telemetry/index.js +1 -0
  138. package/packages/client/dist/telemetry/offline-queue.d.ts +57 -0
  139. package/packages/client/dist/telemetry/offline-queue.js +1 -0
  140. package/packages/client/dist/tier/index.d.ts +5 -0
  141. package/packages/client/dist/tier/index.js +1 -0
  142. package/packages/client/dist/tier/tier-aware-client.d.ts +105 -0
  143. package/packages/client/dist/tier/tier-aware-client.js +1 -0
  144. package/packages/client/dist/types/index.d.ts +140 -0
  145. package/packages/client/dist/types/index.js +1 -0
  146. package/packages/client/dist/yoloop/discovery-hook.d.ts +85 -0
  147. package/packages/client/dist/yoloop/discovery-hook.js +2 -0
  148. package/packages/client/dist/yoloop/index.d.ts +10 -0
  149. package/packages/client/dist/yoloop/index.js +1 -0
  150. package/packages/client/dist/yoloop/invoke-hooks.d.ts +125 -0
  151. package/packages/client/dist/yoloop/invoke-hooks.js +5 -0
  152. package/packages/client/dist/yoloop/shared-discover-epics.d.ts +289 -0
  153. package/packages/client/dist/yoloop/shared-discover-epics.js +1 -0
  154. package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +172 -0
  155. package/packages/client/dist/yoloop/shared-yoloop-types.js +1 -0
  156. package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +124 -0
  157. package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -0
  158. package/postinstall.js +754 -0
  159. package/targets-stubs/antigravity/README.md +36 -0
  160. package/targets-stubs/antigravity/gemini.md +29 -0
  161. package/targets-stubs/antigravity/install-antigravity.sh +153 -0
  162. package/targets-stubs/antigravity/mcp-config.json +30 -0
  163. package/targets-stubs/antigravity/skill/SKILL.md +159 -0
  164. package/targets-stubs/claude-code/.mcp.json +32 -0
  165. package/targets-stubs/claude-code/README.md +20 -0
  166. package/targets-stubs/claude-code/neocortex-root.agent.yaml +42 -0
  167. package/targets-stubs/claude-code/neocortex-root.md +310 -0
  168. package/targets-stubs/claude-code/neocortex.agent.yaml +42 -0
  169. package/targets-stubs/claude-code/neocortex.md +378 -0
  170. package/targets-stubs/codex/AGENTS.md +244 -0
  171. package/targets-stubs/codex/README.md +47 -0
  172. package/targets-stubs/codex/config-mcp.toml +22 -0
  173. package/targets-stubs/codex/install-codex.sh +63 -0
  174. package/targets-stubs/codex/neocortex.toml +29 -0
  175. package/targets-stubs/cursor/README.md +33 -0
  176. package/targets-stubs/cursor/agent.md +204 -0
  177. package/targets-stubs/cursor/install-cursor.sh +50 -0
  178. package/targets-stubs/cursor/mcp.json +30 -0
  179. package/targets-stubs/gemini-cli/README.md +34 -0
  180. package/targets-stubs/gemini-cli/agent.md +234 -0
  181. package/targets-stubs/gemini-cli/agents/neocortex.md +54 -0
  182. package/targets-stubs/gemini-cli/gemini.md +46 -0
  183. package/targets-stubs/gemini-cli/install-gemini.sh +70 -0
  184. package/targets-stubs/gemini-cli/settings-mcp.json +30 -0
  185. package/targets-stubs/kimi/mcp.json +33 -0
  186. package/targets-stubs/kimi/neocortex.md +54 -0
  187. package/targets-stubs/lib/mcp-merge.js +189 -0
  188. package/targets-stubs/openclaw/README.md +12 -0
  189. package/targets-stubs/openclaw/SKILL.md +88 -0
  190. package/targets-stubs/opencode/neocortex-root.md +261 -0
  191. package/targets-stubs/opencode/neocortex.md +59 -0
  192. package/targets-stubs/opencode/opencode-mcp.json +35 -0
  193. package/targets-stubs/vscode/README.md +34 -0
  194. package/targets-stubs/vscode/copilot-instructions.md +47 -0
  195. package/targets-stubs/vscode/install-vscode.sh +72 -0
  196. package/targets-stubs/vscode/mcp.json +36 -0
  197. package/targets-stubs/vscode/neocortex.agent.md +245 -0
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P180.07 -- user-scope scheduler install/start/stop/status/doctor for
6
+ * `neocortex-runner`.
7
+ */
8
+ export declare const SCHEDULER_REASON_CODES: Readonly<{
9
+ readonly OK: "continuity-ok";
10
+ readonly SCHEDULER_INSTALL_UNSAFE: "scheduler-install-unsafe";
11
+ readonly PRIMARY_USER_SCHEDULER_UNAVAILABLE: "primary-user-scheduler-unavailable";
12
+ readonly CRON_FALLBACK_SELECTED: "cron-fallback-selected";
13
+ readonly CRON_FALLBACK_NOT_ALLOWED: "cron-fallback-primary-scheduler-available";
14
+ readonly SCHEDULER_UNAVAILABLE: "scheduler-unavailable";
15
+ readonly SCHEDULER_COMMAND_FAILED: "scheduler-command-failed";
16
+ readonly RUNNER_BINARY_UNTRUSTED: "runner-binary-untrusted";
17
+ }>;
18
+ export type SchedulerReasonCode = (typeof SCHEDULER_REASON_CODES)[keyof typeof SCHEDULER_REASON_CODES] | string;
19
+ export type SchedulerCommand = 'install' | 'start' | 'stop' | 'status' | 'doctor';
20
+ export type SchedulerStrategy = 'systemd-user' | 'launchd-user' | 'windows-task-scheduler' | 'cron-fallback';
21
+ export interface SchedulerBinaryTrustResult {
22
+ readonly trusted: boolean;
23
+ readonly reasonCode?: string;
24
+ readonly packageName?: string;
25
+ readonly packageVersion?: string;
26
+ readonly executablePath?: string;
27
+ readonly expectedRelativePath?: string;
28
+ readonly publicSafe: true;
29
+ }
30
+ export interface SchedulerManifest {
31
+ readonly kind: 'systemd-service' | 'systemd-timer' | 'launchd-plist' | 'windows-task-xml' | 'cron-snippet';
32
+ readonly path: string;
33
+ readonly content: string;
34
+ readonly publicSafe: true;
35
+ }
36
+ export interface SchedulerControlCommand {
37
+ readonly command: string;
38
+ readonly args: readonly string[];
39
+ readonly preview: string;
40
+ readonly safeUserScope: true;
41
+ readonly manualOnly?: boolean;
42
+ }
43
+ export interface SchedulerCommandRunResult {
44
+ readonly ok: boolean;
45
+ readonly code?: number | null;
46
+ readonly signal?: string | null;
47
+ readonly reasonCode?: string;
48
+ }
49
+ export interface SchedulerCapabilityReport {
50
+ readonly platform: NodeJS.Platform;
51
+ readonly primaryStrategy?: SchedulerStrategy;
52
+ readonly selectedStrategy?: SchedulerStrategy;
53
+ readonly fallbackStrategy?: SchedulerStrategy;
54
+ readonly primaryAvailable: boolean;
55
+ readonly cronFallbackAvailable: boolean;
56
+ readonly safeToInstall: boolean;
57
+ readonly blockers: readonly SchedulerReasonCode[];
58
+ readonly reasonCodes: readonly SchedulerReasonCode[];
59
+ readonly publicSafe: true;
60
+ }
61
+ export interface RunnerSchedulerCommandOptions {
62
+ readonly command: SchedulerCommand;
63
+ readonly projectRoot?: string;
64
+ readonly executablePath?: string;
65
+ readonly platform?: NodeJS.Platform;
66
+ readonly env?: NodeJS.ProcessEnv;
67
+ readonly dryRun?: boolean;
68
+ readonly intervalSeconds?: number;
69
+ readonly strategy?: SchedulerStrategy;
70
+ readonly allowCronFallback?: boolean;
71
+ readonly trustCheck?: boolean;
72
+ readonly uid?: number | null;
73
+ readonly commandAvailable?: (command: string) => boolean;
74
+ readonly commandRunner?: (command: SchedulerControlCommand) => SchedulerCommandRunResult;
75
+ readonly trustChecker?: (executablePath: string | undefined) => SchedulerBinaryTrustResult;
76
+ readonly now?: () => string;
77
+ }
78
+ export interface RunnerSchedulerCommandResult {
79
+ readonly ok: boolean;
80
+ readonly command: SchedulerCommand;
81
+ readonly platform: NodeJS.Platform;
82
+ readonly strategy?: SchedulerStrategy;
83
+ readonly dryRun: boolean;
84
+ readonly manifestPaths: readonly string[];
85
+ readonly manifests: readonly SchedulerManifest[];
86
+ readonly controlCommands: readonly SchedulerControlCommand[];
87
+ readonly uninstallGuidance: readonly string[];
88
+ readonly capability: SchedulerCapabilityReport;
89
+ readonly reasonCodes: readonly SchedulerReasonCode[];
90
+ readonly applied: boolean;
91
+ readonly publicSafe: true;
92
+ }
93
+ export declare function runRunnerSchedulerCommand(options: RunnerSchedulerCommandOptions): Promise<RunnerSchedulerCommandResult>;
94
+ export declare function detectSchedulerCapability(input?: {
95
+ readonly platform?: NodeJS.Platform;
96
+ readonly env?: NodeJS.ProcessEnv;
97
+ readonly strategy?: SchedulerStrategy;
98
+ readonly allowCronFallback?: boolean;
99
+ readonly uid?: number | null;
100
+ readonly commandAvailable?: (command: string) => boolean;
101
+ }): SchedulerCapabilityReport;
102
+ export declare function renderSchedulerManifests(input: {
103
+ readonly strategy: SchedulerStrategy;
104
+ readonly paths: SchedulerPaths;
105
+ readonly projectRoot: string;
106
+ readonly executablePath: string;
107
+ readonly intervalSeconds: number;
108
+ }): readonly SchedulerManifest[];
109
+ interface SchedulerPaths {
110
+ readonly systemdServicePath: string;
111
+ readonly systemdTimerPath: string;
112
+ readonly launchdPlistPath: string;
113
+ readonly windowsTaskXmlPath: string;
114
+ readonly cronSnippetPath: string;
115
+ }
116
+ export {};
@@ -0,0 +1,6 @@
1
+ import{spawnSync as W}from"node:child_process";import{existsSync as w,mkdirSync as K,writeFileSync as X}from"node:fs";import{delimiter as V,dirname as Y,isAbsolute as _,join as u,resolve as G}from"node:path";const s=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"}),F="neocortex-runner",$=`${F}.service`,E=`${F}.timer`,T="com.ornexus.neocortex.runner",Q=`${T}.plist`,k="NeocortexRunner",q="neocortex-runner-task.xml",z="runner.cron",Z=60;async function ge(e){const t=e.env??process.env,r=e.platform??process.platform,a=e.dryRun===!0,c=y(e.projectRoot??process.cwd()),n=y(e.executablePath??process.argv[1]),m=e.commandAvailable??(p=>H(p,t)),f=Ee(e.intervalSeconds??Z,10,1440*60),h=J({platform:r,env:t,strategy:e.strategy,allowCronFallback:e.allowCronFallback,commandAvailable:m,uid:e.uid}),d=me(e,n),i=[...h.blockers];(!c||!n)&&i.push(s.SCHEDULER_INSTALL_UNSAFE),d.trusted||i.push(s.SCHEDULER_INSTALL_UNSAFE,s.RUNNER_BINARY_UNTRUSTED);const l=h.selectedStrategy;l||i.push(s.SCHEDULER_UNAVAILABLE);const g=(e.command==="install"||e.command==="start"||e.command==="stop")&&i.length>0,U=A([...h.reasonCodes,...i,g?s.SCHEDULER_INSTALL_UNSAFE:s.OK]);if(g||!l||!c||!n)return{ok:!g&&!!l,command:e.command,platform:r,strategy:l,dryRun:a,manifestPaths:[],manifests:[],controlCommands:[],uninstallGuidance:l?v(l,M(l,t)):[],capability:j(h,i),reasonCodes:U,applied:!1,publicSafe:!0};const C=M(l,t),L=e.command==="install"?ee({strategy:l,paths:C,projectRoot:c,executablePath:n,intervalSeconds:f}):[],R=te(e.command,l,C);let b=!1,D=!0;const I=[];if(e.command==="install"&&!a){for(const p of L)K(Y(p.path),{recursive:!0}),X(p.path,p.content,"utf8");b=L.length>0}if(!a&&R.length>0){const p=e.commandRunner??pe;for(const O of R){if(O.manualOnly)continue;const x=p(O);x.ok?b=!0:(D=!1,I.push(x.reasonCode??s.SCHEDULER_COMMAND_FAILED))}}return{ok:D,command:e.command,platform:r,strategy:l,dryRun:a,manifestPaths:L.map(p=>p.path),manifests:L,controlCommands:R,uninstallGuidance:v(l,C),capability:j(h,i),reasonCodes:A([...U,...I,D?s.OK:s.SCHEDULER_COMMAND_FAILED]),applied:b,publicSafe:!0}}function J(e={}){const t=e.env??process.env,r=e.platform??process.platform,a=e.commandAvailable??(l=>H(l,t)),c=fe(r,t,e.uid),n=de(r),m=n?B(n,a):!1,f=r!=="win32"&&a("crontab"),h=e.allowCronFallback!==!1;let d=e.strategy;const i=[];return d||(n&&m?d=n:h&&f&&(d="cron-fallback",i.push(s.PRIMARY_USER_SCHEDULER_UNAVAILABLE,s.CRON_FALLBACK_SELECTED))),d==="cron-fallback"&&m&&(d=void 0,i.push(s.CRON_FALLBACK_NOT_ALLOWED)),d&&!B(d,a)&&(d!=="cron-fallback"||!f)&&(d=void 0),d||i.push(s.SCHEDULER_UNAVAILABLE),c.length>0&&i.push(...c),i.length===0&&i.push(s.OK),{platform:r,primaryStrategy:n,selectedStrategy:d,fallbackStrategy:f?"cron-fallback":void 0,primaryAvailable:m,cronFallbackAvailable:f,safeToInstall:c.length===0,blockers:c,reasonCodes:A(i),publicSafe:!0}}function ee(e){switch(e.strategy){case"systemd-user":return[{kind:"systemd-service",path:e.paths.systemdServicePath,content:oe(e.executablePath,e.projectRoot),publicSafe:!0},{kind:"systemd-timer",path:e.paths.systemdTimerPath,content:ce(e.intervalSeconds),publicSafe:!0}];case"launchd-user":return[{kind:"launchd-plist",path:e.paths.launchdPlistPath,content:ie(e.executablePath,e.projectRoot,e.intervalSeconds),publicSafe:!0}];case"windows-task-scheduler":return[{kind:"windows-task-xml",path:e.paths.windowsTaskXmlPath,content:le(e.executablePath,e.projectRoot,e.intervalSeconds),publicSafe:!0}];case"cron-fallback":return[{kind:"cron-snippet",path:e.paths.cronSnippetPath,content:ue(e.executablePath,e.projectRoot),publicSafe:!0}]}}function M(e,t){const r=he(t),a=y(t.XDG_CONFIG_HOME)??u(r,".config"),c=u(a,"systemd","user"),n=u(r,"Library","LaunchAgents"),m=y(t.APPDATA)??u(y(t.USERPROFILE)??r,"AppData","Roaming"),f=u(m,"Neocortex","Runner"),h=u(a,"neocortex");return{systemdServicePath:u(c,$),systemdTimerPath:u(c,E),launchdPlistPath:u(n,Q),windowsTaskXmlPath:u(f,q),cronSnippetPath:u(h,z)}}function te(e,t,r){return e==="doctor"?[]:e==="install"?re(t,r):e==="start"?ne(t,r):e==="stop"?se(t,r):ae(t,r)}function re(e,t){switch(e){case"systemd-user":return[o("systemctl",["--user","daemon-reload"]),o("systemctl",["--user","enable","--now",E])];case"launchd-user":return[o("launchctl",["load","-w",t.launchdPlistPath])];case"windows-task-scheduler":return[o("schtasks",["/Create","/TN",k,"/XML",t.windowsTaskXmlPath,"/F"])];case"cron-fallback":return[o("crontab",["-l","# append snippet from",t.cronSnippetPath],!0)]}}function ne(e,t){switch(e){case"systemd-user":return[o("systemctl",["--user","start",E])];case"launchd-user":return[o("launchctl",["load","-w",t.launchdPlistPath])];case"windows-task-scheduler":return[o("schtasks",["/Run","/TN",k])];case"cron-fallback":return[o("crontab",["-l","# ensure snippet from",t.cronSnippetPath,"is installed"],!0)]}}function se(e,t){switch(e){case"systemd-user":return[o("systemctl",["--user","stop",E])];case"launchd-user":return[o("launchctl",["unload","-w",t.launchdPlistPath])];case"windows-task-scheduler":return[o("schtasks",["/End","/TN",k])];case"cron-fallback":return[o("crontab",["-l","# remove neocortex-runner snippet"],!0)]}}function ae(e,t){switch(e){case"systemd-user":return[o("systemctl",["--user","status",E,"--no-pager"])];case"launchd-user":return[o("launchctl",["list",T])];case"windows-task-scheduler":return[o("schtasks",["/Query","/TN",k,"/FO","LIST"])];case"cron-fallback":return[o("crontab",["-l","# look for neocortex-runner snippet from",t.cronSnippetPath],!0)]}}function v(e,t){switch(e){case"systemd-user":return[`systemctl --user disable --now ${E}`,`rm ${t.systemdServicePath}`,`rm ${t.systemdTimerPath}`];case"launchd-user":return[`launchctl unload -w ${t.launchdPlistPath}`,`rm ${t.launchdPlistPath}`];case"windows-task-scheduler":return[`schtasks /Delete /TN ${k} /F`,`Remove-Item ${t.windowsTaskXmlPath}`];case"cron-fallback":return["Remove the # neocortex-runner snippet from the user crontab.",`rm ${t.cronSnippetPath}`]}}function oe(e,t){return["[Unit]","Description=Neocortex Enterprise Continuity Runner (user scope)","After=network-online.target","","[Service]","Type=oneshot",`WorkingDirectory=${N(t)}`,`ExecStart=${N(e)} tick --project-root ${N(t)}`,"","[Install]","WantedBy=default.target",""].join(`
2
+ `)}function ce(e){return["[Unit]","Description=Run Neocortex Enterprise Continuity Runner periodically (user scope)","","[Timer]","OnBootSec=60s",`OnUnitActiveSec=${e}s`,`Unit=${$}`,"","[Install]","WantedBy=timers.target",""].join(`
3
+ `)}function ie(e,t,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>"," <key>Label</key>",` <string>${S(T)}</string>`," <key>ProgramArguments</key>"," <array>",` <string>${S(e)}</string>`," <string>tick</string>"," <string>--project-root</string>",` <string>${S(t)}</string>`," </array>"," <key>WorkingDirectory</key>",` <string>${S(t)}</string>`," <key>StartInterval</key>",` <integer>${r}</integer>`," <key>RunAtLoad</key>"," <true/>","</dict>","</plist>",""].join(`
4
+ `)}function le(e,t,r){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 (user scope)</Description>"," </RegistrationInfo>"," <Triggers>"," <TimeTrigger>"," <Repetition>",` <Interval>PT${r}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>${S(e)}</Command>`,` <Arguments>tick --project-root ${S(Se(t))}</Arguments>`,` <WorkingDirectory>${S(t)}</WorkingDirectory>`," </Exec>"," </Actions>","</Task>",""].join(`
5
+ `)}function ue(e,t){return["# neocortex-runner user-scope cron fallback","# Reason: primary-user-scheduler-unavailable",`* * * * * ${P(e)} tick --project-root ${P(t)} # neocortex-runner`,""].join(`
6
+ `)}function de(e){if(e==="linux")return"systemd-user";if(e==="darwin")return"launchd-user";if(e==="win32")return"windows-task-scheduler"}function B(e,t){switch(e){case"systemd-user":return t("systemctl");case"launchd-user":return t("launchctl");case"windows-task-scheduler":return t("schtasks")||t("schtasks.exe");case"cron-fallback":return t("crontab")}}function fe(e,t,r){const a=[],c=r??(typeof process.getuid=="function"?process.getuid():null);e!=="win32"&&c===0&&a.push(s.SCHEDULER_INSTALL_UNSAFE),e!=="win32"&&(t.SUDO_USER||t.SUDO_UID||t.SUDO_COMMAND)&&a.push(s.SCHEDULER_INSTALL_UNSAFE);const n=t.HOME??t.USERPROFILE;return(!n||!_(n)||!y(n))&&a.push(s.SCHEDULER_INSTALL_UNSAFE),A(a)}function me(e,t){return e.trustCheck===!1?{trusted:!0,executablePath:t??void 0,publicSafe:!0}:e.trustChecker?e.trustChecker(t??void 0):{trusted:!1,reasonCode:s.RUNNER_BINARY_UNTRUSTED,executablePath:t??void 0,publicSafe:!0}}function he(e){return e.HOME??e.USERPROFILE??process.env.HOME??process.cwd()}function y(e){if(!e||/[\r\n\0]/.test(e))return null;const t=_(e)?e:G(e);return _(t)?t:null}function o(e,t,r=!1){return{command:e,args:t,preview:[e,...t.map(P)].join(" "),safeUserScope:!0,...r?{manualOnly:!0}:{}}}function pe(e){const t=W(e.command,[...e.args],{stdio:"ignore",shell:!1});return{ok:t.status===0,code:t.status,signal:t.signal,reasonCode:t.status===0?s.OK:s.SCHEDULER_COMMAND_FAILED}}function H(e,t){const r=t.PATH??process.env.PATH??"",a=(t.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean),c=r.split(V).filter(Boolean);for(const n of c){const m=u(n,e);if(w(m))return!0;for(const f of a)if(w(u(n,`${e}${f.toLowerCase()}`))||w(u(n,`${e}${f.toUpperCase()}`)))return!0}return!1}function j(e,t){const r=A([...e.blockers,...t]);return{...e,safeToInstall:r.length===0,blockers:r,reasonCodes:A([...e.reasonCodes,...r])}}function N(e){return/[\s"'\\]/.test(e)?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:e}function P(e){return/^[A-Za-z0-9_./:=@%+-]+$/.test(e)?e:`'${e.replace(/'/g,"'\\''")}'`}function Se(e){return/[\s"]/.test(e)?`"${e.replace(/"/g,'\\"')}"`:e}function S(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function Ee(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,Math.floor(e))):t}function A(e){return Array.from(new Set(e))}export{s as SCHEDULER_REASON_CODES,J as detectSchedulerCapability,ee as renderSchedulerManifests,ge as runRunnerSchedulerCommand};
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @license FSL-1.1
4
+ * Copyright (c) 2026 OrNexus AI
5
+ *
6
+ * Published neocortex-runner binary shim. The implementation lives in
7
+ * `runner/cli.ts`; this top-level source emits `dist/runner-cli.js`.
8
+ */
9
+ export {};
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import{runRunnerCli as r}from"./runner/cli.js";r(process.argv.slice(2)).then(e=>{process.exit(e)}).catch(e=>{const s=e instanceof Error?e.message:String(e);process.stderr.write(JSON.stringify({error_code:"runner-fatal",message:s})+`
3
+ `),process.exit(1)});
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * Pure request-scoped projection helpers for invoke state snapshots.
6
+ */
7
+ import type { StateSnapshot } from '../commands/invoke.js';
8
+ /**
9
+ * Return a request-scoped state snapshot for explicit story-targeted commands.
10
+ *
11
+ * The function is intentionally pure and fail-open. If it cannot prove a safe
12
+ * target story + parent epic from the already-sanitized snapshot, it returns a
13
+ * full scoped snapshot instead of guessing.
14
+ */
15
+ export declare function projectStateSnapshotForInvoke(args: string, snapshot: StateSnapshot): StateSnapshot;
@@ -0,0 +1 @@
1
+ const A=new Set(["yolo","implement","diagnose","research","write-spec","create-tasks","refactor-suggest","property-tests","validate-tests","qa-gate","update-project-memory","commit-push","sync-main","create-pr","review-pr","merge-pr","review"]),O=new Set(["yoloop","auto-yolo","epic-runner","story-runner","loop-yolo","auto-epic"]),C=new Set(["create-epic","epic","criar-epic","planejamento"]);function T(r,e){return{kind:"full",trigger:r,targetEpicId:null,targetStoryId:null,includedStoryCount:Object.keys(e.stories).length,omittedStoryCount:0,omittedEpicCount:0,reason:"full-state"}}function d(r,e){return{...e,scope:T(r,e)}}function w(r){const[e]=r.trim().split(/\s+/,1);return e?e.replace(/^@?\*/,"").replace(/^@/,"").toLowerCase():null}function R(r){const[e]=r.trim().split(/\s+/,1);return e?/^[A-Z]?\d+(?:\.\d+)+$/i.test(e.replace(/^@/,""))||/(?:^|\/)[A-Z]?\d+(?:\.\d+)+\.story\.md$/i.test(e.replace(/^@/,"")):!1}function P(r){const e=r.match(/(?:^|[/@\s])([A-Z]?\d+(?:\.\d+)+)\.story\.md\b/i);return e?.[1]?e[1]:r.match(/(?:^|\s|@)([A-Z]?\d+(?:\.\d+)+)(?=$|\s)/i)?.[1]??null}function _(r){const e=r.trim(),t=e.search(/\s/);return t===-1?"":e.slice(t).trim()}function v(r){const e=_(r).split(/\s+/).find(t=>t.length>0&&!t.startsWith("-"));return e?e.replace(/^@/,"").replace(/^['"]|['"]$/g,""):null}function S(r,e){const n=r.replace(/^@/,"").replace(/^epic-/i,"").replace(/\.md$/i,""),o=[n,n.toUpperCase(),/^p\d+$/i.test(n)?`P${n.replace(/^p/i,"")}`:null,/^\d+$/.test(n)?`P${n}`:null].filter(i=>typeof i=="string"&&i.length>0);for(const i of o)if(e.epics[i])return i;return null}function x(r,e){const t=r.match(/(?:^|[/@\s])epic-(P?\d+)\.md\b/i);return t?.[1]?S(t[1],e):null}function $(r,e){const t=x(r,e);if(t)return t;const n=v(r);if(n){const s=S(n,e);if(s)return s}const o=e.yoloop,i=o?.state?.currentSession?.currentEpicId;if(typeof i=="string"&&e.epics[i])return i;const c=o?.lock?.currentEpicId??o?.lock?.epicId;return typeof c=="string"&&e.epics[c]?c:null}function j(r,e){if(typeof r.epic_id=="string"&&r.epic_id.length>0)return r.epic_id;const t=e.split(".").slice(0,-1).join(".");return t.length>0?t:null}function G(r){return typeof r=="string"&&["done","completed","merged","cancelled","canceled","abandoned"].includes(r.toLowerCase())}function y(r,e,t){if(t.has(r))return;const n=e.stories[r];if(!n)return;t.add(r);const o=n.depends_on;if(Array.isArray(o))for(const i of o)typeof i=="string"&&y(i,e,t)}function M(r,e,t){const n=new Set;y(r,t,n);const o=e.stories;if(Array.isArray(o))for(const c of o)typeof c=="string"&&t.stories[c]&&n.add(c);const i={};for(const c of n){const s=t.stories[c];s&&(i[c]=s)}return i}function E(r,e,t=[]){const n={};for(const o of t)e.epics[o]&&(n[o]=e.epics[o]);for(const[o,i]of Object.entries(r)){const c=j(i,o);c&&e.epics[c]&&(n[c]=e.epics[c])}return n}function I(r,e,t){if(t.has(r))return;const n=e.epics[r];if(!n)return;t.add(r);const o=n.depends_on;if(Array.isArray(o))for(const i of o)typeof i=="string"&&i.length>0&&I(i,e,t)}function F(r,e,t){const n=new Set;return I(r,t,n),E(e,t,[...n])}function Y(r,e){const t=new Set,n=r.stories;if(Array.isArray(n))for(const i of n){if(typeof i!="string")continue;const c=e.stories[i];if(c){if(G(c.status)){t.add(i);continue}y(i,e,t)}}const o={};for(const i of t){const c=e.stories[i];c&&(o[i]=c)}return o}function z(r,e){const t={};for(const o of Object.keys(e.epics))t[o]={id:o};const n={kind:"projected",trigger:r,targetEpicId:null,targetStoryId:null,includedStoryCount:0,omittedStoryCount:Object.keys(e.stories).length,omittedEpicCount:0,reason:"targeted-invocation"};return{...e,stories:{},epics:t,scope:n}}function Z(r,e){const t=r.trim();try{const n=w(t);if(n!==null&&C.has(n))return z(t,e);if(n!==null&&O.has(n)){const l=$(t,e);if(!l)return d(t,e);const m=e.epics[l];if(!m)return d(t,e);const f=Y(m,e),a=F(l,f,e);if(!a[l])return d(t,e);const k={kind:"projected",trigger:t,targetEpicId:l,targetStoryId:null,includedStoryCount:Object.keys(f).length,omittedStoryCount:Math.max(0,Object.keys(e.stories).length-Object.keys(f).length),omittedEpicCount:Math.max(0,Object.keys(e.epics).length-Object.keys(a).length),reason:"targeted-invocation"};return{...e,stories:f,epics:a,scope:k}}if(!(n!==null&&A.has(n)||R(t)))return d(t,e);const i=P(t);if(!i)return d(t,e);const c=e.stories[i];if(!c)return d(t,e);const s=j(c,i);if(!s)return d(t,e);const g=e.epics[s];if(!g)return d(t,e);const u=M(i,g,e),p=E(u,e);if(!u[i]||!p[s])return d(t,e);const b={kind:"projected",trigger:t,targetEpicId:s,targetStoryId:i,includedStoryCount:Object.keys(u).length,omittedStoryCount:Math.max(0,Object.keys(e.stories).length-Object.keys(u).length),omittedEpicCount:Math.max(0,Object.keys(e.epics).length-Object.keys(p).length),reason:"targeted-invocation"};return{...e,stories:u,epics:p,scope:b}}catch{return d(t,e)}}export{Z as projectStateSnapshotForInvoke};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * Client-owned `.neocortex/state.json` automatic repair helpers.
6
+ */
7
+ export declare class StateRepairHardStopError extends Error {
8
+ readonly reasonCode: string;
9
+ constructor(message: string, reasonCode: string);
10
+ }
11
+ export interface StateRepairAuditSummary {
12
+ readonly repaired: boolean;
13
+ readonly reasonCodes: readonly string[];
14
+ readonly backupPath?: string;
15
+ readonly changes: readonly string[];
16
+ }
17
+ export declare function maybeRepairStateJsonBeforeInvoke(projectRoot: string): StateRepairAuditSummary;
@@ -0,0 +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};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ */
5
+ export { OfflineTelemetryQueue, type TelemetryEvent, type QueueConfig, type QueueStats, type FlushResult } from './offline-queue.js';
@@ -0,0 +1 @@
1
+ import{OfflineTelemetryQueue as r}from"./offline-queue.js";export{r as OfflineTelemetryQueue};
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * This file is part of Neocortex CLI, licensed under the
6
+ * Functional Source License, Version 1.1 (FSL-1.1).
7
+ *
8
+ * Change Date: February 20, 2029
9
+ * Change License: MIT
10
+ *
11
+ * See the LICENSE file in the project root for full license text.
12
+ */
13
+ export interface TelemetryEvent {
14
+ type: string;
15
+ timestamp: number;
16
+ data: Record<string, unknown>;
17
+ }
18
+ export interface QueueConfig {
19
+ /** Path to queue file. Default: ~/.neocortex/.telemetry-queue */
20
+ queueFilePath: string;
21
+ /** Maximum number of events in queue. Default: 1000 */
22
+ maxEvents: number;
23
+ /** Maximum queue file size in bytes. Default: 5_242_880 (5MB) */
24
+ maxSizeBytes: number;
25
+ }
26
+ export interface QueueStats {
27
+ count: number;
28
+ sizeBytes: number;
29
+ }
30
+ export interface FlushResult {
31
+ sent: number;
32
+ failed: number;
33
+ }
34
+ export declare class OfflineTelemetryQueue {
35
+ private readonly config;
36
+ constructor(config?: Partial<QueueConfig>);
37
+ /**
38
+ * Add a telemetry event to the queue.
39
+ * Evicts oldest events if limits are reached.
40
+ */
41
+ enqueue(event: TelemetryEvent): Promise<void>;
42
+ /**
43
+ * Flush all queued events using the provided send function.
44
+ * Returns count of sent and failed events.
45
+ */
46
+ flush(sendFn: (events: TelemetryEvent[]) => Promise<boolean>): Promise<FlushResult>;
47
+ /**
48
+ * Get queue statistics.
49
+ */
50
+ getStats(): Promise<QueueStats>;
51
+ /**
52
+ * Clear all queued events.
53
+ */
54
+ clear(): Promise<void>;
55
+ private loadQueue;
56
+ private saveQueue;
57
+ }
@@ -0,0 +1 @@
1
+ import{readFile as a,writeFile as n,mkdir as r}from"node:fs/promises";import{dirname as u}from"node:path";import{join as c}from"node:path";import{homedir as o}from"node:os";const h={queueFilePath:c(o(),".neocortex",".telemetry-queue"),maxEvents:1e3,maxSizeBytes:5242880};class d{config;constructor(t){this.config={...h,...t}}async enqueue(t){try{const e=await this.loadQueue();for(e.push(t);e.length>this.config.maxEvents;)e.shift();let i=JSON.stringify(e);for(;Buffer.byteLength(i,"utf8")>this.config.maxSizeBytes&&e.length>0;)e.shift(),i=JSON.stringify(e);await this.saveQueue(e)}catch{}}async flush(t){try{const e=await this.loadQueue();return e.length===0?{sent:0,failed:0}:await t(e)?(await this.saveQueue([]),{sent:e.length,failed:0}):{sent:0,failed:e.length}}catch{return{sent:0,failed:0}}}async getStats(){try{const t=await this.loadQueue(),e=JSON.stringify(t);return{count:t.length,sizeBytes:Buffer.byteLength(e,"utf8")}}catch{return{count:0,sizeBytes:0}}}async clear(){try{await this.saveQueue([])}catch{}}async loadQueue(){try{const t=await a(this.config.queueFilePath,"utf8"),e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}async saveQueue(t){const e=u(this.config.queueFilePath);await r(e,{recursive:!0});const i=`${this.config.queueFilePath}.tmp`;await n(i,JSON.stringify(t),"utf8");const{rename:s}=await import("node:fs/promises");await s(i,this.config.queueFilePath)}}export{d as OfflineTelemetryQueue};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ */
5
+ export { TierAwareClient, type TierAwareClientOptions, type PreFlightResult, type QuotaSnapshot, type SubscriptionTier, } from './tier-aware-client.js';
@@ -0,0 +1 @@
1
+ import{TierAwareClient as i}from"./tier-aware-client.js";export{i as TierAwareClient};
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * This file is part of Neocortex CLI, licensed under the
6
+ * Functional Source License, Version 1.1 (FSL-1.1).
7
+ *
8
+ * Change Date: February 20, 2029
9
+ * Change License: MIT
10
+ *
11
+ * See the LICENSE file in the project root for full license text.
12
+ */
13
+ /**
14
+ * @neocortex/client - TierAwareClient
15
+ *
16
+ * Client-side tier awareness: JWT tier extraction, cached tier,
17
+ * pre-flight trigger checks, quota caching from response metadata,
18
+ * and offline enforcement via cached quota data.
19
+ *
20
+ * Follows the same "NEVER throws" pattern as LicenseClient.
21
+ * Fail-open: if anything fails, default to 'free' tier / allow operation.
22
+ * No stdout output (preserve pipe compatibility) -- stderr only.
23
+ *
24
+ * Epic 60
25
+ */
26
+ import type { CacheProvider } from '../types/index.js';
27
+ import type { LicenseClient } from '../license/license-client.js';
28
+ /** Subscription tier (inlined to avoid import path issues) */
29
+ export type SubscriptionTier = 'free' | 'pro' | 'enterprise';
30
+ /** Result of a pre-flight trigger check */
31
+ export interface PreFlightResult {
32
+ readonly allowed: boolean;
33
+ readonly message?: string;
34
+ }
35
+ /** Cached quota data from server response metadata */
36
+ export interface QuotaSnapshot {
37
+ readonly stepsRemaining: number;
38
+ readonly invocationsRemaining: number;
39
+ readonly stepsLimit: number;
40
+ readonly invocationsLimit: number;
41
+ readonly cachedAt: number;
42
+ }
43
+ export interface ClientCommandRegistryEntry {
44
+ readonly id: string;
45
+ readonly number: number;
46
+ readonly aliases: readonly string[];
47
+ }
48
+ export declare const CLIENT_PREFLIGHT_COMMAND_REGISTRY: readonly ClientCommandRegistryEntry[];
49
+ export declare function normalizeCommandToken(input: string): string;
50
+ export declare function resolveClientPreFlightTrigger(input: string): string | null;
51
+ export interface TierAwareClientOptions {
52
+ readonly cacheProvider: CacheProvider;
53
+ readonly licenseClient: LicenseClient;
54
+ }
55
+ export declare class TierAwareClient {
56
+ private readonly cache;
57
+ private readonly licenseClient;
58
+ private cachedTier;
59
+ constructor(options: TierAwareClientOptions);
60
+ /**
61
+ * Get the current tier. Checks in-memory, then cache, then JWT token.
62
+ * NEVER throws - returns 'free' on failure (fail-open).
63
+ */
64
+ getCachedTier(): Promise<SubscriptionTier>;
65
+ /**
66
+ * Update cached tier (called when server returns tier info).
67
+ */
68
+ updateTier(tier: SubscriptionTier): Promise<void>;
69
+ /**
70
+ * Invalidate all tier and quota caches.
71
+ * Called when a tier change is detected to ensure fresh data.
72
+ * NEVER throws.
73
+ */
74
+ invalidateTierCache(): Promise<void>;
75
+ /**
76
+ * Check if a trigger is allowed for the current tier WITHOUT calling the server.
77
+ * Returns immediately (in-memory lookup).
78
+ * NEVER throws - returns { allowed: true } on failure (fail-open).
79
+ */
80
+ preFlightCheck(trigger: string, tier?: SubscriptionTier): Promise<PreFlightResult>;
81
+ /**
82
+ * Update cached quota from server response metadata.
83
+ * Called after each successful invoke.
84
+ */
85
+ updateQuotaFromResponse(metadata: Record<string, unknown>): Promise<void>;
86
+ /**
87
+ * Get cached quota for today.
88
+ * NEVER throws - returns null if cache empty or expired.
89
+ */
90
+ getCachedQuota(): Promise<QuotaSnapshot | null>;
91
+ /**
92
+ * Check quota in offline mode using cached data.
93
+ * NEVER throws - returns { allowed: true } on failure (fail-open).
94
+ *
95
+ * @param isOffline - Whether the circuit breaker is in L2+ degradation
96
+ */
97
+ offlineQuotaCheck(isOffline?: boolean): Promise<PreFlightResult>;
98
+ /**
99
+ * Extract tier from JWT payload via base64url decode.
100
+ * No cryptographic verification - client-side is UX only.
101
+ */
102
+ private extractTierFromJwt;
103
+ private buildUpgradeMessage;
104
+ private getQuotaCacheKey;
105
+ }
@@ -0,0 +1 @@
1
+ const o="neocortex:tier",m="neocortex:quota:",T=3e5,w=36e5,l=new Set(["free","pro","enterprise"]),s="free",h={status:"free",init:"free","create-epic":"free","idea-diagnose":"free","idea-research":"free","generate-epic":"free",exec:"pro",yolo:"pro",epic:"pro","setup-branch":"free",diagnose:"free",research:"free","write-spec":"free","create-tasks":"free",implement:"free","update-memory":"free",commit:"free",sync:"free","create-pr":"free",review:"pro",merge:"free","fix-blocked":"free","finalize-epic":"free",cleanup:"free","resolve-conflicts":"free",audit:"free",menu:"free",plans:"free",billing:"free",subscribe:"free","arch-plan":"free","arch-prd":"free","arch-architecture":"free","arch-api-contracts":"free","arch-api-integrations":"free","arch-database":"free","arch-security":"free","arch-design-system":"free","arch-ux-design":"free","arch-review":"free","arch-fitness-functions":"pro","arch-performance":"pro","arch-testing":"pro","arch-infrastructure":"pro",refactor:"pro","tech-debt":"free","tech-debt-scan":"pro","qa-scan":"pro","mutation-test":"pro",yoloop:"pro","migrate-state":"free","policy-audit":"pro","sync-openapi":"free","generate-pacts":"pro","verify-pacts":"free","property-test":"pro","chaos-plan":"pro","ui-ux-review":"pro","solyd-system":"enterprise",goal:"enterprise","goal-tick":"enterprise",loop:"enterprise","loop-tick":"enterprise",jobs:"enterprise",runner:"enterprise"},u=[{id:"status",number:1,aliases:["st"]},{id:"init",number:2,aliases:["inicializar"]},{id:"arch-plan",number:3,aliases:["arquitetura","architecture","arch"]},{id:"arch-prd",number:4,aliases:["prd","product-requirements"]},{id:"arch-architecture",number:5,aliases:["arch-doc","tech-architecture"]},{id:"arch-api-contracts",number:6,aliases:["api-contracts","api-contract"]},{id:"arch-api-integrations",number:7,aliases:["api-integrations","api-int"]},{id:"arch-database",number:8,aliases:["database-schema","db-schema","db"]},{id:"arch-security",number:9,aliases:["cyber-security","security","sec"]},{id:"arch-design-system",number:10,aliases:["design-system","ds","atomic-design"]},{id:"arch-ux-design",number:11,aliases:["ux-design","ux","wireframes","wireframe","user-flows"]},{id:"arch-performance",number:12,aliases:["performance","perf","capacity-planning","capacity","arch-perf","performance-strategy"]},{id:"arch-testing",number:13,aliases:["testing-strategy","test-plan","test-strategy","arch-test"]},{id:"arch-infrastructure",number:14,aliases:["infrastructure","infra","deploy-plan","deployment","arch-infra","arch-deploy"]},{id:"arch-review",number:15,aliases:["review-consolidation","consolidation","architecture-review","arch-consolidation"]},{id:"arch-fitness-functions",number:16,aliases:["fitness","fitness-functions","archfit","arch-fit","fit-funcs"]},{id:"create-epic",number:17,aliases:["criar-epic","planejamento"]},{id:"idea-diagnose",number:18,aliases:["idea-diag"]},{id:"idea-research",number:19,aliases:["idea-pesq"]},{id:"generate-epic",number:20,aliases:["gerar-epic"]},{id:"exec",number:21,aliases:["executar","pipeline"]},{id:"yolo",number:22,aliases:[]},{id:"epic",number:23,aliases:["parallel-epic"]},{id:"setup-branch",number:24,aliases:["setup","branch"]},{id:"diagnose",number:25,aliases:["diag","diagnostico","c02"]},{id:"research",number:26,aliases:["pesquisar","pesq","research-fix","c03"]},{id:"write-spec",number:27,aliases:["spec","especificacao","c04"]},{id:"create-tasks",number:28,aliases:["tasks","tarefas","c05"]},{id:"implement",number:29,aliases:["impl","implementar","c06"]},{id:"commit",number:30,aliases:["push","commit-push","commit_push","cp","c07"]},{id:"sync",number:31,aliases:["sincronizar","c08"]},{id:"create-pr",number:32,aliases:["pr","c09"]},{id:"review",number:33,aliases:["revisar","c11"]},{id:"merge",number:34,aliases:["mesclar","c12"]},{id:"fix-blocked",number:35,aliases:["fix","corrigir"]},{id:"finalize-epic",number:36,aliases:["finalizar"]},{id:"resolve-conflicts",number:37,aliases:["conflitos"]},{id:"update-memory",number:38,aliases:["memoria"]},{id:"refactor",number:39,aliases:["refactoring","refact","refac","rf","cleanup-code","code-cleanup","code-quality","improve-code","modernize","modernization","legacy","legacy-code","debt-pay","pay-debt","debt-reduction","smell-fix","fix-smells","code-smells","strangler","strangler-fig"]},{id:"cleanup",number:40,aliases:["limpar","limpeza"]},{id:"audit",number:41,aliases:["auditar","auditoria"]},{id:"tech-debt",number:42,aliases:["debt","debts","debt-list","tech-debts","td"]},{id:"menu",number:43,aliases:["help","ajuda","?","commands","cmds"]},{id:"plans",number:44,aliases:["planos","pricing"]},{id:"billing",number:45,aliases:["bill","subscription","sub"]},{id:"subscribe",number:46,aliases:["upgrade","checkout"]},{id:"qa-scan",number:47,aliases:["qa","qa-test","visual-qa","e2e-scan","troubleshoot","debug-ui","scan","a11y","accessibility","wcag"]},{id:"yoloop",number:48,aliases:["auto-yolo","epic-runner","story-runner","loop-yolo","auto-epic"]},{id:"migrate-state",number:49,aliases:["migrate","state-migrate","schema-migrate"]},{id:"policy-audit",number:50,aliases:["policy","audit-policy","policy-history","policies"]},{id:"mutation-test",number:51,aliases:["mutation","stryker","kill-mutants"]},{id:"sync-openapi",number:52,aliases:["openapi-sync","api-sync","spec-sync","regen-openapi"]},{id:"generate-pacts",number:53,aliases:["pacts","gen-pacts","regen-pacts","create-pacts"]},{id:"verify-pacts",number:54,aliases:["verify-pact","pact-verify","check-pacts","pact-check"]},{id:"property-test",number:55,aliases:["property","pbt","proptest","property-tests","invariant-test"]},{id:"chaos-plan",number:56,aliases:["chaos","gameday","resilience-test"]},{id:"ui-ux-review",number:57,aliases:["ux-review","design-review","visual-review","product-polish"]},{id:"solyd-system",number:58,aliases:["security-system","authorized-security","sec-system"]},{id:"goal",number:59,aliases:["goals","durable-goal","continuity-goal"]},{id:"loop",number:60,aliases:["loops","durable-loop","continuity-loop"]},{id:"jobs",number:61,aliases:["job","continuity-jobs"]},{id:"runner",number:62,aliases:["neocortex-runner","continuity-runner"]}],f=new Map(u.map(r=>[r.id,r])),b=new Map(u.map(r=>[r.number,r])),g=new Map(u.flatMap(r=>r.aliases.map(a=>[p(a),r.id])));function p(r){return r.trim().toLowerCase().replace(/^\*/,"")}function y(r){const a=r.trim();if(/^@?epic-[a-z0-9][a-z0-9._-]*$/i.test(a))return"epic";const e=a.split(/\s+/,1)[0]??"",i=p(e);return i?/^\d+$/.test(i)?b.get(Number.parseInt(i,10))?.id??null:f.has(i)?i:g.get(i)??null:null}const d={free:0,pro:1,enterprise:2};class C{cache;licenseClient;cachedTier=null;constructor(a){this.cache=a.cacheProvider,this.licenseClient=a.licenseClient}async getCachedTier(){try{if(this.cachedTier)return this.cachedTier;const a=await this.cache.get(o);if(a&&l.has(a))return this.cachedTier=a,this.cachedTier;const e=await this.licenseClient.getToken();if(e){const i=this.extractTierFromJwt(e);return this.cachedTier=i,this.cache.set(o,i,36e5).catch(()=>{}),i}return s}catch{return s}}async updateTier(a){try{if(!l.has(a))return;this.cachedTier=a,await this.cache.set(o,a,36e5).catch(()=>{})}catch{}}async invalidateTierCache(){try{this.cachedTier=null,await this.cache.clear().catch(()=>{})}catch{}}async preFlightCheck(a,e){try{const i=e??await this.getCachedTier(),t=y(a)??a,c=h[t]??"free";return d[i]>=d[c]?{allowed:!0}:{allowed:!1,message:this.buildUpgradeMessage(t,i,c)}}catch{return{allowed:!0}}}async updateQuotaFromResponse(a){try{const e=a.quotaRemaining;if(!e)return;const i={stepsRemaining:e.stepsRemaining??0,invocationsRemaining:e.invocationsRemaining??0,stepsLimit:e.stepsLimit??0,invocationsLimit:e.invocationsLimit??0,cachedAt:Date.now()},t=this.getQuotaCacheKey();await this.cache.set(t,JSON.stringify(i),3e5).catch(()=>{})}catch{}}async getCachedQuota(){try{const a=this.getQuotaCacheKey(),e=await this.cache.get(a);if(!e)return null;const i=JSON.parse(e);return Date.now()-i.cachedAt>3e5?null:i}catch{return null}}async offlineQuotaCheck(a=!1){try{if(!a)return{allowed:!0};const e=await this.getCachedQuota();return e?e.stepsRemaining<=0&&e.stepsLimit>0?{allowed:!1,message:`Daily step limit reached (${e.stepsLimit}/${e.stepsLimit}). Resets at 00:00 UTC.`}:e.invocationsRemaining<=0&&e.invocationsLimit>0?{allowed:!1,message:`Daily invocation limit reached (${e.invocationsLimit}/${e.invocationsLimit}). Resets at 00:00 UTC.`}:{allowed:!0}:{allowed:!0}}catch{return{allowed:!0}}}extractTierFromJwt(a){try{const e=a.split(".");if(e.length!==3)return s;const i=e[1],t=Buffer.from(i,"base64url").toString("utf8"),n=JSON.parse(t).tier;return n&&l.has(n)?n:s}catch{return s}}buildUpgradeMessage(a,e,i){return`The *${a} command requires ${i.toUpperCase()} plan. Your current plan: ${e.toUpperCase()}. Upgrade: https://neocortex.sh/portal/dashboard/plans`}getQuotaCacheKey(){const e=new Date().toISOString().slice(0,10);return`${m}${e}`}}export{u as CLIENT_PREFLIGHT_COMMAND_REGISTRY,C as TierAwareClient,p as normalizeCommandToken,y as resolveClientPreFlightTrigger};
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * This file is part of Neocortex CLI, licensed under the
6
+ * Functional Source License, Version 1.1 (FSL-1.1).
7
+ *
8
+ * Change Date: February 20, 2029
9
+ * Change License: MIT
10
+ *
11
+ * See the LICENSE file in the project root for full license text.
12
+ */
13
+ /**
14
+ * @neocortex/client - Type Definitions
15
+ *
16
+ * All types for the asset resolution abstraction layer.
17
+ */
18
+ /** Mode of asset resolution */
19
+ export declare enum ResolverMode {
20
+ /** Read assets from local filesystem (development) */
21
+ LOCAL = "local",
22
+ /** Fetch assets from remote IP Protection Server (production) */
23
+ REMOTE = "remote"
24
+ }
25
+ /** Metadata about the codebase for context collection */
26
+ export interface CodebaseMetadata {
27
+ readonly projectName: string;
28
+ readonly languages: readonly string[];
29
+ readonly frameworks: readonly string[];
30
+ readonly dependencies: Readonly<Record<string, string>>;
31
+ readonly nodeVersion: string;
32
+ }
33
+ /** Metadata extracted from the story file */
34
+ export interface StoryMetadata {
35
+ readonly id: string;
36
+ readonly epicId: string;
37
+ readonly title: string;
38
+ readonly status: string;
39
+ readonly dependencies: readonly string[];
40
+ readonly acceptanceCriteria: readonly string[];
41
+ }
42
+ /** Full pipeline context sent to the server for prompt assembly */
43
+ export interface PipelineContext {
44
+ readonly storyId: string;
45
+ readonly stepId: string;
46
+ readonly epicId: string;
47
+ readonly storyTitle: string;
48
+ readonly currentStatus: string;
49
+ readonly stepsCompleted: readonly string[];
50
+ readonly branchName: string;
51
+ readonly platformTarget: string;
52
+ readonly codebaseMetadata: CodebaseMetadata;
53
+ readonly storyMetadata: StoryMetadata;
54
+ }
55
+ /** Content of a resolved pipeline step */
56
+ export interface StepContent {
57
+ readonly id: string;
58
+ readonly content: string;
59
+ readonly frontmatter: Readonly<Record<string, unknown>>;
60
+ }
61
+ /** Content of a resolved skill */
62
+ export interface SkillContent {
63
+ readonly id: string;
64
+ readonly content: string;
65
+ readonly metadata: Readonly<Record<string, unknown>>;
66
+ }
67
+ /** Content of a resolved standard */
68
+ export interface StandardContent {
69
+ readonly id: string;
70
+ readonly content: string;
71
+ }
72
+ /** Step registry entry matching core/data/step-registry.json structure */
73
+ export interface StepRegistryEntry {
74
+ readonly id: string;
75
+ readonly order?: number;
76
+ readonly name: string;
77
+ readonly status_after?: string;
78
+ readonly file: string;
79
+ readonly auto_continue?: boolean;
80
+ readonly requires_git?: boolean;
81
+ readonly standalone?: boolean;
82
+ readonly terminal?: boolean;
83
+ readonly returns_to?: string;
84
+ readonly returns_to_status?: string;
85
+ }
86
+ /** Full step registry structure */
87
+ export interface StepRegistry {
88
+ readonly version: string;
89
+ readonly steps: {
90
+ readonly core: readonly StepRegistryEntry[];
91
+ readonly recovery: readonly StepRegistryEntry[];
92
+ readonly utility: readonly StepRegistryEntry[];
93
+ readonly planning: readonly StepRegistryEntry[];
94
+ readonly epic: readonly StepRegistryEntry[];
95
+ };
96
+ readonly [key: string]: unknown;
97
+ }
98
+ /** Assembled prompt ready for execution */
99
+ export interface AssembledPrompt {
100
+ readonly prompt: string;
101
+ readonly variables: Readonly<Record<string, string>>;
102
+ readonly includedSkills: readonly string[];
103
+ readonly includedStandards: readonly string[];
104
+ }
105
+ /** Interface for encrypted cache (implemented in Story 42.3) */
106
+ export interface CacheProvider {
107
+ get(key: string): Promise<string | null>;
108
+ set(key: string, value: string, ttlMs?: number): Promise<void>;
109
+ clear(): Promise<void>;
110
+ }
111
+ /** No-op cache implementation for development/fallback */
112
+ export declare class NoOpCache implements CacheProvider {
113
+ get(): Promise<null>;
114
+ set(): Promise<void>;
115
+ clear(): Promise<void>;
116
+ }
117
+ /** Options for LocalResolver */
118
+ export interface LocalResolverOptions {
119
+ readonly projectRoot: string;
120
+ }
121
+ /** Options for RemoteResolver */
122
+ export interface RemoteResolverOptions {
123
+ readonly serverUrl: string;
124
+ readonly licenseKey: string;
125
+ readonly timeout?: number;
126
+ readonly retryCount?: number;
127
+ readonly cacheProvider?: CacheProvider;
128
+ readonly licenseClient?: import('../license/license-client.js').LicenseClient;
129
+ }
130
+ /** Options for resolver factory */
131
+ export interface CreateResolverOptions {
132
+ readonly forceLocal?: boolean;
133
+ /** Force offline mode: skip server, use cache exclusively (Story 42.9 - AC6) */
134
+ readonly forceOffline?: boolean;
135
+ readonly projectRoot?: string;
136
+ readonly serverUrl?: string;
137
+ readonly licenseKey?: string;
138
+ readonly cacheProvider?: CacheProvider;
139
+ readonly licenseClient?: import('../license/license-client.js').LicenseClient;
140
+ }
@@ -0,0 +1 @@
1
+ var a;(function(e){e.LOCAL="local",e.REMOTE="remote"})(a||(a={}));class c{async get(){return null}async set(){}async clear(){}}export{c as NoOpCache,a as ResolverMode};