wendkeep 0.77.0 → 0.79.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.en.md +58 -3
  3. package/README.md +58 -3
  4. package/docs/en/commands/changes-and-verification.md +74 -2
  5. package/docs/en/commands/operating-profiles.md +49 -5
  6. package/docs/en/commands/verify.md +67 -5
  7. package/docs/en/commands/worktrees.md +39 -4
  8. package/docs/pt-BR/commands/changes-and-verification.md +73 -2
  9. package/docs/pt-BR/commands/operating-profiles.md +51 -5
  10. package/docs/pt-BR/commands/verify.md +67 -6
  11. package/docs/pt-BR/commands/worktrees.md +38 -3
  12. package/hooks/active-context-store.mjs +530 -2
  13. package/hooks/change-core.mjs +203 -123
  14. package/hooks/harness-doctor.mjs +51 -1
  15. package/hooks/obsidian-common.mjs +175 -9
  16. package/hooks/spec-core.mjs +118 -36
  17. package/package.json +2 -2
  18. package/packages/harness/src/sensors-core.mjs +57 -3
  19. package/packages/vault/src/evidence-envelope.mjs +73 -0
  20. package/packages/vault/src/index.mjs +1 -0
  21. package/packages/vault/src/memory-handoff.mjs +46 -5
  22. package/packages/vault/src/vault-path-safety.mjs +11 -0
  23. package/schema/wendkeep.evidence-envelope-v2.schema.json +92 -0
  24. package/schema/wendkeep.provenance-receipt-v2.schema.json +66 -0
  25. package/src/archive-operation-lock.mjs +235 -0
  26. package/src/change.mjs +1832 -48
  27. package/src/delivery.mjs +724 -67
  28. package/src/evidence-envelope.mjs +288 -0
  29. package/src/memory.mjs +2 -1
  30. package/src/provenance-gate.mjs +575 -0
  31. package/src/provenance-sources.mjs +547 -0
  32. package/src/receipt-ledger.mjs +841 -0
  33. package/src/release-provenance.mjs +48 -0
  34. package/src/skills-seed.mjs +11 -5
  35. package/src/verify.mjs +85 -22
  36. package/src/worktree-cleanup.mjs +1733 -118
  37. package/src/worktree.mjs +94 -5
@@ -30,7 +30,8 @@ npx wendkeep change status [slug] [--session <id>]
30
30
  npx wendkeep spec effective [--change <slug>] [--session <id>]
31
31
  npx wendkeep sensors list
32
32
  npx wendkeep verify [--deep] [--change <slug>] [--session <id>]
33
- npx wendkeep change archive <slug> [--session <id>]
33
+ npx wendkeep change archive <slug> [--json] [--session <id>]
34
+ npx wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]
34
35
  ```
35
36
 
36
37
  ## Opções e códigos de saída
@@ -47,6 +48,10 @@ npx wendkeep change archive <slug> [--session <id>]
47
48
  somente um contexto ativo inequívoco da worktree é aceito; ambiguidade retorna exit `2`.
48
49
  - `change relink [--apply]` e `change backlink [--apply]` reparam o grafo; dry-run é o padrão.
49
50
  - `change abandon <slug>` descarta sem ADR; `archive --force` exige decisão humana explícita.
51
+ - `change archive recover <operation-id> --change <slug> [--spec-action rollback|resume]` inspeciona
52
+ uma transação pendente por padrão; com `rollback` ou `resume`, converge somente a promoção de
53
+ specs preparada no journal, sob lock e validação. Não promove a change, não apaga o journal e não
54
+ inventa reconciliação.
50
55
  - `wendkeep spec list|show|effective|migrate|rebase` administra contratos vivos e deltas.
51
56
  - `wendkeep sensors list|add` administra provas executáveis.
52
57
  - Exit `0` indica comando concluído; os gates usam exit `1` para prova vermelha e exit `2` para
@@ -76,7 +81,71 @@ npx wendkeep sensors add api-contracts "npm run test:contracts" --severity criti
76
81
  A change arquivada move seu delta para o spec vivo quando aplicável e preserva proposta,
77
82
  tarefas/evidência e design quando existente. GOVERN/ASSURE geram ADR; GUIDE compacta sem impacto
78
83
  de contrato não gera ADR automático. O archive só passa com tarefas fechadas, sensores exigidos
79
- verdes e verdict atual.
84
+ verdes e verdict atual ligado ao mesmo Evidence Envelope v2. Evidência v1 é mostrada como
85
+ `legacy-unbound`; `change status <slug>` também diagnostica `bound`, `stale` e `context-mismatch`.
86
+ O archive compara `evidenceEnvelopeId` e o `evidenceBinding` completo de package/verdict com o
87
+ checkout provado. Se houver divergência, volte à worktree/sessão correta e rode `verify`,
88
+ `verify --deep` e `wk-verify` novamente. Campos, normalização textual/binária, códigos e recovery
89
+ estão detalhados no [guia de verify](verify.md).
90
+
91
+ O gate comum reclassifica envelope, package e verdict como `verified`, `reported`,
92
+ `legacy-unbound`, `stale`, `conflict` ou `unproven`; somente `verified` permite archive. Um bloqueio
93
+ retorna `WENDKEEP_PROVENANCE_GATE_BLOCKED`: estabilize/recupere o contexto, rode `verify`, depois
94
+ `verify --deep` e obtenha novo passe `wk-verify`. `--force` pode dispensar somente tarefa aberta;
95
+ para proveniência, integridade, package e verdict ele **não** altera o resultado nem promove spec/ADR.
96
+ Os erros de ledger são `WENDKEEP_RECEIPT_LEDGER_BUSY`, `WENDKEEP_RECEIPT_LEDGER_CONFLICT`,
97
+ `WENDKEEP_RECEIPT_LEDGER_CORRUPT` e `WENDKEEP_RECEIPT_LEDGER_TRUNCATED`. No bloqueio, use a saída
98
+ `--json` sanitizada (`state`, `reasonCodes`, `diagnostics`, `repair.command`), execute o recovery
99
+ indicado e rode `npx --no-install wendkeep verify --deep --json`; preserve e recapture a prova, sem
100
+ editar ledger/checkpoint ou expor stderr, token, URL privada ou path do Vault.
101
+
102
+ ### Contrato pós-fix do archive
103
+
104
+ Antes da mutação, faça a recaptura final com `wendkeep verify --deep --change <slug>`. O package
105
+ e o verdict devem estar completos e canônicos, com binding do mesmo checkout, change, tarefas,
106
+ spec e sensores. O archive grava primeiro um receipt de autorização no ledger separado
107
+ `change-archive-receipts-v2`; só depois de validá-lo pode promover spec/ADR ou mover a change.
108
+ `change archive --json` expõe o resultado serializável com os campos `state`, `reason_codes`,
109
+ `diagnostics` e `repair`. Corrupção ou truncamento no ledger de prova ou no ledger de archive
110
+ bloqueia fechado antes de qualquer escrita. `--force` não bypassa proveniência nem integridade,
111
+ nem package/verdict, corrupção ou truncamento. O recovery exato é repetir
112
+ `wendkeep verify --deep --change <slug>` no checkout correto.
113
+
114
+ A mutação adquire o lock do runtime `.brain/runtime/change-archive-operation.lock` e abre uma
115
+ transação privada ASCII em `.brain/runtime/archive-transactions/<uuid>/{original,authorized}`.
116
+ Ela renomeia atomicamente a change viva para `original`, confere o digest e promove somente a
117
+ cópia `authorized`; o namespace público nunca é fonte de publicação. Em caso de falha de
118
+ selagem ou divergência `WENDKEEP_ARCHIVE_INPUT_CHANGED` antes da promoção, o snapshot
119
+ `authorized` é removido e `original` é restaurado sem promoção parcial. O archive bem-sucedido
120
+ mantém o journal `completed`; o finalizer pós-release valida os digests de `original` e do destino
121
+ publicado, mas retém `original` e a transação, sem cleanup destrutivo automático.
122
+
123
+ O lock do archive é um `directory lock`: o diretório canônico contém marker específico do token e
124
+ lease. A aquisição prepara um diretório irmão `.pending`, escreve owner/lease e publica por rename
125
+ atômico para o lock; não usa hardlink e reobserva colisões com no máximo 3 tentativas de topologia.
126
+ Owner vivo retorna `WENDKEEP_ARCHIVE_BUSY`; owner morto pode sofrer reap seguro sem apagar sucessor.
127
+ Estrutura/marker inválido retorna `WENDKEEP_ARCHIVE_LOCK_UNAVAILABLE`; perda de ownership retorna
128
+ `WENDKEEP_ARCHIVE_LOCK_OWNERSHIP_LOST`.
129
+
130
+ Cada operação mantém `archive-transaction.json` com as fases `prepared` → `isolated` → `copied` →
131
+ `sealed` → `published` → `promotion-prepared` → `promotion-applied` → `completed` ou
132
+ `recovery-required`. Um journal pending bloqueia novo archive do mesmo slug antes do gate. Em
133
+ colisão ou falha pós-publicação, `original` permanece retido e o estado é
134
+ `published-recovery-required`. Use a inspeção fail-closed e idempotente
135
+ `wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]`;
136
+ sem `--spec-action`, só retorna ações sanitizadas. `rollback` restaura before-images e `resume`
137
+ converge after-images de uma promoção `promotion-prepared`; ambos preservam o journal para nova
138
+ reconciliação.
139
+
140
+ A promoção multi-spec é uma unidade atômica: captura before-images/digests de todos os capabilities,
141
+ faz rollback de todos os alvos (incluindo estado/README) em falha antes ou depois da escrita e só
142
+ permite retry após a reconciliação do journal e nova verificação. O finalizer pós-release valida os
143
+ digests do original e do destino, mas retém o journal `completed` e `original`; sem cleanup
144
+ destrutivo automático. Os campos sanitizados
145
+ `operation_id` e `transaction_phase` acompanham o diagnóstico; `repair.command` aponta para
146
+ `wendkeep change archive recover <operation-id> --change <slug>` quando há operação identificada.
147
+ Texto e --json usam o mesmo diagnóstico sanitizado com code, operation, state, blocker, expected,
148
+ observed, recovery, reason_codes, diagnostics e repair.
80
149
 
81
150
  ## Cerca de escopo para ferramentas
82
151
 
@@ -105,6 +174,8 @@ exige uma nova seleção/lease; não use autorização de outra conversa.
105
174
  - Sensor não executado: mantenha uma ou mais tags `[sensor:id]` na mesma linha do checkbox. Todos
106
175
  os IDs distintos dessa linha são exigidos e executados uma vez, na ordem declarada.
107
176
  - Evidência stale: rode novamente `verify` e `verify --deep` depois de alterar tarefas/spec.
177
+ - Evidência de outra worktree/sessão: retorne ao contexto causal correto; ela não satisfaz o
178
+ archive atual mesmo que todos os sensores estejam verdes.
108
179
  - Rebase em conflito: resolva o delta ou use `--accept-current` apenas quando isso for a decisão.
109
180
 
110
181
  ## Próximos passos
@@ -59,7 +59,7 @@ npx wendkeep flow finish <id> [--session <id>]
59
59
  npx wendkeep flow promote <id> [--change-slug <slug>] [--session <id>]
60
60
  npx wendkeep delivery start [id] --allow <capability> [--source-change <slug>] [--source-commit <sha>] [--session <id>]
61
61
  npx wendkeep delivery status [id] [--session <id>]
62
- npx wendkeep delivery finish [id] [--target <ref>] [--ci-url <url>] [--version <x.y.z>] [--npm-integrity <sha512>] [--release-url <url>] [--session <id>]
62
+ npx wendkeep delivery finish [id] [--target <remote>/<branch>] [--ci-url <url>] [--version <x.y.z>] [--npm-integrity <sha512>] [--release-url <url>] [--session <id>]
63
63
  npx wendkeep delivery abandon [id] --reason <texto> [--session <id>]
64
64
  ```
65
65
 
@@ -179,13 +179,38 @@ harness nativo da LLM.
179
179
  `contract_impact` e `operation_risk` são dimensões independentes. `delivery start` captura repo,
180
180
  branch/worktree, SHA, change de origem e capabilities em `.brain/runtime/deliveries/`; não cria
181
181
  pasta em `08-Mudanças`, delta, spec ou ADR.
182
- - `delivery finish` exige working tree limpa, comprova que o target contém o commit de origem e,
183
- para capability `publish`, exige CI, versão, integridade npm e GitHub Release. O receipt é
184
- append-only em `.brain/runtime/delivery-receipts.jsonl`. Se código/config precisar mudar, a
185
- delivery para com `WENDKEEP_DELIVERY_IMPLEMENTATION_REQUIRED` e o trabalho volta a implementation.
182
+ - Para as capabilities `git:merge` e `git:push`, `delivery finish` exige `--target
183
+ <remote>/<branch>` (por exemplo, `--target origin/main`). `delivery start` vincula o remote
184
+ `origin` ao `repository` esperado; `finish` resolve o destino com `git ls-remote` e bloqueia a
185
+ delivery antes dos adapters de proveniência se o target não puder ser resolvido ou o binding
186
+ divergir.
187
+ - `delivery finish` exige working tree limpa e rederiva source/target. Merge/push prova
188
+ ancestralidade; tag prova package/version e tag no target; `publish` consulta CI, NPM e GitHub
189
+ Release ligados ao mesmo commit, versão, integrity e notas. No modo offline, uma claim fica
190
+ `reported` e não vira `verified`; a conclusão bloqueia sem gravar receipt. Novos receipts formam
191
+ `.brain/runtime/delivery-receipts-v2.jsonl`, com hash chain e checkpoint; o v1 é somente
192
+ `legacy-unbound`. `WENDKEEP_PROVENANCE_GATE_BLOCKED` traz o recovery. Se código/config precisar
193
+ mudar, `WENDKEEP_DELIVERY_IMPLEMENTATION_REQUIRED` devolve o trabalho a implementation.
194
+ O gate usa a mesma taxonomia `verified`, `reported`, `legacy-unbound`, `stale`, `conflict` e
195
+ `unproven`. Os erros do ledger são `WENDKEEP_RECEIPT_LEDGER_BUSY`,
196
+ `WENDKEEP_RECEIPT_LEDGER_CONFLICT`, `WENDKEEP_RECEIPT_LEDGER_CORRUPT` e
197
+ `WENDKEEP_RECEIPT_LEDGER_TRUNCATED`; consulte `state`, `reasonCodes`, `diagnostics` e
198
+ `repair.command` sanitizados em `--json`, execute o recovery indicado e recapture a prova, sem editar
199
+ ledger/checkpoint ou expor stderr, tokens, URLs privadas e paths do Vault.
186
200
  - Em Vault multi-contexto, `active_contexts[].delivery_id` é a autoridade. `--session <id>` escolhe
187
201
  explicitamente a work session; sem ela, somente um active context inequívoco da worktree pode ser
188
202
  usado. Status, finish e abandon implícitos consultam esse binding, não um ponteiro global.
203
+ - Falhas de `delivery`, tanto em texto quanto em `delivery --json`, expõem o mesmo diagnóstico
204
+ PROV-8: `code` estável, `operation`, `state`, primeiro `blocker`, `expected`/`observed`
205
+ sanitizados e `recovery` objetivo. Stderr do Git, tokens, URLs privadas e caminhos privados não
206
+ são propagados.
207
+ - Receipts `delivery.completed` e `delivery.abandoned` vinculam `repository_id`, o `repository`
208
+ público no formato `owner/repo`, `worktree_id`, `work_session_id`, `change_slug` e `branch`.
209
+ O path privado da worktree nunca entra no receipt. Na finalização contextual, o receipt entra no
210
+ ledger e o `state` durável é gravado antes de limpar `active_contexts[].delivery_id`. Um retry
211
+ converge para o mesmo receipt quando o binding já está limpo ou ainda vinculado. Em
212
+ `delivery abandon`, o motivo livre vira `reason_digest`; o texto bruto não entra no ledger nem no
213
+ estado.
189
214
  - `CURRENT_DELIVERY` é somente uma projeção derivada: contém o ID quando existe um único contexto
190
215
  ativo inequívoco com delivery e fica vazio com zero ou múltiplos contextos.
191
216
  `WENDKEEP_DELIVERY_CONTEXT_MISMATCH` indica que o ID explícito pertence a outro contexto; nenhum
@@ -274,6 +299,27 @@ continuam disponíveis e executam seus próprios contratos. Um FLOW concluído d
274
299
  consultável; um FLOW promovido passa a seguir o lifecycle normal de change. Uma delivery concluída
275
300
  deixa receipt sem gerar ADR; GUIDE compacto arquiva o resultado sem spec/design/ADR artificiais.
276
301
 
302
+ Para archive em GOVERN/ASSURE, o `directory lock` usa marker específico do token e lease: a
303
+ aquisição prepara um diretório irmão `.pending` e publica por rename atômico, sem hardlink, com no
304
+ máximo 3 tentativas de topologia. Owner vivo retorna `WENDKEEP_ARCHIVE_BUSY`, owner morto pode ser
305
+ reapado com segurança, marker inválido retorna `WENDKEEP_ARCHIVE_LOCK_UNAVAILABLE` e perda de
306
+ ownership retorna `WENDKEEP_ARCHIVE_LOCK_OWNERSHIP_LOST`. O journal `archive-transaction.json`
307
+ percorre `prepared` → `isolated` → `copied` → `sealed` → `published` → `promotion-prepared` →
308
+ `promotion-applied` → `completed` ou `recovery-required`; um journal pending bloqueia novo archive
309
+ do mesmo slug antes do gate.
310
+ `original` fica retido em collision/falha pós-publicação e `published-recovery-required` exige
311
+ inspeção. `operation_id` e `transaction_phase` aparecem apenas sanitizados. Use
312
+ `wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]`:
313
+ sem `--spec-action`, inspeção somente-leitura, fail-closed e idempotente, sem promoção, deleção ou
314
+ reconciliação inventada; `rollback` restaura before-images e `resume` converge after-images de
315
+ `promotion-prepared`, retendo o journal. Quando há operation ID, `repair.command` aponta para esse
316
+ recovery; não trate `command:null` como fluxo normal.
317
+
318
+ A promoção multi-spec é atômica, com before-images/digests, rollback dos alvos antes/depois da
319
+ escrita e retry somente após reconciliação e nova verificação. O finalizer pós-release valida os
320
+ digests do original e do destino publicado, mas o `completed` journal mantém o `original` retido;
321
+ sem cleanup destrutivo automático.
322
+
277
323
  ## Erros comuns e diagnóstico
278
324
 
279
325
  - Perfil desconhecido: use exatamente `OFF`, `FLOW`, `GUIDE`, `GOVERN` ou `ASSURE`.
@@ -43,7 +43,8 @@ npx wendkeep change use <slug>
43
43
  - **Exit 1:** o gate executou, mas ao menos um sensor crítico ficou vermelho ou um mutante
44
44
  sobreviveu.
45
45
  - **Exit 2:** uso/contexto inválido, como `no change (--change or active)`, vault ausente,
46
- change inexistente ou `wendkeep.sensors.json` inválido.
46
+ change inexistente, projeto fora de um repositório Git, `wendkeep.sensors.json` inválido ou
47
+ `WENDKEEP_EVIDENCE_HEAD_CHANGED`.
47
48
 
48
49
  `verify --deep` gera `verificacao.json`; ele não substitui o verificador. A skill `wk-verify`
49
50
  precisa ser executada por autor diferente e grava `verdict.json`.
@@ -73,11 +74,60 @@ npx wendkeep memory status --gate --vault .MeuApp-vault
73
74
 
74
75
  ## Resultado esperado
75
76
 
76
- `evidencia.json` contém resultados dos sensores e um selo liga a prova ao hash atual de
77
- `tarefas.md`. Quando um sensor fica vermelho, sua entrada recebe somente um diagnóstico local
78
- sanitizado e limitado a 2.000 caracteres; stdout/stderr de sensores verdes não é persistido. No
79
- deep, o pacote contém requisitos, tarefas e evidência suficientes para revisão read-only; o
80
- verdict cobre cada `[req:]` antes do archive.
77
+ `evidencia.json` segue o [schema público v2](../../../schema/wendkeep.evidence-envelope-v2.schema.json).
78
+ O envelope liga `project_id`, `repository_id`, `worktree_id`, `work_session_id`, change e branch a
79
+ `base_sha`, `head_sha`, `index_tree_sha`, `worktree_digest`, tarefas, spec e configuração dos
80
+ sensores por SHA-256 completo. O digest cobre staged, unstaged, untracked, rename e delete; paths
81
+ usam `/`, texto normaliza CRLF/CR para LF e binários preservam bytes. A classificação binária
82
+ respeita atributos Git `binary`/`-text` e extensões binárias conhecidas (incluindo `.bin`); arquivos
83
+ ignorados não entram.
84
+
85
+ Cada sensor registra comando sanitizado e seu hash, início/fim, duração, exit code, digest da saída
86
+ e tail sanitizado de até 2.000 caracteres. Os artefatos são publicados por temporário path-safe no
87
+ mesmo diretório e rename atômico. No deep, `verificacao.json` e `verdict.json` carregam o mesmo
88
+ `evidenceEnvelopeId` e `evidenceBinding` completo; o verificador independente deve preservar ambos
89
+ no verdict.
90
+
91
+ Evidência v1 continua legível como `legacy-unbound`, nunca como autoridade equivalente. Rode
92
+ `wendkeep change status <slug>` para ver `bound`, `stale` ou `context-mismatch`.
93
+
94
+ O gate de proveniência normaliza a visão legada numa taxonomia única: `verified` quando toda prova
95
+ obrigatória está fresca e vinculada; `reported` para claim registrada sem observação autoritativa;
96
+ `legacy-unbound` para v1; `stale` para um snapshot anterior; `conflict` para identidade/conteúdo
97
+ incompatível; e `unproven` para prova ausente ou insuficiente. A precedência é `conflict` > `stale`
98
+ > `legacy-unbound` > `unproven` > `reported` > `verified`, e somente `verified` fecha o gate.
99
+
100
+ Para o archive pós-fix, o passe final é `wendkeep verify --deep --change <slug>`. Ele deve deixar
101
+ package e verdict completos e canônicos, ligados ao mesmo checkout, change, tarefas, spec e
102
+ sensores. O archive grava o receipt de autorização antes da mutação no ledger separado
103
+ `change-archive-receipts-v2`. Sua saída `change archive --json` é serializável e expõe `state`,
104
+ `reason_codes`, `diagnostics` e `repair`; corrupção ou truncamento de ledger bloqueia fechado.
105
+ `--force` não bypassa proveniência ou integridade. O recovery exato é repetir
106
+ `wendkeep verify --deep --change <slug>` depois de estabilizar o contexto.
107
+
108
+ O archive usa um `directory lock` com marker específico do token e lease. A aquisição prepara um
109
+ diretório irmão `.pending` e publica-o por rename atômico, sem hardlink, com no máximo 3 tentativas
110
+ de topologia. Owner vivo produz `WENDKEEP_ARCHIVE_BUSY`; owner morto só é reapado com observação
111
+ segura; marker/estrutura inválida produz `WENDKEEP_ARCHIVE_LOCK_UNAVAILABLE`; perda de ownership
112
+ produz `WENDKEEP_ARCHIVE_LOCK_OWNERSHIP_LOST`. O manifest `archive-transaction.json` registra
113
+ `prepared` → `isolated` → `copied` → `sealed` → `published` → `promotion-prepared` →
114
+ `promotion-applied` → `completed` ou `recovery-required`. Um journal pending bloqueia novo archive
115
+ do mesmo slug antes do gate. Em
116
+ collision ou falha pós-publicação, `original` é retido e o estado
117
+ `published-recovery-required` bloqueia retry destrutivo. `operation_id` e `transaction_phase` são
118
+ campos sanitizados. Inspecione com
119
+ `wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]`:
120
+ sem `--spec-action`, é somente-leitura, fail-closed e idempotente, sem promoção, deleção ou
121
+ reconciliação inventada. `rollback` restaura before-images e `resume` converge after-images de uma
122
+ promoção `promotion-prepared`, mantendo o journal para reconciliação. Quando há operation ID,
123
+ `repair.command` aponta para `wendkeep change archive recover <operation-id> --change <slug>`; não
124
+ trate `command:null` como fluxo normal.
125
+
126
+ A promoção multi-spec é uma unidade atômica: captura before-images/digests de todos os capabilities,
127
+ faz rollback de todos os alvos (incluindo estado/README) em falha antes ou depois da escrita e só
128
+ permite retry após reconciliação do journal e nova verificação. O finalizador pós-release valida os
129
+ digests do original e do destino, mas o `completed` journal mantém o `original` retido; sem cleanup
130
+ destrutivo automático. Falha mantém `published-recovery-required`.
81
131
 
82
132
  ## Erros comuns e diagnóstico
83
133
 
@@ -87,6 +137,17 @@ verdict cobre cada `[req:]` antes do archive.
87
137
  - Gate vermelho: consulte o campo `note` limitado da entrada em `evidencia.json`, corrija a causa
88
138
  e repita; não use `archive --force` por conta própria.
89
139
  - Verdict stale/ausente: regenere `--deep` e peça novo passe independente.
140
+ - `WENDKEEP_EVIDENCE_HEAD_CHANGED`: o HEAD mudou enquanto os sensores rodavam; estabilize o
141
+ checkout e repita. A evidência anterior não foi substituída.
142
+ - `legacy-unbound`, `stale` ou `context-mismatch`: volte à worktree/sessão correta, recupere o
143
+ contexto se necessário e rode `verify` + `verify --deep` novamente.
144
+ - `WENDKEEP_PROVENANCE_GATE_BLOCKED`: leia `state`, `reasonCodes` e `repair`; não reutilize uma
145
+ prova de outra branch/worktree/sessão. Rode o comando indicado e recapture o envelope.
146
+ - Os erros `WENDKEEP_RECEIPT_LEDGER_BUSY`, `WENDKEEP_RECEIPT_LEDGER_CONFLICT`,
147
+ `WENDKEEP_RECEIPT_LEDGER_CORRUPT` e `WENDKEEP_RECEIPT_LEDGER_TRUNCATED` exigem preservar o
148
+ ledger/checkpoint e executar o recovery objetivo em `repair.command` (ou
149
+ `npx --no-install wendkeep verify --deep --json` para uma prova fresca); a saída textual/JSON
150
+ permanece sanitizada e não contém stderr bruto, tokens, URLs privadas ou paths do Vault.
90
151
  - Mutantes sobreviventes: fortaleça o teste discriminante; após três rodadas, revise manualmente.
91
152
 
92
153
  ## Próximos passos
@@ -58,6 +58,31 @@ interrompido/failed e uma recuperação objetiva.
58
58
  head comprovado; divergência ou rede indisponível bloqueia. Branch já ausente é sucesso idempotente.
59
59
  `--open-main` abre a worktree principal somente depois da conclusão.
60
60
 
61
+ ### Cleanup pós-fix: retomada crash-safe
62
+
63
+ A operação de cleanup é **crash-safe** e retomável antes do receipt, depois do receipt e antes do
64
+ finalize, e depois do finalize: um crash em qualquer fronteira preserva operation/state e permite
65
+ repetir a mesma prova sem duplicar remoção ou receipt. O subject de cada operação inclui todos os
66
+ active contexts, actor, pr, head e merge. O PR canônico é a autoridade resolvida pelo adapter
67
+ GitHub; texto fornecido pelo chamador não substitui essa autoridade.
68
+
69
+ O HEAD é rederivado antes do finalize, a partir do checkout, e comparado ao head/merge comprovado. O reason
70
+ fica sanitizado e recebe digest para auditoria, sem armazenar path privado, token ou stderr.
71
+ Checkpoint ausente ou inválido é WENDKEEP_RECEIPT_LEDGER_TRUNCATED. Receipt v1 continua
72
+ legacy-unbound e nunca autoriza cleanup.
73
+
74
+ Texto e --json expõem sempre operation, state, blocker, recovery e os códigos estáveis
75
+ WENDKEEP_WORKTREE_CLEANUP_BUSY, WENDKEEP_RECEIPT_LEDGER_CORRUPT e
76
+ WENDKEEP_RECEIPT_LEDGER_TRUNCATED; a recuperação retoma a reserva ou indica o reparo objetivo.
77
+
78
+ O gate comum classifica a operação de cleanup e bloqueia antes da mutação, inclusive em finish,
79
+ remove e cleanup --apply. Depois do append, o receipt é classificado pelo mesmo gate antes do
80
+ finalize; falha de proveniência não finaliza nem marca sucesso. Um estado cleaned sem receipt v2
81
+ fica bloqueado como unproven; um receipt v1 não autoriza e permanece legacy-unbound.
82
+
83
+ Texto e --json de bloqueio mantêm o diagnóstico equivalente e sanitizado: code, operation, state,
84
+ blocker, expected, observed, recovery, reason_codes, diagnostics e repair.
85
+
61
86
  ## Cleanup, remove e prune
62
87
 
63
88
  `cleanup --merged` e `prune` são dry-run por padrão. `--dry-run` apenas torna essa intenção
@@ -70,9 +95,19 @@ mas mantém todo o preflight e preserva as branches local e remota.
70
95
 
71
96
  O registry fica no Git common-dir, em `wendkeep/worktrees-v1.json`, sob lock multiprocesso. Ele
72
97
  guarda identidade do repositório/worktree, binding canônico, PR e estado transitório de cleanup;
73
- `.wendkeep.json` permanece inalterado. Receipts ficam em
74
- `wendkeep/worktree-cleanup-receipts-v1.jsonl`. `.worktrees/` entra no ignore versionado e no exclude
75
- privado. A saída JSON de `list`/`status` não expõe path nem conteúdo do Vault.
98
+ `.wendkeep.json` permanece inalterado. Novos receipts ficam em
99
+ `wendkeep/worktree-cleanup-receipts-v2.jsonl`: cada linha inclui `previous_hash` e `receipt_hash`, e
100
+ um checkpoint separado fixa a sequência/hash/tamanho validado. O v1 permanece legível como
101
+ `legacy-unbound`, sem append ou reescrita silenciosa. `WENDKEEP_RECEIPT_LEDGER_CORRUPT` indica
102
+ adulteração/JSON parcial; `WENDKEEP_RECEIPT_LEDGER_TRUNCATED` indica cauda removida. Ambos bloqueiam
103
+ antes da remoção e exigem diagnosticar o store, nunca inventar receipt. `.worktrees/` entra no
104
+ ignore versionado e no exclude privado; JSON de `list`/`status` não expõe path/conteúdo do Vault.
105
+ O gate de cleanup usa `verified`, `reported`, `legacy-unbound`, `stale`, `conflict` e `unproven`;
106
+ `WENDKEEP_PROVENANCE_GATE_BLOCKED` e os códigos `WENDKEEP_RECEIPT_LEDGER_BUSY`,
107
+ `WENDKEEP_RECEIPT_LEDGER_CONFLICT`, `WENDKEEP_RECEIPT_LEDGER_CORRUPT` e
108
+ `WENDKEEP_RECEIPT_LEDGER_TRUNCATED` falham fechados. O recovery objetivo lê o JSON sanitizado de
109
+ `worktree status <slug> --json`, executa `repair.command` quando presente e recaptura a prova; não
110
+ edite ledger/checkpoint nem exponha stderr, tokens, URLs privadas ou paths do Vault.
76
111
 
77
112
  `create` é idempotente quando slug, path e branch já correspondem. Colisões falham fechadas.
78
113
  Falhas depois da reserva ficam como `failed`; rode `worktree status <slug>` e siga `recovery`.