@ornexus/neocortex 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/LICENSE +56 -0
  2. package/README.md +661 -0
  3. package/install.js +453 -0
  4. package/install.ps1 +1478 -0
  5. package/install.sh +1409 -0
  6. package/package.json +93 -0
  7. package/packages/client/dist/adapters/adapter-registry.d.ts +62 -0
  8. package/packages/client/dist/adapters/adapter-registry.d.ts.map +1 -0
  9. package/packages/client/dist/adapters/adapter-registry.js +107 -0
  10. package/packages/client/dist/adapters/adapter-registry.js.map +1 -0
  11. package/packages/client/dist/adapters/antigravity-adapter.d.ts +19 -0
  12. package/packages/client/dist/adapters/antigravity-adapter.d.ts.map +1 -0
  13. package/packages/client/dist/adapters/antigravity-adapter.js +78 -0
  14. package/packages/client/dist/adapters/antigravity-adapter.js.map +1 -0
  15. package/packages/client/dist/adapters/claude-code-adapter.d.ts +20 -0
  16. package/packages/client/dist/adapters/claude-code-adapter.d.ts.map +1 -0
  17. package/packages/client/dist/adapters/claude-code-adapter.js +80 -0
  18. package/packages/client/dist/adapters/claude-code-adapter.js.map +1 -0
  19. package/packages/client/dist/adapters/codex-adapter.d.ts +20 -0
  20. package/packages/client/dist/adapters/codex-adapter.d.ts.map +1 -0
  21. package/packages/client/dist/adapters/codex-adapter.js +81 -0
  22. package/packages/client/dist/adapters/codex-adapter.js.map +1 -0
  23. package/packages/client/dist/adapters/cursor-adapter.d.ts +20 -0
  24. package/packages/client/dist/adapters/cursor-adapter.d.ts.map +1 -0
  25. package/packages/client/dist/adapters/cursor-adapter.js +116 -0
  26. package/packages/client/dist/adapters/cursor-adapter.js.map +1 -0
  27. package/packages/client/dist/adapters/gemini-adapter.d.ts +19 -0
  28. package/packages/client/dist/adapters/gemini-adapter.d.ts.map +1 -0
  29. package/packages/client/dist/adapters/gemini-adapter.js +72 -0
  30. package/packages/client/dist/adapters/gemini-adapter.js.map +1 -0
  31. package/packages/client/dist/adapters/index.d.ts +20 -0
  32. package/packages/client/dist/adapters/index.d.ts.map +1 -0
  33. package/packages/client/dist/adapters/index.js +22 -0
  34. package/packages/client/dist/adapters/index.js.map +1 -0
  35. package/packages/client/dist/adapters/platform-detector.d.ts +47 -0
  36. package/packages/client/dist/adapters/platform-detector.d.ts.map +1 -0
  37. package/packages/client/dist/adapters/platform-detector.js +107 -0
  38. package/packages/client/dist/adapters/platform-detector.js.map +1 -0
  39. package/packages/client/dist/adapters/target-adapter.d.ts +71 -0
  40. package/packages/client/dist/adapters/target-adapter.d.ts.map +1 -0
  41. package/packages/client/dist/adapters/target-adapter.js +13 -0
  42. package/packages/client/dist/adapters/target-adapter.js.map +1 -0
  43. package/packages/client/dist/adapters/vscode-adapter.d.ts +20 -0
  44. package/packages/client/dist/adapters/vscode-adapter.d.ts.map +1 -0
  45. package/packages/client/dist/adapters/vscode-adapter.js +73 -0
  46. package/packages/client/dist/adapters/vscode-adapter.js.map +1 -0
  47. package/packages/client/dist/cache/crypto-utils.d.ts +31 -0
  48. package/packages/client/dist/cache/crypto-utils.d.ts.map +1 -0
  49. package/packages/client/dist/cache/crypto-utils.js +77 -0
  50. package/packages/client/dist/cache/crypto-utils.js.map +1 -0
  51. package/packages/client/dist/cache/encrypted-cache.d.ts +31 -0
  52. package/packages/client/dist/cache/encrypted-cache.d.ts.map +1 -0
  53. package/packages/client/dist/cache/encrypted-cache.js +92 -0
  54. package/packages/client/dist/cache/encrypted-cache.js.map +1 -0
  55. package/packages/client/dist/cache/index.d.ts +14 -0
  56. package/packages/client/dist/cache/index.d.ts.map +1 -0
  57. package/packages/client/dist/cache/index.js +14 -0
  58. package/packages/client/dist/cache/index.js.map +1 -0
  59. package/packages/client/dist/cli.d.ts +15 -0
  60. package/packages/client/dist/cli.d.ts.map +1 -0
  61. package/packages/client/dist/cli.js +182 -0
  62. package/packages/client/dist/cli.js.map +1 -0
  63. package/packages/client/dist/commands/activate.d.ts +48 -0
  64. package/packages/client/dist/commands/activate.d.ts.map +1 -0
  65. package/packages/client/dist/commands/activate.js +186 -0
  66. package/packages/client/dist/commands/activate.js.map +1 -0
  67. package/packages/client/dist/commands/cache-status.d.ts +40 -0
  68. package/packages/client/dist/commands/cache-status.d.ts.map +1 -0
  69. package/packages/client/dist/commands/cache-status.js +113 -0
  70. package/packages/client/dist/commands/cache-status.js.map +1 -0
  71. package/packages/client/dist/commands/invoke.d.ts +71 -0
  72. package/packages/client/dist/commands/invoke.d.ts.map +1 -0
  73. package/packages/client/dist/commands/invoke.js +345 -0
  74. package/packages/client/dist/commands/invoke.js.map +1 -0
  75. package/packages/client/dist/config/resolver-selection.d.ts +41 -0
  76. package/packages/client/dist/config/resolver-selection.d.ts.map +1 -0
  77. package/packages/client/dist/config/resolver-selection.js +278 -0
  78. package/packages/client/dist/config/resolver-selection.js.map +1 -0
  79. package/packages/client/dist/context/context-collector.d.ts +29 -0
  80. package/packages/client/dist/context/context-collector.d.ts.map +1 -0
  81. package/packages/client/dist/context/context-collector.js +223 -0
  82. package/packages/client/dist/context/context-collector.js.map +1 -0
  83. package/packages/client/dist/context/context-sanitizer.d.ts +29 -0
  84. package/packages/client/dist/context/context-sanitizer.d.ts.map +1 -0
  85. package/packages/client/dist/context/context-sanitizer.js +146 -0
  86. package/packages/client/dist/context/context-sanitizer.js.map +1 -0
  87. package/packages/client/dist/index.d.ts +55 -0
  88. package/packages/client/dist/index.d.ts.map +1 -0
  89. package/packages/client/dist/index.js +37 -0
  90. package/packages/client/dist/index.js.map +1 -0
  91. package/packages/client/dist/license/index.d.ts +6 -0
  92. package/packages/client/dist/license/index.d.ts.map +1 -0
  93. package/packages/client/dist/license/index.js +6 -0
  94. package/packages/client/dist/license/index.js.map +1 -0
  95. package/packages/client/dist/license/license-client.d.ts +53 -0
  96. package/packages/client/dist/license/license-client.d.ts.map +1 -0
  97. package/packages/client/dist/license/license-client.js +164 -0
  98. package/packages/client/dist/license/license-client.js.map +1 -0
  99. package/packages/client/dist/machine/fingerprint.d.ts +24 -0
  100. package/packages/client/dist/machine/fingerprint.d.ts.map +1 -0
  101. package/packages/client/dist/machine/fingerprint.js +61 -0
  102. package/packages/client/dist/machine/fingerprint.js.map +1 -0
  103. package/packages/client/dist/machine/index.d.ts +6 -0
  104. package/packages/client/dist/machine/index.d.ts.map +1 -0
  105. package/packages/client/dist/machine/index.js +6 -0
  106. package/packages/client/dist/machine/index.js.map +1 -0
  107. package/packages/client/dist/resilience/circuit-breaker.d.ts +71 -0
  108. package/packages/client/dist/resilience/circuit-breaker.d.ts.map +1 -0
  109. package/packages/client/dist/resilience/circuit-breaker.js +171 -0
  110. package/packages/client/dist/resilience/circuit-breaker.js.map +1 -0
  111. package/packages/client/dist/resilience/degradation-manager.d.ts +68 -0
  112. package/packages/client/dist/resilience/degradation-manager.d.ts.map +1 -0
  113. package/packages/client/dist/resilience/degradation-manager.js +165 -0
  114. package/packages/client/dist/resilience/degradation-manager.js.map +1 -0
  115. package/packages/client/dist/resilience/freshness-indicator.d.ts +60 -0
  116. package/packages/client/dist/resilience/freshness-indicator.d.ts.map +1 -0
  117. package/packages/client/dist/resilience/freshness-indicator.js +101 -0
  118. package/packages/client/dist/resilience/freshness-indicator.js.map +1 -0
  119. package/packages/client/dist/resilience/index.d.ts +9 -0
  120. package/packages/client/dist/resilience/index.d.ts.map +1 -0
  121. package/packages/client/dist/resilience/index.js +9 -0
  122. package/packages/client/dist/resilience/index.js.map +1 -0
  123. package/packages/client/dist/resilience/recovery-detector.d.ts +60 -0
  124. package/packages/client/dist/resilience/recovery-detector.d.ts.map +1 -0
  125. package/packages/client/dist/resilience/recovery-detector.js +75 -0
  126. package/packages/client/dist/resilience/recovery-detector.js.map +1 -0
  127. package/packages/client/dist/resolvers/asset-resolver.d.ts +80 -0
  128. package/packages/client/dist/resolvers/asset-resolver.d.ts.map +1 -0
  129. package/packages/client/dist/resolvers/asset-resolver.js +14 -0
  130. package/packages/client/dist/resolvers/asset-resolver.js.map +1 -0
  131. package/packages/client/dist/resolvers/local-resolver.d.ts +27 -0
  132. package/packages/client/dist/resolvers/local-resolver.d.ts.map +1 -0
  133. package/packages/client/dist/resolvers/local-resolver.js +219 -0
  134. package/packages/client/dist/resolvers/local-resolver.js.map +1 -0
  135. package/packages/client/dist/resolvers/remote-resolver.d.ts +63 -0
  136. package/packages/client/dist/resolvers/remote-resolver.d.ts.map +1 -0
  137. package/packages/client/dist/resolvers/remote-resolver.js +207 -0
  138. package/packages/client/dist/resolvers/remote-resolver.js.map +1 -0
  139. package/packages/client/dist/telemetry/index.d.ts +6 -0
  140. package/packages/client/dist/telemetry/index.d.ts.map +1 -0
  141. package/packages/client/dist/telemetry/index.js +6 -0
  142. package/packages/client/dist/telemetry/index.js.map +1 -0
  143. package/packages/client/dist/telemetry/offline-queue.d.ts +58 -0
  144. package/packages/client/dist/telemetry/offline-queue.d.ts.map +1 -0
  145. package/packages/client/dist/telemetry/offline-queue.js +132 -0
  146. package/packages/client/dist/telemetry/offline-queue.js.map +1 -0
  147. package/packages/client/dist/types/index.d.ts +141 -0
  148. package/packages/client/dist/types/index.d.ts.map +1 -0
  149. package/packages/client/dist/types/index.js +39 -0
  150. package/packages/client/dist/types/index.js.map +1 -0
  151. package/targets-stubs/antigravity/README.md +20 -0
  152. package/targets-stubs/claude-code/README.md +20 -0
  153. package/targets-stubs/codex/README.md +20 -0
  154. package/targets-stubs/cursor/README.md +20 -0
  155. package/targets-stubs/gemini-cli/README.md +20 -0
  156. package/targets-stubs/vscode/README.md +20 -0
package/install.sh ADDED
@@ -0,0 +1,1409 @@
1
+ #!/bin/bash
2
+
3
+ # Neocortex - Instalador Unix
4
+ # Epic & Story Development Orchestrator
5
+
6
+ # Versao do instalador
7
+ VERSION="3.8.0"
8
+
9
+ # Flags
10
+ MIGRATION_DETECTED=false
11
+ MIGRATION_SOURCES=""
12
+ CODERABBIT_INSTALLED=false
13
+ LEGACY_ITEMS=""
14
+ LEGACY_WARNINGS=0
15
+ SELECTED_TARGETS=""
16
+ VALID_TARGETS="claude-code cursor vscode gemini-cli codex antigravity"
17
+ LOCAL_MODE=false
18
+ NEOCORTEX_SERVER_URL="https://api.neocortex.ornexus.com"
19
+
20
+ # =============================================================================
21
+ # DETECCAO DE AMBIENTE
22
+ # =============================================================================
23
+
24
+ is_interactive() { [ -t 0 ] && [ -t 1 ]; }
25
+
26
+ supports_colors() { [ -t 1 ] && [ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]; }
27
+
28
+ supports_unicode() {
29
+ case "${LANG:-}${LC_ALL:-}${LC_CTYPE:-}" in
30
+ *UTF-8*|*utf-8*|*utf8*) return 0 ;;
31
+ *) return 1 ;;
32
+ esac
33
+ }
34
+
35
+ if [ -z "$HOME" ]; then
36
+ HOME=$(getent passwd "$(whoami)" | cut -d: -f6 2>/dev/null || echo "/root")
37
+ export HOME
38
+ fi
39
+
40
+ # =============================================================================
41
+ # PARSING DE ARGUMENTOS
42
+ # =============================================================================
43
+
44
+ AUTO_YES=false
45
+ DEBUG_MODE=false
46
+ SKIP_PROJECT_DIRS=false
47
+ CREATE_PROJECT=false
48
+ QUIET_MODE=false
49
+ NO_BANNER=false
50
+ CLEANUP_LEGACY=false
51
+
52
+ while [[ $# -gt 0 ]]; do
53
+ case $1 in
54
+ -y|--yes) AUTO_YES=true; shift ;;
55
+ -d|--debug) DEBUG_MODE=true; shift ;;
56
+ -s|--skip-project) SKIP_PROJECT_DIRS=true; shift ;;
57
+ -q|--quiet) QUIET_MODE=true; shift ;;
58
+ --no-banner) NO_BANNER=true; shift ;;
59
+ --cleanup-legacy) CLEANUP_LEGACY=true; shift ;;
60
+ --targets=*) SELECTED_TARGETS="${1#--targets=}"; shift ;;
61
+ --create-project) CREATE_PROJECT=true; shift ;;
62
+ --local) LOCAL_MODE=true; shift ;;
63
+ --server-url=*) NEOCORTEX_SERVER_URL="${1#--server-url=}"; shift ;;
64
+ -h|--help)
65
+ echo ""
66
+ echo " Neocortex Installer v${VERSION}"
67
+ echo " Epic & Story Development Orchestrator"
68
+ echo ""
69
+ echo " Uso: npx @ornexus/neocortex [opcoes]"
70
+ echo ""
71
+ echo " Opcoes:"
72
+ echo " -y, --yes Modo automatico (Claude Code only)"
73
+ echo " --targets=<lista> Plataformas separadas por virgula"
74
+ echo " --create-project Instalar estrutura no projeto"
75
+ echo " -s, --skip-project Nao perguntar sobre projeto"
76
+ echo " -q, --quiet Modo silencioso"
77
+ echo " --cleanup-legacy Remover artefatos legados de ~/.claude/"
78
+ echo " --local Modo local (copia IP para desenvolvimento)"
79
+ echo " --server-url=<url> URL do server Neocortex (padrao: api.neocortex.ornexus.com)"
80
+ echo " -d, --debug Modo debug"
81
+ echo " -h, --help Mostra esta ajuda"
82
+ echo ""
83
+ echo " Plataformas: claude-code, cursor, vscode, gemini-cli, codex, antigravity"
84
+ exit 0
85
+ ;;
86
+ *) shift ;;
87
+ esac
88
+ done
89
+
90
+ if ! is_interactive; then
91
+ AUTO_YES=true
92
+ fi
93
+
94
+ # =============================================================================
95
+ # CORES E SIMBOLOS
96
+ # =============================================================================
97
+
98
+ if supports_colors && [ "$QUIET_MODE" = false ]; then
99
+ RED='\033[0;31m'
100
+ GREEN='\033[0;32m'
101
+ YELLOW='\033[1;33m'
102
+ BLUE='\033[0;34m'
103
+ MAGENTA='\033[0;35m'
104
+ CYAN='\033[0;36m'
105
+ WHITE='\033[1;37m'
106
+ GRAY='\033[0;90m'
107
+ BOLD='\033[1m'
108
+ DIM='\033[2m'
109
+ NC='\033[0m'
110
+ else
111
+ RED='' GREEN='' YELLOW='' BLUE='' MAGENTA='' CYAN=''
112
+ WHITE='' GRAY='' BOLD='' DIM='' NC=''
113
+ fi
114
+
115
+ if supports_unicode; then
116
+ SYM_OK="✓"
117
+ SYM_FAIL="✗"
118
+ SYM_WARN="!"
119
+ SYM_ARROW="→"
120
+ SYM_DOT="·"
121
+ SYM_SPINNER_FRAMES=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
122
+ else
123
+ SYM_OK="ok"
124
+ SYM_FAIL="x"
125
+ SYM_WARN="!"
126
+ SYM_ARROW="->"
127
+ SYM_DOT="."
128
+ SYM_SPINNER_FRAMES=('|' '/' '-' '\')
129
+ fi
130
+
131
+ # =============================================================================
132
+ # FUNCOES DE LOG
133
+ # =============================================================================
134
+
135
+ # Step header: [1/5] Installing core...
136
+ step() {
137
+ local num=$1 total=$2 msg=$3
138
+ echo ""
139
+ echo -e " ${BOLD}${CYAN}[$num/$total]${NC} ${BOLD}$msg${NC}"
140
+ }
141
+
142
+ # Success line
143
+ ok() { echo -e " ${GREEN}${SYM_OK}${NC} $1"; }
144
+
145
+ # Warning line
146
+ warn() { echo -e " ${YELLOW}${SYM_WARN}${NC} $1"; }
147
+
148
+ # Error line
149
+ fail() { echo -e " ${RED}${SYM_FAIL}${NC} $1"; }
150
+
151
+ # Info line
152
+ info() { echo -e " ${DIM}${SYM_ARROW} $1${NC}"; }
153
+
154
+ # Debug line
155
+ debug() { [ "$DEBUG_MODE" = true ] && echo -e " ${GRAY}[debug] $1${NC}"; }
156
+
157
+ # Spinner for background tasks
158
+ run_with_spinner() {
159
+ local msg="$1"
160
+ shift
161
+ "$@" &
162
+ local pid=$!
163
+ local i=0
164
+ local len=${#SYM_SPINNER_FRAMES[@]}
165
+
166
+ while kill -0 "$pid" 2>/dev/null; do
167
+ printf "\r ${CYAN}%s${NC} %s" "${SYM_SPINNER_FRAMES[$((i % len))]}" "$msg"
168
+ i=$((i + 1))
169
+ sleep 0.08
170
+ done
171
+
172
+ wait "$pid"
173
+ local exit_code=$?
174
+
175
+ if [ $exit_code -eq 0 ]; then
176
+ printf "\r ${GREEN}${SYM_OK}${NC} %s\n" "$msg"
177
+ else
178
+ printf "\r ${RED}${SYM_FAIL}${NC} %s\n" "$msg"
179
+ fi
180
+
181
+ return $exit_code
182
+ }
183
+
184
+ # =============================================================================
185
+ # FUNCOES DE COPIA (silenciosas - sem log individual)
186
+ # =============================================================================
187
+
188
+ copy_file() {
189
+ local src="$1" dest="$2"
190
+ debug "Copiando: $src -> $dest"
191
+ [ -f "$src" ] && cp "$src" "$dest" 2>/dev/null
192
+ }
193
+
194
+ copy_dir() {
195
+ local src="$1" dest="$2"
196
+ debug "Copiando dir: $src -> $dest"
197
+ [ -d "$src" ] && cp -r "$src" "$dest" 2>/dev/null
198
+ }
199
+
200
+ # =============================================================================
201
+ # DETECCAO DE VERSAO ANTIGA
202
+ # =============================================================================
203
+
204
+ detect_old_installation() {
205
+ debug "Verificando instalacoes antigas..."
206
+
207
+ local dest_dir="${HOME}/.claude/agents/neocortex"
208
+
209
+ if [ -f "$dest_dir/.version" ]; then
210
+ INSTALLED_VERSION=$(cat "$dest_dir/.version" 2>/dev/null)
211
+ local new_version=""
212
+ if [ -f "$SOURCE_DIR/package.json" ]; then
213
+ new_version=$(grep '"version"' "$SOURCE_DIR/package.json" 2>/dev/null | head -1 | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
214
+ fi
215
+ if [ -n "$INSTALLED_VERSION" ] && [ -n "$new_version" ]; then
216
+ if [ "$INSTALLED_VERSION" = "$new_version" ]; then
217
+ info "Reinstalando v$new_version"
218
+ else
219
+ info "Atualizando v$INSTALLED_VERSION ${SYM_ARROW} v$new_version"
220
+ fi
221
+ fi
222
+ fi
223
+
224
+ # Check for old files
225
+ local old_files=()
226
+ if [ -f "$dest_dir/step-registry.json" ]; then
227
+ if ! grep -q "state.json" "$dest_dir/workflow.md" 2>/dev/null; then
228
+ old_files+=("workflow antigo")
229
+ fi
230
+ fi
231
+
232
+ if grep -r "orchestrator.db" "$dest_dir" 2>/dev/null | grep -v "backup" | grep -v "migrated" > /dev/null; then
233
+ old_files+=("referencias SQLite")
234
+ fi
235
+
236
+ if [ ${#old_files[@]} -gt 0 ]; then
237
+ MIGRATION_DETECTED=true
238
+ MIGRATION_SOURCES="${old_files[*]}"
239
+ debug "Detectado: $MIGRATION_SOURCES"
240
+ fi
241
+ }
242
+
243
+ detect_legacy_artifacts() {
244
+ local warnings=0
245
+ local legacy_items=""
246
+ local claude_dir="$HOME/.claude"
247
+
248
+ debug "Verificando artefatos legados em ~/.claude/..."
249
+
250
+ # Check 1: .git inside agents/ (leftover from contains-studio/agents repo)
251
+ if [ -d "$claude_dir/agents/.git" ]; then
252
+ warn "Repositorio .git detectado em ~/.claude/agents/"
253
+ info "Pode conflitar com instalacoes do Neocortex"
254
+ info "Execute com --cleanup-legacy para remover"
255
+ legacy_items="${legacy_items}${claude_dir}/agents/.git
256
+ "
257
+ warnings=$((warnings + 1))
258
+ fi
259
+
260
+ # Check 2: Nested .claude/.claude/ (BMAD installation error)
261
+ if [ -d "$claude_dir/.claude" ]; then
262
+ warn "Diretorio aninhado detectado: ~/.claude/.claude/"
263
+ info "Possivelmente erro de instalacao anterior (BMAD)"
264
+ info "Execute com --cleanup-legacy para remover"
265
+ legacy_items="${legacy_items}${claude_dir}/.claude
266
+ "
267
+ warnings=$((warnings + 1))
268
+ fi
269
+
270
+ # Check 3: Loose agents without namespace (files directly in agents/, not in subdirs)
271
+ local loose_count=0
272
+ if [ -d "$claude_dir/agents" ]; then
273
+ for f in "$claude_dir/agents"/*.md; do
274
+ [ -f "$f" ] || continue
275
+ loose_count=$((loose_count + 1))
276
+ debug " Solto: $(basename "$f")"
277
+ done
278
+ fi
279
+ if [ $loose_count -gt 0 ]; then
280
+ info "$loose_count arquivo(s) .md solto(s) em ~/.claude/agents/"
281
+ info "Considere organizar em namespaces (ex: agents/neocortex/)"
282
+ warnings=$((warnings + 1))
283
+ fi
284
+
285
+ # Check 4: Legacy agents-ldtn/ directory
286
+ if [ -d "$claude_dir/agents-ldtn" ]; then
287
+ warn "Diretorio legado detectado: ~/.claude/agents-ldtn/"
288
+ info "Execute com --cleanup-legacy para remover"
289
+ legacy_items="${legacy_items}${claude_dir}/agents-ldtn
290
+ "
291
+ warnings=$((warnings + 1))
292
+ fi
293
+
294
+ # Check 5: .superclaude-metadata.json
295
+ if [ -f "$claude_dir/.superclaude-metadata.json" ]; then
296
+ warn "Metadata legado detectado: ~/.claude/.superclaude-metadata.json"
297
+ info "Execute com --cleanup-legacy para remover"
298
+ legacy_items="${legacy_items}${claude_dir}/.superclaude-metadata.json
299
+ "
300
+ warnings=$((warnings + 1))
301
+ fi
302
+
303
+ # Check 6: superclaude_backup_*.tar.gz in backups/
304
+ local backup_count=0
305
+ if [ -d "$claude_dir/backups" ]; then
306
+ for f in "$claude_dir/backups"/superclaude_backup_*.tar.gz; do
307
+ [ -f "$f" ] || continue
308
+ backup_count=$((backup_count + 1))
309
+ done
310
+ fi
311
+ if [ $backup_count -gt 0 ]; then
312
+ info "$backup_count backup(s) SuperClaude antigo(s) em ~/.claude/backups/"
313
+ warnings=$((warnings + 1))
314
+ fi
315
+
316
+ if [ $warnings -gt 0 ]; then
317
+ warn "$warnings artefato(s) legado(s) detectado(s)"
318
+ fi
319
+
320
+ # Export for cleanup (newline-separated for paths with spaces)
321
+ LEGACY_ITEMS="$legacy_items"
322
+ LEGACY_WARNINGS=$warnings
323
+
324
+ return 0 # Never block installation
325
+ }
326
+
327
+ cleanup_legacy_artifacts() {
328
+ # Only run if --cleanup-legacy was passed
329
+ if [ "$CLEANUP_LEGACY" != true ]; then
330
+ return 0
331
+ fi
332
+
333
+ # Check if there are items to clean
334
+ if [ $LEGACY_WARNINGS -eq 0 ] || [ -z "$LEGACY_ITEMS" ]; then
335
+ info "Nenhum artefato legado encontrado para limpeza"
336
+ return 0
337
+ fi
338
+
339
+ # Safety: refuse cleanup in --yes mode (protect against automated deletion)
340
+ if [ "$AUTO_YES" = true ]; then
341
+ warn "Cleanup requer confirmacao interativa (--yes ignorado para seguranca)"
342
+ return 0
343
+ fi
344
+
345
+ # Show what will be removed
346
+ echo ""
347
+ warn "Os seguintes artefatos serao removidos:"
348
+ local item_count=0
349
+ while IFS= read -r item; do
350
+ [ -z "$item" ] && continue
351
+ local display_item="${item/#$HOME/~}"
352
+ if [ -d "$item" ]; then
353
+ info " - ${display_item}/ (diretorio)"
354
+ else
355
+ info " - ${display_item} (arquivo)"
356
+ fi
357
+ item_count=$((item_count + 1))
358
+ done <<EOF
359
+ $LEGACY_ITEMS
360
+ EOF
361
+
362
+ echo -ne " Confirmar remocao? ${BOLD}[s/N]:${NC} "
363
+
364
+ local response=""
365
+ if read -r -t 30 response 2>/dev/null; then
366
+ : # response received
367
+ else
368
+ echo ""
369
+ info "Timeout - cleanup cancelado"
370
+ return 0
371
+ fi
372
+
373
+ if [[ ! "$response" =~ ^([sS][iI]?[mM]?|[yY][eE]?[sS]?)$ ]]; then
374
+ info "Cleanup cancelado"
375
+ return 0
376
+ fi
377
+
378
+ # Execute cleanup
379
+ local removed=0
380
+ local failed=0
381
+ while IFS= read -r item; do
382
+ [ -z "$item" ] && continue
383
+ local display_item="${item/#$HOME/~}"
384
+ if rm -rf "$item" 2>/dev/null; then
385
+ ok "Removido: $display_item"
386
+ removed=$((removed + 1))
387
+ else
388
+ fail "Falha ao remover: $display_item"
389
+ failed=$((failed + 1))
390
+ fi
391
+ done <<EOF
392
+ $LEGACY_ITEMS
393
+ EOF
394
+
395
+ if [ $failed -eq 0 ]; then
396
+ ok "$removed artefato(s) removido(s) com sucesso"
397
+ else
398
+ warn "$removed removido(s), $failed falha(s)"
399
+ fi
400
+
401
+ return 0
402
+ }
403
+
404
+ detect_project_migration_needs() {
405
+ local migration_needed=false
406
+ local sources=()
407
+
408
+ [ -f ".neocortex/orchestrator.db" ] && { migration_needed=true; sources+=("orchestrator.db"); }
409
+ for yaml_path in "bmad-output/sprint-status.yaml" ".neocortex/sprint-status.yaml" "docs/sprint-status.yaml"; do
410
+ [ -f "$yaml_path" ] && { migration_needed=true; sources+=("$yaml_path"); }
411
+ done
412
+
413
+ if [ "$migration_needed" = true ]; then
414
+ echo "${sources[*]}"
415
+ return 0
416
+ fi
417
+ return 1
418
+ }
419
+
420
+ # =============================================================================
421
+ # BANNER
422
+ # =============================================================================
423
+
424
+ show_banner() {
425
+ [ "$QUIET_MODE" = true ] && return
426
+ [ "$NO_BANNER" = true ] && return
427
+
428
+ # True color blue gradient (#00B4FF → #7DD3FC → #0070A8) matching neocortex-cli theme
429
+ local g1="\033[38;2;0;180;255m" # #00B4FF bright blue
430
+ local g2="\033[38;2;48;191;254m" # #30BFFE
431
+ local g3="\033[38;2;95;204;253m" # #5FCCFD light blue
432
+ local g4="\033[38;2;102;192;236m" # #66C0EC
433
+ local g5="\033[38;2;56;154;204m" # #389ACC
434
+ local g6="\033[38;2;0;112;168m" # #0070A8 deep blue
435
+ local gd="\033[38;5;236m"
436
+ local gt="\033[38;5;243m"
437
+ local rst="\033[0m"
438
+
439
+ local lines=(
440
+ "${g1} ███╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ████████╗███████╗██╗ ██╗${rst}"
441
+ "${g2} ████╗ ██║██╔════╝██╔═══██╗██╔════╝██╔═══██╗██╔══██╗╚══██╔══╝██╔════╝╚██╗██╔╝${rst}"
442
+ "${g3} ██╔██╗ ██║█████╗ ██║ ██║██║ ██║ ██║██████╔╝ ██║ █████╗ ╚███╔╝${rst}"
443
+ "${g4} ██║╚██╗██║██╔══╝ ██║ ██║██║ ██║ ██║██╔══██╗ ██║ ██╔══╝ ██╔██╗${rst}"
444
+ "${g5} ██║ ╚████║███████╗╚██████╔╝╚██████╗╚██████╔╝██║ ██║ ██║ ███████╗██╔╝ ██╗${rst}"
445
+ "${g6} ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝${rst}"
446
+ ""
447
+ "${gd} ──────────────────────────────────────────────────────────────────────────────────${rst}"
448
+ "${gt} Development Orchestrator | OrNexus Team v${VERSION}${rst}"
449
+ )
450
+
451
+ echo ""
452
+ for line in "${lines[@]}"; do
453
+ echo -e "$line"
454
+ sleep 0.02
455
+ done
456
+ echo ""
457
+ }
458
+
459
+ # =============================================================================
460
+ # DETECCAO DO DIRETORIO FONTE
461
+ # =============================================================================
462
+
463
+ detect_source_dir() {
464
+ if [ -n "${BASH_SOURCE[0]}" ]; then
465
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
466
+ elif [ -n "$0" ]; then
467
+ SCRIPT_DIR="$(cd "$(dirname "$0")" 2>/dev/null && pwd)"
468
+ else
469
+ SCRIPT_DIR="$PWD"
470
+ fi
471
+
472
+ if [ ! -f "$SCRIPT_DIR/targets/claude-code/neocortex.md" ]; then
473
+ if [ ! -f "$SCRIPT_DIR/neocortex.md" ]; then
474
+ for possible_dir in \
475
+ "$SCRIPT_DIR" \
476
+ "$(npm root -g 2>/dev/null)/neocortex" \
477
+ "$(dirname "$0")" \
478
+ "$PWD/node_modules/neocortex" \
479
+ "$HOME/.npm/_npx/"*"/node_modules/neocortex"; do
480
+ if [ -f "$possible_dir/targets/claude-code/neocortex.md" ] 2>/dev/null || \
481
+ [ -f "$possible_dir/neocortex.md" ] 2>/dev/null; then
482
+ SCRIPT_DIR="$possible_dir"
483
+ break
484
+ fi
485
+ done
486
+ fi
487
+ fi
488
+
489
+ SOURCE_DIR="$SCRIPT_DIR"
490
+ debug "Source: $SOURCE_DIR"
491
+ }
492
+
493
+ # =============================================================================
494
+ # TIER 3: CLEANUP DE IP LEGADA E CONFIG DO THIN CLIENT
495
+ # =============================================================================
496
+
497
+ cleanup_legacy_ip() {
498
+ local neocortex_dir="${HOME}/.claude/agents/neocortex"
499
+ local skills_dir="${HOME}/.claude/skills/neocortex"
500
+ local cleaned=false
501
+
502
+ # Remover core/ e seus subdiretorios
503
+ if [ -d "$neocortex_dir/core" ]; then
504
+ rm -rf "$neocortex_dir/core"
505
+ cleaned=true
506
+ fi
507
+
508
+ # Remover step folders (steps-c, steps-e, steps-p, steps-r, steps-u)
509
+ for folder in steps-c steps-e steps-p steps-r steps-u; do
510
+ if [ -d "$neocortex_dir/$folder" ]; then
511
+ rm -rf "$neocortex_dir/$folder"
512
+ cleaned=true
513
+ fi
514
+ done
515
+
516
+ # Remover skills
517
+ if [ -d "$skills_dir" ]; then
518
+ rm -rf "$skills_dir"
519
+ cleaned=true
520
+ fi
521
+
522
+ # Remover arquivos desnecessarios
523
+ for file in package.json README.md; do
524
+ if [ -f "$neocortex_dir/$file" ]; then
525
+ rm -f "$neocortex_dir/$file"
526
+ cleaned=true
527
+ fi
528
+ done
529
+
530
+ if [ "$cleaned" = true ]; then
531
+ info "IP proprietaria removida de versao anterior (agora servida via server remoto)"
532
+ fi
533
+ }
534
+
535
+ setup_thin_client_config() {
536
+ local config_dir="${HOME}/.neocortex"
537
+ local config_file="${config_dir}/config.json"
538
+
539
+ mkdir -p "$config_dir" 2>/dev/null
540
+ mkdir -p "$config_dir/cache" 2>/dev/null
541
+
542
+ if [ -f "$config_file" ]; then
543
+ # Preservar config existente, atualizar apenas serverUrl se necessario
544
+ local existing_mode
545
+ existing_mode=$(grep '"mode"' "$config_file" 2>/dev/null | head -1 | sed 's/.*"mode"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
546
+
547
+ if [ "$existing_mode" = "active" ] || [ "$existing_mode" = "local" ]; then
548
+ debug "Config existente preservada (mode=$existing_mode)"
549
+ return 0
550
+ fi
551
+ fi
552
+
553
+ # Criar config base para thin client
554
+ cat > "$config_file" << EOFCONFIG
555
+ {
556
+ "version": "${VERSION}",
557
+ "mode": "pending-activation",
558
+ "serverUrl": "${NEOCORTEX_SERVER_URL}",
559
+ "tier": 3,
560
+ "cache": {
561
+ "enabled": true,
562
+ "directory": "${config_dir}/cache",
563
+ "encryption": "AES-256-GCM"
564
+ },
565
+ "resilience": {
566
+ "circuitBreaker": true,
567
+ "maxRetries": 3,
568
+ "timeoutMs": 5000
569
+ },
570
+ "installedAt": "$(date -Iseconds 2>/dev/null || date '+%Y-%m-%dT%H:%M:%S')",
571
+ "installerVersion": "${VERSION}"
572
+ }
573
+ EOFCONFIG
574
+
575
+ debug "Thin client config criada: $config_file"
576
+ }
577
+
578
+ cleanup_legacy_ip_project() {
579
+ local project_dir="$1"
580
+ local neocortex_dir="$project_dir/.claude/agents/neocortex"
581
+ local skills_dir="$project_dir/.claude/skills/neocortex"
582
+ local cleaned=false
583
+
584
+ # Remover core/ e seus subdiretorios
585
+ if [ -d "$neocortex_dir/core" ]; then
586
+ rm -rf "$neocortex_dir/core"
587
+ cleaned=true
588
+ fi
589
+
590
+ # Remover step folders
591
+ for folder in steps-c steps-e steps-p steps-r steps-u; do
592
+ if [ -d "$neocortex_dir/$folder" ]; then
593
+ rm -rf "$neocortex_dir/$folder"
594
+ cleaned=true
595
+ fi
596
+ done
597
+
598
+ # Remover skills
599
+ if [ -d "$skills_dir" ]; then
600
+ rm -rf "$skills_dir"
601
+ cleaned=true
602
+ fi
603
+
604
+ # Remover arquivos desnecessarios
605
+ for file in package.json README.md; do
606
+ if [ -f "$neocortex_dir/$file" ]; then
607
+ rm -f "$neocortex_dir/$file"
608
+ cleaned=true
609
+ fi
610
+ done
611
+
612
+ if [ "$cleaned" = true ]; then
613
+ info "IP proprietaria removida do projeto (agora servida via server remoto)"
614
+ fi
615
+ }
616
+
617
+ # =============================================================================
618
+ # INSTALACAO CORE
619
+ # =============================================================================
620
+
621
+ install_core() {
622
+ local errors=0
623
+
624
+ CLAUDE_DIR="${HOME}/.claude"
625
+ AGENTS_DIR="${CLAUDE_DIR}/agents"
626
+ DEST_DIR="${AGENTS_DIR}/neocortex"
627
+
628
+ debug "HOME=$HOME | DEST=$DEST_DIR | LOCAL_MODE=$LOCAL_MODE"
629
+
630
+ # Create directories
631
+ if [ ! -d "$CLAUDE_DIR" ]; then
632
+ mkdir -p "$CLAUDE_DIR" 2>/dev/null || { fail "Falha ao criar $CLAUDE_DIR"; return 1; }
633
+ fi
634
+ mkdir -p "$AGENTS_DIR" 2>/dev/null || { fail "Falha ao criar $AGENTS_DIR"; return 1; }
635
+
636
+ # Clean previous installation
637
+ if [ -d "$DEST_DIR" ]; then
638
+ rm -rf "$DEST_DIR" 2>/dev/null
639
+ debug "Instalacao anterior removida"
640
+ fi
641
+ mkdir -p "$DEST_DIR" 2>/dev/null || { fail "Falha ao criar $DEST_DIR"; return 1; }
642
+
643
+ if [ "$LOCAL_MODE" = true ]; then
644
+ # Mode local: copiar IP completa (comportamento legado para devs)
645
+ copy_dir "$SOURCE_DIR/core" "$DEST_DIR/" || ((errors++))
646
+ copy_file "$SOURCE_DIR/package.json" "$DEST_DIR/" || ((errors++))
647
+ copy_file "$SOURCE_DIR/README.md" "$DEST_DIR/" || ((errors++))
648
+ else
649
+ # Tier 3 Remote Mode: NÃO copiar IP
650
+ # Apenas setup do thin client - steps/skills/standards vem do server
651
+ cleanup_legacy_ip
652
+ setup_thin_client_config
653
+ fi
654
+
655
+ # Write version file
656
+ local pkg_version=""
657
+ if [ -f "$SOURCE_DIR/package.json" ]; then
658
+ pkg_version=$(grep '"version"' "$SOURCE_DIR/package.json" 2>/dev/null | head -1 | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
659
+ fi
660
+ [ -n "$pkg_version" ] && echo "$pkg_version" > "$DEST_DIR/.version"
661
+
662
+ if [ $errors -eq 0 ]; then
663
+ if [ "$LOCAL_MODE" = true ]; then
664
+ ok "Core instalado ${DIM}(standards, templates, scripts) [modo local]${NC}"
665
+ else
666
+ ok "Core instalado ${DIM}(thin client configurado) [modo remoto]${NC}"
667
+ fi
668
+ else
669
+ fail "Core instalado com erros"
670
+ fi
671
+
672
+ return $errors
673
+ }
674
+
675
+ # =============================================================================
676
+ # INSTALACAO DE SKILLS
677
+ # =============================================================================
678
+
679
+ install_skills() {
680
+ local errors=0
681
+
682
+ SKILLS_DIR="${CLAUDE_DIR}/skills"
683
+ SKILLS_DEST="${SKILLS_DIR}/neocortex"
684
+ SKILLS_SOURCE="${SOURCE_DIR}/core/skills"
685
+
686
+ # Tier 3 Remote Mode: skills vem do server, nao copiar
687
+ if [ "$LOCAL_MODE" != true ]; then
688
+ ok "Skills ${DIM}(servidas via server remoto) [modo remoto]${NC}"
689
+ return 0
690
+ fi
691
+
692
+ if [ ! -d "$SKILLS_SOURCE" ]; then
693
+ debug "Skills nao encontradas no pacote"
694
+ return 0
695
+ fi
696
+
697
+ mkdir -p "$SKILLS_DIR" 2>/dev/null || { fail "Falha ao criar $SKILLS_DIR"; return 1; }
698
+
699
+ # Clean previous
700
+ [ -d "$SKILLS_DEST" ] && rm -rf "$SKILLS_DEST" 2>/dev/null
701
+
702
+ if cp -r "$SKILLS_SOURCE" "$SKILLS_DEST" 2>/dev/null; then
703
+ # Count skills
704
+ local skill_count=0
705
+ for skill_file in "$SKILLS_DEST"/step-skills/*/*.md "$SKILLS_DEST"/domain-skills/*/*.md; do
706
+ if [ -f "$skill_file" ] && [[ "$(basename "$skill_file")" != "_template.md" ]]; then
707
+ ((skill_count++))
708
+ fi
709
+ done
710
+ ok "Skills instaladas ${DIM}($skill_count skills) [modo local]${NC}"
711
+ else
712
+ fail "Falha ao copiar skills"
713
+ ((errors++))
714
+ fi
715
+
716
+ return $errors
717
+ }
718
+
719
+ # =============================================================================
720
+ # INSTALACAO DE AGENT (Claude Code)
721
+ # =============================================================================
722
+
723
+ install_agent() {
724
+ local errors=0
725
+
726
+ CLAUDE_TARGET_DIR="$SOURCE_DIR/targets/claude-code"
727
+ [ ! -d "$CLAUDE_TARGET_DIR" ] && CLAUDE_TARGET_DIR="$SOURCE_DIR"
728
+
729
+ # Tier 3 Stub-Only: copiar apenas 2 arquivos de interface (stubs minimos)
730
+ copy_file "$CLAUDE_TARGET_DIR/neocortex.md" "$DEST_DIR/"
731
+ copy_file "$CLAUDE_TARGET_DIR/neocortex.agent.yaml" "$DEST_DIR/"
732
+
733
+ # Cleanup: remover workflow.md de instalacoes anteriores (v3.8 -> v3.9)
734
+ if [ -f "$DEST_DIR/workflow.md" ]; then
735
+ rm -f "$DEST_DIR/workflow.md"
736
+ [ "$QUIET_MODE" = false ] && echo " Removed workflow.md (content now server-side)"
737
+ fi
738
+
739
+ if [ "$LOCAL_MODE" = true ]; then
740
+ # Modo local: copiar IP completa (comportamento legado para devs)
741
+ copy_file "$SOURCE_DIR/package.json" "$DEST_DIR/"
742
+ copy_file "$SOURCE_DIR/README.md" "$DEST_DIR/"
743
+ copy_dir "$SOURCE_DIR/core" "$DEST_DIR/"
744
+
745
+ for folder in steps-c steps-e steps-p steps-r steps-u; do
746
+ copy_dir "$SOURCE_DIR/core/steps/$folder" "$DEST_DIR/"
747
+ done
748
+ fi
749
+ # Tier 3 Remote Mode: apenas 2 stub files + server-side orchestration
750
+
751
+ return $errors
752
+ }
753
+
754
+ # =============================================================================
755
+ # INSTALACAO DE TARGETS
756
+ # =============================================================================
757
+
758
+ install_targets() {
759
+ local targets="$1"
760
+ local target_errors=0
761
+ local target_count=0
762
+ local target_results=()
763
+
764
+ targets=$(echo "$targets" | tr ',' ' ')
765
+
766
+ for target in $targets; do
767
+ local adapter_script="$SOURCE_DIR/targets/$target/install-${target}.sh"
768
+ local func_name="install_$(echo "$target" | tr '-' '_')"
769
+
770
+ if [ ! -f "$adapter_script" ]; then
771
+ if [ "$target" = "claude-code" ]; then
772
+ install_agent
773
+ local result=$?
774
+ if [ $result -eq 0 ]; then
775
+ target_results+=("$target:OK")
776
+ ((target_count++))
777
+ ok "${BOLD}claude-code${NC} ${DIM}(agent, steps, core)${NC}"
778
+ else
779
+ target_results+=("$target:FAIL")
780
+ ((target_errors++))
781
+ fail "claude-code"
782
+ fi
783
+ continue
784
+ fi
785
+
786
+ warn "$target ${DIM}(adapter nao encontrado)${NC}"
787
+ target_results+=("$target:SKIP")
788
+ ((target_errors++))
789
+ continue
790
+ fi
791
+
792
+ . "$adapter_script"
793
+
794
+ if type "$func_name" >/dev/null 2>&1; then
795
+ "$func_name" "$SOURCE_DIR" "$HOME"
796
+ local result=$?
797
+ if [ $result -eq 0 ]; then
798
+ target_results+=("$target:OK")
799
+ ((target_count++))
800
+ ok "${BOLD}$target${NC}"
801
+ else
802
+ target_results+=("$target:WARN")
803
+ warn "$target ${DIM}(instalado com avisos)${NC}"
804
+ ((target_count++))
805
+ fi
806
+ else
807
+ fail "$target ${DIM}(funcao $func_name nao encontrada)${NC}"
808
+ target_results+=("$target:FAIL")
809
+ ((target_errors++))
810
+ fi
811
+ done
812
+
813
+ TARGET_RESULTS=("${target_results[@]}")
814
+ TARGET_COUNT=$target_count
815
+
816
+ return $target_errors
817
+ }
818
+
819
+ # =============================================================================
820
+ # CARREGAMENTO DE .ENV
821
+ # =============================================================================
822
+
823
+ load_env_file() {
824
+ local env_file=""
825
+ for possible_env in "./.env" "$SOURCE_DIR/.env"; do
826
+ [ -f "$possible_env" ] && { env_file="$possible_env"; break; }
827
+ done
828
+
829
+ if [ -n "$env_file" ] && [ -f "$env_file" ]; then
830
+ local loaded=0
831
+ while IFS='=' read -r key value || [ -n "$key" ]; do
832
+ [[ -z "$key" || "$key" =~ ^[[:space:]]*# ]] && continue
833
+ key=$(echo "$key" | xargs)
834
+ value=$(echo "$value" | xargs)
835
+ value="${value%\"}"; value="${value#\"}"
836
+ value="${value%\'}"; value="${value#\'}"
837
+ if [ -n "$value" ] && [ -z "${!key}" ]; then
838
+ export "$key=$value"
839
+ ((loaded++))
840
+ fi
841
+ done < "$env_file"
842
+ [ $loaded -gt 0 ] && info "$loaded variavel(eis) carregada(s) do .env"
843
+ return 0
844
+ fi
845
+ return 1
846
+ }
847
+
848
+ # =============================================================================
849
+ # CONFIGURACAO DE TOKENS
850
+ # =============================================================================
851
+
852
+ prompt_tokens() {
853
+ [ "$QUIET_MODE" = true ] && return
854
+ [ -n "$CONTEXT7_API_KEY" ] && return
855
+
856
+ if [ "$AUTO_YES" = true ]; then
857
+ return
858
+ fi
859
+
860
+ echo ""
861
+ info "MCP Context7 nao configurado ${DIM}(opcional)${NC}"
862
+ echo -ne " Configurar agora? ${BOLD}[s/N]:${NC} "
863
+
864
+ local response=""
865
+ if read -r -t 15 response 2>/dev/null; then
866
+ : # resposta recebida
867
+ else
868
+ echo ""
869
+ return
870
+ fi
871
+
872
+ if [[ "$response" =~ ^([sS][iI]?[mM]?|[yY][eE]?[sS]?)$ ]]; then
873
+ echo ""
874
+ info "Obtenha sua API Key em: ${WHITE}https://context7.com${NC}"
875
+ echo -ne " Cole sua ${BOLD}CONTEXT7_API_KEY${NC}: "
876
+
877
+ local api_key=""
878
+ if read -r -t 60 api_key 2>/dev/null; then
879
+ if [[ "$api_key" =~ ^ctx7sk- ]]; then
880
+ export CONTEXT7_API_KEY="$api_key"
881
+ ok "CONTEXT7_API_KEY configurada"
882
+ echo ""
883
+ info "Para persistir: ${DIM}echo 'export CONTEXT7_API_KEY=\"$api_key\"' >> ~/.bashrc${NC}"
884
+ elif [ -n "$api_key" ]; then
885
+ warn "Formato invalido (esperado: ctx7sk-...)"
886
+ fi
887
+ fi
888
+ fi
889
+ }
890
+
891
+ # =============================================================================
892
+ # INSTALACAO DE MCP SERVERS
893
+ # =============================================================================
894
+
895
+ install_mcps() {
896
+ if ! command -v claude >/dev/null 2>&1; then
897
+ info "Claude CLI nao encontrado ${DIM}(MCPs serao instalados depois)${NC}"
898
+ return 0
899
+ fi
900
+
901
+ local mcp_results=""
902
+
903
+ if claude mcp list 2>/dev/null | grep -q "^playwright"; then
904
+ mcp_results="${mcp_results}playwright:OK "
905
+ else
906
+ if claude mcp add playwright npx @playwright/mcp@latest 2>/dev/null; then
907
+ mcp_results="${mcp_results}playwright:OK "
908
+ else
909
+ mcp_results="${mcp_results}playwright:FAIL "
910
+ fi
911
+ fi
912
+
913
+ if claude mcp list 2>/dev/null | grep -q "^context7"; then
914
+ mcp_results="${mcp_results}context7:OK "
915
+ elif [ -n "$CONTEXT7_API_KEY" ]; then
916
+ if claude mcp add --transport http context7 https://mcp.context7.com/mcp --header "CONTEXT7_API_KEY: $CONTEXT7_API_KEY" 2>/dev/null; then
917
+ mcp_results="${mcp_results}context7:OK "
918
+ else
919
+ mcp_results="${mcp_results}context7:FAIL "
920
+ fi
921
+ else
922
+ mcp_results="${mcp_results}context7:SKIP "
923
+ fi
924
+
925
+ # Show compact MCP results
926
+ local mcp_ok="" mcp_skip=""
927
+ for entry in $mcp_results; do
928
+ local name="${entry%%:*}"
929
+ local status="${entry##*:}"
930
+ case "$status" in
931
+ OK) mcp_ok="${mcp_ok}${name}, " ;;
932
+ SKIP) mcp_skip="${mcp_skip}${name}, " ;;
933
+ esac
934
+ done
935
+
936
+ [ -n "$mcp_ok" ] && ok "MCPs: ${DIM}${mcp_ok%, }${NC}"
937
+ [ -n "$mcp_skip" ] && info "MCPs pendentes: ${DIM}${mcp_skip%, }${NC}"
938
+
939
+ return 0
940
+ }
941
+
942
+ # =============================================================================
943
+ # INSTALACAO DO CODERABBIT CLI
944
+ # =============================================================================
945
+
946
+ install_coderabbit() {
947
+ if command -v coderabbit >/dev/null 2>&1; then
948
+ ok "CodeRabbit CLI"
949
+ CODERABBIT_INSTALLED=true
950
+ return 0
951
+ fi
952
+
953
+ if command -v curl >/dev/null 2>&1 && curl -fsSL https://cli.coderabbit.ai/install.sh | sh 2>/dev/null; then
954
+ ok "CodeRabbit CLI ${DIM}(instalado)${NC}"
955
+ CODERABBIT_INSTALLED=true
956
+ elif command -v npm >/dev/null 2>&1 && npm install -g coderabbit 2>/dev/null; then
957
+ ok "CodeRabbit CLI ${DIM}(via npm)${NC}"
958
+ CODERABBIT_INSTALLED=true
959
+ else
960
+ info "CodeRabbit CLI ${DIM}(instale depois: curl -fsSL https://cli.coderabbit.ai/install.sh | sh)${NC}"
961
+ CODERABBIT_INSTALLED=false
962
+ fi
963
+
964
+ return 0
965
+ }
966
+
967
+ # =============================================================================
968
+ # VERIFICACAO POS-INSTALACAO
969
+ # =============================================================================
970
+
971
+ verify_installation() {
972
+ local fails=0
973
+ local warns=0
974
+ local report=""
975
+
976
+ if ! echo "$SELECTED_TARGETS" | grep -q "claude-code"; then
977
+ return 0
978
+ fi
979
+
980
+ # ─── Layer 1: File existence + minimum size ─────────────────────────
981
+ local check_fname check_min check_fpath check_size check_ext check_first_line check_display
982
+ for check_fname in neocortex.md neocortex.agent.yaml; do
983
+ case "$check_fname" in
984
+ neocortex.md) check_min=512 ;;
985
+ neocortex.agent.yaml) check_min=128 ;;
986
+ esac
987
+ check_fpath="${DEST_DIR}/${check_fname}"
988
+
989
+ if [ ! -f "$check_fpath" ]; then
990
+ report="${report}FAIL ${check_fname} (nao encontrado)\n"
991
+ fails=$((fails + 1))
992
+ else
993
+ check_size=$(wc -c < "$check_fpath" 2>/dev/null | tr -d ' ')
994
+ if [ "$check_size" -lt "$check_min" ] 2>/dev/null; then
995
+ report="${report}FAIL ${check_fname} (${check_size} bytes - possivelmente corrompido, minimo ${check_min})\n"
996
+ fails=$((fails + 1))
997
+ else
998
+ # ─── Layer 2: Content marker (frontmatter) ──────────────
999
+ check_ext="${check_fname##*.}"
1000
+ if [ "$check_ext" = "md" ]; then
1001
+ check_first_line=$(head -1 "$check_fpath" 2>/dev/null)
1002
+ if [ "$check_first_line" != "---" ]; then
1003
+ report="${report}WARN ${check_fname} (formato invalido - sem frontmatter)\n"
1004
+ warns=$((warns + 1))
1005
+ else
1006
+ if [ "$check_size" -ge 1024 ]; then check_display="$((check_size / 1024))KB"; else check_display="${check_size}B"; fi
1007
+ report="${report}OK ${check_fname} (${check_display})\n"
1008
+ fi
1009
+ else
1010
+ if [ "$check_size" -ge 1024 ]; then check_display="$((check_size / 1024))KB"; else check_display="${check_size}B"; fi
1011
+ report="${report}OK ${check_fname} (${check_display})\n"
1012
+ fi
1013
+ fi
1014
+ fi
1015
+ done
1016
+
1017
+ if [ "$LOCAL_MODE" = true ]; then
1018
+ # ─── Layer 3: Step directories (local mode only) ─────────────────
1019
+ for dir in steps-c steps-e steps-p steps-r steps-u; do
1020
+ local dir_path="$DEST_DIR/$dir"
1021
+ if [ ! -d "$dir_path" ]; then
1022
+ report="${report}FAIL ${dir}/ (diretorio nao encontrado)\n"
1023
+ fails=$((fails + 1))
1024
+ else
1025
+ local md_count=0
1026
+ for f in "$dir_path"/*.md; do
1027
+ [ -f "$f" ] && md_count=$((md_count + 1))
1028
+ done
1029
+ if [ $md_count -eq 0 ]; then
1030
+ report="${report}WARN ${dir}/ (vazio - nenhum arquivo .md)\n"
1031
+ warns=$((warns + 1))
1032
+ else
1033
+ report="${report}OK ${dir}/ (${md_count} arquivos)\n"
1034
+ fi
1035
+ fi
1036
+ done
1037
+
1038
+ # ─── Layer 3b: Core directory (local mode only) ──────────────────
1039
+ if [ ! -d "$DEST_DIR/core" ]; then
1040
+ report="${report}FAIL core/ (diretorio nao encontrado)\n"
1041
+ fails=$((fails + 1))
1042
+ else
1043
+ report="${report}OK core/\n"
1044
+ fi
1045
+ else
1046
+ # ─── Layer 3: Thin client config (remote mode) ───────────────────
1047
+ local config_file="${HOME}/.neocortex/config.json"
1048
+ if [ -f "$config_file" ]; then
1049
+ report="${report}OK ~/.neocortex/config.json (thin client configurado)\n"
1050
+ else
1051
+ report="${report}WARN ~/.neocortex/config.json (nao encontrado)\n"
1052
+ warns=$((warns + 1))
1053
+ fi
1054
+
1055
+ # Verify NO IP directories exist
1056
+ local ip_found=false
1057
+ for dir in core steps-c steps-e steps-p steps-r steps-u; do
1058
+ if [ -d "$DEST_DIR/$dir" ]; then
1059
+ report="${report}WARN ${dir}/ ainda existe (deveria ter sido removido)\n"
1060
+ warns=$((warns + 1))
1061
+ ip_found=true
1062
+ fi
1063
+ done
1064
+ if [ "$ip_found" = false ]; then
1065
+ report="${report}OK Zero IP no filesystem (modo remoto)\n"
1066
+ fi
1067
+ fi
1068
+
1069
+ # ─── Display report ─────────────────────────────────────────────────
1070
+ if [ $fails -eq 0 ] && [ $warns -eq 0 ]; then
1071
+ # All good - compact output
1072
+ if [ "$QUIET_MODE" != true ]; then
1073
+ ok "Instalacao verificada"
1074
+ fi
1075
+ return 0
1076
+ fi
1077
+
1078
+ # Show detailed report when issues found
1079
+ if [ "$QUIET_MODE" = true ] && [ $fails -eq 0 ]; then
1080
+ return 0 # In quiet mode, skip warnings-only report
1081
+ fi
1082
+
1083
+ echo ""
1084
+ info "Verificacao pos-instalacao:"
1085
+ echo -e "$report" | while IFS= read -r line; do
1086
+ [ -z "$line" ] && continue
1087
+ local status="${line%% *}"
1088
+ local detail="${line#* }"
1089
+ case "$status" in
1090
+ OK) echo -e " ${GREEN}${SYM_OK}${NC} $detail" ;;
1091
+ WARN) echo -e " ${YELLOW}${SYM_WARN}${NC} $detail" ;;
1092
+ FAIL) echo -e " ${RED}${SYM_FAIL}${NC} $detail" ;;
1093
+ esac
1094
+ done
1095
+
1096
+ [ $fails -gt 0 ] && return 1
1097
+ return 0
1098
+ }
1099
+
1100
+ # =============================================================================
1101
+ # RESULTADO
1102
+ # =============================================================================
1103
+
1104
+ show_result() {
1105
+ local install_status=$1
1106
+ [ "$QUIET_MODE" = true ] && return
1107
+
1108
+ echo ""
1109
+ echo -e " ${DIM}────────────────────────────────────────${NC}"
1110
+
1111
+ if [ $install_status -eq 0 ] && verify_installation; then
1112
+ echo ""
1113
+ echo -e " ${GREEN}${BOLD}Instalacao concluida!${NC}"
1114
+ echo ""
1115
+ if [ "$LOCAL_MODE" = true ]; then
1116
+ echo -e " ${DIM}Modo:${NC} Local (IP completa copiada)"
1117
+ echo -e " ${DIM}Locais:${NC}"
1118
+ echo -e " ${DIM}Agente:${NC} ~/.claude/agents/neocortex/"
1119
+ echo -e " ${DIM}Skills:${NC} ~/.claude/skills/neocortex/"
1120
+ else
1121
+ echo -e " ${DIM}Modo:${NC} Remoto (Tier 3 - thin client)"
1122
+ echo -e " ${DIM}Locais:${NC}"
1123
+ echo -e " ${DIM}Agente:${NC} ~/.claude/agents/neocortex/ ${DIM}(3 arquivos)${NC}"
1124
+ echo -e " ${DIM}Config:${NC} ~/.neocortex/config.json"
1125
+ echo ""
1126
+ echo -e " ${DIM}Ative sua licenca:${NC}"
1127
+ echo -e " ${CYAN}npx @ornexus/neocortex-client activate NX-PRO-xxx${NC}"
1128
+ fi
1129
+ echo ""
1130
+ echo -e " ${DIM}Proximo passo:${NC}"
1131
+ echo -e " ${CYAN}@neocortex *init @docs/epics.md${NC}"
1132
+ echo ""
1133
+ else
1134
+ echo ""
1135
+ echo -e " ${RED}${BOLD}Instalacao com problemas${NC}"
1136
+ echo ""
1137
+ echo -e " Execute novamente com ${BOLD}--debug${NC} para detalhes:"
1138
+ echo -e " ${YELLOW}npx @ornexus/neocortex --debug${NC}"
1139
+ echo ""
1140
+ return 1
1141
+ fi
1142
+ }
1143
+
1144
+ # =============================================================================
1145
+ # CRIACAO DE DIRETORIOS DO PROJETO
1146
+ # =============================================================================
1147
+
1148
+ create_project_dirs() {
1149
+ [ "$QUIET_MODE" = true ] && return
1150
+ [ "$SKIP_PROJECT_DIRS" = true ] && return
1151
+
1152
+ local should_create=false
1153
+
1154
+ if [ "$CREATE_PROJECT" = true ] || [ "$AUTO_YES" = true ]; then
1155
+ should_create=true
1156
+ else
1157
+ echo -ne " Instalar estrutura no projeto atual? ${BOLD}[s/N]:${NC} "
1158
+
1159
+ local response="n"
1160
+ if read -r -t 30 response </dev/tty 2>/dev/null; then
1161
+ :
1162
+ else
1163
+ echo ""
1164
+ response="n"
1165
+ fi
1166
+
1167
+ [[ "$response" =~ ^([sS][iI]?[mM]?|[yY][eE]?[sS]?)$ ]] && should_create=true
1168
+ fi
1169
+
1170
+ if [ "$should_create" = true ]; then
1171
+ local project_dir="$PWD"
1172
+
1173
+ # Clean previous project files
1174
+ rm -rf "$project_dir/targets/claude-code" 2>/dev/null
1175
+ rm -f "$project_dir/.cursor/agents/neocortex.md" 2>/dev/null
1176
+ rm -rf "$project_dir/.cursor/skills" 2>/dev/null
1177
+ rm -f "$project_dir/.github/agents/neocortex.md" 2>/dev/null
1178
+ rm -rf "$project_dir/.github/skills" 2>/dev/null
1179
+ rm -f "$project_dir/.github/copilot-instructions.md" 2>/dev/null
1180
+ rm -rf "$project_dir/.agent/skills/neocortex" 2>/dev/null
1181
+ rm -f "$project_dir/AGENTS.md" 2>/dev/null
1182
+ rm -rf "$project_dir/.agents/skills" 2>/dev/null
1183
+ rm -f "$project_dir/GEMINI.md" 2>/dev/null
1184
+ rm -rf "$project_dir/.claude/agents/neocortex" 2>/dev/null
1185
+ rm -rf "$project_dir/.claude/skills/neocortex" 2>/dev/null
1186
+
1187
+ if [ "$LOCAL_MODE" = true ]; then
1188
+ # Modo local: limpar e reconstruir core/
1189
+ rm -rf "$project_dir/core" 2>/dev/null
1190
+ fi
1191
+
1192
+ # Create base directories
1193
+ mkdir -p "$project_dir/.neocortex/specs" \
1194
+ "$project_dir/.neocortex/planning" \
1195
+ "$project_dir/docs/stories" \
1196
+ "$project_dir/docs/epics" \
1197
+ "$project_dir/docs/proposals" 2>/dev/null
1198
+
1199
+ # Copy state template if needed
1200
+ if [ ! -f "$project_dir/.neocortex/state.json" ]; then
1201
+ [ -f "$SOURCE_DIR/core/data/state-template.json" ] && \
1202
+ cp "$SOURCE_DIR/core/data/state-template.json" "$project_dir/.neocortex/state.json"
1203
+ fi
1204
+
1205
+ # Copy core (ONLY in local mode)
1206
+ if [ "$LOCAL_MODE" = true ] && [ -d "$SOURCE_DIR/core" ]; then
1207
+ mkdir -p "$project_dir/core"
1208
+ cp -r "$SOURCE_DIR/core"/* "$project_dir/core/" 2>/dev/null
1209
+ fi
1210
+
1211
+ # Install target-specific files
1212
+ local targets_list
1213
+ targets_list=$(echo "$SELECTED_TARGETS" | tr ',' ' ')
1214
+ local target_summary=""
1215
+
1216
+ for target in $targets_list; do
1217
+ case "$target" in
1218
+ claude-code)
1219
+ local claude_target_dir="$SOURCE_DIR/targets/claude-code"
1220
+ if [ -d "$claude_target_dir" ]; then
1221
+ mkdir -p "$project_dir/.claude/agents/neocortex"
1222
+
1223
+ # Tier 3: copiar apenas 2 stub files
1224
+ cp "$claude_target_dir/neocortex.md" "$project_dir/.claude/agents/neocortex/" 2>/dev/null
1225
+ cp "$claude_target_dir/neocortex.agent.yaml" "$project_dir/.claude/agents/neocortex/" 2>/dev/null
1226
+ # Cleanup workflow.md from previous versions
1227
+ rm -f "$project_dir/.claude/agents/neocortex/workflow.md" 2>/dev/null
1228
+
1229
+ if [ "$LOCAL_MODE" = true ]; then
1230
+ # Modo local: copiar IP completa (comportamento legado)
1231
+ cp "$SOURCE_DIR/package.json" "$project_dir/.claude/agents/neocortex/" 2>/dev/null
1232
+ cp "$SOURCE_DIR/README.md" "$project_dir/.claude/agents/neocortex/" 2>/dev/null
1233
+ mkdir -p "$project_dir/.claude/agents/neocortex/core"
1234
+ cp -r "$SOURCE_DIR/core"/* "$project_dir/.claude/agents/neocortex/core/" 2>/dev/null
1235
+ for folder in steps-c steps-e steps-p steps-r steps-u; do
1236
+ if [ -d "$SOURCE_DIR/core/steps/$folder" ]; then
1237
+ mkdir -p "$project_dir/.claude/agents/neocortex/$folder"
1238
+ cp -r "$SOURCE_DIR/core/steps/$folder"/* "$project_dir/.claude/agents/neocortex/$folder/" 2>/dev/null
1239
+ fi
1240
+ done
1241
+ if [ -d "$SOURCE_DIR/core/skills" ]; then
1242
+ mkdir -p "$project_dir/.claude/skills/neocortex"
1243
+ cp -r "$SOURCE_DIR/core/skills"/* "$project_dir/.claude/skills/neocortex/" 2>/dev/null
1244
+ fi
1245
+ else
1246
+ # Tier 3 Remote Mode: limpar IP de versoes anteriores no projeto
1247
+ cleanup_legacy_ip_project "$project_dir"
1248
+ fi
1249
+ target_summary="${target_summary}claude-code, "
1250
+ fi
1251
+ ;;
1252
+ cursor)
1253
+ local adapter_script="$SOURCE_DIR/targets/cursor/install-cursor.sh"
1254
+ if [ -f "$adapter_script" ]; then
1255
+ . "$adapter_script"
1256
+ install_cursor "$SOURCE_DIR" "$project_dir"
1257
+ target_summary="${target_summary}cursor, "
1258
+ fi
1259
+ ;;
1260
+ vscode)
1261
+ local adapter_script="$SOURCE_DIR/targets/vscode/install-vscode.sh"
1262
+ if [ -f "$adapter_script" ]; then
1263
+ . "$adapter_script"
1264
+ install_vscode "$SOURCE_DIR" "$project_dir"
1265
+ target_summary="${target_summary}vscode, "
1266
+ fi
1267
+ ;;
1268
+ gemini-cli)
1269
+ local gemini_target="$SOURCE_DIR/targets/gemini-cli"
1270
+ if [ -d "$gemini_target" ]; then
1271
+ [ -f "$gemini_target/gemini.md" ] && cp "$gemini_target/gemini.md" "$project_dir/GEMINI.md"
1272
+ if [ -d "$gemini_target/commands" ]; then
1273
+ mkdir -p "$project_dir/.gemini/commands"
1274
+ cp "$gemini_target/commands"/*.toml "$project_dir/.gemini/commands/" 2>/dev/null
1275
+ fi
1276
+ if [ -f "$gemini_target/agent.md" ]; then
1277
+ mkdir -p "$project_dir/.gemini/agents"
1278
+ cp "$gemini_target/agent.md" "$project_dir/.gemini/agents/neocortex.md"
1279
+ fi
1280
+ [ -f "$gemini_target/settings-mcp.json" ] && cp "$gemini_target/settings-mcp.json" "$project_dir/.gemini/settings-mcp.json"
1281
+ target_summary="${target_summary}gemini-cli, "
1282
+ fi
1283
+ ;;
1284
+ codex)
1285
+ local adapter_script="$SOURCE_DIR/targets/codex/install-codex.sh"
1286
+ if [ -f "$adapter_script" ]; then
1287
+ . "$adapter_script"
1288
+ install_codex "$SOURCE_DIR" "$project_dir"
1289
+ target_summary="${target_summary}codex, "
1290
+ fi
1291
+ ;;
1292
+ antigravity)
1293
+ local adapter_script="$SOURCE_DIR/targets/antigravity/install-antigravity.sh"
1294
+ if [ -f "$adapter_script" ]; then
1295
+ . "$adapter_script"
1296
+ install_antigravity "$SOURCE_DIR" "$project_dir"
1297
+ target_summary="${target_summary}antigravity, "
1298
+ fi
1299
+ ;;
1300
+ esac
1301
+ done
1302
+
1303
+ echo ""
1304
+ ok "Estrutura do projeto instalada ${DIM}(${target_summary%, })${NC}"
1305
+ echo ""
1306
+ info "Proximo passo: ${CYAN}@neocortex *init @docs/epics.md${NC}"
1307
+ fi
1308
+ }
1309
+
1310
+ # =============================================================================
1311
+ # MIGRACAO
1312
+ # =============================================================================
1313
+
1314
+ show_migration_info() {
1315
+ [ "$QUIET_MODE" = true ] && return
1316
+
1317
+ local project_sources
1318
+ if project_sources=$(detect_project_migration_needs); then
1319
+ echo ""
1320
+ warn "${BOLD}Migracao detectada${NC}"
1321
+ for src in $project_sources; do
1322
+ info "Arquivo antigo: $src"
1323
+ done
1324
+ info "Execute: ${CYAN}@neocortex *init @docs/epics.md${NC} para migrar"
1325
+ fi
1326
+ }
1327
+
1328
+ # =============================================================================
1329
+ # MAIN
1330
+ # =============================================================================
1331
+
1332
+ TOTAL_STEPS=3
1333
+
1334
+ main() {
1335
+ show_banner
1336
+ detect_source_dir
1337
+ detect_old_installation
1338
+ detect_legacy_artifacts
1339
+ cleanup_legacy_artifacts
1340
+
1341
+ # Determine targets
1342
+ if [ -z "$SELECTED_TARGETS" ]; then
1343
+ SELECTED_TARGETS="claude-code"
1344
+ fi
1345
+
1346
+ debug "Targets: $SELECTED_TARGETS"
1347
+
1348
+ # Validate targets
1349
+ local invalid_targets=""
1350
+ for target in $(echo "$SELECTED_TARGETS" | tr ',' ' '); do
1351
+ echo "$VALID_TARGETS" | grep -wq "$target" || invalid_targets="$invalid_targets $target"
1352
+ done
1353
+
1354
+ if [ -n "$invalid_targets" ]; then
1355
+ fail "Plataformas invalidas:$invalid_targets"
1356
+ fail "Validas: $VALID_TARGETS"
1357
+ exit 1
1358
+ fi
1359
+
1360
+ # Count targets for step total
1361
+ local target_count=$(echo "$SELECTED_TARGETS" | tr ',' ' ' | wc -w | tr -d ' ')
1362
+ if echo "$SELECTED_TARGETS" | grep -q "claude-code"; then
1363
+ TOTAL_STEPS=5 # core + skills + targets + mcps + tools
1364
+ fi
1365
+
1366
+ # Step 1: Core
1367
+ step 1 $TOTAL_STEPS "Instalando core"
1368
+ install_core
1369
+ local core_result=$?
1370
+ if [ $core_result -ne 0 ]; then
1371
+ fail "Falha na instalacao do core"
1372
+ exit 1
1373
+ fi
1374
+
1375
+ # Step 2: Skills
1376
+ step 2 $TOTAL_STEPS "Instalando skills"
1377
+ install_skills
1378
+
1379
+ # Step 3: Targets
1380
+ step 3 $TOTAL_STEPS "Instalando ${BOLD}$target_count${NC} plataforma(s)"
1381
+ install_targets "$SELECTED_TARGETS"
1382
+
1383
+ # Step 4-5: Claude Code extras
1384
+ if echo "$SELECTED_TARGETS" | grep -q "claude-code"; then
1385
+ load_env_file
1386
+ prompt_tokens
1387
+
1388
+ step 4 $TOTAL_STEPS "Configurando MCPs"
1389
+ install_mcps
1390
+
1391
+ step 5 $TOTAL_STEPS "Verificando ferramentas"
1392
+ install_coderabbit
1393
+ fi
1394
+
1395
+ # Result
1396
+ show_result $core_result
1397
+ local result_code=$?
1398
+
1399
+ if [ $result_code -eq 0 ]; then
1400
+ show_migration_info
1401
+ create_project_dirs
1402
+ echo -e " ${DIM}Desenvolvido por OrNexus Team${NC}"
1403
+ echo ""
1404
+ fi
1405
+
1406
+ exit $result_code
1407
+ }
1408
+
1409
+ main