@ornexus/neocortex 4.0.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.
Potentially problematic release.
This version of @ornexus/neocortex might be problematic. Click here for more details.
- package/LICENSE +56 -0
- package/README.md +32 -0
- package/install.js +486 -0
- package/install.ps1 +1790 -0
- package/install.sh +1587 -0
- package/package.json +104 -0
- package/packages/client/dist/adapters/adapter-registry.d.ts +61 -0
- package/packages/client/dist/adapters/adapter-registry.js +106 -0
- package/packages/client/dist/adapters/antigravity-adapter.d.ts +18 -0
- package/packages/client/dist/adapters/antigravity-adapter.js +77 -0
- package/packages/client/dist/adapters/claude-code-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/claude-code-adapter.js +79 -0
- package/packages/client/dist/adapters/codex-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/codex-adapter.js +80 -0
- package/packages/client/dist/adapters/cursor-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/cursor-adapter.js +115 -0
- package/packages/client/dist/adapters/gemini-adapter.d.ts +18 -0
- package/packages/client/dist/adapters/gemini-adapter.js +71 -0
- package/packages/client/dist/adapters/index.d.ts +19 -0
- package/packages/client/dist/adapters/index.js +21 -0
- package/packages/client/dist/adapters/platform-detector.d.ts +46 -0
- package/packages/client/dist/adapters/platform-detector.js +106 -0
- package/packages/client/dist/adapters/target-adapter.d.ts +70 -0
- package/packages/client/dist/adapters/target-adapter.js +12 -0
- package/packages/client/dist/adapters/vscode-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/vscode-adapter.js +72 -0
- package/packages/client/dist/agent/refresh-stubs.d.ts +65 -0
- package/packages/client/dist/agent/refresh-stubs.js +234 -0
- package/packages/client/dist/agent/update-agent-yaml.d.ts +26 -0
- package/packages/client/dist/agent/update-agent-yaml.js +102 -0
- package/packages/client/dist/agent/update-description.d.ts +45 -0
- package/packages/client/dist/agent/update-description.js +251 -0
- package/packages/client/dist/cache/crypto-utils.d.ts +30 -0
- package/packages/client/dist/cache/crypto-utils.js +76 -0
- package/packages/client/dist/cache/encrypted-cache.d.ts +30 -0
- package/packages/client/dist/cache/encrypted-cache.js +94 -0
- package/packages/client/dist/cache/in-memory-asset-cache.d.ts +59 -0
- package/packages/client/dist/cache/in-memory-asset-cache.js +70 -0
- package/packages/client/dist/cache/index.d.ts +13 -0
- package/packages/client/dist/cache/index.js +13 -0
- package/packages/client/dist/cli.d.ts +14 -0
- package/packages/client/dist/cli.js +194 -0
- package/packages/client/dist/commands/activate.d.ts +55 -0
- package/packages/client/dist/commands/activate.js +390 -0
- package/packages/client/dist/commands/cache-status.d.ts +39 -0
- package/packages/client/dist/commands/cache-status.js +112 -0
- package/packages/client/dist/commands/invoke.d.ts +70 -0
- package/packages/client/dist/commands/invoke.js +490 -0
- package/packages/client/dist/config/resolver-selection.d.ts +40 -0
- package/packages/client/dist/config/resolver-selection.js +278 -0
- package/packages/client/dist/config/secure-config.d.ts +78 -0
- package/packages/client/dist/config/secure-config.js +269 -0
- package/packages/client/dist/constants.d.ts +25 -0
- package/packages/client/dist/constants.js +25 -0
- package/packages/client/dist/context/context-collector.d.ts +28 -0
- package/packages/client/dist/context/context-collector.js +222 -0
- package/packages/client/dist/context/context-sanitizer.d.ts +28 -0
- package/packages/client/dist/context/context-sanitizer.js +145 -0
- package/packages/client/dist/index.d.ts +55 -0
- package/packages/client/dist/index.js +38 -0
- package/packages/client/dist/license/index.d.ts +5 -0
- package/packages/client/dist/license/index.js +5 -0
- package/packages/client/dist/license/license-client.d.ts +79 -0
- package/packages/client/dist/license/license-client.js +257 -0
- package/packages/client/dist/machine/fingerprint.d.ts +34 -0
- package/packages/client/dist/machine/fingerprint.js +160 -0
- package/packages/client/dist/machine/index.d.ts +5 -0
- package/packages/client/dist/machine/index.js +5 -0
- package/packages/client/dist/resilience/circuit-breaker.d.ts +70 -0
- package/packages/client/dist/resilience/circuit-breaker.js +170 -0
- package/packages/client/dist/resilience/degradation-manager.d.ts +67 -0
- package/packages/client/dist/resilience/degradation-manager.js +164 -0
- package/packages/client/dist/resilience/freshness-indicator.d.ts +59 -0
- package/packages/client/dist/resilience/freshness-indicator.js +100 -0
- package/packages/client/dist/resilience/index.d.ts +8 -0
- package/packages/client/dist/resilience/index.js +8 -0
- package/packages/client/dist/resilience/recovery-detector.d.ts +59 -0
- package/packages/client/dist/resilience/recovery-detector.js +74 -0
- package/packages/client/dist/resolvers/asset-resolver.d.ts +79 -0
- package/packages/client/dist/resolvers/asset-resolver.js +13 -0
- package/packages/client/dist/resolvers/local-resolver.d.ts +26 -0
- package/packages/client/dist/resolvers/local-resolver.js +218 -0
- package/packages/client/dist/resolvers/remote-resolver.d.ts +91 -0
- package/packages/client/dist/resolvers/remote-resolver.js +282 -0
- package/packages/client/dist/telemetry/index.d.ts +5 -0
- package/packages/client/dist/telemetry/index.js +5 -0
- package/packages/client/dist/telemetry/offline-queue.d.ts +57 -0
- package/packages/client/dist/telemetry/offline-queue.js +131 -0
- package/packages/client/dist/tier/index.d.ts +5 -0
- package/packages/client/dist/tier/index.js +5 -0
- package/packages/client/dist/tier/tier-aware-client.d.ts +97 -0
- package/packages/client/dist/tier/tier-aware-client.js +260 -0
- package/packages/client/dist/types/index.d.ts +140 -0
- package/packages/client/dist/types/index.js +38 -0
- package/postinstall.js +272 -0
- package/targets-stubs/antigravity/README.md +36 -0
- package/targets-stubs/antigravity/gemini.md +22 -0
- package/targets-stubs/antigravity/install-antigravity.sh +44 -0
- package/targets-stubs/antigravity/mcp-config.json +9 -0
- package/targets-stubs/antigravity/skill/SKILL.md +67 -0
- package/targets-stubs/claude-code/README.md +20 -0
- package/targets-stubs/claude-code/neocortex.agent.yaml +24 -0
- package/targets-stubs/claude-code/neocortex.md +125 -0
- package/targets-stubs/codex/README.md +32 -0
- package/targets-stubs/codex/agents.md +61 -0
- package/targets-stubs/codex/config-mcp.toml +6 -0
- package/targets-stubs/codex/install-codex.sh +61 -0
- package/targets-stubs/cursor/README.md +33 -0
- package/targets-stubs/cursor/agent.md +94 -0
- package/targets-stubs/cursor/install-cursor.sh +35 -0
- package/targets-stubs/cursor/mcp.json +11 -0
- package/targets-stubs/gemini-cli/README.md +34 -0
- package/targets-stubs/gemini-cli/agent.md +101 -0
- package/targets-stubs/gemini-cli/gemini.md +16 -0
- package/targets-stubs/gemini-cli/install-gemini.sh +56 -0
- package/targets-stubs/gemini-cli/settings-mcp.json +11 -0
- package/targets-stubs/vscode/README.md +34 -0
- package/targets-stubs/vscode/agent.md +102 -0
- package/targets-stubs/vscode/copilot-instructions.md +16 -0
- package/targets-stubs/vscode/install-vscode.sh +42 -0
- package/targets-stubs/vscode/mcp.json +13 -0
package/install.ps1
ADDED
|
@@ -0,0 +1,1790 @@
|
|
|
1
|
+
# Neocortex - Instalador Windows
|
|
2
|
+
# Development Orchestrator
|
|
3
|
+
|
|
4
|
+
param(
|
|
5
|
+
[switch]$Yes,
|
|
6
|
+
[switch]$Debug,
|
|
7
|
+
[switch]$SkipProject,
|
|
8
|
+
[switch]$CreateProject,
|
|
9
|
+
[switch]$Quiet,
|
|
10
|
+
[switch]$NoBanner,
|
|
11
|
+
[switch]$CleanupLegacy,
|
|
12
|
+
[switch]$Local,
|
|
13
|
+
[switch]$Help,
|
|
14
|
+
[string]$Targets = "",
|
|
15
|
+
# SSoT: packages/client/src/constants.ts DEFAULT_SERVER_URL
|
|
16
|
+
[string]$ServerUrl = "https://api.neocortex.sh"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
$VERSION = "4.0.1"
|
|
20
|
+
|
|
21
|
+
# =============================================================================
|
|
22
|
+
# CONFIGURACOES
|
|
23
|
+
# =============================================================================
|
|
24
|
+
|
|
25
|
+
$ErrorActionPreference = "Continue"
|
|
26
|
+
$script:Errors = 0
|
|
27
|
+
$script:MigrationDetected = $false
|
|
28
|
+
$script:MigrationSources = @()
|
|
29
|
+
$script:LegacyItems = @()
|
|
30
|
+
$script:LegacyWarnings = 0
|
|
31
|
+
|
|
32
|
+
$AUTO_YES = $Yes
|
|
33
|
+
$DEBUG_MODE = $Debug
|
|
34
|
+
$SKIP_PROJECT_DIRS = $SkipProject
|
|
35
|
+
$QUIET_MODE = $Quiet
|
|
36
|
+
$NO_BANNER = $NoBanner
|
|
37
|
+
# LOCAL_MODE removed (Epic 50): thin-client ALWAYS, zero IP on client
|
|
38
|
+
$LOCAL_MODE = $false
|
|
39
|
+
$NEOCORTEX_SERVER_URL = $ServerUrl
|
|
40
|
+
|
|
41
|
+
function Test-Interactive {
|
|
42
|
+
try {
|
|
43
|
+
if (-not [Environment]::UserInteractive) { return $false }
|
|
44
|
+
if ($null -eq $Host.UI -or $null -eq $Host.UI.RawUI) { return $false }
|
|
45
|
+
return $true
|
|
46
|
+
} catch { return $false }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (-not (Test-Interactive)) {
|
|
50
|
+
$AUTO_YES = $true
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
# =============================================================================
|
|
54
|
+
# AJUDA
|
|
55
|
+
# =============================================================================
|
|
56
|
+
|
|
57
|
+
if ($Help) {
|
|
58
|
+
Write-Host ""
|
|
59
|
+
Write-Host " Neocortex Installer v$VERSION" -ForegroundColor White
|
|
60
|
+
Write-Host " Development Orchestrator" -ForegroundColor DarkGray
|
|
61
|
+
Write-Host ""
|
|
62
|
+
Write-Host " Uso: npx @ornexus/neocortex [opcoes]"
|
|
63
|
+
Write-Host ""
|
|
64
|
+
Write-Host " Opcoes:" -ForegroundColor DarkGray
|
|
65
|
+
Write-Host " -Yes Modo automatico (Claude Code only)" -ForegroundColor Cyan
|
|
66
|
+
Write-Host " -Targets <lista> Plataformas separadas por virgula" -ForegroundColor Cyan
|
|
67
|
+
Write-Host " -CreateProject Instalar estrutura no projeto" -ForegroundColor Cyan
|
|
68
|
+
Write-Host " -SkipProject Nao perguntar sobre projeto" -ForegroundColor Cyan
|
|
69
|
+
Write-Host " -Quiet Modo silencioso" -ForegroundColor Cyan
|
|
70
|
+
Write-Host " -CleanupLegacy (Redundante) Limpeza agora e automatica" -ForegroundColor Cyan
|
|
71
|
+
Write-Host " -Local (Removido) Thin-client obrigatorio, zero IP no client" -ForegroundColor DarkGray
|
|
72
|
+
Write-Host " -ServerUrl <url> URL do server Neocortex" -ForegroundColor Cyan
|
|
73
|
+
Write-Host " -Debug Modo debug" -ForegroundColor Cyan
|
|
74
|
+
Write-Host " -Help Mostra esta ajuda" -ForegroundColor Cyan
|
|
75
|
+
Write-Host ""
|
|
76
|
+
Write-Host " Plataformas: claude-code, cursor, vscode, gemini-cli, codex, antigravity" -ForegroundColor DarkGray
|
|
77
|
+
exit 0
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# =============================================================================
|
|
81
|
+
# FUNCOES DE LOG
|
|
82
|
+
# =============================================================================
|
|
83
|
+
|
|
84
|
+
function Write-Step {
|
|
85
|
+
param([int]$Num, [int]$Total, [string]$Message)
|
|
86
|
+
Write-Host ""
|
|
87
|
+
Write-Host " [$Num/$Total] " -ForegroundColor Cyan -NoNewline
|
|
88
|
+
Write-Host $Message -ForegroundColor White
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function Write-Ok {
|
|
92
|
+
param([string]$Message)
|
|
93
|
+
if (-not $QUIET_MODE) {
|
|
94
|
+
Write-Host " " -NoNewline
|
|
95
|
+
Write-Host "[ok]" -ForegroundColor Green -NoNewline
|
|
96
|
+
Write-Host " $Message"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function Write-Warn {
|
|
101
|
+
param([string]$Message)
|
|
102
|
+
Write-Host " " -NoNewline
|
|
103
|
+
Write-Host "[!]" -ForegroundColor Yellow -NoNewline
|
|
104
|
+
Write-Host " $Message"
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function Write-Fail {
|
|
108
|
+
param([string]$Message)
|
|
109
|
+
Write-Host " " -NoNewline
|
|
110
|
+
Write-Host "[x]" -ForegroundColor Red -NoNewline
|
|
111
|
+
Write-Host " $Message"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function Write-Info {
|
|
115
|
+
param([string]$Message)
|
|
116
|
+
if (-not $QUIET_MODE) {
|
|
117
|
+
Write-Host " -> " -ForegroundColor DarkGray -NoNewline
|
|
118
|
+
Write-Host $Message -ForegroundColor DarkGray
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function Write-Dbg {
|
|
123
|
+
param([string]$Message)
|
|
124
|
+
if ($DEBUG_MODE) {
|
|
125
|
+
Write-Host " [debug] $Message" -ForegroundColor DarkGray
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# =============================================================================
|
|
130
|
+
# UTF-8 BOM-FREE WRITE HELPER (Epic 63 - Story 63.1)
|
|
131
|
+
# PowerShell 5.1 writes UTF-8 WITH BOM via Out-File -Encoding utf8 and
|
|
132
|
+
# Set-Content -Encoding utf8. Node.js JSON.parse fails on BOM prefix.
|
|
133
|
+
# This helper uses .NET API to write UTF-8 WITHOUT BOM, compatible with
|
|
134
|
+
# both PowerShell 5.1 and 7+.
|
|
135
|
+
# =============================================================================
|
|
136
|
+
|
|
137
|
+
function Write-Utf8NoBom {
|
|
138
|
+
param(
|
|
139
|
+
[string]$Path,
|
|
140
|
+
[string]$Content
|
|
141
|
+
)
|
|
142
|
+
$utf8NoBom = [System.Text.UTF8Encoding]::new($false)
|
|
143
|
+
[System.IO.File]::WriteAllText($Path, $Content, $utf8NoBom)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# =============================================================================
|
|
147
|
+
# ACL HELPERS (Story 66.1 - Windows file permission hardening)
|
|
148
|
+
# Fail-open: never throws, never blocks installation
|
|
149
|
+
# =============================================================================
|
|
150
|
+
|
|
151
|
+
function Set-FileAcl {
|
|
152
|
+
param([string]$Path)
|
|
153
|
+
try {
|
|
154
|
+
$username = $env:USERNAME
|
|
155
|
+
if (-not $username) { return }
|
|
156
|
+
& icacls $Path /inheritance:r /grant:r "${username}:(F)" 2>$null | Out-Null
|
|
157
|
+
} catch { }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function Set-DirAcl {
|
|
161
|
+
param([string]$Path)
|
|
162
|
+
try {
|
|
163
|
+
$username = $env:USERNAME
|
|
164
|
+
if (-not $username) { return }
|
|
165
|
+
& icacls $Path /inheritance:r /grant:r "${username}:(OI)(CI)(F)" 2>$null | Out-Null
|
|
166
|
+
} catch { }
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function Read-HostWithTimeout {
|
|
170
|
+
param([int]$TimeoutSeconds = 10, [string]$Default = "n")
|
|
171
|
+
try {
|
|
172
|
+
if (-not (Test-Interactive)) { return $Default }
|
|
173
|
+
$endTime = [DateTime]::Now.AddSeconds($TimeoutSeconds)
|
|
174
|
+
while (-not $Host.UI.RawUI.KeyAvailable) {
|
|
175
|
+
if ([DateTime]::Now -ge $endTime) {
|
|
176
|
+
Write-Host ""
|
|
177
|
+
return $Default
|
|
178
|
+
}
|
|
179
|
+
Start-Sleep -Milliseconds 100
|
|
180
|
+
}
|
|
181
|
+
return Read-Host
|
|
182
|
+
} catch { return $Default }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
# =============================================================================
|
|
186
|
+
# BANNER
|
|
187
|
+
# =============================================================================
|
|
188
|
+
|
|
189
|
+
function Show-Banner {
|
|
190
|
+
if ($QUIET_MODE) { return }
|
|
191
|
+
if ($NO_BANNER) { return }
|
|
192
|
+
|
|
193
|
+
Write-Host ""
|
|
194
|
+
Write-Host " #######" -ForegroundColor Cyan
|
|
195
|
+
Write-Host " ### ########" -ForegroundColor Cyan
|
|
196
|
+
Write-Host " ######### #####" -ForegroundColor Cyan
|
|
197
|
+
Write-Host -NoNewline " ## ############## " -ForegroundColor Cyan
|
|
198
|
+
Write-Host "N E O C O R T E X" -ForegroundColor White
|
|
199
|
+
Write-Host -NoNewline " ## ### ###### ## " -ForegroundColor Cyan
|
|
200
|
+
Write-Host "v$VERSION" -ForegroundColor White
|
|
201
|
+
Write-Host " ## ### ### ##" -ForegroundColor Cyan
|
|
202
|
+
Write-Host -NoNewline " ## ###### ### ## " -ForegroundColor Cyan
|
|
203
|
+
Write-Host "OrNexus Team" -ForegroundColor DarkGray
|
|
204
|
+
Write-Host " ############### ##" -ForegroundColor Cyan
|
|
205
|
+
Write-Host " ##### ########" -ForegroundColor Cyan
|
|
206
|
+
Write-Host " ######## ##" -ForegroundColor Cyan
|
|
207
|
+
Write-Host " #######" -ForegroundColor Cyan
|
|
208
|
+
Write-Host ""
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
# =============================================================================
|
|
212
|
+
# FUNCOES DE COPIA (silenciosas)
|
|
213
|
+
# =============================================================================
|
|
214
|
+
|
|
215
|
+
function Copy-Silent {
|
|
216
|
+
param([string]$Source, [string]$Destination)
|
|
217
|
+
Write-Dbg "Copiando: $Source -> $Destination"
|
|
218
|
+
if (Test-Path $Source -PathType Leaf) {
|
|
219
|
+
try {
|
|
220
|
+
# Epic 65: -ErrorAction Stop converts non-terminating errors to terminating
|
|
221
|
+
# Without this, Copy-Item on Windows silently fails and try/catch never triggers
|
|
222
|
+
Copy-Item -Path $Source -Destination $Destination -Force -ErrorAction Stop
|
|
223
|
+
# Post-copy verification: confirm file arrived at destination
|
|
224
|
+
$destFile = if ($Destination.EndsWith('\') -or $Destination.EndsWith('/') -or (Test-Path $Destination -PathType Container)) {
|
|
225
|
+
Join-Path $Destination (Split-Path $Source -Leaf)
|
|
226
|
+
} else { $Destination }
|
|
227
|
+
if (-not (Test-Path $destFile -PathType Leaf)) {
|
|
228
|
+
Write-Dbg "Copy-Item retornou OK mas arquivo nao existe no destino: $destFile"
|
|
229
|
+
$script:Errors++
|
|
230
|
+
return $false
|
|
231
|
+
}
|
|
232
|
+
return $true
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
Write-Dbg "Copy-Item falhou: $_"
|
|
236
|
+
$script:Errors++
|
|
237
|
+
return $false
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
Write-Dbg "Arquivo nao encontrado: $Source"
|
|
241
|
+
$script:Errors++
|
|
242
|
+
return $false
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function Copy-DirSilent {
|
|
246
|
+
param([string]$Source, [string]$Destination)
|
|
247
|
+
Write-Dbg "Copiando dir: $Source -> $Destination"
|
|
248
|
+
if (Test-Path $Source -PathType Container) {
|
|
249
|
+
try {
|
|
250
|
+
Copy-Item -Path $Source -Destination $Destination -Recurse -Force -ErrorAction Stop
|
|
251
|
+
return $true
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
Write-Dbg "Copy-Item dir falhou: $_"
|
|
255
|
+
return $false
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return $false
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
# =============================================================================
|
|
262
|
+
# DETECCAO DO DIRETORIO FONTE
|
|
263
|
+
# =============================================================================
|
|
264
|
+
|
|
265
|
+
function Get-SourceDirectory {
|
|
266
|
+
if ($PSScriptRoot) {
|
|
267
|
+
$script:SourceDir = $PSScriptRoot
|
|
268
|
+
} else {
|
|
269
|
+
$script:SourceDir = Get-Location
|
|
270
|
+
}
|
|
271
|
+
Write-Dbg "Source: $script:SourceDir"
|
|
272
|
+
|
|
273
|
+
if (-not (Test-Path "$script:SourceDir\targets-stubs\claude-code\neocortex.md") -and
|
|
274
|
+
-not (Test-Path "$script:SourceDir\targets\claude-code\neocortex.md") -and
|
|
275
|
+
-not (Test-Path "$script:SourceDir\neocortex.md")) {
|
|
276
|
+
Write-Dbg "Stubs nao encontrados em PSScriptRoot, buscando em paths alternativos..."
|
|
277
|
+
$possibleDirs = @(
|
|
278
|
+
$script:SourceDir,
|
|
279
|
+
# Scoped paths (primary) -- npm publishes as @ornexus/neocortex
|
|
280
|
+
"$env:APPDATA\npm\node_modules\@ornexus\neocortex",
|
|
281
|
+
"$env:LOCALAPPDATA\npm-cache\_npx\*\node_modules\@ornexus\neocortex",
|
|
282
|
+
".\node_modules\@ornexus\neocortex",
|
|
283
|
+
# Unscoped paths (fallback for backward compat)
|
|
284
|
+
"$env:APPDATA\npm\node_modules\neocortex",
|
|
285
|
+
"$env:LOCALAPPDATA\npm-cache\_npx\*\node_modules\neocortex",
|
|
286
|
+
".\node_modules\neocortex"
|
|
287
|
+
)
|
|
288
|
+
$script:SourceFound = $false
|
|
289
|
+
foreach ($dir in $possibleDirs) {
|
|
290
|
+
# Epic 64 (Story 64.6): Debug each possibleDir tested
|
|
291
|
+
Write-Dbg "Get-SourceDirectory: testing $dir"
|
|
292
|
+
$expandedDirs = Get-Item $dir -ErrorAction SilentlyContinue
|
|
293
|
+
foreach ($expanded in $expandedDirs) {
|
|
294
|
+
$found = (Test-Path "$($expanded.FullName)\targets-stubs\claude-code\neocortex.md") -or
|
|
295
|
+
(Test-Path "$($expanded.FullName)\targets\claude-code\neocortex.md") -or
|
|
296
|
+
(Test-Path "$($expanded.FullName)\neocortex.md")
|
|
297
|
+
Write-Dbg "Get-SourceDirectory: $($expanded.FullName) found=$found"
|
|
298
|
+
if ($found) {
|
|
299
|
+
$script:SourceDir = $expanded.FullName
|
|
300
|
+
$script:SourceFound = $true
|
|
301
|
+
break
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if ($script:SourceFound) { break }
|
|
305
|
+
}
|
|
306
|
+
# Epic 65: Emit visible warning when stubs cannot be found anywhere
|
|
307
|
+
if (-not $script:SourceFound) {
|
|
308
|
+
Write-Warn "Arquivos de instalacao (stubs) nao encontrados em nenhum path conhecido"
|
|
309
|
+
Write-Warn "PSScriptRoot: $PSScriptRoot"
|
|
310
|
+
Write-Warn "Tente reinstalar: npm install -g @ornexus/neocortex"
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
# =============================================================================
|
|
316
|
+
# DETECCAO DE VERSAO ANTIGA
|
|
317
|
+
# =============================================================================
|
|
318
|
+
|
|
319
|
+
function Test-OldInstallation {
|
|
320
|
+
Write-Dbg "Verificando instalacoes antigas..."
|
|
321
|
+
$destDir = "$env:USERPROFILE\.claude\agents\neocortex"
|
|
322
|
+
|
|
323
|
+
$versionFile = "$destDir\.version"
|
|
324
|
+
if (Test-Path $versionFile) {
|
|
325
|
+
$installedVersion = (Get-Content $versionFile -Raw).Trim()
|
|
326
|
+
$pkgJsonPath = Join-Path $script:SourceDir "package.json"
|
|
327
|
+
if (Test-Path $pkgJsonPath) {
|
|
328
|
+
$pkgJson = Get-Content $pkgJsonPath -Raw | ConvertFrom-Json -ErrorAction SilentlyContinue
|
|
329
|
+
if ($pkgJson.version) {
|
|
330
|
+
if ($installedVersion -eq $pkgJson.version) {
|
|
331
|
+
Write-Info "Reinstalando v$($pkgJson.version)"
|
|
332
|
+
} else {
|
|
333
|
+
Write-Info "Atualizando v$installedVersion -> v$($pkgJson.version)"
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function Test-ProjectMigrationNeeds {
|
|
341
|
+
$sources = @()
|
|
342
|
+
if (Test-Path ".neocortex\orchestrator.db") { $sources += "orchestrator.db" }
|
|
343
|
+
@("bmad-output\sprint-status.yaml", ".neocortex\sprint-status.yaml", "docs\sprint-status.yaml") | ForEach-Object {
|
|
344
|
+
if (Test-Path $_) { $sources += $_ }
|
|
345
|
+
}
|
|
346
|
+
if ($sources.Count -gt 0) { return $sources }
|
|
347
|
+
return $null
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
# =============================================================================
|
|
351
|
+
# LIMPEZA AUTOMATICA DE ARTEFATOS LEGADOS (Invoke-AutoCleanupLegacy)
|
|
352
|
+
# Unifica: Test-LegacyArtifacts + Invoke-CleanupLegacy + Remove-LegacyIP
|
|
353
|
+
# + Remove-LegacyIPProject + npm globals + cross-platform cleanup
|
|
354
|
+
# Roda AUTOMATICAMENTE a cada instalacao - sem necessidade de -CleanupLegacy
|
|
355
|
+
# Idempotente: rodar multiplas vezes sem efeitos colaterais
|
|
356
|
+
# Seguro: NAO remove dados do usuario (stories, epics, state.json, config.json)
|
|
357
|
+
# =============================================================================
|
|
358
|
+
|
|
359
|
+
function Invoke-AutoCleanupLegacy {
|
|
360
|
+
$removed = 0
|
|
361
|
+
$claudeDir = "$env:USERPROFILE\.claude"
|
|
362
|
+
$neocortexDir = "$claudeDir\agents\neocortex"
|
|
363
|
+
$skillsDir = "$claudeDir\skills\neocortex"
|
|
364
|
+
|
|
365
|
+
Write-Dbg "Executando limpeza automatica de artefatos legados..."
|
|
366
|
+
|
|
367
|
+
# --- Helper: remove e loga ---
|
|
368
|
+
function Remove-LegacyItem {
|
|
369
|
+
param([string]$Target, [string]$Label)
|
|
370
|
+
if (Test-Path $Target) {
|
|
371
|
+
$displayItem = $Target -replace [regex]::Escape($env:USERPROFILE), "~"
|
|
372
|
+
try {
|
|
373
|
+
Remove-Item -Path $Target -Recurse -Force -ErrorAction Stop
|
|
374
|
+
Write-Info "Removido: $displayItem ($Label)"
|
|
375
|
+
$script:autoRemoved++
|
|
376
|
+
} catch {
|
|
377
|
+
Write-Dbg "Falha ao remover: $displayItem"
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
$script:autoRemoved = 0
|
|
383
|
+
|
|
384
|
+
# --- Categoria 1: Pacotes NPM globais legados ---
|
|
385
|
+
$npmCmd = Get-Command npm -ErrorAction SilentlyContinue
|
|
386
|
+
if ($npmCmd) {
|
|
387
|
+
foreach ($pkg in @("@ornexus/neocortex-cli", "@ornexus-ai/neocortex")) {
|
|
388
|
+
$npmList = & npm list -g $pkg --depth=0 2>$null
|
|
389
|
+
if ($npmList -match [regex]::Escape($pkg)) {
|
|
390
|
+
try {
|
|
391
|
+
& npm uninstall -g $pkg 2>$null
|
|
392
|
+
if ($LASTEXITCODE -eq 0) {
|
|
393
|
+
Write-Info "Removido: $pkg (pacote npm global legado)"
|
|
394
|
+
$script:autoRemoved++
|
|
395
|
+
}
|
|
396
|
+
} catch {
|
|
397
|
+
Write-Dbg "Falha ao remover pacote npm: $pkg"
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
# Verificar binario neocortex-cli no PATH
|
|
403
|
+
$ncliCmd = Get-Command neocortex-cli -ErrorAction SilentlyContinue
|
|
404
|
+
if ($ncliCmd -and $ncliCmd.Source -match "node_modules|npm") {
|
|
405
|
+
try {
|
|
406
|
+
Remove-Item -Path $ncliCmd.Source -Force -ErrorAction Stop
|
|
407
|
+
Write-Info "Removido: $($ncliCmd.Source) (binario neocortex-cli legado)"
|
|
408
|
+
$script:autoRemoved++
|
|
409
|
+
} catch {
|
|
410
|
+
Write-Dbg "Falha ao remover binario neocortex-cli"
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
# --- Categoria 2: Claude Code (~\.claude\) ---
|
|
416
|
+
# IP proprietaria de versoes anteriores
|
|
417
|
+
Remove-LegacyItem "$neocortexDir\core" "IP legada"
|
|
418
|
+
Remove-LegacyItem $skillsDir "skills legadas"
|
|
419
|
+
Remove-LegacyItem "$neocortexDir\workflow.md" "workflow removido no Tier 3"
|
|
420
|
+
Remove-LegacyItem "$neocortexDir\package.json" "arquivo desnecessario"
|
|
421
|
+
Remove-LegacyItem "$neocortexDir\README.md" "arquivo desnecessario"
|
|
422
|
+
|
|
423
|
+
# Step folders legados
|
|
424
|
+
foreach ($folder in @("steps-c", "steps-e", "steps-p", "steps-r", "steps-u")) {
|
|
425
|
+
Remove-LegacyItem "$neocortexDir\$folder" "steps legados"
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
# Artefatos de instalacoes anteriores
|
|
429
|
+
Remove-LegacyItem "$claudeDir\agents\.git" "repo git antigo"
|
|
430
|
+
Remove-LegacyItem "$claudeDir\.claude" "diretorio aninhado (erro BMAD)"
|
|
431
|
+
Remove-LegacyItem "$claudeDir\agents-ldtn" "diretorio legado"
|
|
432
|
+
Remove-LegacyItem "$claudeDir\.superclaude-metadata.json" "metadata SuperClaude"
|
|
433
|
+
|
|
434
|
+
# Backups SuperClaude antigos
|
|
435
|
+
if (Test-Path "$claudeDir\backups" -PathType Container) {
|
|
436
|
+
Get-ChildItem -Path "$claudeDir\backups" -Filter "superclaude_backup_*.tar.gz" -File -ErrorAction SilentlyContinue | ForEach-Object {
|
|
437
|
+
Remove-LegacyItem $_.FullName "backup SuperClaude antigo"
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
# --- Categoria 3: Cursor ---
|
|
442
|
+
Remove-LegacyItem "$env:USERPROFILE\.cursor\neocortex" "configs Cursor legadas"
|
|
443
|
+
# .cursorrules com referencias neocortex (verificar antes de remover)
|
|
444
|
+
$cursorrules = "$env:USERPROFILE\.cursorrules"
|
|
445
|
+
if (Test-Path $cursorrules -PathType Leaf) {
|
|
446
|
+
$content = Get-Content $cursorrules -Raw -ErrorAction SilentlyContinue
|
|
447
|
+
if ($content -match "(?i)neocortex|ornexus|synapse") {
|
|
448
|
+
Remove-LegacyItem $cursorrules "cursorrules com refs legadas"
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
# --- Categoria 4: VS Code ---
|
|
453
|
+
Remove-LegacyItem "$env:USERPROFILE\.vscode\neocortex" "configs VS Code legadas"
|
|
454
|
+
# .instructions.md com referencias neocortex antigo
|
|
455
|
+
$instructionsMd = "$env:USERPROFILE\.instructions.md"
|
|
456
|
+
if (Test-Path $instructionsMd -PathType Leaf) {
|
|
457
|
+
$content = Get-Content $instructionsMd -Raw -ErrorAction SilentlyContinue
|
|
458
|
+
if ($content -match "(?i)neocortex|ornexus|synapse") {
|
|
459
|
+
Remove-LegacyItem $instructionsMd "instructions.md com refs legadas"
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
# --- Categoria 5: Gemini CLI ---
|
|
464
|
+
Remove-LegacyItem "$env:USERPROFILE\.gemini\neocortex" "configs Gemini legadas"
|
|
465
|
+
|
|
466
|
+
# --- Categoria 6: Codex ---
|
|
467
|
+
Remove-LegacyItem "$env:USERPROFILE\.codex\neocortex" "configs Codex legadas"
|
|
468
|
+
|
|
469
|
+
# --- Categoria 7: Antigravity ---
|
|
470
|
+
# Configs legadas de Antigravity sao gerenciadas pelo adapter, sem path fixo global
|
|
471
|
+
|
|
472
|
+
# --- Categoria 8: Plaintext cache cleanup (Epic 62 - GAP 1) ---
|
|
473
|
+
$cacheDir = "$env:USERPROFILE\.neocortex\cache"
|
|
474
|
+
if (Test-Path $cacheDir -PathType Container) {
|
|
475
|
+
# Remove plaintext menu-cache.json
|
|
476
|
+
Remove-LegacyItem "$cacheDir\menu-cache.json" "cache plaintext (menu)"
|
|
477
|
+
|
|
478
|
+
# Remove any non-.enc files in cache dir (excluding directories)
|
|
479
|
+
Get-ChildItem -Path $cacheDir -File -ErrorAction SilentlyContinue | Where-Object {
|
|
480
|
+
$_.Extension -ne ".enc"
|
|
481
|
+
} | ForEach-Object {
|
|
482
|
+
Remove-LegacyItem $_.FullName "cache plaintext"
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
# --- Resultado ---
|
|
487
|
+
$removed = $script:autoRemoved
|
|
488
|
+
if ($removed -gt 0) {
|
|
489
|
+
Write-Ok "$removed artefato(s) legado(s) removido(s) automaticamente"
|
|
490
|
+
} else {
|
|
491
|
+
Write-Dbg "Nenhum artefato legado encontrado"
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
# Resetar contadores legados (compatibilidade)
|
|
495
|
+
$script:LegacyItems = @()
|
|
496
|
+
$script:LegacyWarnings = 0
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
# Cleanup de IP legada em projetos individuais (project-level)
|
|
500
|
+
function Invoke-AutoCleanupLegacyProject {
|
|
501
|
+
param([string]$ProjectDir)
|
|
502
|
+
|
|
503
|
+
$neocortexDir = "$ProjectDir\.claude\agents\neocortex"
|
|
504
|
+
$skillsDir = "$ProjectDir\.claude\skills\neocortex"
|
|
505
|
+
$cleaned = $false
|
|
506
|
+
|
|
507
|
+
# Remover core/ e seus subdiretorios
|
|
508
|
+
if (Test-Path "$neocortexDir\core") {
|
|
509
|
+
Remove-Item -Path "$neocortexDir\core" -Recurse -Force -ErrorAction SilentlyContinue
|
|
510
|
+
$cleaned = $true
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
# Remover step folders
|
|
514
|
+
foreach ($folder in @("steps-c", "steps-e", "steps-p", "steps-r", "steps-u")) {
|
|
515
|
+
if (Test-Path "$neocortexDir\$folder") {
|
|
516
|
+
Remove-Item -Path "$neocortexDir\$folder" -Recurse -Force -ErrorAction SilentlyContinue
|
|
517
|
+
$cleaned = $true
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
# Remover skills
|
|
522
|
+
if (Test-Path $skillsDir) {
|
|
523
|
+
Remove-Item -Path $skillsDir -Recurse -Force -ErrorAction SilentlyContinue
|
|
524
|
+
$cleaned = $true
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
# Remover arquivos desnecessarios
|
|
528
|
+
foreach ($file in @("package.json", "README.md", "workflow.md")) {
|
|
529
|
+
if (Test-Path "$neocortexDir\$file") {
|
|
530
|
+
Remove-Item -Path "$neocortexDir\$file" -Force -ErrorAction SilentlyContinue
|
|
531
|
+
$cleaned = $true
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if ($cleaned) {
|
|
536
|
+
Write-Info "IP proprietaria removida do projeto (agora servida via server remoto)"
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
# =============================================================================
|
|
541
|
+
# VERIFICACAO POS-INSTALACAO
|
|
542
|
+
# =============================================================================
|
|
543
|
+
|
|
544
|
+
function Verify-Installation {
|
|
545
|
+
$fails = 0
|
|
546
|
+
$warns = 0
|
|
547
|
+
$report = @()
|
|
548
|
+
|
|
549
|
+
if ($script:SelectedTargets -notcontains "claude-code") {
|
|
550
|
+
return $true
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
# --- Layer 1: File existence + minimum size ---
|
|
554
|
+
$criticalFiles = @(
|
|
555
|
+
@{ Name = "neocortex.md"; MinBytes = 512; Label = "Agent principal (stub)" },
|
|
556
|
+
@{ Name = "neocortex.agent.yaml"; MinBytes = 128; Label = "Agent config YAML (stub)" }
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
foreach ($entry in $criticalFiles) {
|
|
560
|
+
$fpath = Join-Path $script:DestDir $entry.Name
|
|
561
|
+
$fname = $entry.Name
|
|
562
|
+
# Epic 64 (Story 64.6): Debug file verification details
|
|
563
|
+
$fileExists = Test-Path $fpath -PathType Leaf
|
|
564
|
+
$fileSize = if ($fileExists) { (Get-Item $fpath).Length } else { 0 }
|
|
565
|
+
Write-Dbg "Verify-Installation: $fname exists=$fileExists size=$fileSize path=$fpath"
|
|
566
|
+
|
|
567
|
+
if (-not (Test-Path $fpath -PathType Leaf)) {
|
|
568
|
+
$report += @{ Status = "FAIL"; Detail = "$fname (nao encontrado)" }
|
|
569
|
+
$fails++
|
|
570
|
+
} else {
|
|
571
|
+
$fileInfo = Get-Item $fpath
|
|
572
|
+
$size = $fileInfo.Length
|
|
573
|
+
|
|
574
|
+
if ($size -lt $entry.MinBytes) {
|
|
575
|
+
$report += @{ Status = "FAIL"; Detail = "$fname ($size bytes - possivelmente corrompido, minimo $($entry.MinBytes))" }
|
|
576
|
+
$fails++
|
|
577
|
+
} else {
|
|
578
|
+
# --- Layer 2: Content marker (frontmatter) ---
|
|
579
|
+
$ext = [System.IO.Path]::GetExtension($fname)
|
|
580
|
+
if ($ext -eq ".md") {
|
|
581
|
+
$firstLine = (Get-Content $fpath -TotalCount 1 -ErrorAction SilentlyContinue)
|
|
582
|
+
if ($firstLine -ne "---") {
|
|
583
|
+
$report += @{ Status = "WARN"; Detail = "$fname (formato invalido - sem frontmatter)" }
|
|
584
|
+
$warns++
|
|
585
|
+
} else {
|
|
586
|
+
$displaySize = if ($size -ge 1024) { "$([math]::Floor($size / 1024))KB" } else { "${size}B" }
|
|
587
|
+
$report += @{ Status = "OK"; Detail = "$fname ($displaySize)" }
|
|
588
|
+
}
|
|
589
|
+
} else {
|
|
590
|
+
$displaySize = if ($size -ge 1024) { "$([math]::Floor($size / 1024))KB" } else { "${size}B" }
|
|
591
|
+
$report += @{ Status = "OK"; Detail = "$fname ($displaySize)" }
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if ($LOCAL_MODE) {
|
|
598
|
+
# --- Layer 3: Step directories (local mode only) ---
|
|
599
|
+
foreach ($dir in @("steps-c", "steps-e", "steps-p", "steps-r", "steps-u")) {
|
|
600
|
+
$dirPath = Join-Path $script:DestDir $dir
|
|
601
|
+
if (-not (Test-Path $dirPath -PathType Container)) {
|
|
602
|
+
$report += @{ Status = "FAIL"; Detail = "$dir/ (diretorio nao encontrado)" }
|
|
603
|
+
$fails++
|
|
604
|
+
} else {
|
|
605
|
+
$mdCount = (Get-ChildItem -Path $dirPath -Filter "*.md" -File -ErrorAction SilentlyContinue).Count
|
|
606
|
+
if ($mdCount -eq 0) {
|
|
607
|
+
$report += @{ Status = "WARN"; Detail = "$dir/ (vazio - nenhum arquivo .md)" }
|
|
608
|
+
$warns++
|
|
609
|
+
} else {
|
|
610
|
+
$report += @{ Status = "OK"; Detail = "$dir/ ($mdCount arquivos)" }
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
# --- Layer 3b: Core directory (local mode only) ---
|
|
616
|
+
$corePath = Join-Path $script:DestDir "core"
|
|
617
|
+
if (-not (Test-Path $corePath -PathType Container)) {
|
|
618
|
+
$report += @{ Status = "FAIL"; Detail = "core/ (diretorio nao encontrado)" }
|
|
619
|
+
$fails++
|
|
620
|
+
} else {
|
|
621
|
+
$report += @{ Status = "OK"; Detail = "core/" }
|
|
622
|
+
}
|
|
623
|
+
} else {
|
|
624
|
+
# --- Layer 3: Thin client config (remote mode) ---
|
|
625
|
+
$configFile = "$env:USERPROFILE\.neocortex\config.json"
|
|
626
|
+
if (Test-Path $configFile -PathType Leaf) {
|
|
627
|
+
$report += @{ Status = "OK"; Detail = "~\.neocortex\config.json (thin client configured)" }
|
|
628
|
+
} else {
|
|
629
|
+
$report += @{ Status = "WARN"; Detail = "~\.neocortex\config.json (nao encontrado)" }
|
|
630
|
+
$warns++
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
# Verify NO IP directories exist
|
|
634
|
+
$ipFound = $false
|
|
635
|
+
foreach ($dir in @("core", "steps-c", "steps-e", "steps-p", "steps-r", "steps-u")) {
|
|
636
|
+
if (Test-Path (Join-Path $script:DestDir $dir) -PathType Container) {
|
|
637
|
+
$report += @{ Status = "WARN"; Detail = "$dir/ ainda existe (deveria ter sido removido)" }
|
|
638
|
+
$warns++
|
|
639
|
+
$ipFound = $true
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
if (-not $ipFound) {
|
|
643
|
+
$report += @{ Status = "OK"; Detail = "Zero IP no filesystem (modo remoto)" }
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
# --- Layer 4: Tool availability (Story 66.4 AC1/AC2) ---
|
|
648
|
+
$claudeCmd = Get-Command claude -ErrorAction SilentlyContinue
|
|
649
|
+
if (-not $claudeCmd) {
|
|
650
|
+
$claudeCmd = Get-Command claude.exe -ErrorAction SilentlyContinue
|
|
651
|
+
}
|
|
652
|
+
if (-not $claudeCmd) {
|
|
653
|
+
$report += @{ Status = "WARN"; Detail = "Claude Code CLI nao encontrado no PATH" }
|
|
654
|
+
$warns++
|
|
655
|
+
Write-Info "Instale Claude Code: https://claude.ai/download"
|
|
656
|
+
} else {
|
|
657
|
+
$report += @{ Status = "OK"; Detail = "Claude Code CLI encontrado" }
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
$ncCmd = Get-Command neocortex-client -ErrorAction SilentlyContinue
|
|
661
|
+
if (-not $ncCmd) {
|
|
662
|
+
$ncCmd = Get-Command "neocortex-client.cmd" -ErrorAction SilentlyContinue
|
|
663
|
+
}
|
|
664
|
+
if (-not $ncCmd) {
|
|
665
|
+
$report += @{ Status = "WARN"; Detail = "neocortex-client nao encontrado no PATH" }
|
|
666
|
+
$warns++
|
|
667
|
+
Write-Info "Pode ser necessario reabrir o terminal apos npm install -g"
|
|
668
|
+
} else {
|
|
669
|
+
$report += @{ Status = "OK"; Detail = "neocortex-client encontrado" }
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
# --- Display report ---
|
|
673
|
+
if ($fails -eq 0 -and $warns -eq 0) {
|
|
674
|
+
if (-not $QUIET_MODE) {
|
|
675
|
+
Write-Ok "Instalacao verificada"
|
|
676
|
+
}
|
|
677
|
+
return $true
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
# Epic 64 (Story 64.3): In quiet mode, report FAILs before returning
|
|
681
|
+
if ($QUIET_MODE) {
|
|
682
|
+
if ($fails -gt 0) {
|
|
683
|
+
# Critical failures MUST be visible even in quiet mode
|
|
684
|
+
Write-Fail "Verificacao falhou: $fails arquivo(s) critico(s) faltando"
|
|
685
|
+
foreach ($entry in ($report | Where-Object { $_.Status -eq "FAIL" })) {
|
|
686
|
+
Write-Fail " $($entry.Detail)"
|
|
687
|
+
}
|
|
688
|
+
return $false
|
|
689
|
+
}
|
|
690
|
+
return $true # In quiet mode, skip warnings-only report
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
Write-Host ""
|
|
694
|
+
Write-Info "Verificacao pos-instalacao:"
|
|
695
|
+
foreach ($entry in $report) {
|
|
696
|
+
switch ($entry.Status) {
|
|
697
|
+
"OK" { Write-Host " " -NoNewline; Write-Host "[ok]" -ForegroundColor Green -NoNewline; Write-Host " $($entry.Detail)" }
|
|
698
|
+
"WARN" { Write-Host " " -NoNewline; Write-Host "[!]" -ForegroundColor Yellow -NoNewline; Write-Host " $($entry.Detail)" }
|
|
699
|
+
"FAIL" { Write-Host " " -NoNewline; Write-Host "[x]" -ForegroundColor Red -NoNewline; Write-Host " $($entry.Detail)" }
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
if ($fails -gt 0) { return $false }
|
|
704
|
+
return $true
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
# =============================================================================
|
|
708
|
+
# TIER 3: CONFIG DO THIN CLIENT
|
|
709
|
+
# =============================================================================
|
|
710
|
+
|
|
711
|
+
function Set-ThinClientConfig {
|
|
712
|
+
$configDir = "$env:USERPROFILE\.neocortex"
|
|
713
|
+
$configFile = "$configDir\config.json"
|
|
714
|
+
|
|
715
|
+
New-Item -ItemType Directory -Path $configDir -Force -ErrorAction SilentlyContinue | Out-Null
|
|
716
|
+
New-Item -ItemType Directory -Path "$configDir\cache" -Force -ErrorAction SilentlyContinue | Out-Null
|
|
717
|
+
|
|
718
|
+
# Story 66.1 AC5: Apply ACLs on ~/.neocortex/ and cache/
|
|
719
|
+
Set-DirAcl $configDir
|
|
720
|
+
Set-DirAcl "$configDir\cache"
|
|
721
|
+
|
|
722
|
+
if (Test-Path $configFile) {
|
|
723
|
+
try {
|
|
724
|
+
$existingConfig = Get-Content $configFile -Raw | ConvertFrom-Json -ErrorAction SilentlyContinue
|
|
725
|
+
if ($existingConfig.mode -eq "active" -or $existingConfig.mode -eq "local" -or $existingConfig.mode -eq "remote") {
|
|
726
|
+
# --- Config schema migration (Epic 62 - GAP 4) ---
|
|
727
|
+
if (-not $existingConfig.configVersion) {
|
|
728
|
+
Write-Dbg "Migrando schema do config.json (adicionando configVersion)"
|
|
729
|
+
try {
|
|
730
|
+
# Add configVersion
|
|
731
|
+
$existingConfig | Add-Member -NotePropertyName "configVersion" -NotePropertyValue 1 -Force
|
|
732
|
+
# Remove known obsolete fields
|
|
733
|
+
$existingConfig.PSObject.Properties.Remove("version")
|
|
734
|
+
$existingConfig.PSObject.Properties.Remove("cache")
|
|
735
|
+
# Clean obsolete tier:3 from old base template
|
|
736
|
+
if ($existingConfig.tier -eq 3 -and $existingConfig.mode -eq "pending-activation") {
|
|
737
|
+
$existingConfig.PSObject.Properties.Remove("tier")
|
|
738
|
+
}
|
|
739
|
+
Write-Utf8NoBom -Path $configFile -Content ($existingConfig | ConvertTo-Json -Depth 5)
|
|
740
|
+
Write-Dbg "Config migrada para configVersion 1"
|
|
741
|
+
} catch {
|
|
742
|
+
Write-Dbg "Falha na migracao do config: $_"
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
# --- Fix stale localhost serverUrl (Epic 70 - Story 70.02) ----
|
|
746
|
+
# If config has localhost serverUrl and installer has production URL,
|
|
747
|
+
# update serverUrl while preserving all other config fields.
|
|
748
|
+
$existingServerUrl = $existingConfig.serverUrl
|
|
749
|
+
if ($existingServerUrl -match '^https?://(localhost|127\.0\.0\.1|0\.0\.0\.0)(:\d+)?') {
|
|
750
|
+
if ($NEOCORTEX_SERVER_URL -ne $existingServerUrl) {
|
|
751
|
+
Write-Dbg "Fixing stale localhost serverUrl: $existingServerUrl -> $NEOCORTEX_SERVER_URL"
|
|
752
|
+
try {
|
|
753
|
+
$existingConfig.serverUrl = $NEOCORTEX_SERVER_URL
|
|
754
|
+
Write-Utf8NoBom -Path $configFile -Content ($existingConfig | ConvertTo-Json -Depth 5)
|
|
755
|
+
Set-FileAcl $configFile
|
|
756
|
+
Write-Dbg "serverUrl updated to $NEOCORTEX_SERVER_URL"
|
|
757
|
+
} catch {
|
|
758
|
+
Write-Dbg "Failed to update serverUrl: $_"
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
# --- Fix stale ornexus.com serverUrl (Epic P46 - Story P46.04) ----
|
|
764
|
+
if ($existingServerUrl -match 'api\.neocortex\.ornexus\.com') {
|
|
765
|
+
Write-Dbg "Fixing old ornexus.com serverUrl: $existingServerUrl -> $NEOCORTEX_SERVER_URL"
|
|
766
|
+
try {
|
|
767
|
+
$existingConfig.serverUrl = $NEOCORTEX_SERVER_URL
|
|
768
|
+
Write-Utf8NoBom -Path $configFile -Content ($existingConfig | ConvertTo-Json -Depth 5)
|
|
769
|
+
Set-FileAcl $configFile
|
|
770
|
+
Write-Dbg "serverUrl updated from ornexus.com to $NEOCORTEX_SERVER_URL"
|
|
771
|
+
} catch {
|
|
772
|
+
Write-Dbg "Failed to update serverUrl: $_"
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
Write-Dbg "Config existente preservada (mode=$($existingConfig.mode))"
|
|
777
|
+
return
|
|
778
|
+
}
|
|
779
|
+
} catch { }
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
$config = @{
|
|
783
|
+
configVersion = 1
|
|
784
|
+
mode = "pending-activation"
|
|
785
|
+
serverUrl = $NEOCORTEX_SERVER_URL
|
|
786
|
+
resilience = @{
|
|
787
|
+
circuitBreaker = $true
|
|
788
|
+
maxRetries = 3
|
|
789
|
+
timeoutMs = 5000
|
|
790
|
+
}
|
|
791
|
+
installedAt = (Get-Date -Format "o")
|
|
792
|
+
installerVersion = $VERSION
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
Write-Utf8NoBom -Path $configFile -Content ($config | ConvertTo-Json -Depth 5)
|
|
796
|
+
# Story 66.1 AC4: Apply ACL on config.json
|
|
797
|
+
Set-FileAcl $configFile
|
|
798
|
+
Write-Dbg "Thin client config criada: $configFile"
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
# Remove-LegacyIPProject substituida por Invoke-AutoCleanupLegacyProject
|
|
802
|
+
# (definida na secao de limpeza automatica acima)
|
|
803
|
+
|
|
804
|
+
# =============================================================================
|
|
805
|
+
# INSTALACAO CORE
|
|
806
|
+
# =============================================================================
|
|
807
|
+
|
|
808
|
+
function Install-Core {
|
|
809
|
+
$script:ClaudeDir = "$env:USERPROFILE\.claude"
|
|
810
|
+
$script:AgentsDir = "$script:ClaudeDir\agents"
|
|
811
|
+
$script:DestDir = "$script:AgentsDir\neocortex"
|
|
812
|
+
|
|
813
|
+
Write-Dbg "DEST=$script:DestDir"
|
|
814
|
+
|
|
815
|
+
# Create directories with verification (Epic 65)
|
|
816
|
+
if (-not (Test-Path $script:ClaudeDir)) {
|
|
817
|
+
try { New-Item -ItemType Directory -Path $script:ClaudeDir -Force -ErrorAction Stop | Out-Null }
|
|
818
|
+
catch { Write-Fail "Falha ao criar $script:ClaudeDir`: $_"; return $false }
|
|
819
|
+
}
|
|
820
|
+
try { New-Item -ItemType Directory -Path $script:AgentsDir -Force -ErrorAction Stop | Out-Null }
|
|
821
|
+
catch { Write-Fail "Falha ao criar $script:AgentsDir`: $_"; return $false }
|
|
822
|
+
|
|
823
|
+
# Clean previous
|
|
824
|
+
if (Test-Path $script:DestDir) {
|
|
825
|
+
try {
|
|
826
|
+
Remove-Item -Path $script:DestDir -Recurse -Force -ErrorAction Stop
|
|
827
|
+
} catch {
|
|
828
|
+
Write-Warn "Falha ao remover instalacao anterior: $_ (tentando continuar)"
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
try { New-Item -ItemType Directory -Path $script:DestDir -Force -ErrorAction Stop | Out-Null }
|
|
832
|
+
catch { Write-Fail "Falha ao criar $script:DestDir`: $_"; return $false }
|
|
833
|
+
|
|
834
|
+
# Verify directory was actually created (Epic 65: anti-silent-failure)
|
|
835
|
+
if (-not (Test-Path $script:DestDir -PathType Container)) {
|
|
836
|
+
Write-Fail "Diretorio $script:DestDir nao existe apos criacao"
|
|
837
|
+
return $false
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if ($LOCAL_MODE) {
|
|
841
|
+
# Modo local: copiar IP completa (comportamento legado para devs)
|
|
842
|
+
$coreSource = Join-Path $script:SourceDir "core"
|
|
843
|
+
if (Test-Path $coreSource -PathType Container) {
|
|
844
|
+
Copy-Item -Path $coreSource -Destination "$script:DestDir\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
845
|
+
}
|
|
846
|
+
$r = Copy-Silent "$($script:SourceDir)\package.json" "$script:DestDir\"
|
|
847
|
+
if (-not $r) { Write-Fail "Falha ao copiar package.json (Install-Core)" }
|
|
848
|
+
$r = Copy-Silent "$($script:SourceDir)\README.md" "$script:DestDir\"
|
|
849
|
+
if (-not $r) { Write-Fail "Falha ao copiar README.md (Install-Core)" }
|
|
850
|
+
} else {
|
|
851
|
+
# Tier 3 Remote Mode: NAO copiar IP
|
|
852
|
+
# Nota: Invoke-AutoCleanupLegacy ja rodou no inicio - aqui apenas config
|
|
853
|
+
Set-ThinClientConfig
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
# --- Version-aware cache purge on upgrade (Epic 62 - GAP 2+3) ---
|
|
857
|
+
$pkgJsonPath = Join-Path $script:SourceDir "package.json"
|
|
858
|
+
$pkgVersion = $null
|
|
859
|
+
if (Test-Path $pkgJsonPath) {
|
|
860
|
+
$pkgJson = Get-Content $pkgJsonPath -Raw | ConvertFrom-Json -ErrorAction SilentlyContinue
|
|
861
|
+
$pkgVersion = $pkgJson.version
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
if ($pkgVersion) {
|
|
865
|
+
$oldVersion = $null
|
|
866
|
+
# Read existing .version from either location
|
|
867
|
+
$versionPaths = @("$script:DestDir\.version", "$env:USERPROFILE\.neocortex\.version")
|
|
868
|
+
foreach ($vp in $versionPaths) {
|
|
869
|
+
if (Test-Path $vp -PathType Leaf) {
|
|
870
|
+
$oldVersion = (Get-Content $vp -Raw -ErrorAction SilentlyContinue).Trim()
|
|
871
|
+
if ($oldVersion) { break }
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
# If version changed, purge all cache files
|
|
876
|
+
if ($oldVersion -and $oldVersion -ne $pkgVersion) {
|
|
877
|
+
$cachePurgeDir = "$env:USERPROFILE\.neocortex\cache"
|
|
878
|
+
if (Test-Path $cachePurgeDir -PathType Container) {
|
|
879
|
+
$purged = 0
|
|
880
|
+
Get-ChildItem -Path $cachePurgeDir -File -ErrorAction SilentlyContinue | ForEach-Object {
|
|
881
|
+
Remove-Item $_.FullName -Force -ErrorAction SilentlyContinue
|
|
882
|
+
$purged++
|
|
883
|
+
}
|
|
884
|
+
if ($purged -gt 0) {
|
|
885
|
+
Write-Info "Cache purgado: versao alterada de $oldVersion para $pkgVersion ($purged arquivo(s))"
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
# Write version file
|
|
891
|
+
Write-Utf8NoBom -Path "$script:DestDir\.version" -Content $pkgVersion
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
if ($LOCAL_MODE) {
|
|
895
|
+
Write-Ok "Core instalado (standards, templates, scripts) [modo local]"
|
|
896
|
+
} else {
|
|
897
|
+
Write-Ok "Remote mode configured (thin client ready)"
|
|
898
|
+
}
|
|
899
|
+
return $true
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
# =============================================================================
|
|
903
|
+
# INSTALACAO DE SKILLS
|
|
904
|
+
# =============================================================================
|
|
905
|
+
|
|
906
|
+
function Install-Skills {
|
|
907
|
+
$script:SkillsDir = "$script:ClaudeDir\skills"
|
|
908
|
+
$script:SkillsDest = "$script:SkillsDir\neocortex"
|
|
909
|
+
$skillsSource = "$script:SourceDir\core\skills"
|
|
910
|
+
|
|
911
|
+
# Tier 3 Remote Mode: skills vem do server, nao copiar
|
|
912
|
+
if (-not $LOCAL_MODE) {
|
|
913
|
+
Write-Ok "Skills: delivered by remote server"
|
|
914
|
+
return $true
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
if (-not (Test-Path $skillsSource -PathType Container)) { return $true }
|
|
918
|
+
|
|
919
|
+
New-Item -ItemType Directory -Path $script:SkillsDir -Force | Out-Null
|
|
920
|
+
|
|
921
|
+
if (Test-Path $script:SkillsDest) {
|
|
922
|
+
Remove-Item -Path $script:SkillsDest -Recurse -Force -ErrorAction SilentlyContinue
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
try {
|
|
926
|
+
Copy-Item -Path $skillsSource -Destination $script:SkillsDest -Recurse -Force
|
|
927
|
+
|
|
928
|
+
# Count skills
|
|
929
|
+
$skillCount = 0
|
|
930
|
+
Get-ChildItem "$script:SkillsDest\step-skills\*\*.md", "$script:SkillsDest\domain-skills\*\*.md" -File -ErrorAction SilentlyContinue |
|
|
931
|
+
Where-Object { $_.Name -ne "_template.md" } | ForEach-Object { $skillCount++ }
|
|
932
|
+
|
|
933
|
+
Write-Ok "Skills instaladas ($skillCount skills) [modo local]"
|
|
934
|
+
return $true
|
|
935
|
+
} catch {
|
|
936
|
+
Write-Fail "Falha ao copiar skills"
|
|
937
|
+
return $false
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
# =============================================================================
|
|
942
|
+
# INSTALACAO DE AGENT (Claude Code)
|
|
943
|
+
# =============================================================================
|
|
944
|
+
|
|
945
|
+
function Install-Agent {
|
|
946
|
+
$claudeTargetDir = Join-Path $script:SourceDir "targets\claude-code"
|
|
947
|
+
if (-not (Test-Path $claudeTargetDir)) {
|
|
948
|
+
$claudeTargetDir = Join-Path $script:SourceDir "targets-stubs\claude-code"
|
|
949
|
+
}
|
|
950
|
+
if (-not (Test-Path $claudeTargetDir)) {
|
|
951
|
+
$claudeTargetDir = $script:SourceDir
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
# Epic 64 (Story 64.6): Debug diagnostics for Install-Agent
|
|
955
|
+
Write-Dbg "Install-Agent: SourceDir=$($script:SourceDir)"
|
|
956
|
+
Write-Dbg "Install-Agent: DestDir=$($script:DestDir)"
|
|
957
|
+
Write-Dbg "Install-Agent: claudeTargetDir=$claudeTargetDir"
|
|
958
|
+
$srcMdExists = Test-Path "$claudeTargetDir\neocortex.md"
|
|
959
|
+
$srcYamlExists = Test-Path "$claudeTargetDir\neocortex.agent.yaml"
|
|
960
|
+
Write-Dbg "Install-Agent: neocortex.md exists=$srcMdExists"
|
|
961
|
+
Write-Dbg "Install-Agent: neocortex.agent.yaml exists=$srcYamlExists"
|
|
962
|
+
|
|
963
|
+
# Epic 65: Early validation -- if NEITHER source file exists, emit clear error
|
|
964
|
+
if (-not $srcMdExists -and -not $srcYamlExists) {
|
|
965
|
+
Write-Fail "Arquivos fonte nao encontrados em: $claudeTargetDir"
|
|
966
|
+
Write-Fail "Diretorio de origem ($($script:SourceDir)) pode estar incompleto"
|
|
967
|
+
Write-Fail "Tente reinstalar: npm install -g @ornexus/neocortex"
|
|
968
|
+
$script:Errors += 2
|
|
969
|
+
return $false
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
# Tier 3: Copy only 2 stub files
|
|
973
|
+
# Epic 64 (Story 64.2): Capture Copy-Silent return and check for errors
|
|
974
|
+
$stubResult1 = Copy-Silent "$claudeTargetDir\neocortex.md" "$script:DestDir\"
|
|
975
|
+
if (-not $stubResult1) { Write-Fail "Falha ao copiar neocortex.md de $claudeTargetDir" }
|
|
976
|
+
Write-Dbg "Install-Agent: Copy neocortex.md result=$stubResult1"
|
|
977
|
+
$stubResult2 = Copy-Silent "$claudeTargetDir\neocortex.agent.yaml" "$script:DestDir\"
|
|
978
|
+
if (-not $stubResult2) { Write-Fail "Falha ao copiar neocortex.agent.yaml de $claudeTargetDir" }
|
|
979
|
+
Write-Dbg "Install-Agent: Copy neocortex.agent.yaml result=$stubResult2"
|
|
980
|
+
|
|
981
|
+
# Epic 65: Post-copy verification -- belt and suspenders
|
|
982
|
+
$destMd = Join-Path $script:DestDir "neocortex.md"
|
|
983
|
+
$destYaml = Join-Path $script:DestDir "neocortex.agent.yaml"
|
|
984
|
+
if (-not (Test-Path $destMd -PathType Leaf)) {
|
|
985
|
+
Write-Fail "neocortex.md nao encontrado no destino apos copia: $destMd"
|
|
986
|
+
if (-not $stubResult1) {} else { $script:Errors++ }
|
|
987
|
+
}
|
|
988
|
+
if (-not (Test-Path $destYaml -PathType Leaf)) {
|
|
989
|
+
Write-Fail "neocortex.agent.yaml nao encontrado no destino apos copia: $destYaml"
|
|
990
|
+
if (-not $stubResult2) {} else { $script:Errors++ }
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
# Cleanup workflow.md from previous versions
|
|
994
|
+
if (Test-Path "$script:DestDir\workflow.md") {
|
|
995
|
+
Remove-Item "$script:DestDir\workflow.md" -Force -ErrorAction SilentlyContinue
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
if ($LOCAL_MODE) {
|
|
999
|
+
# Modo local: copiar IP completa (comportamento legado para devs)
|
|
1000
|
+
$r = Copy-Silent "$($script:SourceDir)\package.json" "$script:DestDir\"
|
|
1001
|
+
if (-not $r) { Write-Fail "Falha ao copiar package.json" }
|
|
1002
|
+
$r = Copy-Silent "$($script:SourceDir)\README.md" "$script:DestDir\"
|
|
1003
|
+
if (-not $r) { Write-Fail "Falha ao copiar README.md" }
|
|
1004
|
+
|
|
1005
|
+
$coreSource = Join-Path $script:SourceDir "core"
|
|
1006
|
+
if (Test-Path $coreSource -PathType Container) {
|
|
1007
|
+
Copy-Item -Path $coreSource -Destination "$script:DestDir\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
foreach ($folder in @("steps-c", "steps-e", "steps-p", "steps-r", "steps-u")) {
|
|
1011
|
+
$stepSrc = "$($script:SourceDir)\core\steps\$folder"
|
|
1012
|
+
if (Test-Path $stepSrc -PathType Container) {
|
|
1013
|
+
Copy-Item -Path $stepSrc -Destination "$script:DestDir\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
# Tier 3 Remote Mode: apenas 2 arquivos de interface (stubs)
|
|
1018
|
+
|
|
1019
|
+
return ($script:Errors -eq 0)
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
# =============================================================================
|
|
1023
|
+
# CARREGAMENTO DE .ENV
|
|
1024
|
+
# =============================================================================
|
|
1025
|
+
|
|
1026
|
+
function Import-EnvFile {
|
|
1027
|
+
$envFile = $null
|
|
1028
|
+
@(".\.env", "$script:SourceDir\.env") | ForEach-Object {
|
|
1029
|
+
if ((Test-Path $_ -PathType Leaf) -and -not $envFile) { $envFile = $_ }
|
|
1030
|
+
}
|
|
1031
|
+
if (-not $envFile) { return $false }
|
|
1032
|
+
|
|
1033
|
+
$loaded = 0
|
|
1034
|
+
Get-Content $envFile | ForEach-Object {
|
|
1035
|
+
$line = $_.Trim()
|
|
1036
|
+
if (-not $line -or $line.StartsWith("#")) { return }
|
|
1037
|
+
if ($line -match "^([^=]+)=(.*)$") {
|
|
1038
|
+
$key = $matches[1].Trim()
|
|
1039
|
+
$value = $matches[2].Trim() -replace '^["'']|["'']$', ''
|
|
1040
|
+
if ($value -and -not [Environment]::GetEnvironmentVariable($key)) {
|
|
1041
|
+
[Environment]::SetEnvironmentVariable($key, $value, "Process")
|
|
1042
|
+
Set-Item -Path "env:$key" -Value $value -ErrorAction SilentlyContinue
|
|
1043
|
+
$loaded++
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
if ($loaded -gt 0) { Write-Info "$loaded variavel(eis) carregada(s) do .env" }
|
|
1048
|
+
return $true
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
# =============================================================================
|
|
1052
|
+
# CONFIGURACAO DE TOKENS
|
|
1053
|
+
# =============================================================================
|
|
1054
|
+
|
|
1055
|
+
function Request-Tokens {
|
|
1056
|
+
if ($QUIET_MODE -or $AUTO_YES -or $env:CONTEXT7_API_KEY) { return }
|
|
1057
|
+
|
|
1058
|
+
Write-Host ""
|
|
1059
|
+
Write-Info "MCP Context7 nao configurado (opcional)"
|
|
1060
|
+
Write-Host " Configurar agora? [s/N]: " -NoNewline -ForegroundColor White
|
|
1061
|
+
$response = Read-HostWithTimeout -TimeoutSeconds 15 -Default "n"
|
|
1062
|
+
|
|
1063
|
+
if ($response -match "^[sS]([iI][mM]?)?$|^[yY]([eE][sS]?)?$") {
|
|
1064
|
+
Write-Host ""
|
|
1065
|
+
Write-Info "Obtenha sua API Key em: https://context7.com"
|
|
1066
|
+
Write-Host " Cole sua CONTEXT7_API_KEY: " -NoNewline -ForegroundColor White
|
|
1067
|
+
try {
|
|
1068
|
+
$apiKey = Read-Host
|
|
1069
|
+
if ($apiKey -match "^ctx7sk-") {
|
|
1070
|
+
$env:CONTEXT7_API_KEY = $apiKey
|
|
1071
|
+
Write-Ok "CONTEXT7_API_KEY configurada"
|
|
1072
|
+
Write-Info "Para persistir: `$env:CONTEXT7_API_KEY = `"$apiKey`" em `$PROFILE"
|
|
1073
|
+
} elseif ($apiKey) {
|
|
1074
|
+
Write-Warn "Formato invalido (esperado: ctx7sk-...)"
|
|
1075
|
+
}
|
|
1076
|
+
} catch {}
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
# =============================================================================
|
|
1081
|
+
# INSTALACAO DE MCP SERVERS
|
|
1082
|
+
# =============================================================================
|
|
1083
|
+
|
|
1084
|
+
function Install-MCPs {
|
|
1085
|
+
$claudeCmd = Get-Command claude -ErrorAction SilentlyContinue
|
|
1086
|
+
if (-not $claudeCmd) {
|
|
1087
|
+
Write-Info "Claude CLI nao encontrado (MCPs serao instalados depois)"
|
|
1088
|
+
return
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
$existingMcps = ""
|
|
1092
|
+
try { $existingMcps = & claude mcp list 2>$null } catch {}
|
|
1093
|
+
|
|
1094
|
+
$mcpOk = @()
|
|
1095
|
+
$mcpSkip = @()
|
|
1096
|
+
|
|
1097
|
+
# Playwright
|
|
1098
|
+
if ($existingMcps -match "playwright") {
|
|
1099
|
+
$mcpOk += "playwright"
|
|
1100
|
+
} else {
|
|
1101
|
+
try {
|
|
1102
|
+
& claude mcp add playwright npx @playwright/mcp@latest 2>$null
|
|
1103
|
+
if ($LASTEXITCODE -eq 0) { $mcpOk += "playwright" }
|
|
1104
|
+
} catch {}
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
# Context7
|
|
1108
|
+
if ($existingMcps -match "context7") {
|
|
1109
|
+
$mcpOk += "context7"
|
|
1110
|
+
} elseif ($env:CONTEXT7_API_KEY) {
|
|
1111
|
+
try {
|
|
1112
|
+
& claude mcp add --transport http context7 https://mcp.context7.com/mcp --header "CONTEXT7_API_KEY: $env:CONTEXT7_API_KEY" 2>$null
|
|
1113
|
+
if ($LASTEXITCODE -eq 0) { $mcpOk += "context7" }
|
|
1114
|
+
} catch {}
|
|
1115
|
+
} else {
|
|
1116
|
+
$mcpSkip += "context7"
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
if ($mcpOk.Count -gt 0) { Write-Ok "MCPs: $($mcpOk -join ', ')" }
|
|
1120
|
+
if ($mcpSkip.Count -gt 0) { Write-Info "MCPs pendentes: $($mcpSkip -join ', ')" }
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
# =============================================================================
|
|
1124
|
+
# INSTALACAO DO CODERABBIT CLI
|
|
1125
|
+
# =============================================================================
|
|
1126
|
+
|
|
1127
|
+
function Install-CodeRabbit {
|
|
1128
|
+
$coderabbitCmd = Get-Command coderabbit -ErrorAction SilentlyContinue
|
|
1129
|
+
if ($coderabbitCmd) {
|
|
1130
|
+
Write-Ok "CodeRabbit CLI"
|
|
1131
|
+
$script:CodeRabbitInstalled = $true
|
|
1132
|
+
return
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
# Try curl via sh
|
|
1136
|
+
try {
|
|
1137
|
+
$shCmd = Get-Command sh -ErrorAction SilentlyContinue
|
|
1138
|
+
if ($shCmd) {
|
|
1139
|
+
$installScript = Invoke-WebRequest -Uri "https://cli.coderabbit.ai/install.sh" -UseBasicParsing -TimeoutSec 30 -ErrorAction Stop
|
|
1140
|
+
$installScript.Content | & sh 2>$null
|
|
1141
|
+
if ($LASTEXITCODE -eq 0) {
|
|
1142
|
+
Write-Ok "CodeRabbit CLI (instalado)"
|
|
1143
|
+
$script:CodeRabbitInstalled = $true
|
|
1144
|
+
return
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
} catch {}
|
|
1148
|
+
|
|
1149
|
+
# Try npm
|
|
1150
|
+
$npmCmd = Get-Command npm -ErrorAction SilentlyContinue
|
|
1151
|
+
if ($npmCmd) {
|
|
1152
|
+
try {
|
|
1153
|
+
& npm install -g coderabbit 2>$null
|
|
1154
|
+
if ($LASTEXITCODE -eq 0) {
|
|
1155
|
+
Write-Ok "CodeRabbit CLI (via npm)"
|
|
1156
|
+
$script:CodeRabbitInstalled = $true
|
|
1157
|
+
return
|
|
1158
|
+
}
|
|
1159
|
+
} catch {}
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
Write-Info "CodeRabbit CLI (instale depois: curl -fsSL https://cli.coderabbit.ai/install.sh | sh)"
|
|
1163
|
+
$script:CodeRabbitInstalled = $false
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
# =============================================================================
|
|
1167
|
+
# MULTI-TARGET SUPPORT
|
|
1168
|
+
# =============================================================================
|
|
1169
|
+
|
|
1170
|
+
$script:ValidTargets = @("claude-code", "cursor", "vscode", "gemini-cli", "codex", "antigravity")
|
|
1171
|
+
$script:SelectedTargets = @()
|
|
1172
|
+
$script:TargetResults = @()
|
|
1173
|
+
$script:TargetCount = 0
|
|
1174
|
+
|
|
1175
|
+
function Install-Targets {
|
|
1176
|
+
param([string[]]$TargetList)
|
|
1177
|
+
|
|
1178
|
+
$homeDir = $env:USERPROFILE
|
|
1179
|
+
|
|
1180
|
+
foreach ($target in $TargetList) {
|
|
1181
|
+
switch ($target) {
|
|
1182
|
+
"claude-code" {
|
|
1183
|
+
$success = Install-Agent
|
|
1184
|
+
if ($success) {
|
|
1185
|
+
$script:TargetResults += "$target`:OK"
|
|
1186
|
+
$script:TargetCount++
|
|
1187
|
+
Write-Ok "claude-code (thin client)"
|
|
1188
|
+
} else {
|
|
1189
|
+
$script:TargetResults += "$target`:FAIL"
|
|
1190
|
+
Write-Fail "claude-code"
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
"cursor" {
|
|
1194
|
+
$cursorTargetDir = Join-Path $script:SourceDir "targets\cursor"
|
|
1195
|
+
if (Test-Path $cursorTargetDir -PathType Container) {
|
|
1196
|
+
# Clean previous
|
|
1197
|
+
Remove-Item -Path "$homeDir\.cursor\agents\neocortex.md" -Force -ErrorAction SilentlyContinue
|
|
1198
|
+
Remove-Item -Path "$homeDir\.cursor\mcp.json" -Force -ErrorAction SilentlyContinue
|
|
1199
|
+
if (Test-Path "$homeDir\.cursor\skills") { Remove-Item -Path "$homeDir\.cursor\skills" -Recurse -Force -ErrorAction SilentlyContinue }
|
|
1200
|
+
|
|
1201
|
+
# Agent
|
|
1202
|
+
if (Test-Path "$cursorTargetDir\agent.md") {
|
|
1203
|
+
New-Item -ItemType Directory -Path "$homeDir\.cursor\agents" -Force | Out-Null
|
|
1204
|
+
Copy-Item -Path "$cursorTargetDir\agent.md" -Destination "$homeDir\.cursor\agents\neocortex.md" -Force
|
|
1205
|
+
}
|
|
1206
|
+
# Rules
|
|
1207
|
+
if (Test-Path "$cursorTargetDir\rules" -PathType Container) {
|
|
1208
|
+
New-Item -ItemType Directory -Path "$homeDir\.cursor\rules" -Force | Out-Null
|
|
1209
|
+
Copy-Item -Path "$cursorTargetDir\rules\*.mdc" -Destination "$homeDir\.cursor\rules\" -Force -ErrorAction SilentlyContinue
|
|
1210
|
+
}
|
|
1211
|
+
# Commands
|
|
1212
|
+
if (Test-Path "$cursorTargetDir\commands" -PathType Container) {
|
|
1213
|
+
New-Item -ItemType Directory -Path "$homeDir\.cursor\commands" -Force | Out-Null
|
|
1214
|
+
Copy-Item -Path "$cursorTargetDir\commands\*.md" -Destination "$homeDir\.cursor\commands\" -Force -ErrorAction SilentlyContinue
|
|
1215
|
+
}
|
|
1216
|
+
# MCP config
|
|
1217
|
+
if (Test-Path "$cursorTargetDir\mcp.json") {
|
|
1218
|
+
Copy-Item -Path "$cursorTargetDir\mcp.json" -Destination "$homeDir\.cursor\mcp.json" -Force
|
|
1219
|
+
}
|
|
1220
|
+
# Skills
|
|
1221
|
+
$skillsSource = Join-Path $script:SourceDir "core\skills"
|
|
1222
|
+
if (Test-Path $skillsSource -PathType Container) {
|
|
1223
|
+
New-Item -ItemType Directory -Path "$homeDir\.cursor\skills" -Force | Out-Null
|
|
1224
|
+
Copy-Item -Path "$skillsSource\*" -Destination "$homeDir\.cursor\skills\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
Write-Ok "cursor"
|
|
1228
|
+
$script:TargetResults += "$target`:OK"
|
|
1229
|
+
$script:TargetCount++
|
|
1230
|
+
} else {
|
|
1231
|
+
Write-Warn "cursor (adapter nao encontrado)"
|
|
1232
|
+
$script:TargetResults += "$target`:SKIP"
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
"vscode" {
|
|
1236
|
+
$vscodeTargetDir = Join-Path $script:SourceDir "targets\vscode"
|
|
1237
|
+
if (Test-Path $vscodeTargetDir -PathType Container) {
|
|
1238
|
+
# Clean previous
|
|
1239
|
+
Remove-Item -Path "$homeDir\.github\agents\neocortex.md" -Force -ErrorAction SilentlyContinue
|
|
1240
|
+
Remove-Item -Path "$homeDir\.github\copilot-instructions.md" -Force -ErrorAction SilentlyContinue
|
|
1241
|
+
if (Test-Path "$homeDir\.github\skills") { Remove-Item -Path "$homeDir\.github\skills" -Recurse -Force -ErrorAction SilentlyContinue }
|
|
1242
|
+
|
|
1243
|
+
if (Test-Path "$vscodeTargetDir\agent.md") {
|
|
1244
|
+
New-Item -ItemType Directory -Path "$homeDir\.github\agents" -Force | Out-Null
|
|
1245
|
+
Copy-Item -Path "$vscodeTargetDir\agent.md" -Destination "$homeDir\.github\agents\neocortex.md" -Force
|
|
1246
|
+
}
|
|
1247
|
+
if (Test-Path "$vscodeTargetDir\instructions" -PathType Container) {
|
|
1248
|
+
New-Item -ItemType Directory -Path "$homeDir\.github\instructions" -Force | Out-Null
|
|
1249
|
+
Copy-Item -Path "$vscodeTargetDir\instructions\*.instructions.md" -Destination "$homeDir\.github\instructions\" -Force -ErrorAction SilentlyContinue
|
|
1250
|
+
}
|
|
1251
|
+
if (Test-Path "$vscodeTargetDir\prompts" -PathType Container) {
|
|
1252
|
+
New-Item -ItemType Directory -Path "$homeDir\.github\prompts" -Force | Out-Null
|
|
1253
|
+
Copy-Item -Path "$vscodeTargetDir\prompts\*.prompt.md" -Destination "$homeDir\.github\prompts\" -Force -ErrorAction SilentlyContinue
|
|
1254
|
+
}
|
|
1255
|
+
if (Test-Path "$vscodeTargetDir\mcp.json") {
|
|
1256
|
+
New-Item -ItemType Directory -Path "$homeDir\.vscode" -Force | Out-Null
|
|
1257
|
+
Copy-Item -Path "$vscodeTargetDir\mcp.json" -Destination "$homeDir\.vscode\mcp.json" -Force
|
|
1258
|
+
}
|
|
1259
|
+
if (Test-Path "$vscodeTargetDir\copilot-instructions.md") {
|
|
1260
|
+
Copy-Item -Path "$vscodeTargetDir\copilot-instructions.md" -Destination "$homeDir\.github\copilot-instructions.md" -Force
|
|
1261
|
+
}
|
|
1262
|
+
$skillsSource = Join-Path $script:SourceDir "core\skills"
|
|
1263
|
+
if (Test-Path $skillsSource -PathType Container) {
|
|
1264
|
+
New-Item -ItemType Directory -Path "$homeDir\.github\skills" -Force | Out-Null
|
|
1265
|
+
Copy-Item -Path "$skillsSource\*" -Destination "$homeDir\.github\skills\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
Write-Ok "vscode"
|
|
1269
|
+
$script:TargetResults += "$target`:OK"
|
|
1270
|
+
$script:TargetCount++
|
|
1271
|
+
} else {
|
|
1272
|
+
Write-Warn "vscode (adapter nao encontrado)"
|
|
1273
|
+
$script:TargetResults += "$target`:SKIP"
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
"gemini-cli" {
|
|
1277
|
+
$geminiTargetDir = Join-Path $script:SourceDir "targets\gemini-cli"
|
|
1278
|
+
$geminiHome = if ($env:GEMINI_HOME) { $env:GEMINI_HOME } else { "$homeDir\.gemini" }
|
|
1279
|
+
if (Test-Path $geminiTargetDir -PathType Container) {
|
|
1280
|
+
Remove-Item -Path "$geminiHome\agents\neocortex.md" -Force -ErrorAction SilentlyContinue
|
|
1281
|
+
if (Test-Path "$geminiHome\skills") { Remove-Item -Path "$geminiHome\skills" -Recurse -Force -ErrorAction SilentlyContinue }
|
|
1282
|
+
|
|
1283
|
+
if (Test-Path "$geminiTargetDir\agent.md") {
|
|
1284
|
+
New-Item -ItemType Directory -Path "$geminiHome\agents" -Force | Out-Null
|
|
1285
|
+
Copy-Item -Path "$geminiTargetDir\agent.md" -Destination "$geminiHome\agents\neocortex.md" -Force
|
|
1286
|
+
}
|
|
1287
|
+
if (Test-Path "$geminiTargetDir\gemini.md") {
|
|
1288
|
+
Copy-Item -Path "$geminiTargetDir\gemini.md" -Destination "$homeDir\GEMINI.md" -Force
|
|
1289
|
+
}
|
|
1290
|
+
if (Test-Path "$geminiTargetDir\commands" -PathType Container) {
|
|
1291
|
+
New-Item -ItemType Directory -Path "$geminiHome\commands" -Force | Out-Null
|
|
1292
|
+
Copy-Item -Path "$geminiTargetDir\commands\*.toml" -Destination "$geminiHome\commands\" -Force -ErrorAction SilentlyContinue
|
|
1293
|
+
}
|
|
1294
|
+
if (Test-Path "$geminiTargetDir\settings-mcp.json") {
|
|
1295
|
+
$settingsFile = "$geminiHome\settings.json"
|
|
1296
|
+
if (Test-Path $settingsFile) {
|
|
1297
|
+
try {
|
|
1298
|
+
$existingSettings = Get-Content $settingsFile -Raw | ConvertFrom-Json
|
|
1299
|
+
$mcpFragment = Get-Content "$geminiTargetDir\settings-mcp.json" -Raw | ConvertFrom-Json
|
|
1300
|
+
if ($mcpFragment.mcpServers) {
|
|
1301
|
+
if (-not $existingSettings.mcpServers) {
|
|
1302
|
+
$existingSettings | Add-Member -NotePropertyName "mcpServers" -NotePropertyValue $mcpFragment.mcpServers -Force
|
|
1303
|
+
} else {
|
|
1304
|
+
$mcpFragment.mcpServers.PSObject.Properties | ForEach-Object {
|
|
1305
|
+
$existingSettings.mcpServers | Add-Member -NotePropertyName $_.Name -NotePropertyValue $_.Value -Force
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
Write-Utf8NoBom -Path $settingsFile -Content ($existingSettings | ConvertTo-Json -Depth 10)
|
|
1310
|
+
} catch {
|
|
1311
|
+
Copy-Item -Path "$geminiTargetDir\settings-mcp.json" -Destination "$geminiHome\settings-mcp.json" -Force
|
|
1312
|
+
}
|
|
1313
|
+
} else {
|
|
1314
|
+
Copy-Item -Path "$geminiTargetDir\settings-mcp.json" -Destination $settingsFile -Force
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
$skillsSource = Join-Path $script:SourceDir "core\skills"
|
|
1318
|
+
if (Test-Path $skillsSource -PathType Container) {
|
|
1319
|
+
New-Item -ItemType Directory -Path "$geminiHome\skills" -Force | Out-Null
|
|
1320
|
+
Copy-Item -Path "$skillsSource\*" -Destination "$geminiHome\skills\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
Write-Ok "gemini-cli"
|
|
1324
|
+
$script:TargetResults += "$target`:OK"
|
|
1325
|
+
$script:TargetCount++
|
|
1326
|
+
} else {
|
|
1327
|
+
Write-Warn "gemini-cli (adapter nao encontrado)"
|
|
1328
|
+
$script:TargetResults += "$target`:SKIP"
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
"codex" {
|
|
1332
|
+
$codexTargetDir = Join-Path $script:SourceDir "targets\codex"
|
|
1333
|
+
$codexHome = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { "$homeDir\.codex" }
|
|
1334
|
+
if (Test-Path $codexTargetDir -PathType Container) {
|
|
1335
|
+
Remove-Item -Path "$codexHome\AGENTS.md" -Force -ErrorAction SilentlyContinue
|
|
1336
|
+
New-Item -ItemType Directory -Path $codexHome -Force | Out-Null
|
|
1337
|
+
|
|
1338
|
+
if (Test-Path "$codexTargetDir\agents.md") {
|
|
1339
|
+
Copy-Item -Path "$codexTargetDir\agents.md" -Destination "$codexHome\AGENTS.md" -Force
|
|
1340
|
+
}
|
|
1341
|
+
if (Test-Path "$codexTargetDir\config-mcp.toml") {
|
|
1342
|
+
$configFile = "$codexHome\config.toml"
|
|
1343
|
+
if (Test-Path $configFile) {
|
|
1344
|
+
$configContent = Get-Content $configFile -Raw
|
|
1345
|
+
$mcpContent = Get-Content "$codexTargetDir\config-mcp.toml" -Raw
|
|
1346
|
+
if ($configContent -match "# Neocortex MCP Servers") {
|
|
1347
|
+
$lines = Get-Content $configFile
|
|
1348
|
+
$markerIndex = ($lines | Select-String "# Neocortex MCP Servers" | Select-Object -First 1).LineNumber - 1
|
|
1349
|
+
$beforeSection = $lines[0..($markerIndex - 1)] -join "`n"
|
|
1350
|
+
Write-Utf8NoBom -Path $configFile -Content "$($beforeSection.TrimEnd())`n`n# Neocortex MCP Servers`n$mcpContent"
|
|
1351
|
+
} else {
|
|
1352
|
+
$existingContent = [System.IO.File]::ReadAllText($configFile, [System.Text.UTF8Encoding]::new($false))
|
|
1353
|
+
Write-Utf8NoBom -Path $configFile -Content "$existingContent`n# Neocortex MCP Servers`n$mcpContent"
|
|
1354
|
+
}
|
|
1355
|
+
} else {
|
|
1356
|
+
Write-Utf8NoBom -Path $configFile -Content "# Neocortex MCP Servers`n$mcpContent"
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
Write-Ok "codex"
|
|
1361
|
+
$script:TargetResults += "$target`:OK"
|
|
1362
|
+
$script:TargetCount++
|
|
1363
|
+
} else {
|
|
1364
|
+
Write-Warn "codex (adapter nao encontrado)"
|
|
1365
|
+
$script:TargetResults += "$target`:SKIP"
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
"antigravity" {
|
|
1369
|
+
$antiTargetDir = Join-Path $script:SourceDir "targets\antigravity"
|
|
1370
|
+
$geminiHome = if ($env:GEMINI_HOME) { $env:GEMINI_HOME } else { "$homeDir\.gemini" }
|
|
1371
|
+
if (Test-Path $antiTargetDir -PathType Container) {
|
|
1372
|
+
if (Test-Path "$geminiHome\antigravity") { Remove-Item -Path "$geminiHome\antigravity" -Recurse -Force -ErrorAction SilentlyContinue }
|
|
1373
|
+
|
|
1374
|
+
if (Test-Path "$antiTargetDir\skill\SKILL.md") {
|
|
1375
|
+
New-Item -ItemType Directory -Path "$homeDir\.agent\skills\neocortex" -Force | Out-Null
|
|
1376
|
+
Copy-Item -Path "$antiTargetDir\skill\SKILL.md" -Destination "$homeDir\.agent\skills\neocortex\SKILL.md" -Force
|
|
1377
|
+
}
|
|
1378
|
+
if (Test-Path "$antiTargetDir\rules" -PathType Container) {
|
|
1379
|
+
New-Item -ItemType Directory -Path "$homeDir\.agent\rules" -Force | Out-Null
|
|
1380
|
+
Copy-Item -Path "$antiTargetDir\rules\*.md" -Destination "$homeDir\.agent\rules\" -Force -ErrorAction SilentlyContinue
|
|
1381
|
+
}
|
|
1382
|
+
if (Test-Path "$antiTargetDir\workflows" -PathType Container) {
|
|
1383
|
+
New-Item -ItemType Directory -Path "$homeDir\.agent\workflows" -Force | Out-Null
|
|
1384
|
+
Copy-Item -Path "$antiTargetDir\workflows\*.md" -Destination "$homeDir\.agent\workflows\" -Force -ErrorAction SilentlyContinue
|
|
1385
|
+
}
|
|
1386
|
+
if (Test-Path "$antiTargetDir\mcp-config.json") {
|
|
1387
|
+
New-Item -ItemType Directory -Path "$geminiHome\antigravity" -Force | Out-Null
|
|
1388
|
+
Copy-Item -Path "$antiTargetDir\mcp-config.json" -Destination "$geminiHome\antigravity\mcp_config.json" -Force
|
|
1389
|
+
}
|
|
1390
|
+
if (Test-Path "$antiTargetDir\gemini.md") {
|
|
1391
|
+
Copy-Item -Path "$antiTargetDir\gemini.md" -Destination "$homeDir\GEMINI.md" -Force
|
|
1392
|
+
}
|
|
1393
|
+
$skillsSource = Join-Path $script:SourceDir "core\skills"
|
|
1394
|
+
if (Test-Path $skillsSource -PathType Container) {
|
|
1395
|
+
$skillsDest = "$homeDir\.agent\skills\neocortex\skills"
|
|
1396
|
+
New-Item -ItemType Directory -Path $skillsDest -Force | Out-Null
|
|
1397
|
+
Copy-Item -Path "$skillsSource\*" -Destination "$skillsDest\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
Write-Ok "antigravity"
|
|
1401
|
+
$script:TargetResults += "$target`:OK"
|
|
1402
|
+
$script:TargetCount++
|
|
1403
|
+
} else {
|
|
1404
|
+
Write-Warn "antigravity (adapter nao encontrado)"
|
|
1405
|
+
$script:TargetResults += "$target`:SKIP"
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
default {
|
|
1409
|
+
Write-Warn "'$target' nao reconhecido"
|
|
1410
|
+
$script:TargetResults += "$target`:SKIP"
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
# =============================================================================
|
|
1417
|
+
# CRIACAO DE DIRETORIOS DO PROJETO
|
|
1418
|
+
# =============================================================================
|
|
1419
|
+
|
|
1420
|
+
function New-ProjectDirectories {
|
|
1421
|
+
if ($QUIET_MODE -or $SKIP_PROJECT_DIRS) { return }
|
|
1422
|
+
|
|
1423
|
+
$shouldCreate = $false
|
|
1424
|
+
|
|
1425
|
+
if ($CreateProject -or $AUTO_YES) {
|
|
1426
|
+
$shouldCreate = $true
|
|
1427
|
+
} else {
|
|
1428
|
+
Write-Host " Instalar estrutura no projeto atual? [s/N]: " -NoNewline -ForegroundColor White
|
|
1429
|
+
$response = Read-HostWithTimeout -TimeoutSeconds 30 -Default "n"
|
|
1430
|
+
if ($response -match "^[sS]([iI][mM]?)?$|^[yY]([eE][sS]?)?$") { $shouldCreate = $true }
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
if (-not $shouldCreate) { return }
|
|
1434
|
+
|
|
1435
|
+
$projectDir = Get-Location
|
|
1436
|
+
|
|
1437
|
+
# Clean previous
|
|
1438
|
+
@("$projectDir\core", "$projectDir\targets\claude-code", "$projectDir\.cursor\skills",
|
|
1439
|
+
"$projectDir\.github\skills", "$projectDir\.agent\skills\neocortex",
|
|
1440
|
+
"$projectDir\.agents\skills", "$projectDir\.claude\agents\neocortex",
|
|
1441
|
+
"$projectDir\.claude\skills\neocortex") | ForEach-Object {
|
|
1442
|
+
if (Test-Path $_) { Remove-Item -Path $_ -Recurse -Force -ErrorAction SilentlyContinue }
|
|
1443
|
+
}
|
|
1444
|
+
@("$projectDir\.cursor\agents\neocortex.md", "$projectDir\.github\agents\neocortex.md",
|
|
1445
|
+
"$projectDir\.github\copilot-instructions.md", "$projectDir\AGENTS.md",
|
|
1446
|
+
"$projectDir\GEMINI.md") | ForEach-Object {
|
|
1447
|
+
if (Test-Path $_) { Remove-Item -Path $_ -Force -ErrorAction SilentlyContinue }
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
# Create base dirs
|
|
1451
|
+
@("$projectDir\.neocortex\specs", "$projectDir\.neocortex\planning",
|
|
1452
|
+
"$projectDir\docs\stories", "$projectDir\docs\epics", "$projectDir\docs\proposals") | ForEach-Object {
|
|
1453
|
+
New-Item -ItemType Directory -Path $_ -Force | Out-Null
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
# State template
|
|
1457
|
+
$stateTemplate = Join-Path $script:SourceDir "core\data\state-template.json"
|
|
1458
|
+
$stateTarget = "$projectDir\.neocortex\state.json"
|
|
1459
|
+
if (-not (Test-Path $stateTarget) -and (Test-Path $stateTemplate)) {
|
|
1460
|
+
Copy-Item -Path $stateTemplate -Destination $stateTarget -Force
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
# Core (ONLY in local mode)
|
|
1464
|
+
$coreSource = Join-Path $script:SourceDir "core"
|
|
1465
|
+
if ($LOCAL_MODE -and (Test-Path $coreSource -PathType Container)) {
|
|
1466
|
+
New-Item -ItemType Directory -Path "$projectDir\core" -Force | Out-Null
|
|
1467
|
+
Copy-Item -Path "$coreSource\*" -Destination "$projectDir\core\" -Recurse -Force
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
# Target-specific files
|
|
1471
|
+
$targetSummary = @()
|
|
1472
|
+
foreach ($target in $script:SelectedTargets) {
|
|
1473
|
+
switch ($target) {
|
|
1474
|
+
"claude-code" {
|
|
1475
|
+
$claudeTargetDir = Join-Path $script:SourceDir "targets\claude-code"
|
|
1476
|
+
if (Test-Path $claudeTargetDir -PathType Container) {
|
|
1477
|
+
$agentDest = "$projectDir\.claude\agents\neocortex"
|
|
1478
|
+
New-Item -ItemType Directory -Path $agentDest -Force | Out-Null
|
|
1479
|
+
|
|
1480
|
+
# SEMPRE copiar os 3 arquivos de interface
|
|
1481
|
+
# Tier 3: Copy only 2 stub files
|
|
1482
|
+
# Epic 64 (Story 64.2): Capture Copy-Silent return
|
|
1483
|
+
$r = Copy-Silent "$claudeTargetDir\neocortex.md" "$agentDest\"
|
|
1484
|
+
if (-not $r) { Write-Fail "Falha ao copiar neocortex.md (projeto)" }
|
|
1485
|
+
$r = Copy-Silent "$claudeTargetDir\neocortex.agent.yaml" "$agentDest\"
|
|
1486
|
+
if (-not $r) { Write-Fail "Falha ao copiar neocortex.agent.yaml (projeto)" }
|
|
1487
|
+
# Cleanup workflow.md from previous versions
|
|
1488
|
+
if (Test-Path "$agentDest\workflow.md") {
|
|
1489
|
+
Remove-Item "$agentDest\workflow.md" -Force -ErrorAction SilentlyContinue
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
if ($LOCAL_MODE) {
|
|
1493
|
+
# Modo local: copiar IP completa (comportamento legado)
|
|
1494
|
+
$r = Copy-Silent "$($script:SourceDir)\package.json" "$agentDest\"
|
|
1495
|
+
if (-not $r) { Write-Fail "Falha ao copiar package.json (projeto)" }
|
|
1496
|
+
$r = Copy-Silent "$($script:SourceDir)\README.md" "$agentDest\"
|
|
1497
|
+
if (-not $r) { Write-Fail "Falha ao copiar README.md (projeto)" }
|
|
1498
|
+
New-Item -ItemType Directory -Path "$agentDest\core" -Force | Out-Null
|
|
1499
|
+
Copy-Item -Path "$coreSource\*" -Destination "$agentDest\core\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1500
|
+
foreach ($folder in @("steps-c", "steps-e", "steps-p", "steps-r", "steps-u")) {
|
|
1501
|
+
$stepSrc = "$($script:SourceDir)\core\steps\$folder"
|
|
1502
|
+
if (Test-Path $stepSrc -PathType Container) {
|
|
1503
|
+
New-Item -ItemType Directory -Path "$agentDest\$folder" -Force | Out-Null
|
|
1504
|
+
Copy-Item -Path "$stepSrc\*" -Destination "$agentDest\$folder\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
$skillsSource = Join-Path $script:SourceDir "core\skills"
|
|
1508
|
+
if (Test-Path $skillsSource -PathType Container) {
|
|
1509
|
+
New-Item -ItemType Directory -Path "$projectDir\.claude\skills\neocortex" -Force | Out-Null
|
|
1510
|
+
Copy-Item -Path "$skillsSource\*" -Destination "$projectDir\.claude\skills\neocortex\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1511
|
+
}
|
|
1512
|
+
} else {
|
|
1513
|
+
# Tier 3 Remote Mode: limpar IP de versoes anteriores no projeto
|
|
1514
|
+
Invoke-AutoCleanupLegacyProject -ProjectDir $projectDir
|
|
1515
|
+
}
|
|
1516
|
+
$targetSummary += "claude-code"
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
"cursor" {
|
|
1520
|
+
$cursorTargetDir = Join-Path $script:SourceDir "targets\cursor"
|
|
1521
|
+
if (Test-Path $cursorTargetDir -PathType Container) {
|
|
1522
|
+
if (Test-Path "$cursorTargetDir\agent.md") {
|
|
1523
|
+
New-Item -ItemType Directory -Path "$projectDir\.cursor\agents" -Force | Out-Null
|
|
1524
|
+
Copy-Item -Path "$cursorTargetDir\agent.md" -Destination "$projectDir\.cursor\agents\neocortex.md" -Force
|
|
1525
|
+
}
|
|
1526
|
+
if (Test-Path "$cursorTargetDir\rules" -PathType Container) {
|
|
1527
|
+
New-Item -ItemType Directory -Path "$projectDir\.cursor\rules" -Force | Out-Null
|
|
1528
|
+
Copy-Item -Path "$cursorTargetDir\rules\*.mdc" -Destination "$projectDir\.cursor\rules\" -Force -ErrorAction SilentlyContinue
|
|
1529
|
+
}
|
|
1530
|
+
if (Test-Path "$cursorTargetDir\commands" -PathType Container) {
|
|
1531
|
+
New-Item -ItemType Directory -Path "$projectDir\.cursor\commands" -Force | Out-Null
|
|
1532
|
+
Copy-Item -Path "$cursorTargetDir\commands\*.md" -Destination "$projectDir\.cursor\commands\" -Force -ErrorAction SilentlyContinue
|
|
1533
|
+
}
|
|
1534
|
+
if (Test-Path "$cursorTargetDir\mcp.json") {
|
|
1535
|
+
Copy-Item -Path "$cursorTargetDir\mcp.json" -Destination "$projectDir\.cursor\mcp.json" -Force
|
|
1536
|
+
}
|
|
1537
|
+
$skillsSource = Join-Path $script:SourceDir "core\skills"
|
|
1538
|
+
if (Test-Path $skillsSource -PathType Container) {
|
|
1539
|
+
New-Item -ItemType Directory -Path "$projectDir\.cursor\skills" -Force | Out-Null
|
|
1540
|
+
Copy-Item -Path "$skillsSource\*" -Destination "$projectDir\.cursor\skills\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1541
|
+
}
|
|
1542
|
+
$targetSummary += "cursor"
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
"vscode" {
|
|
1546
|
+
$vscodeTargetDir = Join-Path $script:SourceDir "targets\vscode"
|
|
1547
|
+
if (Test-Path $vscodeTargetDir -PathType Container) {
|
|
1548
|
+
if (Test-Path "$vscodeTargetDir\agent.md") {
|
|
1549
|
+
New-Item -ItemType Directory -Path "$projectDir\.github\agents" -Force | Out-Null
|
|
1550
|
+
Copy-Item -Path "$vscodeTargetDir\agent.md" -Destination "$projectDir\.github\agents\neocortex.md" -Force
|
|
1551
|
+
}
|
|
1552
|
+
if (Test-Path "$vscodeTargetDir\instructions" -PathType Container) {
|
|
1553
|
+
New-Item -ItemType Directory -Path "$projectDir\.github\instructions" -Force | Out-Null
|
|
1554
|
+
Copy-Item -Path "$vscodeTargetDir\instructions\*.instructions.md" -Destination "$projectDir\.github\instructions\" -Force -ErrorAction SilentlyContinue
|
|
1555
|
+
}
|
|
1556
|
+
if (Test-Path "$vscodeTargetDir\prompts" -PathType Container) {
|
|
1557
|
+
New-Item -ItemType Directory -Path "$projectDir\.github\prompts" -Force | Out-Null
|
|
1558
|
+
Copy-Item -Path "$vscodeTargetDir\prompts\*.prompt.md" -Destination "$projectDir\.github\prompts\" -Force -ErrorAction SilentlyContinue
|
|
1559
|
+
}
|
|
1560
|
+
if (Test-Path "$vscodeTargetDir\mcp.json") {
|
|
1561
|
+
New-Item -ItemType Directory -Path "$projectDir\.vscode" -Force | Out-Null
|
|
1562
|
+
Copy-Item -Path "$vscodeTargetDir\mcp.json" -Destination "$projectDir\.vscode\mcp.json" -Force
|
|
1563
|
+
}
|
|
1564
|
+
if (Test-Path "$vscodeTargetDir\copilot-instructions.md") {
|
|
1565
|
+
Copy-Item -Path "$vscodeTargetDir\copilot-instructions.md" -Destination "$projectDir\.github\copilot-instructions.md" -Force
|
|
1566
|
+
}
|
|
1567
|
+
$skillsSource = Join-Path $script:SourceDir "core\skills"
|
|
1568
|
+
if (Test-Path $skillsSource -PathType Container) {
|
|
1569
|
+
New-Item -ItemType Directory -Path "$projectDir\.github\skills" -Force | Out-Null
|
|
1570
|
+
Copy-Item -Path "$skillsSource\*" -Destination "$projectDir\.github\skills\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1571
|
+
}
|
|
1572
|
+
$targetSummary += "vscode"
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
"gemini-cli" {
|
|
1576
|
+
$geminiTargetDir = Join-Path $script:SourceDir "targets\gemini-cli"
|
|
1577
|
+
if (Test-Path $geminiTargetDir -PathType Container) {
|
|
1578
|
+
if (Test-Path "$geminiTargetDir\gemini.md") { Copy-Item -Path "$geminiTargetDir\gemini.md" -Destination "$projectDir\GEMINI.md" -Force }
|
|
1579
|
+
if (Test-Path "$geminiTargetDir\commands" -PathType Container) {
|
|
1580
|
+
New-Item -ItemType Directory -Path "$projectDir\.gemini\commands" -Force | Out-Null
|
|
1581
|
+
Copy-Item -Path "$geminiTargetDir\commands\*.toml" -Destination "$projectDir\.gemini\commands\" -Force -ErrorAction SilentlyContinue
|
|
1582
|
+
}
|
|
1583
|
+
if (Test-Path "$geminiTargetDir\agent.md") {
|
|
1584
|
+
New-Item -ItemType Directory -Path "$projectDir\.gemini\agents" -Force | Out-Null
|
|
1585
|
+
Copy-Item -Path "$geminiTargetDir\agent.md" -Destination "$projectDir\.gemini\agents\neocortex.md" -Force
|
|
1586
|
+
}
|
|
1587
|
+
if (Test-Path "$geminiTargetDir\settings-mcp.json") {
|
|
1588
|
+
Copy-Item -Path "$geminiTargetDir\settings-mcp.json" -Destination "$projectDir\.gemini\settings-mcp.json" -Force
|
|
1589
|
+
}
|
|
1590
|
+
$targetSummary += "gemini-cli"
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
"codex" {
|
|
1594
|
+
$codexTargetDir = Join-Path $script:SourceDir "targets\codex"
|
|
1595
|
+
if (Test-Path $codexTargetDir -PathType Container) {
|
|
1596
|
+
if (Test-Path "$codexTargetDir\agents.md") { Copy-Item -Path "$codexTargetDir\agents.md" -Destination "$projectDir\AGENTS.md" -Force }
|
|
1597
|
+
$skillsSource = Join-Path $script:SourceDir "core\skills"
|
|
1598
|
+
if (Test-Path $skillsSource -PathType Container) {
|
|
1599
|
+
New-Item -ItemType Directory -Path "$projectDir\.agents\skills" -Force | Out-Null
|
|
1600
|
+
Copy-Item -Path "$skillsSource\*" -Destination "$projectDir\.agents\skills\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1601
|
+
}
|
|
1602
|
+
$targetSummary += "codex"
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
"antigravity" {
|
|
1606
|
+
$antiTargetDir = Join-Path $script:SourceDir "targets\antigravity"
|
|
1607
|
+
if (Test-Path $antiTargetDir -PathType Container) {
|
|
1608
|
+
if (Test-Path "$antiTargetDir\skill\SKILL.md") {
|
|
1609
|
+
New-Item -ItemType Directory -Path "$projectDir\.agent\skills\neocortex" -Force | Out-Null
|
|
1610
|
+
Copy-Item -Path "$antiTargetDir\skill\SKILL.md" -Destination "$projectDir\.agent\skills\neocortex\SKILL.md" -Force
|
|
1611
|
+
}
|
|
1612
|
+
if (Test-Path "$antiTargetDir\rules" -PathType Container) {
|
|
1613
|
+
New-Item -ItemType Directory -Path "$projectDir\.agent\rules" -Force | Out-Null
|
|
1614
|
+
Copy-Item -Path "$antiTargetDir\rules\*.md" -Destination "$projectDir\.agent\rules\" -Force -ErrorAction SilentlyContinue
|
|
1615
|
+
}
|
|
1616
|
+
if (Test-Path "$antiTargetDir\workflows" -PathType Container) {
|
|
1617
|
+
New-Item -ItemType Directory -Path "$projectDir\.agent\workflows" -Force | Out-Null
|
|
1618
|
+
Copy-Item -Path "$antiTargetDir\workflows\*.md" -Destination "$projectDir\.agent\workflows\" -Force -ErrorAction SilentlyContinue
|
|
1619
|
+
}
|
|
1620
|
+
if (Test-Path "$antiTargetDir\gemini.md") { Copy-Item -Path "$antiTargetDir\gemini.md" -Destination "$projectDir\GEMINI.md" -Force }
|
|
1621
|
+
$skillsSource = Join-Path $script:SourceDir "core\skills"
|
|
1622
|
+
if (Test-Path $skillsSource -PathType Container) {
|
|
1623
|
+
$skillsDest = "$projectDir\.agent\skills\neocortex\skills"
|
|
1624
|
+
New-Item -ItemType Directory -Path $skillsDest -Force | Out-Null
|
|
1625
|
+
Copy-Item -Path "$skillsSource\*" -Destination "$skillsDest\" -Recurse -Force -ErrorAction SilentlyContinue
|
|
1626
|
+
}
|
|
1627
|
+
$targetSummary += "antigravity"
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
Write-Host ""
|
|
1634
|
+
Write-Ok "Estrutura do projeto instalada ($($targetSummary -join ', '))"
|
|
1635
|
+
Write-Host ""
|
|
1636
|
+
Write-Info "Proximo passo: @neocortex *init @docs/epics.md"
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
# =============================================================================
|
|
1640
|
+
# RESULTADO
|
|
1641
|
+
# =============================================================================
|
|
1642
|
+
|
|
1643
|
+
function Show-Result {
|
|
1644
|
+
param([bool]$Success)
|
|
1645
|
+
if ($QUIET_MODE) { return $Success }
|
|
1646
|
+
|
|
1647
|
+
Write-Host ""
|
|
1648
|
+
Write-Host " ----------------------------------------" -ForegroundColor DarkGray
|
|
1649
|
+
|
|
1650
|
+
if ($Success) {
|
|
1651
|
+
Write-Host ""
|
|
1652
|
+
|
|
1653
|
+
# Success logo (brain/cortex shape, text centered vertically)
|
|
1654
|
+
Write-Host " #######" -ForegroundColor Cyan
|
|
1655
|
+
Write-Host " ### ########" -ForegroundColor Cyan
|
|
1656
|
+
Write-Host " ######### #####" -ForegroundColor Cyan
|
|
1657
|
+
Write-Host -NoNewline " ## ############## " -ForegroundColor Cyan
|
|
1658
|
+
Write-Host "N E O C O R T E X" -ForegroundColor White
|
|
1659
|
+
Write-Host -NoNewline " ## ### ###### ## " -ForegroundColor Cyan
|
|
1660
|
+
Write-Host "v$VERSION" -ForegroundColor White
|
|
1661
|
+
Write-Host " ## ### ### ##" -ForegroundColor Cyan
|
|
1662
|
+
Write-Host -NoNewline " ## ###### ### ## " -ForegroundColor Cyan
|
|
1663
|
+
Write-Host "Installation complete!" -ForegroundColor Green
|
|
1664
|
+
Write-Host -NoNewline " ############### ## " -ForegroundColor Cyan
|
|
1665
|
+
Write-Host "OrNexus Team" -ForegroundColor DarkGray
|
|
1666
|
+
Write-Host " ##### ########" -ForegroundColor Cyan
|
|
1667
|
+
Write-Host " ######## ##" -ForegroundColor Cyan
|
|
1668
|
+
Write-Host " #######" -ForegroundColor Cyan
|
|
1669
|
+
Write-Host ""
|
|
1670
|
+
|
|
1671
|
+
# Story 66.4 AC6: Target count
|
|
1672
|
+
$okTargets = ($script:TargetResults | Where-Object { $_ -match ":OK$" }).Count
|
|
1673
|
+
if ($okTargets -gt 0) {
|
|
1674
|
+
Write-Host " $okTargets plataforma(s) instalada(s)" -ForegroundColor DarkGray
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
if ($LOCAL_MODE) {
|
|
1678
|
+
Write-Host " Modo: Local (IP completa copiada)" -ForegroundColor DarkGray
|
|
1679
|
+
Write-Host " Locais:" -ForegroundColor DarkGray
|
|
1680
|
+
Write-Host " Agente: ~\.claude\agents\neocortex\" -ForegroundColor DarkGray
|
|
1681
|
+
Write-Host " Skills: ~\.claude\skills\neocortex\" -ForegroundColor DarkGray
|
|
1682
|
+
} else {
|
|
1683
|
+
Write-Host " Mode: Remote (thin client)" -ForegroundColor DarkGray
|
|
1684
|
+
Write-Host " Status: Ready to activate" -ForegroundColor DarkGray
|
|
1685
|
+
Write-Host ""
|
|
1686
|
+
Write-Host " Activate your license:" -ForegroundColor DarkGray
|
|
1687
|
+
Write-Host " neocortex activate YOUR-LICENSE-KEY" -ForegroundColor Cyan
|
|
1688
|
+
Write-Host ""
|
|
1689
|
+
Write-Host " Get your key at: https://neocortex.ornexus.com/login" -ForegroundColor DarkGray
|
|
1690
|
+
Write-Host ""
|
|
1691
|
+
Write-Host " After activation:" -ForegroundColor DarkGray
|
|
1692
|
+
Write-Host " @neocortex *menu" -ForegroundColor Cyan
|
|
1693
|
+
}
|
|
1694
|
+
Write-Host ""
|
|
1695
|
+
Write-Host " Proximo passo:" -ForegroundColor DarkGray
|
|
1696
|
+
Write-Host " @neocortex *init @docs/epics.md" -ForegroundColor Cyan
|
|
1697
|
+
Write-Host ""
|
|
1698
|
+
return $true
|
|
1699
|
+
} else {
|
|
1700
|
+
Write-Host ""
|
|
1701
|
+
Write-Host " Instalacao com problemas" -ForegroundColor Red
|
|
1702
|
+
Write-Host ""
|
|
1703
|
+
# Story 66.4 AC5: Windows troubleshooting
|
|
1704
|
+
Write-Host " Execute novamente com " -NoNewline
|
|
1705
|
+
Write-Host "-Debug" -ForegroundColor White -NoNewline
|
|
1706
|
+
Write-Host " para detalhes:"
|
|
1707
|
+
Write-Host " npx @ornexus/neocortex -Debug" -ForegroundColor Yellow
|
|
1708
|
+
Write-Host ""
|
|
1709
|
+
return $false
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
# =============================================================================
|
|
1714
|
+
# MAIN
|
|
1715
|
+
# =============================================================================
|
|
1716
|
+
|
|
1717
|
+
Show-Banner
|
|
1718
|
+
Get-SourceDirectory
|
|
1719
|
+
Test-OldInstallation
|
|
1720
|
+
|
|
1721
|
+
# Determine targets
|
|
1722
|
+
if ($Targets) {
|
|
1723
|
+
$script:SelectedTargets = $Targets -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ }
|
|
1724
|
+
$invalid = $script:SelectedTargets | Where-Object { $_ -notin $script:ValidTargets }
|
|
1725
|
+
if ($invalid) {
|
|
1726
|
+
Write-Fail "Plataformas invalidas: $($invalid -join ', ')"
|
|
1727
|
+
Write-Host " Validas: $($script:ValidTargets -join ', ')"
|
|
1728
|
+
exit 1
|
|
1729
|
+
}
|
|
1730
|
+
} elseif ($Yes) {
|
|
1731
|
+
$script:SelectedTargets = @("claude-code")
|
|
1732
|
+
} else {
|
|
1733
|
+
$script:SelectedTargets = @("claude-code")
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
Write-Dbg "Targets: $($script:SelectedTargets -join ', ')"
|
|
1737
|
+
|
|
1738
|
+
$totalSteps = 4
|
|
1739
|
+
if ($script:SelectedTargets -contains "claude-code") { $totalSteps = 6 }
|
|
1740
|
+
|
|
1741
|
+
# Step 1: Limpeza automatica de versoes anteriores
|
|
1742
|
+
Write-Step 1 $totalSteps "Limpeza de versoes anteriores"
|
|
1743
|
+
Invoke-AutoCleanupLegacy
|
|
1744
|
+
|
|
1745
|
+
# Step 2: Core
|
|
1746
|
+
Write-Step 2 $totalSteps "Instalando core"
|
|
1747
|
+
$coreSuccess = Install-Core
|
|
1748
|
+
|
|
1749
|
+
if (-not $coreSuccess) {
|
|
1750
|
+
Write-Fail "Falha na instalacao do core"
|
|
1751
|
+
exit 1
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
# Step 3: Skills
|
|
1755
|
+
Write-Step 3 $totalSteps "Instalando skills"
|
|
1756
|
+
Install-Skills | Out-Null
|
|
1757
|
+
|
|
1758
|
+
# Step 4: Targets
|
|
1759
|
+
Write-Step 4 $totalSteps "Instalando $($script:SelectedTargets.Count) plataforma(s)"
|
|
1760
|
+
Install-Targets -TargetList $script:SelectedTargets
|
|
1761
|
+
|
|
1762
|
+
# Step 5-6: Claude Code extras
|
|
1763
|
+
if ($script:SelectedTargets -contains "claude-code") {
|
|
1764
|
+
Import-EnvFile | Out-Null
|
|
1765
|
+
Request-Tokens
|
|
1766
|
+
|
|
1767
|
+
Write-Step 5 $totalSteps "Configurando MCPs"
|
|
1768
|
+
Install-MCPs
|
|
1769
|
+
|
|
1770
|
+
Write-Step 6 $totalSteps "Verificando ferramentas"
|
|
1771
|
+
Install-CodeRabbit
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
$installSuccess = ($script:TargetResults | Where-Object { $_ -match ":FAIL$" }).Count -eq 0
|
|
1775
|
+
$verifySuccess = Verify-Installation
|
|
1776
|
+
$installSuccess = $installSuccess -and $verifySuccess
|
|
1777
|
+
|
|
1778
|
+
if (Show-Result $installSuccess) {
|
|
1779
|
+
$projectSources = Test-ProjectMigrationNeeds
|
|
1780
|
+
if ($projectSources) {
|
|
1781
|
+
Write-Warn "Migracao detectada"
|
|
1782
|
+
Write-Info "Execute: @neocortex *init @docs/epics.md para migrar"
|
|
1783
|
+
}
|
|
1784
|
+
New-ProjectDirectories
|
|
1785
|
+
Write-Host " Desenvolvido por OrNexus Team" -ForegroundColor DarkGray
|
|
1786
|
+
Write-Host ""
|
|
1787
|
+
exit 0
|
|
1788
|
+
} else {
|
|
1789
|
+
exit 1
|
|
1790
|
+
}
|