stealthos-cli 0.1.0-alpha.3 → 0.1.0-alpha.4
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.
- package/ai/CONTRACT.md +110 -0
- package/ai/INDEX.md +203 -0
- package/ai/README.md +434 -0
- package/ai/ROUTER.md +288 -0
- package/ai/agents/README.md +103 -0
- package/ai/agents/architect.md +59 -0
- package/ai/agents/backend-engineer.md +62 -0
- package/ai/agents/founder.md +45 -0
- package/ai/agents/frontend-engineer.md +61 -0
- package/ai/agents/product-manager.md +56 -0
- package/ai/agents/qa-engineer.md +53 -0
- package/ai/agents/researcher.md +74 -0
- package/ai/agents/reviewer.md +73 -0
- package/ai/agents/security-engineer.md +59 -0
- package/ai/agents/sre-engineer.md +70 -0
- package/ai/agents/tech-lead.md +70 -0
- package/ai/architecture/README.md +35 -0
- package/ai/architecture/components.md +24 -0
- package/ai/architecture/containers.md +30 -0
- package/ai/architecture/event-flows.md +36 -0
- package/ai/architecture/sequence-diagrams.md +38 -0
- package/ai/architecture/system-context.md +46 -0
- package/ai/architecture/threat-modeling.md +40 -0
- package/ai/blueprints/README.md +67 -0
- package/ai/blueprints/_schema.json +40 -0
- package/ai/blueprints/ai-platform.json +28 -0
- package/ai/blueprints/crm.json +22 -0
- package/ai/blueprints/game.json +25 -0
- package/ai/blueprints/mobile.json +24 -0
- package/ai/blueprints/realtime.json +22 -0
- package/ai/blueprints/saas.json +25 -0
- package/ai/blueprints/telemetry.json +30 -0
- package/ai/blueprints/web.json +23 -0
- package/ai/bootstrap/discovery-questions.md +117 -0
- package/ai/bootstrap/dispatcher.md +85 -0
- package/ai/bootstrap/existing-project.md +191 -0
- package/ai/bootstrap/new-project.md +127 -0
- package/ai/bootstrap/tech-mapping.md +164 -0
- package/ai/clients/README.md +114 -0
- package/ai/clients/antigravity.md +125 -0
- package/ai/clients/claude-code.md +65 -0
- package/ai/clients/cline.md +69 -0
- package/ai/clients/codex-aider-cli.md +82 -0
- package/ai/clients/continue.md +67 -0
- package/ai/clients/copilot.md +49 -0
- package/ai/clients/cursor.md +81 -0
- package/ai/clients/snippets/mcp-absolute-paths.json +9 -0
- package/ai/clients/snippets/mcp-http.json +7 -0
- package/ai/clients/snippets/mcp-stdio.json +9 -0
- package/ai/clients/trae.md +69 -0
- package/ai/clients/windsurf.md +71 -0
- package/ai/core/pipeline/execution-engine.md +157 -0
- package/ai/engineering/README.md +32 -0
- package/ai/engineering/observability/incident-response.md +82 -0
- package/ai/evals/protocol-tests.md +150 -0
- package/ai/evolution/agent-evolution.md +161 -0
- package/ai/evolution/improvements.md +91 -0
- package/ai/evolution/learnings.md +49 -0
- package/ai/evolution/patterns-discovered.md +48 -0
- package/ai/execution/README.md +33 -0
- package/ai/execution/backlog.md +27 -0
- package/ai/execution/milestones.md +26 -0
- package/ai/execution/roadmap.md +30 -0
- package/ai/execution/sprint.md +42 -0
- package/ai/governance/README.md +34 -0
- package/ai/governance/architecture-principles.md +99 -0
- package/ai/governance/definition-of-done.md +88 -0
- package/ai/governance/definition-of-ready.md +69 -0
- package/ai/governance/engineering-principles.md +70 -0
- package/ai/governance/quality-gates.md +85 -0
- package/ai/governance/security-policies.md +84 -0
- package/ai/hooks/enforce-audit.ps1 +41 -0
- package/ai/hooks/enforce-audit.sh +39 -0
- package/ai/hooks/guard-edit.ps1 +182 -0
- package/ai/hooks/guard-edit.sh +161 -0
- package/ai/hooks/inject-os-reminder.ps1 +40 -0
- package/ai/hooks/inject-os-reminder.sh +16 -0
- package/ai/manifest.json +238 -0
- package/ai/memory/_detected-stack.json +33 -0
- package/ai/memory/_summary.md +49 -0
- package/ai/memory/archive/.gitkeep +3 -0
- package/ai/memory/completed-tasks.md +156 -0
- package/ai/memory/decisions.md +257 -0
- package/ai/memory/errors-and-solutions.md +41 -0
- package/ai/memory/known-issues.md +40 -0
- package/ai/memory/pending-tasks.md +37 -0
- package/ai/memory/project-context.md +67 -0
- package/ai/operating-system/architecture.md +54 -0
- package/ai/operating-system/coding-standards.md +84 -0
- package/ai/operating-system/folder-structure.md +126 -0
- package/ai/operating-system/performance-rules.md +86 -0
- package/ai/operating-system/quality-control.md +81 -0
- package/ai/operating-system/security-rules.md +91 -0
- package/ai/operating-system/workflow.md +86 -0
- package/ai/product/README.md +24 -0
- package/ai/product/business-rules.md +26 -0
- package/ai/product/personas.md +29 -0
- package/ai/product/user-journeys.md +30 -0
- package/ai/product/vision.md +35 -0
- package/ai/rules/behavior.md +45 -0
- package/ai/rules/do.md +47 -0
- package/ai/rules/dont.md +46 -0
- package/ai/rules/execution-flow.md +125 -0
- package/ai/rules/structural-constraints.md +59 -0
- package/ai/rules/structure-canon.md +116 -0
- package/ai/runtime.md +179 -0
- package/ai/scripts/detect-stack.ps1 +166 -0
- package/ai/scripts/detect-stack.sh +172 -0
- package/ai/scripts/init-ai-os.ps1 +170 -0
- package/ai/scripts/init-ai-os.sh +99 -0
- package/ai/scripts/lint-os.ps1 +99 -0
- package/ai/scripts/lint-os.sh +85 -0
- package/ai/scripts/start-os.ps1 +151 -0
- package/ai/scripts/start-os.sh +141 -0
- package/ai/server/README.md +105 -0
- package/ai/server/aios-server.mjs +2134 -0
- package/ai/server/package-lock.json +802 -0
- package/ai/server/package.json +31 -0
- package/ai/server/src/analyzer/graph-builder.ts +92 -0
- package/ai/server/src/analyzer/index.ts +191 -0
- package/ai/server/src/analyzer/module-mapper.ts +171 -0
- package/ai/server/src/analyzer/smell-detector.ts +54 -0
- package/ai/server/src/analyzer/stack-detector.ts +70 -0
- package/ai/server/src/index.ts +16 -0
- package/ai/server/src/packager/context-builder.ts +217 -0
- package/ai/server/src/packager/index.ts +3 -0
- package/ai/server/src/packager/memory-injector.ts +128 -0
- package/ai/server/src/packager/module-summarizer.ts +60 -0
- package/ai/server/src/packager/token-estimator.ts +26 -0
- package/ai/server/src/snapshot/index.ts +3 -0
- package/ai/server/src/snapshot/snapshot-creator.ts +206 -0
- package/ai/server/src/snapshot/snapshot-diff.ts +86 -0
- package/ai/server/src/snapshot/snapshot-restore.ts +14 -0
- package/ai/server/src/types.ts +94 -0
- package/ai/server/tsconfig.json +26 -0
- package/ai/skills/architecture-design.md +82 -0
- package/ai/skills/backend-engineering.md +57 -0
- package/ai/skills/database-design.md +76 -0
- package/ai/skills/frontend-engineering.md +63 -0
- package/ai/skills/performance.md +73 -0
- package/ai/skills/scalability.md +84 -0
- package/ai/skills/security.md +71 -0
- package/ai/skills/testing.md +77 -0
- package/ai/specs/ADR/ADR-0002-typescript-runtime.md +103 -0
- package/ai/specs/ADR/ADR-0004-runtime-orchestrator.md +94 -0
- package/ai/specs/ADR/ADR-0005-workflow-engine.md +105 -0
- package/ai/specs/ADR/ADR-0006-runtime-state.md +104 -0
- package/ai/specs/ADR/ADR-0007-state-compiler-drift-context-layers-artifact-index.md +82 -0
- package/ai/specs/ADR/ADR-0008-intent-runtime-discovery-branching.md +93 -0
- package/ai/specs/ADR/ADR-0009-confidence-system-maturity-tracking.md +113 -0
- package/ai/specs/ADR/ADR-0010-structural-architecture-standards.md +121 -0
- package/ai/specs/ADR/ADR-0011-mcp-prompts.md +86 -0
- package/ai/specs/ADR/ADR-0012-stealthos-hybrid-architecture.md +174 -0
- package/ai/specs/ADR/_TEMPLATE.md +60 -0
- package/ai/specs/BRD/_TEMPLATE.md +50 -0
- package/ai/specs/PRD/_TEMPLATE.md +72 -0
- package/ai/specs/README.md +43 -0
- package/ai/specs/RFC/RFC-0001-runtime-orchestrator.md +149 -0
- package/ai/specs/RFC/RFC-0002-runtime-orchestrator-extended.md +134 -0
- package/ai/specs/RFC/_TEMPLATE.md +61 -0
- package/ai/specs/RUNBOOKS/_TEMPLATE.md +68 -0
- package/ai/specs/SDD/_TEMPLATE.md +104 -0
- package/ai/specs/TASKS/_TEMPLATE.md +52 -0
- package/ai/tools/debugging.md +64 -0
- package/ai/tools/dependency-analysis.md +46 -0
- package/ai/tools/internet-research.md +42 -0
- package/ai/tools/mcp-discovery.md +44 -0
- package/ai/workflows/_schema.json +81 -0
- package/ai/workflows/init.json +148 -0
- package/ai/workflows/sync.json +71 -0
- package/ai/workflows/work.json +91 -0
- package/package.json +7 -1
- package/scripts/bundle-ai.mjs +58 -0
- package/src/cli.mjs +1 -1
- package/src/commands/install.mjs +35 -11
- package/src/lib/resolve-source.mjs +27 -10
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# detect-stack.ps1
|
|
2
|
+
# Inspeciona um projeto e produz um relatorio que pode pre-preencher project-context.md.
|
|
3
|
+
|
|
4
|
+
param(
|
|
5
|
+
[string]$TargetPath = (Get-Location).Path,
|
|
6
|
+
[string]$OutputPath = ""
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
$ErrorActionPreference = "Continue"
|
|
10
|
+
|
|
11
|
+
function Test-File($name) { Test-Path (Join-Path $TargetPath $name) }
|
|
12
|
+
function Test-Dir($name) { Test-Path (Join-Path $TargetPath $name) -PathType Container }
|
|
13
|
+
|
|
14
|
+
$findings = [ordered]@{
|
|
15
|
+
detected_at = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
|
|
16
|
+
target = $TargetPath
|
|
17
|
+
languages = @()
|
|
18
|
+
frameworks = @()
|
|
19
|
+
databases = @()
|
|
20
|
+
infra = @()
|
|
21
|
+
ci_cd = @()
|
|
22
|
+
test_frameworks = @()
|
|
23
|
+
linters = @()
|
|
24
|
+
formatters = @()
|
|
25
|
+
package_manager = $null
|
|
26
|
+
structure_style = $null
|
|
27
|
+
smells = @()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# ----- Linguagens -----
|
|
31
|
+
if (Test-File "package.json") { $findings.languages += "JavaScript/Node.js" }
|
|
32
|
+
if (Test-File "tsconfig.json") { $findings.languages += "TypeScript" }
|
|
33
|
+
if ((Test-File "pyproject.toml") -or (Test-File "requirements.txt") -or (Test-File "setup.py")) { $findings.languages += "Python" }
|
|
34
|
+
if (Test-File "Cargo.toml") { $findings.languages += "Rust" }
|
|
35
|
+
if (Test-File "go.mod") { $findings.languages += "Go" }
|
|
36
|
+
if ((Test-File "pom.xml") -or (Test-File "build.gradle") -or (Test-File "build.gradle.kts")) { $findings.languages += "Java/Kotlin/JVM" }
|
|
37
|
+
if (Test-File "composer.json") { $findings.languages += "PHP" }
|
|
38
|
+
if (Test-File "Gemfile") { $findings.languages += "Ruby" }
|
|
39
|
+
if (Test-File "mix.exs") { $findings.languages += "Elixir" }
|
|
40
|
+
if (Test-File "pubspec.yaml") { $findings.languages += "Dart/Flutter" }
|
|
41
|
+
$csproj = Get-ChildItem -Path $TargetPath -Filter "*.csproj" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
42
|
+
if ($csproj) { $findings.languages += ".NET (C#)" }
|
|
43
|
+
|
|
44
|
+
# ----- Package manager -----
|
|
45
|
+
if (Test-File "pnpm-lock.yaml") { $findings.package_manager = "pnpm" }
|
|
46
|
+
elseif (Test-File "yarn.lock") { $findings.package_manager = "yarn" }
|
|
47
|
+
elseif (Test-File "package-lock.json") { $findings.package_manager = "npm" }
|
|
48
|
+
elseif (Test-File "bun.lockb") { $findings.package_manager = "bun" }
|
|
49
|
+
elseif (Test-File "poetry.lock") { $findings.package_manager = "poetry" }
|
|
50
|
+
elseif (Test-File "Pipfile.lock") { $findings.package_manager = "pipenv" }
|
|
51
|
+
elseif (Test-File "Cargo.lock") { $findings.package_manager = "cargo" }
|
|
52
|
+
|
|
53
|
+
# ----- Frameworks (a partir de package.json) -----
|
|
54
|
+
if (Test-File "package.json") {
|
|
55
|
+
try {
|
|
56
|
+
$pkg = Get-Content (Join-Path $TargetPath "package.json") -Raw | ConvertFrom-Json
|
|
57
|
+
$allDeps = @{}
|
|
58
|
+
if ($pkg.dependencies) { $pkg.dependencies.PSObject.Properties | ForEach-Object { $allDeps[$_.Name] = $_.Value } }
|
|
59
|
+
if ($pkg.devDependencies) { $pkg.devDependencies.PSObject.Properties | ForEach-Object { $allDeps[$_.Name] = $_.Value } }
|
|
60
|
+
|
|
61
|
+
$frontendMap = @{ "react"="React"; "next"="Next.js"; "vue"="Vue"; "nuxt"="Nuxt"; "svelte"="Svelte"; "@sveltejs/kit"="SvelteKit"; "solid-js"="Solid"; "astro"="Astro"; "@angular/core"="Angular" }
|
|
62
|
+
$backendMap = @{ "express"="Express"; "fastify"="Fastify"; "@nestjs/core"="NestJS"; "koa"="Koa"; "hono"="Hono" }
|
|
63
|
+
$testMap = @{ "jest"="Jest"; "vitest"="Vitest"; "mocha"="Mocha"; "@playwright/test"="Playwright"; "cypress"="Cypress"; "@testing-library/react"="Testing Library" }
|
|
64
|
+
$dbMap = @{ "prisma"="Prisma"; "typeorm"="TypeORM"; "sequelize"="Sequelize"; "mongoose"="Mongoose"; "drizzle-orm"="Drizzle"; "pg"="PostgreSQL"; "mysql2"="MySQL"; "mongodb"="MongoDB"; "redis"="Redis"; "ioredis"="Redis" }
|
|
65
|
+
$linterMap = @{ "eslint"="ESLint"; "@biomejs/biome"="Biome"; "tslint"="TSLint" }
|
|
66
|
+
$formatterMap = @{ "prettier"="Prettier"; "@biomejs/biome"="Biome" }
|
|
67
|
+
|
|
68
|
+
foreach ($k in $frontendMap.Keys) { if ($allDeps.ContainsKey($k)) { $findings.frameworks += $frontendMap[$k] } }
|
|
69
|
+
foreach ($k in $backendMap.Keys) { if ($allDeps.ContainsKey($k)) { $findings.frameworks += $backendMap[$k] } }
|
|
70
|
+
foreach ($k in $testMap.Keys) { if ($allDeps.ContainsKey($k)) { $findings.test_frameworks += $testMap[$k] } }
|
|
71
|
+
foreach ($k in $dbMap.Keys) { if ($allDeps.ContainsKey($k)) { $findings.databases += $dbMap[$k] } }
|
|
72
|
+
foreach ($k in $linterMap.Keys) { if ($allDeps.ContainsKey($k)) { $findings.linters += $linterMap[$k] } }
|
|
73
|
+
foreach ($k in $formatterMap.Keys) { if ($allDeps.ContainsKey($k)) { $findings.formatters += $formatterMap[$k] } }
|
|
74
|
+
} catch {
|
|
75
|
+
Write-Host "[WARN] package.json malformado: $_" -ForegroundColor Yellow
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# ----- Python frameworks -----
|
|
80
|
+
if (Test-File "pyproject.toml") {
|
|
81
|
+
$content = Get-Content (Join-Path $TargetPath "pyproject.toml") -Raw -ErrorAction SilentlyContinue
|
|
82
|
+
if ($content -match "fastapi") { $findings.frameworks += "FastAPI" }
|
|
83
|
+
if ($content -match "django") { $findings.frameworks += "Django" }
|
|
84
|
+
if ($content -match "flask") { $findings.frameworks += "Flask" }
|
|
85
|
+
if ($content -match "pytest") { $findings.test_frameworks += "pytest" }
|
|
86
|
+
if ($content -match "ruff") { $findings.linters += "Ruff" }
|
|
87
|
+
if ($content -match "black") { $findings.formatters += "Black" }
|
|
88
|
+
if ($content -match "mypy") { $findings.linters += "mypy" }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# ----- Infra -----
|
|
92
|
+
if (Test-File "Dockerfile") { $findings.infra += "Docker" }
|
|
93
|
+
if ((Test-File "docker-compose.yml") -or (Test-File "docker-compose.yaml")) { $findings.infra += "Docker Compose" }
|
|
94
|
+
if (Test-Dir "terraform") { $findings.infra += "Terraform" }
|
|
95
|
+
if ((Test-Dir "kubernetes") -or (Test-Dir "k8s") -or (Test-Dir "helm")) { $findings.infra += "Kubernetes" }
|
|
96
|
+
if ((Test-File "serverless.yml") -or (Test-File "sam-template.yaml")) { $findings.infra += "Serverless" }
|
|
97
|
+
|
|
98
|
+
# ----- CI/CD -----
|
|
99
|
+
if (Test-Dir ".github\workflows") { $findings.ci_cd += "GitHub Actions" }
|
|
100
|
+
if (Test-File ".gitlab-ci.yml") { $findings.ci_cd += "GitLab CI" }
|
|
101
|
+
if (Test-File "Jenkinsfile") { $findings.ci_cd += "Jenkins" }
|
|
102
|
+
if (Test-File ".circleci\config.yml") { $findings.ci_cd += "CircleCI" }
|
|
103
|
+
if ((Test-File "azure-pipelines.yml") -or (Test-File "azure-pipelines.yaml")) { $findings.ci_cd += "Azure Pipelines" }
|
|
104
|
+
|
|
105
|
+
# ----- Configs detectados -----
|
|
106
|
+
if (Test-File ".editorconfig") { $findings.formatters += "EditorConfig" }
|
|
107
|
+
if ((Test-File ".prettierrc") -or (Test-File ".prettierrc.json") -or (Test-File "prettier.config.js")) {
|
|
108
|
+
if ($findings.formatters -notcontains "Prettier") { $findings.formatters += "Prettier" }
|
|
109
|
+
}
|
|
110
|
+
if ((Test-File ".eslintrc") -or (Test-File ".eslintrc.json") -or (Test-File "eslint.config.js")) {
|
|
111
|
+
if ($findings.linters -notcontains "ESLint") { $findings.linters += "ESLint" }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# ----- Smells -----
|
|
115
|
+
if ((Test-File ".env") -and -not (Test-File ".gitignore")) {
|
|
116
|
+
$findings.smells += "Possivel commit de .env (sem .gitignore)"
|
|
117
|
+
} elseif (Test-File ".env") {
|
|
118
|
+
$gitignore = Get-Content (Join-Path $TargetPath ".gitignore") -Raw -ErrorAction SilentlyContinue
|
|
119
|
+
if ($gitignore -and $gitignore -notmatch "\.env") {
|
|
120
|
+
$findings.smells += ".env nao esta no .gitignore"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (Test-Dir "node_modules") {
|
|
125
|
+
$gitignore = Get-Content (Join-Path $TargetPath ".gitignore") -Raw -ErrorAction SilentlyContinue
|
|
126
|
+
if ($gitignore -and $gitignore -notmatch "node_modules") {
|
|
127
|
+
$findings.smells += "node_modules nao esta no .gitignore"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if ($findings.test_frameworks.Count -eq 0 -and $findings.languages.Count -gt 0) {
|
|
132
|
+
$findings.smells += "Nenhum framework de teste detectado"
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if ($findings.ci_cd.Count -eq 0 -and $findings.languages.Count -gt 0) {
|
|
136
|
+
$findings.smells += "Nenhuma config de CI/CD detectada"
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (-not (Test-File "README.md")) {
|
|
140
|
+
$findings.smells += "README.md ausente"
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
# Dedup
|
|
144
|
+
foreach ($k in @("languages","frameworks","databases","infra","ci_cd","test_frameworks","linters","formatters","smells")) {
|
|
145
|
+
if ($findings[$k]) { $findings[$k] = @($findings[$k] | Sort-Object -Unique) }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
# ----- Output -----
|
|
149
|
+
$json = $findings | ConvertTo-Json -Depth 5
|
|
150
|
+
Write-Host ""
|
|
151
|
+
Write-Host "----- Stack Detection Report -----" -ForegroundColor Cyan
|
|
152
|
+
Write-Host $json
|
|
153
|
+
Write-Host "----------------------------------" -ForegroundColor Cyan
|
|
154
|
+
|
|
155
|
+
if ($OutputPath) {
|
|
156
|
+
$json | Out-File -FilePath $OutputPath -Encoding utf8
|
|
157
|
+
Write-Host ""
|
|
158
|
+
Write-Host "Relatorio salvo em: $OutputPath" -ForegroundColor Green
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# Salvar tambem em .ai/memory/_detected-stack.json para o agente consumir
|
|
162
|
+
$autoOut = Join-Path $TargetPath ".ai\memory\_detected-stack.json"
|
|
163
|
+
if (Test-Path (Join-Path $TargetPath ".ai\memory")) {
|
|
164
|
+
$json | Out-File -FilePath $autoOut -Encoding utf8
|
|
165
|
+
Write-Host "Cache salvo em: $autoOut" -ForegroundColor Green
|
|
166
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# detect-stack.sh - Inspeciona projeto e produz relatorio JSON (macOS/Linux)
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
TARGET="$(pwd)"
|
|
6
|
+
OUTPUT=""
|
|
7
|
+
|
|
8
|
+
while [[ $# -gt 0 ]]; do
|
|
9
|
+
case "$1" in
|
|
10
|
+
--target) TARGET="$2"; shift 2 ;;
|
|
11
|
+
--output) OUTPUT="$2"; shift 2 ;;
|
|
12
|
+
*) echo "Arg desconhecido: $1" >&2; exit 1 ;;
|
|
13
|
+
esac
|
|
14
|
+
done
|
|
15
|
+
|
|
16
|
+
has_file() { [[ -f "$TARGET/$1" ]]; }
|
|
17
|
+
has_dir() { [[ -d "$TARGET/$1" ]]; }
|
|
18
|
+
file_grep() { [[ -f "$TARGET/$1" ]] && grep -q "$2" "$TARGET/$1" 2>/dev/null; }
|
|
19
|
+
|
|
20
|
+
# Arrays
|
|
21
|
+
declare -a LANGS=()
|
|
22
|
+
declare -a FRAMEWORKS=()
|
|
23
|
+
declare -a DBS=()
|
|
24
|
+
declare -a INFRA=()
|
|
25
|
+
declare -a CI=()
|
|
26
|
+
declare -a TESTS=()
|
|
27
|
+
declare -a LINTERS=()
|
|
28
|
+
declare -a FORMATTERS=()
|
|
29
|
+
declare -a SMELLS=()
|
|
30
|
+
PKG_MGR=""
|
|
31
|
+
|
|
32
|
+
# Linguagens
|
|
33
|
+
has_file "package.json" && LANGS+=("JavaScript/Node.js")
|
|
34
|
+
has_file "tsconfig.json" && LANGS+=("TypeScript")
|
|
35
|
+
{ has_file "pyproject.toml" || has_file "requirements.txt" || has_file "setup.py"; } && LANGS+=("Python")
|
|
36
|
+
has_file "Cargo.toml" && LANGS+=("Rust")
|
|
37
|
+
has_file "go.mod" && LANGS+=("Go")
|
|
38
|
+
{ has_file "pom.xml" || has_file "build.gradle" || has_file "build.gradle.kts"; } && LANGS+=("Java/Kotlin/JVM")
|
|
39
|
+
has_file "composer.json" && LANGS+=("PHP")
|
|
40
|
+
has_file "Gemfile" && LANGS+=("Ruby")
|
|
41
|
+
has_file "mix.exs" && LANGS+=("Elixir")
|
|
42
|
+
has_file "pubspec.yaml" && LANGS+=("Dart/Flutter")
|
|
43
|
+
ls "$TARGET"/*.csproj 2>/dev/null | head -1 >/dev/null 2>&1 && LANGS+=(".NET (C#)")
|
|
44
|
+
|
|
45
|
+
# Package manager
|
|
46
|
+
has_file "pnpm-lock.yaml" && PKG_MGR="pnpm"
|
|
47
|
+
[[ -z "$PKG_MGR" ]] && has_file "yarn.lock" && PKG_MGR="yarn"
|
|
48
|
+
[[ -z "$PKG_MGR" ]] && has_file "package-lock.json" && PKG_MGR="npm"
|
|
49
|
+
[[ -z "$PKG_MGR" ]] && has_file "bun.lockb" && PKG_MGR="bun"
|
|
50
|
+
[[ -z "$PKG_MGR" ]] && has_file "poetry.lock" && PKG_MGR="poetry"
|
|
51
|
+
[[ -z "$PKG_MGR" ]] && has_file "Pipfile.lock" && PKG_MGR="pipenv"
|
|
52
|
+
[[ -z "$PKG_MGR" ]] && has_file "Cargo.lock" && PKG_MGR="cargo"
|
|
53
|
+
|
|
54
|
+
# Frameworks via package.json
|
|
55
|
+
if has_file "package.json"; then
|
|
56
|
+
PKG="$TARGET/package.json"
|
|
57
|
+
grep -q '"react"' "$PKG" && FRAMEWORKS+=("React")
|
|
58
|
+
grep -q '"next"' "$PKG" && FRAMEWORKS+=("Next.js")
|
|
59
|
+
grep -q '"vue"' "$PKG" && FRAMEWORKS+=("Vue")
|
|
60
|
+
grep -q '"nuxt"' "$PKG" && FRAMEWORKS+=("Nuxt")
|
|
61
|
+
grep -q '"svelte"' "$PKG" && FRAMEWORKS+=("Svelte")
|
|
62
|
+
grep -q '"@sveltejs/kit"' "$PKG" && FRAMEWORKS+=("SvelteKit")
|
|
63
|
+
grep -q '"solid-js"' "$PKG" && FRAMEWORKS+=("Solid")
|
|
64
|
+
grep -q '"astro"' "$PKG" && FRAMEWORKS+=("Astro")
|
|
65
|
+
grep -q '"@angular/core"' "$PKG" && FRAMEWORKS+=("Angular")
|
|
66
|
+
grep -q '"express"' "$PKG" && FRAMEWORKS+=("Express")
|
|
67
|
+
grep -q '"fastify"' "$PKG" && FRAMEWORKS+=("Fastify")
|
|
68
|
+
grep -q '"@nestjs/core"' "$PKG" && FRAMEWORKS+=("NestJS")
|
|
69
|
+
grep -q '"koa"' "$PKG" && FRAMEWORKS+=("Koa")
|
|
70
|
+
grep -q '"hono"' "$PKG" && FRAMEWORKS+=("Hono")
|
|
71
|
+
grep -q '"jest"' "$PKG" && TESTS+=("Jest")
|
|
72
|
+
grep -q '"vitest"' "$PKG" && TESTS+=("Vitest")
|
|
73
|
+
grep -q '"mocha"' "$PKG" && TESTS+=("Mocha")
|
|
74
|
+
grep -q '"@playwright/test"' "$PKG" && TESTS+=("Playwright")
|
|
75
|
+
grep -q '"cypress"' "$PKG" && TESTS+=("Cypress")
|
|
76
|
+
grep -q '"@testing-library/react"' "$PKG" && TESTS+=("Testing Library")
|
|
77
|
+
grep -q '"prisma"' "$PKG" && DBS+=("Prisma")
|
|
78
|
+
grep -q '"typeorm"' "$PKG" && DBS+=("TypeORM")
|
|
79
|
+
grep -q '"sequelize"' "$PKG" && DBS+=("Sequelize")
|
|
80
|
+
grep -q '"mongoose"' "$PKG" && DBS+=("Mongoose")
|
|
81
|
+
grep -q '"drizzle-orm"' "$PKG" && DBS+=("Drizzle")
|
|
82
|
+
grep -q '"pg"' "$PKG" && DBS+=("PostgreSQL")
|
|
83
|
+
grep -q '"mysql2"' "$PKG" && DBS+=("MySQL")
|
|
84
|
+
grep -q '"mongodb"' "$PKG" && DBS+=("MongoDB")
|
|
85
|
+
grep -q '"redis"\|"ioredis"' "$PKG" && DBS+=("Redis")
|
|
86
|
+
grep -q '"eslint"' "$PKG" && LINTERS+=("ESLint")
|
|
87
|
+
grep -q '"@biomejs/biome"' "$PKG" && { LINTERS+=("Biome"); FORMATTERS+=("Biome"); }
|
|
88
|
+
grep -q '"prettier"' "$PKG" && FORMATTERS+=("Prettier")
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# Python frameworks
|
|
92
|
+
if has_file "pyproject.toml"; then
|
|
93
|
+
file_grep "pyproject.toml" "fastapi" && FRAMEWORKS+=("FastAPI")
|
|
94
|
+
file_grep "pyproject.toml" "django" && FRAMEWORKS+=("Django")
|
|
95
|
+
file_grep "pyproject.toml" "flask" && FRAMEWORKS+=("Flask")
|
|
96
|
+
file_grep "pyproject.toml" "pytest" && TESTS+=("pytest")
|
|
97
|
+
file_grep "pyproject.toml" "ruff" && LINTERS+=("Ruff")
|
|
98
|
+
file_grep "pyproject.toml" "black" && FORMATTERS+=("Black")
|
|
99
|
+
file_grep "pyproject.toml" "mypy" && LINTERS+=("mypy")
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# Infra
|
|
103
|
+
has_file "Dockerfile" && INFRA+=("Docker")
|
|
104
|
+
{ has_file "docker-compose.yml" || has_file "docker-compose.yaml"; } && INFRA+=("Docker Compose")
|
|
105
|
+
has_dir "terraform" && INFRA+=("Terraform")
|
|
106
|
+
{ has_dir "kubernetes" || has_dir "k8s" || has_dir "helm"; } && INFRA+=("Kubernetes")
|
|
107
|
+
{ has_file "serverless.yml" || has_file "sam-template.yaml"; } && INFRA+=("Serverless")
|
|
108
|
+
|
|
109
|
+
# CI/CD
|
|
110
|
+
has_dir ".github/workflows" && CI+=("GitHub Actions")
|
|
111
|
+
has_file ".gitlab-ci.yml" && CI+=("GitLab CI")
|
|
112
|
+
has_file "Jenkinsfile" && CI+=("Jenkins")
|
|
113
|
+
has_file ".circleci/config.yml" && CI+=("CircleCI")
|
|
114
|
+
{ has_file "azure-pipelines.yml" || has_file "azure-pipelines.yaml"; } && CI+=("Azure Pipelines")
|
|
115
|
+
|
|
116
|
+
# Configs
|
|
117
|
+
has_file ".editorconfig" && FORMATTERS+=("EditorConfig")
|
|
118
|
+
{ has_file ".prettierrc" || has_file ".prettierrc.json" || has_file "prettier.config.js"; } && FORMATTERS+=("Prettier")
|
|
119
|
+
{ has_file ".eslintrc" || has_file ".eslintrc.json" || has_file "eslint.config.js"; } && LINTERS+=("ESLint")
|
|
120
|
+
|
|
121
|
+
# Smells
|
|
122
|
+
if has_file ".env" && has_file ".gitignore" && ! grep -q '\.env' "$TARGET/.gitignore"; then
|
|
123
|
+
SMELLS+=(".env nao esta no .gitignore")
|
|
124
|
+
fi
|
|
125
|
+
if has_dir "node_modules" && has_file ".gitignore" && ! grep -q "node_modules" "$TARGET/.gitignore"; then
|
|
126
|
+
SMELLS+=("node_modules nao esta no .gitignore")
|
|
127
|
+
fi
|
|
128
|
+
[[ ${#TESTS[@]} -eq 0 && ${#LANGS[@]} -gt 0 ]] && SMELLS+=("Nenhum framework de teste detectado")
|
|
129
|
+
[[ ${#CI[@]} -eq 0 && ${#LANGS[@]} -gt 0 ]] && SMELLS+=("Nenhuma config de CI/CD detectada")
|
|
130
|
+
! has_file "README.md" && SMELLS+=("README.md ausente")
|
|
131
|
+
|
|
132
|
+
# Dedup helper
|
|
133
|
+
dedup_join() {
|
|
134
|
+
local IFS=$'\n'
|
|
135
|
+
local sorted=($(printf "%s\n" "$@" | awk '!x[$0]++'))
|
|
136
|
+
local first=1
|
|
137
|
+
printf "["
|
|
138
|
+
for s in "${sorted[@]}"; do
|
|
139
|
+
[[ $first -eq 0 ]] && printf ","
|
|
140
|
+
printf '"%s"' "$s"
|
|
141
|
+
first=0
|
|
142
|
+
done
|
|
143
|
+
printf "]"
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
DATE=$(date "+%Y-%m-%d %H:%M:%S")
|
|
147
|
+
JSON=$(cat <<EOF
|
|
148
|
+
{
|
|
149
|
+
"detected_at": "$DATE",
|
|
150
|
+
"target": "$TARGET",
|
|
151
|
+
"languages": $(dedup_join "${LANGS[@]:-}"),
|
|
152
|
+
"frameworks": $(dedup_join "${FRAMEWORKS[@]:-}"),
|
|
153
|
+
"databases": $(dedup_join "${DBS[@]:-}"),
|
|
154
|
+
"infra": $(dedup_join "${INFRA[@]:-}"),
|
|
155
|
+
"ci_cd": $(dedup_join "${CI[@]:-}"),
|
|
156
|
+
"test_frameworks": $(dedup_join "${TESTS[@]:-}"),
|
|
157
|
+
"linters": $(dedup_join "${LINTERS[@]:-}"),
|
|
158
|
+
"formatters": $(dedup_join "${FORMATTERS[@]:-}"),
|
|
159
|
+
"package_manager": "$PKG_MGR",
|
|
160
|
+
"smells": $(dedup_join "${SMELLS[@]:-}")
|
|
161
|
+
}
|
|
162
|
+
EOF
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
echo "----- Stack Detection Report -----"
|
|
166
|
+
echo "$JSON"
|
|
167
|
+
echo "----------------------------------"
|
|
168
|
+
|
|
169
|
+
[[ -n "$OUTPUT" ]] && echo "$JSON" > "$OUTPUT" && echo "Salvo em: $OUTPUT"
|
|
170
|
+
|
|
171
|
+
AUTO_OUT="$TARGET/.ai/memory/_detected-stack.json"
|
|
172
|
+
[[ -d "$TARGET/.ai/memory" ]] && echo "$JSON" > "$AUTO_OUT" && echo "Cache: $AUTO_OUT"
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# init-ai-os.ps1
|
|
2
|
+
# Inicializa ou verifica o AI Operating System em um projeto.
|
|
3
|
+
# Uso:
|
|
4
|
+
# .\scripts\init-ai-os.ps1 # interativo
|
|
5
|
+
# .\scripts\init-ai-os.ps1 -Mode new # forca novo
|
|
6
|
+
# .\scripts\init-ai-os.ps1 -Mode existing # forca existente
|
|
7
|
+
# .\scripts\init-ai-os.ps1 -Verify # so verifica integridade
|
|
8
|
+
# .\scripts\init-ai-os.ps1 -TargetPath C:\path\to\project
|
|
9
|
+
|
|
10
|
+
param(
|
|
11
|
+
[ValidateSet("auto", "new", "existing", "verify")]
|
|
12
|
+
[string]$Mode = "auto",
|
|
13
|
+
|
|
14
|
+
[string]$TargetPath = (Get-Location).Path,
|
|
15
|
+
|
|
16
|
+
[string]$TemplateRoot = (Split-Path (Split-Path $PSScriptRoot -Parent) -Parent),
|
|
17
|
+
|
|
18
|
+
[switch]$Verify
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
if ($Verify) { $Mode = "verify" }
|
|
22
|
+
|
|
23
|
+
$ErrorActionPreference = "Stop"
|
|
24
|
+
|
|
25
|
+
function Write-Section($text) {
|
|
26
|
+
Write-Host ""
|
|
27
|
+
Write-Host "=== $text ===" -ForegroundColor Cyan
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function Write-Ok($text) { Write-Host "[OK] $text" -ForegroundColor Green }
|
|
31
|
+
function Write-Warn($text) { Write-Host "[WARN] $text" -ForegroundColor Yellow }
|
|
32
|
+
function Write-Err($text) { Write-Host "[ERR] $text" -ForegroundColor Red }
|
|
33
|
+
|
|
34
|
+
# ----- Detect mode if auto -----
|
|
35
|
+
function Get-ProjectMode {
|
|
36
|
+
param([string]$Path)
|
|
37
|
+
|
|
38
|
+
$aiExists = Test-Path (Join-Path $Path ".ai")
|
|
39
|
+
$hasCode = @(
|
|
40
|
+
"package.json", "pyproject.toml", "requirements.txt", "Cargo.toml",
|
|
41
|
+
"go.mod", "pom.xml", "build.gradle", "composer.json", "Gemfile",
|
|
42
|
+
"mix.exs", "pubspec.yaml"
|
|
43
|
+
) | Where-Object { Test-Path (Join-Path $Path $_) }
|
|
44
|
+
|
|
45
|
+
if ($aiExists) { return "verify" }
|
|
46
|
+
if ($hasCode.Count -gt 0) { return "existing" }
|
|
47
|
+
return "new"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if ($Mode -eq "auto") {
|
|
51
|
+
$Mode = Get-ProjectMode -Path $TargetPath
|
|
52
|
+
Write-Host "Modo detectado: $Mode"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# ----- VERIFY MODE -----
|
|
56
|
+
if ($Mode -eq "verify") {
|
|
57
|
+
Write-Section "Verificando integridade do AI OS em $TargetPath"
|
|
58
|
+
|
|
59
|
+
$manifestPath = Join-Path $TargetPath ".ai\manifest.json"
|
|
60
|
+
if (-not (Test-Path $manifestPath)) {
|
|
61
|
+
Write-Err "manifest.json nao encontrado em .ai/. OS pode estar quebrado."
|
|
62
|
+
exit 1
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
$manifest = Get-Content $manifestPath -Raw | ConvertFrom-Json
|
|
66
|
+
$missing = @()
|
|
67
|
+
foreach ($f in $manifest.required_files) {
|
|
68
|
+
$full = Join-Path $TargetPath ($f -replace '/', '\')
|
|
69
|
+
if (-not (Test-Path $full)) {
|
|
70
|
+
$missing += $f
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if ($missing.Count -eq 0) {
|
|
75
|
+
Write-Ok "Todos os $($manifest.required_files.Count) arquivos obrigatorios presentes."
|
|
76
|
+
} else {
|
|
77
|
+
Write-Err "$($missing.Count) arquivos faltando:"
|
|
78
|
+
$missing | ForEach-Object { Write-Host " - $_" }
|
|
79
|
+
exit 1
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Link lint
|
|
83
|
+
Write-Section "Validando links cruzados"
|
|
84
|
+
& (Join-Path $PSScriptRoot "lint-os.ps1") -TargetPath $TargetPath
|
|
85
|
+
exit $LASTEXITCODE
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# ----- NEW MODE -----
|
|
89
|
+
if ($Mode -eq "new") {
|
|
90
|
+
Write-Section "Bootstrap: projeto NOVO em $TargetPath"
|
|
91
|
+
|
|
92
|
+
if (Test-Path (Join-Path $TargetPath ".ai")) {
|
|
93
|
+
Write-Warn ".ai/ ja existe. Use -Mode verify para checar integridade ou -Mode existing para retrofit."
|
|
94
|
+
exit 1
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Copia template
|
|
98
|
+
$templateAi = Join-Path $TemplateRoot ".ai"
|
|
99
|
+
$templateClaude = Join-Path $TemplateRoot ".claude"
|
|
100
|
+
$templateEntries = @("CLAUDE.md", "GEMINI.md", "GPT.md")
|
|
101
|
+
|
|
102
|
+
if (-not (Test-Path $templateAi)) {
|
|
103
|
+
Write-Err "Template .ai/ nao encontrado em $TemplateRoot. Rode este script a partir do diretorio raiz do template."
|
|
104
|
+
exit 1
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
Copy-Item $templateAi (Join-Path $TargetPath ".ai") -Recurse
|
|
108
|
+
Write-Ok "Estrutura .ai/ copiada."
|
|
109
|
+
|
|
110
|
+
if (Test-Path $templateClaude) {
|
|
111
|
+
Copy-Item $templateClaude (Join-Path $TargetPath ".claude") -Recurse
|
|
112
|
+
Write-Ok "Hooks .claude/ copiados."
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
foreach ($entry in $templateEntries) {
|
|
116
|
+
$src = Join-Path $TemplateRoot $entry
|
|
117
|
+
$dst = Join-Path $TargetPath $entry
|
|
118
|
+
if ((Test-Path $src) -and -not (Test-Path $dst)) {
|
|
119
|
+
Copy-Item $src $dst
|
|
120
|
+
Write-Ok "Entry point $entry copiado."
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
Write-Host ""
|
|
125
|
+
Write-Host "Proximo passo: abra Claude Code / Gemini / GPT neste diretorio."
|
|
126
|
+
Write-Host "O agente seguira o fluxo de bootstrap/new-project.md automaticamente."
|
|
127
|
+
exit 0
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
# ----- EXISTING MODE -----
|
|
131
|
+
if ($Mode -eq "existing") {
|
|
132
|
+
Write-Section "Bootstrap: projeto EXISTENTE em $TargetPath"
|
|
133
|
+
|
|
134
|
+
if (-not (Test-Path (Join-Path $TargetPath ".ai"))) {
|
|
135
|
+
# Copia o template
|
|
136
|
+
$templateAi = Join-Path $TemplateRoot ".ai"
|
|
137
|
+
if (-not (Test-Path $templateAi)) {
|
|
138
|
+
Write-Err "Template .ai/ nao encontrado em $TemplateRoot."
|
|
139
|
+
exit 1
|
|
140
|
+
}
|
|
141
|
+
Copy-Item $templateAi (Join-Path $TargetPath ".ai") -Recurse
|
|
142
|
+
Write-Ok "Estrutura .ai/ enxertada no projeto."
|
|
143
|
+
|
|
144
|
+
$templateClaude = Join-Path $TemplateRoot ".claude"
|
|
145
|
+
if (Test-Path $templateClaude) {
|
|
146
|
+
Copy-Item $templateClaude (Join-Path $TargetPath ".claude") -Recurse
|
|
147
|
+
Write-Ok "Hooks .claude/ enxertados."
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@("CLAUDE.md", "GEMINI.md", "GPT.md") | ForEach-Object {
|
|
151
|
+
$src = Join-Path $TemplateRoot $_
|
|
152
|
+
$dst = Join-Path $TargetPath $_
|
|
153
|
+
if ((Test-Path $src) -and -not (Test-Path $dst)) {
|
|
154
|
+
Copy-Item $src $dst
|
|
155
|
+
Write-Ok "Entry point $_ enxertado."
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
Write-Ok ".ai/ ja existe — pulando copia."
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
# Detectar stack e gerar pre-fill de project-context.md
|
|
163
|
+
Write-Section "Detectando stack do projeto"
|
|
164
|
+
& (Join-Path $PSScriptRoot "detect-stack.ps1") -TargetPath $TargetPath
|
|
165
|
+
Write-Host ""
|
|
166
|
+
Write-Host "Proximo passo: abra Claude Code / Gemini / GPT neste diretorio."
|
|
167
|
+
Write-Host "O agente seguira o fluxo de bootstrap/existing-project.md."
|
|
168
|
+
Write-Host "Ele vai validar a deteccao com voce e completar o que falta via discovery-questions."
|
|
169
|
+
exit 0
|
|
170
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# init-ai-os.sh - Equivalente Unix do init-ai-os.ps1
|
|
3
|
+
# Uso:
|
|
4
|
+
# ./scripts/init-ai-os.sh # auto
|
|
5
|
+
# ./scripts/init-ai-os.sh --mode new
|
|
6
|
+
# ./scripts/init-ai-os.sh --mode existing
|
|
7
|
+
# ./scripts/init-ai-os.sh --verify
|
|
8
|
+
# ./scripts/init-ai-os.sh --target /path/to/project
|
|
9
|
+
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
MODE="auto"
|
|
13
|
+
TARGET="$(pwd)"
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
TEMPLATE_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
|
16
|
+
|
|
17
|
+
while [[ $# -gt 0 ]]; do
|
|
18
|
+
case "$1" in
|
|
19
|
+
--mode) MODE="$2"; shift 2 ;;
|
|
20
|
+
--target) TARGET="$2"; shift 2 ;;
|
|
21
|
+
--verify) MODE="verify"; shift ;;
|
|
22
|
+
--template-root) TEMPLATE_ROOT="$2"; shift 2 ;;
|
|
23
|
+
*) echo "Arg desconhecido: $1"; exit 1 ;;
|
|
24
|
+
esac
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
c_cyan='\033[0;36m'; c_green='\033[0;32m'; c_yellow='\033[0;33m'; c_red='\033[0;31m'; c_reset='\033[0m'
|
|
28
|
+
section() { echo -e "\n${c_cyan}=== $1 ===${c_reset}"; }
|
|
29
|
+
ok() { echo -e "${c_green}[OK]${c_reset} $1"; }
|
|
30
|
+
warn() { echo -e "${c_yellow}[WARN]${c_reset} $1"; }
|
|
31
|
+
err() { echo -e "${c_red}[ERR]${c_reset} $1"; }
|
|
32
|
+
|
|
33
|
+
detect_mode() {
|
|
34
|
+
[[ -d "$TARGET/.ai" ]] && { echo "verify"; return; }
|
|
35
|
+
for f in package.json pyproject.toml requirements.txt Cargo.toml go.mod pom.xml build.gradle composer.json Gemfile mix.exs pubspec.yaml; do
|
|
36
|
+
[[ -f "$TARGET/$f" ]] && { echo "existing"; return; }
|
|
37
|
+
done
|
|
38
|
+
echo "new"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if [[ "$MODE" == "auto" ]]; then
|
|
42
|
+
MODE=$(detect_mode)
|
|
43
|
+
echo "Modo detectado: $MODE"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
case "$MODE" in
|
|
47
|
+
verify)
|
|
48
|
+
section "Verificando integridade em $TARGET"
|
|
49
|
+
[[ -f "$TARGET/.ai/manifest.json" ]] || { err "manifest.json ausente"; exit 1; }
|
|
50
|
+
# Requer jq
|
|
51
|
+
if ! command -v jq &>/dev/null; then
|
|
52
|
+
warn "jq nao instalado — pulando validacao detalhada"
|
|
53
|
+
exit 0
|
|
54
|
+
fi
|
|
55
|
+
missing=()
|
|
56
|
+
while IFS= read -r f; do
|
|
57
|
+
[[ -e "$TARGET/$f" ]] || missing+=("$f")
|
|
58
|
+
done < <(jq -r '.required_files[]' "$TARGET/.ai/manifest.json")
|
|
59
|
+
if [[ ${#missing[@]} -eq 0 ]]; then
|
|
60
|
+
ok "Todos os arquivos obrigatorios presentes."
|
|
61
|
+
else
|
|
62
|
+
err "Faltando: ${missing[*]}"
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
;;
|
|
66
|
+
|
|
67
|
+
new)
|
|
68
|
+
section "Bootstrap: projeto NOVO em $TARGET"
|
|
69
|
+
[[ -d "$TARGET/.ai" ]] && { warn ".ai/ ja existe"; exit 1; }
|
|
70
|
+
[[ -d "$TEMPLATE_ROOT/.ai" ]] || { err "template .ai/ ausente em $TEMPLATE_ROOT"; exit 1; }
|
|
71
|
+
cp -r "$TEMPLATE_ROOT/.ai" "$TARGET/.ai" && ok ".ai/ copiado"
|
|
72
|
+
[[ -d "$TEMPLATE_ROOT/.claude" ]] && cp -r "$TEMPLATE_ROOT/.claude" "$TARGET/.claude" && ok ".claude/ copiado"
|
|
73
|
+
for e in CLAUDE.md GEMINI.md GPT.md; do
|
|
74
|
+
[[ -f "$TEMPLATE_ROOT/$e" && ! -f "$TARGET/$e" ]] && cp "$TEMPLATE_ROOT/$e" "$TARGET/$e" && ok "$e copiado"
|
|
75
|
+
done
|
|
76
|
+
echo "Proximo passo: abra Claude Code/Gemini/GPT — o agente seguira bootstrap/new-project.md."
|
|
77
|
+
;;
|
|
78
|
+
|
|
79
|
+
existing)
|
|
80
|
+
section "Bootstrap: projeto EXISTENTE em $TARGET"
|
|
81
|
+
if [[ ! -d "$TARGET/.ai" ]]; then
|
|
82
|
+
cp -r "$TEMPLATE_ROOT/.ai" "$TARGET/.ai" && ok ".ai/ enxertado"
|
|
83
|
+
[[ -d "$TEMPLATE_ROOT/.claude" ]] && cp -r "$TEMPLATE_ROOT/.claude" "$TARGET/.claude" && ok ".claude/ enxertado"
|
|
84
|
+
for e in CLAUDE.md GEMINI.md GPT.md; do
|
|
85
|
+
[[ -f "$TEMPLATE_ROOT/$e" && ! -f "$TARGET/$e" ]] && cp "$TEMPLATE_ROOT/$e" "$TARGET/$e" && ok "$e enxertado"
|
|
86
|
+
done
|
|
87
|
+
else
|
|
88
|
+
ok ".ai/ ja existe"
|
|
89
|
+
fi
|
|
90
|
+
section "Detectando stack"
|
|
91
|
+
[[ -x "$SCRIPT_DIR/detect-stack.sh" ]] && "$SCRIPT_DIR/detect-stack.sh" --target "$TARGET" || warn "detect-stack.sh nao encontrado/executavel (use a versao .ps1 ou crie equivalente)"
|
|
92
|
+
echo "Proximo passo: abra Claude Code/Gemini/GPT — o agente seguira bootstrap/existing-project.md."
|
|
93
|
+
;;
|
|
94
|
+
|
|
95
|
+
*)
|
|
96
|
+
err "Modo invalido: $MODE"
|
|
97
|
+
exit 1
|
|
98
|
+
;;
|
|
99
|
+
esac
|