From 5987aedeaf0688c43eee505937cc5af3cf6126d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Ign=C3=A1cio=20Fontoura=20Solla?= Date: Thu, 30 Jul 2026 21:40:40 -0300 Subject: [PATCH] chore(ops): Cloud Agents rename session and use pnpm push without Docker Document native Postgres on Cloud (no db:start) and that gate:fast/push need no DB. Print rename_chat title in agent:claim brief; reinforce rename_chat + pnpm push (not raw --no-verify) in work-issue skill. --- .cursor/cloud-setup.sh | 1 + .cursor/skills/local-database/SKILL.md | 4 ++++ .cursor/skills/work-issue/SKILL.md | 18 +++++++++++++----- docs/AGENT-OPS.md | 2 ++ scripts/agent-claim.mjs | 17 ++++++++++++++--- 5 files changed, 34 insertions(+), 8 deletions(-) diff --git a/.cursor/cloud-setup.sh b/.cursor/cloud-setup.sh index 3c319cdf..334be2aa 100755 --- a/.cursor/cloud-setup.sh +++ b/.cursor/cloud-setup.sh @@ -32,3 +32,4 @@ echo "[cloud-setup] seeding teqo_test..." DATABASE_URL=postgresql://teqo:teqo@localhost:5432/teqo_test pnpm db:seed:minimal echo "[cloud-setup] OK — minimal database ready (dev + test)." +echo "[cloud-setup] gate:fast/gate:push need no DB; use pnpm push (not raw git push --no-verify)." diff --git a/.cursor/skills/local-database/SKILL.md b/.cursor/skills/local-database/SKILL.md index b69cedf2..89fe9fb1 100644 --- a/.cursor/skills/local-database/SKILL.md +++ b/.cursor/skills/local-database/SKILL.md @@ -13,6 +13,10 @@ Production is a live **Neon Postgres** with real citizens' PII. Local developmen - Tests load `.env.test` (database `teqo_test`) and call `assertTestDatabase()` (`tests/helpers/assertTestDatabase.ts`), which **throws** unless the database name ends in `_test`. - Never repoint `DATABASE_URL` in `.env`, `.env.local`, or `.env.test` at Neon. `.env.test` is committed and local-only on purpose. +## Cursor Cloud (sem Docker) + +VMs Cloud **não rodam** `docker compose` / `pnpm db:start`. Postgres nativo: `.cursor/environment.json` (`cloud-setup.sh` + `ensure-postgres.sh`). Mesmos URLs `localhost:5432/teqo` e `teqo_test`. Agentes em `work-issue`: não tente Docker; `gate:fast`/`gate:push` não precisam de banco. + ## Local connection values - Dev database: `postgresql://teqo:teqo@localhost:5432/teqo` diff --git a/.cursor/skills/work-issue/SKILL.md b/.cursor/skills/work-issue/SKILL.md index 3ec42cd1..f9041c29 100644 --- a/.cursor/skills/work-issue/SKILL.md +++ b/.cursor/skills/work-issue/SKILL.md @@ -14,9 +14,9 @@ Esta skill conduz UMA Issue rastreável do claim ao merge em `stage`. Substitui ## Checklist do fluxo ``` -- [ ] 0. Prep: `pnpm i` antes do `agent:claim` (Cloud Agents já rodam via `.cursor/environment.json` → `install`; worktrees locais: obrigatório, ou deixe para o `ensure-repo-deps` do `pnpm push`) +- [ ] 0. Prep: `pnpm i` antes do `agent:claim` (Cloud Agents já rodam via `.cursor/environment.json` → `install`; worktrees locais: obrigatório, ou deixe para o `ensure-repo-deps` do `pnpm push`). Cloud → §Prep Cloud (sem Docker; não use `db:start`) - [ ] 1. Claim: pnpm agent:claim (ou -- --issue ) — o brief do stdout é o contrato -- [ ] 1b. Renomear a sessão (cursor-app-control rename_chat) — padrão `# — ` +- [ ] 1b. Renomear a sessão (cursor-app-control rename_chat) — padrão `# — ` (linha `rename_chat:` do brief) - [ ] 1c. Abrir o plano no editor (cursor-app-control open_resource) para o humano acompanhar - [ ] 2. Verificação de modelo (best effort): comparar model: da Issue com o modelo da sessão - [ ] 3. Freshness audit (enxuto) do plano contra o repositório @@ -36,6 +36,14 @@ pnpm i Não pule este passo — sem deps instaladas o claim falha antes de imprimir o brief. +### Prep Cursor Cloud (sem Docker) + +VMs Cloud **não têm Docker** — `pnpm db:start` (docker compose) **não funciona** aqui. O ambiente já sobe Postgres nativo via `.cursor/environment.json` (`cloud-setup.sh` no install + `ensure-postgres.sh` no start): bancos `teqo` e `teqo_test` migrados e com `db:seed:minimal`. + +- **`pnpm gate:fast` e `pnpm gate:push` não precisam de Postgres** — `test:unit` usa `DATABASE_URL` inválida de propósito (sem conexão real). +- Só `pnpm test:int` / `pnpm migrate` tocam o banco — já preparado no install; se conexão falhar: `bash ./.cursor/ensure-postgres.sh`. +- **Proibido `git push --no-verify`** no fechamento da Issue. O pre-push roda `pnpm gate:push` (~1–2 min) — espere passar; CI não substitui o hook local. + ## Passo 1 — Claim ```bash @@ -47,7 +55,7 @@ O brief impresso no stdout é o contrato: id, priority, **model**, spec, link do ### Renomear a sessão -Logo após o claim bem-sucedido, **renomeie a aba desta conversa** para o humano identificar o trabalho em curso — não espere ele pedir. +Logo após o claim bem-sucedido, **renomeie a aba desta conversa** para o humano identificar o trabalho em curso — não espere ele pedir. Política do repo: no fluxo `work-issue` isso **não** é opcional — a descrição padrão da ferramenta MCP ("só quando o usuário pedir") não se aplica aqui. **Padrão canônico** (decisão travada — use sempre este formato, sem variações): @@ -109,7 +117,7 @@ Ordem fixa, fases pequenas e verificáveis, respeitando o appetite do plano: 1. **Schema e server** — migrations (`pnpm migrate:create`, seguir `payload-migrations`), collections, utilities, server actions, testes de domínio. Guardrails do repo: Local API com `user` → `overrideAccess: false`; escrita multi-collection → transação com `req: { transactionID }`; pessoa → join com `Contact`; opt-in/PII → `Consent` por chave estável falhando fechado. 2. **UI via /impeccable** (classes B/C/D — a classe está no plano; se A, declare "Impeccable: N/A" e siga só engenharia): shape conforme a classe → craft → critique → (harden/optimize **só sob gatilho**) → polish. Paleta = tokens `data-theme='campaign'`; reusar `src/components/ui` e shells existentes; shape obrigatório em C **para** para confirmação do brief antes do craft. -3. **Gates de engenharia** — iteração: `pnpm gate:fast`. Push: **`pnpm push`** (ensure-deps + `gate:push` no script — não depende do hook Husky). `pnpm gate:push` manual só para debug sem push. Scan Aikido dos arquivos editados. Comandos bare, nunca piped. Escape WIP: `git push --no-verify` sem passar por `pnpm push`. +3. **Gates de engenharia** — iteração: `pnpm gate:fast`. Push: **`pnpm push -u origin HEAD`** (ensure-deps + `gate:push` no script — não depende do hook Husky). `pnpm gate:push` manual só para debug sem push. Scan Aikido dos arquivos editados. Comandos bare, nunca piped. **Nunca** `git push --no-verify` cru (pula o gate) — em Cloud não há Docker, mas `gate:fast`/`gate:push` não precisam de banco (ver §Prep Cloud). Tracer bullet: se a Issue for grande, a primeira fatia vertical real (schema mínimo → uma action → uma superfície UI) vem cedo. @@ -147,4 +155,4 @@ Lance **três** subagentes via `Task` **em paralelo** na mesma mensagem — read ## Resumo final ao usuário -Issue trabalhada + sessão renomeada + plano aberto no editor + verificação de modelo (declarado vs sessão, ou registro do ausente), veredito do freshness audit, o que entrou por fase, resultado do critique/polish (se UI), simplify (3 reviewers paralelos) + débitos registrados, gates, link do PR e estado do merge em stage, pontas soltas consolidadas. `in-prod` entra no auto-promote (`promote-stage-to-main.yml`) após CI stage green — não é passo do agente. +Issue trabalhada + sessão renomeada + plano aberto no editor + verificação de modelo (declarado vs sessão, ou registro do ausente), veredito do freshness audit, o que entrou por fase, resultado do critique/polish (se UI), simplify (3 reviewers paralelos) + débitos registrados, gates (`pnpm push`, sem `--no-verify` cru), link do PR e estado do merge em stage, pontas soltas consolidadas. `in-prod` entra no auto-promote (`promote-stage-to-main.yml`) após CI stage green — não é passo do agente. diff --git a/docs/AGENT-OPS.md b/docs/AGENT-OPS.md index 8a92b893..7d1f3c1e 100644 --- a/docs/AGENT-OPS.md +++ b/docs/AGENT-OPS.md @@ -79,6 +79,8 @@ Fast gate local do agente (iteração): `pnpm gate:fast` (lint + typecheck + tes `.cursor/environment.json` instala deps, sobe Postgres nativo (`ensure-postgres.sh` — VMs Cloud não rodam Docker/compose), migra e roda `db:seed:minimal` — clone + `gh` + DB mínimo bastam. Sem secrets de stage/prod. Hooks do repo são portáteis (paths relativos em `.cursor/hooks.json`); hooks pessoais (ex.: impeccable) ficam no `~/.cursor/hooks.json` do usuário. +**Agentes Cloud (skill `work-issue`):** renomear sessão após claim (`rename_chat:` no brief); **não** usar `pnpm db:start` (Docker); **não** `git push --no-verify` cru — usar `pnpm push` (roda `gate:push` antes). `gate:fast`/`gate:push` não precisam de Postgres (`test:unit` não conecta); int/migrate usam o Postgres nativo do install. + ## Agent pool (orquestrador de workers Cloud) Supervisor **remoto** que mantém até 5 Cursor Cloud Agents rodando `work-issue` sobre Issues `ready` elegíveis para autonomia (label `ready`, sem `blocked`/`requirements-changed`/`needs:consent`, deps satisfeitas; `needs:migration` cede ao `migration-lock`). Implementação: `.github/workflows/agent-pool.yml` (tick stateless: `schedule */10min` + `pull_request` closed em `stage` + `workflow_dispatch`) rodando `scripts/agent-pool.mjs`; workers spawnados via Cloud Agents API v1 com o `model:` da Issue (fallback `composer-2.5`). Canal canônico humano: `gh workflow run agent-pool.yml -f action=start|stop|pause|resume` (wrappers: `pnpm agent:pool -- start|stop|pause|resume|status|doctor`). Estado escalar em repo variables `POOL_*`; ativos derivados (marcadores `pool-worker` nos comentários + status dos runs). Claim coordenado pelo supervisor (alocador único, sem race); falha terminal → Issue a `blocked` para triagem; fila drenada → pool se desliga. **Nunca** chama `agent:promote`. Requer repo secret `CURSOR_API_KEY`; `schedule`/trigger de PR só ativam após merge em `main`. Arquitetura e runbook: [`docs/plans/agent-pool-orchestrator.md`](plans/agent-pool-orchestrator.md) + skill `agent-pool`. diff --git a/scripts/agent-claim.mjs b/scripts/agent-claim.mjs index e709f41c..6cdf32ed 100644 --- a/scripts/agent-claim.mjs +++ b/scripts/agent-claim.mjs @@ -88,8 +88,19 @@ gh([ ]) const { rest } = parseFrontmatter(pick.issue.body) +const issueId = pick.meta.id ?? null +let subject = pick.issue.title +if (issueId) { + const idPrefix = `${issueId} — ` + if (subject.startsWith(idPrefix)) subject = subject.slice(idPrefix.length) +} +const sessionTitle = issueId + ? `#${pick.issue.number} ${issueId} — ${subject}` + : `#${pick.issue.number} — ${subject}` + console.log(`\n[agent:claim] Claimed #${pick.issue.number} — ${pick.issue.title}`) -console.log(` id: ${pick.meta.id ?? '(none)'} priority: ${pick.priority}`) +console.log(` id: ${issueId ?? '(none)'} priority: ${pick.priority}`) +console.log(` rename_chat: ${sessionTitle.slice(0, 200)}`) if (pick.meta.model) { console.log( ` model: ${pick.meta.model} (propriedade da Issue — verificar, não recalcular; ver skill model-selection)`, @@ -108,6 +119,6 @@ console.log(` url: https://github.com/fsolla/teqo/issues/${pick.issue.number}`) console.log('\n--- spec ---\n') console.log(rest.trim() || '(empty body — see linked plan)') console.log( - '\n[agent:claim] Fluxo: implementar → fast gate → gh pr create --base stage (Closes #' + - `${pick.issue.number}) → PARAR. Promote a main é humano (pnpm agent:promote --i-am-human).`, + '\n[agent:claim] Fluxo: rename_chat (cursor-app-control) → implementar → gate:fast → pnpm push -u origin HEAD → gh pr create --base stage (Closes #' + + `${pick.issue.number}) → PARAR. Promote stage→main é automático após CI stage green.`, )