@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
package/install.js ADDED
@@ -0,0 +1,572 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Neocortex - Cross-Platform Multi-Target Installer
5
+ * Interactive platform selection with @clack/prompts + OS detection + shell dispatch
6
+ */
7
+
8
+ const { spawn } = require('child_process');
9
+ const path = require('path');
10
+ const os = require('os');
11
+ const fs = require('fs');
12
+ const {
13
+ intro, outro, multiselect, confirm, spinner, cancel, isCancel, note, log
14
+ } = require('@clack/prompts');
15
+ const color = require('picocolors');
16
+
17
+ const SCRIPT_DIR = __dirname;
18
+ const args = process.argv.slice(2);
19
+
20
+ // Read version from package.json
21
+ const pkg = JSON.parse(fs.readFileSync(path.join(SCRIPT_DIR, 'package.json'), 'utf8'));
22
+ const VERSION = pkg.version;
23
+
24
+ // ═══════════════════════════════════════════════════════════════════
25
+ // PLATFORM DEFINITIONS
26
+ // ═══════════════════════════════════════════════════════════════════
27
+
28
+ const PLATFORMS = [
29
+ { name: 'Claude Code CLI', key: 'claude-code', tier: 1, default: true, detect: 'claude', label: 'Tier 1 - Full Pipeline' },
30
+ { name: 'Cursor IDE', key: 'cursor', tier: 2, default: false, detect: 'cursor', label: 'Tier 2 - CLI Pipeline' },
31
+ { name: 'VS Code / GitHub Copilot', key: 'vscode', tier: 3, default: false, detect: 'code', label: 'Tier 3 - Agent-Directed' },
32
+ { name: 'Gemini', key: 'gemini', tier: 2, default: false, detect: 'gemini', label: 'Tier 2 - CLI Pipeline' },
33
+ { name: 'Gemini CLI', key: 'gemini-cli', tier: 2, default: false, detect: 'gemini', label: 'Tier 2 - CLI Pipeline' },
34
+ { name: 'OpenAI Codex CLI', key: 'codex', tier: 2, default: false, detect: 'codex', label: 'Tier 2 - CLI Pipeline' },
35
+ { name: 'Google Antigravity', key: 'antigravity', tier: 3, default: false, detect: 'agy', label: 'Tier 3 - Agent-Directed', experimental: true },
36
+ { name: 'OpenCode', key: 'opencode', tier: 2, default: false, detect: 'opencode', label: 'Tier 2 - CLI Pipeline' },
37
+ { name: 'Kimi Code CLI', key: 'kimi', tier: 3, default: false, detect: 'kimi', label: 'Tier 3 - Agent-Directed' },
38
+ { name: 'OpenClaw', key: 'openclaw', tier: 3, default: false, detect: 'openclaw', label: 'Tier 3 - Skill Thin-Client' },
39
+ ];
40
+
41
+ // ═══════════════════════════════════════════════════════════════════
42
+ // PLATFORM DETECTION
43
+ // ═══════════════════════════════════════════════════════════════════
44
+
45
+ function detectPlatform(command) {
46
+ const { execSync } = require('child_process');
47
+ try {
48
+ // Platform-aware detection: `where.exe` on Windows, `which` on Unix
49
+ // `which` does not exist natively on Windows (Epic 63 - Story 63.4)
50
+ if (process.platform === 'win32') {
51
+ // Epic 67 - Story 67.4: Use where.exe /Q (quiet mode) to suppress
52
+ // localized error messages (e.g., "INFO: ..." in non-EN locales).
53
+ // /Q returns only exit code without any stdout/stderr output.
54
+ execSync(`where.exe /Q ${command}`, { stdio: 'pipe' });
55
+ } else {
56
+ execSync(`which ${command} 2>/dev/null`, { stdio: 'pipe' });
57
+ }
58
+ return true;
59
+ } catch {
60
+ return false;
61
+ }
62
+ }
63
+
64
+ function detectInstalledPlatforms() {
65
+ const detected = {};
66
+ for (const p of PLATFORMS) {
67
+ detected[p.key] = detectPlatform(p.detect);
68
+ }
69
+ return detected;
70
+ }
71
+
72
+ // ═══════════════════════════════════════════════════════════════════
73
+ // ARGUMENT HANDLING
74
+ // ═══════════════════════════════════════════════════════════════════
75
+
76
+ function parseTargetsArg() {
77
+ for (const arg of args) {
78
+ if (arg.startsWith('--targets=')) {
79
+ return arg.replace('--targets=', '').split(',').map(t => t.trim()).filter(Boolean);
80
+ }
81
+ }
82
+ return null;
83
+ }
84
+
85
+ function isAutoYes() {
86
+ return args.includes('-y') || args.includes('--yes') || args.includes('-Yes');
87
+ }
88
+
89
+ function isVersion() {
90
+ return args.includes('-v') || args.includes('--version') || args.includes('-V');
91
+ }
92
+
93
+ function isHelp() {
94
+ return args.includes('-h') || args.includes('--help') || args.includes('-Help');
95
+ }
96
+
97
+ function isDebug() {
98
+ return args.includes('-d') || args.includes('--debug') || args.includes('-Debug');
99
+ }
100
+
101
+ /**
102
+ * Declarative flag mapping: Unix CLI flags -> PowerShell parameters.
103
+ * To add a new flag, just add an entry here. No switch/case to update.
104
+ */
105
+ const FLAG_MAP_WIN32 = {
106
+ // Auto-confirm mode
107
+ '-y': '-Yes',
108
+ '--yes': '-Yes',
109
+ // Debug output
110
+ '-d': '-Debug',
111
+ '--debug': '-Debug',
112
+ // Skip project directory creation
113
+ '-s': '-SkipProject',
114
+ '--skip-project': '-SkipProject',
115
+ // Force project directory creation
116
+ '--create-project': '-CreateProject',
117
+ // Suppress non-essential output
118
+ '-q': '-Quiet',
119
+ '--quiet': '-Quiet',
120
+ '--dry-run': '-DryRun',
121
+ // Suppress ASCII banner
122
+ '--no-banner': '-NoBanner',
123
+ // Show help text
124
+ '-h': '-Help',
125
+ '--help': '-Help',
126
+ // Remove legacy artifacts from ~/.claude/
127
+ '--cleanup-legacy': '-CleanupLegacy',
128
+ // --local removed (Epic 50): thin-client mandatory, zero IP on client
129
+ // Server URL override
130
+ // --server-url=<url> is passed through as-is (handled by shell scripts)
131
+ };
132
+
133
+ function mapArgs(platform, originalArgs) {
134
+ const filtered = originalArgs.filter(a => !a.startsWith('--targets='));
135
+ if (platform === 'win32') {
136
+ return filtered.map(arg => FLAG_MAP_WIN32[arg] || arg);
137
+ }
138
+ return filtered;
139
+ }
140
+
141
+ // ═══════════════════════════════════════════════════════════════════
142
+ // SCRIPT EXECUTION
143
+ // ═══════════════════════════════════════════════════════════════════
144
+
145
+ function checkScript(scriptPath) {
146
+ if (!fs.existsSync(scriptPath)) {
147
+ log.error(`Script nao encontrado: ${scriptPath}`);
148
+ process.exit(1);
149
+ }
150
+ }
151
+
152
+ function runWindows(selectedTargets) {
153
+ const scriptPath = path.join(SCRIPT_DIR, 'install.ps1');
154
+ checkScript(scriptPath);
155
+
156
+ const mappedArgs = mapArgs('win32', args);
157
+ if (selectedTargets) {
158
+ mappedArgs.push('-Targets', selectedTargets.join(','));
159
+ }
160
+
161
+ const shells = ['pwsh', 'powershell'];
162
+
163
+ function tryShell(index) {
164
+ if (index >= shells.length) {
165
+ log.error('PowerShell nao encontrado.');
166
+ log.info('Instale o PowerShell Core: https://aka.ms/powershell');
167
+ process.exit(1);
168
+ }
169
+
170
+ const shell = shells[index];
171
+ const psArgs = ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath, ...mappedArgs];
172
+
173
+ const child = spawn(shell, psArgs, { stdio: 'inherit', shell: false });
174
+
175
+ child.on('error', (err) => {
176
+ if (err.code === 'ENOENT') tryShell(index + 1);
177
+ else {
178
+ log.error(`Falha ao executar ${shell}: ${err.message}`);
179
+ process.exit(1);
180
+ }
181
+ });
182
+
183
+ child.on('exit', (code) => process.exit(code || 0));
184
+ }
185
+
186
+ tryShell(0);
187
+ }
188
+
189
+ function runUnix(selectedTargets) {
190
+ const scriptPath = path.join(SCRIPT_DIR, 'install.sh');
191
+ checkScript(scriptPath);
192
+
193
+ try { fs.chmodSync(scriptPath, '755'); } catch { }
194
+
195
+ const filteredArgs = mapArgs('unix', args);
196
+ if (selectedTargets) {
197
+ filteredArgs.push(`--targets=${selectedTargets.join(',')}`);
198
+ }
199
+
200
+ const child = spawn('bash', [scriptPath, ...filteredArgs], { stdio: 'inherit', shell: false });
201
+
202
+ child.on('error', (err) => {
203
+ if (err.code === 'ENOENT') {
204
+ const shChild = spawn('sh', [scriptPath, ...filteredArgs], { stdio: 'inherit', shell: false });
205
+ shChild.on('error', (e) => { log.error(`Shell nao encontrado: ${e.message}`); process.exit(1); });
206
+ shChild.on('exit', (code) => process.exit(code || 0));
207
+ } else {
208
+ log.error(`Falha ao executar instalador: ${err.message}`);
209
+ process.exit(1);
210
+ }
211
+ });
212
+
213
+ child.on('exit', (code) => process.exit(code || 0));
214
+ }
215
+
216
+ // ═══════════════════════════════════════════════════════════════════
217
+ // HELP
218
+ // ═══════════════════════════════════════════════════════════════════
219
+
220
+ function printNoSudoGlobalInstallGuidance() {
221
+ console.error(color.red(' Permission denied while updating Neocortex.'));
222
+ console.error(color.yellow(' Prefer a no-sudo global install path before retrying:'));
223
+ console.error(color.dim(' 1. Use a Node version manager (npm recommended), then run:'));
224
+ console.error(color.cyan(' npm install -g @ornexus/neocortex@latest'));
225
+ console.error(color.dim(' 2. Or on Unix, configure an npm user prefix:'));
226
+ console.error(color.cyan(' npm config set prefix ~/.local'));
227
+ console.error(color.cyan(' export PATH="$HOME/.local/bin:$PATH"'));
228
+ console.error(color.cyan(' npm install -g @ornexus/neocortex@latest'));
229
+ console.error(color.dim(' Avoid starting with elevated installs; root/sudo HOME can target the wrong user config.'));
230
+ console.error(color.dim(' Reason: P177_NOSUDO_EACCES_GUIDANCE'));
231
+ }
232
+
233
+ function showHelp() {
234
+ console.log('');
235
+ console.log(color.bold(` Neocortex Installer v${VERSION}`));
236
+ console.log(color.dim(' Development Orchestrator'));
237
+ console.log('');
238
+ console.log(` ${color.dim('Uso:')} npx @ornexus/neocortex ${color.dim('[opcoes]')}`);
239
+ console.log(` npx @ornexus/neocortex activate ${color.dim('<KEY>')}`);
240
+ console.log('');
241
+ console.log(color.dim(' Comandos:'));
242
+ console.log(` ${color.cyan('activate <KEY>')} Ativar licenca (repara config se necessario)`);
243
+ console.log(` ${color.cyan('invoke --args <args>')} Invocar o server (thin-client)`);
244
+ console.log(` ${color.cyan('refresh-memory')} Reparar NEOCORTEX.md e wrappers/symlinks`);
245
+ console.log(` ${color.cyan('update')} Atualizar para a ultima versao`);
246
+ console.log('');
247
+ console.log(color.dim(' Opcoes:'));
248
+ console.log(` ${color.cyan('-y, --yes')} Modo automatico (Claude Code only)`);
249
+ console.log(` ${color.cyan('--targets=<lista>')} Plataformas separadas por virgula`);
250
+ console.log(` ${color.cyan('--create-project')} Instalar estrutura no projeto`);
251
+ console.log(` ${color.cyan('-s, --skip-project')} Nao perguntar sobre projeto`);
252
+ console.log(` ${color.cyan('-q, --quiet')} Modo silencioso`);
253
+ console.log(` ${color.cyan('--dry-run')} Mostra adapters/stubs resolvidos sem modificar arquivos`);
254
+ console.log(` ${color.cyan('--cleanup-legacy')} Remover artefatos legados de ~/.claude/`);
255
+ console.log(` ${color.dim('--local')} ${color.dim('(Removido) Thin-client obrigatorio')}`);
256
+ console.log(` ${color.cyan('--server-url=<url>')} URL do server Neocortex`);
257
+ console.log(` ${color.cyan('-d, --debug')} Modo debug`);
258
+ console.log(` ${color.cyan('-v, --version')} Mostra a versao instalada`);
259
+ console.log(` ${color.cyan('-h, --help')} Mostra esta ajuda`);
260
+ console.log('');
261
+ console.log(color.dim(' Plataformas:'));
262
+ for (const p of PLATFORMS) {
263
+ const tag = p.experimental ? color.red(' [experimental]') : '';
264
+ console.log(` ${color.cyan(p.key.padEnd(20))} ${p.name} ${color.dim(`(${p.label})`)}${tag}`);
265
+ }
266
+ console.log('');
267
+ console.log(color.dim(' Exemplos:'));
268
+ console.log(` npx @ornexus/neocortex ${color.dim('# Selecao interativa')}`);
269
+ console.log(` npx @ornexus/neocortex --yes ${color.dim('# Claude Code (auto)')}`);
270
+ console.log(` npx @ornexus/neocortex --targets=claude-code,cursor`);
271
+ console.log('');
272
+ console.log(color.dim(' Linux global install:'));
273
+ console.log(` ${color.cyan('npm install -g @ornexus/neocortex')} ${color.dim('# use Node version manager or npm user prefix; avoid sudo-first flows')}`);
274
+ console.log(` ${color.dim('See docs/install/linux-global-install.md for root HOME recovery guidance.')}`);
275
+ console.log('');
276
+ // Epic P72 - Story P72.04: BSL-1.1 license notice in --help output.
277
+ console.log(color.dim(' Licenca: BSL-1.1 (Business Source License 1.1)'));
278
+ console.log('');
279
+ process.exit(0);
280
+ }
281
+
282
+ // ═══════════════════════════════════════════════════════════════════
283
+ // INTERACTIVE WIZARD
284
+ // ═══════════════════════════════════════════════════════════════════
285
+
286
+ async function interactiveWizard() {
287
+ // Detect installed platforms
288
+ const s = spinner();
289
+ s.start('Detectando plataformas instaladas...');
290
+ const detected = detectInstalledPlatforms();
291
+ const detectedNames = PLATFORMS.filter(p => detected[p.key]).map(p => p.name);
292
+ s.stop(
293
+ detectedNames.length > 0
294
+ ? `${detectedNames.length} plataforma(s) detectada(s): ${color.dim(detectedNames.join(', '))}`
295
+ : 'Nenhuma plataforma detectada automaticamente'
296
+ );
297
+
298
+ // Platform selection
299
+ const options = PLATFORMS.map(p => {
300
+ const hints = [];
301
+ if (detected[p.key]) hints.push('detectado');
302
+ if (p.experimental) hints.push('experimental');
303
+ hints.push(p.label);
304
+
305
+ return {
306
+ value: p.key,
307
+ label: p.name,
308
+ hint: hints.join(' | '),
309
+ };
310
+ });
311
+
312
+ const selectedPlatforms = await multiselect({
313
+ message: 'Selecione as plataformas de destino:',
314
+ options,
315
+ initialValues: PLATFORMS.filter(p => p.default).map(p => p.key),
316
+ required: true,
317
+ });
318
+
319
+ if (isCancel(selectedPlatforms)) {
320
+ cancel('Instalacao cancelada.');
321
+ process.exit(0);
322
+ }
323
+
324
+ // Show selection summary
325
+ const selectedNames = selectedPlatforms.map(key => {
326
+ const p = PLATFORMS.find(pl => pl.key === key);
327
+ return p.name;
328
+ });
329
+ log.info(`Plataformas: ${color.bold(selectedNames.join(', '))}`);
330
+
331
+ // Ask about project-level installation
332
+ let createProject = false;
333
+ if (!args.includes('-s') && !args.includes('--skip-project')) {
334
+ const projectInstall = await confirm({
335
+ message: 'Instalar estrutura completa no diretorio atual do projeto?',
336
+ initialValue: false,
337
+ });
338
+
339
+ if (isCancel(projectInstall)) {
340
+ cancel('Instalacao cancelada.');
341
+ process.exit(0);
342
+ }
343
+
344
+ createProject = projectInstall;
345
+ }
346
+
347
+ return { selectedPlatforms, createProject };
348
+ }
349
+
350
+ // ═══════════════════════════════════════════════════════════════════
351
+ // ASCII BANNER
352
+ // ═══════════════════════════════════════════════════════════════════
353
+
354
+ function showAsciiBanner() {
355
+ const c = '\x1b[36m'; // cyan
356
+ const b = '\x1b[1m'; // bold
357
+ const d = '\x1b[2m'; // dim
358
+ const r = '\x1b[0m'; // reset
359
+
360
+ console.log('');
361
+ console.log(`${c} #######${r}`);
362
+ console.log(`${c} ### ########${r}`);
363
+ console.log(`${c} ######### #####${r}`);
364
+ console.log(`${c} ## ############## ${b}N E O C O R T E X${r}`);
365
+ console.log(`${c} ## ### ###### ## ${b}v${VERSION}${r}`);
366
+ console.log(`${c} ## ### ### ##${r}`);
367
+ console.log(`${c} ## ###### ### ## ${d}OrNexus Team${r}`);
368
+ console.log(`${c} ############### ##${r}`);
369
+ console.log(`${c} ##### ########${r}`);
370
+ console.log(`${c} ######## ##${r}`);
371
+ console.log(`${c} #######${r}`);
372
+ console.log('');
373
+ }
374
+
375
+ // ═══════════════════════════════════════════════════════════════════
376
+ // MAIN
377
+ // ═══════════════════════════════════════════════════════════════════
378
+
379
+ async function main() {
380
+ const platform = os.platform();
381
+
382
+ // ── Subcommand delegation (Epic 70 - Story 70.01) ─────────────────
383
+ // Delegate known subcommands to neocortex-client binary.
384
+ // This ensures `neocortex activate KEY` reaches the activate handler
385
+ // instead of running the installation wizard.
386
+ const DELEGATED_COMMANDS = new Set(['activate', 'invoke', 'cache-status', 'refresh-memory']);
387
+ const firstArg = args[0]?.toLowerCase();
388
+ if (firstArg && DELEGATED_COMMANDS.has(firstArg)) {
389
+ // Resolve neocortex-client: prefer sibling in same bin directory (npm shim),
390
+ // fallback to direct path to dist/cli.js within the package.
391
+ const clientBinDirect = path.join(SCRIPT_DIR, 'packages', 'client', 'dist', 'cli.js');
392
+ const child = spawn(process.execPath, [clientBinDirect, ...args], {
393
+ stdio: 'inherit',
394
+ env: process.env,
395
+ });
396
+ child.on('error', (err) => {
397
+ console.error(`Failed to delegate to neocortex-client: ${err.message}`);
398
+ process.exit(1);
399
+ });
400
+ child.on('exit', (code) => process.exit(code ?? 1));
401
+ return; // Do not continue with install wizard
402
+ }
403
+
404
+ // ── Update command (Epic P86 - Story P86.07) ─────────────────────────
405
+ // Handled directly (not delegated to neocortex-client) because update
406
+ // needs npm which is in the installer's scope, not the client's.
407
+ if (firstArg === 'update') {
408
+ const currentVersion = VERSION;
409
+ console.log('');
410
+ console.log(color.cyan(' Neocortex Update'));
411
+ console.log(color.dim(` Current version: v${currentVersion}`));
412
+ console.log('');
413
+ console.log(color.dim(' Updating to latest version...'));
414
+
415
+ const { execSync } = require('child_process');
416
+ try {
417
+ // Run npm install -g silently, capture output
418
+ execSync('npm install -g @ornexus/neocortex@latest', {
419
+ stdio: ['pipe', 'pipe', 'pipe'],
420
+ timeout: 120000, // 2 min timeout
421
+ });
422
+
423
+ // Read new version
424
+ let newVersion = currentVersion;
425
+ try {
426
+ const newPkg = JSON.parse(fs.readFileSync(path.join(SCRIPT_DIR, 'package.json'), 'utf8'));
427
+ newVersion = newPkg.version;
428
+ } catch {
429
+ // Fallback: query npm for installed version
430
+ try {
431
+ const lsOutput = execSync('npm ls -g @ornexus/neocortex --depth=0 --json 2>/dev/null', {
432
+ encoding: 'utf-8', timeout: 10000,
433
+ });
434
+ const match = lsOutput.match(/"version":\s*"([^"]+)"/);
435
+ if (match) newVersion = match[1];
436
+ } catch { /* keep currentVersion */ }
437
+ }
438
+
439
+ if (newVersion === currentVersion) {
440
+ console.log(color.green(` Already at latest version: v${currentVersion}`));
441
+ } else {
442
+ console.log(color.green(` Updated: v${currentVersion} -> v${newVersion}`));
443
+ }
444
+ console.log('');
445
+ } catch (err) {
446
+ const msg = (err.stderr && err.stderr.toString()) || err.message || '';
447
+ if (msg.includes('EACCES') || msg.includes('permission denied')) {
448
+ printNoSudoGlobalInstallGuidance();
449
+ } else if (msg.includes('ENETUNREACH') || msg.includes('ENOTFOUND') || msg.includes('fetch failed')) {
450
+ console.error(color.red(' Network error. Check your internet connection and try again.'));
451
+ } else {
452
+ console.error(color.red(` Update failed: ${msg.split('\n')[0]}`));
453
+ }
454
+ console.error('');
455
+ process.exit(1);
456
+ }
457
+ process.exit(0);
458
+ }
459
+
460
+ // Version flag -- print just the version number and exit (for scripting)
461
+ // Epic P72 - Story P72.04: include BSL-1.1 license notice.
462
+ if (isVersion()) {
463
+ console.log(VERSION);
464
+ console.log('Licensed under BSL-1.1 (Business Source License 1.1)');
465
+ return;
466
+ }
467
+
468
+ // Debug info
469
+ if (isDebug()) {
470
+ console.log(color.dim(` [debug] Platform: ${platform} | Node: ${process.version} | Dir: ${SCRIPT_DIR}`));
471
+ console.log(color.dim(` [debug] Args: ${args.join(' ') || '(none)'}`));
472
+ console.log('');
473
+ }
474
+
475
+ // Help
476
+ if (isHelp()) {
477
+ showHelp();
478
+ return;
479
+ }
480
+
481
+ // Determine selected targets
482
+ let selectedTargets = null;
483
+ let createProject = false;
484
+
485
+ // Priority 1: --targets= argument
486
+ const targetsArg = parseTargetsArg();
487
+ if (targetsArg) {
488
+ const validKeys = PLATFORMS.map(p => p.key);
489
+ const invalid = targetsArg.filter(t => !validKeys.includes(t));
490
+ if (invalid.length > 0) {
491
+ console.log('');
492
+ log.error(`Plataformas invalidas: ${color.bold(invalid.join(', '))}`);
493
+ log.info(`Validas: ${validKeys.join(', ')}`);
494
+ process.exit(1);
495
+ }
496
+ selectedTargets = targetsArg;
497
+
498
+ // In non-interactive mode with explicit targets, still check for project flag
499
+ if (args.includes('--create-project')) createProject = true;
500
+ }
501
+ // Priority 2: --yes flag = Claude Code only (backward compat)
502
+ else if (isAutoYes()) {
503
+ selectedTargets = ['claude-code'];
504
+ createProject = true;
505
+ }
506
+ // Priority 3: Interactive selection (if TTY)
507
+ else if (process.stdin.isTTY && process.stdout.isTTY) {
508
+ showAsciiBanner();
509
+ intro(color.bgWhite(color.black(` Neocortex v${VERSION} `)));
510
+
511
+ const result = await interactiveWizard();
512
+ selectedTargets = result.selectedPlatforms;
513
+ createProject = result.createProject;
514
+
515
+ if (selectedTargets.length === 0) {
516
+ cancel('Nenhuma plataforma selecionada.');
517
+ process.exit(0);
518
+ }
519
+ }
520
+ // Priority 4: Non-interactive, no flags = Claude Code only
521
+ else {
522
+ selectedTargets = ['claude-code'];
523
+ }
524
+
525
+ // ── Thin-Client Mode (Epic 50) ─────────────────────────────────
526
+ // ALL installations are thin-client. Zero IP on client, always.
527
+ const configPath = path.join(os.homedir(), '.neocortex', 'config.json');
528
+ const hasConfig = fs.existsSync(configPath);
529
+
530
+ if (!hasConfig) {
531
+ // Not activated yet - show activation instructions
532
+ log.info('');
533
+ log.info(color.cyan('Thin-Client Mode'));
534
+ log.info(color.dim('All content is served by the Neocortex remote server.'));
535
+ log.info('');
536
+ log.info(color.yellow('To activate your license:'));
537
+ log.info(color.bold(' neocortex activate NX-PRO-xxx'));
538
+ log.info('');
539
+ } else {
540
+ try {
541
+ // Strip UTF-8 BOM if present (PowerShell 5.1 writes BOM via Out-File -Encoding utf8)
542
+ // Defense in depth: handles configs written by old PS 5.1 installers (Epic 63 - Story 63.1)
543
+ const cfg = JSON.parse(fs.readFileSync(configPath, 'utf-8').replace(/^\uFEFF/, ''));
544
+ if (cfg.mode === 'remote') {
545
+ log.info(color.dim(`Remote mode active (server: ${cfg.serverUrl || 'default'})`));
546
+ }
547
+ } catch { /* ignore corrupted config */ }
548
+ }
549
+
550
+ // Dispatch to platform-specific installer
551
+ if (createProject) {
552
+ args.push('--create-project');
553
+ } else if (!args.includes('-s') && !args.includes('--skip-project')) {
554
+ args.push('--skip-project');
555
+ }
556
+
557
+ // Suppress shell banner when JS wizard already showed it (avoid duplicate)
558
+ if (process.stdin.isTTY && process.stdout.isTTY && !args.includes('-q') && !args.includes('--quiet')) {
559
+ args.push('--no-banner');
560
+ }
561
+
562
+ if (platform === 'win32') {
563
+ runWindows(selectedTargets);
564
+ } else {
565
+ runUnix(selectedTargets);
566
+ }
567
+ }
568
+
569
+ main().catch(err => {
570
+ log.error(err.message);
571
+ process.exit(1);
572
+ });