mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-12 22:13:05 +00:00
chore(OPS92): consolidar MCPs — global só jina+playwright; penpot/postgres subagentes; gh CLI; re-homed (Closes #857)
Global (~/.config/opencode/opencode.jsonc) fica só com jina+playwright (remove github/postgres/forgejo/stalwart/office-word/jobspy) — manual como OPS89. Repo Teqo opencode.json: penpot+postgres com permission gated (penpot*/postgres*/query deny no build, allow só nos subagentes penpot/postgres). Novos .opencode/agent/penpot.md + postgres.md (mode subagent, docs de limite teqo vs teqo_wt*). Re-homed: jobspy→jobs, forgejo+office-word→lei-mercados-digitais, forgejo+stalwart→infra-solla (remove postgres pin, AGENTS.md sem office-word), forgejo→iara-pwa (limpa pins postgres/stalwart). Prosa: AGENTS-infra.md, prompt-montagem-home.md, project-status/engineering-audit sem MCP/pnpm issue. Validação: opencode debug config nos 5 repos (Teqo 4, jobs 3, lei 6, infra 7, iara 3 MCPs), gh auth ok, gate:fast verde.
This commit is contained in:
parent
2920aa9d63
commit
d816e3ff41
9 changed files with 251 additions and 6 deletions
|
|
@ -66,7 +66,7 @@ Antes da varredura, colha os défices comportamentais registrados pelo fluxo:
|
|||
pnpm issue all # kind `agent-miss` nos contadores; ou api.listIssues({ state: 'open', labels: 'kind:agent-miss' })
|
||||
```
|
||||
|
||||
**Investigue cada miss colhida** (leitura da Issue via API do GitHub/MCP — disponível no Cloud): o corpo registra causa raiz, fix aplicado e o guardrail proposto por `agent:file-miss`. Verifique no código se o fix segurou e se a classe do defeito ainda é reproduzível. Miss cuja classe já tem guarda viva não gera guardrail novo — gera item de hardening da guarda existente (o passo 2 já trata guarda dodgeable como finding).
|
||||
**Investigue cada miss colhida** (leitura da Issue via API do GitHub — `gh` CLI / `scripts/lib/github-api.mjs`, disponível no Cloud): o corpo registra causa raiz, fix aplicado e o guardrail proposto por `agent:file-miss`. Verifique no código se o fix segurou e se a classe do defeito ainda é reproduzível. Miss cuja classe já tem guarda viva não gera guardrail novo — gera item de hardening da guarda existente (o passo 2 já trata guarda dodgeable como finding).
|
||||
|
||||
Cada Issue colhida alimenta o **Passo 4b (recurrence prevention)**: toda miss vira candidata a guardrail determinístico (tipo / ESLint / convention spec / CI / pin comportamental). O ledger desses guardrails vive em **`docs/GUARDRAILS.md`** (criar o arquivo na primeira execução — é o escopo da Issue OPS2): uma linha por guardrail — miss de origem (link da Issue), classe 1–6, mecanismo, status. Quando o guardrail mergeia, **feche as Issues colhidas** (`done`) com comentário apontando o guardrail. Em Cursor Cloud o fechamento é determinístico e não exige escrita manual: o PR do guardrail carrega `Closes #N` (keyword repetida por número — o regex do `issue-done-on-main-merge.yml` não resolve `Closes #A, #B`) e o merge em `main` flippa a miss para `done`; guardrails de várias misses podem ir no mesmo PR desde que cada uma tenha seu `closes`. Miss que não admite guardrail determinístico vira convenção explícita marcada "judgment-only" — não fingir que doc é guarda.
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,6 @@ pnpm agent:status
|
|||
- **Bloqueios** — cada `blocked` com o motivo (dep aberta, jurídico, `requirements-changed`).
|
||||
- **Sugestões de consolidação** — as heurísticas do script (merge por domínio+prio; break-down por gargalo de depends) como **texto para o usuário decidir**. Nunca aplique consolidação aqui: aplicação é manual ou via `plan-issue`/`pnpm agent:register`. Nunca proponha nada sobre Issues `in-progress`.
|
||||
|
||||
3. Se o usuário pedir interpretação além da saída (ex.: "o que destrava mais coisa?"), responda a partir do grafo — sem inventar dados que o script não imprimiu; se faltar dado, leia a Issue via API do GitHub (MCP/`pnpm issue`) somente-leitura.
|
||||
3. Se o usuário pedir interpretação além da saída (ex.: "o que destrava mais coisa?"), responda a partir do grafo — sem inventar dados que o script não imprimiu; se faltar dado, leia a Issue via API do GitHub (`gh` CLI / `pnpm issue` + `scripts/lib/github-api.mjs`) somente-leitura.
|
||||
|
||||
**NÃO faz:** editar `docs/roadmap.md` (legado congelado), claim, registro, qualquer escrita de Issue.
|
||||
|
|
|
|||
25
.opencode/agent/penpot.md
Normal file
25
.opencode/agent/penpot.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
description: Usa Penpot MCP para consultar geometria, páginas e componentes do design do site (Teqo)
|
||||
mode: subagent
|
||||
---
|
||||
|
||||
# Penpot — subagente de design
|
||||
|
||||
Você é o subagente dedicado ao **Penpot MCP** neste repo. O MCP `penpot` (remote, `design.penpot.app`) está declarado em `opencode.json` mas com `permission` negado na sessão primária — só este subagente tem `penpot*` liberado. Use-o quando o agente principal precisar inspecionar o design do site, geometria de páginas, tokens ou mapas.
|
||||
|
||||
## Quando usar
|
||||
|
||||
- O agente principal delega via `Task` (tool `task`) com `subagent_type: "penpot"` quando precisa do Penpot.
|
||||
- Não é um gerenciador de MCPs — são dois subagentes fixos (`penpot`, `postgres`), nada dinâmico.
|
||||
|
||||
## Ferramentas
|
||||
|
||||
- `penpot_execute_code` — executa código no contexto do plugin Penpot (`penpot`, `penpotUtils`, `storage`).
|
||||
- `penpot_export_shape` — exporta shape/página como PNG/SVG.
|
||||
- Leia `penpot_high_level_overview` antes de usar a API se ainda não leu.
|
||||
|
||||
## Limites
|
||||
|
||||
- Não edite `~/.config/opencode/opencode.jsonc` (global manual, fora do git).
|
||||
- Não invente gerenciador/descoberta dinâmica.
|
||||
- MCP aponta para o design do Teqo via token em `.opencode/secrets/penpot-token` (`{file:...}`) — mantido por `scripts/worktree.mjs:copyOpendevSecrets`.
|
||||
26
.opencode/agent/postgres.md
Normal file
26
.opencode/agent/postgres.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
description: Consulta o banco local teqo (Postgres) via MCP — read-only por padrão
|
||||
mode: subagent
|
||||
---
|
||||
|
||||
# Postgres — subagente de banco local
|
||||
|
||||
Você é o subagente dedicado ao **Postgres MCP** neste repo. O MCP `postgres` (`npx @modelcontextprotocol/server-postgres`, `postgresql://teqo:teqo@localhost:5432/teqo`) está declarado em `opencode.json` mas com `permission` negado na sessão primária — só este subagente tem `postgres*`/`query` liberado.
|
||||
|
||||
## Quando usar
|
||||
|
||||
- O agente principal delega via `Task` com `subagent_type: "postgres"` quando precisa inspecionar o banco local.
|
||||
- Use para `SELECT` read-only, inspeção de schema (`postgres://<host>/<table>/schema`), debug de migrations ou dados de campanha/municípios.
|
||||
|
||||
## Limites
|
||||
|
||||
- **Nunca** aponte `DATABASE_URL` para `teqo_1313` (prod no homeserver) — guards `guard-dev-db` / `assertTestDatabase` continuam valendo. O MCP aponta fixo para `teqo` (não `teqo_wt*`); worktrees isolados com `teqo_wt<slot>` devem usar `psql $DATABASE_URL` direto, não o MCP.
|
||||
- Não edite `~/.config/opencode/opencode.jsonc` (global manual).
|
||||
- Não crie gerenciador dinâmico de MCPs.
|
||||
- Todas as queries rodam em transação `READ ONLY` (garantia do server).
|
||||
|
||||
## Exemplo
|
||||
|
||||
```sql
|
||||
SELECT count(*) FROM "municipality";
|
||||
```
|
||||
|
|
@ -10,7 +10,7 @@ Production is self-hosted on the homeserver (`jorgesolla1313.com.br`, behind the
|
|||
|
||||
- Local dev runs against a local Docker Postgres (`pnpm db:start`). To copy production content locally, use `pnpm db:pull` (`scripts/db-pull.mjs`): it only reads prod, only writes local, and excludes supporter PII (`contact`/`signature`/`subscription` row data).
|
||||
- `pnpm db:doctor` diagnoses local database connectivity for the dev AND test targets: it names who holds the port, points at exited/crash-looping containers, and flags Postgres containers sharing one data volume (two postmasters on one PGDATA corrupt the WAL — this destroyed the local cluster's checkpoint on 2026-07-25; the canonical setup is ONE compose container on 5432 hosting `teqo` + `teqo_test`). `pnpm dev` runs the same preflight via `guard-dev-db` and refuses to start with a named remedy instead of a later ECONNREFUSED. `db:start`/`db:stop` pin the compose project with `-p teqo`, so they always target that ONE container even from a worktree directory. **`db:start` is idempotent (OPS37):** with `teqo-postgres-1` up and healthy it is a no-op — a plain `compose up` from another worktree would recreate the shared container and kill every live dev/e2e connection (the compose file's relative `./docker/postgres/init` bind mount makes the config hash differ per worktree); apply a real config/image change on purpose with `pnpm db:start --force-recreate`.
|
||||
- **Per-worktree environments (`pnpm worktree next`, 2026-08-08; default-go 2026-08-10):** parallel agents each get a deterministic isolated env — no fighting over port 3000, the shared `teqo_test`, or a second Postgres container. **`next` claims BEFORE creating the worktree (OPS33, 2026-08-10):** the same queue/order and optimistic lock as `pnpm agent:claim` (shared `claimIssue` in `scripts/lib/agent-github.mjs`); a failed claim prints the reason and stops with no orphan worktree; `--issue <N>` claims the directed issue (`ready`) or **reopens** an already-claimed one (`in-progress`, no re-claim, worktree reuse stays idempotent); the claim brief is printed and the output warns "já claimada — não rodar `pnpm agent:claim"` (`plan`/`new`/`kill` never touch Issues; the pool's coordinated `claimIssueForPool` is untouched). `worktree next [--issue N] [--stay]` provisions: a dev-server port `3100+slot` (slot = numeric part of the issue code, capped at 999 with hash fallback, bumped on collision among live worktrees), plus dedicated databases `teqo_wt<slot>` (dev) and `teqo_wt<slot>_test` (tests) created on the shared container with the full migration chain AND the minimal seed applied (`pnpm migrate` + `pnpm db:seed:minimal` per database — OPS28 parity: CI runs the same pair before e2e, so a worktree's `pnpm test:e2e` mirrors CI instead of failing on seed-dependent specs; the seed is idempotent and local-guarded, and `--no-migrate` skips both); writes `.env.local` + `.env.test.local` (gitignored, marker `# teqo worktree env (generated by pnpm worktree next)`; manual envs are never overwritten) and copies `PAYLOAD_SECRET`/`S3_*` (all-or-nothing)/VAPID from the main repo — plus the gitignored `.opencode/secrets/*` (e.g. `penpot-token`, referenced by the worktree's `opencode.json` MCP config), without which opencode refuses to launch ("bad file reference" for the dangling `{file:…}`). **`next`/`plan`/`new` print `cd <dir>` as the last line BY DEFAULT** — the caller applies it... (line truncated to 2000 chars)
|
||||
- **Per-worktree environments (`pnpm worktree next`, 2026-08-08; default-go 2026-08-10):** parallel agents each get a deterministic isolated env — no fighting over port 3000, the shared `teqo_test`, or a second Postgres container. **`next` claims BEFORE creating the worktree (OPS33, 2026-08-10):** the same queue/order and optimistic lock as `pnpm agent:claim` (shared `claimIssue` in `scripts/lib/agent-github.mjs`); a failed claim prints the reason and stops with no orphan worktree; `--issue <N>` claims the directed issue (`ready`) or **reopens** an already-claimed one (`in-progress`, no re-claim, worktree reuse stays idempotent); the claim brief is printed and the output warns "já claimada — não rodar `pnpm agent:claim"` (`plan`/`new`/`kill` never touch Issues; the pool's coordinated `claimIssueForPool` is untouched). `worktree next [--issue N] [--stay]` provisions: a dev-server port `3100+slot` (slot = numeric part of the issue code, capped at 999 with hash fallback, bumped on collision among live worktrees), plus dedicated databases `teqo_wt<slot>` (dev) and `teqo_wt<slot>_test` (tests) created on the shared container with the full migration chain AND the minimal seed applied (`pnpm migrate` + `pnpm db:seed:minimal` per database — OPS28 parity: CI runs the same pair before e2e, so a worktree's `pnpm test:e2e` mirrors CI instead of failing on seed-dependent specs; the seed is idempotent and local-guarded, and `--no-migrate` skips both); writes `.env.local` + `.env.test.local` (gitignored, marker `# teqo worktree env (generated by pnpm worktree next)`; manual envs are never overwritten) and copies `PAYLOAD_SECRET`/`S3_*` (all-or-nothing)/VAPID from the main repo — plus the gitignored `.opencode/secrets/*` (e.g. `penpot-token`, referenced by the repo's `opencode.json` penpot/postgres MCPs — gated to subagents `penpot`/`postgres` via `permission`), without which opencode refuses to launch ("bad file reference" for the dangling `{file:…}`). **`next`/`plan`/`new` print `cd <dir>` as the last line BY DEFAULT** — the caller applies it... (line truncated to 2000 chars)
|
||||
- To (repopulate news content, `pnpm db:seed:posts` fetches articles live from jorgesolla.com.br into the LOCAL db (same non-local `DATABASE_URL` guard as `pnpm dev`). It writes from a CLI process outside the deployed runtime, so after seeding — or after ANY direct-DB change — you must bust the production `posts` cache via `POST /api/revalidate`. See "Posts & Tags" in `AGENTS-public.md`.
|
||||
- To (re)populate the TSE 2022 election baseline, `pnpm db:seed:tse` downloads TSE open data and imports the Bahia scope into the LOCAL db (same guard). Since the 2026-07-23 hardening, elections-tab reads are cached under the `election-tse` tag — after re-seeding a database the deployed app reads, bust it via `POST /api/revalidate?tag=election-tse`. See "Election baseline data" in `AGENTS-campaign.md`.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
> Use este prompt com um agente **poderoso (visão + raciocínio)** para montar a
|
||||
> home pública da campanha a partir do rascunho Penpot e do wireframe HTML.
|
||||
> Você tem acesso ao **MCP do Penpot** (já configurado) e pode ler imagens.
|
||||
> Você tem acesso ao **MCP do Penpot via subagente `penpot`** (declarado em `opencode.json`, `permission` gated) e pode ler imagens — chame o subagente quando precisar de geometria do Penpot.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -17,11 +17,11 @@ antiga) — **não mexa nela**.
|
|||
|
||||
## 2. Fontes de verdade (leia TODAS antes de codar)
|
||||
|
||||
1. **Rascunho Penpot (o SPEC visual)** — acesse via MCP do Penpot:
|
||||
1. **Rascunho Penpot (o SPEC visual)** — acesse via subagente `penpot` (MCP `penpot`, `permission` gated):
|
||||
- Team: `369311f5-bdaf-8185-8008-54047a2d029c`
|
||||
- File: `8694f143-a620-8054-8008-66e8aa584028`
|
||||
- Page: `62dfa60b-a5ec-8097-8008-7cc15cc939bd` ("Page 2")
|
||||
- Use `penpotUtils` (getPageById, shapeStructure, dump de geometria x/y/w/h,
|
||||
- Use `penpotUtils` via `penpot_execute_code` no subagente (getPageById, shapeStructure, dump de geometria x/y/w/h,
|
||||
cores, fontes) para extrair o layout exato. Há 2 boards: **desktop
|
||||
1024×1954** e **mobile 393×2365**. Referências exportadas também em:
|
||||
`/home/fsolla/Downloads/Board(2).png` (desktop) e
|
||||
|
|
|
|||
1
docs/changelog/2026-08-24-ops92-consolidar-mcps.md
Normal file
1
docs/changelog/2026-08-24-ops92-consolidar-mcps.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
**Recently resolved (2026-08-24):** **OPS92** — consolidar MCPs do opencode: global fica só com `jina` + `playwright`; `penpot` e `postgres` viram subagentes no repo Teqo (`opencode.json` + `.opencode/agent/penpot.md`/`postgres.md` com `permission` gated — `penpot*`/`postgres*`/`query` negados no `build` e liberados só nos subagentes, validado via `opencode debug config`/`agent`); GitHub MCP morto (`github` removido do global, já `enabled:false` desde 17/08) — `gh` CLI 2.98 autenticado cobre o canal; `forgejo`/`jobspy`/`office-word`/`stalwart` re-homed para os repos donos (decisões do gate 2026-08-24): `forgejo` → `lei-mercados-digitais` + `infra-solla` + `iara-pwa`, `jobspy` → `jobs`, `office-word` → `lei-mercados-digitais`, `stalwart` → `infra-solla`; `AGENTS-infra.md:13` e `docs/campanha/prompt-montagem-home.md` coerentes com subagente, `project-status`/`engineering-audit` sem `MCP/pnpm issue`. Global é manual (fora do git, como OPS89); Teqo fica com 4 MCPs (2 globais + 2 locais), siblings com o dono + 2 globais (validado `opencode debug config` nos 5 repos). Sem migration, sem Longa, `pnpm gate:fast` verde.
|
||||
159
docs/plans/ops92-consolidar-mcps-impl.md
Normal file
159
docs/plans/ops92-consolidar-mcps-impl.md
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
# Impl: Consolidar MCPs do opencode: global fica só com playwright + jina; penpot/postgres viram subagentes; GitHub MCP morre (CLI gh); forgejo/jobspy/office-word/stalwart re-homed para os projetos donos
|
||||
|
||||
Status: aprovado
|
||||
Atualizado em: 2026-08-24
|
||||
Issue: #857
|
||||
Intenção: docs/plans/ops92-consolidar-mcps.md
|
||||
Appetite restante: ~0,5–1 dia herdado (config-only + 2 subagentes + prosa; sem migration, sem testes novos; tracer bullet)
|
||||
|
||||
## Leitura da intenção
|
||||
|
||||
- **Outcome:** abrir o opencode no Teqo expõe só `jina` + `playwright` (e built-ins) no global; `penpot` e `postgres` vivem só em subagentes do repo Teqo; GitHub via `gh` CLI; cada projeto irmão expõe localmente só o MCP que usa — sessões baratas sem perder ferramenta quando chamada.
|
||||
- **O que NÃO negociar:** anti-goals da intenção — NÃO criar gerenciador de MCPs; NÃO automatizar config global (continua manual do dono, como OPS89); NÃO criar config morta em projeto que não pediu; NÃO tocar `eur-lex`/`mcp-brasil` no `lei-mercados-digitais`; NÃO mexer em credenciais/tokens além de mover blocos; NÃO auditar/limpar configs fora dos destinos confirmados; freeze de migrations/LGPD/URLs não afetado.
|
||||
- **O que reavaliar:** hipóteses de "Direção no codebase" — confirmadas com leitura ao vivo:
|
||||
- Global real `~/.config/opencode/opencode.jsonc` tem 7 MCPs (`github:false` + `jina` + `playwright` + `postgres` + `forgejo` + `stalwart` + `office-word` + `jobspy`) — remover 5 blocos inteiros, manter 2.
|
||||
- Repo Teqo `opencode.json` (10 linhas) hoje só `$schema` + `mcp.penpot` (`:4-8`, token em `.opencode/secrets/penpot-token` via `{file:…}`) — vai ganhar `postgres` irmão.
|
||||
- Subagentes existentes `.opencode/agent/*.md` (4 arquivos) — `design-vision*.md` com `mode: subagent` + `model: deepinfra/Qwen…`, `designer-campanha-solla.md` com `mode: all` — dão o precedente de frontmatter (`description`/`mode`/`model`/`temperature`).
|
||||
- Irmãos verificados: `jobs/opencode.json` só `provider` (herda tudo do global); `lei-mercados-digitais/opencode.json` só `eur-lex`+`mcp-brasil`; `infra-solla/opencode.jsonc` desliga `postgres:false` e herda `forgejo`/`stalwart`/`office-word` dos globais; `iara-pwa/opencode.jsonc` desliga `postgres:false` + `stalwart:false` (Issue #5 dela) e herda `forgejo`.
|
||||
- `scripts/worktree.mjs:239-258` (`copyOpendevSecrets`) copia `.opencode/secrets/*` — vira no-op se o repo não declarar `penpot` (mas penpot permanece declarado, então continua vivo).
|
||||
- Menções `(MCP|pnpm issue)` em skills: `.agents/skills/project-status/SKILL.md:25`, `.agents/skills/work-issue/SKILL.md:82` + `engineering-audit/SKILL.md:69` — trocar para `gh`/sem MCP.
|
||||
|
||||
## Abordagem recomendada
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
G["~/.config/opencode/opencode.jsonc\n(global, manual, fora do git)\nANTES 7 MCPs -> DEPOIS só jina + playwright\nREMOVE github/postgres/forgejo/stalwart/office-word/jobspy"] --> T["Sessão opencode no Teqo\nbuilt-ins + 2 MCPs globais"]
|
||||
R["opencode.json (repo Teqo)\nANTES só penpot (1)\nDEPOIS penpot + postgres\n + permission gate"] --> T
|
||||
R --> S1[".opencode/agent/penpot.md\nsubagent, permission: penpot/* allow"]
|
||||
R --> S2[".opencode/agent/postgres.md\nsubagent, permission: postgres/* allow"]
|
||||
S1 --> T
|
||||
S2 --> T
|
||||
T -->|usa quando precisa| GH["GitHub via gh CLI\n(gh 2.98 auth ok)"]
|
||||
G2["Re-homed (repos donos)\njobs/opencode.json -> jobspy\nlei/opencode.json -> forgejo+office-word\ninfra/opencode.jsonc -> forgejo+stalwart\niara/opencode.jsonc -> forgejo"] --> O["Sessões nesses repos\nexpõem só o dono"]
|
||||
```
|
||||
|
||||
**Decisões caras (deliberadas com rejeitadas):**
|
||||
|
||||
### D1 — Onde declarar `penpot` + `postgres` (caro: muda quem paga contexto em toda sessão)
|
||||
|
||||
```
|
||||
Opções: A | B | C
|
||||
Recomendação: A — ambos em opencode.json do repo Teqo (commitado) + 2 subagentes no repo
|
||||
Alternativas rejeitadas: B porque global voltaria a pagar contexto em TODO projeto (anula o outcome: abrir no Teqo custa mínimo mas abrir em jobs/lei também pagaria penpot/postgres); C porque remover postgres totalmente perde a ferramenta local deste projeto (banco teqo é ferramenta diária, não "outro projeto" — a intenção fixa "ficam no Teqo mas só dentro de subagentes")
|
||||
```
|
||||
|
||||
- A mantém o princípio "edit the owner, don't twin" (OPS82/OPS89): repo é o dono de penpot (design do site) e do postgres local; global paga 0.
|
||||
- B (global) foi cogitado no gate aberto — rejeitado exatamente pelo corte "repo Teqo (`opencode.json` + `.opencode/agent/*.md`)" registrado na intenção.
|
||||
- C (matar postgres) barateia ainda mais mas remove capacidade que o plano de intenção marca como aceito explícito (`postgres` consulta o banco local).
|
||||
|
||||
### D2 — Gate de tools por agente: `permission` vs `tools` (caro: se errar o mecanismo, o gate é silenciosamente ignorado)
|
||||
|
||||
```
|
||||
Opções: A | B | C
|
||||
Recomendação: A — permission por agente (mecanismo vigente)
|
||||
Alternativas rejeitadas: B porque AgentConfig.tools está deprecated no schema e opencode debug config já mostra agent.<nome>.permission vazio — tools seria ignorado sem erro visível, sessão primária continuaria vendo penpot/postgres e o outcome "só nos subagentes" falharia silenciosamente; C porque sem gate nenhum, penpot/postgres voltam a custar em toda sessão (anula D1)
|
||||
```
|
||||
|
||||
- Validar na hora com `opencode debug config | grep -A2 permission` e `opencode debug agent penpot` / `postgres` — o executor valida o mecanismo vigente, sem inventar paralelo.
|
||||
- Precedente: intenção já sinaliza "mecanismo oficial de gate … marcado como deprecated em favor de `permission` — o executor valida o mecanismo vigente na hora".
|
||||
|
||||
### D3 — Global manual vs automação (caro: automação reverte decisão de propriedade)
|
||||
|
||||
```
|
||||
Opções: A | B
|
||||
Recomendação: A — edição manual pelo dono, fora do git (mesmo padrão OPS89, sem CI lendo opencode.json)
|
||||
Alternativas rejeitadas: B porque automatizar o global cria gerenciador de MCPs (rabbit hole nomeado da intenção) e acopla CI a arquivo fora do repo que nenhum gate valida estruturalmente — já provado que nenhum gate/CI lê opencode.json (OPS89: zero readFileSync/JSON.parse em tests/, zero match em .github/)
|
||||
```
|
||||
|
||||
- Arquivo `~/.config/opencode/opencode.jsonc` é JSONC com comentários `//` pt-BR (estilo `cheapestinception`/`deepinfra`) — blocos removidos manualmente, validado com `opencode debug config` após.
|
||||
|
||||
### D4 — Destinos do re-home (caro: colocar no projeto errado cria config morta = mesmo desperdício)
|
||||
|
||||
```
|
||||
Opções: A | B | C
|
||||
Recomendação: A — só os destinos confirmados no gate 2026-08-24 (intenção "Questões em aberto"): forgejo -> lei-mercados-digitais + infra-solla + iara-pwa; jobspy -> jobs; office-word -> lei-mercados-digitais; stalwart -> só infra-solla
|
||||
Alternativas rejeitadas: B porque adicionar stalwart em iara-pwa contradiz decisão versionada da própria iara-pwa (opencode.jsonc Issue #5 "e-mail pessoal; fora do fluxo de dev") — já desabilita stalwart; C porque adicionar office-word em infra-solla cria twin sem dono (intenção decide "não — só lei-mercados-digitais; AGENTS.md do infra-solla sai coerente sem office-word")
|
||||
```
|
||||
|
||||
- Prova: `iara-pwa/opencode.jsonc: stalwart { enabled:false }` com comentário Issue #5; `infra-solla/AGENTS.md:65` lista hoje `office-word` em uso — vai sair da lista.
|
||||
- `jobs/opencode.json` hoje sem `mcp` — herda tudo do global; após re-home, declara explicitamente só `jobspy`.
|
||||
|
||||
### D5 — Morte do GitHub MCP e validação (caro: se gh não cobre, perde capacidade)
|
||||
|
||||
```
|
||||
Opções: A | B
|
||||
Recomendação: A — remover bloco github do global e usar gh CLI (já autenticado, já fallback real nos scripts do repo)
|
||||
Alternativas rejeitadas: B porque reativar GitHub MCP exige OAuth nunca autorizado desde 17/08 (bloco já com enabled:false) e duplicaria canal com gh — scripts/check-changelog-append-only.mjs e check-plans-only-pr-closes.mjs já provam gh como fallback
|
||||
```
|
||||
|
||||
- Verificação ao vivo: `gh auth status` → `fsolla` logged in (GITHUB_TOKEN + keyring); `opencode debug config` após limpeza não lista `github` em `mcp`.
|
||||
|
||||
### Componentes / mudanças
|
||||
|
||||
- **`~/.config/opencode/opencode.jsonc` (global, FORA do repo — MANUAL, dono aplica; não commitar)** — remover 5 blocos de `mcp`: `github` (já `enabled:false` mas ainda declara tipo/url — deletar inteiro), `postgres`, `forgejo`, `stalwart`, `office-word`, `jobspy`. Mantém só `jina` + `playwright` + `provider` (`cheapestinference`/`deepinfra`/`vercel`) + `permission` + `model`/`compaction`. Validar com `opencode debug config` (deve listar só 2 MCPs globais + o repo penpot/postgres quando dentro do Teqo).
|
||||
- **`opencode.json` (repo Teqo, raiz)** — de 10 linhas (`$schema` + `mcp.penpot`) para `penpot` + `postgres` como siblings em `mcp`. `postgres` bloco: `type:local, command: [npx -y @modelcontextprotocol/server-postgres, postgresql://teqo:teqo@localhost:5432/teqo], enabled:true` (mesmo command hoje no global). Adicionar `permission` top-level para gating (mecanismo A da D2): denegar por default na sessão primária e liberar por agente — validar schema vigente (`opencode debug config` deve mostrar `agent.penpot.permission` e `agent.postgres.permission` com allows). Sem `permission`, o Teqo voltaria a pagar 2 MCPs em toda sessão (anula D1 — B rejeitada).
|
||||
- **`.opencode/agent/penpot.md` (novo)** — `mode: subagent`, `description` fixa "usa Penpot MCP para geometria do site", `model` herdado ou sem override, `permission` liberando `penpot:*`. Reusa frontmatter de `design-vision.md` (`mode: subagent`, `model: deepinfra/Qwen…`, `temperature: 0.2`) como precedente; não cria gerenciador dinâmico.
|
||||
- **`.opencode/agent/postgres.md` (novo)** — `mode: subagent`, `description` "consulta o banco local teqo (read-only por padrão)", `permission` liberando `postgres:*`. Mesmo molde. O MCP aponta para `teqo` fixo (não `teqo_wt*` do worktree) — documentar limitação e nunca usar contra prod `teqo_1313` (guard `guard-dev-db`/`assertTestDatabase` continuam).
|
||||
- **`scripts/worktree.mjs:239-258, 345`** — nenhuma mudança de código: `copyOpendevSecrets` continua copiando `.opencode/secrets/penpot-token`; com penpot ainda declarado no repo, não vira no-op. Só nota de verificação: sem penpot no repo, o `{file:.opencode/secrets/penpot-token}` dangling faria `opencode` recusar abrir — por isso penpot permanece declarado (intenção: "a cópia de secrets continua necessária — penpot permanece declarado no repo").
|
||||
- **Projetos irmãos (edits commitados nesses repos, não no Teqo — listar como verificação cruzada; no Teqo o diff é só prosa/docs):**
|
||||
- `jobs/opencode.json` — adicionar `mcp.jobspy` (bloco hoje no global: `command: [.venv/bin/python, mcp/jobspy_server.py]`).
|
||||
- `lei-mercados-digitais/opencode.json` — adicionar `mcp.forgejo` + `mcp.office-word`; manter `eur-lex` + `mcp-brasil` intactos.
|
||||
- `infra-solla/opencode.jsonc` — declarar `mcp.forgejo` + `mcp.stalwart` locais (blocos copiados do global, com `FORGEJO_*`/`JMAP_*`); remover pin morto `"postgres": {enabled:false}` ; atualizar `AGENTS.md:65` para remover `office-word` da lista "Em uso" (fica `forgejo, jina, playwright, stalwart + locais airbnb/homeexchange/whatsapp`).
|
||||
- `iara-pwa/opencode.jsonc` — declarar `mcp.forgejo` local; limpar pins mortos `"postgres": {enabled:false}` e `"stalwart": {enabled:false}` (este último já é `enabled:false` proposital, mas com re-home global sem stalwart, o pin vira ruído — remover e deixar comentário da Issue #5).
|
||||
- **Prosa/docs no Teqo:**
|
||||
- `AGENTS-infra.md:13` — atualizar frase que cita `.opencode/secrets/*` (ex.: `penpot-token`, referenciado pelo `opencode.json` MCP config → agora `penpot/postgres` gated por subagentes).
|
||||
- `docs/campanha/prompt-montagem-home.md:24` — atualizar "Use `penpotUtils` …" para "via subagente `penpot` (`penpot` MCP)" — hoje diz "MCP do Penpot (já configurado)" sem mencionar subagente.
|
||||
- `.agents/skills/project-status/SKILL.md:25` — trocar `MCP/pnpm issue` por `gh CLI / pnpm issue` (remove menção a MCP morto); `engineering-audit/SKILL.md:69` mesma limpeza.
|
||||
- `docs/campanha/plano-site-campanha-2026.md` se citar penpot MCP como ativo — verificar e atualizar.
|
||||
- **Migration:** sem migration — config-only; nenhum schema Payload muda (`push:false` não tocado).
|
||||
- **Access / Consent:** N/A — sem collection/PII; não afeta `CampaignUser`/`Consent` fail-closed.
|
||||
- **UI:** N/A — Impeccable A (sem UI); TUI do opencode é consumidor de verificação, não produto.
|
||||
|
||||
### Dados → forma (se aplicável)
|
||||
|
||||
Não há dado de negócio. Forma é tooling de dev — a única "forma" deliberada é a de **gate** (D2: `permission` vs `tools`), já decidida acima com rejeitadas e gatilho de revisitação (se o schema estabilizar outro mecanismo, validar com `opencode debug config` antes de replicar).
|
||||
|
||||
## Fases verificáveis
|
||||
|
||||
1. **Tracer Teqo (repo + subagentes) — 40% do appetite** — `opencode.json` com `penpot`+`postgres` + `permission` gate; criar `.opencode/agent/penpot.md` + `postgres.md` (frontmatter no molde `design-vision*.md`). Verificar **dentro do Teqo**: `opencode debug config` lista `penpot`+`postgres` no `mcp` mas `agent penpot`/`postgres` têm `permission` allow; sessão primária `opencode debug agent build` não lista tools penpot/postgres; `node -e "JSON.parse(require('fs').readFileSync('opencode.json','utf8'))"` passa; `pnpm gate:fast` verde (nenhum teste lê `opencode.json` estruturalmente — já provado em OPS89). Push via `pnpm push` → CI `checks` verde.
|
||||
2. **Global manual (dono) — condiciona o aceite, ordem recomendada: antes do merge** — remover do global os 5 blocos (`github`/`postgres`/`forgejo`/`stalwart`/`office-word`/`jobspy` — github já `false`, deletar). Verificar **fora de qualquer repo ou no Teqo após**: `opencode debug config` mostra só `jina`+`playwright` em `mcp` global; `gh auth status` continua `Logged in`; `opencode agent list` sem `github`. Se o dono não aplicar antes do merge, a janela é aceita (global com twin temporário vs Teqo já limpo — configs são merged, sem perda) — gatilho: aceitar fecha só com Fase 2 verde.
|
||||
3. **Re-home irmãos (nos repos donos) — 30% do appetite, em PRs separados por repo** — `jobs` (+jobspy), `lei-mercados-digitais` (+forgejo+office-word), `infra-solla` (+forgejo+stalwart, remove postgres pin, AGENTS.md sem office-word), `iara-pwa` (+forgejo, limpa pins postgres/stalwart). Verificar por repo: `opencode debug config` dentro de cada repo lista só os MCPs donos + os 2 globais (`jina`/`playwright`); nenhum lista MCP de outro dono.
|
||||
4. **Prosa + validação de ponta a ponta — 30% do appetite** — atualizar `AGENTS-infra.md`, `prompt-montagem-home.md`, `project-status/SKILL.md`, `engineering-audit/SKILL.md`; `grep -rn "MCP.*pnpm issue\|penpot MCP.*ativo" .agents docs AGENTS-infra.md` deve retornar só histórico ou nada; validar fluxo desejado: abrir opencode no Teqo → `Task` para `penpot` executa `penpotUtils.getPageById` com sucesso; `Task` para `postgres` executa `SELECT 1` no `teqo`; `gh issue view 857` funciona; `pnpm dev` sobe e `pnpm worktree next --stay --no-migrate` provisiona com `penpot-token` copiado (não "bad file reference").
|
||||
|
||||
## Rabbit holes / Não escopo (engenharia)
|
||||
|
||||
- NÃO criar gerenciador/descoberta dinâmica de MCPs — só 2 subagentes fixos (corte da intenção; D1-B/C já rejeitados).
|
||||
- NÃO automatizar o global (script que reescreve `~/.config/opencode/opencode.jsonc`) — continua manual do dono (D3-B rejeitada; OPS89 já provou manual sem CI).
|
||||
- NÃO editar credenciais/tokens em claro — mover blocos e só; validar lendo (`{env:…}` / `{file:…}` continuam referenciando env/arquivo, sem inline).
|
||||
- NÃO tocar `eur-lex`/`mcp-brasil` no `lei-mercados-digitais` nem auditar/limpar configs de projetos fora da lista de 4 irmãos.
|
||||
- NÃO reformatar JSONC globais além dos blocos removidos — tocar só `mcp.*`, manter `provider.*`/`permission`/`model`/`compaction`.
|
||||
- NÃO alterar `scripts/worktree.mjs` — com penpot ainda no repo, a cópia de secrets não é no-op; mexer vira risco de "bad file reference".
|
||||
- NÃO trocar `postgres` para `teqo_wt*` dinâmico — o MCP continua apontando para `teqo` fixo; worktrees com banco isolado usam `psql`/`DATABASE_URL` direto, não o MCP.
|
||||
|
||||
## Riscos e mitigação
|
||||
|
||||
- **Global JSONC inválido após edição manual** → loader do opencode falha alto; mitigar com `opencode debug config` imediatamente após colar e `python3 -m json.tool` não serve (JSONC) — usar `opencode debug config` como validator; manter backup do arquivo antes.
|
||||
- **Token leak no debug** → `opencode debug config` no global imprime secrets resolvidos (`FORGEJO_ACCESS_TOKEN`, `JMAP_PASSWORD`, `penpot userToken`); não colar saída em Issue/PR/log; ao validar nos irmãos, redigir tokens (`grep` por `enabled` sem `debug` quando só precisa listar keys).
|
||||
- **Permission gate silenciosamente ignorado (tools vs permission)** → sessão primária continuaria vendo penpot/postgres e o custo volta; mitigar validando `opencode debug agent penpot`/`postgres` e `opencode debug agent build` após D1; se o schema mudar, o plano volta a D2 com evidência (gatilho explícito).
|
||||
- **Editar 4 repos irmãos cria config morta** → só os destinos confirmados no gate (D4); cada PR irmão verificado com `opencode debug config` dentro daquele repo (deve listar só dono + jina/playwright).
|
||||
- **`scripts/worktree.mjs` vira no-op sem penpot** → não acontece porque penpot permanece declarado no repo Teqo (intenção trava); se alguém remover penpot do `opencode.json`, o worktree falha com "bad file reference" — gatilho de reversão imediata.
|
||||
- **`postgres` MCP aponta para `teqo` fixo, não para `teqo_wt*` do worktree** → subagente postgres no worktree consulta o banco errado se o dev espera `teqo_wt`; documentar nos dois `.md` que o MCP é para `teqo` (main/shared) e que worktrees isolados devem usar `psql $DATABASE_URL` direto; nunca apontar `DATABASE_URL` para `teqo_1313` prod (guard `guard-dev-db`/`assertTestDatabase` continuam).
|
||||
- **Global editado sem CI (sem rede de segurança automatizada)** → nenhum gate lê `opencode.jsonc` global; mitigar com verificação manual `opencode debug config` + `gh auth status` + `opencode agent list` na Fase 2; manter twin temporário (global+repo com mesmo bloco) até Fase 2 verde — configs são merged, sem janela de perda (só custo temporário).
|
||||
- **Infra-solla AGENTS.md stale** → após re-home, `grep -n office-word AGENTS.md` deve dar zero; CI de `infra-solla` (`docker compose config -q`) não valida MCP, então a verificação é manual via `opencode debug config` naquele repo.
|
||||
|
||||
## Aceite de engenharia
|
||||
|
||||
- [ ] Aceite de produto da intenção coberto: Teqo expõe só `playwright`+`jina` no global; `penpot` e `postgres` só via subagentes no repo Teqo (com `permission` gate validado); GitHub via `gh` sem perda; cada irmão expõe só o dono (forgejo/jobspy/office-word/stalwart nos destinos confirmados); `pnpm dev`, `worktree next` e docs que citam penpot coerentes.
|
||||
- [ ] Invariantes AGENTS/engineering-standards: sem twin — global é owner só de `jina`/`playwright`, cada repo é owner do seu MCP; sem gerenciador; sem automação do global; sem credencial inline; sem migration retroativa.
|
||||
- [ ] Testes de domínio previstos: sem testes novos — config-only; `pnpm gate:fast` verde já cobre que nenhum teste lê `opencode.json` estruturalmente (OPS89); verificação é `opencode debug config` + `gh auth status` + `Task` penpot/postgres.
|
||||
- [ ] Prosa/docs vivos sem menção stale a "MCP/ `pnpm issue`" (skills) nem "penpot MCP ativo" sem subagente.
|
||||
|
||||
## Self-score decision-quality
|
||||
|
||||
1. **Decisões caras têm rejeitadas?** Sim — D1 (A|B|C: B paga contexto em todo projeto, C perde ferramenta local), D2 (A|B|C: B é deprecated silencioso, C anula gate), D3 (A|B: B vira gerenciador contra anti-goal), D4 (A|B|C: B contradiz Issue #5 iara, C cria config morta), D5 (A|B: B reanima OAuth morto) — formato `Opções: A | B | C / Recomendação: … — porque … / Alternativas rejeitadas: … porque …` em todas.
|
||||
2. **Cabe no appetite?** Sim — config-only + 2 subagentes + prosa + `opencode debug config`; ~0,5–1 dia herdado mantido; sem migration, sem testes novos; tracerbullet Fase 1 entrega Teqo isolado antes de tocar irmãos.
|
||||
3. **Rabbit holes nomeados?** Sim — gerenciador de MCPs, automação do global, credenciais em claro, reformatar global inteiro, tocar eur-lex/mcp-brasil, auditar outros projetos, worktree.mjs, postgres dinâmico — todos com corte "não fazer" explícito.
|
||||
4. **Depth check reusa?** Sim — reusa `opencode.json` existente (não duplica global), frontmatter de `.opencode/agent/design-vision*.md` (mode subagent/model/temperature), bloco `postgres` idêntico ao global, `copyOpendevSecrets` existente, `gh` CLI já fallback nos scripts, `permission` vigente (não inventa paralelo).
|
||||
5. **Intenção (aceite de produto) permanece satisfeita?** Sim — engenharia não reescreveu outcome; só concretizou "penpot/postgres viram subagentes" + gate + re-home confirmado no gate 2026-08-24; nenhuma hipótese reavaliada muda resultado nem escopo.
|
||||
|
||||
**Score: 5/5** — gate ≥4 atendido.
|
||||
|
|
@ -5,6 +5,40 @@
|
|||
"type": "remote",
|
||||
"url": "https://design.penpot.app/mcp/stream?userToken={file:.opencode/secrets/penpot-token}",
|
||||
"enabled": true
|
||||
},
|
||||
"postgres": {
|
||||
"type": "local",
|
||||
"command": [
|
||||
"npx",
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-postgres",
|
||||
"postgresql://teqo:teqo@localhost:5432/teqo"
|
||||
],
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"permission": {
|
||||
"penpot*": "deny",
|
||||
"postgres*": "deny",
|
||||
"query": "deny",
|
||||
"forgejo*": "deny",
|
||||
"stalwart*": "deny",
|
||||
"office-word*": "deny",
|
||||
"office_word*": "deny",
|
||||
"jobspy*": "deny",
|
||||
"github*": "deny"
|
||||
},
|
||||
"agent": {
|
||||
"penpot": {
|
||||
"permission": {
|
||||
"penpot*": "allow"
|
||||
}
|
||||
},
|
||||
"postgres": {
|
||||
"permission": {
|
||||
"postgres*": "allow",
|
||||
"query": "allow"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue