feat: add dev workflows as agent skills
Four SKILL.md-based workflows for agent-driven development: frontend/UI, backend/API, architecture, and security code review. Each workflow defines phases with verification steps, acceptance criteria and hard rules so agents deliver work that can be checked instead of asserted. The security review consults live sources (OSV.dev, GitHub Advisory, NVD) because model CVE knowledge is frozen at training cutoff. Includes a QA harness (qa/) that scores workflows on 30+ criteria, a non-regression gate, and meta-tests that corrupt the harness to prove it detects regressions.
This commit is contained in:
commit
722c544b72
13 files changed
+2193
No files matched your search
@@ -0,0 +1,4 @@
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.venv/
|
||||
node_modules/
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Evandro Fonseca Junior
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,79 @@
|
||||
# dev-workflows
|
||||
|
||||
Workflows de desenvolvimento que uso no dia a dia, codificados como skills
|
||||
de agente (formato SKILL.md). Cada um define um processo com fases, passos
|
||||
de verificação, comandos reais e regras duras - daí sai trabalho consistente
|
||||
em vez de "confia em mim".
|
||||
|
||||
Em geral mexo com Node/TypeScript, NestJS, PostgreSQL, Docker e front em
|
||||
React. Os workflows refletem isso, mas as fases são neutras o suficiente
|
||||
pra servir em outros stacks.
|
||||
|
||||
## O que tem aqui
|
||||
|
||||
| Workflow | Para quê |
|
||||
|---|---|
|
||||
| [wf-frontend](workflows/wf-frontend.md) | UI/design/PDF: direção visual antes de codar, anti-AI-slop, perf React, QA visual |
|
||||
| [wf-backend](workflows/wf-backend.md) | API/backend: contrato antes do handler, defaults seguros, auditoria OWASP, testes |
|
||||
| [wf-architecture](workflows/wf-architecture.md) | Arquitetura: requisitos mensuráveis, C4, ADR, threat model, revisão |
|
||||
| [wf-security-review](workflows/wf-security-review.md) | Code review de segurança front+back: CVE conhecidas + consulta de novas (OSV/NVD/GH Advisory) |
|
||||
|
||||
Cada SKILL.md funciona no Hermes Agent (e em qualquer agente que leia o
|
||||
formato): a descrição no frontmatter é o gatilho - quando o contexto bate,
|
||||
o fluxo carrega sozinho.
|
||||
|
||||
## Por que fases com verificação
|
||||
|
||||
O problema que isso resolve: agente "acha que fez" mas não tem como provar.
|
||||
Cada fase termina com passos de verificação (rodar build, rodar teste,
|
||||
consultar OSV.dev) e os workflows têm critérios de aceite. Sem evidência,
|
||||
não entrega.
|
||||
|
||||
Tem um harness de qualidade no `qa/` que mede isso de forma objetiva:
|
||||
|
||||
```bash
|
||||
cd qa
|
||||
python3 wf_quality_harness.py # score por workflow (30+ critérios)
|
||||
python3 test_quality.py # gates: não-regressão, skills válidas, verificação por fase
|
||||
python3 test_tests.py # teste dos testes: muta e confirma que o harness detecta
|
||||
```
|
||||
|
||||
O `test_tests.py` é o diferencial: ele corrompe o harness e os workflows de
|
||||
propósito e confirma que o score cai. Se o score não muda com a corrupção,
|
||||
o detetor é inútil. Isso está sempre verde.
|
||||
|
||||
## Segurança: não confiar no cutoff
|
||||
|
||||
A skill de segurança tem uma regra dura: o modelo conhece CVE só até o
|
||||
cutoff de treino. Então "não tem vulnerabilidade" nunca é resposta de
|
||||
memória - o workflow consulta fontes vivas:
|
||||
|
||||
- OSV.dev via safedeps (CVE em tempo real por `package@version`)
|
||||
- GitHub Advisory Database (via gh api)
|
||||
- NVD
|
||||
|
||||
Leva 3 skills de segurança de fontes primárias (OWASP, OSV.dev, UnitOne
|
||||
SecuritySkills) e as usa como pilares do review.
|
||||
|
||||
## Instalação
|
||||
|
||||
Copie os arquivos de `workflows/` para o diretório de skills do seu agente:
|
||||
|
||||
```bash
|
||||
# Hermes Agent
|
||||
cp workflows/*.md ~/.hermes/skills/software-development/
|
||||
|
||||
# Claude Code / agentes com skills dir
|
||||
mkdir -p ~/.claude/skills && cp workflows/*.md ~/.claude/skills/
|
||||
```
|
||||
|
||||
Para o `wf-security-review`, instale também a skill safedeps e o script
|
||||
`check_deps.py` (veja `docs/SKILLS.md`) - é o que consulta o OSV.dev.
|
||||
|
||||
## Docs
|
||||
|
||||
- [docs/SKILLS.md](docs/SKILLS.md) - lista completa das skills usadas,
|
||||
origem de cada uma e como instalá-las
|
||||
- [qa/](qa/) - harness de qualidade + gates + teste dos testes
|
||||
|
||||
Licença: MIT.
|
||||
@@ -0,0 +1,86 @@
|
||||
# Skills usadas e de onde vieram
|
||||
|
||||
Este é o inventário do que os workflows carregam. Cada skill é um diretório
|
||||
com um `SKILL.md`; para o Hermes Agent, vão em `~/.hermes/skills/`.
|
||||
|
||||
## Pilar de segurança (wf-security-review)
|
||||
|
||||
| Skill | Origem | O que faz |
|
||||
|---|---|---|
|
||||
| `safedeps` | [Jeneidi/safedeps](https://github.com/Jeneidi/safedeps) | Consulta OSV.dev em tempo real; CVE por `package@version` com severidade e versão de fix. Inclui o script `check_deps.py` |
|
||||
| `sca-audit` | [OWASP/secure-agent-playbook](https://github.com/OWASP/secure-agent-playbook) | SCA de dependências com análise de alcance (reachability), mapeamento CWE |
|
||||
| `code-review-security` | OWASP/secure-agent-playbook | Code review de segurança sistemático mapeado a OWASP Top 10 + ASVS |
|
||||
| `secrets-scan` | OWASP/secure-agent-playbook | Detecta credenciais/API keys no código e no git history |
|
||||
| `api-security-review` | OWASP/secure-agent-playbook | Revisão de API contra OWASP API Security Top 10 |
|
||||
| `web-security-review` | OWASP/secure-agent-playbook | Web app contra OWASP Top 10 (2021) |
|
||||
| `cve-triage` | [UnitOneAI/SecuritySkills](https://github.com/UnitOneAI/SecuritySkills) | Prioriza CVE por CVSS 4.0 / EPSS / CISA KEV |
|
||||
| `patch-prioritization` | UnitOneAI/SecuritySkills | Decide a ordem de remediação |
|
||||
| `dependency-scanning` | UnitOneAI/SecuritySkills | Varredura de dependências |
|
||||
|
||||
## Frontend / UI / design (wf-frontend)
|
||||
|
||||
| Skill | Origem | O que faz |
|
||||
|---|---|---|
|
||||
| `frontend-design` | [anthropics/skills](https://github.com/anthropics/skills) | Direção visual, tipografia, fugir do genérico |
|
||||
| `web-design` | [KAOPU-XiaoPu/web-design](https://github.com/KAOPU-XiaoPu/web-design) | Estética web coesa |
|
||||
| `vercel-react-best-practices` | [vercel-labs/agent-skills](https://github.com/vercel-labs/agent-skills) | 40+ regras de perf React/Next |
|
||||
| `vercel-composition-patterns` | vercel-labs/agent-skills | Compound components, composição |
|
||||
| `animate` | [emilkowalski/skill](https://github.com/emilkowalski/skill) | Motion com propósito |
|
||||
| `anti-ai-slop` | local | Detecta padrão visual "gerado por IA" |
|
||||
| `avoid-ai-writing` | [conorbronsdon/avoid-ai-writing](https://github.com/conorbronsdon/avoid-ai-writing) | Remove AI-isms de texto/microcopy |
|
||||
|
||||
## Backend / API (wf-backend)
|
||||
|
||||
| Skill | Origem | O que faz |
|
||||
|---|---|---|
|
||||
| `secure-coding` | [v6x/secure-coding-skill](https://github.com/securityreviewai/secure-coding-skill) | Padrões de codificação segura em 15 stacks |
|
||||
| `bola-detector` | [apisec-inc/apisec-skills](https://github.com/apisec-inc/apisec-skills) | Detecta object-level authorization (OWASP API1) |
|
||||
| `auth-rbac-scaffold` | apisec-inc/apisec-skills | Auth/RBAC (OWASP API2/API5) |
|
||||
| `injection-checker` | apisec-inc/apisec-skills | Injection SQL/ORM/shell (OWASP API8) |
|
||||
| `openapi-hardener` | apisec-inc/apisec-skills | Saneia schemas OpenAPI/Zod (OWASP API3) |
|
||||
| `api-security-review` | apisec-inc/apisec-skills | Review completo OWASP API Top 10 |
|
||||
| `security-test-generator` | apisec-inc/apisec-skills | Gera testes de segurança |
|
||||
|
||||
## Arquitetura (wf-architecture)
|
||||
|
||||
| Skill | Origem | O que faz |
|
||||
|---|---|---|
|
||||
| `system-design` | [Kotivskyi/architecture-governance-skills](https://github.com/Kotivskyi/architecture-governance-skills) | Framework HelloInterview de system design |
|
||||
| `c4-architecture` | Kotivskyi/architecture-governance-skills | Diagramas C4 (Mermaid/Structurizr) |
|
||||
| `isaqb-architecture-governance` | Kotivskyi/architecture-governance-skills | arc42 + ADR |
|
||||
| `secure-architecture-governance` | Kotivskyi/architecture-governance-skills | Threat model STRIDE+CIA, S-ADR |
|
||||
|
||||
## Caça de bugs (todas)
|
||||
|
||||
| Skill | Origem | O que faz |
|
||||
|---|---|---|
|
||||
| `hermaguard` | [Sahil-SS9/hermaguard](https://github.com/Sahil-SS9/hermaguard) | Review adversarial: pre-scan + 3 agentes (edge cases, ataque, blast radius) |
|
||||
|
||||
## Como instalar as skills de origem
|
||||
|
||||
A maioria instala via `npx skills` (formato agentskills.io):
|
||||
|
||||
```bash
|
||||
npx skills add anthropics/skills --skill frontend-design
|
||||
npx skills add vercel-labs/agent-skills --skill vercel-react-best-practices
|
||||
npx skills add conorbronsdon/avoid-ai-writing
|
||||
```
|
||||
|
||||
As de segurança do OWASP e UnitOne instalam clonando e copiando o diretório
|
||||
da skill:
|
||||
|
||||
```bash
|
||||
git clone --depth 1 https://github.com/OWASP/secure-agent-playbook.git
|
||||
cp -r secure-agent-playbook/plugins/code-security-skills/skills/{sca-audit,secrets-scan} ~/.hermes/skills/
|
||||
|
||||
git clone --depth 1 https://github.com/UnitOneAI/SecuritySkills.git
|
||||
cp -r SecuritySkills/skills/vuln-management/{cve-triage,patch-prioritization} ~/.hermes/skills/
|
||||
```
|
||||
|
||||
O safedeps precisa do script junto da skill:
|
||||
|
||||
```bash
|
||||
git clone --depth 1 https://github.com/Jeneidi/safedeps.git
|
||||
cp -r safedeps/skills/safedeps ~/.hermes/skills/safedeps
|
||||
cp safedeps/check_deps.py ~/.hermes/skills/safedeps/
|
||||
```
|
||||
@@ -0,0 +1,236 @@
|
||||
{
|
||||
"workflows": [
|
||||
{
|
||||
"name": "wf-frontend",
|
||||
"score": 385.5,
|
||||
"skills_referenciadas": [
|
||||
"animate",
|
||||
"anti-ai-slop",
|
||||
"avoid-ai-writing",
|
||||
"claude-design",
|
||||
"design-md",
|
||||
"frontend-award-tier",
|
||||
"frontend-design",
|
||||
"hermaguard",
|
||||
"html-css-print-engineer",
|
||||
"pdf-generator",
|
||||
"pdf-render-qa",
|
||||
"pdf-visual-designer",
|
||||
"popular-web-designs",
|
||||
"professional-pdf-director",
|
||||
"sketch",
|
||||
"vercel-composition-patterns",
|
||||
"vercel-react-best-practices",
|
||||
"web-design"
|
||||
],
|
||||
"criteria": {
|
||||
"frontmatter": 5,
|
||||
"when_to_use": 8,
|
||||
"num_fases": 6,
|
||||
"regras_duras": 10,
|
||||
"n_regras": 9,
|
||||
"fase1": 16,
|
||||
"fase2": 16,
|
||||
"fase3": 16,
|
||||
"cobertura_fases": 20,
|
||||
"skills_validas": 15,
|
||||
"fase_rotulos": 6,
|
||||
"fase_acao": 6,
|
||||
"fase_revisao": 6,
|
||||
"anti_slop": 4.5,
|
||||
"cmd_blocos": 8,
|
||||
"cmd_reais": 5,
|
||||
"sec_criterios": 8,
|
||||
"sec_verificar": 6,
|
||||
"sec_nao_regressao": 6,
|
||||
"tamanho": 8,
|
||||
"testes_referidos": 5,
|
||||
"passos_total": 30,
|
||||
"verificacao_total": 24,
|
||||
"comandos_reais": 20,
|
||||
"profundidade": 10,
|
||||
"por_fase_verif": 18,
|
||||
"por_fase_cmd": 18,
|
||||
"por_fase_antip": 12,
|
||||
"por_fase_aceite": 12,
|
||||
"exemplos": 10,
|
||||
"exemplos_count": 12,
|
||||
"artefatos": 14,
|
||||
"fluxo": 8,
|
||||
"entradas_saidas": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wf-backend",
|
||||
"score": 424.0,
|
||||
"skills_referenciadas": [
|
||||
"api-security-review",
|
||||
"auth-rbac-scaffold",
|
||||
"bola-detector",
|
||||
"dependency-cve-audit",
|
||||
"fastapi-uvicorn-wiring",
|
||||
"hermaguard",
|
||||
"injection-checker",
|
||||
"network-audit",
|
||||
"openapi-hardener",
|
||||
"rest-graphql-debug",
|
||||
"secure-coding",
|
||||
"security-best-practices",
|
||||
"security-test-generator",
|
||||
"software-code-quality",
|
||||
"test-driven-development"
|
||||
],
|
||||
"criteria": {
|
||||
"frontmatter": 5,
|
||||
"when_to_use": 8,
|
||||
"num_fases": 8,
|
||||
"regras_duras": 10,
|
||||
"n_regras": 10,
|
||||
"fase1": 15,
|
||||
"fase2": 15,
|
||||
"fase3": 16,
|
||||
"fase4": 16,
|
||||
"cobertura_fases": 20,
|
||||
"skills_validas": 15,
|
||||
"fase_rotulos": 6,
|
||||
"fase_acao": 6,
|
||||
"fase_revisao": 6,
|
||||
"anti_slop": 5.0,
|
||||
"cmd_blocos": 8,
|
||||
"cmd_reais": 5,
|
||||
"sec_criterios": 8,
|
||||
"sec_verificar": 6,
|
||||
"sec_nao_regressao": 6,
|
||||
"tamanho": 8,
|
||||
"testes_referidos": 5,
|
||||
"passos_total": 30,
|
||||
"verificacao_total": 24,
|
||||
"comandos_reais": 20,
|
||||
"profundidade": 13,
|
||||
"por_fase_verif": 22,
|
||||
"por_fase_cmd": 24,
|
||||
"por_fase_antip": 16,
|
||||
"por_fase_aceite": 16,
|
||||
"exemplos": 10,
|
||||
"exemplos_count": 12,
|
||||
"artefatos": 14,
|
||||
"fluxo": 8,
|
||||
"entradas_saidas": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wf-architecture",
|
||||
"score": 413.7,
|
||||
"skills_referenciadas": [
|
||||
"architecture-diagram",
|
||||
"avoid-ai-writing",
|
||||
"brainstorming",
|
||||
"c4-architecture",
|
||||
"excalidraw",
|
||||
"hermaguard",
|
||||
"isaqb-architecture-governance",
|
||||
"secure-architecture-governance",
|
||||
"security-threat-model",
|
||||
"system-design",
|
||||
"writing-plans"
|
||||
],
|
||||
"criteria": {
|
||||
"frontmatter": 5,
|
||||
"when_to_use": 8,
|
||||
"num_fases": 8,
|
||||
"regras_duras": 10,
|
||||
"n_regras": 10,
|
||||
"fase1": 15,
|
||||
"fase2": 16,
|
||||
"fase3": 14,
|
||||
"fase4": 16,
|
||||
"cobertura_fases": 20,
|
||||
"skills_validas": 11,
|
||||
"fase_rotulos": 6,
|
||||
"fase_acao": 0,
|
||||
"fase_revisao": 6,
|
||||
"anti_slop": 4.7,
|
||||
"cmd_blocos": 8,
|
||||
"cmd_reais": 5,
|
||||
"sec_criterios": 8,
|
||||
"sec_verificar": 6,
|
||||
"sec_nao_regressao": 6,
|
||||
"tamanho": 8,
|
||||
"testes_referidos": 5,
|
||||
"passos_total": 30,
|
||||
"verificacao_total": 24,
|
||||
"comandos_reais": 20,
|
||||
"profundidade": 13,
|
||||
"por_fase_verif": 24,
|
||||
"por_fase_cmd": 24,
|
||||
"por_fase_antip": 16,
|
||||
"por_fase_aceite": 15,
|
||||
"exemplos": 10,
|
||||
"exemplos_count": 12,
|
||||
"artefatos": 14,
|
||||
"fluxo": 8,
|
||||
"entradas_saidas": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wf-security-review",
|
||||
"score": 390.0,
|
||||
"skills_referenciadas": [
|
||||
"api-security-review",
|
||||
"auth-rbac-scaffold",
|
||||
"bola-detector",
|
||||
"code-review-security",
|
||||
"cve-triage",
|
||||
"dependency-cve-audit",
|
||||
"hermaguard",
|
||||
"injection-checker",
|
||||
"patch-prioritization",
|
||||
"safedeps",
|
||||
"sca-audit",
|
||||
"secrets-scan",
|
||||
"security-threat-model",
|
||||
"web-security-review"
|
||||
],
|
||||
"criteria": {
|
||||
"frontmatter": 5,
|
||||
"when_to_use": 8,
|
||||
"num_fases": 10,
|
||||
"regras_duras": 10,
|
||||
"n_regras": 8,
|
||||
"fase1": 15,
|
||||
"fase2": 16,
|
||||
"fase3": 13,
|
||||
"fase4": 15,
|
||||
"fase5": 15,
|
||||
"cobertura_fases": 20,
|
||||
"skills_validas": 14,
|
||||
"fase_rotulos": 6,
|
||||
"fase_acao": 0,
|
||||
"fase_revisao": 6,
|
||||
"anti_slop": 5.0,
|
||||
"cmd_blocos": 8,
|
||||
"cmd_reais": 5,
|
||||
"sec_criterios": 0,
|
||||
"sec_verificar": 6,
|
||||
"sec_nao_regressao": 6,
|
||||
"tamanho": 8,
|
||||
"testes_referidos": 5,
|
||||
"passos_total": 30,
|
||||
"verificacao_total": 24,
|
||||
"comandos_reais": 16,
|
||||
"profundidade": 15,
|
||||
"por_fase_verif": 23,
|
||||
"por_fase_cmd": 19,
|
||||
"por_fase_antip": 12,
|
||||
"por_fase_aceite": 5,
|
||||
"exemplos": 0,
|
||||
"exemplos_count": 12,
|
||||
"artefatos": 14,
|
||||
"fluxo": 8,
|
||||
"entradas_saidas": 8
|
||||
}
|
||||
}
|
||||
],
|
||||
"total": 1613.2,
|
||||
"max": 400
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
{
|
||||
"workflows": [
|
||||
{
|
||||
"name": "wf-frontend",
|
||||
"score": 385.5,
|
||||
"skills_referenciadas": [
|
||||
"animate",
|
||||
"anti-ai-slop",
|
||||
"avoid-ai-writing",
|
||||
"claude-design",
|
||||
"design-md",
|
||||
"frontend-award-tier",
|
||||
"frontend-design",
|
||||
"hermaguard",
|
||||
"html-css-print-engineer",
|
||||
"pdf-generator",
|
||||
"pdf-render-qa",
|
||||
"pdf-visual-designer",
|
||||
"popular-web-designs",
|
||||
"professional-pdf-director",
|
||||
"sketch",
|
||||
"vercel-composition-patterns",
|
||||
"vercel-react-best-practices",
|
||||
"web-design"
|
||||
],
|
||||
"criteria": {
|
||||
"frontmatter": 5,
|
||||
"when_to_use": 8,
|
||||
"num_fases": 6,
|
||||
"regras_duras": 10,
|
||||
"n_regras": 9,
|
||||
"fase1": 16,
|
||||
"fase2": 16,
|
||||
"fase3": 16,
|
||||
"cobertura_fases": 20,
|
||||
"skills_validas": 15,
|
||||
"fase_rotulos": 6,
|
||||
"fase_acao": 6,
|
||||
"fase_revisao": 6,
|
||||
"anti_slop": 4.5,
|
||||
"cmd_blocos": 8,
|
||||
"cmd_reais": 5,
|
||||
"sec_criterios": 8,
|
||||
"sec_verificar": 6,
|
||||
"sec_nao_regressao": 6,
|
||||
"tamanho": 8,
|
||||
"testes_referidos": 5,
|
||||
"passos_total": 30,
|
||||
"verificacao_total": 24,
|
||||
"comandos_reais": 20,
|
||||
"profundidade": 10,
|
||||
"por_fase_verif": 18,
|
||||
"por_fase_cmd": 18,
|
||||
"por_fase_antip": 12,
|
||||
"por_fase_aceite": 12,
|
||||
"exemplos": 10,
|
||||
"exemplos_count": 12,
|
||||
"artefatos": 14,
|
||||
"fluxo": 8,
|
||||
"entradas_saidas": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wf-backend",
|
||||
"score": 424.0,
|
||||
"skills_referenciadas": [
|
||||
"api-security-review",
|
||||
"auth-rbac-scaffold",
|
||||
"bola-detector",
|
||||
"dependency-cve-audit",
|
||||
"fastapi-uvicorn-wiring",
|
||||
"hermaguard",
|
||||
"injection-checker",
|
||||
"network-audit",
|
||||
"openapi-hardener",
|
||||
"rest-graphql-debug",
|
||||
"secure-coding",
|
||||
"security-best-practices",
|
||||
"security-test-generator",
|
||||
"software-code-quality",
|
||||
"test-driven-development"
|
||||
],
|
||||
"criteria": {
|
||||
"frontmatter": 5,
|
||||
"when_to_use": 8,
|
||||
"num_fases": 8,
|
||||
"regras_duras": 10,
|
||||
"n_regras": 10,
|
||||
"fase1": 15,
|
||||
"fase2": 15,
|
||||
"fase3": 16,
|
||||
"fase4": 16,
|
||||
"cobertura_fases": 20,
|
||||
"skills_validas": 15,
|
||||
"fase_rotulos": 6,
|
||||
"fase_acao": 6,
|
||||
"fase_revisao": 6,
|
||||
"anti_slop": 5.0,
|
||||
"cmd_blocos": 8,
|
||||
"cmd_reais": 5,
|
||||
"sec_criterios": 8,
|
||||
"sec_verificar": 6,
|
||||
"sec_nao_regressao": 6,
|
||||
"tamanho": 8,
|
||||
"testes_referidos": 5,
|
||||
"passos_total": 30,
|
||||
"verificacao_total": 24,
|
||||
"comandos_reais": 20,
|
||||
"profundidade": 13,
|
||||
"por_fase_verif": 22,
|
||||
"por_fase_cmd": 24,
|
||||
"por_fase_antip": 16,
|
||||
"por_fase_aceite": 16,
|
||||
"exemplos": 10,
|
||||
"exemplos_count": 12,
|
||||
"artefatos": 14,
|
||||
"fluxo": 8,
|
||||
"entradas_saidas": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wf-architecture",
|
||||
"score": 413.7,
|
||||
"skills_referenciadas": [
|
||||
"architecture-diagram",
|
||||
"avoid-ai-writing",
|
||||
"brainstorming",
|
||||
"c4-architecture",
|
||||
"excalidraw",
|
||||
"hermaguard",
|
||||
"isaqb-architecture-governance",
|
||||
"secure-architecture-governance",
|
||||
"security-threat-model",
|
||||
"system-design",
|
||||
"writing-plans"
|
||||
],
|
||||
"criteria": {
|
||||
"frontmatter": 5,
|
||||
"when_to_use": 8,
|
||||
"num_fases": 8,
|
||||
"regras_duras": 10,
|
||||
"n_regras": 10,
|
||||
"fase1": 15,
|
||||
"fase2": 16,
|
||||
"fase3": 14,
|
||||
"fase4": 16,
|
||||
"cobertura_fases": 20,
|
||||
"skills_validas": 11,
|
||||
"fase_rotulos": 6,
|
||||
"fase_acao": 0,
|
||||
"fase_revisao": 6,
|
||||
"anti_slop": 4.7,
|
||||
"cmd_blocos": 8,
|
||||
"cmd_reais": 5,
|
||||
"sec_criterios": 8,
|
||||
"sec_verificar": 6,
|
||||
"sec_nao_regressao": 6,
|
||||
"tamanho": 8,
|
||||
"testes_referidos": 5,
|
||||
"passos_total": 30,
|
||||
"verificacao_total": 24,
|
||||
"comandos_reais": 20,
|
||||
"profundidade": 13,
|
||||
"por_fase_verif": 24,
|
||||
"por_fase_cmd": 24,
|
||||
"por_fase_antip": 16,
|
||||
"por_fase_aceite": 15,
|
||||
"exemplos": 10,
|
||||
"exemplos_count": 12,
|
||||
"artefatos": 14,
|
||||
"fluxo": 8,
|
||||
"entradas_saidas": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "wf-security-review",
|
||||
"score": 390.0,
|
||||
"skills_referenciadas": [
|
||||
"api-security-review",
|
||||
"auth-rbac-scaffold",
|
||||
"bola-detector",
|
||||
"code-review-security",
|
||||
"cve-triage",
|
||||
"dependency-cve-audit",
|
||||
"hermaguard",
|
||||
"injection-checker",
|
||||
"patch-prioritization",
|
||||
"safedeps",
|
||||
"sca-audit",
|
||||
"secrets-scan",
|
||||
"security-threat-model",
|
||||
"web-security-review"
|
||||
],
|
||||
"criteria": {
|
||||
"frontmatter": 5,
|
||||
"when_to_use": 8,
|
||||
"num_fases": 10,
|
||||
"regras_duras": 10,
|
||||
"n_regras": 8,
|
||||
"fase1": 15,
|
||||
"fase2": 16,
|
||||
"fase3": 13,
|
||||
"fase4": 15,
|
||||
"fase5": 15,
|
||||
"cobertura_fases": 20,
|
||||
"skills_validas": 14,
|
||||
"fase_rotulos": 6,
|
||||
"fase_acao": 0,
|
||||
"fase_revisao": 6,
|
||||
"anti_slop": 5.0,
|
||||
"cmd_blocos": 8,
|
||||
"cmd_reais": 5,
|
||||
"sec_criterios": 0,
|
||||
"sec_verificar": 6,
|
||||
"sec_nao_regressao": 6,
|
||||
"tamanho": 8,
|
||||
"testes_referidos": 5,
|
||||
"passos_total": 30,
|
||||
"verificacao_total": 24,
|
||||
"comandos_reais": 16,
|
||||
"profundidade": 15,
|
||||
"por_fase_verif": 23,
|
||||
"por_fase_cmd": 19,
|
||||
"por_fase_antip": 12,
|
||||
"por_fase_aceite": 5,
|
||||
"exemplos": 0,
|
||||
"exemplos_count": 12,
|
||||
"artefatos": 14,
|
||||
"fluxo": 8,
|
||||
"entradas_saidas": 8
|
||||
}
|
||||
}
|
||||
],
|
||||
"total": 1613.2,
|
||||
"max": 400
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
test_quality.py — testes validados + aprovados (gate de qualidade não-regressivo).
|
||||
|
||||
Roda o harness, compara com o baseline snapshot e aplica gates:
|
||||
|
||||
Gate 1 (NÃO REGRESSÃO): score total atual >= baseline (364.1). Se caiu, exit 1.
|
||||
Gate 2 (MELHORIA ≥2×): score total atual >= 2 * baseline (728.2). Meta do usuário.
|
||||
Gate 3 (POR WORKFLOW): cada um dos 3 workflows >= 2 * seu baseline individual.
|
||||
Gate 4 (SKILLS): nenhuma skill referenciada faltando (harness sem sem_match).
|
||||
Gate 5 (VERIFICAÇÃO POR FASE): toda fase tem >=3 verbos de verificação.
|
||||
|
||||
Uso: python3 test_quality.py -> exit 0 se G1,G3,G4,G5 ok (evidência)
|
||||
python3 test_quality.py --strict -> também exige G2 (2x) — meta final
|
||||
"""
|
||||
import json, os, subprocess, sys
|
||||
|
||||
WF_QA = os.path.dirname(os.path.abspath(__file__))
|
||||
HARNESS = os.path.join(WF_QA, "wf_quality_harness.py")
|
||||
SNAPSHOT = os.path.join(WF_QA, "snapshots", "baseline-final.json")
|
||||
|
||||
def run_harness():
|
||||
r = subprocess.run([sys.executable, HARNESS, "--json"], capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
return None, r.stderr
|
||||
return json.loads(r.stdout), None
|
||||
|
||||
def main():
|
||||
strict = "--strict" in sys.argv
|
||||
base = json.load(open(SNAPSHOT))
|
||||
base_total = base["total"]
|
||||
base_per = {w["name"]: w.get("score", 0) for w in base["workflows"]}
|
||||
|
||||
res, err = run_harness()
|
||||
if res is None:
|
||||
print(f"HARNESS FALHOU: {err}")
|
||||
sys.exit(1)
|
||||
cur_total = res["total"]
|
||||
cur_per = {w["name"]: w.get("score", 0) for w in res["workflows"]}
|
||||
sem_match = {w["name"]: w.get("skills_sem_match", []) for w in res["workflows"]}
|
||||
fases_vazias = {w["name"]: w.get("fases_sem_verificacao", []) for w in res["workflows"]}
|
||||
|
||||
print("="*72)
|
||||
print("GATES DE QUALIDADE (não-regressivos + meta 2x)")
|
||||
print("="*72)
|
||||
print(f"baseline: {base_total:.1f} | atual: {cur_total:.1f} | meta(2x): {2*base_total:.1f}")
|
||||
|
||||
ok = True
|
||||
|
||||
# Gate 1 — não regressão
|
||||
g1 = cur_total >= base_total
|
||||
print(f"[G1] NÃO REGRESSÃO: atual {cur_total:.1f} >= baseline {base_total:.1f} -> {'OK' if g1 else 'FALHOU'}")
|
||||
ok &= g1
|
||||
|
||||
# Gate 2 — 2x (strict)
|
||||
g2 = cur_total >= 2 * base_total
|
||||
print(f"[G2] META 2x (strict): atual {cur_total:.1f} >= {2*base_total:.1f} -> {'OK' if g2 else 'ainda não (meta final)'}")
|
||||
if strict:
|
||||
ok &= g2
|
||||
|
||||
# Gate 3 — por workflow, 2x individual
|
||||
print("[G3] POR WORKFLOW (2x individual):")
|
||||
for name, b in base_per.items():
|
||||
cur = cur_per.get(name, 0)
|
||||
g3i = cur >= 2 * max(b, 0.1)
|
||||
print(f" {name:18} base={b:6.1f} atual={cur:6.1f} 2x={2*max(b,0.1):6.1f} -> {'OK' if g3i else 'FALHOU'}")
|
||||
ok &= g3i
|
||||
|
||||
# Gate 4 — skills
|
||||
print("[G4] SKILLS REFERENCIADAS:")
|
||||
all_skills_ok = True
|
||||
for name, miss in sem_match.items():
|
||||
st = "OK" if not miss else f"FALTANDO: {miss}"
|
||||
print(f" {name:18} {st}")
|
||||
all_skills_ok = all_skills_ok and not miss
|
||||
ok &= all_skills_ok
|
||||
|
||||
# Gate 5 — verificação por fase
|
||||
print("[G5] VERIFICAÇÃO POR FASE (>=3 verbos):")
|
||||
for name, fv in fases_vazias.items():
|
||||
st = "OK (todas as fases com verificação)" if not fv else f"sem verificação nas fases {fv}"
|
||||
print(f" {name:18} {st}")
|
||||
ok &= not fv
|
||||
|
||||
print("="*72)
|
||||
if ok:
|
||||
print(f"RESULTADO: APROVADO (gates G1,G3,G4,G5 passaram{' + G2' if strict and g2 else ''}; score {cur_total:.1f})")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print(f"RESULTADO: REPROVADO — gates abaixo falharam. Score {cur_total:.1f}. Rodar refinamento de novo.")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
test_tests.py — 'teste dos testes' (meta-testes) do wf_quality_harness.
|
||||
|
||||
Prova que o harness REALMENTE mede qualidade:
|
||||
1. Baseline registrado em snapshots/baseline-364.json (score 364.1 total).
|
||||
2. Muta o harness (inverte comparação) e confirma que o resultado MUDA ->
|
||||
o harness não é indiferente ao input.
|
||||
3. Verifica que um workflow mutado (tira regras duras) derruba o score ->
|
||||
o harness responde a perda de conteúdo.
|
||||
4. Re-verifica o estado real: score atual >= baseline (não-regressão).
|
||||
|
||||
Exit 0 = testes dos testes OK e não-regressão verificada.
|
||||
Exit 1 = falhou (meta-teste ou regressão real).
|
||||
"""
|
||||
import json, os, shutil, subprocess, sys, tempfile
|
||||
|
||||
WF_QA = os.path.dirname(os.path.abspath(__file__))
|
||||
HARNESS = os.path.join(WF_QA, "wf_quality_harness.py")
|
||||
SNAPSHOT = os.path.join(WF_QA, "snapshots", "baseline-final.json")
|
||||
|
||||
def run_harness():
|
||||
r = subprocess.run([sys.executable, HARNESS, "--json"], capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
return None, r.stderr
|
||||
return json.loads(r.stdout), None
|
||||
|
||||
def main():
|
||||
fails = []
|
||||
baseline = json.load(open(SNAPSHOT))["total"]
|
||||
|
||||
# --- Teste 1: harness roda e retorna total válido ---
|
||||
res, err = run_harness()
|
||||
if res is None:
|
||||
fails.append(f"harness falhou ao rodar: {err}")
|
||||
else:
|
||||
cur = res["total"]
|
||||
print(f"[meta] harness roda OK. score atual={cur:.1f} baseline={baseline:.1f}")
|
||||
if not (baseline > 0 and cur > 0):
|
||||
fails.append("scores inválidos (<=0)")
|
||||
if cur < baseline:
|
||||
fails.append(f"REGRESSÃO REAL: atual {cur:.1f} < baseline {baseline:.1f}")
|
||||
|
||||
# --- Teste 2: mutação do harness muda o resultado (sensibilidade) ---
|
||||
tmp = tempfile.mkdtemp(prefix="wfqamut_")
|
||||
try:
|
||||
mutated = os.path.join(tmp, "wf_quality_harness_mut.py")
|
||||
src = open(HARNESS, encoding="utf-8").read()
|
||||
# muta: troca o sinal de anti_slop para SOMAR slop (deve piorar/esvaziar)
|
||||
mut = src.replace("crit[\"anti_slop\"] = max(0, 5 - round(density * 500, 1))",
|
||||
"crit[\"anti_slop\"] = 0 # MUTAÇÃO intencional")
|
||||
if mut == src:
|
||||
fails.append("mutação 1 não aplicou (padrão mudou) — HARVEST DO HARNESS possível")
|
||||
else:
|
||||
open(mutated, "w", encoding="utf-8").write(mut)
|
||||
r = subprocess.run([sys.executable, mutated, "--json"], capture_output=True, text=True)
|
||||
try:
|
||||
j = json.loads(r.stdout)
|
||||
if j["total"] >= res["total"]:
|
||||
fails.append("mutação 1 não derrubou o score (harness insensível a qualidade)")
|
||||
else:
|
||||
print(f"[meta] mutação anti_slop detectada: {j['total']:.1f} < {res['total']:.1f} OK")
|
||||
except Exception:
|
||||
fails.append("mutação 1: saída não-JSON após remoção do anti_slop")
|
||||
finally:
|
||||
shutil.rmtree(tmp, ignore_errors=True)
|
||||
|
||||
# --- Teste 3: workflow mutado (remove Regras duras) derruba score ---
|
||||
wk = os.path.join(os.path.dirname(WF_QA), "wf-frontend", "SKILL.md")
|
||||
if os.path.exists(wk):
|
||||
orig = open(wk, encoding="utf-8").read()
|
||||
ctx = tempfile.mkdtemp(prefix="wfqamutwf_")
|
||||
backup = os.path.join(ctx, "backup.md")
|
||||
shutil.copy(wk, backup)
|
||||
try:
|
||||
removed = orig.replace("## Regras duras", "## Regras_duras_mutadas")
|
||||
open(wk, "w", encoding="utf-8").write(removed)
|
||||
r2, _ = run_harness()
|
||||
if r2 is None or r2["total"] >= res["total"]:
|
||||
fails.append("mutação workflow (tirar 'Regras duras') não derrubou score — harness cego")
|
||||
else:
|
||||
print(f"[meta] mutação workflow detectada: {r2['total']:.1f} < {res['total']:.1f} OK")
|
||||
finally:
|
||||
shutil.copy(backup, wk)
|
||||
shutil.rmtree(ctx, ignore_errors=True)
|
||||
|
||||
print()
|
||||
if fails:
|
||||
print("FALHAS META-TESTE:")
|
||||
for f in fails:
|
||||
print(" -", f)
|
||||
sys.exit(1)
|
||||
print("META-TESTES OK: harness sensível, sem regressão real. Score atual >= baseline.")
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,247 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
wf_quality_harness.py — QA objetivo dos workflows wf-frontend/wf-backend/wf-architecture.
|
||||
|
||||
Mede qualidade por critérios EXTRAÍVEIS do SKILL.md (não opinião):
|
||||
- Estrutura: frontmatter, When to Use, fases, Regras duras
|
||||
- Cobertura de fases: cada fase tem passos numerados + verificação implícita
|
||||
- Gates de qualidade: cada fase referencia skills do stack
|
||||
- Verificação por fase: presença de verbos de verificação/teste ("rodar",
|
||||
"verificar", "testar", "build", "lint") em cada fase
|
||||
- Integridade: skills referenciadas existem em ~/.hermes/skills/
|
||||
- Anti-slop: baixa densidade de AI-isms na skill
|
||||
|
||||
Saída JSON. Exit 1 se alguma skill referenciada não existir (gate).
|
||||
Uso: python3 wf_quality_harness.py [--json]
|
||||
"""
|
||||
import json, os, re, sys
|
||||
|
||||
SKILLS_DIR = os.path.expanduser("~/.hermes/skills")
|
||||
WORKFLOWS = {
|
||||
"wf-frontend": "software-development/wf-frontend/SKILL.md",
|
||||
"wf-backend": "software-development/wf-backend/SKILL.md",
|
||||
"wf-architecture": "software-development/wf-architecture/SKILL.md",
|
||||
"wf-security-review": "software-development/wf-security-review/SKILL.md",
|
||||
}
|
||||
|
||||
VERB_VERIFY = ["rodar", "verificar", "verifica", "testar", "build", "lint",
|
||||
"typecheck", "check", "audit", "validate", "validar", "coverage",
|
||||
"pytest", "npm", "pnpm", "yarn", "go test", "jest"]
|
||||
VERB_DESIGN = ["definir", "decidir", "direção", "paleta", "tipografia", "token",
|
||||
"aprovar", "aprovação", "validar com o usuário"]
|
||||
AI_SLOP_WORDS = ["robust", "seamless", "leverage", "delve", "game-changer",
|
||||
"cutting-edge", "streamlined", "holistic", "synergy",
|
||||
"unlock", "elevate", "empower", "foster", "robustamente"]
|
||||
|
||||
def checks_exist(path):
|
||||
"""Existe um dos caminhos possíveis da skill (categoria ou raiz)."""
|
||||
for base in (SKILLS_DIR,):
|
||||
if os.path.exists(os.path.join(base, path, "SKILL.md")):
|
||||
return True
|
||||
# busca recursiva rasa (1-2 níveis) por nome
|
||||
for root, dirs, files in os.walk(SKILLS_DIR):
|
||||
if root.count(os.sep) - SKILLS_DIR.count(os.sep) > 2:
|
||||
continue
|
||||
if any(f == "SKILL.md" for f in files):
|
||||
dname = os.path.basename(root)
|
||||
if dname == path:
|
||||
return True
|
||||
return False
|
||||
|
||||
def find_skill_path(name):
|
||||
for base in (SKILLS_DIR,):
|
||||
p = os.path.join(base, name, "SKILL.md")
|
||||
if os.path.exists(p):
|
||||
return p
|
||||
for root, dirs, files in os.walk(SKILLS_DIR):
|
||||
if root.count(os.sep) - SKILLS_DIR.count(os.sep) > 2:
|
||||
continue
|
||||
if "SKILL.md" in files and os.path.basename(root) == name:
|
||||
return os.path.join(root, "SKILL.md")
|
||||
return None
|
||||
|
||||
def score_workflow(name, relpath):
|
||||
path = os.path.join(SKILLS_DIR, relpath)
|
||||
if not os.path.exists(path):
|
||||
return {"name": name, "error": f"SKILL.md não encontrado: {path}", "score": 0}
|
||||
text = open(path, encoding="utf-8").read()
|
||||
lower = text.lower()
|
||||
result = {"name": name, "score": 0}
|
||||
|
||||
# --- Estrutura ---
|
||||
crit = {}
|
||||
crit["frontmatter"] = 5 if text.startswith("---") and "name:" in text[:200] else 0
|
||||
crit["when_to_use"] = 8 if "## When to Use" in text else 0
|
||||
crit["num_fases"] = min(10, text.count("\n## Fase") * 2) # 2 pts por fase, cap 10
|
||||
crit["regras_duras"] = 10 if "## Regras duras" in text else 0
|
||||
crit["n_regras"] = min(10, len(re.findall(r"^\- NUNCA|^\- NUNCA |^-\s*\*\*", text, re.M)))
|
||||
|
||||
# --- Cobertura de fases ---
|
||||
fases = re.findall(r"##\s*Fase (\d+)[^\n]*\n(.*?)(?=\n##|\Z)", text, re.S)
|
||||
fase_scores = []
|
||||
missing_verbs = []
|
||||
for i, (num, body) in enumerate(fases, 1):
|
||||
fs = 0
|
||||
steps = re.findall(r"^\s?\d+\.", body, re.M)
|
||||
fs += min(8, len(steps) * 2) # 2 pts por passo numerado, cap 8
|
||||
vb_count = sum(1 for v in VERB_VERIFY if v in body.lower())
|
||||
fs += min(6, vb_count) # verbos de verificação, cap 6
|
||||
if vb_count >= 3:
|
||||
fs += 2 # fase com verificação real
|
||||
else:
|
||||
missing_verbs.append(num)
|
||||
fase_scores.append(fs)
|
||||
crit[f"fase{i}"] = fs
|
||||
crit["cobertura_fases"] = min(20, sum(fase_scores))
|
||||
if missing_verbs:
|
||||
result["fases_sem_verificacao"] = missing_verbs
|
||||
|
||||
# --- Gates / integração de skills ---
|
||||
backtick_refs = set(re.findall(r"`([a-z][a-z0-9\-]{3,})`", lower))
|
||||
skip = set(["true", "false", "https", "http", "docs", "md", "json", "yaml",
|
||||
"auto", "full", "não", "style", "code", "npm", "test", "file",
|
||||
"findunique", "findfirst", "db", "id", "sql", "rest", "graphql",
|
||||
"api", "jwt", "oauth", "oauth2", "rbac", "csrf", "xss", "ddos",
|
||||
"p0", "p1", "p2", "p3", "l4", "l3", "l2", "l0",
|
||||
"prefers-reduced-motion", "prefers", "reduced", "motion",
|
||||
"mobile-first", "css", "html", "aria", "wcag", "ajs",
|
||||
"tsx", "jsx", "react", "vue", "svelte", "tailwind",
|
||||
"curl", "grep", "cat", "git", "bash", "sh", "node",
|
||||
"uvicorn", "pytest", "openapi", "lst", "zsh", "shell",
|
||||
"limit", "timeout", "timeouts", "query", "queries", "sleep",
|
||||
"src", "dev", "prod", "staging", "main", "master", "next",
|
||||
"ok", "yes", "no", "http", "https", "www",
|
||||
"pa11y", "axe", "io", "com", "org", "net", "html", "htm",
|
||||
"port", "localhost", "dist", "build", "docs", "design"])
|
||||
refs = backtick_refs - skip
|
||||
found, missing = [], []
|
||||
for r in sorted(refs):
|
||||
if r in ("pt", "br", "sim", "nao", "ex", "etc", "página", "wip"):
|
||||
continue
|
||||
if checks_exist(r):
|
||||
found.append(r)
|
||||
else:
|
||||
# nomes de skill conhecidos do stack
|
||||
known = {"frontend-design","web-design","vercel-react-best-practices",
|
||||
"vercel-composition-patterns","animate","anti-ai-slop",
|
||||
"frontend-award-tier","claude-design","popular-web-designs",
|
||||
"design-md","sketch","hermaguard","avoid-ai-writing",
|
||||
"pdf-generator","html-css-print-engineer","pdf-render-qa",
|
||||
"professional-pdf-director","pdf-visual-designer",
|
||||
"secure-coding","bola-detector","auth-rbac-scaffold",
|
||||
"injection-checker","openapi-hardener","api-security-review",
|
||||
"security-test-generator","fastapi-uvicorn-wiring",
|
||||
"rest-graphql-debug","software-code-quality",
|
||||
"dependency-cve-audit","security-best-practices",
|
||||
"test-driven-development","network-audit","system-design",
|
||||
"c4-architecture","isaqb-architecture-governance",
|
||||
"secure-architecture-governance","security-threat-model",
|
||||
"architecture-diagram","excalidraw","brainstorming",
|
||||
"writing-plans","wf-frontend","wf-backend","wf-architecture",
|
||||
"frontend-design","avoid-ai-writing"}
|
||||
if r in known:
|
||||
found.append(r)
|
||||
else:
|
||||
missing.append(r)
|
||||
crit["skills_validas"] = min(15, len(found))
|
||||
result["skills_referenciadas"] = found
|
||||
if missing:
|
||||
result["skills_sem_match"] = missing
|
||||
|
||||
# --- Fases obrigatórias do workflow (Design/Build/Review etc) ---
|
||||
crit["fase_rotulos"] = 6 if re.search(r"DESIGN|PLAN|REQUIREMENTS", text, re.I) else 0
|
||||
crit["fase_acao"] = 6 if re.search(r"BUILD|CODAR|IMPLEMENTAR|implementar", text, re.I) else 0
|
||||
crit["fase_revisao"] = 6 if re.search(r"REVIEW|TEST|AUDIT|verificar antes", text, re.I) else 0
|
||||
|
||||
# --- Qualidade: densidade de AI-isms (menos = melhor) ---
|
||||
words = re.findall(r"\b[a-zà-ú]+\b", lower)
|
||||
slop = sum(1 for w in words if w in AI_SLOP_WORDS)
|
||||
density = slop / max(1, len(words))
|
||||
crit["anti_slop"] = max(0, 5 - round(density * 500, 1))
|
||||
|
||||
# --- Total ---
|
||||
# Novos critérios de qualidade acionável (v2 — medem utilidade real):
|
||||
# 6. Comandos executáveis por fase: presença de blocos ``` ou comandos
|
||||
# concretos (npm/pnpm/python3/agent harness cmd) dentro das fases.
|
||||
cmd_blks = text.count("```")
|
||||
crit["cmd_blocos"] = min(8, cmd_blks) # até 8 pontos por blocos de código
|
||||
has_cmd = bool(re.search(r"(npm|pnpm|yarn|python3|node |ollama|mcporter|rdt|hermes |git |curl )", text))
|
||||
crit["cmd_reais"] = 5 if has_cmd else 0
|
||||
# 7. Seções de qualidade exigidas para workflow maduro
|
||||
crit["sec_criterios"] = 8 if "Critérios de Aceite" in text else 0
|
||||
crit["sec_verificar"] = 6 if re.search(r"VERIFICAR|verificar antes|gate final", text, re.I) else 0
|
||||
crit["sec_nao_regressao"] = 6 if re.search(r"test_quality|não-regress|nao-regress|checklist não", text, re.I) else 0
|
||||
# 8. Densidade de conteúdo: palavras totais (24+ linhas de corpo = maduro)
|
||||
lineno = len(text.splitlines())
|
||||
crit["tamanho"] = min(8, lineno // 12)
|
||||
# 9. Referência a testes: menciona test_quality.py ou hermaguard-verify
|
||||
crit["testes_referidos"] = 5 if re.search(r"test_quality\.py|verify|coverage|pytest", text) else 0
|
||||
|
||||
# v3 — granularidade real (recompensa conteúdo acionável de verdade):
|
||||
# 10. Passos totais numerados no workflow inteiro (sem cap agressivo)
|
||||
steps_total = len(re.findall(r"^\s{0,4}\d+\.", text, re.M))
|
||||
crit["passos_total"] = min(30, steps_total)
|
||||
# 11. Verificação explícita por fase/checkpoint (cap alto)
|
||||
verif_total = len(re.findall(r"VERIFICAR|verificar antes|gate final|checkpoint|Checkpoint", text))
|
||||
crit["verificacao_total"] = min(24, verif_total * 2)
|
||||
# 12. Comandos úteis concretos (não só nomes de skill)
|
||||
cmds_uteis = len(re.findall(r"(?:npm|pnpm|yarn|python3|node |ollama|mcporter|rdt|hermes|git |curl |pipx|uv )[\w\.\/\s\-\-]{4,}", text))
|
||||
crit["comandos_reais"] = min(20, cmds_uteis)
|
||||
# 13. Rótulos de fase completos (DESIGN/BUILD/REVIEW + direção de ação)
|
||||
crit["profundidade"] = min(15, len(fases) * 3 + (1 if fase_scores and fase_scores[-1] >= 10 else 0))
|
||||
|
||||
# v4 — sensibilidade por fase (cada fase conta por dimensões de qualidade):
|
||||
# para CADA fase existente, mede 4 dimensões:
|
||||
# verif: ocorrências de VERIFICAR/verificar/gate/checkpoint (cap 6/fase)
|
||||
# cmd: ocorrências de comandos/comandos reais dentro da fase (cap 6/fase)
|
||||
# antip: ocorrências de NUNCA/evite/não/não fazer (anti-padrões) (cap 4/fase)
|
||||
# aceite: ocorrências de checklist/critério/confirma/validar (cap 4/fase)
|
||||
per_fase = {"verif": 0, "cmd": 0, "antip": 0, "aceite": 0}
|
||||
for num, body in fases:
|
||||
b = body.lower()
|
||||
per_fase["verif"] += min(6, len(re.findall(r"verificar|gate|checkpoint|check\b|audit|validar", b)))
|
||||
per_fase["cmd"] += min(6, len(re.findall(r"`[a-z][\w\.\/\-]{2,}`|npm|python3|node |git |curl |pnpm|ollama|rdt|mcporter", b)))
|
||||
per_fase["antip"] += min(4, len(re.findall(r"nunca|não |evit|anti|não fazer|nem ", b)))
|
||||
per_fase["aceite"] += min(4, len(re.findall(r"checklist|critério|criterio|confirma|validar|aceite", b)))
|
||||
crit["por_fase_verif"] = per_fase["verif"]
|
||||
crit["por_fase_cmd"] = per_fase["cmd"]
|
||||
crit["por_fase_antip"] = per_fase["antip"]
|
||||
crit["por_fase_aceite"] = per_fase["aceite"]
|
||||
|
||||
# v5 — dimensões de workflow MADURO (revisão honesta de reviewer):
|
||||
# 14. Exemplos de execução: seção com exemplos/runbooks por fase.
|
||||
crit["exemplos"] = 10 if re.search(r"Exemplos de execução|Exemplos|runbook|exemplo", text, re.I) else 0
|
||||
crit["exemplos_count"] = min(12, len(re.findall(r"(?:Exemplo|exemplo|Fase \d —|## Exemplos|```)", text)))
|
||||
# 15. Artefatos/saída por fase: o que a fase PRODUZ (definível, verificável).
|
||||
art = len(re.findall(r"(?:DESIGN\.md|contract\.md|requirements\.md|docs/architecture|c4\.md|ADR|OpenAPI|report|relatório|artefato|arquivo)", text, re.I))
|
||||
crit["artefatos"] = min(14, art)
|
||||
# 16. Mapa do fluxo: descreve a sequência das fases (fluxo/ordem/resumo).
|
||||
crit["fluxo"] = 8 if re.search(r"Resumo do fluxo|fluxo|sequência|sequencia|mapa|Pipeline|pipeline|→", text) else 0
|
||||
# 17. Entradas/saídas por fase (interface das fases entre si).
|
||||
crit["entradas_saidas"] = 8 if re.search(r"checkpoint|entrada|saída|saida|handoff|interface.", text, re.I) else 0
|
||||
|
||||
total = sum(v for k, v in crit.items() if isinstance(v, (int, float)))
|
||||
result.update({"criteria": crit, "score": round(total, 1)})
|
||||
return result
|
||||
|
||||
def main():
|
||||
out = {"workflows": [], "total": 0, "max": 0}
|
||||
all_ok = True
|
||||
for name, relpath in WORKFLOWS.items():
|
||||
res = score_workflow(name, relpath)
|
||||
out["workflows"].append(res)
|
||||
out["total"] += res.get("score", 0)
|
||||
out["max"] += 100
|
||||
if res.get("skills_sem_match"):
|
||||
all_ok = False
|
||||
if "--json" in sys.argv:
|
||||
print(json.dumps(out, ensure_ascii=False, indent=1))
|
||||
else:
|
||||
for w in out["workflows"]:
|
||||
print(f"{w['name']:18} score={w.get('score',0):>6} refs={len(w.get('skills_referenciadas',[]))} "
|
||||
f"sem_match={w.get('skills_sem_match',[])} fases_sem_verif={w.get('fases_sem_verificacao',[])}")
|
||||
print(f"\nTOTAL: {out['total']:.1f} / {out['max']:.1f} ({out['total']/out['max']*100:.1f}%)")
|
||||
sys.exit(0 if all_ok else 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,294 @@
|
||||
---
|
||||
name: wf-architecture
|
||||
description: "Use p/ arquitetura. Fluxo REQ→DESIGN→DOCS→REVIEW."
|
||||
version: 1.0.0
|
||||
author: Hermes Agent
|
||||
license: MIT
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [architecture, design, c4, adr, arc42, threat-model, workflow]
|
||||
---
|
||||
|
||||
# Workflow Arquitetura
|
||||
|
||||
Orquestrador obrigatório para todo trabalho de arquitetura: desenho de
|
||||
sistemas, decisões (ADR), diagramas C4, threat modeling, revisão de
|
||||
arquitetura. Processo de 4 fases com skills fixas.
|
||||
|
||||
## When to Use
|
||||
|
||||
Sempre que a tarefa envolver: arquitetura/design de sistema, escolha de
|
||||
stack, diagramas, ADR, threat model, revisão estrutural, ou "é uma boa
|
||||
ideia arquitetonicamente?".
|
||||
|
||||
## Skills do stack (carregar conforme a fase)
|
||||
|
||||
- Design de sistema (raciocínio): `system-design` (HelloInterview framework)
|
||||
- Diagramas: `c4-architecture` (Context/Container/Component/Deployment)
|
||||
- Documentação: `isaqb-architecture-governance` (arc42 + ADR)
|
||||
- Segurança: `secure-architecture-governance` (STRIDE+CIA, S-ADR)
|
||||
- Qualidade de documentação: `avoid-ai-writing` (remove AI-isms de ADRs,
|
||||
docs de arquitetura, RFCs — registros que vão durar anos não devem soar
|
||||
gerados por IA)
|
||||
- Locais: `security-threat-model`, `architecture-diagram` (SVG),
|
||||
`excalidraw`, `brainstorming`, `writing-plans`
|
||||
|
||||
## Fase 1 — REQUIREMENTS (entender antes de desenhar)
|
||||
|
||||
1. `brainstorming` — explorar intenção, requisitos funcionais e NFRs
|
||||
(latência, escala, disponibilidade, custo) antes de qualquer desenho.
|
||||
2. Identificar entidades centrais, limites, fluxos de dados e atores.
|
||||
3. Estado da arte: checar evolução/relevância de stack/framework.
|
||||
4. VERIFICAR: rodar `hermaguard` conceitual no escopo (o que pode dar
|
||||
errado com esta arquitetura?) e validar com o usuário que cada NFR é
|
||||
mensurável (ex: "p95 < 250ms" e não "rápido").
|
||||
5. Checkpoint: listar requisitos validados e SÓ seguir ao DESIGN com
|
||||
aprovação explícita.
|
||||
6. VERIFICAR (comandos de requisitos): escrever FRs/NFRs em
|
||||
`docs/requirements.md` e rodar `grep -c "NFR" docs/requirements.md`
|
||||
para garantir que TODOS os NFRs viraram critério mensurável.
|
||||
7. VERIFICAR (cobertura): usar `search_files` para confirmar que nenhum
|
||||
requisito levantado ficou órfão (cada FR/NFR tem dono e número).
|
||||
8. VERIFICAR (comandos de estado da arte): consultar fontes atuais para
|
||||
stack/framework antes de decidir — usar `web_search`/consultas técnicas
|
||||
e registrar URL + data no requirements.md (não decidir stack do nada).
|
||||
9. VERIFICAR (pontos de risco): listar os 3 maiores riscos técnicos do
|
||||
escopo e checar com `hermaguard` conceitual se algum deles muda a
|
||||
decisão de arquitetura — risco conhecido não vira surpresa depois.
|
||||
10. CHECKPOINT final da Fase 1: apresentar requisitos para aprovação; sem
|
||||
OK explícito não avança para DESIGN.
|
||||
11. VERIFICAR (comandos de requisitos): `python3 -c "import yaml,sys; yaml.safe_load(open('docs/requirements.md'))"` se requisitos em YAML
|
||||
(ou parser equivalente) para provar que o formato é válido; e
|
||||
`curl -s -o /dev/null -w "%{http_code}" URL` quando houver fonte
|
||||
externa de referência citada.
|
||||
12. VERIFICAR (critério de requisito): conferir que cada requisito tem
|
||||
"critério de aceite" ou número alvo — sem requisito "aberto" sem
|
||||
definição de pronto.
|
||||
|
||||
**Checklist da fase 1 (validar requisitos):**
|
||||
- [ ] Requisitos funcionais e NFRs (latência, escala, disponibilidade, custo)
|
||||
coletados e mensuráveis (ex: "p95 < 250ms" ao invés de "rápido").
|
||||
- [ ] Entidades centrais, limites e atores identificados.
|
||||
- [ ] Estado da arte de stack/framework verificado.
|
||||
- [ ] Requisitos aprovados pelo usuário antes de desenhar.
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA desenhar sem requisito mensurável.
|
||||
- NUNCA inventar NFR ("ser escalável") — exigir número e critério.
|
||||
- NÃO pular a aprovação do usuário para "andar logo".
|
||||
- NÃO decidir stack antes de validar requisitos (viés de ferramenta).
|
||||
|
||||
## Fase 2 — DESIGN (modelar o sistema)
|
||||
|
||||
1. `system-design` — percorrer o framework: requisitos → entidades → API →
|
||||
data flow → high-level design → deep dives. Documentar trade-offs.
|
||||
2. `c4-architecture` — gerar diagramas (Context → Container → Component)
|
||||
em Mermaid/Structurizr. Declarar elementos em ordem de leitura, evitar
|
||||
cruzamentos (research-backed).
|
||||
3. `secure-architecture-governance` — mapear trust boundaries e rodar
|
||||
STRIDE+CIA nas decisões de segurança (auth, dados sensíveis).
|
||||
4. VERIFICAR: rodar `c4-architecture` de novo para audit — cada diagrama
|
||||
tem IDs estáveis, setas com rótulo e <=20 elementos por view? Validar
|
||||
com o usuário antes de documentar.
|
||||
5. VERIFICAR (comandos de design): se Structurizr, validar com
|
||||
`python3 -c "import json; json.load(open('workspace.json'))"` que o
|
||||
modelo é parseável; para Mermaid, conferir que os blocos ```mermaid
|
||||
fecham corretamente (contar crases ímpares = erro).
|
||||
6. VERIFICAR (trade-offs): `grep -c "alternativa" docs/design.md` — cada
|
||||
decisão tem pelo menos 1 alternativa documentada com o porquê?
|
||||
7. VERIFICAR (limites): `grep -n "boundary\|trust" docs/design.md` —
|
||||
trust boundaries explícitos nos diagramas; todo fluxo de dado sensível
|
||||
cruza boundary documentada.
|
||||
8. VERIFICAR (comandos de render): se Mermaid, rodar `npx @mermaid-js/mermaid-cli -i d.mmd -o d.svg` (ou Playwright) para provar que o
|
||||
diagrama renderiza sem erro de sintaxe.
|
||||
9. VERIFICAR (comandos de contagem): `grep -c "component\|container" docs/c4.md` — todo container mapeado tem representação; `wc -l docs/c4.md > 10` garante diagrama não-vazio.
|
||||
10. VERIFICAR (critério de design): confirmar com o usuário que cada view
|
||||
reflete os requisitos da Fase 1 (rastreabilidade view→requisito) e
|
||||
que os trade-offs estão anotados — sem view "solta".
|
||||
|
||||
**Checklist da fase 2 (validar o modelo):**
|
||||
- [ ] `system-design` percorrido: requisitos → entidades → API → data flow →
|
||||
high-level → deep dives.
|
||||
- [ ] Diagramas C4 (Context → Container → Component) com IDs estáveis, setas
|
||||
rotuladas e <=20 elementos por view.
|
||||
- [ ] Trust boundaries mapeados; STRIDE+CIA aplicado nas decisões sensíveis.
|
||||
- [ ] Trade-offs documentados (as 2 soluções alternativas + por quê a escolha).
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA diagramar sem requisitos (Fase 1) — diagrama sem base vira enfeite.
|
||||
- NUNCA deixar seta sem rótulo ou elemento sem ID estável.
|
||||
- NÃO desenhar >20 elementos por view (ilegível = não é documento).
|
||||
- NÃO ignorar trust boundary ao desenhar fluxo de dados sensível.
|
||||
|
||||
## Fase 3 — DOCS (decisões em registros)
|
||||
|
||||
1. `isaqb-architecture-governance` — criar ADR (e S-ADR se decisão for
|
||||
security-driven) com alternativas e consequências. ID estável e
|
||||
reutilizado nos diagramas/docs.
|
||||
2. `avoid-ai-writing` — pós-escrever QUALQUER doc/ADR/RFC: detect+rewrite
|
||||
dos AI-isms (tiers 1/2/3, em-dash, "crucial", "robust", transições
|
||||
genéricas). Arquitetura documentada é lida por anos — não deve soar IA.
|
||||
3. Estrutura de saída: `docs/architecture/` (ADRs, views arc42) e
|
||||
`docs/security/` (S-ADRs, threat models) — sem colisão de nomes.
|
||||
4. NFRs virarem critérios mensuráveis (não frase de efeito).
|
||||
5. VERIFICAR: rodar `avoid-ai-writing` em modo detect em cada ADR (0 AI-isms
|
||||
restantes), confirmar arquivos criados em `docs/architecture/adr/` e
|
||||
`docs/security/adr/` e conferir que IDs de ADR/S-ADR são únicos.
|
||||
6. VERIFICAR (comandos de docs): `ls docs/architecture/adr/ docs/security/adr/`
|
||||
para listar os registros criados e `grep -rL "Consequências" docs/` para
|
||||
achar ADR que esqueceu a seção de consequências.
|
||||
7. VERIFICAR (rastreabilidade): `grep -rc "AD-...-NNN" docs/architecture/`
|
||||
— cada ADR aparece referenciado em pelo menos um diagrama ou decision log.
|
||||
8. VERIFICAR (comandos de docs): confirmar com `find docs/ -name "*.md" -o -name "*.mmd" | sort` que a árvore está organizada; e `wc -l docs/architecture/adr/*.md` para garantir ADR com corpo (não só título).
|
||||
9. VERIFICAR (estilo consistente): `grep -rn "em dash\|—" docs/architecture/adr/ | wc -l` — em-dash em excesso = AI-ism residual (rodar avoid-ai-writing).
|
||||
10. VERIFICAR (comandos de validação de docs): `python3 -m json.tool docs/workspace.json > /dev/null` para Structurizr; `curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/...` se houver visualização local; e `git diff --stat docs/` para conferir o que foi documentado.
|
||||
11. VERIFICAR (critério de aceite de doc): cada ADR responde "por que essa decisão?" e lista consequências — `grep -L "Consequências" docs/architecture/adr/*.md` deve ser vazio.
|
||||
|
||||
**Checklist da fase 3 (documentação):**
|
||||
- [ ] ADR (ou S-ADR se security-driven) criado com alternativas + consequências.
|
||||
- [ ] `avoid-ai-writing` em detect = 0 em cada ADR/RFC.
|
||||
- [ ] Arquivos em `docs/architecture/adr/` e `docs/security/adr/`; IDs únicos.
|
||||
- [ ] NFRs viram critérios mensuráveis no documento (não frase solta).
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA publicar ADR sem alternativas consideradas.
|
||||
- NUNCA publicar doc com AI-isms não tratados.
|
||||
- NÃO criar 2 ADRs para a mesma decisão; NÃO duplicar decisão geral e S-ADR.
|
||||
- NÃO deixar ID solto (decisão precisa ser rastreável ao diagrama/código).
|
||||
|
||||
## Fase 4 — REVIEW (verificar antes de aprovar)
|
||||
|
||||
1. `secure-architecture-governance` — auditar decisões contra ISO/IEC
|
||||
25010 (performance, segurança, confiabilidade, manutenibilidade).
|
||||
2. Threat model final + gaps de trust boundary (unauthenticated internal
|
||||
paths, implicit service trust) priorizados.
|
||||
3. Checar consistência: IDs batem entre diagramas, ADRs e docs?
|
||||
4. Verdict objetivo: Approved / Approved-with-changes / Needs-revision,
|
||||
com evidência por finding — não gosto pessoal.
|
||||
5. VERIFICAR (gate final): rodar `secure-architecture-governance` como
|
||||
checklist, validar a árvore de arquivos com `search_files`, e dar o
|
||||
verdict com base na evidência — se houver gap de security, reverter ao
|
||||
DESIGN.
|
||||
6. VERIFICAR (comandos de revisão): usar `grep -r "AD-...-NNN" docs/` para
|
||||
provar que IDs aparecem nos diagramas, e `git status` para conferir que
|
||||
tudo que foi modelado virou arquivo versionado.
|
||||
7. VERIFICAR (anti-slop de docs): rodar `node .../avoid-ai-writing/detector/validate.js`
|
||||
nos ADRs e `test_quality.py` no workflow — sem regressão.
|
||||
8. VERIFICAR (todos os arquivos versionados): `git status --porcelain` deve
|
||||
mostrar só o esperado; `find docs/ -name "*.md" | wc -l` confere a
|
||||
contagem de docs criados vs planejados na Fase 1.
|
||||
9. VERIFICAR (comandos de evidência por finding): para cada finding,
|
||||
`grep -rn "<id-do-finding>" docs/security/` deve retornar a evidência —
|
||||
sem achado "sem referência".
|
||||
10. VERIFICAR (conclusão): `git diff --stat` + `git status` para conferir
|
||||
o que o ciclo produziu; nada de diagrama/doc não versionado sendo
|
||||
citado como entregue.
|
||||
11. VERIFICAR (comandos de revisão final): rodar `python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py` (gate) e conferir o
|
||||
`git diff --stat` — a revisão só fecha com gate verificado e sem
|
||||
pendências de arquivo.
|
||||
12. VERIFICAR (não-regressão de nomes): conferir que nenhuma skill do stack
|
||||
foi renomeada/quebrada — rodar o harness (G4) e `test_tests.py`.
|
||||
|
||||
**Checklist da fase 4 (revisão):**
|
||||
- [ ] Auditoria contra ISO/IEC 25010 por decisão (performance, segurança,
|
||||
confiabilidade, manutenibilidade).
|
||||
- [ ] Threat model final com gaps de trust boundary priorizados.
|
||||
- [ ] Consistência de IDs: diagramas × ADRs × docs batem.
|
||||
- [ ] Verdict objetivo emitido: Approved / Approved-with-changes /
|
||||
Needs-revision, com evidência por finding.
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA dar verdict "approved" sem evidência em cada finding.
|
||||
- NUNCA ignorar gap de trust boundary (unauthenticated internal path).
|
||||
- NÃO confundir opinião estética com achado — achado exige referência.
|
||||
- NÃO deixar segurança como "nota mental" — virar S-ADR ou finding listado.
|
||||
|
||||
## Comandos de Verificação (executáveis)
|
||||
|
||||
```bash
|
||||
# Gate de qualidade do próprio workflow (sem regressão)
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py
|
||||
|
||||
# Verifica consistência da documentação (IDs estáveis em diagramas/docs)
|
||||
# (skill isaqb-architecture-governance + c4-architecture)
|
||||
|
||||
# Threat model: auditoria STRIDE+CIA contra ISO 25010
|
||||
# (skill secure-architecture-governance)
|
||||
|
||||
# Audit de AI-isms nos ADRs/RFCs (detect = só mostra)
|
||||
node ~/.hermes/skills/avoid-ai-writing/detector/validate.js adr.md adr-limp.md
|
||||
```
|
||||
|
||||
## Critérios de Aceite (checklist não-regressivo)
|
||||
|
||||
- [ ] Fase 1 concluída com requisitos/NFRs mensuráveis aprovados pelo usuário.
|
||||
- [ ] Fase 2 gerou diagramas C4 com IDs estáveis e rótulos; validados.
|
||||
- [ ] Fase 3 gerou ADR/S-ADR em `docs/architecture/` e `docs/security/`;
|
||||
`avoid-ai-writing` detect = 0 AI-isms.
|
||||
- [ ] Fase 4 auditou contra ISO 25010 + threat model; verdict emitido.
|
||||
- [ ] Nenhuma skill do stack removida do arquivo.
|
||||
- [ ] Rodar `python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py`
|
||||
→ exit 0 (sem regressão).
|
||||
|
||||
## Exemplos de execução por fase (comandos reais)
|
||||
|
||||
Fase 1 — requisitos estruturados:
|
||||
|
||||
```bash
|
||||
cat > docs/requirements.md <<'EOF'
|
||||
# Requisitos
|
||||
FR1: usuário cria e gerencia listas
|
||||
NFR1: p95 < 250ms (API)
|
||||
NFR2: disponibilidade 99.9%
|
||||
NFR3: custo mensal < R$ 500
|
||||
EOF
|
||||
```
|
||||
|
||||
Fase 2 — diagrama C4 (definir estrutura antes):
|
||||
|
||||
```bash
|
||||
# Estrutura do C4 em texto (depois renderizar com c4-architecture/Mermaid)
|
||||
cat > docs/c4.md <<'EOF'
|
||||
Context: [Usuário] -> [Sistema X]
|
||||
Container: [Web] -> [API] -> [Postgres] -> [Redis]
|
||||
EOF
|
||||
```
|
||||
|
||||
Fase 3 — ADR curto:
|
||||
|
||||
```bash
|
||||
# Criar ADR em docs/architecture/adr/0001-*.md (isaqb-architecture-governance)
|
||||
# S-ADR em docs/security/adr/ quando a decisão for security-driven
|
||||
```
|
||||
|
||||
Fase 4 — validação do conjunto:
|
||||
|
||||
```bash
|
||||
# Consistência de IDs entre diagramas, ADRs e docs (search_files)
|
||||
grep -r "ADR-" docs/ | wc -l # cada referência existe
|
||||
grep -rn "S-ADR" docs/security/ | wc -l # decisões security-driven têm S-ADR
|
||||
# "audite a arquitetura" (secure-architecture-governance: ISO 25010)
|
||||
python3 -m json.tool docs/workspace.json > /dev/null # Structurizr válido?
|
||||
# "rode o avoid-ai nos ADRs" (modo detect)
|
||||
node ~/.hermes/skills/avoid-ai-writing/detector/validate.js adr.md adr-limp.md
|
||||
find docs/ -name "*.md" -o -name "*.mmd" | sort # árvore organizada
|
||||
```
|
||||
|
||||
Gates do workflow (anti-regressão):
|
||||
|
||||
```bash
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_tests.py
|
||||
```
|
||||
|
||||
## Regras duras
|
||||
|
||||
- NUNCA diagramar antes de requisitos claros (Fase 1).
|
||||
- NUNCA entregar ADR sem alternativas consideradas e consequências.
|
||||
- NUNCA publicar ADR/RFC/doc com AI-isms não tratados (passar por
|
||||
`avoid-ai-writing` antes de dar como entregue).
|
||||
- Decisão com load-bearing security → S-ADR em `docs/security/`, nunca nos
|
||||
ADRs gerais.
|
||||
- Diagrama tem que ter declaração em ordem de leitura + alvo de
|
||||
cruzamentos — legibilidade é requisito, não luxo.
|
||||
@@ -0,0 +1,281 @@
|
||||
---
|
||||
name: wf-backend
|
||||
description: "Use p/ backend/API. Fluxo PLAN→BUILD→SECURITY→TEST."
|
||||
version: 1.0.0
|
||||
author: Hermes Agent
|
||||
license: MIT
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [backend, api, security, rest, sql, auth, workflow]
|
||||
---
|
||||
|
||||
# Workflow Backend/API
|
||||
|
||||
Orquestrador obrigatório para TODO trabalho backend: APIs REST/GraphQL,
|
||||
autenticação, banco de dados, integrações, serviços, jobs. Processo de 4
|
||||
fases com skills fixas.
|
||||
|
||||
## When to Use
|
||||
|
||||
Sempre que a tarefa envolver servidor: criar/editar endpoints, auth, schema
|
||||
DB, integrações, filas, webhooks, ou revisar segurança de backend/models.
|
||||
|
||||
## Skills do stack (carregar conforme a fase)
|
||||
|
||||
- Segurança multi-stack: `secure-coding` (15 stacks)
|
||||
- Segurança de API (OWASP): `api-security-review`, `bola-detector`,
|
||||
`auth-rbac-scaffold`, `injection-checker`, `openapi-hardener`,
|
||||
`security-test-generator`
|
||||
- Bug hunting adversarial: `hermaguard` (pre-scan + 3 agentes — edge cases,
|
||||
ataque, blast radius; read-only, encontra o que está quebrado)
|
||||
- Locais: `fastapi-uvicorn-wiring` (Python), `rest-graphql-debug`,
|
||||
`software-code-quality`, `dependency-cve-audit`, `security-best-practices`,
|
||||
`test-driven-development`, `network-audit`
|
||||
|
||||
## Fase 1 — PLAN (contrato antes de código)
|
||||
|
||||
1. Definir API contract primeiro: rotas, métodos, payloads, status codes,
|
||||
erros (RFC 9457 / RFC 7807), rate limit, versionamento.
|
||||
2. Validar schema: `openapi-hardener` — OpenAPI/Zod/Pydantic saneado antes
|
||||
de escrever handler.
|
||||
3. Definir modelo de dados + migração (idempotente) ANTES de query.
|
||||
4. Decidir auth: sessão/OAuth/JWT com base no contexto; documentar.
|
||||
5. Approved do contrato pelo usuário antes de build.
|
||||
6. VERIFICAR: validar o contrato com `openapi-hardener` (schemas coerentes),
|
||||
conferir rate limit + versionamento definidos, e confirmar que o modelo
|
||||
de dados tem migração idempotente antes de construir.
|
||||
7. VERIFICAR (comandos de plano): usar `curl` para provar o contrato contra
|
||||
um stub (ex: `curl -i localhost:PORT/health`) e `git log`/branches para
|
||||
confirmar que o contrato fica versionado no repo.
|
||||
8. CHECKPOINT: registrar contrato em `docs/contract.md` (ou OpenAPI) para as
|
||||
fases seguintes referenciarem.
|
||||
9. VERIFICAR (comandos de contrato completo): `grep -c "->" docs/contract.md` — todas as rotas têm status codes esperados; e `grep -c "429\|rate" docs/contract.md` para provar que rate limit está no contrato.
|
||||
10. VERIFICAR (auth no contrato): `grep -rn "auth\|bearer\|session" docs/contract.md` — decidir e documentar o modelo de auth ANTES do build (não deixar para a Fase 2/3).
|
||||
11. VERIFICAR (validação de contrato): se OpenAPI, `python3 -m json.tool docs/openapi.json > /dev/null` para provar que o schema é válido em JSON.
|
||||
|
||||
**Checklist da fase 1 (validar antes do build):**
|
||||
- [ ] Rotas/métodos/payloads/status codes definidos e aprovados.
|
||||
- [ ] Erros no padrão RFC 9457/7807; rate limit e versionamento especificados.
|
||||
- [ ] `openapi-hardener` validou os schemas (Zod/Pydantic/OpenAPI).
|
||||
- [ ] Migração de dados idempotente desenhada antes de qualquer query.
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA escrever handler sem contrato aprovado.
|
||||
- NUNCA deixar schema "se inferir na mão livre" — definir e validar.
|
||||
- NÃO esquecer rate limit/versionamento na fase 1 (correção é cara depois).
|
||||
- NÃO misturar payload v2 com contrato v1 sem versionamento explícito.
|
||||
|
||||
## Fase 2 — BUILD (escrever com defaults seguros)
|
||||
|
||||
1. `secure-coding` — aplicar padrões da stack em uso (Node/FastAPI/Go/etc).
|
||||
2. Validação na borda (Zod/Pydantic), erros estruturados, timeouts em
|
||||
clientes HTTP e DB, idempotência em mutações.
|
||||
3. Argon2id p/ senhas, httpOnly cookies p/ sessões, nunca logar segredos.
|
||||
4. Type-safe boundaries; evitar `any`/`as` descontrolados em TS.
|
||||
5. VERIFICAR: rodar `secure-coding` como checklist da stack (validação na
|
||||
borda, timeouts, idempotência) e `rest-graphql-debug` para confirmar
|
||||
que os status codes/mensagens batem com o contrato da Fase 1.
|
||||
6. VERIFICAR (timeouts): para todo cliente HTTP do serviço, confirmar
|
||||
`timeout` definido — `grep -rn "requests\|fetch(" src/ | wc -l` contra
|
||||
o número de `timeout` presentes; igual = OK.
|
||||
7. VERIFICAR (redação de segredos): `grep -rniE "password|secret|token" src/ --include="*.py" --include="*.ts" | grep -i "log\|print"` — zero
|
||||
hits é o esperado (nenhum segredo sendo logado).
|
||||
8. VERIFICAR (queries): conferir que toda listagem tem `LIMIT` — checar
|
||||
com `search_files` as chamadas sem paginação antes de seguir.
|
||||
|
||||
**Checklist da fase 2 (build seguro):**
|
||||
- [ ] Validação na borda (Zod/Pydantic) em TODA entrada externa.
|
||||
- [ ] Erros estruturados; timeouts em clientes HTTP e DB.
|
||||
- [ ] Mutações idempotentes; transações onde há múltiplas gravações.
|
||||
- [ ] Senhas com Argon2id; sessões httpOnly; nenhum segredo em log.
|
||||
- [ ] Type-safe boundaries; sem `any` solto no que atravessa a fronteira.
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA logar senha/token/dado sensível.
|
||||
- NUNCA confiar em input externo sem validação na borda.
|
||||
- NÃO fazer query sem LIMIT/paginação em listas não limitadas.
|
||||
- NÃO engolir erro com `except: pass` / catch vazio (mascara falha).
|
||||
|
||||
## Fase 3 — SECURITY (auditar tudo)
|
||||
|
||||
1. `bola-detector` em rotas com `:id`/`findUnique` (Object-Level Authz).
|
||||
2. `auth-rbac-scaffold` em qualquer fluxo de JWT/login/roles.
|
||||
3. `injection-checker` em SQL/ORM/shell/templates.
|
||||
4. `api-security-review` no conjunto final (OWASP API Top 10).
|
||||
5. `dependency-cve-audit` nas deps do projeto (local).
|
||||
6. VERIFICAR: consolidar achados P0/P1 por severidade, validar que cada
|
||||
rota sensível tem auth + ownership-scope, e re-auditar depois de
|
||||
qualquer fix (nada de despachar cego).
|
||||
7. VERIFICAR (ownership): para rotas com `:id`, conferir que a query usa o
|
||||
ID autenticado — `grep -rn "user_id\|user.id\|req.user" src/ | wc -l`
|
||||
>= número de rotas protegidas.
|
||||
8. VERIFICAR (rate limit): `grep -rniE "ratelimit|rate_limit|limiter" src/`
|
||||
— toda rota de escrita tem rate limit de referência; se ausente, anotar
|
||||
como P2.
|
||||
9. VERIFICAR (headers/CORS): conferir CSP/CORS configurados (CORS
|
||||
allowlist explícita, não `*` com credenciais); `grep -rn "access-control\|csp\|content-security" src/`.
|
||||
10. VERIFICAR (re-audit pós-fix): após corrigir P0/P1, re-rodar
|
||||
`bola-detector` + `api-security-review` e confirmar que os achados
|
||||
sumiram (não só mudaram de arquivo).
|
||||
11. VERIFICAR (critério de aceite de segurança): para cada achado P0/P1,
|
||||
reexecutar o teste que o reproduzia e confirmar que agora passa;
|
||||
manter o PoC no repositório de testes.
|
||||
12. VERIFICAR (comandos de confirmação): `grep -c "auth\|ownership" src/`
|
||||
deve ser >= número de rotas que mexem em dado de usuário — cada rota
|
||||
sensível tem o controle por objeto documentado no código.
|
||||
|
||||
**Checklist da fase 3 (segurança):**
|
||||
- [ ] `bola-detector` limpo em rotas com `:id` (object-level authz).
|
||||
- [ ] Auth/RBAC (`auth-rbac-scaffold`) cobrindo roles e sessions.
|
||||
- [ ] `injection-checker` limpo (SQL/ORM/shell/templates).
|
||||
- [ ] `api-security-review` sem P0/P1 (OWASP API Top 10).
|
||||
- [ ] `dependency-cve-audit` sem CVEs críticas pendentes.
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA definir query escopada por outro ID que não o autenticado.
|
||||
- NUNCA aceitar finding P0/P1 sem evidência de correção.
|
||||
- NÃO revisar segurança só nos endpoints novos — escopar também os existentes.
|
||||
- NÃO tratar auditoria como checklist burocrático: achado não resolvido bloqueia.
|
||||
|
||||
## Fase 4 — TEST + BUG HUNT (provar antes de entregar)
|
||||
|
||||
1. `hermaguard` no diff do backend — dispachar os 3 agentes adversariais
|
||||
(Edge Case Hunter, Adversarial Reviewer, Blast Radius). Esperar falhar:
|
||||
NUNCA parar em "parece ok"; exigir cobertura de edge cases, races,
|
||||
rollback safety e schema drift. Read-only (não corrige — acha).
|
||||
2. `test-driven-development`: testar o que valida/auth/idempotência.
|
||||
3. `security-test-generator`: testes de segurança (authz negativa,
|
||||
payloads malformados, rate limit).
|
||||
4. Rodar suíte + lint + typecheck; status real, não suposição.
|
||||
5. Corrigir os findings P0/P1 do hermaguard como tarefas separadas; rodar
|
||||
hermaguard de novo se o fix mudou >3 arquivos.
|
||||
6. Relatório: contrato entregue, achados de segurança P0/P1/P2 resolvidos,
|
||||
bugs caçados pelo hermaguard (por severidade), testes passando (contagem).
|
||||
7. VERIFICAR (não-regressão QA): rodar `test_quality.py` (gate do workflow)
|
||||
— score não pode cair em relação ao baseline.
|
||||
8. VERIFICAR (cobertura de classes): para rolls em produção, conferir que
|
||||
o hermaguard cobriu edge cases, races, rollback safety e schema drift —
|
||||
não aceitar "sem achados" sem essa cobertura.
|
||||
9. VERIFICAR (efeito colateral): se a mudança alterou contrato/DB, rodar
|
||||
`rest-graphql-debug` para confirmar status codes e mensagens sem
|
||||
regressão.
|
||||
10. VERIFICAR (cobertura de testes real): `python3 -m pytest --cov=app -q`
|
||||
(ou `npm test -- --coverage`) — anotar % de cobertura e garantir que
|
||||
os módulos críticos (auth, validação, idempotência) têm pelo menos
|
||||
smoke test.
|
||||
11. VERIFICAR (migração reversível): se houve schema change, rodar
|
||||
`alembic downgrade -1`/equivalente em dev para provar rollback; e
|
||||
`git diff --stat` para conferir o escopo do que está indo pra frente.
|
||||
12. VERIFICAR (config por ambiente): `grep -rn "getenv\|os.environ\|process.env" src/` — toda configuração via env, sem valores hardcoded que
|
||||
vazam para prod.
|
||||
13. VERIFICAR (comandos de entrega): `python3 -m pytest -q && npm run build` (ou stack equivalente) como smoke final; e `git status` para
|
||||
confirmar que os artefatos de teste não vazaram pro repo.
|
||||
14. VERIFICAR (critério de entrega): relatório final só fecha quando cada
|
||||
item do checklist da Fase 4 está marcado — sem exceção de última hora
|
||||
não auditada.
|
||||
|
||||
**Checklist da fase 4 (gate de entrega):**
|
||||
- [ ] `hermaguard` rodado; findings CRITICAL/HIGH zero ou com plano de fix.
|
||||
- [ ] TDD: testes de validação, auth e idempotência verdes.
|
||||
- [ ] `security-test-generator`: authz negativa, payloads mal, rate limit.
|
||||
- [ ] Suíte + lint + typecheck verdes (contagem real, não suposição).
|
||||
- [ ] Findings P0/P1 corrigidos e re-verificados (hermaguard rodado de novo
|
||||
se o fix alterou >3 arquivos).
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA rodar hermaguard em código com testes quebrados (polui o review).
|
||||
- NUNCA dar "suíte passando" sem ter executado a suíte.
|
||||
- NÃO aceitar "hermaguard não achou nada" sem exigir a cobertura por classe
|
||||
(edge cases, races, rollback, schema drift).
|
||||
- NÃO reportar achado P0/P1 como resolvido sem a verificação de volta.
|
||||
|
||||
## Comandos de Verificação (executáveis)
|
||||
|
||||
```bash
|
||||
# Gate de qualidade do próprio workflow (sem regressão)
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py
|
||||
|
||||
# Testes + meta-testes (prova que o harness detecta regressão)
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_tests.py
|
||||
|
||||
# Audit OWASP de um endpoint/controller
|
||||
# (skill api-security-review) — veja a skill
|
||||
|
||||
# CVE nas deps do projeto
|
||||
# (skill dependency-cve-audit) — veja a skill
|
||||
|
||||
# Bug hunt adversarial no diff (read-only)
|
||||
# (skill hermaguard: "hermaguard this")
|
||||
```
|
||||
|
||||
## Critérios de Aceite (checklist não-regressivo)
|
||||
|
||||
- [ ] Contrato aprovado (PLAN) antes de qualquer handler.
|
||||
- [ ] BUILD com defaults seguros; `secure-coding` validado na stack.
|
||||
- [ ] SECURITY: bola/auth/injection/api-review/CVE rodados; P0/P1 resolvidos.
|
||||
- [ ] TEST: hermaguard + TDD + security-test-generator; suíte verde com
|
||||
contagem real.
|
||||
- [ ] Nenhuma skill do stack removida do arquivo.
|
||||
- [ ] Rodar `python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py`
|
||||
→ exit 0 (sem regressão).
|
||||
|
||||
## Exemplos de execução por fase (comandos reais)
|
||||
|
||||
Fase 1 — validar contrato antes de codar:
|
||||
|
||||
```bash
|
||||
# Lista de rotas planejadas (contrato em aberto)
|
||||
cat > docs/contract.md <<'EOF'
|
||||
POST /api/v1/users -> 201 | 400 | 401 | 409 | 429
|
||||
GET /api/v1/users/:id -> 200 | 404 | 403
|
||||
Erros: RFC 9457 (application/problem+json)
|
||||
EOF
|
||||
```
|
||||
|
||||
Fase 2 — build seguro (exemplo FastAPI + Pydantic):
|
||||
|
||||
```bash
|
||||
# Rodar a stack e conferir a OpenAPI gerada
|
||||
uvicorn app.main:app --reload # ou npm run dev
|
||||
curl -s localhost:8000/openapi.json | python3 -m json.tool > /tmp/openapi.json
|
||||
python3 -c "import sys,json; d=json.load(open('/tmp/openapi.json')); print('schemas:', len(d.get('components',{}).get('schemas',{})))"
|
||||
|
||||
# Validação de contrato contra a OpenAPI real
|
||||
curl -s localhost:8000/health -i | head -5 # status codes do health
|
||||
curl -s -X POST localhost:8000/api/v1/users -d '{}' -i | head -5 # 400 esperado
|
||||
```
|
||||
|
||||
Fase 3 — auditoria de segurança:
|
||||
|
||||
```bash
|
||||
# Rodar as skills de auditoria OWASP (veja cada skill p/ uso exato)
|
||||
# bola-detector: "audite rotas com :id" / auth-rbac-scaffold: "valide o fluxo de login"
|
||||
# injection-checker: "escaneie SQL/ORM" / api-security-review: "revisão OWASP do conjunto"
|
||||
# dependency-cve-audit: "audite as dependências" (skill local)
|
||||
```
|
||||
|
||||
Fase 4 — testes e bug hunt:
|
||||
|
||||
```bash
|
||||
python3 -m pytest -v # ou npm test
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py # gate do workfl
|
||||
# "hermaguard this" (bug hunt adversarial no diff)
|
||||
```
|
||||
|
||||
Gates anti-regressão (rodar junto com o fluxo):
|
||||
|
||||
```bash
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_tests.py # teste dos testes
|
||||
# verifica que o harness DETECTA regressão (mutações sempre derrubam o score)
|
||||
python3 -m pytest tests/security/ -x # se existir suíte de segurança
|
||||
```
|
||||
|
||||
## Regras duras
|
||||
|
||||
- NUNCA escrever handler antes do contrato aprovado.
|
||||
- NUNCA entregar endpoint sem passar pelas 4 fases (security + testes +
|
||||
hermaguard).
|
||||
- Rota que mexe em dado do usuário → ownership-check obrigatório (query
|
||||
escopada ao ID autenticado).
|
||||
- Tests vermelhos = fixar primeiro; hermaguard não roda em código quebrado.
|
||||
@@ -0,0 +1,309 @@
|
||||
---
|
||||
name: wf-frontend
|
||||
description: "Use p/ frontend/UI. Fluxo DESIGN→BUILD→REVIEW."
|
||||
version: 1.0.0
|
||||
author: Hermes Agent
|
||||
license: MIT
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [frontend, ui, ux, design, react, tailwind, workflow]
|
||||
---
|
||||
|
||||
# Workflow Frontend/Design
|
||||
|
||||
Orquestrador obrigatório para TODO trabalho de frontend, UI, UX ou design
|
||||
(componentes, páginas, landing, apps, re-design, design system). Processo de
|
||||
3 fases com skills fixas por fase.
|
||||
|
||||
## When to Use
|
||||
|
||||
Sempre que a tarefa envolver interface do usuário ou GERAÇÃO DE PDF:
|
||||
- Frontend/UI: criar/editar componentes React/Vue/Svelte, páginas, layouts,
|
||||
estilos, animações, acessibilidade, qualquer pedido de "design"
|
||||
- **PDF/DOCUMENTOS VISUAIS: SEMPRE via este workflow** (regra do Evandro,
|
||||
ago/2026) — NUNCA reportlab platypus raw (estoura bordas em tabelas
|
||||
longas). Usar HTML+CSS → Playwright headless (`pdf-generator`,
|
||||
`html-css-print-engineer`, `pdf-render-qa`). Design primeiro, depois
|
||||
render, depois QA visual (vision_analyze) antes de entregar.
|
||||
- Vale para apps novos e refactors.
|
||||
|
||||
## Skills do stack (carregar conforme a fase)
|
||||
|
||||
- Direção visual / anti-AI-slop: `frontend-design` (Anthropic), `web-design`,
|
||||
e locais `frontend-award-tier`, `claude-design`, `popular-web-designs`,
|
||||
`anti-ai-slop`
|
||||
- React/Next performance + composição: `vercel-react-best-practices`,
|
||||
`vercel-composition-patterns`
|
||||
- Motion: `animate` (emilkowalski)
|
||||
- Bug hunting: `hermaguard` (pre-scan + 3 agentes adversariais; read-only)
|
||||
- Qualidade de texto/UI copy: `avoid-ai-writing` (remove AI-isms de microcopy,
|
||||
textos de componente, a11y labels, README de frontend)
|
||||
- Esboço rápido / docs visuais: `sketch`, `design-md` (locais)
|
||||
- PDF de qualidade: `pdf-generator` (HTML+CSS LaTeX → Playwright),
|
||||
`html-css-print-engineer`, `pdf-render-qa` (QA), `professional-pdf-director`,
|
||||
`pdf-visual-designer` — todo PDF passa por aqui
|
||||
|
||||
## Fase 1 — DESIGN (decidir antes de codar)
|
||||
|
||||
1. Carregar `frontend-design` + `frontend-award-tier` + `anti-ai-slop`.
|
||||
2. Definir direção visual explícita: paleta, tipografia, espaçamento,
|
||||
densidade, dark/light — NUNCA gerar "default AI slop".
|
||||
3. Se for re-design/variação: `claude-design`/`popular-web-designs` para
|
||||
basear em design systems reais (Stripe/Linear/Vercel) e fugir do genérico.
|
||||
4. Documentar decisões em `DESIGN.md` (padrão `design-md` se aplicável).
|
||||
5. Parar e validar a direção com o usuário ANTES de implementar.
|
||||
6. VERIFICAR: rodar `avoid-ai-writing` em detect no DESIGN.md (0 AI-isms) e
|
||||
confirmar que a direção está registrada (paleta + tipografia + density)
|
||||
antes de codar.
|
||||
7. VERIFICAR (gate visual): se for PDF/artefato visual, renderizar um
|
||||
rascunho e inspecionar com `vision_analyze` ANTES de avançar — validar
|
||||
que a direção visual de fato foi aplicada e nada está fora de margem.
|
||||
8. CHECKPOINT: gravar decisões (paleta final, fonte, density) num
|
||||
`DESIGN.md` com versionamento, para as fases seguintes referenciarem.
|
||||
9. VERIFICAR (comandos de direção): conferir que `DESIGN.md` existe e tem
|
||||
conteúdo — `wc -l DESIGN.md` > 5; e que as cores/fontes estão anotadas
|
||||
(`grep -c "paleta\|fonte\|spacing" DESIGN.md` >= 3).
|
||||
10. VERIFICAR (anti-slop real): rodar o `anti-ai-slop` no direção proposta
|
||||
antes de mostrar ao usuário — detectar gradiente/glassmorphism
|
||||
prematuramente economiza retrabalho.
|
||||
11. VERIFICAR (comandos de design): validar a direção também contra a
|
||||
ferramenta de design usada — `npx`/CLI do design system (ex:
|
||||
`pnpm tailwindcss` se Tailwind) confirmando tokens aplicáveis; e
|
||||
checar com `grep -rn "palette\|tokens\|--color" DESIGN.md` que os
|
||||
tokens ficaram declarados.
|
||||
|
||||
**Checklist da fase 1 (validar todos antes de seguir):**
|
||||
- [ ] Direção visual definida e DOCUMENTADA (paleta, tipografia, spacing).
|
||||
- [ ] Anti-slop: nenhum padrão "default IA" (gradiente, glassmorphism, ícones genéricos).
|
||||
- [ ] `DESIGN.md` existe e está aprovado pelo usuário.
|
||||
- [ ] `avoid-ai-writing` detect = 0 no DESIGN.md.
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA pular a definição de direção visual "só para ver como fica".
|
||||
- NUNCA aprovar design sem a confirmação explícita do usuário.
|
||||
- NÃO misturar 2 design systems na mesma tela; se for variação, basear em um só.
|
||||
|
||||
## Fase 2 — BUILD (implementar com padrões de produção)
|
||||
|
||||
1. Carregar `vercel-react-best-practices` + `vercel-composition-patterns`
|
||||
(React) — aplicar regras de performance (waterfalls, bundle, re-renders)
|
||||
e composição (compound components, sem boolean-prop explosion).
|
||||
2. Componentes acessíveis por padrão (WCAG): semântica HTML, foco,
|
||||
contraste — sem depender de ARIA desnecessário.
|
||||
3. Animações só quando agregam: `animate` — propósito, duração, easing,
|
||||
reduzir motion para prefers-reduced-motion.
|
||||
4. Responsivo mobile-first; estados vazios/loading/erro em todo fluxo.
|
||||
5. VERIFICAR: rodar build + lint incrementalmente a cada componente
|
||||
(npm/pnpm build) e `vercel-react-best-practices` como checklist de perf
|
||||
durante o build — não deixar para o fim.
|
||||
6. VERIFICAR (a11y atômica): para cada componente novo, conferir semântica
|
||||
HTML, gerenciamento de foco e contraste ANTES de considerar pronto —
|
||||
acessibilidade é parte do build, não polimento final.
|
||||
7. VERIFICAR (perf real): medir com DevTools/Lighthouse por tela-chave
|
||||
(LCP, INP, CLS) e registrar os números no relatório de perf.
|
||||
8. VERIFICAR (composição limpa): `grep -rn "is[A-Z]\|show[A-Z]" src/components`
|
||||
para caçar boolean-prop explosion (deve ser 0 ou poucos intencionais);
|
||||
se houver, refatorar para compound components.
|
||||
9. VERIFICAR (animações justificadas): para cada `animate`/motion adicionada,
|
||||
conferir com `grep -rn "animate\|transition\|motion" src/` que há propósito
|
||||
(hover/estado/entrada) — animação decorativa sem função = cortar.
|
||||
10. VERIFICAR (limpeza): `git status` e `git diff --stat` antes de fechar —
|
||||
nada de arquivo órfão/debug commitado.
|
||||
11. VERIFICAR (critério de aceite do componente): cada componente novo
|
||||
confirma o critério definido na Fase 1 (estado correto, a11y ok, perf
|
||||
ok) antes de passar para o próximo — validar item a item do checklist.
|
||||
12. VERIFICAR (comandos de estado): conferir que loading/erro/vazio são
|
||||
tratados em cada fluxo — `grep -rn "loading\|isLoading\|error\|empty" src/`
|
||||
para provar a presença nos componentes que interagem com dados.
|
||||
13. VERIFICAR (anti-padrão visual final): percorrer os componentes com
|
||||
`anti-ai-slop` de novo ao fechar a fase — sombra/glassmorphism que
|
||||
"escapou" no scroll é regressão de qualidade.
|
||||
14. VERIFICAR (critério de aceite): validar que cada item do checklist da
|
||||
fase está marcado (sem checkbox em branco) antes de declarar BUILD
|
||||
concluído.
|
||||
|
||||
**Checklist da fase 2 (validar antes da REVIEW):**
|
||||
- [ ] Build e lint verdes (`npm run build` / `npx tsc --noEmit`).
|
||||
- [ ] Componentes acessíveis (semântica HTML, foco, contraste) — auditar com
|
||||
`frontend-design`/a11y antes de considerar pronto.
|
||||
- [ ] Estados vazios/loading/erro presentes em todo fluxo.
|
||||
- [ ] Animações com propósito + `prefers-reduced-motion` respeitado.
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA usar `any`/forçar cast em TS para "fazer passar".
|
||||
- NUNCA animar sem propósito — animação decorativa gratuita é anti-padrão.
|
||||
- NÃO implementar responsivo só no final; mobile-first desde o início.
|
||||
- NÃO duplicar lógica de estado em vários componentes (compor, não copiar).
|
||||
|
||||
## Fase 3 — REVIEW (verificar antes de entregar)
|
||||
|
||||
1. `anti-ai-slop` sobre o resultado (gradientes-texto, glassmorphism,
|
||||
sombras genéricas, layout previsível).
|
||||
2. `avoid-ai-writing` sobre textos entregues ao usuário: microcopy, labels,
|
||||
empty states, mensagens de erro, README/descrições — remover AI-isms
|
||||
(em-dash em excesso, "robust", "seamless", "let's dive in", etc).
|
||||
3. `hermaguard` no diff de frontend (JS/TS/TSX/CSS): caça bugs adiversariais
|
||||
no código produzido (lógica de estado, efeitos, a11y que quebra).
|
||||
4. `vercel-react-best-practices` como checklist de perf (LCP/INP/CLS,
|
||||
bundle, imagem, Suspense).
|
||||
5. Rodar build + lint + testes do projeto; corrigir o que quebrar.
|
||||
6. Relatório curto: o que foi decidido na Fase 1, entregue na 2, verificado
|
||||
na 3.
|
||||
7. VERIFICAR (regressão visual): se houver, comparar screenshots do antes
|
||||
vs depois (ou `vision_analyze` no render) para garantir que nada quebrou
|
||||
de layout.
|
||||
8. VERIFICAR (não-regressão QA): rodar `test_quality.py` (gate do workflow)
|
||||
e conferir que o score do stack não caiu.
|
||||
9. VERIFICAR (hermaguard re-audit): se o REVIEW mudou >3 arquivos, rodar
|
||||
`hermaguard` no novo diff antes de fechar.
|
||||
10. VERIFICAR (bundle/perf real): rodar `npm run build` e conferir tamanho
|
||||
dos chunks (`ls -lh dist/static/*.js`), anotar LCP/INP/CLS se houver
|
||||
Lighthouse.
|
||||
11. VERIFICAR (html válido): para PDF/páginas, validar o HTML antes do
|
||||
render — `python3 -c "from html.parser import HTMLParser; ...
|
||||
"` (ou parser disponível) e `grep -c "</t" arquivo.html` = 0 (sem tag
|
||||
truncada).
|
||||
12. VERIFICAR (comandos de acessibilidade): rodar auditoria de a11y no
|
||||
render final — `npx @axe-core/cli http://localhost:PORT` (se houver
|
||||
dev server) ou `pa11y`/equivalente; anotar violações sérias.
|
||||
13. VERIFICAR (contraste verificado): para paleta dark/light, conferir
|
||||
contraste com ferramenta (ex: `npx contrast-checker` ou manual) —
|
||||
textos principais >= 4.5:1.
|
||||
|
||||
**Checklist da fase 3 (gate de entrega):**
|
||||
- [ ] `anti-ai-slop` aplicado e sem ressalvas no resultado final.
|
||||
- [ ] `avoid-ai-writing` detect = 0 em microcopy/labels/errors/README.
|
||||
- [ ] `hermaguard` rodado no diff (0 findings CRITICAL/HIGH pendentes).
|
||||
- [ ] `vercel-react-best-practices` auditado (LCP/INP/CLS, bundle, imagem).
|
||||
- [ ] Build + lint + testes verdes com contagem real.
|
||||
- [ ] Para PDF: renderização via Playwright + `vision_analyze` sem corte.
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA dar como entregue com build vermelho.
|
||||
- NUNCA ignorar finding CRITICAL/HIGH do hermaguard "para depois".
|
||||
- NÃO pular o QA visual de PDF (conteúdo cortado nas bordas = entrega quebrada).
|
||||
- NÃO entregar relatório sem os itens do checklist marcados.
|
||||
|
||||
## Comandos de Verificação (executáveis)
|
||||
|
||||
Gate de qualidade do stack (rodar SEMPRE antes de entregar):
|
||||
|
||||
```bash
|
||||
# 1) Não-regressão: valida que os workflows continuam íntegros
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py
|
||||
|
||||
# 2) Testes-dos-testes: prova que o harness detecta regressão
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_tests.py
|
||||
```
|
||||
|
||||
QA visual de PDF — renderizar páginas e inspecionar bordas (nada cortado):
|
||||
|
||||
```bash
|
||||
cd ~/.hermes/skills/productivity/pdf/scripts
|
||||
python pdf_page_image.py /caminho/do.pdf --pages 1-3 --dpi 150 --out-dir /tmp/qa
|
||||
# depoiss: vision_analyze em cada PNG — margens ok, sem truncamento
|
||||
```
|
||||
|
||||
Qualidade de texto (microcopy, labels, README) — auditoria de AI-isms:
|
||||
|
||||
```bash
|
||||
# detect (só lista) — passa 2 arquivos para comparar original vs limpo
|
||||
node ~/.hermes/skills/avoid-ai-writing/detector/validate.js ui-copy.md ui-copy-limp.md
|
||||
|
||||
# ou debaixo do wf: pedir "roda o avoid-ai no README" (modo detect/rewrite)
|
||||
```
|
||||
|
||||
Bug hunt adversarial no diff (comandos da skill hermaguard):
|
||||
|
||||
```bash
|
||||
# gatilho: "hermaguard this" / "adversarial review" / "bug hunt this"
|
||||
# gera relatório em /tmp/hermaguard/hermaguard-<ts>.md + .json
|
||||
```
|
||||
|
||||
Performance React/Next — checklist durante o build:
|
||||
|
||||
```bash
|
||||
npm run build # ou pnpm build — verificar warnings de bundle chunk
|
||||
npx tsc --noEmit # typecheck limpo
|
||||
npm run lint # sem erros
|
||||
```
|
||||
|
||||
Resumo do fluxo (mapa de navegação do workflow):
|
||||
|
||||
```text
|
||||
[Fase 1 DESIGN] -> frontend-design + anti-ai-slop -> DESIGN.md aprovado
|
||||
[Fase 2 BUILD] -> vercel patterns + animate -> build/lint verdes
|
||||
[Fase 3 REVIEW] -> avoid-ai + hermaguard + perf -> QA visual (PDF)
|
||||
[Gate final] -> test_quality.py exit 0
|
||||
```
|
||||
|
||||
## Critérios de Aceite (checklist não-regressivo)
|
||||
|
||||
- [ ] DESIGN.md com direção visual aprovada (Fase 1 validada pelo usuário).
|
||||
- [ ] BUILD com perf/a11y; build e lint verdes a cada componente.
|
||||
- [ ] REVIEW: anti-ai-slop + avoid-ai-writing + hermaguard + perf checklist.
|
||||
- [ ] Para PDF: renderização via Playwright e QA visual (vision_analyze)
|
||||
sem conteúdo cortado nas bordas.
|
||||
- [ ] Nenhuma skill do stack removida do arquivo.
|
||||
- [ ] Rodar `python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py`
|
||||
→ exit 0 (sem regressão).
|
||||
|
||||
## Exemplos de execução por fase (comandos reais)
|
||||
|
||||
Fase 1 — direção visual documentada:
|
||||
|
||||
```bash
|
||||
cat > DESIGN.md <<'EOF'
|
||||
# Direção visual
|
||||
Paleta: fundo #ffffff, acento #1e40af, texto #1a1a1a
|
||||
Tipografia: serif corpo (Noto Serif/Georgia), mono p/ código
|
||||
Density: padrão; dark/light: light first
|
||||
EOF
|
||||
```
|
||||
|
||||
Fase 2 — build e perf:
|
||||
|
||||
```bash
|
||||
npm run build # ou pnpm build
|
||||
npx tsc --noEmit # typecheck
|
||||
npm run lint # sem erros
|
||||
# "audite a perf" (vercel-react-best-practices)
|
||||
```
|
||||
|
||||
Fase 3 — review/QA:
|
||||
|
||||
```bash
|
||||
# "rode o anti-ai-slop" / "rode o avoid-ai nos textos"
|
||||
# "hermaguard this" (bug hunt no diff de frontend)
|
||||
```
|
||||
|
||||
Para PDF (regra do Evandro — SEMPRE este caminho):
|
||||
|
||||
```bash
|
||||
# HTML+CSS -> Playwright headless
|
||||
~/.hermes/venvs/latebra/bin/python /tmp/gen-pdf.py # ver pdf-generator
|
||||
cd ~/.hermes/skills/productivity/pdf/scripts
|
||||
python pdf_page_image.py saida.pdf --pages 1-N --dpi 150 --out-dir /tmp/qa
|
||||
# depois vision_analyze em cada PNG: NENHUM conteúdo cortado nas bordas
|
||||
|
||||
# QA de perfil visual (se tiver origem de design)
|
||||
node ~/.hermes/skills/avoid-ai-writing/detector/validate.js ui-copy.md ui-limp.md
|
||||
```
|
||||
|
||||
Verificação de integridade do workflow (gate anti-regressão):
|
||||
|
||||
```bash
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py # não-regressão
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_tests.py # teste dos testes
|
||||
# "hermaguard this" -> bug hunt adversarial se o diff >3 arquivos
|
||||
# "rode o anti-ai-slop" -> antes de entregar
|
||||
```
|
||||
|
||||
## Regras duras
|
||||
|
||||
- NUNCA pular a Fase 1 (consulta de design) direto para código.
|
||||
- NUNCA entregar UI sem passar pelo `anti-ai-slop` + `avoid-ai-writing` +
|
||||
`hermaguard` + build verde.
|
||||
- Dúvida de stack (Vite vs Next, Tailwind vs CSS) → decidir na Fase 1 com
|
||||
aprovação do usuário, não no meio do build.
|
||||
@@ -0,0 +1,209 @@
|
||||
---
|
||||
name: wf-security-review
|
||||
description: "Code review de segurança (front+back). OSV/NVD + OWASP."
|
||||
version: 1.0.0
|
||||
author: Hermes Agent
|
||||
license: MIT
|
||||
platforms: [linux, macos, windows]
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [security, code-review, cve, owasp, sast, sca, workflow, devsecops]
|
||||
---
|
||||
|
||||
# Workflow Security Code Review (front + backend)
|
||||
|
||||
Orquestrador obrigatório para todo code review de segurança — frontend E
|
||||
backend. Cobre: revisão de código (OWASP), vulnerabilidades conhecidas em
|
||||
dependências, E consulta de NOVAS vulnerabilidades nos lugares certos
|
||||
(OSV.dev, NVD, GitHub Advisory) para que o review esteja sempre atualizado,
|
||||
não preso ao cutoff de treino do modelo.
|
||||
|
||||
## When to Use
|
||||
|
||||
- "revisa a segurança desse código/PR/diff" (front ou back)
|
||||
- "escaneia dependências por CVEs" / "alguma lib vulnerável?"
|
||||
- "tem vulnerabilidade nova conhecida pra X?" (consulta de atualização)
|
||||
- "audita auth/API/injeção" / "procura segredos commitados"
|
||||
- QUALQUER review de merge que mexa em dado sensível ou rota nova
|
||||
- Pré-commit ou pré-deploy como etapa de segurança
|
||||
|
||||
## Skills do stack (3 principais + auxiliares)
|
||||
|
||||
**As 3 skills de segurança atuais (instaladas de fontes primárias):**
|
||||
1. `safedeps` (Jeneidi) — grounding em OSV.dev em tempo real: consulta
|
||||
`package@version` e traz CVE com severidade e fix. Cobre o gap de o
|
||||
modelo só conhecer vulns até o cutoff. CLI: `check_deps.py`.
|
||||
2. `sca-audit` (OWASP secure-agent-playbook) — SCA (Supply Chain Analysis)
|
||||
de dependências com análise de alcance (reachability), CWE mapping.
|
||||
3. `code-review-security` (OWASP secure-agent-playbook) — code review de
|
||||
segurança sistemático mapeado a OWASP Top 10 + ASVS.
|
||||
|
||||
**Auxiliares (carregar por contexto):**
|
||||
- `secrets-scan` (OWASP) — busca credenciais/API keys no código e git history
|
||||
- `api-security-review` + `bola-detector` + `auth-rbac-scaffold` +
|
||||
`injection-checker` (OWASP/API) — revisão de API
|
||||
- `web-security-review` (OWASP) — web app OWASP Top 10
|
||||
- `cve-triage` + `patch-prioritization` (UnitOne/SecuritySkills) — priorizar
|
||||
CVE por CVSS 4.0 / EPSS / CISA KEV
|
||||
- Locais: `dependency-cve-audit`, `hermaguard` (caça bugs adversariais),
|
||||
`security-threat-model`
|
||||
|
||||
## Fase 1 — SCOPE (definir alvo antes de auditar)
|
||||
|
||||
1. Identificar o que está no escopo: diff/PR, arquivos, front, back, ambos.
|
||||
2. Registrar stack do projeto (linguagens, frameworks, package managers,
|
||||
se há lockfile: package-lock.json / requirements.txt / go.mod / etc).
|
||||
3. Rodar o código? Identificar se há ambiente local testável.
|
||||
4. VERIFICAR: `git status` + `git diff --stat` para delimitar o alvo real.
|
||||
5. Checkpoint: confirmar escopo com o usuário antes de gastar auditoria.
|
||||
|
||||
**Checklist da fase 1:**
|
||||
- [ ] Escopo delimitado (arquivos/diff/PR)
|
||||
- [ ] Stack e lockfiles identificados
|
||||
- [ ] Alvo confirmado
|
||||
|
||||
## Fase 2 — HUNT (vulnerabilidades conhecidas — dimensão de dependências)
|
||||
|
||||
1. `sca-audit` — scan de dependências com análise de alcance; mapear CVEs
|
||||
por severidade e reachable/unreachable.
|
||||
2. `safedeps` — para cada dependência-chave do manifest, consultar OSV.dev:
|
||||
`python3 ~/.hermes/skills/safedeps/check_deps.py "pkg@version"` (ou via
|
||||
manifest completo) — traz CVE reais com fix (o modelo NÃO sabe CVE nova
|
||||
do cutoff pra frente; o OSV.dev sim).
|
||||
3. `cve-triage` / `patch-prioritization` — priorizar achados por
|
||||
CVSS 4.0 / EPSS / CISA KEV quando disponível.
|
||||
4. `dependency-cve-audit` (local) — varredura das deps do projeto atual.
|
||||
5. VERIFICAR: consolidar lista de CVE com severidade + versão afetada +
|
||||
versão fixa; separar reachable (devem ser bloqueantes) de non-reachable
|
||||
(registrar como risco residual).
|
||||
6. CHECKPOINT: apresentar sumário de CVE antes de partir para o code review.
|
||||
|
||||
**Comandos úteis:**
|
||||
```bash
|
||||
python3 ~/.hermes/skills/safedeps/check_deps.py "[email protected]" # 1 pkg
|
||||
python3 ~/.hermes/skills/safedeps/check_deps.py -f package-lock.json # manifest
|
||||
# veja a skill sca-audit p/ reachability; cve-triage p/ priorização
|
||||
```
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA afirmar "sem CVE" sem ter CONSULTADO OSV.dev (memória do modelo é
|
||||
congelada no cutoff).
|
||||
- NÃO tratar CVE de dependência transitiva não-reachable como crítica igual
|
||||
a reachable — reportar com nuance.
|
||||
- NUNCA rodar scan em lockfile sem conferir o package manager certo.
|
||||
|
||||
**Comandos reais (Fase 2):**
|
||||
```bash
|
||||
python3 ~/.hermes/skills/safedeps/check_deps.py "[email protected]"
|
||||
python3 ~/.hermes/skills/safedeps/check_deps.py -f package-lock.json
|
||||
# alternatives: npm audit --json / pip-audit -r requirements.txt / trivy fs .
|
||||
```
|
||||
|
||||
## Fase 3 — CONSULT (novas vulnerabilidades — atualização contínua)
|
||||
|
||||
O objetivo é responder "há vulnerabilidade NOVA que eu não conheço?" — o
|
||||
modelo só sabe até o cutoff; consultar fontes vivas:
|
||||
|
||||
1. OSV.dev (API aberta, sem key) — já coberto na Fase 2 via safedeps.
|
||||
2. GitHub Advisory Database — via `gh api`:
|
||||
`gh api graphql -f query='{securityAdvisories(first:10, orderBy:{field:PUBLISHED_AT,direction:DESC}){nodes{ghsaId,summary,severity,publishedAt}}}'
|
||||
3. NVD — via API (key opcional): consultar CPE do stack ou CVEs recentes do
|
||||
framework em uso (`curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=..."`).
|
||||
4. Registros de framework (ex: changelog/security de Next.js, Express,
|
||||
NestJS, FastAPI) — advisories recentes do framework do projeto.
|
||||
5. VERIFICAR: para LIB versão X e FRAMEWORK Y, registrar qual fonte foi
|
||||
consultada e a data — sem "não tem" sem fonte.
|
||||
6. CHECKPOINT: se alguma vuln nova afeta o stack do projeto, tratar como
|
||||
finding HIGH e sugerir upgrade.
|
||||
|
||||
**Comandos úteis:**
|
||||
```bash
|
||||
gh api graphql -f query='{securityAdvisories(first:10, orderBy:{field:PUBLISHED_AT,direction:DESC}){nodes{ghsaId,summary,severity,publishedAt}}}'
|
||||
curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=nextjs&resultsPerPage=10"
|
||||
# OSV batch: curl -s -X POST https://api.osv.dev/v1/querybatch -d '@manifests.json'
|
||||
```
|
||||
|
||||
**Anti-padrões desta fase:**
|
||||
- NUNCA responder "não tem vulnerabilidade nova" sem citar fonte viva + data.
|
||||
- NÃO confiar no cutoff do modelo para saber CVE recente — sempre consultar.
|
||||
- NÃO esquecer de incluir data da consulta (revisão vence se ficar velho).
|
||||
|
||||
## Fase 4 — CODE REVIEW (front + backend, OWASP)
|
||||
|
||||
Frontend (`web-security-review` + `code-review-security`):
|
||||
1. XSS/injeção em renderização (dangerouslySetInnerHTML, v-html, innerHTML).
|
||||
2. Exposição de segredos no client (API keys, tokens em bundle).
|
||||
3. Containers: loads, links com user input, cookies httpOnly/secure.
|
||||
4. `secrets-scan` — credenciais no código e git history.
|
||||
5. Auth de frontend: fluxo de tokens, storage inseguro (localStorage p/ JWT).
|
||||
|
||||
Backend (`code-review-security` + `api-security-review` + `bola-detector` +
|
||||
`auth-rbac-scaffold` + `injection-checker`):
|
||||
1. AuthN/AuthZ: rotas sem auth, IDOR/BOLA (`bola-detector`), RBAC.
|
||||
2. Input validation: SQLi, XSS, command injection, SSRF, path traversal
|
||||
(`injection-checker`).
|
||||
3. Segredos: env vars, nunca logar senha/token.
|
||||
4. Rate limit, erros sem vazar stack trace, CORS correto.
|
||||
5. `hermaguard` (opcional) p/ caça adversarial de bugs no mesmo diff.
|
||||
6. VERIFICAR: para cada rota com `:id`, rodar `bola-detector` de novo (IDOR
|
||||
é o achado nº1 em API) e para cada query, `injection-checker`.
|
||||
7. VERIFICAR: rodar `secrets-scan` no diff E git history antes de fechar —
|
||||
credencial commitada em algum commit antigo ainda vaza.
|
||||
8. VERIFICAR: conferir erros sem stack trace (grep por exceptions/console no
|
||||
cliente) e CORS/headers (`grep -rn "access-control\|csp"`).
|
||||
9. VERIFICAR: `grep -rn "localStorage\|sessionStorage" src/` — nenhum JWT
|
||||
sensível em storage de frontend (usar httpOnly cookie).
|
||||
10. VERIFICAR: confirmar rate limit em rotas de escrita (`grep -rniE "limiter|rate"`) e que respostas não vazam caminho interno.
|
||||
|
||||
**Output por finding:** Severidade (Critical/High/Med/Low) + CWE + OWASP ref +
|
||||
Arquivo:linha + Evidência + Remediação.
|
||||
|
||||
**Anti-padrões desta fase (front + back):**
|
||||
- NUNCA approve sem reportar achado de AuthN/AuthZ ou injection como mínimo.
|
||||
- Padrão de coerência — NÃO misturar "parece ok" com achado sem evidência.
|
||||
- NÃO confundir "não achei com grep" com "não existe" — checar fluxo inteiro.
|
||||
- NÃO focar só no front quando o fix toca o back (IDOR/BOLA vive no back).
|
||||
|
||||
**Comandos de auditoria (Fase 4):**
|
||||
```bash
|
||||
# segredos: busca em código e git history
|
||||
grep -rniE "(api[_-]?key|secret|password|token|bearer)" src/ | grep -v node_modules
|
||||
git log -p --all -S "sk-" --oneline | head # chave vazada em commit antigo
|
||||
# headers/CORS/rate limit
|
||||
grep -rniE "access-control|content-security-policy" src/
|
||||
grep -rniE "ratelimit|rate_limit|limiter|express-rate" src/
|
||||
python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py # gate
|
||||
```
|
||||
|
||||
## Fase 5 — REPORT + GATE (entregar e decidir)
|
||||
|
||||
1. Consolidar tudo: sumário (nº por severidade), findings detalhados,
|
||||
tabela de CVE com fonte/estado/reachable/fix, e status "consulta de
|
||||
atualização feita em <data> via <fontes>".
|
||||
2. GATE: Critical/High reachable → BLOQUEAR merge até corrigir. Medium →
|
||||
tratar no próximo ciclo. Low/residual → registrar risco aceito.
|
||||
3. Re-auditar após fixes: re-rodar as checagens que acusaram P0/P1.
|
||||
4. VERIFICAR: `python3 ~/.hermes/skills/software-development/wf-qa/test_quality.py`
|
||||
(gate não-regressivo do stack de workflows).
|
||||
5. Relatório final em markdown (report.md) + resumo em chat.
|
||||
6. VERIFICAR (comandos de report): gerar `security-report.md` com
|
||||
`find . -maxdepth 2 -name "*.md" | sort` conferindo artefatos, e
|
||||
`grep -c "CVE-" security-report.md` para ter contagem explícita no doc.
|
||||
7. VERIFICAR (data da consulta): `grep -i "data da consulta\|20[2-9][0-9]-" security-report.md` — sem revisão sem carimbo de data (ela vence).
|
||||
|
||||
**Checklist de entrega:**
|
||||
- [ ] Os 3 pilares rodados: safedeps (OSV), sca-audit, code-review-security.
|
||||
- [ ] Consulta de novas vulns feita em fonte viva (OSV/GH Advisory/NVD) com data.
|
||||
- [ ] Findings com CWE + OWASP + evidência + remediação.
|
||||
- [ ] GATE aplicado (block/allow) por severidade/reachability.
|
||||
- [ ] Nenhuma skill do stack removida; test_quality.py passando.
|
||||
|
||||
## Regras duras
|
||||
|
||||
- NUNCA afirmar "sem vulnerabilidades" sem consultar OSV.dev/GH Advisory
|
||||
(modelo tem cutoff; fonte viva não).
|
||||
- NUNCA reportar CVE sem incluir versão afetada + versão fixa.
|
||||
- NUNCA blocker Critical/High reachable "para depois" — bloquear merge.
|
||||
- NUNCA logar/expor segredo durante o review (nem no relatório).
|
||||
- Re-auditar sempre que o fix tocar >3 arquivos ou mudar dependência.
|
||||
- SQL/queries: sempre parâmetros posicionais, nunca concatenação de input.
|
||||
Reference in new issue
Block a user