@fontdata/ai-harness 2.3.2 → 2.5.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/plugin.json +1 -1
- package/README.md +16 -1
- package/dist/contratos/artefatos.js +7 -1
- package/dist/install/plan.js +9 -5
- package/dist/install/settings.js +54 -13
- package/dist/update/update.js +13 -4
- package/package.json +1 -1
- package/templates/CLAUDE.md +1 -1
- package/templates/skills/executar-plan/SKILL.md +20 -3
- package/templates/skills/executar-plan/references/relatorios-da-entrega.md +51 -0
- package/templates/skills/executar-plan/templates/relatorios/CLIENTE.md +51 -0
- package/templates/skills/executar-plan/templates/relatorios/TECNICO.md +44 -0
- package/templates/skills/nova-tarefa/SKILL.md +11 -3
- package/templates/skills/nova-tarefa/templates/PLAN.md +1 -0
- package/templates/skills/nova-tarefa/templates/SPEC.md +11 -0
package/README.md
CHANGED
|
@@ -103,6 +103,21 @@ npx @fontdata/ai-harness init --comandos resolver-bug,nova-tarefa --sem-harness
|
|
|
103
103
|
Com o plugin `fontdata@ai-harness` habilitado, o `init` não instala os hooks no projeto, para eles não rodarem
|
|
104
104
|
duas vezes.
|
|
105
105
|
|
|
106
|
+
### Permissões para o modo auto
|
|
107
|
+
|
|
108
|
+
O `init` e o `update` gravam em `.claude/settings.json` as permissões que os fluxos usam, para rodarem sem pedir
|
|
109
|
+
aprovação, inclusive no modo auto do Claude Code:
|
|
110
|
+
|
|
111
|
+
- `permissions.allow`: o rastro, a checagem de conflitos, o `doctor` e a `memoria` do harness; `git add`,
|
|
112
|
+
`git commit` e `git push` (o `/git-commit-push`); a abertura de sub-agents (`Agent`); e consultas só de leitura
|
|
113
|
+
(`git status`, `diff`, `log`, `show`, `blame`, `gh pr view`, `gh pr diff`, `npm outdated`...);
|
|
114
|
+
- `permissions.deny`: o push forçado (`--force`, `-f`, `--force-with-lease` e refspec com `+`), que vence o `allow`.
|
|
115
|
+
|
|
116
|
+
Ficam de fora os comandos de teste e build, que variam por projeto, e os que regravam a instalação (`init`,
|
|
117
|
+
`update`, `migrar`). O projeto acrescenta os seus no próprio `settings.json`; o harness nunca remove regras.
|
|
118
|
+
Nos modos 1 e 2 nada é gravado no projeto: rode `npx @fontdata/ai-harness update --yes` num projeto já instalado,
|
|
119
|
+
ou `init`, para receber as regras.
|
|
120
|
+
|
|
106
121
|
## Subcomandos do CLI
|
|
107
122
|
|
|
108
123
|
| Subcomando | O que faz |
|
|
@@ -127,7 +142,7 @@ duas vezes.
|
|
|
127
142
|
| `docs/trabalhos/<id>/PLAN.md` | Plano: sprints, fases e tasks (as tasks também no frontmatter) |
|
|
128
143
|
| `docs/trabalhos/<id>/DECISOES.md` | Decisões tomadas no planejamento e na execução |
|
|
129
144
|
| `docs/trabalhos/<id>/BLOQUEIOS.md` | Dúvidas que pararam uma task |
|
|
130
|
-
| `docs/trabalhos/<id>/relatorios/TECNICO.md` e `CLIENTE.md` | Relatório para engenharia e para cliente
|
|
145
|
+
| `docs/trabalhos/<id>/relatorios/TECNICO.md` e `CLIENTE.md` | Relatório para engenharia e para cliente e suporte |
|
|
131
146
|
| `docs/eventos/<id>.jsonl` | Rastro de eventos (não versionado por padrão) |
|
|
132
147
|
| `.ai-harness/lock.json` e `config.json` | Lock da instalação e configuração dos hooks (versionar) |
|
|
133
148
|
|
|
@@ -154,6 +154,9 @@ function validatePlan(file, data) {
|
|
|
154
154
|
if ('condensado' in data && typeof data.condensado !== 'boolean') {
|
|
155
155
|
problems.push(problem(file, 'formato-invalido', 'condensado deve ser true ou false.'));
|
|
156
156
|
}
|
|
157
|
+
if ('relatorios_entrega' in data && typeof data.relatorios_entrega !== 'boolean') {
|
|
158
|
+
problems.push(problem(file, 'formato-invalido', 'relatorios_entrega deve ser true ou false.'));
|
|
159
|
+
}
|
|
157
160
|
if ('auditoria_plano' in data && !['pendente', 'aprovado', 'reprovado'].includes(String(data.auditoria_plano))) {
|
|
158
161
|
problems.push(problem(file, 'status-invalido', 'auditoria_plano inválida. Use: pendente, aprovado, reprovado.'));
|
|
159
162
|
}
|
|
@@ -261,7 +264,10 @@ export function validateWork(root, folderId) {
|
|
|
261
264
|
const migrated = [...parsed.values()].some((data) => data.migrado === true);
|
|
262
265
|
if (typeof declared === 'string' && !migrated) {
|
|
263
266
|
const required = [...(REQUIRED_BY_WORK_TYPE[declared] ?? [])];
|
|
264
|
-
|
|
267
|
+
const plan = parsed.get('PLAN.md');
|
|
268
|
+
// Feature só exige relatórios quando o plano nasceu com relatorios_entrega; as anteriores ficam como estão.
|
|
269
|
+
const reportsDue = declared === 'bug' || (declared === 'feature' && plan?.relatorios_entrega === true);
|
|
270
|
+
if (reportsDue && plan?.status === 'concluido') {
|
|
265
271
|
required.push('relatorios/TECNICO.md', 'relatorios/CLIENTE.md');
|
|
266
272
|
}
|
|
267
273
|
for (const rel of required) {
|
package/dist/install/plan.js
CHANGED
|
@@ -7,7 +7,7 @@ import { buildLockItem, LOCK_VERSION, readLock, writeLock } from './lock.js';
|
|
|
7
7
|
import { HOOKS_ITEM_ID, PROJECT_HOOKS_DIR, projectHooksConfig } from './hooks.js';
|
|
8
8
|
import { neededSkillsFor, resolveSelection } from './selection.js';
|
|
9
9
|
import { COMMENTS_RULE_PATH, commentsHooksConfig, ensureCommentsBaseline } from '../comentarios/instalar.js';
|
|
10
|
-
import { combineHooks, HARNESS_PERMISSIONS, mergeSettings } from './settings.js';
|
|
10
|
+
import { combineHooks, HARNESS_DENY, HARNESS_PERMISSIONS, mergeSettings } from './settings.js';
|
|
11
11
|
/** Rule de convenção com o que é específico do projeto (D-38): é do projeto, então fica fora do lock. */
|
|
12
12
|
export const PROJECT_RULE_PATH = '.claude/rules/harness-projeto.md';
|
|
13
13
|
/** Esqueleto da rule de projeto; os comandos `-legado` renomeados pelo update entram na última seção. */
|
|
@@ -161,8 +161,9 @@ export function executePlan(root, plan, pkg, now = new Date()) {
|
|
|
161
161
|
applyAtomically(root, plan.files);
|
|
162
162
|
const permission = needsEventPermission(plan);
|
|
163
163
|
const hooks = combineHooks(plan.registerHooks ? projectHooksConfig() : {}, plan.registerComments ? commentsHooksConfig() : {});
|
|
164
|
-
if (Object.keys(hooks).length || permission)
|
|
165
|
-
mergeSettings(root, { hooks, allow: permission ? HARNESS_PERMISSIONS : [] }, now);
|
|
164
|
+
if (Object.keys(hooks).length || permission) {
|
|
165
|
+
mergeSettings(root, { hooks, allow: permission ? HARNESS_PERMISSIONS : [], deny: permission ? HARNESS_DENY : [] }, now);
|
|
166
|
+
}
|
|
166
167
|
if (plan.registerComments)
|
|
167
168
|
ensureCommentsBaseline(root);
|
|
168
169
|
const items = new Map();
|
|
@@ -200,8 +201,11 @@ export function describePlan(plan) {
|
|
|
200
201
|
lines.push('O CLAUDE.md atual será copiado para CLAUDE.md.bak.');
|
|
201
202
|
if (plan.registerHooks)
|
|
202
203
|
lines.push('Hooks do harness registrados em .claude/settings.json (sem duplicar os existentes).');
|
|
203
|
-
if (needsEventPermission(plan))
|
|
204
|
-
lines.push(`Permissões ${HARNESS_PERMISSIONS.join('
|
|
204
|
+
if (needsEventPermission(plan)) {
|
|
205
|
+
lines.push(`Permissões ${HARNESS_PERMISSIONS.join(', ')} em .claude/settings.json, para o rastro, a checagem de conflitos, ` +
|
|
206
|
+
'o /git-commit-push, os sub-agents e as consultas de leitura não pedirem aprovação (inclusive no modo auto); ' +
|
|
207
|
+
'o push forçado fica bloqueado em permissions.deny.');
|
|
208
|
+
}
|
|
205
209
|
if (plan.registerComments) {
|
|
206
210
|
lines.push('Padrão de comentários: rule carregada em toda sessão, hook que bloqueia a violação e catraca do legado (gerada só na primeira instalação).');
|
|
207
211
|
}
|
package/dist/install/settings.js
CHANGED
|
@@ -5,8 +5,43 @@ export const SETTINGS_PATH = join('.claude', 'settings.json');
|
|
|
5
5
|
export const EVENT_PERMISSION = 'Bash(npx @fontdata/ai-harness evento:*)';
|
|
6
6
|
/** O /executar-plan checa (e aguarda) conflito de arquivos com outros trabalhos por este comando. */
|
|
7
7
|
export const CONFLICTS_PERMISSION = 'Bash(npx @fontdata/ai-harness conflitos:*)';
|
|
8
|
+
/** O /git-commit-push roda sem confirmação, o que inclui o modo auto do Claude Code. */
|
|
9
|
+
export const GIT_PERMISSIONS = ['Bash(git add:*)', 'Bash(git commit:*)', 'Bash(git push:*)'];
|
|
10
|
+
/** O /executar-plan e as skills de fluxo delegam a sub-agents a cada task e gate. */
|
|
11
|
+
export const AGENT_PERMISSION = 'Agent';
|
|
12
|
+
/**
|
|
13
|
+
* Comandos só de leitura que as skills, os comandos e os agents rodam. Ficam de fora os que regravam a instalação
|
|
14
|
+
* (`init`, `update`, `migrar`), os de teste e build, que variam por projeto, e o `npm audit`, cujo prefixo
|
|
15
|
+
* liberaria também o `npm audit fix`.
|
|
16
|
+
*/
|
|
17
|
+
export const READ_PERMISSIONS = [
|
|
18
|
+
'Bash(npx @fontdata/ai-harness doctor:*)',
|
|
19
|
+
'Bash(npx @fontdata/ai-harness memoria:*)',
|
|
20
|
+
'Bash(git status:*)',
|
|
21
|
+
'Bash(git diff:*)',
|
|
22
|
+
'Bash(git log:*)',
|
|
23
|
+
'Bash(git show:*)',
|
|
24
|
+
'Bash(git blame:*)',
|
|
25
|
+
'Bash(git describe:*)',
|
|
26
|
+
'Bash(git rev-list:*)',
|
|
27
|
+
'Bash(git rev-parse:*)',
|
|
28
|
+
'Bash(git remote -v)',
|
|
29
|
+
'Bash(git symbolic-ref --short refs/remotes/origin/HEAD)',
|
|
30
|
+
'Bash(gh pr view:*)',
|
|
31
|
+
'Bash(gh pr diff:*)',
|
|
32
|
+
'Bash(npm outdated:*)',
|
|
33
|
+
];
|
|
8
34
|
/** Regras de `permissions.allow` que o init e o update gravam para as skills e os agents do harness. */
|
|
9
|
-
export const HARNESS_PERMISSIONS = [EVENT_PERMISSION, CONFLICTS_PERMISSION];
|
|
35
|
+
export const HARNESS_PERMISSIONS = [EVENT_PERMISSION, CONFLICTS_PERMISSION, ...GIT_PERMISSIONS, AGENT_PERMISSION, ...READ_PERMISSIONS];
|
|
36
|
+
/** O push liberado não vale para reescrever o histórico remoto: `deny` vence o `allow`. */
|
|
37
|
+
export const HARNESS_DENY = [
|
|
38
|
+
'Bash(git push --force:*)',
|
|
39
|
+
'Bash(git push *--force*)',
|
|
40
|
+
'Bash(git push -f:*)',
|
|
41
|
+
'Bash(git push * -f)',
|
|
42
|
+
'Bash(git push * -f *)',
|
|
43
|
+
'Bash(git push * +*)',
|
|
44
|
+
];
|
|
10
45
|
function isPlainObject(value) {
|
|
11
46
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
12
47
|
}
|
|
@@ -24,12 +59,12 @@ export function combineHooks(...configs) {
|
|
|
24
59
|
}
|
|
25
60
|
return combined;
|
|
26
61
|
}
|
|
27
|
-
/** A regra já está em `permissions.allow` do `.claude/settings.json` do projeto? */
|
|
28
|
-
export function hasAllowRule(root, rule) {
|
|
62
|
+
/** A regra já está em `permissions.allow` (ou na lista pedida) do `.claude/settings.json` do projeto? */
|
|
63
|
+
export function hasAllowRule(root, rule, key = 'allow') {
|
|
29
64
|
try {
|
|
30
65
|
const settings = JSON.parse(readFileSync(join(root, SETTINGS_PATH), 'utf8'));
|
|
31
|
-
const
|
|
32
|
-
return Array.isArray(
|
|
66
|
+
const list = settings.permissions?.[key];
|
|
67
|
+
return Array.isArray(list) && list.includes(rule);
|
|
33
68
|
}
|
|
34
69
|
catch {
|
|
35
70
|
return false;
|
|
@@ -60,7 +95,11 @@ export function mergeSettings(root, additions, now = new Date()) {
|
|
|
60
95
|
const invalid = !isPlainObject(parsed) ||
|
|
61
96
|
(parsed.hooks !== undefined && !isPlainObject(parsed.hooks)) ||
|
|
62
97
|
(parsed.permissions !== undefined && !isPlainObject(parsed.permissions)) ||
|
|
63
|
-
(isPlainObject(parsed.permissions) &&
|
|
98
|
+
(isPlainObject(parsed.permissions) &&
|
|
99
|
+
['allow', 'deny'].some((key) => {
|
|
100
|
+
const list = parsed.permissions[key];
|
|
101
|
+
return list !== undefined && !Array.isArray(list);
|
|
102
|
+
}));
|
|
64
103
|
if (invalid) {
|
|
65
104
|
throw new Error(`O ${SETTINGS_PATH} está com JSON inválido; corrija-o antes de instalar os hooks.`);
|
|
66
105
|
}
|
|
@@ -87,17 +126,19 @@ export function mergeSettings(root, additions, now = new Date()) {
|
|
|
87
126
|
}
|
|
88
127
|
next.hooks = merged;
|
|
89
128
|
}
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
129
|
+
for (const key of ['allow', 'deny']) {
|
|
130
|
+
const rules = additions[key] ?? [];
|
|
131
|
+
if (!rules.length)
|
|
132
|
+
continue;
|
|
133
|
+
const permissions = { ...(next.permissions ?? {}) };
|
|
134
|
+
const list = [...(permissions[key] ?? [])];
|
|
94
135
|
for (const rule of rules) {
|
|
95
|
-
if (
|
|
136
|
+
if (list.includes(rule))
|
|
96
137
|
continue;
|
|
97
|
-
|
|
138
|
+
list.push(rule);
|
|
98
139
|
changed = true;
|
|
99
140
|
}
|
|
100
|
-
next.permissions = { ...permissions,
|
|
141
|
+
next.permissions = { ...permissions, [key]: list };
|
|
101
142
|
}
|
|
102
143
|
if (!changed)
|
|
103
144
|
return { changed: false, backup: null };
|
package/dist/update/update.js
CHANGED
|
@@ -9,7 +9,7 @@ import { HOOKS_ITEM_ID, isHarnessPluginEnabled, projectHooksConfig } from '../in
|
|
|
9
9
|
import { hashContent, LOCK_PATH, LOCK_VERSION, readLock, writeLock } from '../install/lock.js';
|
|
10
10
|
import { itemSources, packageInfo, PROJECT_RULE_PATH, projectRuleContent } from '../install/plan.js';
|
|
11
11
|
import { neededSkillsFor } from '../install/selection.js';
|
|
12
|
-
import { combineHooks, HARNESS_PERMISSIONS, hasAllowRule, mergeSettings } from '../install/settings.js';
|
|
12
|
+
import { combineHooks, HARNESS_DENY, HARNESS_PERMISSIONS, hasAllowRule, mergeSettings } from '../install/settings.js';
|
|
13
13
|
import { adoptLegacyInstall } from './legado.js';
|
|
14
14
|
/** `<id>-legado.md`, com sufixo numérico quando o nome já está em uso. */
|
|
15
15
|
function legacyPath(root, path) {
|
|
@@ -108,6 +108,10 @@ export function checkUpdate(root, catalog = loadCatalog(), legacy, home) {
|
|
|
108
108
|
addItem('rule', 'comentarios', true);
|
|
109
109
|
addItem('hook', 'comentarios', true);
|
|
110
110
|
}
|
|
111
|
+
const permissoesFaltando = [
|
|
112
|
+
...HARNESS_PERMISSIONS.filter((rule) => !hasAllowRule(root, rule)),
|
|
113
|
+
...HARNESS_DENY.filter((rule) => !hasAllowRule(root, rule, 'deny')).map((rule) => `deny ${rule}`),
|
|
114
|
+
];
|
|
111
115
|
return {
|
|
112
116
|
changes,
|
|
113
117
|
lock,
|
|
@@ -115,7 +119,8 @@ export function checkUpdate(root, catalog = loadCatalog(), legacy, home) {
|
|
|
115
119
|
adotada,
|
|
116
120
|
registrarHooks: adotada && !pluginHooks,
|
|
117
121
|
registrarComentarios: adotada,
|
|
118
|
-
permissaoAusente:
|
|
122
|
+
permissaoAusente: permissoesFaltando.length > 0,
|
|
123
|
+
permissoesFaltando,
|
|
119
124
|
};
|
|
120
125
|
}
|
|
121
126
|
/**
|
|
@@ -154,7 +159,7 @@ export function applyUpdate(root, report, options, pkg, now = new Date()) {
|
|
|
154
159
|
return { de: path, para };
|
|
155
160
|
});
|
|
156
161
|
const hooks = combineHooks(report.registrarHooks ? projectHooksConfig() : {}, report.registrarComentarios ? commentsHooksConfig() : {});
|
|
157
|
-
mergeSettings(root, { hooks, allow: HARNESS_PERMISSIONS }, now);
|
|
162
|
+
mergeSettings(root, { hooks, allow: HARNESS_PERMISSIONS, deny: HARNESS_DENY }, now);
|
|
158
163
|
if (report.registrarComentarios)
|
|
159
164
|
ensureCommentsBaseline(root);
|
|
160
165
|
if (report.adotada) {
|
|
@@ -220,7 +225,11 @@ export function describeUpdate(report) {
|
|
|
220
225
|
'a rule de projeto e a permissão do `ai-harness evento`.',
|
|
221
226
|
]
|
|
222
227
|
: [];
|
|
223
|
-
const permission = report.permissaoAusente && !report.adotada
|
|
228
|
+
const permission = report.permissaoAusente && !report.adotada
|
|
229
|
+
? [
|
|
230
|
+
`Faltam permissões do harness em .claude/settings.json (${report.permissoesFaltando.join(', ')}); o --yes as acrescenta.`,
|
|
231
|
+
]
|
|
232
|
+
: [];
|
|
224
233
|
if (!report.changes.length) {
|
|
225
234
|
const status = adopted.length || permission.length ? 'Nenhum arquivo a atualizar.' : 'A instalação está em dia: nenhum arquivo a atualizar.';
|
|
226
235
|
return [...adopted, ...permission, status].join('\n');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fontdata/ai-harness",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.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
|
@@ -26,7 +26,7 @@ Comece por `/harness`, que conduz o setup em etapas.
|
|
|
26
26
|
| `docs/trabalhos/<id>/PLAN.md` | Plano: sprints, fases e tasks (as tasks também no frontmatter) |
|
|
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
|
-
| `docs/trabalhos/<id>/relatorios/TECNICO.md` e `relatorios/CLIENTE.md` | Relatório para engenharia e para cliente
|
|
29
|
+
| `docs/trabalhos/<id>/relatorios/TECNICO.md` e `relatorios/CLIENTE.md` | Relatório para engenharia e para cliente e suporte (sem jargão) |
|
|
30
30
|
| `docs/eventos/<id>.jsonl` | Rastro de eventos (não versionado por padrão) |
|
|
31
31
|
| `.ai-harness/` | Lock da instalação e configuração dos hooks (versionar) |
|
|
32
32
|
|
|
@@ -116,15 +116,32 @@ portões extras (com os achados IMPORTANTE e SUGESTÃO do `code-reviewer`), esta
|
|
|
116
116
|
npx @fontdata/ai-harness evento trabalho_concluido --trabalho <id> --nome executar-plan
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
2.
|
|
119
|
+
2. **Relatórios da entrega** (só trabalho do tipo `feature`; o de `bug` é escrito pelo `/resolver-bug`). Siga
|
|
120
|
+
`references/relatorios-da-entrega.md` e grave, a partir dos templates:
|
|
121
|
+
|
|
122
|
+
- **`relatorios/CLIENTE.md`** (`templates/relatorios/CLIENTE.md`): o que há de novo, para quem, o que preparar,
|
|
123
|
+
como usar, situações comuns e o que ainda não faz — **sem jargão técnico**. É o texto entregue ao cliente e
|
|
124
|
+
aos técnicos de suporte.
|
|
125
|
+
- **`relatorios/TECNICO.md`** (`templates/relatorios/TECNICO.md`): onde está no código, configuração e
|
|
126
|
+
implantação, testes que protegem e o diagnóstico para o suporte.
|
|
127
|
+
|
|
128
|
+
Preencha `arquivos` com os arquivos tocados, grave `status: final` e registre cada um:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npx @fontdata/ai-harness evento relatorio_gerado --trabalho <id> --nome executar-plan --dados '{"caminho":"docs/trabalhos/<id>/relatorios/CLIENTE.md"}'
|
|
132
|
+
npx @fontdata/ai-harness evento relatorio_gerado --trabalho <id> --nome executar-plan --dados '{"caminho":"docs/trabalhos/<id>/relatorios/TECNICO.md"}'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
3. Retire `<id>` da lista `trabalhos_ativos` de `.ai-harness/estado.json`, lendo o arquivo logo antes de gravar
|
|
120
136
|
e preservando os ids das outras sessões.
|
|
121
|
-
|
|
137
|
+
4. Com bloqueios abertos, apresente cada um ao usuário. Cada resposta vira decisão em `DECISOES.md`
|
|
122
138
|
(`decisao_registrada`), o bloqueio é fechado (`bloqueio_fechado`) e a task volta para `pendente` numa nova
|
|
123
139
|
rodada desta skill.
|
|
124
140
|
|
|
125
141
|
## Restrições
|
|
126
142
|
|
|
127
|
-
- **Não** modifique `SPEC.md`, `CLAUDE.md` nem o conteúdo do plano — só o status das tasks e do plano.
|
|
143
|
+
- **Não** modifique `SPEC.md`, `CLAUDE.md` nem o conteúdo do plano — só o status das tasks e do plano. Os
|
|
144
|
+
relatórios da entrega são arquivos novos, não alteração do plano.
|
|
128
145
|
- **Não** implemente fora do escopo do plano nem invente solução alternativa para task bloqueada.
|
|
129
146
|
- **Não** feche task sem `suite_verde` no rastro.
|
|
130
147
|
- Conteúdo em **pt-BR**.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Relatórios da entrega
|
|
2
|
+
|
|
3
|
+
Ao concluir um trabalho do tipo `feature`, o orquestrador entrega dois relatórios. Eles são escritos **depois** da
|
|
4
|
+
execução, a partir do que foi de fato entregue, não do que foi planejado.
|
|
5
|
+
|
|
6
|
+
| Relatório | Quem lê | Para quê |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| `relatorios/CLIENTE.md` | cliente e técnico de suporte | saber o que mudou, como usar e o que responder |
|
|
9
|
+
| `relatorios/TECNICO.md` | engenharia e suporte avançado | manter, implantar e diagnosticar |
|
|
10
|
+
|
|
11
|
+
## De onde tirar o conteúdo
|
|
12
|
+
|
|
13
|
+
1. **`SPEC.md`**, seção *Como vai operar*: perfis, preparação, passo a passo e dúvidas previsíveis.
|
|
14
|
+
2. **O código entregue** (diff do trabalho): nomes reais de telas, botões, mensagens e parâmetros. Onde o código
|
|
15
|
+
diverge da `SPEC.md`, vale o código, e a divergência entra em *Pendências e riscos* do `TECNICO.md`.
|
|
16
|
+
3. **`DECISOES.md`**: regras de negócio escolhidas durante o trabalho que mudam o comportamento para quem usa.
|
|
17
|
+
4. **`BLOQUEIOS.md`** e *Fora do escopo* da `SPEC.md`: o que **não** foi entregue vai para *O que ainda não faz*.
|
|
18
|
+
|
|
19
|
+
Não invente passo, mensagem ou tela que não esteja no código. Sem informação para uma seção, escreva o que falta
|
|
20
|
+
e avise o usuário no encerramento em vez de preencher com suposição.
|
|
21
|
+
|
|
22
|
+
## Como escrever o relatório para o cliente
|
|
23
|
+
|
|
24
|
+
O mesmo texto vai para o cliente e para o técnico de suporte: ele precisa bastar para o técnico atender um
|
|
25
|
+
chamado sem abrir o código. O hook `sem-jargao` avisa quando aparecem termos técnicos.
|
|
26
|
+
|
|
27
|
+
- Frases curtas, voz ativa, sem siglas.
|
|
28
|
+
- Use os nomes como aparecem na tela, entre aspas: clique em "Salvar pedido".
|
|
29
|
+
- Troque o termo técnico pelo efeito: em vez de "o endpoint retorna 404", "o sistema avisa que o pedido não foi
|
|
30
|
+
encontrado".
|
|
31
|
+
- Não cite arquivos, funções, versões, commits ou nomes de sistema interno.
|
|
32
|
+
- Em *Situações comuns*, liste as mensagens de aviso e erro que a funcionalidade mostra, com o texto exato.
|
|
33
|
+
- Em *Perguntas frequentes*, parta das dúvidas previsíveis da `SPEC.md` e das regras de `DECISOES.md`.
|
|
34
|
+
|
|
35
|
+
## Diagnóstico para o suporte (relatório técnico)
|
|
36
|
+
|
|
37
|
+
Para cada situação comum do relatório para o cliente, diga onde o técnico confirma a causa: o log, a tela de
|
|
38
|
+
configuração, o parâmetro ou o registro a conferir. É a ponte entre o que o cliente relata e o que engenharia
|
|
39
|
+
precisaria investigar.
|
|
40
|
+
|
|
41
|
+
## Exemplo — relatório para o cliente
|
|
42
|
+
|
|
43
|
+
> **O que há de novo.** Agora é possível consultar um pedido direto pelo número, sem percorrer a lista inteira.
|
|
44
|
+
>
|
|
45
|
+
> **Antes de começar.** Não é preciso preparar nada.
|
|
46
|
+
>
|
|
47
|
+
> **Como usar.** 1. No menu "Pedidos", clique em "Consultar". 2. Digite o número do pedido. 3. O sistema mostra os
|
|
48
|
+
> itens, o frete e o total.
|
|
49
|
+
>
|
|
50
|
+
> **Situações comuns.** "Pedido não encontrado": o número não existe ou foi digitado errado — confira o número no
|
|
51
|
+
> comprovante do cliente.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
schema_versao: 1
|
|
3
|
+
tipo: relatorio_cliente
|
|
4
|
+
id: "{{id}}"
|
|
5
|
+
trabalho_tipo: feature
|
|
6
|
+
titulo: "{{titulo}}"
|
|
7
|
+
status: rascunho
|
|
8
|
+
criado_em: "{{data}}"
|
|
9
|
+
atualizado_em: "{{data}}"
|
|
10
|
+
arquivos: []
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# {{titulo}}
|
|
14
|
+
|
|
15
|
+
## O que há de novo
|
|
16
|
+
|
|
17
|
+
Em duas ou três frases, o que a pessoa passa a conseguir fazer e por que isso ajuda.
|
|
18
|
+
|
|
19
|
+
## Para quem é
|
|
20
|
+
|
|
21
|
+
Perfis e setores que vão usar, e onde a funcionalidade aparece (tela, menu, relatório).
|
|
22
|
+
|
|
23
|
+
## Antes de começar
|
|
24
|
+
|
|
25
|
+
Permissão, parâmetro, cadastro ou configuração que precisa estar pronto, e quem faz isso — ou "Não é preciso
|
|
26
|
+
preparar nada".
|
|
27
|
+
|
|
28
|
+
## Como usar
|
|
29
|
+
|
|
30
|
+
1. Primeiro passo, com o nome da tela ou do botão como aparece para quem usa.
|
|
31
|
+
2. Próximo passo.
|
|
32
|
+
3. O resultado esperado ao final.
|
|
33
|
+
|
|
34
|
+
## O que muda no que você já fazia
|
|
35
|
+
|
|
36
|
+
Telas, relatórios ou rotinas que passam a se comportar diferente — ou "Nada muda no que já existia".
|
|
37
|
+
|
|
38
|
+
## Situações comuns
|
|
39
|
+
|
|
40
|
+
| O que aparece ou acontece | O que significa | O que fazer |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| Mensagem ou situação | Explicação simples | Ação recomendada |
|
|
43
|
+
|
|
44
|
+
## O que ainda não faz
|
|
45
|
+
|
|
46
|
+
O que ficou para depois, para ninguém prometer ao cliente o que não foi entregue.
|
|
47
|
+
|
|
48
|
+
## Perguntas frequentes
|
|
49
|
+
|
|
50
|
+
**Pergunta que o suporte provavelmente vai ouvir?**
|
|
51
|
+
Resposta curta.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
schema_versao: 1
|
|
3
|
+
tipo: relatorio_tecnico
|
|
4
|
+
id: "{{id}}"
|
|
5
|
+
trabalho_tipo: feature
|
|
6
|
+
titulo: "{{titulo}}"
|
|
7
|
+
status: rascunho
|
|
8
|
+
criado_em: "{{data}}"
|
|
9
|
+
atualizado_em: "{{data}}"
|
|
10
|
+
arquivos: []
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Relatório técnico — {{titulo}}
|
|
14
|
+
|
|
15
|
+
## O que foi entregue
|
|
16
|
+
|
|
17
|
+
Resumo do comportamento implementado, com referência aos critérios de aceite do `SPEC.md`.
|
|
18
|
+
|
|
19
|
+
## Onde está no código
|
|
20
|
+
|
|
21
|
+
Módulos, arquivos e pontos de entrada, com `arquivo:linha`.
|
|
22
|
+
|
|
23
|
+
## Configuração e implantação
|
|
24
|
+
|
|
25
|
+
Variáveis de ambiente, migrações, permissões, parâmetros e a ordem de implantação — ou "nenhuma".
|
|
26
|
+
|
|
27
|
+
## Decisões
|
|
28
|
+
|
|
29
|
+
As decisões de `DECISOES.md` que afetam quem mantém ou dá suporte, com o id (`D-NN`).
|
|
30
|
+
|
|
31
|
+
## Testes que protegem
|
|
32
|
+
|
|
33
|
+
- Testes críticos: caminho e o que cada um verifica.
|
|
34
|
+
- Suíte completa: comando e resultado.
|
|
35
|
+
|
|
36
|
+
## Diagnóstico para o suporte
|
|
37
|
+
|
|
38
|
+
| Sintoma relatado | Onde olhar | Causa provável |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| O que o cliente diz | Log, tela, tabela ou parâmetro | O que costuma estar errado |
|
|
41
|
+
|
|
42
|
+
## Pendências e riscos
|
|
43
|
+
|
|
44
|
+
Itens fora do escopo, bloqueios resolvidos com ressalva e pontos de atenção.
|
|
@@ -37,8 +37,11 @@ os trabalhos que já os tocaram e por quê.
|
|
|
37
37
|
|
|
38
38
|
## Passo 2 — Recorte
|
|
39
39
|
|
|
40
|
-
- **Nova tarefa:** faça de 2 a 3 perguntas, uma por vez, para entender o que deve ser feito.
|
|
41
|
-
|
|
40
|
+
- **Nova tarefa:** faça de 2 a 3 perguntas, uma por vez, para entender o que deve ser feito. Uma delas cobre a
|
|
41
|
+
**operação**: quem vai usar, o que precisa estar configurado ou liberado antes e o que muda no que as pessoas já
|
|
42
|
+
fazem. Pule a pergunta só quando o pedido já responder.
|
|
43
|
+
- Resuma o que foi entendido (o que entra, o que fica fora, critérios de aceite, como vai operar) e **aguarde
|
|
44
|
+
aprovação**.
|
|
42
45
|
|
|
43
46
|
Toda ambiguidade que você resolver por conta própria vira decisão registrada (Passo 5), sempre com a escolha
|
|
44
47
|
mais conservadora.
|
|
@@ -48,6 +51,8 @@ mais conservadora.
|
|
|
48
51
|
1. Defina o id `AAAA-MM-DD-<slug>` (data de hoje, slug curto em minúsculas, sem acento).
|
|
49
52
|
2. Crie `docs/trabalhos/<id>/SPEC.md` a partir de `templates/SPEC.md`, preenchendo `{{id}}`, `{{titulo}}` e
|
|
50
53
|
`{{data}}`. Os nomes dos arquivos da pasta são sempre em caixa alta.
|
|
54
|
+
A seção **Como vai operar** é obrigatória: é dela que o `/executar-plan` tira o relatório para o cliente e para
|
|
55
|
+
o suporte. Funcionalidade sem efeito visível para quem usa (ajuste interno, rotina técnica) diz isso na seção.
|
|
51
56
|
3. Registre o início do trabalho:
|
|
52
57
|
|
|
53
58
|
```bash
|
|
@@ -63,6 +68,8 @@ Crie `docs/trabalhos/<id>/PLAN.md` a partir de `templates/PLAN.md`, seguindo `re
|
|
|
63
68
|
- tasks paralelizáveis da mesma fase não tocam os mesmos arquivos;
|
|
64
69
|
- `arquivos` do frontmatter lista todos os arquivos (ou pastas) que as tasks vão criar ou alterar — é por ele que
|
|
65
70
|
o `/executar-plan` impede dois trabalhos de mexerem no mesmo código ao mesmo tempo;
|
|
71
|
+
- `relatorios_entrega: true` fica no frontmatter, como vem do template: com ela, o `doctor` exige
|
|
72
|
+
`relatorios/TECNICO.md` e `relatorios/CLIENTE.md` quando o plano chega a `concluido`;
|
|
66
73
|
- **plano condensado:** com 1 sprint e 1 fase, use `condensado: true` e omita os títulos de sprint e fase — o
|
|
67
74
|
contrato das tasks continua completo.
|
|
68
75
|
|
|
@@ -85,7 +92,8 @@ npx @fontdata/ai-harness evento decisao_registrada --trabalho <id> --nome nova-t
|
|
|
85
92
|
## Passo 7 — 🚦 GATE de aprovação
|
|
86
93
|
|
|
87
94
|
Mostre ao usuário: os caminhos gravados, as tasks por fase (quais rodam em paralelo), quantos agents serão
|
|
88
|
-
necessários
|
|
95
|
+
necessários, as decisões registradas e o resumo de **como vai operar**. Avise que, ao concluir, o `/executar-plan`
|
|
96
|
+
entrega `relatorios/TECNICO.md` e `relatorios/CLIENTE.md`. **Peça aprovação explícita.**
|
|
89
97
|
|
|
90
98
|
- Com aprovação, grave `status: aprovado` no `SPEC.md`.
|
|
91
99
|
- **Start inicial (fluxo `/harness`):** o próximo passo normalmente é a etapa scaffold do `/harness` — **não** dispare a execução.
|
|
@@ -24,6 +24,17 @@ Conclusão (não existe, existe parcialmente ou já existe) e a evidência encon
|
|
|
24
24
|
|
|
25
25
|
- Comportamento 1, descrito do ponto de vista de quem usa.
|
|
26
26
|
|
|
27
|
+
## Como vai operar
|
|
28
|
+
|
|
29
|
+
Base do relatório para o cliente, escrito no encerramento do `/executar-plan`. Responda do ponto de vista de quem
|
|
30
|
+
usa o sistema e de quem dá suporte.
|
|
31
|
+
|
|
32
|
+
- **Quem usa:** perfis, telas ou menus onde a funcionalidade aparece.
|
|
33
|
+
- **Antes de usar:** permissão, parâmetro, cadastro ou configuração necessários — ou "nada".
|
|
34
|
+
- **Passo a passo esperado:** o caminho principal, em poucas etapas.
|
|
35
|
+
- **O que muda no que já existe:** telas, relatórios ou rotinas que passam a se comportar diferente.
|
|
36
|
+
- **Dúvidas previsíveis:** o que o suporte provavelmente vai ouvir e a resposta.
|
|
37
|
+
|
|
27
38
|
## Fora do escopo
|
|
28
39
|
|
|
29
40
|
- O que fica explicitamente para depois.
|