@fontdata/ai-harness 3.3.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +2 -2
- package/README.md +22 -2
- package/dist/cli.js +6 -0
- package/dist/doctor/checks.js +27 -4
- package/dist/update/update.js +3 -1
- package/dist/versao/command.js +424 -0
- package/dist/versao/config.js +325 -0
- package/dist/versao/detectar.js +332 -0
- package/dist/versao/diff.js +58 -0
- package/dist/versao/extratores/comum.js +41 -0
- package/dist/versao/extratores/csproj.js +28 -0
- package/dist/versao/extratores/dproj.js +149 -0
- package/dist/versao/extratores/index.js +26 -0
- package/dist/versao/extratores/json.js +118 -0
- package/dist/versao/extratores/pubspec.js +15 -0
- package/dist/versao/extratores/pyproject.js +26 -0
- package/dist/versao/extratores/regex.js +20 -0
- package/dist/versao/extratores/versoes-txt.js +29 -0
- package/dist/versao/formato.js +67 -0
- package/dist/versao/git.js +91 -0
- package/dist/versao/texto.js +16 -0
- package/dist/versao/tipos.js +1 -0
- package/package.json +1 -1
- package/templates/CLAUDE.md +1 -0
- package/templates/catalog.json +2 -1
- package/templates/commands/publicar-release.md +93 -0
- package/templates/commands/versao.md +153 -116
- package/templates/rules/comentarios.md +3 -1
- package/templates/skills/evoluir-harness/SKILL.md +3 -2
- package/templates/skills/evoluir-harness/references/versao.md +70 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
const TIPOS_PATCH = new Set(['fix', 'chore', 'refactor', 'docs', 'style', 'perf', 'test', 'build', 'ci']);
|
|
3
|
+
const SEP_CAMPO = '\x1f';
|
|
4
|
+
const SEP_COMMIT = '\x1e';
|
|
5
|
+
function rodarGit(raiz, args) {
|
|
6
|
+
const r = spawnSync('git', args, { cwd: raiz, encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 });
|
|
7
|
+
if (r.error)
|
|
8
|
+
throw new Error(`Não foi possível rodar o git: ${r.error.message}`);
|
|
9
|
+
if (r.status !== 0)
|
|
10
|
+
throw new Error(`git ${args.join(' ')} falhou: ${r.stderr.trim()}`);
|
|
11
|
+
return r.stdout;
|
|
12
|
+
}
|
|
13
|
+
function escaparRegex(texto) {
|
|
14
|
+
return texto.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
15
|
+
}
|
|
16
|
+
function regexDoModelo(modelo, app) {
|
|
17
|
+
if (modelo.split('{versao}').length !== 2) {
|
|
18
|
+
throw new Error(`O modelo de tag "${modelo}" precisa ter exatamente um {versao}.`);
|
|
19
|
+
}
|
|
20
|
+
if (modelo.includes('{app}') && !app) {
|
|
21
|
+
throw new Error(`O modelo de tag "${modelo}" usa {app}, mas nenhum app foi informado.`);
|
|
22
|
+
}
|
|
23
|
+
const literal = modelo.split('{versao}').map((parte) => escaparRegex(parte.replaceAll('{app}', app ?? '')));
|
|
24
|
+
return new RegExp(`^${literal[0]}(\\d+(?:\\.\\d+)*)${literal[1]}$`);
|
|
25
|
+
}
|
|
26
|
+
function compararVersoes(a, b) {
|
|
27
|
+
const sa = a.split('.').map(Number);
|
|
28
|
+
const sb = b.split('.').map(Number);
|
|
29
|
+
for (let i = 0; i < Math.max(sa.length, sb.length); i++) {
|
|
30
|
+
const diferenca = (sa[i] ?? 0) - (sb[i] ?? 0);
|
|
31
|
+
if (diferenca !== 0)
|
|
32
|
+
return diferenca;
|
|
33
|
+
}
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Acha a tag de maior versão alcançável do HEAD que casa com o modelo (ex.: `V{versao}`, `{app}-v{versao}`).
|
|
38
|
+
* Retags com sufixo `-N` não casam, porque `{versao}` só aceita segmentos numéricos separados por ponto.
|
|
39
|
+
* Sem tag, a base é o primeiro commit e `primeiroRelease` fica true.
|
|
40
|
+
*/
|
|
41
|
+
export function acharTagBase(raiz, modelo, app) {
|
|
42
|
+
const regex = regexDoModelo(modelo, app);
|
|
43
|
+
let melhor = null;
|
|
44
|
+
for (const tag of rodarGit(raiz, ['tag', '--merged', 'HEAD']).split('\n')) {
|
|
45
|
+
const versao = regex.exec(tag.trim())?.[1];
|
|
46
|
+
if (!versao)
|
|
47
|
+
continue;
|
|
48
|
+
if (!melhor || compararVersoes(versao, melhor.versao) > 0)
|
|
49
|
+
melhor = { tag: tag.trim(), versao };
|
|
50
|
+
}
|
|
51
|
+
if (melhor)
|
|
52
|
+
return { ...melhor, base: melhor.tag, primeiroRelease: false };
|
|
53
|
+
const primeiro = rodarGit(raiz, ['rev-list', '--max-parents=0', 'HEAD']).trim().split('\n').at(-1) ?? '';
|
|
54
|
+
return { tag: null, versao: null, base: primeiro, primeiroRelease: true };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Commits de `base..HEAD`, do mais novo ao mais antigo. Com `primeiroRelease`, lista todo o histórico do HEAD,
|
|
58
|
+
* incluindo o primeiro commit. Com `caminhos`, só os commits que tocam esses caminhos.
|
|
59
|
+
*/
|
|
60
|
+
export function listarCommits(raiz, base, caminhos, primeiroRelease = false) {
|
|
61
|
+
const intervalo = primeiroRelease ? 'HEAD' : `${base}..HEAD`;
|
|
62
|
+
const args = ['log', `--format=%H${SEP_CAMPO}%s${SEP_CAMPO}%b${SEP_COMMIT}`, intervalo];
|
|
63
|
+
if (caminhos?.length)
|
|
64
|
+
args.push('--', ...caminhos);
|
|
65
|
+
return rodarGit(raiz, args)
|
|
66
|
+
.split(SEP_COMMIT)
|
|
67
|
+
.map((bloco) => bloco.replace(/^\n+/, ''))
|
|
68
|
+
.filter((bloco) => bloco.trim())
|
|
69
|
+
.map((bloco) => {
|
|
70
|
+
const [hash = '', titulo = '', corpo = ''] = bloco.split(SEP_CAMPO);
|
|
71
|
+
return { hash: hash.trim(), titulo: titulo.trim(), corpo: corpo.trim() };
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/** `feat` → minor; outro tipo semântico conhecido → patch. Mudança incompatível só gera aviso, nunca major. */
|
|
75
|
+
export function classificarBump(commits) {
|
|
76
|
+
let tipo = 'nenhum';
|
|
77
|
+
const avisos = [];
|
|
78
|
+
for (const commit of commits) {
|
|
79
|
+
const casamento = /^(\w+)(?:\([^)]*\))?(!)?:/.exec(commit.titulo);
|
|
80
|
+
const tipoCommit = casamento?.[1]?.toLowerCase();
|
|
81
|
+
if (tipoCommit === 'feat')
|
|
82
|
+
tipo = 'minor';
|
|
83
|
+
else if (tipoCommit && TIPOS_PATCH.has(tipoCommit) && tipo === 'nenhum')
|
|
84
|
+
tipo = 'patch';
|
|
85
|
+
if (casamento?.[2] || /^BREAKING[ -]CHANGE:?/m.test(commit.corpo)) {
|
|
86
|
+
avisos.push(`O commit ${commit.hash.slice(0, 7)} "${commit.titulo}" declara mudança incompatível; ` +
|
|
87
|
+
'o bump calculado não passa de minor. Se for o caso, peça o major explicitamente.');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { tipo, avisos };
|
|
91
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
/** Lê o arquivo como bytes, sem decodificar; o EOL é o da primeira quebra (LF se não houver). */
|
|
3
|
+
export function lerTexto(caminho) {
|
|
4
|
+
const conteudo = readFileSync(caminho);
|
|
5
|
+
const bom = conteudo.length >= 3 && conteudo[0] === 0xef && conteudo[1] === 0xbb && conteudo[2] === 0xbf;
|
|
6
|
+
const lf = conteudo.indexOf(0x0a);
|
|
7
|
+
const eol = lf > 0 && conteudo[lf - 1] === 0x0d ? '\r\n' : '\n';
|
|
8
|
+
return { conteudo, bom, eol };
|
|
9
|
+
}
|
|
10
|
+
/** Troca os bytes [inicio, fim) por `novo` em UTF-8; o resto do buffer sai idêntico. */
|
|
11
|
+
export function substituirTrecho(buffer, inicio, fim, novo) {
|
|
12
|
+
if (!Number.isInteger(inicio) || !Number.isInteger(fim) || inicio < 0 || fim < inicio || fim > buffer.length) {
|
|
13
|
+
throw new Error(`intervalo inválido [${inicio}, ${fim}) para buffer de ${buffer.length} bytes`);
|
|
14
|
+
}
|
|
15
|
+
return Buffer.concat([buffer.subarray(0, inicio), Buffer.from(novo, 'utf8'), buffer.subarray(fim)]);
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fontdata/ai-harness",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Harness de engenharia com IA da Fontdata para Claude Code: roda os slash commands direto na pasta do projeto via npx, sem instalar nada — ou instala-os em .claude/commands.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/templates/CLAUDE.md
CHANGED
|
@@ -27,6 +27,7 @@ Comece por `/harness`, que conduz o setup em etapas.
|
|
|
27
27
|
| `docs/trabalhos/<id>/DECISOES.md` | Decisões tomadas no planejamento e na execução |
|
|
28
28
|
| `docs/trabalhos/<id>/BLOQUEIOS.md` | Dúvidas que pararam uma task |
|
|
29
29
|
| `docs/trabalhos/<id>/relatorios/TECNICO.md` e `relatorios/CLIENTE.md` | Relatório para engenharia e para cliente e suporte (sem jargão) |
|
|
30
|
+
| `docs/trabalhos/<id>/<id>.sql` | Script SQL entregável do trabalho, opcional (`<id>-<sufixo>.sql` se houver mais de um); apoio vai em `anexos/` |
|
|
30
31
|
| `docs/eventos/<id>.jsonl` | Rastro de eventos (não versionado por padrão) |
|
|
31
32
|
| `.ai-harness/` | Lock da instalação e configuração dos hooks (versionar) |
|
|
32
33
|
|
package/templates/catalog.json
CHANGED
|
@@ -79,7 +79,8 @@
|
|
|
79
79
|
"title": "Utilitário",
|
|
80
80
|
"commands": [
|
|
81
81
|
{ "id": "git-commit-push", "file": "commands/git-commit-push.md", "title": "/git-commit-push", "description": "Gera mensagem e executa git add/commit/push em PT-BR.", "recommended": true },
|
|
82
|
-
{ "id": "versao", "file": "commands/versao.md", "title": "/versao", "description": "Detecta
|
|
82
|
+
{ "id": "versao", "file": "commands/versao.md", "title": "/versao", "description": "Detecta as fontes de versão do projeto (qualquer stack) pela CLI `ai-harness versao` e pelo `.ai-harness/versao.json` e aplica o bump de versão + changelog, com gate de aprovação e sem push.", "recommended": true },
|
|
83
|
+
{ "id": "publicar-release", "file": "commands/publicar-release.md", "title": "/publicar-release", "description": "Depois do /versao, cria a tag pelo modelo do versao.json (exceto com auto-tag), faz o push após confirmação e cria o GitHub Release com notas geradas.", "recommended": false },
|
|
83
84
|
{ "id": "revisar-pr", "file": "commands/revisar-pr.md", "title": "/revisar-pr", "description": "Revisa um PR ou o diff atual em BLOQUEANTE/IMPORTANTE/SUGESTÃO e, se pedido, organiza as correções num trabalho com teste de regressão.", "recommended": false, "replaces": ["corrigir-review"] }
|
|
84
85
|
]
|
|
85
86
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Publica no GitHub a versão que o /versao acabou de gerar — tag, push e release com notas geradas. Opcional; roda depois do /versao.
|
|
3
|
+
argument-hint: "[--app <nome>]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /publicar-release — Tag, push e GitHub Release
|
|
7
|
+
|
|
8
|
+
Você publica a versão que o `/versao` acabou de commitar: cria a tag (quando o projeto não tem auto-tag), envia o
|
|
9
|
+
commit e a tag ao remoto e cria o GitHub Release. **O bump não é feito aqui**: versão, arquivos e changelog são do
|
|
10
|
+
`/versao`. Publicações em npm, lojas ou servidores seguem pelos workflows do próprio projeto.
|
|
11
|
+
|
|
12
|
+
> **🚦 Há um GATE de confirmação obrigatório antes do push (Passo 4).** Nada vai para o remoto sem o "sim" do
|
|
13
|
+
> usuário.
|
|
14
|
+
|
|
15
|
+
## Uso
|
|
16
|
+
|
|
17
|
+
- `/publicar-release` — publica a versão do HEAD.
|
|
18
|
+
- `/publicar-release --app <nome>` — em monorepo, publica a versão do app indicado.
|
|
19
|
+
|
|
20
|
+
Argumento recebido: $ARGUMENTS
|
|
21
|
+
|
|
22
|
+
## Passo 0 — Pré-checagens (somente leitura; abortar se alguma falhar)
|
|
23
|
+
|
|
24
|
+
1. **Árvore limpa:** `git status --short` sem saída. Se houver mudança, pare e sugira `/git-commit-push`.
|
|
25
|
+
2. **Branch e remoto:** `git branch --show-current` (pare se o HEAD estiver destacado) e `git fetch --tags`.
|
|
26
|
+
Compare com o upstream (`git rev-list --left-right --count @{u}...HEAD`): se estiver **atrás** ou divergente,
|
|
27
|
+
pare e avise. Estar à frente só pelo commit de release é o esperado.
|
|
28
|
+
3. **GitHub CLI:** `gh auth status`. Sem autenticação, pare e peça para o usuário rodar `gh auth login`.
|
|
29
|
+
|
|
30
|
+
## Passo 1 — Ler a versão e o modelo da tag (somente leitura)
|
|
31
|
+
|
|
32
|
+
Rode `npx @fontdata/ai-harness versao detectar --json` (com `--app <nome>` se ele veio em `$ARGUMENTS`). Do JSON,
|
|
33
|
+
use `versaoAtual`, `tag` (o modelo, ex.: `v{versao}` ou `{app}-v{versao}`), `fontes`, `divergencias` e `problemas`.
|
|
34
|
+
|
|
35
|
+
- `ok: false`, `problemas` não vazio ou `divergencias` não vazio: pare, mostre o que veio e sugira o `/versao`.
|
|
36
|
+
- `apps` não vazio e sem `--app`: pare e pergunte qual app publicar.
|
|
37
|
+
- `tag` nulo: pergunte o padrão de tag do projeto (veja `git tag --sort=-creatordate | head`) e sugira gravá-lo no
|
|
38
|
+
campo `tag` do `.ai-harness/versao.json`.
|
|
39
|
+
|
|
40
|
+
Nome da tag: troque `{versao}` por `versaoAtual` e `{app}` pelo nome do app. Se a CLI não responder, leia a versão
|
|
41
|
+
nas fontes do `.ai-harness/versao.json` (ou do projeto) e siga o padrão das tags existentes, avisando o usuário.
|
|
42
|
+
|
|
43
|
+
## Passo 2 — Conferir que o HEAD é o commit de release do `/versao`
|
|
44
|
+
|
|
45
|
+
1. A tag ainda não existe: `git rev-parse -q --verify "refs/tags/<tag>"` e `git ls-remote --tags origin "<tag>"`
|
|
46
|
+
sem saída. Se existir, pare: a versão já foi publicada ou o `/versao` não rodou.
|
|
47
|
+
2. O commit do HEAD mudou a versão: `git show --stat HEAD` toca as fontes listadas em `fontes`, e
|
|
48
|
+
`git log -1 --format=%s` segue o modelo `commit` do `.ai-harness/versao.json` (quando houver) ou cita a versão.
|
|
49
|
+
3. O valor das fontes no HEAD é `versaoAtual` (o `detectar` lê a árvore, que está limpa pelo Passo 0).
|
|
50
|
+
|
|
51
|
+
Se algum item falhar, pare e explique; o caminho é rodar o `/versao` antes.
|
|
52
|
+
|
|
53
|
+
## Passo 3 — Tag (só se o projeto não tiver auto-tag)
|
|
54
|
+
|
|
55
|
+
- Procure `.github/workflows/*auto-tag*`. **Se existir**, não crie a tag: a Action cria quando o commit de release
|
|
56
|
+
chegar na branch de produção. Avise isso e siga sem tag local.
|
|
57
|
+
- **Senão**, crie a tag anotada local: `git tag -a "<tag>" -m "<tag>"`.
|
|
58
|
+
|
|
59
|
+
## Passo 4 — 🚦 GATE: confirmar o envio
|
|
60
|
+
|
|
61
|
+
Mostre e **aguarde confirmação explícita** do usuário:
|
|
62
|
+
|
|
63
|
+
- branch e remoto de destino;
|
|
64
|
+
- commits que vão subir: `git log --oneline @{u}..HEAD`;
|
|
65
|
+
- tag que vai junto (ou "nenhuma, o auto-tag cria");
|
|
66
|
+
- o release que será criado em seguida.
|
|
67
|
+
|
|
68
|
+
Sem "sim", pare. Se a tag foi criada no Passo 3 e o usuário desistir, ofereça removê-la com `git tag -d "<tag>"`.
|
|
69
|
+
|
|
70
|
+
## Passo 5 — Push
|
|
71
|
+
|
|
72
|
+
`git push --follow-tags` (envia o commit de release e a tag anotada). Se o push for recusado, pare e explique.
|
|
73
|
+
|
|
74
|
+
## Passo 6 — GitHub Release
|
|
75
|
+
|
|
76
|
+
- Com tag local: `gh release create "<tag>" --title "<tag>" --generate-notes`.
|
|
77
|
+
- Com auto-tag: espere a tag aparecer no remoto (`git ls-remote --tags origin "<tag>"`, ou acompanhe com
|
|
78
|
+
`gh run list --workflow <arquivo-do-auto-tag>`) antes de criar o release; se o workflow já cria o release, não
|
|
79
|
+
crie outro.
|
|
80
|
+
|
|
81
|
+
## Passo 7 — Resumo
|
|
82
|
+
|
|
83
|
+
- Link do release (`gh release view "<tag>" --json url -q .url`).
|
|
84
|
+
- Versão publicada, tag e status do push.
|
|
85
|
+
- Lembre que publicações (npm, lojas, deploy) seguem pelos workflows do projeto disparados pela tag ou pelo release;
|
|
86
|
+
aponte o `gh run list` para acompanhar.
|
|
87
|
+
|
|
88
|
+
## Guardrails
|
|
89
|
+
|
|
90
|
+
- Nunca use `--force` em push nem em tag; nunca mova nem apague tag publicada no remoto.
|
|
91
|
+
- Não faça bump: sem `npm`, `dotnet`, `flutter` ou edição de arquivo de versão. Versão errada volta para o `/versao`.
|
|
92
|
+
- Não pule as pré-checagens nem o GATE do Passo 4.
|
|
93
|
+
- Se qualquer comando falhar, pare e explique o erro e o próximo passo; não contorne sozinho.
|
|
@@ -1,87 +1,81 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
3
|
-
argument-hint: "[X.Y.Z | major | minor | patch | build]"
|
|
2
|
+
description: Aplica o bump de versão em qualquer stack (Node, Delphi, .NET, Flutter, Python, monorepo) pela CLI versao do ai-harness, gera o changelog amigável e commita, com gate de aprovação. Para antes do push.
|
|
3
|
+
argument-hint: "[X.Y.Z | major | minor | patch | build] [--app <nome>]"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# /versao — Bump de versão
|
|
6
|
+
# /versao — Bump de versão sobre a CLI
|
|
7
7
|
|
|
8
|
-
Você é o **orquestrador de release** deste projeto.
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
Você é o **orquestrador de release** deste projeto. Quem acha e grava a versão é a CLI determinística
|
|
9
|
+
`npx @fontdata/ai-harness versao detectar|calcular|aplicar`, que lê o `.ai-harness/versao.json` quando ele existe e
|
|
10
|
+
detecta as fontes por stack quando não existe. Ela não faz commit, tag nem push e não escreve changelog. A você
|
|
11
|
+
cabe o que exige julgamento: o changelog amigável, o gate, a validação e o commit, sempre no padrão que o projeto
|
|
12
|
+
já usa.
|
|
11
13
|
|
|
12
|
-
> **🚦 Há um GATE de aprovação obrigatório** antes de qualquer escrita. **PARE antes de `git push
|
|
13
|
-
>
|
|
14
|
+
> **🚦 Há um GATE de aprovação obrigatório** antes de qualquer escrita. **PARE antes de `git push`**: push é sempre
|
|
15
|
+
> ação manual do usuário.
|
|
14
16
|
|
|
15
17
|
## Uso
|
|
16
18
|
|
|
17
|
-
- `/versao`
|
|
18
|
-
- `/versao X.Y.Z
|
|
19
|
-
- `/versao major|minor|patch|build
|
|
20
|
-
|
|
19
|
+
- `/versao`: usa o `bump.padrao` do `versao.json` ou, sem ele, **infere** pelos commits (nunca sobe major).
|
|
20
|
+
- `/versao X.Y.Z`: versão explícita como **override** (único caminho, junto com `major`, que sobe o major).
|
|
21
|
+
- `/versao major|minor|patch|build`: incrementa o segmento indicado, respeitando os segmentos do projeto
|
|
22
|
+
(`X.Y.Z` ou `X.Y.Z.W`, comum em Delphi/.NET).
|
|
23
|
+
- `--app <nome>`: em monorepo, versiona só aquele app (versão, tag e changelogs próprios).
|
|
24
|
+
|
|
25
|
+
Todos os comandos da CLI aceitam `--json` e `--app <nome>`. Com `"ok": false` a resposta traz `erro` e o código de
|
|
26
|
+
saída é 1. Se o próprio `npx @fontdata/ai-harness versao` falhar (pacote antigo sem o subcomando, sem rede), siga a
|
|
27
|
+
seção **Sem a CLI** no fim deste arquivo. Erro de conteúdo (ex.: `versao.json` inválido, app inexistente) não é
|
|
28
|
+
motivo para o plano B: mostre o `erro` ao usuário e corrija a causa.
|
|
21
29
|
|
|
22
30
|
## Passo 0 — Pré-checagem (abortar se falhar)
|
|
23
31
|
|
|
24
|
-
1. **Working tree limpo:** rode `git status --short`. Se houver saída
|
|
25
|
-
|
|
26
|
-
2. **
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
`
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
## Passo 2 — Levantar commits e calcular a nova versão
|
|
64
|
-
|
|
65
|
-
- `git log <base>..HEAD --pretty=format:%H%x09%s`. Liste ao usuário os commits considerados (título +
|
|
66
|
-
tipo semântico) e a base usada.
|
|
67
|
-
- **Se veio versão explícita `X.Y.Z`:** assuma exatamente ela (override total).
|
|
68
|
-
- **Se veio um tipo (`major|minor|patch|build`):** incremente esse segmento e zere os à direita,
|
|
69
|
-
respeitando o número de segmentos do projeto.
|
|
70
|
-
- **Senão, infira por SemVer** (precedência minor > patch, com reset em cascata):
|
|
71
|
-
1. Algum `feat:` → **minor**: `Y = Y + 1`, demais à direita = `0`.
|
|
72
|
-
2. Senão, algum `fix:`/`chore:`/`refactor:`/`docs:`/`style:`/`perf:`/`test:` → **patch**.
|
|
73
|
-
3. Senão → sem bump elegível: avise e **peça confirmação** (abortar ou versão explícita).
|
|
74
|
-
- **`major` é manual** — só sobe quando o usuário passa `X.Y.Z` explícito ou `major`, porque sinaliza quebra de
|
|
75
|
-
compatibilidade e isso é decisão de quem mantém o projeto. A inferência não sobe major.
|
|
32
|
+
1. **Working tree limpo:** rode `git status --short`. Se houver saída, **aborte** e instrua a commitar ou limpar
|
|
33
|
+
antes (sugira `/git-commit-push`). Bump com árvore suja mistura no commit de release o que não é release.
|
|
34
|
+
2. **Argumento:** separe a versão ou o tipo de bump e o `--app <nome>`, para repassar à CLI nos passos seguintes.
|
|
35
|
+
|
|
36
|
+
## Passo 1 — Detectar as fontes da versão (somente leitura)
|
|
37
|
+
|
|
38
|
+
Rode `npx @fontdata/ai-harness versao detectar --json` (com `--app <nome>` se for o caso) e leia:
|
|
39
|
+
|
|
40
|
+
- `versaoAtual`, `tag` (modelo da tag, ex.: `v{versao}`, `V{versao}`, `{app}-v{versao}`), `segmentos`, `formato` e
|
|
41
|
+
`base` (`tag`, `versao`, `primeiroRelease`: sem tag anterior, avise que é o primeiro release);
|
|
42
|
+
- `fontes`: cada `caminho` e `extrator`, com as `ocorrencias` (`linha`, `valor`). Fonte com `somenteLeitura`
|
|
43
|
+
(ex.: `Versoes.txt`) é lida, não gravada pela CLI; fonte com `naoTocar` nunca é gravada;
|
|
44
|
+
- `apps`: se não estiver vazio e o usuário não passou `--app`, liste os apps com as versões e pergunte qual
|
|
45
|
+
versionar antes de seguir;
|
|
46
|
+
- `divergencias` e `problemas`: **destaque** cada um. Fontes com versões diferentes precisam de decisão do usuário
|
|
47
|
+
(qual é a certa) antes do gate; não escolha por conta própria.
|
|
48
|
+
|
|
49
|
+
**Sem `versao.json` (`origem` é `deteccao`):** mostre o `versaoJson` proposto e explique em uma frase cada campo
|
|
50
|
+
relevante (`arquivos`, `tag`, `bump.padrao`, `changelogs`, `naoTocar`). Ofereça gravá-lo em
|
|
51
|
+
`.ai-harness/versao.json`, que passa a ser a fonte de verdade do projeto. Só grave com aprovação; se o usuário
|
|
52
|
+
ajustar algo, grave a versão ajustada e rode o `detectar` de novo. Se ele recusar, siga com a detecção.
|
|
53
|
+
|
|
54
|
+
## Passo 2 — Calcular a nova versão, levantar os commits e simular a gravação
|
|
55
|
+
|
|
56
|
+
Rode `npx @fontdata/ai-harness versao calcular [argumento] --json` repassando o argumento do usuário (`X.Y.Z`,
|
|
57
|
+
`major`, `minor`, `patch` ou `build`) e o `--app`. Leia `versaoAtual`, `proxima`, `tagProxima`, `bump` (`tipo` e
|
|
58
|
+
`origem`: explícito, config ou inferido) e `commits` (`hash`, `titulo`, `corpo`), que já vêm filtrados pelos
|
|
59
|
+
`caminhos` do app em monorepo.
|
|
60
|
+
|
|
61
|
+
- Mostre a base (`base.tag`), a regra do bump e a lista de commits considerados (título e tipo semântico).
|
|
62
|
+
- Repasse os `avisos` (ex.: `!:`/`BREAKING CHANGE` virou minor, próxima versão não é maior que a atual).
|
|
63
|
+
- **`major` é manual:** a inferência nunca sobe major, porque isso sinaliza quebra de compatibilidade e é decisão
|
|
64
|
+
de quem mantém o projeto. Se houver commit de quebra, diga isso e ofereça `/versao major` ou `X.Y.Z`.
|
|
65
|
+
- Sem commit elegível ou sem `proxima`: avise e **peça confirmação** (abortar ou versão explícita).
|
|
66
|
+
|
|
67
|
+
Com a nova versão definida, rode `npx @fontdata/ai-harness versao aplicar <nova> --dry-run --json` (com `--app` se
|
|
68
|
+
for o caso), em que `<nova>` é a `proxima`. Ele não grava nada e devolve, por arquivo, o `diff` que o gate vai
|
|
69
|
+
mostrar. Se vier `problemas` ou alguma fonte com `status` de erro, pare e resolva antes do gate: o `aplicar` real
|
|
70
|
+
não grava nada quando uma fonte falha.
|
|
76
71
|
|
|
77
72
|
## Passo 3 — Gerar o changelog (no padrão do projeto)
|
|
78
73
|
|
|
79
|
-
Este comando é **autossuficiente**: gere aqui
|
|
80
|
-
|
|
81
|
-
|
|
74
|
+
Este comando é **autossuficiente**: gere aqui o changelog **amigável ao usuário final** (pt-BR, sem
|
|
75
|
+
hash/arquivo/jargão) a partir dos `commits` do Passo 2, sem depender de skill ou comando externo. A CLI não escreve
|
|
76
|
+
changelog; quem grava os blocos é o Passo 5.
|
|
82
77
|
|
|
83
|
-
**3.1 — Leia os commits.** Use
|
|
84
|
-
quando precisar de contexto para entender o que a mudança entrega.
|
|
78
|
+
**3.1 — Leia os commits.** Use o `titulo` e, quando precisar entender o que a mudança entrega, o `corpo`.
|
|
85
79
|
|
|
86
80
|
**3.2 — Categorize (modo compacto, 3 categorias).** Agrupe mapeando os prefixos semânticos:
|
|
87
81
|
|
|
@@ -89,73 +83,116 @@ quando precisar de contexto para entender o que a mudança entrega.
|
|
|
89
83
|
- **🐛 Correções** — `fix:`
|
|
90
84
|
- **⚡ Melhorias** — `perf:`/`refactor:`/`chore:`/`style:`/`docs:`/`test:`/`build:`/`ci:`
|
|
91
85
|
|
|
92
|
-
Mantenha **⚠️ Mudanças importantes** (`BREAKING CHANGE
|
|
93
|
-
**🔒 Segurança** como blocos próprios **só se houver itens**. Commits sem prefixo: classifique pelo
|
|
94
|
-
|
|
86
|
+
Mantenha **⚠️ Mudanças importantes** (`BREAKING CHANGE`/`!:`, destacando o que o usuário precisa fazer) e
|
|
87
|
+
**🔒 Segurança** como blocos próprios **só se houver itens**. Commits sem prefixo: classifique pelo conteúdo da
|
|
88
|
+
mensagem. Inclua apenas as seções que tiverem itens.
|
|
95
89
|
|
|
96
90
|
**3.3 — Traduza técnico → usuário final.** Para cada item que vai aparecer:
|
|
97
91
|
|
|
98
|
-
- Reescreva em **linguagem clara e não técnica**, focando no **benefício para quem usa o produto
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
- **Filtre o ruído**: descarte merges, bumps triviais de versão, ajustes de lint/formatação e commits
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
- Reescreva em **linguagem clara e não técnica**, focando no **benefício para quem usa o produto**. Quando fizer
|
|
93
|
+
sentido, use **negrito com o nome do recurso + frase do ganho** (ex.: `**Sincronização mais rápida**: arquivos
|
|
94
|
+
sincronizam 2x mais rápido entre dispositivos`).
|
|
95
|
+
- **Filtre o ruído**: descarte merges, bumps triviais de versão, ajustes de lint/formatação e commits puramente
|
|
96
|
+
internos sem impacto perceptível. O bloco "Melhorias" é um resumo curto, não um despejo de commits. Ignore
|
|
97
|
+
`docs:`/`chore:` puramente internos quando o projeto assim fizer no histórico.
|
|
104
98
|
- Não invente recursos que os commits não suportam; em dúvida, descreva de forma conservadora.
|
|
105
|
-
- **Sem emoji dentro dos itens
|
|
99
|
+
- **Sem emoji dentro dos itens**: os emojis ficam apenas nos títulos das seções.
|
|
106
100
|
|
|
107
|
-
**3.4 — Siga o estilo do projeto.** Se existir um `CHANGELOG_STYLE.md` na raiz, **siga as diretrizes dele**
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
**3.4 — Siga o estilo do projeto.** Se existir um `CHANGELOG_STYLE.md` na raiz, **siga as diretrizes dele** (tom,
|
|
102
|
+
formato, seções). Prepare um bloco por arquivo de histórico, replicando o formato que já está nele:
|
|
103
|
+
|
|
104
|
+
- cada caminho de `changelogs` do `versao.json` (do app, em monorepo) e, sem config, o `CHANGELOG.md` e os
|
|
105
|
+
arquivos de novidades consumidos pela UI (ex.: `src/data/novidades.ts`);
|
|
106
|
+
- `CHANGELOG.md`: nova seção `## [X.Y.Z] - <currentDate>` no topo (após o cabeçalho), no estilo das anteriores;
|
|
107
|
+
- `Versoes.txt` (fonte `versoes-txt`, só leitura na CLI): o bloco que você escreve, com o **mesmo espaçamento**
|
|
108
|
+
entre blocos, o mesmo cabeçalho e o **mesmo formato de número** (inclusive zeros à esquerda, conforme o
|
|
109
|
+
`formato`) das entradas existentes;
|
|
110
|
+
- use a data de `currentDate`; **nunca invente data**.
|
|
111
111
|
|
|
112
112
|
## Passo 4 — 🚦 GATE de aprovação (obrigatório)
|
|
113
113
|
|
|
114
114
|
Apresente ao usuário, **antes de escrever qualquer coisa**:
|
|
115
115
|
|
|
116
|
-
- versão atual → nova versão;
|
|
117
|
-
-
|
|
118
|
-
|
|
116
|
+
- versão atual → nova versão, e a tag que o release terá (`tagProxima`);
|
|
117
|
+
- o **diff exato** de cada arquivo do `aplicar --dry-run` do Passo 2 (`caminho` e, de cada linha do `diff`, o
|
|
118
|
+
`antes` e o `depois`);
|
|
119
|
+
- o changelog proposto e **o bloco exato** de cada arquivo de histórico (inclusive o do `Versoes.txt`, que o
|
|
120
|
+
dry-run lista como changelog gravado pelo `/versao`);
|
|
121
|
+
- em destaque: arquivos `.dproj` (o bump mexe em várias chaves de cada configuração e a IDE reescreve o arquivo
|
|
122
|
+
ao salvar), fontes e campos em `naoTocar` que ficaram de fora, `divergencias` e `avisos`.
|
|
119
123
|
|
|
120
|
-
**Peça aprovação explícita.** Não grave nada sem o "ok". Se o
|
|
121
|
-
`.csproj`), destaque o risco.
|
|
124
|
+
**Peça aprovação explícita.** Não grave nada sem o "ok". Se o usuário pedir outra versão, volte ao Passo 2 com ela.
|
|
122
125
|
|
|
123
|
-
## Passo 5 — Aplicar
|
|
126
|
+
## Passo 5 — Aplicar (somente após aprovação)
|
|
124
127
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
- `Versoes.txt`/histórico texto (se houver): anexe ao final, com o **mesmo espaçamento** entre blocos e o
|
|
132
|
-
**mesmo formato de número** (inclusive zeros à esquerda) das entradas existentes.
|
|
133
|
-
- Use a data de `currentDate`; **nunca invente data**.
|
|
128
|
+
1. Rode `npx @fontdata/ai-harness versao aplicar <nova> --json` (com `--app` se for o caso). Confira que cada
|
|
129
|
+
arquivo saiu com `gravado: true`; se vier `ok: false` ou `problemas`, pare e reporte: nada foi gravado.
|
|
130
|
+
2. Grave os blocos de changelog aprovados no gate, exatamente como mostrados (Edit, no topo ou no fim conforme o
|
|
131
|
+
padrão de cada arquivo).
|
|
132
|
+
3. Se o `versao.json` tiver `gerador`, rode o comando para regenerar os arquivos derivados da versão e mostre o
|
|
133
|
+
que ele alterou (`git status --short`).
|
|
134
134
|
|
|
135
135
|
## Passo 6 — Validar (abortar se vermelho)
|
|
136
136
|
|
|
137
|
-
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
`
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
137
|
+
- Com `validar` no `versao.json`, rode exatamente esse comando.
|
|
138
|
+
- Sem `validar`, use o runner detectado no projeto (scripts do `package.json` com npm/pnpm/yarn, `dotnet test`,
|
|
139
|
+
`flutter test`, `pytest` etc.) e, se fizer sentido para o release, o build.
|
|
140
|
+
- Se `validar` for `"ide"` ou não houver build por linha de comando (Delphi), peça ao usuário que abra o projeto
|
|
141
|
+
na IDE, compile e confirme que a versão aparece certa, e **aguarde a confirmação** antes de seguir.
|
|
142
|
+
- Se algo falhar, **aborte** sem commitar e reporte o erro.
|
|
143
|
+
|
|
144
|
+
## Passo 7 — Finalizar (somente commit, sem `git push`)
|
|
145
|
+
|
|
146
|
+
1. Estagie **apenas** os arquivos do release, listados um a um: os do `aplicar`, os changelogs e o que o
|
|
147
|
+
`gerador` alterou (e o `.ai-harness/versao.json`, se foi criado no Passo 1). Nunca `git add -A`.
|
|
148
|
+
2. Mensagem: o modelo `commit` do `versao.json` com `{versao}` e `{app}` substituídos; sem ele, o padrão do
|
|
149
|
+
histórico do projeto (`git log --oneline` dos últimos releases) ou `chore: Release vX.Y.Z`. Commit semântico,
|
|
150
|
+
com maiúscula após `: `. Finalize com o rodapé `Co-Authored-By` vigente desta sessão, como indicado pelo
|
|
151
|
+
Claude Code, sem escrever um nome de modelo por conta própria.
|
|
152
|
+
3. **Tag:** se existir automação de tag (ex.: `.github/workflows/auto-tag.yml`), não crie a tag: a Action cria
|
|
153
|
+
quando o commit chega na branch alvo, e uma tag manual duplicaria a dela. Caso contrário, só se o usuário pedir,
|
|
154
|
+
crie a tag `tagProxima` localmente.
|
|
155
|
+
4. **Pare aqui, sem `git push`.** Informe o fluxo manual de push e, se o `/publicar-release` estiver instalado em
|
|
156
|
+
`.claude/commands/`, mencione que ele faz a publicação a partir deste commit.
|
|
157
|
+
|
|
158
|
+
## Sem a CLI
|
|
159
|
+
|
|
160
|
+
Use este modo só quando o `npx @fontdata/ai-harness versao` não responder (pacote sem o subcomando, falha de rede).
|
|
161
|
+
Avise o usuário que está no modo manual e siga os mesmos Passos 0, 3, 4, 6 e 7, trocando a CLI pelo que segue.
|
|
162
|
+
|
|
163
|
+
- **Base:** liste as tags com `git tag --sort=-creatordate` e descubra o modelo do projeto: `v*`, `V*`,
|
|
164
|
+
`<app>-v*` (monorepo) ou sem prefixo (`1.2.3`). Use a tag mais recente desse modelo, **ignorando retags com
|
|
165
|
+
sufixo `-N`** (ex.: `v1.2.3-1` é a mesma versão retagueada). Sem tag no modelo, use o primeiro commit
|
|
166
|
+
(`git rev-list --max-parents=0 HEAD`) e avise que é o primeiro release. Os commits vêm de
|
|
167
|
+
`git log <base>..HEAD` (em monorepo, filtre pelo caminho do app).
|
|
168
|
+
- **Fontes:** se houver `.ai-harness/versao.json`, ele lista as fontes. Senão, procure por stack: `version` do
|
|
169
|
+
`package.json` (e do pacote raiz no lock), `.dproj` e constantes em `.pas`, `.csproj`/`AssemblyInfo.cs`/
|
|
170
|
+
`Directory.Build.props`, `pubspec.yaml`, `pyproject.toml`/`__version__`, arquivo `VERSION`. Busque a versão
|
|
171
|
+
atual em todo o projeto para não deixar ocorrência para trás e respeite o `naoTocar` (ex.: `versionCode`,
|
|
172
|
+
`buildNumber`, `runtimeVersion` têm outra numeração).
|
|
173
|
+
- **Cálculo:** versão explícita é override; tipo incrementa o segmento e zera os à direita; sem argumento, `feat:`
|
|
174
|
+
dá minor, os demais tipos dão patch, e quebra dá minor com aviso (major só explícito).
|
|
175
|
+
- **`.dproj`:** atualize as 3 famílias, coerentes entre si:
|
|
176
|
+
1. `FileVersion` e `ProductVersion` dentro de **todos** os `VerInfo_Keys`, de todas as configurações;
|
|
177
|
+
2. `VerInfo_MajorVer`, `VerInfo_MinorVer`, `VerInfo_Release` e `VerInfo_Build` em **cada** `PropertyGroup` que
|
|
178
|
+
tem `VerInfo_Keys`, criando as chaves que a IDE omitiu (ela não grava valor zero);
|
|
179
|
+
3. o bloco legado `<VersionInfo>` (`MajorVer`, `MinorVer`, `Release`, `Build`), quando existir.
|
|
180
|
+
|
|
181
|
+
No `.dproj` os números são inteiros, sem zero à esquerda. Preserve o BOM e o fim de linha CRLF: use
|
|
182
|
+
**Edit, nunca Write** em `.dproj`, porque reescrever o arquivo inteiro perde o BOM e converte as quebras de linha.
|
|
183
|
+
- **Verificação pós-aplicação:** busque a versão antiga de novo e confirme que não sobrou ocorrência fora do
|
|
184
|
+
histórico (changelogs, `Versoes.txt`); em cada `.dproj`, confirme que existe um único valor de `FileVersion` e
|
|
185
|
+
que ele é a versão nova. Mostre o `git diff --stat` ao usuário.
|
|
152
186
|
|
|
153
187
|
## Guardrails
|
|
154
188
|
|
|
155
189
|
- Sem `git push`: o push publica a versão para todos, e quem decide quando é o usuário. Não criar tag se houver
|
|
156
190
|
automação que já faça isso.
|
|
157
|
-
- **Sempre**
|
|
158
|
-
- **
|
|
159
|
-
|
|
191
|
+
- **Sempre** mostrar o diff do `aplicar --dry-run`, o changelog e os blocos no GATE antes de gravar.
|
|
192
|
+
- Versão nos arquivos-fonte só pela CLI (ou pelo modo **Sem a CLI** quando ela falhar); não edite à mão o que o
|
|
193
|
+
`aplicar` grava.
|
|
194
|
+
- **Abortar** se a working tree estiver suja ou se a validação falhar.
|
|
195
|
+
- **Replicar o padrão do projeto** (formato de versão, changelog, commit); nunca impor um novo.
|
|
160
196
|
- `major` só por argumento explícito; a inferência jamais sobe major.
|
|
197
|
+
- Gravar `.ai-harness/versao.json` só com aprovação do usuário.
|
|
161
198
|
- Changelog em **pt-BR**, voltado ao usuário final; usar a data de `currentDate`.
|
|
@@ -47,6 +47,7 @@ Se o porquê não cabe em 3 linhas, **ele não pertence ao código**.
|
|
|
47
47
|
| Task / fase / plano / spec | `PLAN.md` e `SPEC.md` do trabalho em `docs/trabalhos/<id>/` | comentário |
|
|
48
48
|
| Diagnóstico e correção de um defeito | trabalho do tipo `bug` em `docs/trabalhos/<id>/` | comentário |
|
|
49
49
|
| Investigação, medição, auditoria, paridade, comparação | `relatorios/TECNICO.md` do trabalho em `docs/trabalhos/<id>/` | comentário |
|
|
50
|
+
| Script SQL entregável do trabalho (DDL/DML) | raiz do trabalho, `docs/trabalhos/<id>/<id>.sql` | comentário |
|
|
50
51
|
| Documento de apoio do trabalho (imagem, planilha, export, contrato de API) | `anexos/` do trabalho em `docs/trabalhos/<id>/` | comentário |
|
|
51
52
|
| Achado de review | resposta do review, commit | comentário |
|
|
52
53
|
| Decisão de arquitetura | `SPEC.md` | comentário |
|
|
@@ -59,7 +60,8 @@ auditoria, paridade com legado, medição, comparação, levantamento, handoff o
|
|
|
59
60
|
|
|
60
61
|
Convenção: uma pasta por trabalho, `docs/trabalhos/<yyyy-mm-dd>-<slug>/`. Relatório não ganha nome livre em
|
|
61
62
|
`relatorios/`: o conteúdo vai para `relatorios/TECNICO.md` e o arquivo de apoio para `anexos/`, senão o `doctor`
|
|
62
|
-
avisa `arquivo-fora-do-contrato`.
|
|
63
|
+
avisa `arquivo-fora-do-contrato`. O script SQL do trabalho é entregável, não apoio: fica na raiz como `<id>.sql`
|
|
64
|
+
(ou `<id>-<sufixo>.sql`).
|
|
63
65
|
|
|
64
66
|
## Antes e depois
|
|
65
67
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: evoluir-harness
|
|
3
|
-
description: Cria ou ajusta peças do harness no projeto — agents, skills, rules, hooks, code-reviewer
|
|
4
|
-
argument-hint: "[agent|skill|rule|hook|code-reviewer|design-system|auditar]"
|
|
3
|
+
description: Cria ou ajusta peças do harness no projeto — agents, skills, rules, hooks, code-reviewer, design system e o versao.json do /versao — ou audita a pasta .claude e sugere o que mudar. Use de vez em quando, conforme o projeto cresce.
|
|
4
|
+
argument-hint: "[agent|skill|rule|hook|code-reviewer|design-system|versao|auditar]"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Evoluir o harness
|
|
@@ -27,6 +27,7 @@ A primeira palavra do pedido é o tipo; o resto é contexto (nome, domínio, URL
|
|
|
27
27
|
| `hook` | `references/hook.md` | Hooks por agent sobre a biblioteca do harness |
|
|
28
28
|
| `code-reviewer` | `references/code-reviewer.md` | Agent de review somente leitura e o portão extra |
|
|
29
29
|
| `design-system` | a referência `design-system.md` em `references/` | Agent, skill e rules da identidade visual |
|
|
30
|
+
| `versao` | `references/versao.md` | `.ai-harness/versao.json` do `/versao`, inclusive a partir de uma cópia customizada do comando |
|
|
30
31
|
|
|
31
32
|
Tipo desconhecido: mostre a tabela e pergunte. Não carregue as outras referências.
|
|
32
33
|
|