docs: agent ops + slice AGENTS.md + kernels + cursorignore + portable hooks + cloud env + PR template
This commit is contained in:
parent
5b857814c3
commit
4262aa5a67
11 changed files with 1387 additions and 1192 deletions
23
.cursor/cloud-setup.sh
Executable file
23
.cursor/cloud-setup.sh
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env bash
|
||||
# Cursor Cloud environment setup: deps are installed by environment.json's
|
||||
# `install`; this script brings up the local Postgres and builds the MINIMAL
|
||||
# synthetic database (docs/AGENT-OPS.md — agents never see stage/prod URLs).
|
||||
set -euo pipefail
|
||||
|
||||
sudo service docker start
|
||||
|
||||
if [ ! -f .env ]; then
|
||||
sed 's/YOUR_SECRET_HERE/cursor-cloud-local-secret/' .env.example > .env
|
||||
echo "[cloud-setup] wrote .env from .env.example (local-only values)"
|
||||
fi
|
||||
|
||||
pnpm db:start
|
||||
|
||||
# Dev database (teqo) and test database (teqo_test) — compose creates both.
|
||||
pnpm migrate
|
||||
DATABASE_URL=postgresql://teqo:teqo@localhost:5432/teqo_test pnpm migrate
|
||||
|
||||
pnpm db:seed:minimal
|
||||
DATABASE_URL=postgresql://teqo:teqo@localhost:5432/teqo_test pnpm db:seed:minimal
|
||||
|
||||
echo "[cloud-setup] OK — minimal database ready (dev + test)."
|
||||
4
.cursor/environment.json
Normal file
4
.cursor/environment.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"install": "pnpm install --frozen-lockfile && bash ./.cursor/cloud-setup.sh",
|
||||
"start": "sudo service docker start && pnpm db:start"
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
"hooks": {
|
||||
"preToolUse": [
|
||||
{
|
||||
"command": "node \"/Users/francisco.solla/.cursor/skills/impeccable/scripts/hook-before-edit.mjs\"",
|
||||
"command": "node \".cursor/hooks/guard-env-files.mjs\"",
|
||||
"timeout": 5
|
||||
}
|
||||
]
|
||||
|
|
|
|||
37
.cursor/hooks/guard-env-files.mjs
Normal file
37
.cursor/hooks/guard-env-files.mjs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Portable write guard (repo hooks.json, preToolUse on Write/Edit).
|
||||
*
|
||||
* Denies agent writes to local env files (`.env`, `.env.local`, `.env.test`):
|
||||
* they carry DATABASE_URLs and secrets, and the parallel-ops contract says
|
||||
* agents never repoint databases (stage/prod URLs live only in CI secrets and
|
||||
* human-run scripts). Humans editing by hand are unaffected — this only gates
|
||||
* tool calls.
|
||||
*
|
||||
* Contract (same as the impeccable hook): never break a turn accidentally —
|
||||
* malformed input or internal errors allow the tool and exit 0.
|
||||
*/
|
||||
|
||||
const DENY_PATTERN = /(^|\/)\.env(\.local|\.test|\.production)?$/
|
||||
|
||||
let input = ''
|
||||
process.stdin.on('data', (chunk) => (input += chunk))
|
||||
process.stdin.on('end', () => {
|
||||
try {
|
||||
const payload = JSON.parse(input)
|
||||
const filePath = payload?.tool_input?.file_path ?? payload?.tool_input?.path ?? ''
|
||||
if (typeof filePath === 'string' && DENY_PATTERN.test(filePath)) {
|
||||
process.stdout.write(
|
||||
JSON.stringify({
|
||||
decision: 'deny',
|
||||
reason:
|
||||
'Agentes não editam arquivos .env* (contrato agentic ops: nunca repontar DATABASE_URL; stage/prod só em secrets de CI e scripts humanos).',
|
||||
}),
|
||||
)
|
||||
process.exit(0)
|
||||
}
|
||||
} catch {
|
||||
// malformed input → allow
|
||||
}
|
||||
process.exit(0)
|
||||
})
|
||||
|
|
@ -11,7 +11,7 @@ Established 2026-07-23 by the engineering-standards hardening (tracker: `docs/IM
|
|||
|
||||
1. **Dead code dies immediately.** After your edits, check what your change orphaned and delete it in the same delivery: run `pnpm exec knip` (files/dependencies are CI-blocking errors; unused exports are warnings being driven to zero). Never leave commented-out code, unused exports, superseded components, or one-shot scripts behind — git history is the archive.
|
||||
2. **Zero warnings.** `pnpm lint` runs with `--max-warnings=0`. Deliberate placeholders use a `_` prefix. Never silence a rule without an inline justification comment.
|
||||
3. **Full gate before handoff:** `pnpm exec tsc --noEmit`, `pnpm lint`, `pnpm format:check` (Prettier + organize-imports is the formatting authority — never hand-align), `pnpm exec knip`, `pnpm check:cycles` (madge — zero circular imports), `pnpm test` (unit + int, local DB only), `pnpm build`. CI (`.github/workflows/ci.yml`) runs the same on the GitHub mirror.
|
||||
3. **Gate em duas velocidades (desde 2026-07-30, paradigma de agentes paralelos — `docs/AGENT-OPS.md`).** **Fast gate local do agente** (antes de cada push): `pnpm lint`, `pnpm exec tsc --noEmit`, `pnpm test:unit` (+ `pnpm format:check` e `pnpm check:cycles` antes de commitar — o pre-push hook cobre os três primeiros). Se a entrega tocou schema: também `pnpm migrate && pnpm db:seed:minimal && pnpm test:int`. **Gate completo = CI do PR** (`ci-pr.yml`: os anteriores + knip + int + build, contra o DB mínimo). O handoff humano (promote `stage→main`) exige CI stage + ci-pr green — não o build local.
|
||||
4. **Run gate commands bare, never piped** (`pnpm test | tail` swallows the exit code). Never run `knip --fix` blind — verify each removal with `git grep -w <symbol>` first (knip still cannot load `payload.config.ts`, so its graph is incomplete; ledgered as P3).
|
||||
|
||||
## Type honesty
|
||||
|
|
|
|||
20
.cursorignore
Normal file
20
.cursorignore
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Cursor ignore — keep the always-on context lean (agentic ops, 2026-07-30).
|
||||
# Heavy reference material is read on demand, not indexed into every run.
|
||||
|
||||
# Research corpus (~67 sources) and discovery material
|
||||
docs/research/
|
||||
docs/general-coordinator-interview/
|
||||
docs/design-refs/
|
||||
docs/sheets/
|
||||
|
||||
# Committed derived artifacts (read through their loaders, never raw)
|
||||
src/lib/electionAggregates/
|
||||
src/lib/geometries/
|
||||
tests/fixtures/
|
||||
|
||||
# Download caches and build output
|
||||
data/
|
||||
.next/
|
||||
|
||||
# Historical changelog (read on demand)
|
||||
docs/CHANGELOG-AGENTS.md
|
||||
19
.github/pull_request_template.md
vendored
Normal file
19
.github/pull_request_template.md
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
## O que é
|
||||
|
||||
<!-- 2–4 linhas: o que muda e por quê. Link do plano se houver. -->
|
||||
|
||||
Closes #<!-- número da Issue (claim) -->
|
||||
|
||||
## Contrato da entrega
|
||||
|
||||
- [ ] Fast gate local passou: `pnpm lint` (0 warnings), `pnpm exec tsc --noEmit`, `pnpm test:unit`
|
||||
- [ ] `pnpm format:check` e `pnpm check:cycles` limpos
|
||||
- [ ] Órfãos da mudança deletados na mesma entrega (knip em CI confirma)
|
||||
- [ ] **Se tocou schema** (migration, collection, campo, Consent key, dado de boot): `db:seed:minimal` atualizado **neste PR** (`scripts/lib/seed-minimal-manifest.mjs` + pin unit) — senão a label `needs:migration` está errada
|
||||
- [ ] Nenhum `DATABASE_URL`/`ALLOW_REMOTE_DB` de stage/prod em script ou workflow
|
||||
- [ ] `pnpm build` NÃO aparece em workflow que carregue `STAGE_DATABASE_URL`
|
||||
- [ ] Se muda o que o agente precisa saber sempre: `AGENTS.md`/kernels atualizados; entregas registram UMA entrada curta em `docs/CHANGELOG-AGENTS.md` (nunca no AGENTS.md)
|
||||
|
||||
## Notas para review
|
||||
|
||||
<!-- Riscos, decisões, o que ficou de foro (registrar como Issue follow-up). -->
|
||||
1192
AGENTS.md
1192
AGENTS.md
File diff suppressed because one or more lines are too long
73
docs/AGENT-OPS.md
Normal file
73
docs/AGENT-OPS.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# AGENT-OPS — operação do paradigma de agentes paralelos
|
||||
|
||||
Uma página. Norte: simplicidade (só GitHub + Cursor), agente para no merge a `stage`, `main`/prod só via promote humano.
|
||||
|
||||
## Ambientes de dados (test ladder — nunca misturar)
|
||||
|
||||
| Ambiente | Conteúdo | Quem usa |
|
||||
| --- | --- | --- |
|
||||
| **Mínimo** (`teqo_test` local / service CI) | schema migrado + `pnpm db:seed:minimal` (sintético, sem PII) | agentes, Cursor Cloud, CI de PR |
|
||||
| **Stage** (Neon branch `stage`, clone de prod) | snapshot 100% de prod (PII!) | só CI `ci-stage.yml` + humanos em smoke controlado |
|
||||
| **Prod** (Neon prod) | real | deploy Vercel a partir de `main` apenas |
|
||||
|
||||
Agentes **nunca** recebem `DATABASE_URL` de stage/prod e nunca setam `ALLOW_REMOTE_DB`. O escape `ALLOW_STAGE_TEST_DB` (`tests/helpers/assertTestDatabase.ts`) só existe para o workflow `ci-stage.yml`.
|
||||
|
||||
## Fluxo
|
||||
|
||||
```text
|
||||
claim → feature branch → PR --base stage → CI PR green → auto-merge em stage
|
||||
stage → CI stage green → (humano) pnpm agent:promote --i-am-human → main → Vercel prod
|
||||
```
|
||||
|
||||
- **Agente faz sozinho:** `pnpm agent:claim` (pega a próxima Issue `ready` desbloqueada por `prio:P0..P3`, lock otimista ready→in-progress) → implementa → fast gate → `gh pr create --base stage` com `Closes #N` → **PARA**. PR para `stage` mergeia sozinho quando o CI fica verde (auto-merge nativo + protection em `stage`).
|
||||
- **Só humano:** `pnpm agent:promote --i-am-human` (PR `stage→main` + merge com CI stage + ci-pr green; recusa se `main` divergiu de `stage` — merge main em stage antes), `pnpm db:refresh:stage` (refresh semanal do snapshot), editar envs Vercel/Neon, rodar `pnpm build` contra qualquer banco remoto.
|
||||
- Se `main` divergir de `stage` (hotfix): merge/rebase de `main` em `stage` + CI stage green de novo, só depois promote.
|
||||
|
||||
## Comandos
|
||||
|
||||
| Comando | Faz |
|
||||
| --- | --- |
|
||||
| `pnpm agent:claim [-- --dry-run]` | Fila ready+unblocked por prio → `in-progress` + brief no stdout. Deps sem Issue = itens entregues do roadmap (satisfeitas, avisadas no brief) |
|
||||
| `pnpm agent:register -- --id X --title T [--prio P1] [--depends A,B] [--plan docs/plans/x.md]` | Cria Issue (spec + labels) |
|
||||
| `pnpm agent:prioritize -- <issue> <P0..P3>` | Troca a label `prio:*` |
|
||||
| `pnpm agent:file-miss -- --title ...` | Issue `kind:agent-miss` → harvest em guardrail (`docs/GUARDRAILS.md`) |
|
||||
| `pnpm agent:promote -- --i-am-human` | **Humano:** PR `stage→main` + merge se CI green |
|
||||
| `pnpm db:seed:minimal` | DB mínimo sintético (contrato: [`scripts/lib/seed-minimal-manifest.mjs`](../scripts/lib/seed-minimal-manifest.mjs), pin `tests/unit/seedMinimalManifest.unit.spec.ts`) |
|
||||
| `pnpm db:refresh:stage` | **Humano:** nova Neon branch `stage` de prod + swap do secret `STAGE_DATABASE_URL` (requer `NEON_API_KEY`) |
|
||||
|
||||
Labels: estado `ready|in-progress|blocked|done|in-prod`, `prio:P0..P3`, `kind:feature|defect|chore|agent-miss`, `needs:migration|consent`, `requirements-changed`. Issues carregam frontmatter `id/depends/serializes/priority` no body.
|
||||
|
||||
## Contrato de PR (toda entrega)
|
||||
|
||||
1. Se toca schema (migration, collection, Consent key, dado de boot) → **atualizar `db:seed:minimal` no mesmo PR** (label `needs:migration`). CI PR falha se `migrate + seed:minimal + test:int` não passam.
|
||||
2. ≤1 PR aberto tocando `src/migrations/` | `payload-types.ts` (job `migration-lock`).
|
||||
3. `docs/plans/<slug>.md` novo só para Issue nova — nunca recriar plans históricos no merge.
|
||||
|
||||
## CI por alvo
|
||||
|
||||
| Workflow | Trigger | Banco | Passos |
|
||||
| --- | --- | --- | --- |
|
||||
| `ci-pr.yml` | PR → `stage`/`main` | service Postgres 17 (mínimo) | lint, format, typecheck, knip, cycles, unit → migrate → **seed:minimal** → int → **build** + `migration-lock` |
|
||||
| `ci-stage.yml` | push em `stage` | `STAGE_DATABASE_URL` (Environment `stage`) | **só** `migrate` + `test:int` — **NUNCA `pnpm build`** (build migra o banco que vê), nunca seed:minimal |
|
||||
| `ci.yml` | push em `main` | service Postgres | gate pós-promote |
|
||||
| E2E | fora do caminho crítico (nightly/label futura) | — | não bloqueia autonomia |
|
||||
|
||||
Fast gate local do agente antes do push: `pnpm lint && pnpm exec tsc --noEmit && pnpm test:unit` (+ `pnpm format:check` e `pnpm check:cycles` antes de commitar; int/build = CI).
|
||||
|
||||
## Stage DB — runbook de refresh (semanal, humano)
|
||||
|
||||
1. `export NEON_API_KEY=…` (console.neon.tech → API keys; projeto `jorgesolla` / `lively-math-34249863`).
|
||||
2. `pnpm db:refresh:stage` — deleta a branch `stage` velha, cria nova do snapshot de prod, faz swap do secret `STAGE_DATABASE_URL` no Environment `stage`. `--dry-run` inspeciona.
|
||||
3. Próximo `ci-stage` já usa o snapshot novo. Preview Vercel da branch `stage` (`jorgesolla-git-stage-solla.vercel.app`) aponta para o mesmo banco via envs `Preview (stage)` — **atenção**: o endpoint muda a cada refresh; rode também `vercel env add DATABASE_URL preview stage` com a URL nova (o script imprime a URL mascarada; pegue a completa no console Neon ou rode `vercel env pull`).
|
||||
|
||||
## Cursor Cloud
|
||||
|
||||
`.cursor/environment.json` instala deps, sobe Postgres (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.
|
||||
|
||||
## Guardrails progressivos
|
||||
|
||||
`pnpm agent:file-miss` → Issue `kind:agent-miss` → harvest periódico → guardrail programático (spec `codebaseConventions`, ESLint, check CI) → ledger `docs/GUARDRAILS.md`. Padrão já fichado: "migration sem atualizar seed:minimal".
|
||||
|
||||
## Leitura always-on (ordem)
|
||||
|
||||
`AGENTS.md` (fatiado 2026-07-30) → `.cursor/rules/codebase-map.mdc` → `.cursor/rules/engineering-standards.mdc` → esta página → kernels [`PRODUCT.md`](../PRODUCT.md) / [`DESIGN.md`](../DESIGN.md) / [`CUSTOMER.md`](CUSTOMER.md) (kernel no topo). Histórico: [`CHANGELOG-AGENTS.md`](CHANGELOG-AGENTS.md). Referência Payload sob demanda: [`PAYLOAD-REFERENCE.md`](PAYLOAD-REFERENCE.md).
|
||||
105
docs/CHANGELOG-AGENTS.md
Normal file
105
docs/CHANGELOG-AGENTS.md
Normal file
File diff suppressed because one or more lines are too long
1102
docs/PAYLOAD-REFERENCE.md
Normal file
1102
docs/PAYLOAD-REFERENCE.md
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue