@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,229 @@
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
+ import type { YoloopPersistedState } from '../yoloop/shared-yoloop-types.js';
14
+ export declare const INVOKE_PAYLOAD_WARNING_THRESHOLD_BYTES: number;
15
+ interface InitProjectMemoryBootstrapSnapshot {
16
+ readonly canonical: {
17
+ readonly path: 'NEOCORTEX.md';
18
+ readonly exists: boolean;
19
+ readonly incompleteReasons: readonly string[];
20
+ readonly confidence: 'high' | 'medium' | 'low';
21
+ };
22
+ readonly permittedSources: {
23
+ readonly packageBuildFiles: number;
24
+ readonly architectureReadmeDocs: number;
25
+ readonly runtimeConfigTemplates: number;
26
+ readonly platformWrappers: number;
27
+ };
28
+ readonly wrapperFiles: readonly string[];
29
+ readonly recommendedPreviewCommand: string;
30
+ readonly recommendedRefreshCommand: string;
31
+ readonly guardrails: readonly string[];
32
+ }
33
+ export declare function isInitTrigger(args: string): boolean;
34
+ export declare function collectInitProjectMemoryBootstrapSnapshot(projectRoot: string): InitProjectMemoryBootstrapSnapshot;
35
+ export interface InvokeOptions {
36
+ /** Raw args from the user (e.g., "*yolo @docs/stories/1.1.story.md") */
37
+ readonly args: string;
38
+ /** Project root directory (default: cwd; Git repository not required) */
39
+ readonly projectRoot?: string;
40
+ /** Output format: 'json' for full response, 'plain' for instructions only */
41
+ readonly format?: 'json' | 'plain';
42
+ /** Server URL override */
43
+ readonly serverUrl?: string;
44
+ /** Platform target (default: 'claude-code') */
45
+ readonly platformTarget?: string;
46
+ /** CLI input source, used to decide when stdin/args-file need chunk transport. */
47
+ readonly inputSource?: InvokeCliInputSource;
48
+ }
49
+ /**
50
+ * Normalize the project root received from wrappers/CLI flags.
51
+ *
52
+ * Generated platform wrappers historically used
53
+ * `$(git rev-parse --show-toplevel)`. In a legitimate non-Git workspace that
54
+ * command expands to an empty string, which then reached the server as
55
+ * `projectRoot: ""` and was rejected by request validation before orchestration
56
+ * could run. Treat a missing/blank value as the current working directory so
57
+ * projects that intentionally do not have a Git repository can still invoke
58
+ * Neocortex commands.
59
+ */
60
+ export declare function resolveInvokeProjectRoot(projectRoot: string | undefined, fallbackRoot?: string): string;
61
+ export interface InvokeResult {
62
+ readonly success: boolean;
63
+ readonly instructions?: string;
64
+ readonly metadata?: Record<string, unknown>;
65
+ readonly error?: string;
66
+ readonly errorCode?: string;
67
+ readonly exitCode: number;
68
+ }
69
+ export declare function sanitizeInvokeCliOutput(instructions: string | undefined, metadata: Record<string, unknown> | undefined): {
70
+ instructions: string;
71
+ metadata: Record<string, unknown> | undefined;
72
+ };
73
+ type InvokeCliInputSource = 'args' | 'stdin' | 'args-file';
74
+ export interface InvokeCliParsedOptions {
75
+ readonly args: string;
76
+ readonly inputSource: InvokeCliInputSource;
77
+ readonly projectRoot?: string;
78
+ readonly format: 'json' | 'plain';
79
+ readonly serverUrl?: string;
80
+ }
81
+ export interface InvokeCliInputReaders {
82
+ readonly readStdin?: () => string;
83
+ readonly readArgsFile?: (filePath: string) => string;
84
+ }
85
+ export declare class InvokeCliInputError extends Error {
86
+ readonly code: string;
87
+ constructor(code: string, message: string);
88
+ }
89
+ export type StateSnapshotScopeKind = 'full' | 'projected';
90
+ export type StateSnapshotProjectionReason = 'full-state' | 'targeted-invocation' | 'body-size' | 'context-cost' | 'unknown' | (string & {});
91
+ interface StateSnapshotScopeBase {
92
+ readonly kind: StateSnapshotScopeKind;
93
+ readonly trigger?: string;
94
+ readonly targetEpicId?: string | null;
95
+ readonly targetStoryId?: string | null;
96
+ readonly includedStoryCount: number;
97
+ readonly omittedStoryCount: number;
98
+ readonly omittedEpicCount: number;
99
+ readonly reason: StateSnapshotProjectionReason;
100
+ }
101
+ export interface FullStateSnapshotScope extends StateSnapshotScopeBase {
102
+ readonly kind: 'full';
103
+ readonly omittedStoryCount: 0;
104
+ readonly omittedEpicCount: 0;
105
+ readonly reason: 'full-state';
106
+ }
107
+ export interface ProjectedStateSnapshotScope extends StateSnapshotScopeBase {
108
+ readonly kind: 'projected';
109
+ }
110
+ export type StateSnapshotScope = FullStateSnapshotScope | ProjectedStateSnapshotScope;
111
+ export interface StateSnapshot {
112
+ readonly schema_version?: number;
113
+ readonly config: {
114
+ readonly project_name: string;
115
+ readonly default_branch: string;
116
+ readonly language: string;
117
+ readonly yolo_mode?: boolean;
118
+ readonly user_name?: string;
119
+ readonly worktree_base?: string;
120
+ readonly max_parallel_stories?: number;
121
+ };
122
+ readonly stories: Record<string, Record<string, unknown>>;
123
+ readonly epics: Record<string, Record<string, unknown>>;
124
+ /**
125
+ * P141.01 -- request-only scope metadata. Never persisted to state.json.
126
+ * `projected` snapshots mean omitted entries are unknown/out-of-scope for
127
+ * this request, not nonexistent.
128
+ */
129
+ readonly scope?: StateSnapshotScope;
130
+ /**
131
+ * Epic P101.03 -- yoloop client-side persisted state echoed on each invoke
132
+ * so the server can treat yoloop as a pure function over client state.
133
+ * Optional during the P101 rollout; once MIN_CLIENT_VERSION bumps (P101.11),
134
+ * yoloop invocations without this field will receive CLIENT_UPGRADE_REQUIRED.
135
+ */
136
+ readonly yoloop?: YoloopPersistedState;
137
+ /**
138
+ * P180.05 -- optional client-owned Enterprise continuity snapshot.
139
+ * Compact/public-safe only; omitted when the SQLite store is absent or an
140
+ * adapter is unavailable for non-continuity commands.
141
+ */
142
+ readonly continuity?: unknown;
143
+ /**
144
+ * P158.06 -- optional client-side deterministic graph retrieval enrichment.
145
+ * This is request-only metadata for server validation/consumption; it never
146
+ * decides workflow locally and is omitted when disabled or unavailable.
147
+ */
148
+ readonly graphRetrieval?: unknown;
149
+ }
150
+ export interface InvokeArgsRef {
151
+ readonly manifestId: string;
152
+ readonly sha256?: string;
153
+ readonly byteLength?: number;
154
+ readonly chunkCount?: number;
155
+ readonly expiresAt?: string;
156
+ }
157
+ interface InvokeRequestBodyBase {
158
+ readonly projectRoot: string;
159
+ readonly stateSnapshot: StateSnapshot;
160
+ readonly platformTarget?: string;
161
+ }
162
+ export type InvokeRequestBody = InvokeRequestBodyBase & ({
163
+ readonly args: string;
164
+ readonly argsRef?: never;
165
+ } | {
166
+ readonly args?: never;
167
+ readonly argsRef: InvokeArgsRef;
168
+ });
169
+ /**
170
+ * P103.02: Describe a schema-drift issue detected in a user's state.json.
171
+ * Codes map to concrete misalignments against the canonical v1 schema
172
+ * documented in docs/arquitetura-software/STATE-JSON-SCHEMA.md.
173
+ */
174
+ export interface SchemaDriftIssue {
175
+ readonly code: 'PLANNING_LEGACY' | 'STORIES_AS_ARRAY' | 'EPIC_STORIES_NOT_ARRAY' | 'SCHEMA_VERSION_MISSING' | 'SCHEMA_VERSION_OUTDATED';
176
+ readonly message: string;
177
+ }
178
+ /**
179
+ * P103.02: Detect legacy/malformed shapes that cause the orchestrator to
180
+ * silently treat the workspace as empty. Pure function — does NOT emit
181
+ * warnings, does NOT throw. Returns empty array when the shape looks v1-OK
182
+ * or when state has no data (new project).
183
+ */
184
+ export declare function detectStateSchemaDrift(stateData: unknown): SchemaDriftIssue[];
185
+ /**
186
+ * P103.02 test utility: reset the one-time flag between test cases.
187
+ * Exported for tests only; not part of the public API.
188
+ */
189
+ export declare function __resetSchemaDriftWarnedForTests(): void;
190
+ /**
191
+ * Read state.json and construct a sanitized snapshot for the server.
192
+ * Relative paths only - no absolute paths sent to server.
193
+ */
194
+ export declare function collectStateSnapshot(projectRoot: string): StateSnapshot;
195
+ export declare function createFullStateSnapshotScope(trigger: string, snapshot: Pick<StateSnapshot, 'stories' | 'epics'>): FullStateSnapshotScope;
196
+ export declare function computeInvokeRequestBodySizeBytes(body: InvokeRequestBody): number;
197
+ export declare function maybeEmitInvokePayloadSizeWarning(body: InvokeRequestBody): number;
198
+ /**
199
+ * Execute the invoke command.
200
+ *
201
+ * Flow:
202
+ * 1. Load config to get server URL
203
+ * 2. Collect state snapshot from project root
204
+ * 3. Check menu cache for empty invocations
205
+ * 4. Send POST /api/v1/invoke
206
+ * 5. Format and return result
207
+ */
208
+ export declare function invoke(options: InvokeOptions): Promise<InvokeResult>;
209
+ /**
210
+ * Extract the canonical trigger for client-side pre-flight checks.
211
+ * Mirrors server tolerant parsing only for explicit first-token command forms:
212
+ * `*yolo`, `yolo`, `22`, and registered aliases. It deliberately does not
213
+ * infer commands from free text or paths, so uncertain server-side inference
214
+ * remains fail-open and cannot block local invocation.
215
+ */
216
+ export declare function extractPreFlightTrigger(args: string): string | null;
217
+ export declare function parseInvokeCliOptions(argv: string[], readers?: InvokeCliInputReaders): InvokeCliParsedOptions;
218
+ /**
219
+ * CLI handler for the invoke command.
220
+ * Parses CLI args and delegates to invoke().
221
+ *
222
+ * Usage:
223
+ * neocortex-client invoke --args "*yolo @story.md" --project-root /path
224
+ * neocortex-client invoke --args "*status" --format json
225
+ * neocortex-client invoke --stdin < synthetic.story.md
226
+ * neocortex-client invoke --args-file ./synthetic.story.md
227
+ */
228
+ export declare function invokeCliHandler(argv: string[]): Promise<number>;
229
+ export {};
@@ -0,0 +1,63 @@
1
+ import{createHash as D}from"node:crypto";import{existsSync as R,readFileSync as A,unlinkSync as ne,writeFileSync as oe,mkdirSync as se,statSync as ie}from"node:fs";import{join as y}from"node:path";import{homedir as b}from"node:os";import{LicenseClient as ae}from"../license/license-client.js";import{EncryptedCache as $}from"../cache/encrypted-cache.js";import{NoOpCache as ce}from"../types/index.js";import{resolveClientPreFlightTrigger as ue,TierAwareClient as de}from"../tier/tier-aware-client.js";import{loadSecureConfig as pe}from"../config/secure-config.js";import{DEFAULT_SERVER_URL as le}from"../constants.js";import{detectFirstRunLocale as fe,renderFirstRunMessage as me}from"../i18n/first-run.js";import{humanizeError as v,formatHumanizedError as F,detectErrorLocale as U}from"../errors/error-messages.js";import{projectStateSnapshotForInvoke as ge}from"../state/project-state-snapshot.js";import{maybeRepairStateJsonBeforeInvoke as he,StateRepairHardStopError as _e}from"../state/state-json-repair.js";import{bootstrapArchitectureMemory as ye}from"../memory/project-memory-writer.js";const T=y(b(),".neocortex"),M=y(T,"cache"),j=y(M,"menu-cache.json"),B=1440*60*1e3,Y=3e4,E="3.9.62",z=256*1024,Ee=.8,S="[REDACTED]",we=1e5,N=2e3,Se=200,Re=200,Ce=12,Ie=/(?:promptBody|workflow|workflowGraph|stepBody|privateUrl|rawLog|secret|credential|licenseKey|apiKey|internalRouting|serverOnly|proprietary|protected)/i,Ae=/(?:PRIVATE|PROTECTED|SERVER_ONLY)[-_\s]*(?:PROMPT|PROMPT_BODY|WORKFLOW|WORKFLOW_GRAPH|STEP_BODY|STEP|ROUTING)\s*[:=][^\n\r]*/gi,V=Math.floor(z*Ee),K=y(T,".first-run-shown"),Te="<!-- NEOCORTEX-MEMORY-START -->";function Ne(e){return/^\s*\*?init(?:\s|$)/i.test(e)}function be(e){const t=y(e,"NEOCORTEX.md"),r=R(t)?A(t,"utf8"):void 0,o=r===void 0?["missing_canonical_memory"]:[r.includes(Te)?void 0:"missing_managed_memory_block",r.length>18e3?"canonical_memory_over_budget":void 0,/api[-_ ]?key|license[-_ ]?key|password\s*[:=]|secret\s*[:=]/i.test(r)?"possible_secret_shape_detected":void 0].filter(d=>!!d),c=["AGENTS.md","CLAUDE.md","GEMINI.md",".opencode/AGENTS.md",".cursor/rules/neocortex.mdc",".github/copilot-instructions.md"].filter(d=>R(y(e,d))),u=o.includes("possible_secret_shape_detected")?"low":o.length===0?"high":c.length>0?"medium":"low",l=ye(e);return{canonical:{path:"NEOCORTEX.md",exists:r!==void 0,incompleteReasons:o,confidence:u},permittedSources:{packageBuildFiles:l.repositoryMap?.find(d=>d.startsWith("Package/build files:"))?.split(",").length??0,architectureReadmeDocs:l.architectureReferences?.length??0,runtimeConfigTemplates:l.environmentPractices?.[0]?.startsWith("Runtime/config templates:")?l.environmentPractices[0].split(",").length:0,platformWrappers:c.length},wrapperFiles:c,recommendedPreviewCommand:'neocortex-client refresh-memory --dry-run --project-root "$PROJECT_ROOT"',recommendedRefreshCommand:'neocortex-client refresh-memory --project-root "$PROJECT_ROOT"',guardrails:["Use only permitted bootstrap sources; never read real .env files or credentials into memory.","Preserve human-authored wrapper content outside Neocortex managed blocks.","Do not reset .neocortex/state.json or depend on legacy planning.current during init bootstrap."]}}function Oe(){try{if(R(K))return;const e=fe(),t=me(e);process.stderr.write(t);try{se(T,{recursive:!0}),oe(K,new Date().toISOString(),"utf-8")}catch{}}catch{}}function ke(e,t=process.cwd()){return e&&e.trim().length>0?e:t}function xe(e){return e.replace(/[\w.+-]+@[\w-]+\.[\w.-]+/g,S).replace(/(?:sk|pk|whsec|nxk)[-_](?:test|live|ant|proj|pro|free|enterprise)?[-_]?[A-Za-z0-9_-]{16,}/g,S).replace(/NX-[FPE]-[a-f0-9]{24}-[a-f0-9]{4}/g,S).replace(/eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,S).replace(Ae,S)}function C(e,t){const r=xe(e);return r.length<=t?r:`${r.slice(0,t)}\u2026[TRUNCATED:${r.length-t}]`}function O(e,t=0,r=new WeakSet){if(t>Ce)return"[MAX_DEPTH]";if(e==null)return e;if(typeof e=="string")return C(e,N);if(typeof e=="number")return Number.isFinite(e)?e:null;if(typeof e=="boolean")return e;if(typeof e=="bigint")return String(e);if(typeof e=="function"||typeof e=="symbol"||typeof e!="object")return;if(r.has(e))return"[CIRCULAR]";if(r.add(e),Array.isArray(e))return e.slice(0,Se).map(a=>O(a,t+1,r));const o={};for(const[a,c]of Object.entries(e).slice(0,Re)){if(Ie.test(a)){o[a]=S;continue}const u=O(c,t+1,r);u!==void 0&&(o[a]=u)}return o}function k(e,t){return{instructions:C(e??"",we),metadata:t?O(t):void 0}}class h extends Error{code;constructor(t,r){super(r),this.name="InvokeCliInputError",this.code=t}}let x=!1;function Pe(e){const t=[];if(!e||typeof e!="object")return t;const r=e,o=r.planning;if(o&&(o.current!==void 0||Array.isArray(o.history))&&t.push({code:"PLANNING_LEGACY",message:"legacy `planning.current`/`planning.history` detected (not read by v1 orchestrator)"}),Array.isArray(r.stories)&&t.push({code:"STORIES_AS_ARRAY",message:"`stories` is an Array (expected Object keyed by story ID)"}),r.epics&&typeof r.epics=="object"&&!Array.isArray(r.epics))for(const[c,u]of Object.entries(r.epics)){const l=u;if(l&&l.stories!==void 0&&!Array.isArray(l.stories)){t.push({code:"EPIC_STORIES_NOT_ARRAY",message:`epic "${c}" has non-array \`stories\` field (expected string[] of story IDs)`});break}}const a=r.epics&&typeof r.epics=="object"&&Object.keys(r.epics).length>0||r.stories&&typeof r.stories=="object"&&!Array.isArray(r.stories)&&Object.keys(r.stories).length>0||Array.isArray(r.stories)||o&&o.current!==void 0;return r.schema_version===void 0?a&&t.push({code:"SCHEMA_VERSION_MISSING",message:"`schema_version` field missing (expected: `schema_version: 1`)"}):r.schema_version!==1&&t.push({code:"SCHEMA_VERSION_OUTDATED",message:`schema_version=${String(r.schema_version)} (expected: 1)`}),t}function Le(e){if(!(x||e.length===0)){x=!0;try{const t=e.map(r=>` - ${r.message}`).join(`
2
+ `);process.stderr.write(`[Neocortex] state.json schema drift detected:
3
+ ${t}
4
+ Run \`neocortex *migrate-state --preview\` to inspect or \`neocortex *migrate-state --apply\` to migrate.
5
+ See docs/arquitetura-software/STATE-JSON-SCHEMA.md for the schema contract.
6
+ `)}catch{}}}function mt(){x=!1}function H(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.length>0):[]}function De(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.length>0):[]}function $e(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function G(e){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:void 0}function w(e){if(typeof e!="string")return;const t=e.trim();if(t)return t.replace(/[^a-z0-9_.:-]+/gi,"_").slice(0,120)}function P(e,t){if(!$e(e))return;const r={};for(const o of t){const a=e[o];if(typeof a=="boolean")r[o]=a;else if(typeof a=="number"&&Number.isFinite(a))r[o]=a;else if(typeof a=="string"){const c=w(a);c&&(r[o]=c)}}return Object.keys(r).length>0?r:void 0}function ve(e){const t=P(e.completionEvidence??e.completion_evidence,["prNumber","pr_number","prState","pr_state","pullRequestState","merged","mergedAt","issueNumber","issue_number","issueState","issue_state","closedAt"]),r=P(e.issueCloseAudit??e.issue_close_audit,["schema_version","event","storyId","epicId","issueNumber","closedAt","publicSafe","rawLogStorage"]),o=P(e.scopedCiEvidence??e.scoped_ci_evidence,["schema_version","storyId","epicId","prNumber","finalState","publicSafe","rawLogStorage"]);return{...typeof e.merged=="boolean"?{merged:e.merged}:{},...typeof e.safeToContinueYoloop=="boolean"?{safeToContinueYoloop:e.safeToContinueYoloop}:{},...typeof e.mergeBlockedRemotely=="boolean"?{mergeBlockedRemotely:e.mergeBlockedRemotely}:{},...w(e.physicalMergeStatus)?{physicalMergeStatus:w(e.physicalMergeStatus)}:{},...w(e.pr_state??e.prState??e.pull_request_state??e.pullRequestState)?{pr_state:w(e.pr_state??e.prState??e.pull_request_state??e.pullRequestState)}:{},...w(e.issue_state??e.issueState??e.workflow_issue_state)?{issue_state:w(e.issue_state??e.issueState??e.workflow_issue_state)}:{},...G(e.issue_number??e.issueNumber)?{issue_number:G(e.issue_number??e.issueNumber)}:{},...t?{completionEvidence:t}:{},...r?{issueCloseAudit:r}:{},...o?{scopedCiEvidence:o}:{}}}function Fe(e){const t=y(e,".neocortex","state.json");if(!R(t))return{config:{project_name:"unknown",default_branch:"main",language:"pt-BR"},stories:{},epics:{}};let r;try{const d=A(t,"utf-8");r=JSON.parse(d)}catch{return{config:{project_name:"unknown",default_branch:"main",language:"pt-BR"},stories:{},epics:{}}}try{const d=Pe(r);d.length>0&&Le(d)}catch{}const o=r.config??r.project??{},a=r.stories??{},c={};for(const[d,p]of Object.entries(a))c[d]={id:p.id??d,title:p.title,epic_id:p.epic_id,status:p.status??"backlog",steps_completed:p.steps_completed??[],last_step:p.last_step??null,branch_name:p.branch_name??null,pr_number:p.pr_number,workflow_issue:p.workflow_issue,...ve(p),depends_on:H(p.depends_on),files_to_modify:De(p.files_to_modify),risk:typeof p.risk=="string"?p.risk:void 0,blast_radius:typeof p.blast_radius=="number"?p.blast_radius:void 0};const u=r.epics??{},l={};for(const[d,p]of Object.entries(u))l[d]={id:p.id??d,title:p.title,status:p.status,stories:p.stories,total_stories:p.total_stories,completed_stories:p.completed_stories,depends_on:H(p.depends_on)};return{schema_version:typeof r.schema_version=="number"?r.schema_version:void 0,config:{project_name:o.project_name??o.name??"unknown",default_branch:o.default_branch??"main",language:o.language??"pt-BR",yolo_mode:o.yolo_mode,user_name:o.user_name,worktree_base:o.worktree_base,max_parallel_stories:o.max_parallel_stories},stories:c,epics:l}}function gt(e,t){return{kind:"full",trigger:e,targetEpicId:null,targetStoryId:null,includedStoryCount:Object.keys(t.stories).length,omittedStoryCount:0,omittedEpicCount:0,reason:"full-state"}}const J="neocortex:menu:cache";async function Ue(e){try{const t=await e.get(J);if(!t)return null;const r=JSON.parse(t);return r.version!==E||Date.now()-r.cachedAt>B?null:r}catch{return null}}async function Me(e,t,r){try{const o={instructions:t,metadata:r,cachedAt:Date.now(),version:E};await e.set(J,JSON.stringify(o),B),je()}catch{}}function je(){try{R(j)&&ne(j)}catch{}}function Be(){return pe()}async function Ye(e,t){try{let r;if(t){const u=y(T,"cache");r=new $({cacheDir:u,passphrase:t})}else process.stderr.write(`[neocortex] Warning: No license key in config. Run "neocortex activate" to re-authenticate.
7
+ `),r=new ce;const o=new ae({serverUrl:e,licenseKey:t??"",cacheProvider:r}),a=await o.getToken();if(!a)return null;const c=new de({cacheProvider:r,licenseClient:o});return{token:a,client:o,tierClient:c}}catch{return null}}let W=!1;function q(e){return D("sha256").update(e).digest("hex")}function ze(){const e=Number(process.env.NEOCORTEX_INVOKE_CHUNK_BYTES??"49152");return Number.isFinite(e)&&e>=1024&&e<=98304?Math.floor(e):49152}function Ve(e,t,r){return`args-${D("sha256").update("invoke-materialization:v1").update(e).update(String(t)).update(JSON.stringify(r)).digest("hex")}`}async function X(e,t,r,o){const a=await fetch(`${e}${t}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`,"X-Client-Version":E},body:JSON.stringify(r)}),c=await a.text().catch(()=>""),u=(()=>{try{return c?JSON.parse(c):{}}catch{return{}}})();if(!a.ok){const l=typeof u.error_code=="string"?u.error_code:`HTTP_${a.status}`,d=typeof u.message=="string"?u.message:"materialization upload failed";throw new Error(`${l}: ${d}`)}return u}async function Ke(e,t,r){const o=Buffer.from(t,"utf8"),a=ze(),c=[];for(let f=0,_=0;f<o.byteLength;f+=a,_++){const i=o.subarray(f,Math.min(f+a,o.byteLength));c.push({index:_,sha256:q(i),byteLength:i.byteLength})}const u=q(o),l=Ve(u,o.byteLength,c),d=Number(process.env.NEOCORTEX_INVOKE_CHUNK_TTL_SECONDS??"900");for(const f of c){const _=f.index*a,i=o.subarray(_,_+f.byteLength);await X(e,"/api/v1/invoke/materialization/chunks",{manifestId:l,index:f.index,sha256:f.sha256,byteLength:f.byteLength,contentBase64:i.toString("base64"),ttlSeconds:d,idempotencyKey:`${l}:${f.index}:${f.sha256}`},r)}const g=(await X(e,"/api/v1/invoke/materialization/manifests",{manifestId:l,sha256:u,byteLength:o.byteLength,chunkCount:c.length,chunks:c,ttlSeconds:d,retry:{attempt:1,budget:3,idempotencyKey:l}},r)).argsRef;if(!g?.manifestId)throw new Error("MATERIALIZATION_RESPONSE_INVALID: missing argsRef");return{argsRef:g,chunks:c}}function He(e){return Buffer.byteLength(JSON.stringify(e),"utf8")}function Ge(e){return ee(e)??e.trim().split(/\s+/,1)[0]?.slice(0,80)??"(empty)"}function Je(e){return e.args!==void 0?Ge(e.args):`argsRef:${e.argsRef.manifestId.slice(0,80)}`}function Z(e){const t=He(e);if(t<V)return t;const r=e.stateSnapshot.scope,o=Object.keys(e.stateSnapshot.stories).length,a=r?.kind??"full",c=r?.includedStoryCount??o,u=r?.omittedStoryCount??0;return process.stderr.write(`[Neocortex] invoke payload near server limit: trigger=${Je(e)} scope=${a} bytes=${t} limit=${z} includedStories=${c} omittedStories=${u}
8
+ `),t}async function Q(e,t,r){const o=`${e}/api/v1/invoke`,a=new AbortController,c=setTimeout(()=>a.abort(),Y);try{const u=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`,"X-Client-Version":E},body:JSON.stringify(t),signal:a.signal});if(clearTimeout(c),!u.ok){const p=await u.text().catch(()=>"Unknown error");let g;try{g=JSON.parse(p)}catch{}return{ok:!1,status:u.status,error:g?`${g.error_code??"ERROR"}: ${g.message??p}`:`HTTP ${u.status}: ${p}`,errorBody:g}}const l=await u.json(),d=u.headers.get("X-Client-Version-Warning");return d&&!W&&(W=!0,process.stderr.write(`
9
+ [Neocortex] ${d}
10
+
11
+ `)),{ok:!0,status:u.status,data:l}}catch(u){clearTimeout(c);const l=u instanceof Error?u.message:String(u);return{ok:!1,status:0,error:l.includes("abort")?`Request timeout after ${Y/1e3}s`:`Network error: ${l}`}}}async function We(e){const t=ke(e.projectRoot),r=e.platformTarget??"claude-code";Oe();const o=Be(),a=(e.serverUrl??o?.serverUrl??le).replace(/\/+$/,"");try{he(t)}catch(n){if(n instanceof _e)return process.stderr.write(`${n.message}
12
+ `),{success:!1,error:n.message,exitCode:1};const s=n instanceof Error?n.message:String(n);return process.stderr.write(`[Neocortex] state.json repair stopped unexpectedly: ${s}. No request was sent; inspect .neocortex/state.json and rerun.
13
+ `),{success:!1,error:s,exitCode:1}}const c=Fe(t);try{const{maybeAutoResolveYoloopArgs:n}=await import("../yoloop/invoke-hooks.js"),s={args:e.args,projectRoot:t,logger:{info:m=>process.stderr.write(`${m}
14
+ `),warn:m=>process.stderr.write(`${m}
15
+ `)}};n(s),s.args!==e.args&&(e={...e,args:s.args})}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] Auto-resolve hook (P121.05) failed: ${s}. Proceeding with raw args.
16
+ `)}try{const{readYoloopForRequest:n}=await import("../yoloop/invoke-hooks.js"),s=await n(e.args,t);s&&(c.yoloop=s)}catch{}try{const{readContinuityForRequest:n}=await import("../continuity/invoke-hooks.js"),s=await n(e.args,t);s&&(c.continuity=s)}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] continuity snapshot hook failed: ${s}. Proceeding without continuity state.
17
+ `)}try{const{maybeRunDiscoveryHook:n}=await import("../yoloop/invoke-hooks.js");await n({args:e.args,projectRoot:t,stateSnapshot:c,featureFlag:process.env.YOLOOP_AUTO_DISCOVERY!=="off",logger:{warn:s=>{console.warn(s)},info:s=>{console.error(s)}}})}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] discovery hook failed: ${s}. Proceeding without enrichment.
18
+ `)}try{const{readArchitecturePolicy:n}=await import("../policy/architecture-policy.js"),s=await n(t);s&&(c.architecture_policy=s)}catch(n){const s=n instanceof Error?n.message:String(n);console.warn(`[Neocortex] architecture-policy hook failed: ${s}. Proceeding without policy.`)}try{const n=/^(1|true|on|yes)$/i.test(process.env.NEOCORTEX_GRAPH_RETRIEVAL??""),{maybeRunGraphRetrievalHook:s}=await import("../yoloop/invoke-hooks.js"),m=await s({args:e.args,projectRoot:t,featureFlag:n,logger:{warn:I=>process.stderr.write(`${I}
19
+ `)}});m.applied&&m.metadata&&(c.graphRetrieval=m.metadata)}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] graph retrieval hook failed: ${s}. Proceeding without enrichment.
20
+ `)}try{const{readAndConsumeCheckpoint:n}=await import("../checkpoint/index.js"),s=await n(t);s&&(c.implementCheckpoint=s)}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] checkpoint hook failed: ${s}. Proceeding without checkpoint.
21
+ `)}const u=o?.licenseKey?new $({cacheDir:M,passphrase:o.licenseKey}):null,l=e.args.trim();if(Ne(l))try{c.projectMemoryBootstrap=be(t)}catch(n){const s=n instanceof Error?n.message:String(n);process.stderr.write(`[Neocortex] project-memory bootstrap diagnosis failed: ${s}. Proceeding without local memory snapshot.
22
+ `)}if(!l&&u){const n=await Ue(u);if(n)return{success:!0,instructions:n.instructions,metadata:n.metadata,exitCode:0}}const d=await Ye(a,o?.licenseKey);if(!d){const n=o&&!o.licenseKey?" This may be caused by a machine fingerprint change (e.g., hardware or hostname change).":"";try{const s=U(),m=v("NOT_CONFIGURED",s);m&&process.stderr.write(F(m,s))}catch{}return{success:!1,error:`Not authenticated.${n} Visit https://neocortex.sh/portal/login to get your license key, then run: neocortex activate YOUR-LICENSE-KEY`,exitCode:2}}const p=ee(l);if(p)try{const n=await d.tierClient.preFlightCheck(p);if(!n.allowed)return process.stderr.write(`[neocortex] ${n.message}
23
+ `),{success:!1,error:n.message??"Trigger not available on your plan",exitCode:1}}catch{}const g=ge(l,c);let f={args:l,projectRoot:t.replace(b(),"~"),stateSnapshot:g,platformTarget:r};const _=Z(f);if(e.inputSource&&e.inputSource!=="args"&&_>=V)try{f={argsRef:(await Ke(a,l,d.token)).argsRef,projectRoot:t.replace(b(),"~"),stateSnapshot:g,platformTarget:r},Z(f)}catch(n){return{success:!1,error:`INVOKE_MATERIALIZATION_FAILED: ${n instanceof Error?n.message:String(n)}`,errorCode:"INVOKE_MATERIALIZATION_FAILED",exitCode:1}}let i=await Q(a,f,d.token);if(!i.ok&&i.status===401){const n=i.errorBody?.fallback_action;if(n==="refresh_token"||n==="re_authenticate"){const s=await d.client.forceRefresh();s&&(i=await Q(a,f,s))}}if(!i.ok&&i.status===426){const n=i.errorBody,s=n?.upgrade_command??"npm install -g @ornexus/neocortex@latest",m=n?.min_version??"unknown";return process.stderr.write(`
24
+ `),process.stderr.write(`==================================================
25
+ `),process.stderr.write(` UPGRADE REQUIRED
26
+ `),process.stderr.write(`==================================================
27
+ `),process.stderr.write(`
28
+ Your Neocortex version (${E}) is no longer supported.
29
+ `),process.stderr.write(` Minimum required: ${m}
30
+
31
+ `),process.stderr.write(` Run this command to update:
32
+
33
+ `),process.stderr.write(` ${s}
34
+
35
+ `),process.stderr.write(` After updating, re-run your command.
36
+ `),process.stderr.write(`==================================================
37
+
38
+ `),{success:!1,error:`UPGRADE_REQUIRED: Client version ${E} is below minimum ${m}. Run: ${s}`,exitCode:3}}if(!i.ok||!i.data){const n=i.status===401?2:(i.status===429||i.status>=500,1);try{const s=i.errorBody?.error_code??(i.status===429?"RATE_LIMITED":i.status>=500?"SERVER_ERROR":void 0);if(s){const m=U(),I=v(s,m);I&&process.stderr.write(F(I,m))}}catch{}return{success:!1,error:C(i.error??"Unknown error from server",N),exitCode:n}}if(!l&&i.data.metadata?.mode==="menu"&&u&&Me(u,i.data.instructions,i.data.metadata).catch(()=>{}),i.data.metadata&&d.tierClient.updateQuotaFromResponse(i.data.metadata).catch(()=>{}),i.data.metadata?.mode==="error"&&i.data.metadata?.errorCode==="CLIENT_UPGRADE_REQUIRED")return process.stderr.write(`
39
+ `),process.stderr.write(`==================================================
40
+ `),process.stderr.write(` YOLOOP CLIENT UPGRADE REQUIRED
41
+ `),process.stderr.write(`==================================================
42
+ `),process.stderr.write(`
43
+ Your Neocortex client version (${E}) does not
44
+ `),process.stderr.write(` support client-side yoloop state persistence.
45
+
46
+ `),process.stderr.write(` Run this command to upgrade:
47
+
48
+ `),process.stderr.write(` npm install -g @ornexus/neocortex@latest
49
+
50
+ `),process.stderr.write(` After upgrading, re-run your yoloop command.
51
+ `),process.stderr.write(`==================================================
52
+
53
+ `),{success:!1,error:"CLIENT_UPGRADE_REQUIRED: This client does not support yoloop client-side persistence. Run: npm install -g @ornexus/neocortex@latest",exitCode:3};if(i.data.metadata?.yoloopStateUpdate)try{const{persistYoloopFromResponse:n}=await import("../yoloop/invoke-hooks.js");await n(i.data.metadata,t)}catch{}if(i.data.metadata?.continuityStateUpdate)try{const{persistContinuityFromResponse:n}=await import("../continuity/invoke-hooks.js"),s=await n(i.data.metadata,t);if(!s.ok){const m=s.reasonCodes.join(",");return process.stderr.write(`[Neocortex] continuity persistence failed: ${m}. No continuity mutation was committed.
54
+ `),{success:!1,error:`CONTINUITY_PERSISTENCE_FAILED: ${m}`,errorCode:"CONTINUITY_PERSISTENCE_FAILED",exitCode:1}}}catch(n){const s=n instanceof Error?n.message:String(n);return process.stderr.write(`[Neocortex] continuity persistence hook failed: ${s}. No continuity mutation was committed.
55
+ `),{success:!1,error:`CONTINUITY_PERSISTENCE_FAILED: ${C(s,N)}`,errorCode:"CONTINUITY_PERSISTENCE_FAILED",exitCode:1}}if(i.data.metadata?.stateMutated===!0)try{const{persistMigratedStateFromResponse:n}=await import("../yoloop/invoke-hooks.js");await n(i.data.metadata,t)}catch{}if(i.data.metadata?.tier_changed){const n=i.data.metadata.current_tier;try{await d.client.forceRefresh()?(await d.tierClient.invalidateTierCache(),process.stderr.write(`[Neocortex] Token atualizado automaticamente para tier ${n}
56
+ `)):process.stderr.write(`[Neocortex] Seu tier foi atualizado para ${n}! Execute "neocortex activate" para obter um token atualizado.
57
+ `)}catch{process.stderr.write(`[Neocortex] Seu tier foi atualizado para ${n}! Execute "neocortex activate" para obter um token atualizado.
58
+ `)}}const L=k(i.data.instructions,i.data.metadata);return{success:!0,instructions:L.instructions,metadata:L.metadata,exitCode:0}}function ee(e){const[t]=e.trim().split(/\s+/,1);return t?/^@?epic-[a-z0-9][a-z0-9._-]*$/i.test(t)?"epic":ue(t):null}const te="Provide exactly one invoke input source: --args <string>, --stdin, or --args-file <path>.";function re(e){return new h("INVOKE_INPUT_VALUE_MISSING",`${e} requires a value. ${te}`)}function qe(e){try{if(!ie(e).isFile())throw new h("INVOKE_ARGS_FILE_NOT_FILE","--args-file must point to a readable UTF-8 text file.");return A(e,"utf8")}catch(t){throw t instanceof h?t:new h("INVOKE_ARGS_FILE_READ_FAILED","--args-file could not be read as UTF-8 text. Check the path and permissions.")}}function Xe(){try{if(process.stdin.isTTY)throw new h("INVOKE_STDIN_EMPTY","--stdin requires piped UTF-8 text, for example: neocortex-client invoke --stdin < synthetic.story.md");return A(0,"utf8")}catch(e){throw e instanceof h?e:new h("INVOKE_STDIN_READ_FAILED","--stdin could not be read as UTF-8 text. Pipe command text into stdin and retry.")}}function Ze(e,t={}){let r,o=!1,a,c,u="plain",l;for(let f=0;f<e.length;f++)switch(e[f]){case"--args":{const i=e[++f];if(i===void 0)throw re("--args");r=i;break}case"--stdin":o=!0;break;case"--args-file":{const i=e[++f];if(i===void 0)throw re("--args-file");a=i;break}case"--project-root":c=e[++f];break;case"--format":u=e[++f]??"plain";break;case"--server-url":l=e[++f];break}const d=[r!==void 0?"args":void 0,o?"stdin":void 0,a!==void 0?"args-file":void 0].filter(f=>f!==void 0);if(d.length===0)throw new h("INVOKE_INPUT_SOURCE_MISSING",te);if(d.length>1)throw new h("INVOKE_INPUT_SOURCE_CONFLICT",`Choose only one invoke input source; received ${d.join(", ")}.`);const p=d[0];return{args:p==="args"?r:p==="stdin"?(t.readStdin??Xe)():(t.readArgsFile??qe)(a),inputSource:p,projectRoot:c,format:u,serverUrl:l}}async function ht(e){let t;try{t=Ze(e)}catch(o){if(o instanceof h)return process.stderr.write(JSON.stringify({error_code:o.code,message:o.message})+`
59
+ `),1;throw o}const r=await We({args:t.args,inputSource:t.inputSource,projectRoot:t.projectRoot,format:t.format,serverUrl:t.serverUrl});if(!r.success)return process.stderr.write(JSON.stringify({error_code:r.errorCode??(r.exitCode===2?"NOT_CONFIGURED":"INVOKE_ERROR"),message:C(r.error??"",N)})+`
60
+ `),r.exitCode;if(t.format==="json"){const o=k(r.instructions,r.metadata);process.stdout.write(JSON.stringify({instructions:o.instructions,metadata:o.metadata})+`
61
+ `)}else{const o=k(r.instructions,r.metadata);process.stdout.write(o.instructions+`
62
+ `),o.metadata&&process.stderr.write(JSON.stringify(o.metadata)+`
63
+ `)}return 0}export{V as INVOKE_PAYLOAD_WARNING_THRESHOLD_BYTES,h as InvokeCliInputError,mt as __resetSchemaDriftWarnedForTests,be as collectInitProjectMemoryBootstrapSnapshot,Fe as collectStateSnapshot,He as computeInvokeRequestBodySizeBytes,gt as createFullStateSnapshotScope,Pe as detectStateSchemaDrift,ee as extractPreFlightTrigger,We as invoke,ht as invokeCliHandler,Ne as isInitTrigger,Z as maybeEmitInvokePayloadSizeWarning,Ze as parseInvokeCliOptions,ke as resolveInvokeProjectRoot,k as sanitizeInvokeCliOutput};
@@ -0,0 +1,11 @@
1
+ import { type ProjectMemoryTargetId } from '../memory/shared-project-memory-types.js';
2
+ import { type WriteProjectMemoryTargetFilesResult } from '../memory/project-memory-writer.js';
3
+ export interface RefreshMemoryCliOptions {
4
+ readonly projectRoot: string;
5
+ readonly targetIds: readonly ProjectMemoryTargetId[];
6
+ readonly dryRun: boolean;
7
+ readonly memoryNotes?: readonly string[];
8
+ }
9
+ export declare function parseRefreshMemoryArgs(args: readonly string[]): RefreshMemoryCliOptions;
10
+ export declare function refreshProjectMemoryTargets(options: RefreshMemoryCliOptions): readonly WriteProjectMemoryTargetFilesResult[];
11
+ export declare function refreshMemoryCliHandler(args: readonly string[]): Promise<number>;
@@ -0,0 +1 @@
1
+ import{resolve as m}from"node:path";import{isProjectMemoryTargetId as h,listProjectMemoryTargets as d}from"../memory/shared-project-memory-types.js";import{writeProjectMemoryTargetFiles as g}from"../memory/project-memory-writer.js";function i(r){return(r??"").split(",").map(t=>t.trim()).filter(Boolean)}function p(r){let t=process.cwd(),c=!1;const a=[],n=[];for(let s=0;s<r.length;s++){const e=r[s];if(e==="--dry-run"||e==="--preview")c=!0;else if(e==="--project-root")t=r[++s]??t;else if(e.startsWith("--project-root="))t=e.slice(15);else if(e==="--target"||e==="--targets")a.push(...i(r[++s]));else if(e.startsWith("--target="))a.push(...i(e.slice(9)));else if(e.startsWith("--targets="))a.push(...i(e.slice(10)));else if(e==="--note"||e==="--memory-note"||e==="--change"){const l=r[++s];l&&n.push(l)}else e.startsWith("--note=")?n.push(e.slice(7)):e.startsWith("--memory-note=")?n.push(e.slice(14)):e.startsWith("--change=")&&n.push(e.slice(9))}const o=a.length>0?a.map(s=>{if(!h(s))throw new Error(`Unknown project-memory target: ${s}`);return s}):["canonical",...d().map(s=>s.targetId)];return{projectRoot:m(t),targetIds:Array.from(new Set(o)),dryRun:c,memoryNotes:n}}function u(r){return r.targetIds.map(t=>g({projectRoot:r.projectRoot,targetId:t,dryRun:r.dryRun,memoryNotes:r.memoryNotes??[]}))}async function R(r){try{const t=p(r),a=u(t).flatMap(n=>n.files.map(o=>[o.changed?t.dryRun?"would-change":"changed":"unchanged",o.mode,o.relativeFile,o.fallbackReason?`warning=${o.fallbackReason}`:void 0,o.remediationDebt?`debt=${o.remediationDebt}`:void 0,o.reasonCodes&&o.reasonCodes.length>0?`reasons=${o.reasonCodes.join(",")}`:void 0].filter(Boolean).join(" ")));console.log(`${t.dryRun?"Project memory preview":"Project memory refreshed"}: ${t.projectRoot}`);for(const n of a)console.log(n);return 0}catch(t){return console.error(t instanceof Error?t.message:String(t)),1}}export{p as parseRefreshMemoryArgs,R as refreshMemoryCliHandler,u as refreshProjectMemoryTargets};
@@ -0,0 +1,40 @@
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
+ import type { AssetResolver } from '../resolvers/asset-resolver.js';
14
+ import type { CreateResolverOptions } from '../types/index.js';
15
+ /** Result of resolver selection including the reason for the choice */
16
+ export interface ResolverSelectionResult {
17
+ readonly resolver: AssetResolver;
18
+ readonly reason: string;
19
+ readonly mode: 'local' | 'remote';
20
+ }
21
+ /**
22
+ * Create the appropriate AssetResolver based on configuration.
23
+ *
24
+ * Selection follows a strict priority chain:
25
+ * 1. forceLocal option -> LocalResolver
26
+ * 2. NEOCORTEX_MODE=local -> LocalResolver
27
+ * 3. NEOCORTEX_MODE=remote -> RemoteResolver
28
+ * 4. core/ exists locally -> LocalResolver
29
+ * 5. License key + no core/ -> RemoteResolver
30
+ * 6. Default -> LocalResolver
31
+ *
32
+ * @param options - Optional configuration overrides
33
+ * @returns Configured AssetResolver ready for use
34
+ */
35
+ export declare function createResolver(options?: CreateResolverOptions): Promise<AssetResolver>;
36
+ /**
37
+ * Select resolver with full result including reason.
38
+ * Useful for logging/debugging why a specific resolver was chosen.
39
+ */
40
+ export declare function selectResolver(options?: CreateResolverOptions): Promise<ResolverSelectionResult>;
@@ -0,0 +1 @@
1
+ import{access as E,readFile as h,writeFile as R,mkdir as C}from"node:fs/promises";import{join as i,resolve as w}from"node:path";import{homedir as d}from"node:os";import{createHash as g}from"node:crypto";import{LocalResolver as l}from"../resolvers/local-resolver.js";import{RemoteResolver as u}from"../resolvers/remote-resolver.js";import{DEFAULT_SERVER_URL as O}from"../constants.js";const v=i(d(),".neocortex","feature-flags.json"),y=36e5;async function _(e){try{const r=process.env.NEOCORTEX_REMOTE_PERCENTAGE;if(r!==void 0){const n=parseInt(r,10);return isNaN(n)||n<=0?"skip":f(n)?"remote":"local"}const t=await F();if(t)return t.forceLocal?"local":t.forceRemote?"remote":t.remotePercentage<=0?"skip":f(t.remotePercentage)?"remote":"local";const c=s(e),o=await L(c);return o?(await p(o),o.forceLocal?"local":o.forceRemote?"remote":o.remotePercentage<=0?"skip":f(o.remotePercentage)?"remote":"local"):"skip"}catch{return"skip"}}function f(e){const r=process.env.NEOCORTEX_MACHINE_ID??"default";return g("sha256").update(r).digest().readUInt16BE(0)%100<e}async function F(){try{const e=await h(v,"utf-8"),r=JSON.parse(e);return Date.now()-r.fetchedAt<y?r:null}catch{return null}}async function p(e){try{await C(i(d(),".neocortex"),{recursive:!0}),await R(v,JSON.stringify(e),"utf-8")}catch{}}async function L(e){try{const r=new AbortController,t=setTimeout(()=>r.abort(),5e3),c=await fetch(`${e}/api/v1/config`,{signal:r.signal});if(clearTimeout(t),!c.ok)return null;const o=await c.json();return{remotePercentage:o.remotePercentage??0,forceRemote:o.forceRemote??!1,forceLocal:o.forceLocal??!1,fetchedAt:Date.now()}}catch{return null}}async function N(e){try{return await E(i(e,"core")),!0}catch{return!1}}function m(e){return e?.licenseKey||process.env.NEOCORTEX_LICENSE_KEY||void 0}function s(e){return e?.serverUrl||process.env.NEOCORTEX_SERVER_URL||O}async function M(e){return(await k(e)).resolver}async function k(e){const r=w(e?.projectRoot||process.cwd()),t=process.env.NEOCORTEX_MODE?.toLowerCase();if(e?.forceLocal)return{resolver:new l({projectRoot:r}),reason:"Forced local mode via --local flag",mode:"local"};if(t==="local")return{resolver:new l({projectRoot:r}),reason:"NEOCORTEX_MODE=local environment variable",mode:"local"};if(t==="remote"){const a=m(e);return a?{resolver:new u({serverUrl:s(e),licenseKey:a,cacheProvider:e?.cacheProvider,licenseClient:e?.licenseClient}),reason:"NEOCORTEX_MODE=remote environment variable",mode:"remote"}:{resolver:new l({projectRoot:r}),reason:"NEOCORTEX_MODE=remote but no license key found, falling back to local",mode:"local"}}if(await N(r))return{resolver:new l({projectRoot:r}),reason:"Auto-detected development mode (core/ directory exists)",mode:"local"};if(await _(e)==="remote"){const a=m(e);if(a)return{resolver:new u({serverUrl:s(e),licenseKey:a,cacheProvider:e?.cacheProvider,licenseClient:e?.licenseClient}),reason:"Feature flag cutover: machine in remote bucket",mode:"remote"}}const n=m(e);return n?{resolver:new u({serverUrl:s(e),licenseKey:n,cacheProvider:e?.cacheProvider,licenseClient:e?.licenseClient}),reason:"Auto-detected production mode (license key present, no core/ directory)",mode:"remote"}:{resolver:new l({projectRoot:r}),reason:"Default fallback to local mode",mode:"local"}}export{M as createResolver,k as selectResolver};
@@ -0,0 +1,78 @@
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
+ /** Key type discriminator (Story 29.04) */
14
+ export type KeyType = 'license' | 'api_key';
15
+ /** Resolved config with decrypted license key */
16
+ export interface SecureConfig {
17
+ readonly serverUrl?: string;
18
+ readonly mode?: string;
19
+ readonly machineId?: string;
20
+ readonly activatedAt?: string;
21
+ readonly tier?: string;
22
+ readonly licenseKey?: string;
23
+ /** Key type: 'license' (NX-...) or 'api_key' (nxk_...). undefined = legacy (treat as license). Story 29.04 */
24
+ readonly keyType?: KeyType;
25
+ }
26
+ /**
27
+ * Encrypt a license key using the machine fingerprint as passphrase.
28
+ * Returns the encrypted envelope string.
29
+ */
30
+ export declare function encryptLicenseKey(licenseKey: string): string;
31
+ /**
32
+ * Decrypt a license key using the machine fingerprint as passphrase.
33
+ * Returns the plaintext key or null if decryption fails (hardware changed).
34
+ */
35
+ export declare function decryptLicenseKey(encryptedKey: string): string | null;
36
+ /**
37
+ * Set restrictive file permissions on config files.
38
+ * Unix: chmod 600 (owner read/write only).
39
+ * Windows: icacls to remove inheritance and grant Full Control only to current user.
40
+ * Story 61.4 - F4 remediation.
41
+ * Story 66.1 - Windows ACL via icacls.
42
+ */
43
+ export declare function setSecureFilePermissions(filePath: string): void;
44
+ /**
45
+ * Set restrictive directory permissions on config directories.
46
+ * Unix: chmod 700 (owner read/write/execute only).
47
+ * Windows: icacls with (OI)(CI) for propagation to child objects.
48
+ * Story 61.4 - F4 remediation.
49
+ * Story 66.1 - Windows ACL via icacls.
50
+ */
51
+ export declare function setSecureDirPermissions(dirPath: string): void;
52
+ /**
53
+ * Load config from ~/.neocortex/config.json with automatic migration.
54
+ *
55
+ * If the config contains a plaintext `licenseKey` (old format), it is:
56
+ * 1. Encrypted using machine fingerprint
57
+ * 2. Stored as `encryptedLicenseKey`
58
+ * 3. Old `licenseKey` field removed
59
+ * 4. Config rewritten to disk
60
+ *
61
+ * If decryption of `encryptedLicenseKey` fails (hardware change),
62
+ * returns config with licenseKey = undefined.
63
+ */
64
+ export declare function loadSecureConfig(): SecureConfig | null;
65
+ /**
66
+ * Save config after activation with encrypted license key.
67
+ * This is the primary write path called from activate.ts.
68
+ */
69
+ export declare function saveSecureConfig(config: {
70
+ serverUrl: string;
71
+ mode: string;
72
+ machineId: string;
73
+ activatedAt: string;
74
+ tier?: string;
75
+ licenseKey: string;
76
+ /** Key type: 'license' (NX-...) or 'api_key' (nxk_...). Auto-detected from key prefix if omitted. Story 29.04 */
77
+ keyType?: KeyType;
78
+ }): void;
@@ -0,0 +1,12 @@
1
+ import{existsSync as p,readFileSync as U,writeFileSync as R,mkdirSync as S,chmodSync as u}from"node:fs";import{execSync as y}from"node:child_process";import{join as a}from"node:path";import{homedir as L}from"node:os";import{encrypt as I,decrypt as g}from"../cache/crypto-utils.js";import{getMachineFingerprint as l}from"../machine/fingerprint.js";import{DEFAULT_SERVER_URL as x}from"../constants.js";const o=a(L(),".neocortex"),s=a(o,"config.json"),K=["api","neocortex","ornexus","com"].join("."),d=1;function f(r){const e=l();return I(r,e)}function C(r){try{const e=l();return g(r,e).plaintext}catch{return null}}function O(r){try{if(process.platform==="win32"){const e=process.env.USERNAME||process.env.USER||"";if(!e)return;y(`icacls "${r}" /inheritance:r /grant:r "${e}:(F)"`,{stdio:"pipe",timeout:5e3})}else u(r,384)}catch{}}function m(r){try{if(process.platform==="win32"){const e=process.env.USERNAME||process.env.USER||"";if(!e)return;y(`icacls "${r}" /inheritance:r /grant:r "${e}:(OI)(CI)(F)"`,{stdio:"pipe",timeout:5e3})}else u(r,448)}catch{}}let h=!1;function _(r){if(h)return;const e=r.serverUrl;if(!e)return;/^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0)(:\d+)?/i.test(e)&&(h=!0,console.warn(`
2
+ [!] Warning: connected to local server (`+e+`).
3
+ To use production, run: neocortex activate YOUR-LICENSE-KEY
4
+ Get yours at https://neocortex.sh/portal/login
5
+ `))}function F(r){const e=r.match(/^(https?:\/\/)([^/]+)(.*)$/i);if(!e)return null;const[,c,t,n=""]=e;return t.toLowerCase()!==K?null:`${c}api.neocortex.sh${n}`}function Y(){try{if(!p(s))return null;const r=U(s,"utf-8"),e=JSON.parse(r.replace(/^\uFEFF/,""));if(e.licenseKey&&!e.encryptedLicenseKey){const n=f(e.licenseKey),i={...e},E=i.licenseKey;return delete i.licenseKey,i.encryptedLicenseKey=n,i.configVersion||(i.configVersion=d),v(i),{serverUrl:e.serverUrl,mode:e.mode,machineId:e.machineId,activatedAt:e.activatedAt,tier:e.tier,licenseKey:E,keyType:e.keyType}}let c;if(e.encryptedLicenseKey){const n=C(e.encryptedLicenseKey);n&&(c=n)}const t={serverUrl:e.serverUrl,mode:e.mode,machineId:e.machineId,activatedAt:e.activatedAt,tier:e.tier,licenseKey:c,keyType:e.keyType};if(e.machineId&&!c&&e.encryptedLicenseKey){const n=l();e.machineId!==n&&console.warn(`
6
+ [!] Machine fingerprint changed (was: ${e.machineId.slice(0,12)}..., now: ${n.slice(0,12)}...).
7
+ Your encrypted credentials are no longer valid.
8
+ Re-activate with: neocortex activate YOUR-LICENSE-KEY
9
+ `)}if(_(t),t.serverUrl&&!process.env.NEOCORTEX_SERVER_URL&&/^https?:\/\/(localhost|127\.0\.0\.1|0\.0\.0\.0)(:\d+)?/i.test(t.serverUrl)){const i=x;return console.warn(`[neocortex] Auto-repairing serverUrl: ${t.serverUrl} -> ${i}
10
+ [neocortex] To keep localhost, set NEOCORTEX_SERVER_URL=${t.serverUrl}
11
+ `),{...t,serverUrl:i}}if(t.serverUrl&&!process.env.NEOCORTEX_SERVER_URL){const n=F(t.serverUrl);if(n)return{...t,serverUrl:n}}return t}catch{return null}}function v(r){S(o,{recursive:!0}),m(o);const e=a(o,"cache");p(e)&&m(e),R(s,JSON.stringify(r,null,2)+`
12
+ `,"utf-8"),O(s)}function G(r){const e=f(r.licenseKey),c=r.keyType??(r.licenseKey.startsWith("nxk_")?"api_key":"license"),t={configVersion:d,serverUrl:r.serverUrl,mode:r.mode,machineId:r.machineId,activatedAt:r.activatedAt,tier:r.tier,encryptedLicenseKey:e,keyType:c};v(t)}export{C as decryptLicenseKey,f as encryptLicenseKey,Y as loadSecureConfig,G as saveSecureConfig,m as setSecureDirPermissions,O as setSecureFilePermissions};
@@ -0,0 +1,25 @@
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
+ * Production server URL.
15
+ *
16
+ * Single Source of Truth for the default Neocortex IP Protection Server URL.
17
+ * All client-side code MUST import this constant instead of hardcoding the URL.
18
+ *
19
+ * Shell scripts (install.sh, install.ps1) cannot import from TypeScript,
20
+ * so they maintain a hardcoded copy with a comment referencing this file.
21
+ *
22
+ * Epic 70 - Story 70.03
23
+ * Epic P46 - Story P46.01: migrated legacy API host to api.neocortex.sh
24
+ */
25
+ export declare const DEFAULT_SERVER_URL = "https://api.neocortex.sh";
@@ -0,0 +1 @@
1
+ const t="https://api.neocortex.sh";export{t as DEFAULT_SERVER_URL};
@@ -0,0 +1,28 @@
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
+ import type { PipelineContext } from '../types/index.js';
14
+ /** Options for context collection */
15
+ export interface CollectContextOptions {
16
+ readonly projectRoot: string;
17
+ readonly storyFilePath: string;
18
+ readonly storyId: string;
19
+ readonly stepId: string;
20
+ readonly platformTarget?: string;
21
+ }
22
+ /**
23
+ * Collect complete pipeline context.
24
+ *
25
+ * Reads state.json, package.json, and story file to build
26
+ * a sanitized PipelineContext for the remote server.
27
+ */
28
+ export declare function collectContext(options: CollectContextOptions): Promise<PipelineContext>;
@@ -0,0 +1,2 @@
1
+ import{readFile as i}from"node:fs/promises";import{join as p}from"node:path";import{sanitizeObject as l}from"./context-sanitizer.js";const f=/^---\n([\s\S]*?)\n---/;function m(s){const e=s.match(f);if(!e)return{};const t={};for(const n of e[1].split(`
2
+ `)){const c=n.indexOf(":");if(c===-1)continue;const a=n.slice(0,c).trim().replace(/^['"]|['"]$/g,""),r=n.slice(c+1).trim().replace(/^['"]|['"]$/g,"");t[a]=r}return t}function g(s){const e=[],t=/\*\*AC\d+:?\s*([^*]+)\*\*/g;let n;for(;(n=t.exec(s))!==null;)e.push(n[1].trim());return e}const S={react:"React",next:"Next.js",vue:"Vue",nuxt:"Nuxt",angular:"Angular",svelte:"Svelte",express:"Express",fastify:"Fastify",nest:"NestJS",koa:"Koa",hapi:"Hapi"};function w(s){const e=[];for(const[t,n]of Object.entries(S))t in s&&e.push(n);return e}function y(s){const e=new Set;return e.add("JavaScript"),("typescript"in s||Object.keys(s).some(t=>t.includes("ts-")))&&e.add("TypeScript"),[...e]}async function O(s){const{projectRoot:e,storyFilePath:t,storyId:n,stepId:c,platformTarget:a}=s,r=await h(e,n),u=await C(e),o=await I(t),d={storyId:n,stepId:c,epicId:o.epicId||r.epicId||"",storyTitle:o.title,currentStatus:r.status,stepsCompleted:r.stepsCompleted,branchName:r.branchName,platformTarget:a||x(),codebaseMetadata:u,storyMetadata:o};return l(d,e)}async function h(s,e){try{const t=p(s,".neocortex","state.json"),n=await i(t,"utf-8"),a=JSON.parse(n).stories?.[e];return{status:a?.status||"unknown",stepsCompleted:a?.steps_completed||[],branchName:a?.branch_name||"",epicId:a?.epic_id||""}}catch{return{status:"unknown",stepsCompleted:[],branchName:"",epicId:""}}}async function C(s){try{const e=p(s,"package.json"),t=await i(e,"utf-8"),n=JSON.parse(t),c={...n.dependencies||{},...n.devDependencies||{}};return{projectName:n.name||"unknown",languages:y(c),frameworks:w(c),dependencies:n.dependencies||{},nodeVersion:process.version}}catch{return{projectName:"unknown",languages:["JavaScript"],frameworks:[],dependencies:{},nodeVersion:process.version}}}async function I(s){try{const e=await i(s,"utf-8"),t=m(e),n=g(e);let c=[];const a=t.dependencies;if(a)try{c=JSON.parse(a.replace(/'/g,'"'))}catch{c=a.split(",").map(r=>r.trim().replace(/[[\]"']/g,""))}return{id:t.id||"",epicId:t.epic_id||"",title:t.title||"",status:t.status||t.currentStatus||"",dependencies:c,acceptanceCriteria:n}}catch{return{id:"",epicId:"",title:"",status:"",dependencies:[],acceptanceCriteria:[]}}}function x(){return process.env.CLAUDE_CODE||process.env.CLAUDE_AGENT?"claude-code":process.env.CURSOR_SESSION_ID?"cursor":process.env.VSCODE_PID?"vscode":process.env.GEMINI_CLI?"gemini":"unknown"}export{O as collectContext};
@@ -0,0 +1,28 @@
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
+ * Sanitize a single string value.
15
+ *
16
+ * Applies path sanitization, token removal, and truncation.
17
+ */
18
+ export declare function sanitizeValue(value: string, projectRoot: string): string;
19
+ /**
20
+ * Sanitize a record of key-value pairs.
21
+ *
22
+ * Removes entries with sensitive keys and sanitizes remaining values.
23
+ */
24
+ export declare function sanitizeRecord(record: Record<string, string>, projectRoot: string): Record<string, string>;
25
+ /**
26
+ * Deep sanitize an object, processing all string values recursively.
27
+ */
28
+ export declare function sanitizeObject<T>(obj: T, projectRoot: string): T;
@@ -0,0 +1 @@
1
+ import{homedir as o}from"node:os";const f=[/token/i,/key/i,/secret/i,/password/i,/credential/i,/auth/i,/github_pat_/i,/npm_token/i,/api_key/i],l=[/github_pat_[A-Za-z0-9_]{36,}/g,/ghp_[A-Za-z0-9]{36,}/g,/gho_[A-Za-z0-9]{36,}/g,/sk-[A-Za-z0-9]{32,}/g,/Bearer\s+[A-Za-z0-9._\-]+/g,/-----BEGIN\s+(RSA\s+)?PRIVATE\s+KEY-----[\s\S]*?-----END/g],s=1e3;function p(e,n){let t=e;if(n){const i=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");t=t.replace(new RegExp(i,"g"),".")}const r=o();if(r){const i=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");t=t.replace(new RegExp(i,"g"),"~")}return t}function g(e){let n=e;for(const t of l)n=n.replace(t,"[REDACTED]");return n}function E(e){return e.length<=s?e:`${e.slice(0,s)}...[truncated, ${e.length} chars total]`}function a(e){return f.some(n=>n.test(e))}function c(e,n){let t=p(e,n);return t=g(t),t=E(t),t}function _(e,n){const t={};for(const[r,i]of Object.entries(e))a(r)||(t[r]=c(i,n));return t}function u(e,n){if(e==null)return e;if(typeof e=="string")return c(e,n);if(Array.isArray(e))return e.map(t=>u(t,n));if(typeof e=="object"){const t={};for(const[r,i]of Object.entries(e))a(r)&&typeof i=="string"?t[r]="[REDACTED]":t[r]=u(i,n);return t}return e}export{u as sanitizeObject,_ as sanitizeRecord,c as sanitizeValue};