ganbatte-os 0.2.41 → 0.2.42

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 (78) hide show
  1. package/.gos/README.md +2 -6
  2. package/.gos/agents/profiles/ganbatte-os-master.md +91 -58
  3. package/.gos/agents/profiles/index.json +3 -1
  4. package/.gos/agents/profiles/perf-optimizer.md +10 -0
  5. package/.gos/agents/profiles/po.md +1 -1
  6. package/.gos/agents/profiles/security-auditor.md +11 -0
  7. package/.gos/agents/profiles/sm.md +4 -4
  8. package/.gos/agents/profiles/squad-creator.md +2 -2
  9. package/.gos/config.json +23 -2
  10. package/.gos/docs/curation.md +8 -6
  11. package/.gos/docs/gos_installation_guide.md +1 -1
  12. package/.gos/docs/plan-distribuicao-publica.md +2 -3
  13. package/.gos/docs/toolchain-map.md +2 -2
  14. package/.gos/libraries/doc-sync-policy.md +31 -0
  15. package/.gos/libraries/lazy-dev-policy.md +38 -0
  16. package/.gos/libraries/lucide-icons-policy.md +1 -1
  17. package/.gos/libraries/performance-audit-playbook.md +54 -0
  18. package/.gos/libraries/security-audit-playbook.md +63 -0
  19. package/.gos/manifests/g-os-runtime-manifest.json +29 -8
  20. package/.gos/playbooks/plan-creation-playbook.md +3 -5
  21. package/.gos/prompts/01-search.md +2 -2
  22. package/.gos/prompts/03-tasks.md +4 -4
  23. package/.gos/prompts/05-reviews.md +1 -1
  24. package/.gos/scripts/cli/gos-cli.js +16 -0
  25. package/.gos/scripts/hooks/claude-stop-summary.js +0 -16
  26. package/.gos/scripts/integrations/check-plan.js +15 -5
  27. package/.gos/scripts/integrations/setup-ide-adapters.js +72 -75
  28. package/.gos/scripts/tools/model-router.js +122 -0
  29. package/.gos/skills/execute-plan/SKILL.md +37 -23
  30. package/.gos/skills/perf-review/SKILL.md +58 -0
  31. package/.gos/skills/plan-blueprint/SKILL.md +26 -26
  32. package/.gos/skills/plan-to-tasks/SKILL.md +4 -1
  33. package/.gos/skills/progress-tracker/SKILL.md +3 -3
  34. package/.gos/skills/registry.json +3 -4
  35. package/.gos/skills/security-review/SKILL.md +59 -0
  36. package/.gos/skills/simplify-review/SKILL.md +59 -0
  37. package/.gos/skills/validate-plan/SKILL.md +29 -30
  38. package/.gos/squads/code-quality/README.md +20 -0
  39. package/.gos/squads/code-quality/squad.yaml +32 -0
  40. package/.gos/squads/code-quality/workflows/wf-code-quality.yaml +19 -0
  41. package/.gos/squads/design-delivery/README.md +1 -1
  42. package/.gos/squads/design-delivery/squad.yaml +4 -3
  43. package/.gos/squads/design-delivery/workflows/wf-design-delivery.yaml +6 -6
  44. package/.gos/templates/planTemplate.md +14 -5
  45. package/.gos/templates/specTemplate.md +68 -0
  46. package/.gos/templates/taskTemplate.md +8 -5
  47. package/AGENTS.md +0 -2
  48. package/CLAUDE.md +25 -9
  49. package/GEMINI.md +3 -3
  50. package/LICENSE +1 -1
  51. package/README.md +6 -8
  52. package/package.json +2 -3
  53. package/.gos/docs/slack-notifications.md +0 -219
  54. package/.gos/playbooks/sprint-planner-playbook.md +0 -127
  55. package/.gos/scripts/hooks/post-commit-notify.js +0 -175
  56. package/.gos/scripts/tools/clickup-preprocess.js +0 -218
  57. package/.gos/scripts/tools/clickup.js +0 -1058
  58. package/.gos/scripts/tools/slack-notify.js +0 -271
  59. package/.gos/skills/clickup/SKILL.md +0 -151
  60. package/.gos/skills/slack-review/SKILL.md +0 -91
  61. package/.gos/skills/sprint-planner/SKILL.md +0 -434
  62. package/.gos/skills/weekly-update/CHANGELOG.md +0 -165
  63. package/.gos/skills/weekly-update/SKILL.md +0 -361
  64. package/.gos/squads/sprint-planning/agents/sprint-chief.md +0 -47
  65. package/.gos/squads/sprint-planning/agents/sprint-planner-agent.md +0 -43
  66. package/.gos/squads/sprint-planning/agents/sprint-tracker.md +0 -43
  67. package/.gos/squads/sprint-planning/agents/task-importer.md +0 -44
  68. package/.gos/squads/sprint-planning/checklists/sprint-readiness.md +0 -27
  69. package/.gos/squads/sprint-planning/config/config.yaml +0 -65
  70. package/.gos/squads/sprint-planning/data/clickup-field-mapping.yaml +0 -94
  71. package/.gos/squads/sprint-planning/squad.yaml +0 -52
  72. package/.gos/squads/sprint-planning/tasks/close-sprint.md +0 -43
  73. package/.gos/squads/sprint-planning/tasks/create-sprint.md +0 -42
  74. package/.gos/squads/sprint-planning/tasks/import-tasks.md +0 -39
  75. package/.gos/squads/sprint-planning/tasks/sync-status.md +0 -31
  76. package/.gos/squads/sprint-planning/workflows/wf-sprint-creation.yaml +0 -59
  77. package/.gos/squads/sprint-planning/workflows/wf-sprint-sync.yaml +0 -35
  78. package/.gos/templates/sprint-clickup.template.md +0 -80
@@ -0,0 +1,54 @@
1
+ # Performance Audit Playbook (G-OS)
2
+
3
+ Catálogo de otimizações para código de desenvolvimento (React/Next.js frontend + backend Supabase / Cloudflare D1/Workers). Usado por `perf-review` e pelo fechamento de `validate-plan`. Foco em ganhos algorítmicos e arquiteturais, não micro-otimização.
4
+
5
+ ## Regras de manejo
6
+
7
+ - Finding só com evidência (`file:line`) + impacto concreto ("cada render da lista dispara 1+N queries") + correção. "Provavelmente lento" não é finding.
8
+ - Índice/materialização "por suspeita" precisa de evidência de schema/query antes de afirmar.
9
+ - Findings viram tasks de correção e entram no loop do pipeline.
10
+
11
+ ## Categorias
12
+
13
+ ### 1. N+1 e complexidade
14
+ - Query/fetch por item dentro de loop ou por linha de lista renderizada → batch / `in (...)` / dataloader.
15
+ - Varreduras aninhadas na mesma coleção; `find`/`filter` repetido em hot loop onde cabe `Map`.
16
+
17
+ ### 2. Cache estratégico
18
+ - Computações/fetches caros idênticos repetidos por request/render → memoização no boundary certo.
19
+ - Sem cache HTTP / data-layer em dado estável. **Cloudflare**: Cache API / KV para dado quente; `cache-control` correto. **Supabase**: cache no edge / revalidação.
20
+ - **Next.js**: `revalidate`, `cache: 'force-cache'`, React Query/SWR staleTime para dado estável; evitar refetch desnecessário.
21
+
22
+ ### 3. Trabalho fora do caminho crítico (item 4)
23
+ - Serviço/função que NÃO precisa ser realtime rodando síncrono no request → mover para **fila** (Cloudflare Queues / Supabase pg-boss/pgmq) e processar em background.
24
+ - Tarefas periódicas → **cron** (Cloudflare Cron Triggers / Supabase `pg_cron`).
25
+ - Envio de email, geração de relatório, webhooks, agregações pesadas: background, não no caminho do usuário.
26
+
27
+ ### 4. Banco de dados (Supabase Postgres / Cloudflare D1)
28
+ - **Índices**: padrões de query (filtro por coluna, join, order by) sem índice de suporte → flag com evidência do schema.
29
+ - **Views / materialized views**: agregação cara repetida → materialized view + refresh agendado (cron). View para encapsular join complexo recorrente.
30
+ - **Paginação obrigatória**: lista sem limite → `limit`/`offset` ou keyset pagination. Consumo **mediante filtro/search** (não trazer tudo e filtrar no client).
31
+ - **Over-fetch**: `select *` / objeto inteiro onde IDs bastam; colunas não usadas; JSON grande enviado ao client.
32
+ - Query pesada em request quente → materializar / cachear / paginar.
33
+ - **D1**: batch de statements; evitar round-trips múltiplos; usar prepared statements reusados.
34
+
35
+ ### 5. Frontend (React/Next.js)
36
+ - Bundle: dependência pesada para uso trivial; falta de code-splitting em rota rara; imagens/fontes não otimizadas.
37
+ - Render waterfalls; fetch no client para dado disponível no render (mover para server component / server-side).
38
+ - Memoização ausente em boundary claro; re-render em cascata.
39
+ - Deferir para as guidelines do projeto (react-best-practices) quando houver.
40
+
41
+ ### 6. Build/CI
42
+ - CI lento por falta de cache; passos redundantes; suíte que poderia paralelizar.
43
+
44
+ ## Formato do finding
45
+
46
+ ```markdown
47
+ ### [PERF-NN] Título imperativo curto
48
+ - **Evidência**: `path/file.ts:142` — o padrão concreto.
49
+ - **Impacto**: custo pago ("cada listagem: 1+N queries", "500KB de JSON por request").
50
+ - **Esforço**: S | M | L (para a correção).
51
+ - **Correção**: técnica específica (batch, cache, fila, índice, view, paginação).
52
+ ```
53
+
54
+ Ordenar por leverage (impacto ÷ esforço). Findings de alto impacto viram task antes de fechar o plano.
@@ -0,0 +1,63 @@
1
+ # Security Audit Playbook (G-OS)
2
+
3
+ Catálogo de vulnerabilidades conhecidas para auditar código de desenvolvimento (React, Next.js, TypeScript, Node, Deno, Supabase, Cloudflare D1/Workers). Usado por `security-review` e pelo fechamento de `validate-plan`.
4
+
5
+ ## Regras de manejo
6
+
7
+ - Uma vulnerabilidade só é finding **com evidência**: `file:line` + descrição do padrão + impacto em produção + remediação. "Provavelmente tem XSS em algum lugar" não é finding.
8
+ - **NUNCA reproduzir valor de secret.** Referenciar só `file:line` + tipo da credencial; a correção sempre inclui rotação (secret commitado está queimado mesmo após remoção).
9
+ - Comportamento by-design (convenção de plataforma, decisão registrada em ADR) não é finding — salvo se a implementação adiciona risco além da convenção. ADR desatualizada vs código É finding (drift).
10
+ - Findings viram tasks de correção e entram no loop do `execute-plan` / correção do `validate-plan`.
11
+
12
+ ## Categorias
13
+
14
+ ### 1. Credenciais e secrets
15
+ - Chaves/tokens/senhas hardcoded no código ou em `.env` commitado.
16
+ - **Supabase**: `service_role` key usada no client (deve ser só server/edge). `anon` key com RLS desligado = acesso total.
17
+ - Secrets logados ou persistidos em stores de evento/histórico.
18
+ - **Cloudflare**: secrets via `wrangler secret` (não em `wrangler.toml` versionado nem `vars`).
19
+ - Remediação: remover, **rotacionar**, mover para secret manager / env server-side.
20
+
21
+ ### 2. Dados cruzando para interpretadores
22
+ - **SQL injection**: query montada com string de request (Postgres/D1). Usar parâmetros/prepared statements.
23
+ - **Command injection**: shell montado com input.
24
+ - **XSS**: `dangerouslySetInnerHTML`, `eval`, `innerHTML` com conteúdo controlado pelo usuário. Sanitizar / usar APIs seguras.
25
+ - **Path traversal**: path de arquivo derivado de request.
26
+ - **SSRF**: fetch para URL controlada pelo usuário sem allowlist.
27
+
28
+ ### 3. Controle de acesso (o eixo mais crítico em Supabase)
29
+ - **RLS**: tabela com dado sensível e RLS **desligado** ou sem policy → qualquer `anon`/`authenticated` lê tudo. Toda tabela exposta via PostgREST precisa de RLS ligado + policy explícita por operação (select/insert/update/delete).
30
+ - **Policies frouxas**: `using (true)` em tabela sensível; policy que não checa `auth.uid()` / tenant / ownership (IDOR).
31
+ - **Edge Functions (Supabase)**: função sem verificação de JWT/authz server-side; confiar em header do client; `verify_jwt` desligado sem motivo.
32
+ - **Next.js**: route handler / server action sem checagem de identidade server-side; autorização só no client; middleware que não cobre a rota.
33
+ - **Cloudflare Workers**: endpoint mutável sem auth; falta de checagem de origem.
34
+ - **CSRF**: rota que muda estado sem checagem de autenticidade.
35
+
36
+ ### 4. Contratos de entrada
37
+ - Boundary de API que confia no body sem validação de schema (usar **Zod** front + back — validação no client não substitui a do server).
38
+ - Upload de arquivo sem restrição de tipo/tamanho/armazenamento.
39
+ - Mass assignment: atribuição ampla de objeto do request para modelo de persistência.
40
+
41
+ ### 5. Configuração de produção
42
+ - CORS amplo (`*`) com credenciais permitidas.
43
+ - Headers de segurança ausentes (CSP) em superfícies sensíveis; cookies sem `HttpOnly`/`Secure`/`SameSite`.
44
+ - Debug/verbose habilitado em produção; stack trace vazando para o client.
45
+ - **Supabase**: bucket de Storage público quando deveria ser privado; policy de Storage ausente.
46
+
47
+ ### 6. Dependências
48
+ - Rodar o audit do ecossistema em modo read-only: `npm audit` / `pnpm audit` / `deno info`. Reportar só advisories critical/high que afetam código runtime alcançável.
49
+
50
+ ### 7. Minimização de dados
51
+ - PII / dado operacional sensível em logs, em respostas de erro, ou exposto via API.
52
+
53
+ ## Formato do finding
54
+
55
+ ```markdown
56
+ ### [SEC-NN] Título imperativo curto
57
+ - **Evidência**: `path/file.ts:123` — o que está lá (sem reproduzir secret).
58
+ - **Impacto**: o que um atacante consegue / o que vaza.
59
+ - **Severidade**: CRITICAL | HIGH | MEDIUM | LOW.
60
+ - **Remediação**: mudança de código/config + rotação quando aplicável.
61
+ ```
62
+
63
+ Ordenar por severidade; CRITICAL/HIGH viram task de correção obrigatória antes de fechar o plano.
@@ -1,7 +1,7 @@
1
1
  {
2
- "runtime": "ganbatte-os-design-delivery",
2
+ "runtime": "ganbatte-os-development",
3
3
  "version": "0.1.0",
4
- "description": "Runtime curado do ganbatte-os para design-to-code, sprint planning e ClickUp delivery.",
4
+ "description": "Runtime curado do ganbatte-os para desenvolvimento: prototipacao, design-to-code, implementacao, otimizacao e seguranca.",
5
5
  "modules": {
6
6
  "agents": [
7
7
  "ganbatte-os-master",
@@ -10,8 +10,11 @@
10
10
  "dev",
11
11
  "sm",
12
12
  "po",
13
+ "qa",
13
14
  "devops",
14
- "squad-creator"
15
+ "squad-creator",
16
+ "security-auditor",
17
+ "perf-optimizer"
15
18
  ],
16
19
  "skills": [
17
20
  "design-to-code",
@@ -21,21 +24,39 @@
21
24
  "make-version-diff",
22
25
  "component-dedup",
23
26
  "frontend-dev",
27
+ "interface-design",
24
28
  "react-best-practices",
25
29
  "react-doctor",
26
- "sprint-planner",
27
- "clickup",
28
30
  "plan-to-tasks",
29
31
  "agent-teams",
30
32
  "git-ssh-setup",
31
33
  "humanizer",
32
- "weekly-update"
34
+ "stack-profiler",
35
+ "plan-blueprint",
36
+ "progress-tracker",
37
+ "execute-plan",
38
+ "validate-plan",
39
+ "audit-screenshots",
40
+ "idea-intake",
41
+ "prd-from-intake",
42
+ "adr-tech-decisions",
43
+ "prototype-orchestrator",
44
+ "gos-caveman",
45
+ "gos-compress",
46
+ "figma-print-diff",
47
+ "ui-guardrails",
48
+ "cloudflare-pages-setup",
49
+ "typeform-form-pattern",
50
+ "timer-component-pattern",
51
+ "security-review",
52
+ "perf-review",
53
+ "simplify-review"
33
54
  ],
34
55
  "squads": [
35
56
  "design-delivery",
36
57
  "design-squad",
37
- "sprint-planning",
38
- "git-operations"
58
+ "git-operations",
59
+ "code-quality"
39
60
  ]
40
61
  }
41
62
  }
@@ -46,7 +46,6 @@ FIGMA = <url-frame>
46
46
  FIGMA+ = [<url-comp>, ...] # opcional
47
47
  INTERACOES = """<lista estruturada — obrigatório quando tela tem table-clicável/drawer/modal/popup>"""
48
48
  NOTAS = """<prosa livre>""" # opcional
49
- ASSIGNEE = <user-id> # opcional, default 112010775 (Douglas)
50
49
  ```
51
50
 
52
51
  `gos-master` resolve no comprehension gate (não pedir ao usuário):
@@ -59,7 +58,7 @@ ASSIGNEE = <user-id> # opcional, default 112010775 (
59
58
  1. Fase 1 — Mapeamento Visual & Componentização
60
59
  1.4 Comportamentos & Overrides — `## Interações & Estados` + `## Page-level overrides` no plano
61
60
  2. Fase 2 — Aderência à Stack (sem redefinir arquitetura)
62
- 2.5 Fase 2.5 — Backend gaps → criar tasks ClickUp pro Douglas (`--skip-clickup` desliga)
61
+ 2.5 Fase 2.5 — Backend gaps → registro local em `## Backend pendings` + plano-irmão `PLAN-NNN-backend-<slug>` quando grande (`--skip-backend-tracking` desliga)
63
62
  3. Fase 3 — Plano de Execução (gera tasks com `interaction_target` e `override_target` para cobrir comportamentos e overrides)
64
63
 
65
64
  Saídas:
@@ -117,7 +116,7 @@ NOTAS = """<opcional — desvios conhecidos, contexto de QA>"""
117
116
 
118
117
  Skill `validate-plan` (Opus, revisor):
119
118
  - Para cada task em `validacao`: re-roda visual gate curto (anatomia + tokens + comportamentos), confronta `git diff --staged` vs Componentes mapeados, confere checklist da task e `interaction_target`/`override_target`. Tudo bate → auto-marca `concluido`. Falha → mantém `validacao` com nota.
120
- - Para o plano: cobertura de comportamento (`## Interações & Estados`) + cobertura de overrides (`## Page-level overrides`) + checklist do plano + backend pendings ClickUp todos `concluido` → marca `validated_at:` no plan.md + `*progress status PLAN-NNN-<slug> concluido`. Senão → mantém em `validacao`.
119
+ - Para o plano: cobertura de comportamento (`## Interações & Estados`) + cobertura de overrides (`## Page-level overrides`) + checklist do plano + backend pendings locais todos `concluido` → marca `validated_at:` no plan.md + `*progress status PLAN-NNN-<slug> concluido`. Senão → mantém em `validacao`.
121
120
  - Tasks `bloqueada-backend` ficam intocadas — backend tem que fechar primeiro.
122
121
 
123
122
  ### 5. Push manual e fechamento
@@ -128,7 +127,7 @@ Skill `validate-plan` (Opus, revisor):
128
127
  git push
129
128
  ```
130
129
 
131
- Push é ato consciente do humano. Tasks `bloqueada-backend` aguardam ClickUp fechar — quando isso acontece, rodar `*progress status T-NNN-NN em-andamento` (state machine valida ClickUp via MCP) e voltar pra etapa 4.
130
+ Push é ato consciente do humano. Tasks `bloqueada-backend` aguardam o pending local de backend fechar — quando isso acontece, rodar `*progress status T-NNN-NN em-andamento` (state machine valida o status local) e voltar pra etapa 4.
132
131
 
133
132
  ### 6. Commit & resumo
134
133
 
@@ -159,4 +158,3 @@ Push é ato consciente do humano. Tasks `bloqueada-backend` aguardam ClickUp fec
159
158
  - `execute-plan` — executa plano com visual gate, non-blocking em backend gaps (Codex IDE, execução)
160
159
  - `validate-plan` — valida plano pós-execute, auto-marca concluido (Opus, revisor)
161
160
  - `progress-tracker` — gerencia `progress.txt` + state machine (incluindo `bloqueada-backend`)
162
- - `clickup` — sync opcional para tracking externo (não obrigatório)
@@ -14,5 +14,5 @@ Use este prompt quando a tarefa for descobrir contexto antes de construir.
14
14
  - Screenshot ou referencia visual: `design-to-code`
15
15
  - Figma Make bruto: `figma-make-analyzer`
16
16
  - Codigo do Stitch ou outro gerador: `make-code-triage`
17
- - Planejamento de entrega: `sprint-planner`
18
- - Sincronizacao operacional: `clickup`
17
+ - Planejamento por tela: `plan-blueprint`
18
+ - Auditoria de seguranca/performance: `security-review`, `perf-review`
@@ -5,11 +5,11 @@ Quebre a especificacao em tarefas pequenas e ordenadas.
5
5
  ## Regras
6
6
 
7
7
  - cada task deve caber em menos de um dia
8
- - separar FE, UX, QA, DevOps e operacao ClickUp quando fizer sentido
9
- - incluir criterios de aceite objetivos
8
+ - separar backend, frontend, UX e QA quando fizer sentido (backend-first quando houver dependencia)
9
+ - incluir criterios de aceite objetivos e verificaveis
10
10
  - explicitar dependencias
11
11
 
12
12
  ## Saida esperada
13
13
 
14
- - backlog pronto para `sprint-planner`
15
- - ou JSON/markdown que possa virar importacao no ClickUp
14
+ - backlog pronto para `plan-to-tasks`
15
+ - tasks em markdown com frontmatter e criterios de aceite
@@ -8,4 +8,4 @@ Revise a entrega com foco em regressao, fidelidade ao design e prontidao para sp
8
8
  - aderencia ao design/tokens
9
9
  - acessibilidade
10
10
  - riscos de dados mockados ou codigo Make misturado com UI final
11
- - importacao/sincronizacao correta para ClickUp quando fizer parte do fluxo
11
+ - seguranca (RLS, authz, secrets) e performance (N+1, cache, paginacao) quando fizer parte do fluxo
@@ -315,6 +315,22 @@ function cmdInit(root, args) {
315
315
  const gitignoreUpdated = mergeGitignore(root, manifest.gitignoreEntries || []);
316
316
  if (gitignoreUpdated) ok('.gitignore atualizado com entradas do manifest.');
317
317
 
318
+ // 8b. Config de modelo por etapa (Junior executa, Senior audita)
319
+ try {
320
+ const { writeLocalDefaults, resolveAll } = require(path.join(root, '.gos', 'scripts', 'tools', 'model-router.js'));
321
+ const res = writeLocalDefaults(root);
322
+ const map = resolveAll(root);
323
+ if (res.created) {
324
+ ok('Config de modelos por etapa criada em .gos-local/models.json');
325
+ } else {
326
+ info('Config de modelos por etapa ja existe (.gos-local/models.json).');
327
+ }
328
+ info(` plan=${map.plan.model} | execute=${map.execute.model} | validate=${map.validate.model}`);
329
+ info(' Edite .gos-local/models.json para trocar modelo/provider por etapa.');
330
+ } catch (err) {
331
+ warn(`Nao foi possivel configurar models por etapa: ${err.message}`);
332
+ }
333
+
318
334
  // 9. Salvar install log
319
335
  writeJson(installLog, {
320
336
  version: VERSION,
@@ -122,22 +122,6 @@ function main() {
122
122
  const summary = [];
123
123
  const syncMatcher = /^(\.gos|\.claude|data|README\.md|CLAUDE\.md|AGENTS\.md|GEMINI\.md)/;
124
124
 
125
- // Trigger post-commit notification if git commit was made
126
- if (state.gitCommit) {
127
- try {
128
- execFileSync('node', [path.join(ROOT, '.gos', 'scripts', 'hooks', 'post-commit-notify.js')], {
129
- cwd: ROOT,
130
- encoding: 'utf8',
131
- stdio: ['pipe', 'pipe', 'pipe'],
132
- timeout: 30000,
133
- })
134
- summary.push('post-commit-notify OK')
135
- } catch (error) {
136
- const message = error.stderr || error.stdout || error.message || 'falha no post-commit'
137
- summary.push(`post-commit-notify falhou (${String(message).split(/\r?\n/)[0]})`)
138
- }
139
- }
140
-
141
125
  if (anyPathMatches(touchedFiles, syncMatcher)) {
142
126
  try {
143
127
  runNpm(["run", "sync:ides"], { timeout: 180000 });
@@ -13,10 +13,11 @@
13
13
  * Verificacoes:
14
14
  * 1. plan.md existe e tem frontmatter YAML.
15
15
  * 2. context.md existe.
16
- * 3. tasks/ existe e contem >= 1 T-NN*.md.
17
- * 4. Cada T-NN*.md: head -1 == "---" E frontmatter contem `status: pendente`
18
- * E `id:`, `plan_id:`, `seq:`, `title:`.
19
- * 5. Nenhum T-NN*.md tem secao `## Status` no body (formato bugado legado).
16
+ * 3. spec.md existe (spec completa de desenvolvimento).
17
+ * 4. tasks/ existe e contem >= 1 T-NN*.md.
18
+ * 5. Cada T-NN*.md: head -1 == "---" E frontmatter contem `status: pendente`
19
+ * E `id:`, `plan_id:`, `seq:`, `title:`, E body tem `## Critérios de aceite`.
20
+ * 6. Nenhum T-NN*.md tem secao `## Status` no body (formato bugado legado).
20
21
  *
21
22
  * Exit code:
22
23
  * 0 = plano valido, usavel pelo pipeline
@@ -43,6 +44,7 @@ const warnings = [];
43
44
 
44
45
  const planFile = path.join(planDir, 'plan.md');
45
46
  const contextFile = path.join(planDir, 'context.md');
47
+ const specFile = path.join(planDir, 'spec.md');
46
48
  const tasksDir = path.join(planDir, 'tasks');
47
49
 
48
50
  if (!fs.existsSync(planFile)) {
@@ -58,6 +60,10 @@ if (!fs.existsSync(contextFile)) {
58
60
  warnings.push(`context.md ausente — recomendado, nao bloqueia`);
59
61
  }
60
62
 
63
+ if (!fs.existsSync(specFile)) {
64
+ errors.push(`spec.md ausente em ${planDir} — *plan deve emitir spec.md (templates/specTemplate.md)`);
65
+ }
66
+
61
67
  if (!fs.existsSync(tasksDir)) {
62
68
  errors.push(`tasks/ ausente em ${planDir} — *plan deve invocar plan-to-tasks`);
63
69
  } else {
@@ -100,6 +106,10 @@ if (!fs.existsSync(tasksDir)) {
100
106
  if (/^## Status\s*$/m.test(body)) {
101
107
  errors.push(`${rel}: contem secao "## Status" no body (formato legado bugado) — rodar migrate-task-status.js`);
102
108
  }
109
+
110
+ if (!/^## Crit[eé]rios de aceite/m.test(body)) {
111
+ errors.push(`${rel}: sem secao "## Critérios de aceite" no body — task precisa de criterios verificaveis`);
112
+ }
103
113
  }
104
114
  }
105
115
 
@@ -116,5 +126,5 @@ if (errors.length) {
116
126
 
117
127
  const taskCount = fs.readdirSync(tasksDir)
118
128
  .filter((f) => /^T-\d+.*\.md$/.test(f)).length;
119
- console.log(`[check-plan] OK — ${planDir}: plan.md + context.md + ${taskCount} tasks (todas com frontmatter status: pendente).`);
129
+ console.log(`[check-plan] OK — ${planDir}: plan.md + context.md + spec.md + ${taskCount} tasks (frontmatter status: pendente + criterios de aceite).`);
120
130
  process.exit(0);
@@ -26,37 +26,36 @@ function agentSlug(id) {
26
26
  return id.startsWith('gos-') ? id : `gos-${id}`;
27
27
  }
28
28
 
29
- function cleanupStaleAdapters() {
30
- // Remove arquivos .md soltos no root de skills/ (formato legado) em todas as IDEs.
31
- // Codex/Qwen/Gemini/Opencode/Antigravity esperam <slug>/SKILL.md (diretorio), nao .md solto.
32
- // .agent e o diretorio canonico do Antigravity (workspace scope: .agent/skills/, .agent/workflows/).
33
- const allIdes = ['.codex', '.qwen', '.gemini', '.opencode', '.agent'];
34
- for (const ide of allIdes) {
35
- const skillsDir = path.join(root, ide, 'skills');
36
- if (fs.existsSync(skillsDir)) {
37
- for (const entry of fs.readdirSync(skillsDir)) {
38
- const full = path.join(skillsDir, entry);
39
- if (fs.statSync(full).isFile() && entry.endsWith('.md')) {
40
- fs.unlinkSync(full);
41
- }
42
- }
43
- }
44
- const agentsDir = path.join(root, ide, 'agents');
45
- if (fs.existsSync(agentsDir)) {
46
- for (const entry of fs.readdirSync(agentsDir)) {
47
- if (/^gos-gos-/.test(entry)) {
48
- fs.unlinkSync(path.join(agentsDir, entry));
49
- }
50
- }
29
+ // IDEs alvo do G-OS (adapters gerados para estas).
30
+ // Claude Code, Codex, Qwen, Opencode, Gemini CLI, Antigravity (.agent).
31
+ const TARGET_IDES = ['.claude', '.codex', '.qwen', '.opencode', '.gemini', '.agent'];
32
+ // Entrypoints user-facing (slash/workflow). O master roteia o resto internamente (item 10).
33
+ const CMD_WHITELIST = new Set(['gos-master', 'ux-design-expert']);
34
+
35
+ function removeGosPrefixed(dir) {
36
+ // Remove apenas entradas G-OS (prefixo gos-), preservando skills/agents/workflows
37
+ // proprios do usuario que coexistem no mesmo diretorio (contrato do prefixo gos-).
38
+ if (!fs.existsSync(dir)) return;
39
+ for (const entry of fs.readdirSync(dir)) {
40
+ if (/^gos-/.test(entry)) {
41
+ fs.rmSync(path.join(dir, entry), { recursive: true, force: true });
51
42
  }
52
43
  }
44
+ }
53
45
 
54
- // Legado: .antigravity/ era o diretorio errado (Antigravity nunca leu isso — usa .agent/).
55
- // Remove silenciosamente para evitar drift entre IDEs.
56
- const legacyAntigravity = path.join(root, '.antigravity');
57
- if (fs.existsSync(legacyAntigravity)) {
58
- fs.rmSync(legacyAntigravity, { recursive: true, force: true });
46
+ function cleanupStaleAdapters() {
47
+ for (const ide of TARGET_IDES) {
48
+ removeGosPrefixed(path.join(root, ide, 'skills')); // gos-<slug>/
49
+ removeGosPrefixed(path.join(root, ide, 'agents')); // gos-<id>.md
50
+ // Commands sao namespaced sob gos/ — seguro remover o namespace inteiro.
51
+ const cmdGos = path.join(root, ide, 'commands', 'gos');
52
+ if (fs.existsSync(cmdGos)) fs.rmSync(cmdGos, { recursive: true, force: true });
59
53
  }
54
+ // Antigravity: workflows dos entrypoints (gos-*) — limpar apenas os do G-OS.
55
+ removeGosPrefixed(path.join(root, '.agent', 'workflows'));
56
+ // .antigravity/ e o diretorio errado (Antigravity usa .agent/) — remover legado.
57
+ const legacyAntigravity = path.join(root, '.antigravity');
58
+ if (fs.existsSync(legacyAntigravity)) fs.rmSync(legacyAntigravity, { recursive: true, force: true });
60
59
  }
61
60
 
62
61
  function agentWrapper(agentId, target) {
@@ -131,71 +130,57 @@ function main() {
131
130
  const agentProfilePath = path.join(root, '.gos', 'agents', 'profiles', agent.path);
132
131
  const agentDesc = extractAgentDescription(agentProfilePath) || `${agent.id} agent`;
133
132
  const aSlug = agentSlug(agent.id);
133
+ const safeDesc = agentDesc.replace(/"/g, '\\"').replace(/\n/g, ' ').slice(0, 200);
134
+ const isEntrypoint = CMD_WHITELIST.has(agent.id);
135
+
136
+ // Subagents (delegacao interna do master) — para TODOS os agents.
137
+ const qwenAgent = path.join(root, '.qwen', 'agents', `${aSlug}.md`);
138
+ const qwenAgentTarget = relativeTarget(qwenAgent, agentProfilePath);
139
+ writeFile(qwenAgent, `---\nname: "${aSlug}"\ndescription: "${safeDesc}"\nmodel: inherit\ntools:\n - Read\n - Glob\n - Grep\n - Bash\n - Edit\n - Write\n---\n\nFonte canonica: \`${qwenAgentTarget}\`\nLeia e siga o perfil em \`${qwenAgentTarget}\`.`);
140
+
141
+ const codexAgent = path.join(root, '.codex', 'agents', `${aSlug}.md`);
142
+ const codexAgentTarget = relativeTarget(codexAgent, agentProfilePath);
143
+ writeFile(codexAgent, `---\nname: "${aSlug}"\ndescription: "${safeDesc}"\nmodel: inherit\ntools:\n - Read\n - Glob\n - Grep\n - Bash\n - Edit\n - Write\n---\n\nFonte canonica: \`${codexAgentTarget}\`\nLeia e siga o perfil em \`${codexAgentTarget}\`.`);
144
+
145
+ // Slash commands / picker (user-facing) — APENAS entrypoints (item 10).
146
+ if (!isEntrypoint) continue;
134
147
 
135
- // Claude commands (requires YAML frontmatter with description)
136
148
  const claudeFile = path.join(root, '.claude', 'commands', 'gos', 'agents', `${agent.id}.md`);
137
149
  writeFile(claudeFile, claudeCommandWrapper(aSlug, agentDesc, relativeTarget(claudeFile, agentProfilePath), '', 'Claude'));
138
150
 
139
- // Qwen commands (requires YAML frontmatter with description)
140
151
  const qwenCmd = path.join(root, '.qwen', 'commands', 'gos', 'agents', `${agent.id}.md`);
141
152
  writeFile(qwenCmd, qwenCommandWrapper(aSlug, agentDesc, relativeTarget(qwenCmd, agentProfilePath)));
142
153
 
143
- // Qwen sub-agents
144
- const qwenAgent = path.join(root, '.qwen', 'agents', `${aSlug}.md`);
145
- const agentTarget = relativeTarget(qwenAgent, agentProfilePath);
146
- const safeDesc = agentDesc.replace(/"/g, '\\"').replace(/\n/g, ' ').slice(0, 200);
147
- writeFile(qwenAgent, `---\nname: "${aSlug}"\ndescription: "${safeDesc}"\nmodel: inherit\ntools:\n - Read\n - Glob\n - Grep\n - Bash\n - Edit\n - Write\n---\n\nFonte canonica: \`${agentTarget}\`\nLeia e siga o perfil em \`${agentTarget}\`.`);
148
-
149
- // Codex commands (slash commands no Codex IDE Extension)
150
154
  const codexCmd = path.join(root, '.codex', 'commands', 'gos', 'agents', `${agent.id}.md`);
151
155
  writeFile(codexCmd, claudeCommandWrapper(aSlug, agentDesc, relativeTarget(codexCmd, agentProfilePath), '', 'Codex'));
152
156
 
153
- // Codex sub-agents (Codex IDE espera .codex/agents/<id>.md)
154
- const codexAgent = path.join(root, '.codex', 'agents', `${aSlug}.md`);
155
- const codexAgentTarget = relativeTarget(codexAgent, agentProfilePath);
156
- writeFile(codexAgent, `---\nname: "${aSlug}"\ndescription: "${safeDesc}"\nmodel: inherit\ntools:\n - Read\n - Glob\n - Grep\n - Bash\n - Edit\n - Write\n---\n\nFonte canonica: \`${codexAgentTarget}\`\nLeia e siga o perfil em \`${codexAgentTarget}\`.`);
157
-
158
- // Codex / Antigravity (.agent/) / Gemini / Opencode usam namespace plano gos-<slug> em skills/.
159
- // Agents aparecem no mesmo picker se emitidos como wrapper SKILL.md em skills/.
160
- for (const ide of ['.codex', '.agent', '.gemini', '.opencode']) {
157
+ // Codex/Opencode/Gemini/Antigravity populam o picker a partir de <ide>/skills/<slug>/SKILL.md.
158
+ // Emitir o entrypoint tambem como skill garante que aparece no picker de cada uma.
159
+ for (const ide of ['.codex', '.opencode', '.gemini', '.agent']) {
161
160
  const ideAgentSkill = path.join(root, ide, 'skills', aSlug, 'SKILL.md');
162
161
  writeFile(ideAgentSkill, skillWrapper(agent.id, relativeTarget(ideAgentSkill, agentProfilePath), agentDesc));
163
162
  }
164
163
 
165
- // Antigravity workflows (.agent/workflows/<id>.md) — slash command invocation no picker.
166
- const antigravityWorkflow = path.join(root, '.agent', 'workflows', `${agent.id}.md`);
164
+ // Antigravity: workflow (slash command no picker) — nome prefixado gos- p/ coexistencia.
165
+ const antigravityWorkflow = path.join(root, '.agent', 'workflows', `${aSlug}.md`);
167
166
  const workflowTarget = relativeTarget(antigravityWorkflow, agentProfilePath);
168
- const safeAgentDesc = agentDesc.replace(/"/g, '\\"').replace(/\n/g, ' ').slice(0, 200);
169
167
  writeFile(
170
168
  antigravityWorkflow,
171
- `---\ndescription: "${safeAgentDesc}"\n---\n\n# /${agent.id} (Antigravity Workflow)\n\nFonte canonica: \`${workflowTarget}\`\n\nLeia o arquivo canonico apontado em CANONICAL-SOURCE e execute as instrucoes como fonte primaria.\n\nCANONICAL-SOURCE: ${workflowTarget}\n\nArgumentos do usuario seguem o prompt do agente.`
169
+ `---\ndescription: "${safeDesc}"\n---\n\n# /${aSlug} (Antigravity Workflow)\n\nFonte canonica: \`${workflowTarget}\`\n\nLeia o arquivo canonico apontado em CANONICAL-SOURCE e execute as instrucoes como fonte primaria.\n\nCANONICAL-SOURCE: ${workflowTarget}\n\nArgumentos do usuario seguem o prompt do agente.`
172
170
  );
173
171
  }
174
172
 
173
+ // Skills: auto-discoveraveis (o master as invoca internamente), NAO slash commands.
175
174
  for (const skill of skills) {
176
175
  const skillTargetPath = skill.skillFile || skill.path;
177
176
  const canonicalPath = path.join(root, '.gos', skillTargetPath);
178
- const claudeSkill = path.join(root, '.claude', 'commands', 'gos', 'skills', `${skill.slug}.md`);
179
- const codexSkill = path.join(root, '.codex', 'skills', `gos-${skill.slug}`, 'SKILL.md');
180
- const antigravitySkill = path.join(root, '.agent', 'skills', `gos-${skill.slug}`, 'SKILL.md');
181
- const geminiSkill = path.join(root, '.gemini', 'skills', `gos-${skill.slug}`, 'SKILL.md');
182
- const opencodeSkill = path.join(root, '.opencode', 'skills', `gos-${skill.slug}`, 'SKILL.md');
183
- const qwenSkill = path.join(root, '.qwen', 'skills', `gos-${skill.slug}`, 'SKILL.md');
184
-
185
- const qwenCmd = path.join(root, '.qwen', 'commands', 'gos', 'skills', `${skill.slug}.md`);
186
-
187
177
  const skillFm = parseFrontmatter(canonicalPath);
188
178
  const skillDesc = skillFm.description || skill.description || skill.name || skill.slug;
189
- const skillArgHint = skillFm['argument-hint'] || '';
190
-
191
- writeFile(codexSkill, skillWrapper(skill.slug, relativeTarget(codexSkill, canonicalPath), skillDesc));
192
- writeFile(antigravitySkill, skillWrapper(skill.slug, relativeTarget(antigravitySkill, canonicalPath), skillDesc));
193
- writeFile(geminiSkill, skillWrapper(skill.slug, relativeTarget(geminiSkill, canonicalPath), skillDesc));
194
- writeFile(opencodeSkill, skillWrapper(skill.slug, relativeTarget(opencodeSkill, canonicalPath), skillDesc));
195
- writeFile(qwenSkill, skillWrapper(skill.slug, relativeTarget(qwenSkill, canonicalPath), skillDesc));
196
179
 
197
- writeFile(qwenCmd, qwenCommandWrapper(`gos-${skill.slug}`, skillDesc, relativeTarget(qwenCmd, canonicalPath)));
198
- writeFile(claudeSkill, claudeCommandWrapper(`gos-${skill.slug}`, skillDesc, relativeTarget(claudeSkill, canonicalPath), skillArgHint, 'Claude'));
180
+ for (const ide of TARGET_IDES) {
181
+ const t = path.join(root, ide, 'skills', `gos-${skill.slug}`, 'SKILL.md');
182
+ writeFile(t, skillWrapper(skill.slug, relativeTarget(t, canonicalPath), skillDesc));
183
+ }
199
184
  }
200
185
 
201
186
  // Antigravity le AGENTS.md no root do workspace (ja existe no projeto).
@@ -228,11 +213,17 @@ function main() {
228
213
  'Ciclo: pre-flight visual -> loop por task com state machine -> visual gate -> validacao -> humano marca concluido.',
229
214
  'Detalhes: `../.gos/skills/execute-plan/SKILL.md`.',
230
215
  '',
231
- '## Agents disponiveis',
216
+ '## Entrypoints (slash commands user-facing)',
217
+ '',
218
+ 'Apenas 2 comandos: o master roteia o resto internamente (skills, subagents, squads).',
219
+ '',
220
+ ...agents.filter((a) => CMD_WHITELIST.has(a.id)).map((agent) => `- \`/gos:agents:${agent.id}\` -> \`../.gos/agents/profiles/${agent.path}\``),
221
+ '',
222
+ '## Subagents (delegacao interna do master)',
232
223
  '',
233
224
  ...agents.map((agent) => `- \`gos-${agent.id}\` -> \`../.gos/agents/profiles/${agent.path}\``),
234
225
  '',
235
- '## Skills curadas',
226
+ '## Skills curadas (auto-discoveraveis, invocadas pelo master)',
236
227
  '',
237
228
  '| Slug | Arquivo canonico |',
238
229
  '|------|------------------|',
@@ -240,9 +231,10 @@ function main() {
240
231
  '',
241
232
  '## Como o Codex consome',
242
233
  '',
243
- '- Slash commands em `.codex/commands/gos/{agents,skills}/<id>.md` -> unica superficie de skills/agents. Codex carrega o canonico apontado em CANONICAL-SOURCE e executa.',
244
- '- Subagents em `.codex/agents/gos-<id>.md` -> declaracao de subagent (acessivel via Task tool e delegacao interna).',
245
- '- Para invocar o orquestrador master, digite `/gos:agents:gos-master` no picker.',
234
+ '- Slash commands (`.codex/commands/gos/agents/`) apenas para os 2 entrypoints. O `gos-master` analisa o input e decide quais skills, agents, subagents e squads acionar.',
235
+ '- Subagents em `.codex/agents/gos-<id>.md` -> delegacao interna (Task tool).',
236
+ '- Skills em `.codex/skills/gos-<slug>/SKILL.md` -> auto-discoveraveis; o master as invoca, o usuario nao digita.',
237
+ '- Para comecar, digite `/gos:agents:gos-master` no picker.',
246
238
  ''
247
239
  ].join('\n');
248
240
  writeFile(path.join(root, '.codex', 'AGENTS.md'), codexAgentsMd);
@@ -267,10 +259,14 @@ function main() {
267
259
  // Evita regressoes silenciosas que ja quebraram a IDE no passado.
268
260
  const codexFailures = [];
269
261
  for (const agent of agents) {
262
+ // Subagent (delegacao) para TODOS os agents.
270
263
  const expectedAgent = path.join(root, '.codex', 'agents', `${agentSlug(agent.id)}.md`);
271
- const expectedCmd = path.join(root, '.codex', 'commands', 'gos', 'agents', `${agent.id}.md`);
272
264
  if (!fs.existsSync(expectedAgent)) codexFailures.push(expectedAgent);
273
- if (!fs.existsSync(expectedCmd)) codexFailures.push(expectedCmd);
265
+ // Slash command apenas para entrypoints.
266
+ if (CMD_WHITELIST.has(agent.id)) {
267
+ const expectedCmd = path.join(root, '.codex', 'commands', 'gos', 'agents', `${agent.id}.md`);
268
+ if (!fs.existsSync(expectedCmd)) codexFailures.push(expectedCmd);
269
+ }
274
270
  }
275
271
  for (const skill of skills) {
276
272
  const expectedSkill = path.join(root, '.codex', 'skills', `gos-${skill.slug}`, 'SKILL.md');
@@ -284,8 +280,9 @@ function main() {
284
280
  process.exit(1);
285
281
  }
286
282
 
287
- console.log(`Adapters generated for ${agents.length} agents and ${skills.length} skills.`);
288
- console.log(`Codex IDE: ${agents.length} agents + ${skills.length} skills + AGENTS.md + config.toml.`);
283
+ const entrypoints = agents.filter((a) => CMD_WHITELIST.has(a.id)).length;
284
+ console.log(`Adapters gerados: ${entrypoints} entrypoints (slash), ${agents.length} subagents, ${skills.length} skills.`);
285
+ console.log(`IDEs alvo: ${TARGET_IDES.join(', ')}.`);
289
286
  }
290
287
 
291
288
  main();