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
package/CHANGELOG.md CHANGED
@@ -4,6 +4,70 @@ All notable changes to **wendkeep** are documented here. Format based on
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this project follows
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.79.0] — 2026-08-23
8
+
9
+ ### Added
10
+
11
+ - **Gate único de proveniência.** Archive, delivery, release e cleanup rederivam a autoridade no
12
+ subject atual com a taxonomia `verified`, `reported`, `legacy-unbound`, `stale`, `conflict` e
13
+ `unproven`; somente `verified` satisfaz prova obrigatória, com códigos e recovery sanitizados.
14
+ - **Fontes verificáveis.** Adapters injetáveis ligam Git, CI, tag, NPM e GitHub Release ao
15
+ repositório, target commit, package/version, integrity e notas esperados sem confiar em URL/claim
16
+ fornecida nem na worktree incidental.
17
+ - **Receipt Ledger v2.** Autorizações de archive e receipts de delivery/cleanup ganham sequência,
18
+ `previous_hash`, `receipt_hash`, lock, publicação atômica e checkpoint separado, com schema
19
+ público e replay idempotente.
20
+
21
+ ### Changed
22
+
23
+ - **Archive fail-closed.** Evidence Envelope v2, pacote deep e verdict completos/canônicos agora
24
+ são exigidos mesmo sem sensores; uma autorização v2 é encadeada antes da mutação e `--force`
25
+ continua limitado a tarefa aberta, sem pular proveniência.
26
+ - **Delivery e release ligadas ao destino.** Merge/push observam `<remote>/<branch>`, exigem
27
+ ancestralidade e preservam origin/worktree/branch do start; tag/publish derivam package e artefato
28
+ do target e verificam CI → commit → tag → versão/integrity → GitHub Release. Offline
29
+ permanece `reported` e não grava completion receipt.
30
+ - **Cleanup retomável e causal.** Finish/remove/prune validam o ledger antes da mutação, vinculam
31
+ todos os contextos, PR/head/merge e ator disponível, e retomam o mesmo operation ID após crash
32
+ antes/depois do append ou finalize; texto e `--json` preservam códigos e recovery sanitizados.
33
+ - **Compatibilidade explícita.** Ledgers v1 permanecem read-only como prefixo `legacy-unbound`;
34
+ no Windows com Node 18–22, receipts e operation locks tratam `st_dev=0` como metadado
35
+ indisponível quando o inode continua idêntico, sem aceitar identificadores de dispositivo
36
+ não-zero conflitantes; aquisições e liberações concorrentes relêem rotações e sharing
37
+ violations transitórias com limite estrito, e o release fecha e revalida o marker antes do
38
+ unlink nas runtimes antigas;
39
+ README, contrato do harness e guias de changes/verify/profiles/worktrees foram atualizados em
40
+ PT-BR/EN.
41
+
42
+ ### Security
43
+
44
+ - Adulteração intermediária, JSON parcial, cauda/checkpoint removidos, colisão de ID, locks
45
+ trocados por outro owner, writer concorrente e escape por symlink/junction passam a bloquear antes
46
+ da mutação; diagnósticos não persistem tokens nem paths privados.
47
+
48
+ ## [0.78.0] — 2026-08-22
49
+
50
+ ### Added
51
+
52
+ - **Evidence Envelope v2.** `verify` liga cada prova a projeto, repositório, worktree, work session,
53
+ branch, base/HEAD, árvore do índice e digest determinístico de staged/unstaged/untracked por
54
+ SHA-256 canônico; texto normaliza CRLF/CR para LF e binários preservam bytes.
55
+ - **Proveniência por sensor.** Cada resultado registra comando efetivo sanitizado e hash,
56
+ timestamps, duração, exit code, digest da saída e tail sanitizado limitado; alteração da
57
+ configuração invalida o binding anterior.
58
+ - **Diagnóstico causal.** `change status`, doctor, handoff e Observer distinguem evidência `bound`,
59
+ `stale`, `context-mismatch` e `legacy-unbound`; pacote deep e verdict carregam o mesmo
60
+ `evidenceEnvelopeId` e `evidenceBinding` completo e não podem ser reutilizados entre worktrees.
61
+
62
+ ### Changed
63
+
64
+ - **Publicação fail-closed.** Mudança de HEAD durante os sensores preserva a evidência anterior e
65
+ retorna `WENDKEEP_EVIDENCE_HEAD_CHANGED`. Evidência, pacote, verdict trivial e seals são gravados
66
+ por temporário path-safe no mesmo diretório e rename atômico.
67
+ - **Compatibilidade explícita.** Evidência v1 continua legível para histórico, mas sensores v1 não
68
+ satisfazem autoridade v2 no archive. README, schema e guias PT-BR/EN documentam formato,
69
+ normalização, recovery e vínculo do passe independente.
70
+
7
71
  ## [0.77.0] — 2026-08-22
8
72
 
9
73
  ### Added
package/README.en.md CHANGED
@@ -239,7 +239,7 @@ The README is the map; the guides provide syntax, options, exit codes, examples,
239
239
  | Group | Use it for | Detailed guide |
240
240
  |---|---|---|
241
241
  | **Installation and updates** | `init`, `sync`, companions, and the first project↔vault binding | [Installation and first use](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/getting-started.md) |
242
- | **Managed worktrees** | `worktree create/list/status/open/finish/cleanup/remove/prune`, merge proof, preflight, and receipts | [Managed worktrees](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/worktrees.md) |
242
+ | **Managed worktrees** | `worktree create/list/status/open/finish/cleanup/remove/prune`, merge proof, preflight, crash-safe cleanup/common gate, and receipts | [Managed worktrees](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/worktrees.md) |
243
243
  | **Active context** | `active_contexts` by `repository_id`/`worktree_id`/`work_session_id`, causal transition, quarantine, and explicit recovery | [Active context](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/context.md) |
244
244
  | **Operating profiles** | `profile`, `flow`, always-on Keep Core, and Wend Runtime governance | [Operating profiles](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/operating-profiles.md) |
245
245
  | **Changes and verification** | `change`, specs, sensors, TDD, evidence, and archive | [Changes and verification](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/changes-and-verification.md) |
@@ -352,9 +352,28 @@ an initialized registry never copies a global authorization without proven ident
352
352
  ```bash
353
353
  npx wendkeep delivery start release-0-74-0 --allow git:merge --allow git:push --allow publish --source-change <slug> --source-commit <sha> --session <id>
354
354
  npx wendkeep delivery status release-0-74-0 --session <id>
355
- npx wendkeep delivery finish release-0-74-0 --target main --ci-url <url> --version 0.74.0 --npm-integrity <sha512> --release-url <url> --session <id>
355
+ npx wendkeep delivery finish release-0-74-0 --target origin/main --ci-url <url> --version 0.74.0 --npm-integrity <sha512> --release-url <url> --session <id>
356
356
  ```
357
357
 
358
+ For `git:merge` and `git:push` capabilities, `delivery finish` requires
359
+ `--target <remote>/<branch>` (for example, `--target origin/main`). `delivery start` binds the
360
+ `origin` remote to the expected `repository`; during finish, the target is resolved again with
361
+ `git ls-remote`. If the target cannot be resolved or the origin/repository binding diverges, the
362
+ delivery is blocked before provenance adapters run.
363
+
364
+ The provenance gate re-derives authority against the current subject before archive, delivery,
365
+ release, or cleanup. Its single taxonomy is `verified`, `reported`, `legacy-unbound`, `stale`,
366
+ `conflict`, and `unproven`; only `verified` authorizes required proof. Evidence, a verdict, or a
367
+ receipt captured before amend/rebase, from another branch/worktree/session, or backed only by a
368
+ reported/offline external claim fails closed with objective recovery. New receipts use schema v2,
369
+ `previous_hash`, `receipt_hash`, and a separate checkpoint to detect tampering and truncation.
370
+ Stable codes are `WENDKEEP_PROVENANCE_GATE_BLOCKED`, `WENDKEEP_RECEIPT_LEDGER_BUSY`,
371
+ `WENDKEEP_RECEIPT_LEDGER_CONFLICT`, `WENDKEEP_RECEIPT_LEDGER_CORRUPT`, and
372
+ `WENDKEEP_RECEIPT_LEDGER_TRUNCATED`. Safe recovery reads `state`, `reasonCodes`, `diagnostics`,
373
+ and `repair.command` in `--json` output, runs `npx --no-install wendkeep verify --deep --json` or
374
+ the indicated status command, and recaptures proof; it never prints raw stderr, tokens, private URLs,
375
+ or Vault paths, and never edits the ledger/checkpoint.
376
+
358
377
  If the harness does not record a lease, a small fix remains under the configured profile —
359
378
  `GOVERN` by default. `OFF` does not mean “simple task”: it is a persistent human choice that hands
360
379
  governance to the native harness. The LLM may temporarily elevate an `OFF` base to a Wend route,
@@ -531,11 +550,47 @@ explore → propose → apply (TDD) → verify → archive
531
550
 
532
551
  - **Propose** — `wendkeep change new <slug>` scaffolds `08-Mudanças/<slug>/` (`proposta.md`, `design.md`, `tarefas.md`; `--simple` skips the design). `--guide` creates the compact GUIDE contract and omits automatic design/spec/ADR when `contract_impact:none`. It becomes the global *current* change. When the change declares `spec_impact: required`, you author the delta yourself at `specs/<capability>/spec.md` — there is no placeholder to delete. Multiple changes may remain open: `change list`/`status` and the hooks show every pending one, while commands without `--change` act on the current one alone. `change use <slug>` changes focus and `change continue <archived> <new>` creates an auditable continuation.
533
552
  - **Apply** — implement each `tarefas.md` task. Mark machine proof with one or more `[sensor:<id>]` tags on the same task: every distinct ID enters the gate once, in declaration order. Also mark satisfied requirements with one or more `[req:<ID>]` tags.
534
- - **Verify** — `wendkeep verify` runs the sensors your tasks declared (from `wendkeep.sensors.json` at the project root) and writes `evidencia.json`. A red `critical` fails the gate; a red `warning` is advisory. Failures retain only a bounded, sanitized diagnostic; green output is not persisted. `verify --deep` builds a self-contained package with complete effective requirements (living contract + this change's delta), so the independent verifier never needs to reconstruct unarchived requirements from `07-Specs`. Every change needs a `verdict.json` to archive; `verify --deep` writes a trivial one automatically when the change declares no `[req:]`.
553
+ - **Verify** — `wendkeep verify` runs declared sensors and writes an **Evidence Envelope v2** to `evidencia.json`, SHA-256-bound to project/repository/worktree/session, HEAD, index tree, normalized worktree digest, tasks, effective spec, and sensor configuration. Each sensor records a sanitized command, execution window, duration, exit code, output digest, and a sanitized tail bounded to 2,000 characters. If HEAD changes during the run, no new envelope is published. `change status` reports `bound`, `stale`, `context-mismatch`, or `legacy-unbound`; v1 evidence remains readable but cannot satisfy v2 authority. The public schema is [`schema/wendkeep.evidence-envelope-v2.schema.json`](schema/wendkeep.evidence-envelope-v2.schema.json). `verify --deep` binds both package and verdict to the current `envelope_id`.
535
554
  - **Archive** — `wendkeep change archive <slug>` **gates** on the evidence (blocks unless every declared critical sensor is green), promotes each applicable spec delta (`ADDED`/`MODIFIED`/`REMOVED`) into the living `07-Specs/<capability>.md` and moves the change to `_arquivo/`. GOVERN/ASSURE mint an ADR in `04-Decisões/`; compact GUIDE with no contract impact does not mint one automatically.
536
555
 
537
556
  > The gate blocks unless the scaffold is filled, no task is open, evidence is fresh, and every declared requirement is covered. **`--force` waives exactly one of those — the open-task check — and is the human's call, never the agent's.** An unfilled scaffold, a red critical sensor, stale evidence, an orphan requirement or a missing verdict block regardless.
538
557
 
558
+ After the fix, archive requires a **final** recapture with
559
+ `wendkeep verify --deep --change <slug>`. The package is complete and canonical; the verdict must
560
+ also be complete and canonical, with both bound to the same checkout, change, tasks, spec, and sensors. Before any mutation, the command
561
+ writes an authorization receipt to the separate `change-archive-receipts-v2` ledger; only after
562
+ that receipt is valid may it promote the spec/ADR or move the change. `change archive --json`
563
+ returns the serializable `state`, `reason_codes`, `diagnostics`, and `repair` fields. Corruption
564
+ or truncation in any ledger fails closed before mutation. `--force` does not bypass provenance,
565
+ integrity, package, verdict, corruption, or truncation; the exact recovery is the recapture above.
566
+
567
+ Archive sealing uses the runtime lock and a private ASCII transaction at
568
+ `.brain/runtime/archive-transactions/<uuid>/{original,authorized}`: it atomically renames the live
569
+ change to `original`, checks the digest, and promotes only `authorized`. On a seal or divergence
570
+ failure, it removes the snapshot and restores `original` without partial promotion. Multi-spec
571
+ promotion is one atomic unit: it captures before-images/digests, rolls back before/after writes,
572
+ and permits retry only after reconciliation and fresh verification. The post-release finalizer
573
+ validates original/destination digests, but the `completed` journal keeps the `original` retained;
574
+ no destructive cleanup is automatic. A failure leaves `published-recovery-required`. Text and --json
575
+ keep the same sanitized diagnostic (code, operation, state, blocker, expected, observed, recovery).
576
+
577
+ The archive uses a `directory lock` with a token-specific marker and lease: acquisition prepares a
578
+ sibling `.pending` directory and publishes it by atomic rename, uses no hardlink, and allows at most
579
+ 3 topology attempts. A live owner returns `WENDKEEP_ARCHIVE_BUSY`, a dead owner is safely reaped,
580
+ an invalid marker returns `WENDKEEP_ARCHIVE_LOCK_UNAVAILABLE`, and ownership loss returns
581
+ `WENDKEEP_ARCHIVE_LOCK_OWNERSHIP_LOST`. The transaction keeps `archive-transaction.json` with
582
+ phases `prepared` → `isolated` → `copied` → `sealed` → `published` → `promotion-prepared` →
583
+ `promotion-applied` → `completed` or `recovery-required`. A pending journal blocks a new archive for
584
+ the same slug before the gate. On
585
+ a collision/post-publication failure, `original` is retained and the state is
586
+ `published-recovery-required`; `operation_id` and `transaction_phase` are sanitized. Inspect it
587
+ with `wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]`:
588
+ without `--spec-action`, this is a read-only, fail-closed, idempotent operation that returns
589
+ sanitized actions without promoting or deleting. `rollback` restores before-images and `resume`
590
+ converges after-images for a `promotion-prepared` promotion, while retaining the journal for
591
+ reconciliation. When an operation ID exists, `repair.command` points to that recovery; do not treat
592
+ `command:null` as the normal flow.
593
+
539
594
  `wendkeep init` seeds process skills into the vault's `.brain/skills` and delivers identical copies to `.claude/skills/` and `.agents/skills/`; Codex gets the agent definitions (`.brain/agents/*.toml` → `.codex/agents/`) plus a managed section in `AGENTS.md` that indexes the skills. Every skill carries source hash/version metadata; `doctor` warns when reseed + agent restart is required.
540
595
 
541
596
  ### The loop in five minutes
package/README.md CHANGED
@@ -239,7 +239,7 @@ The README is the map; the guides provide syntax, options, exit codes, examples,
239
239
  | Group | Use it for | Detailed guide |
240
240
  |---|---|---|
241
241
  | **Installation and updates** | `init`, `sync`, companions, and the first project↔vault binding | [Installation and first use](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/getting-started.md) |
242
- | **Managed worktrees** | `worktree create/list/status/open/finish/cleanup/remove/prune`, merge proof, preflight, and receipts | [Managed worktrees](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/worktrees.md) |
242
+ | **Managed worktrees** | `worktree create/list/status/open/finish/cleanup/remove/prune`, merge proof, preflight, crash-safe cleanup/common gate, and receipts | [Managed worktrees](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/worktrees.md) |
243
243
  | **Active context** | `active_contexts` by `repository_id`/`worktree_id`/`work_session_id`, causal transition, quarantine, and explicit recovery | [Active context](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/context.md) |
244
244
  | **Operating profiles** | `profile`, `flow`, always-on Keep Core, and Wend Runtime governance | [Operating profiles](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/operating-profiles.md) |
245
245
  | **Changes and verification** | `change`, specs, sensors, TDD, evidence, and archive | [Changes and verification](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/changes-and-verification.md) |
@@ -352,9 +352,28 @@ an initialized registry never copies a global authorization without proven ident
352
352
  ```bash
353
353
  npx wendkeep delivery start release-0-74-0 --allow git:merge --allow git:push --allow publish --source-change <slug> --source-commit <sha> --session <id>
354
354
  npx wendkeep delivery status release-0-74-0 --session <id>
355
- npx wendkeep delivery finish release-0-74-0 --target main --ci-url <url> --version 0.74.0 --npm-integrity <sha512> --release-url <url> --session <id>
355
+ npx wendkeep delivery finish release-0-74-0 --target origin/main --ci-url <url> --version 0.74.0 --npm-integrity <sha512> --release-url <url> --session <id>
356
356
  ```
357
357
 
358
+ For `git:merge` and `git:push` capabilities, `delivery finish` requires
359
+ `--target <remote>/<branch>` (for example, `--target origin/main`). `delivery start` binds the
360
+ `origin` remote to the expected `repository`; during finish, the target is resolved again with
361
+ `git ls-remote`. If the target cannot be resolved or the origin/repository binding diverges, the
362
+ delivery is blocked before provenance adapters run.
363
+
364
+ The provenance gate re-derives authority against the current subject before archive, delivery,
365
+ release, or cleanup. Its single taxonomy is `verified`, `reported`, `legacy-unbound`, `stale`,
366
+ `conflict`, and `unproven`; only `verified` authorizes required proof. Evidence, a verdict, or a
367
+ receipt captured before amend/rebase, from another branch/worktree/session, or backed only by a
368
+ reported/offline external claim fails closed with objective recovery. New receipts use schema v2,
369
+ `previous_hash`, `receipt_hash`, and a separate checkpoint to detect tampering and truncation.
370
+ Stable codes are `WENDKEEP_PROVENANCE_GATE_BLOCKED`, `WENDKEEP_RECEIPT_LEDGER_BUSY`,
371
+ `WENDKEEP_RECEIPT_LEDGER_CONFLICT`, `WENDKEEP_RECEIPT_LEDGER_CORRUPT`, and
372
+ `WENDKEEP_RECEIPT_LEDGER_TRUNCATED`. Safe recovery reads `state`, `reasonCodes`, `diagnostics`,
373
+ and `repair.command` in `--json` output, runs `npx --no-install wendkeep verify --deep --json` or
374
+ the indicated status command, and recaptures proof; it never prints raw stderr, tokens, private URLs,
375
+ or Vault paths, and never edits the ledger/checkpoint.
376
+
358
377
  If the harness does not record a lease, a small fix remains under the configured profile —
359
378
  `GOVERN` by default. `OFF` does not mean “simple task”: it is a persistent human choice that hands
360
379
  governance to the native harness. The LLM may temporarily elevate an `OFF` base to a Wend route,
@@ -531,11 +550,47 @@ explore → propose → apply (TDD) → verify → archive
531
550
 
532
551
  - **Propose** — `wendkeep change new <slug>` scaffolds `08-Mudanças/<slug>/` (`proposta.md`, `design.md`, `tarefas.md`; `--simple` skips the design). `--guide` creates the compact GUIDE contract and omits automatic design/spec/ADR when `contract_impact:none`. It becomes the global *current* change. When the change declares `spec_impact: required`, you author the delta yourself at `specs/<capability>/spec.md` — there is no placeholder to delete. Multiple changes may remain open: `change list`/`status` and the hooks show every pending one, while commands without `--change` act on the current one alone. `change use <slug>` changes focus and `change continue <archived> <new>` creates an auditable continuation.
533
552
  - **Apply** — implement each `tarefas.md` task. Mark machine proof with one or more `[sensor:<id>]` tags on the same task: every distinct ID enters the gate once, in declaration order. Also mark satisfied requirements with one or more `[req:<ID>]` tags.
534
- - **Verify** — `wendkeep verify` runs the sensors your tasks declared (from `wendkeep.sensors.json` at the project root) and writes `evidencia.json`. A red `critical` fails the gate; a red `warning` is advisory. Failures retain only a bounded, sanitized diagnostic; green output is not persisted. `verify --deep` builds a self-contained package with complete effective requirements (living contract + this change's delta), so the independent verifier never needs to reconstruct unarchived requirements from `07-Specs`. Every change needs a `verdict.json` to archive; `verify --deep` writes a trivial one automatically when the change declares no `[req:]`.
553
+ - **Verify** — `wendkeep verify` runs declared sensors and writes an **Evidence Envelope v2** to `evidencia.json`, SHA-256-bound to project/repository/worktree/session, HEAD, index tree, normalized worktree digest, tasks, effective spec, and sensor configuration. Each sensor records a sanitized command, execution window, duration, exit code, output digest, and a sanitized tail bounded to 2,000 characters. If HEAD changes during the run, no new envelope is published. `change status` reports `bound`, `stale`, `context-mismatch`, or `legacy-unbound`; v1 evidence remains readable but cannot satisfy v2 authority. The public schema is [`schema/wendkeep.evidence-envelope-v2.schema.json`](schema/wendkeep.evidence-envelope-v2.schema.json). `verify --deep` binds both package and verdict to the current `envelope_id`.
535
554
  - **Archive** — `wendkeep change archive <slug>` **gates** on the evidence (blocks unless every declared critical sensor is green), promotes each applicable spec delta (`ADDED`/`MODIFIED`/`REMOVED`) into the living `07-Specs/<capability>.md` and moves the change to `_arquivo/`. GOVERN/ASSURE mint an ADR in `04-Decisões/`; compact GUIDE with no contract impact does not mint one automatically.
536
555
 
537
556
  > The gate blocks unless the scaffold is filled, no task is open, evidence is fresh, and every declared requirement is covered. **`--force` waives exactly one of those — the open-task check — and is the human's call, never the agent's.** An unfilled scaffold, a red critical sensor, stale evidence, an orphan requirement or a missing verdict block regardless.
538
557
 
558
+ After the fix, archive requires a **final** recapture with
559
+ `wendkeep verify --deep --change <slug>`. The package is complete and canonical; the verdict must
560
+ also be complete and canonical, with both bound to the same checkout, change, tasks, spec, and sensors. Before any mutation, the command
561
+ writes an authorization receipt to the separate `change-archive-receipts-v2` ledger; only after
562
+ that receipt is valid may it promote the spec/ADR or move the change. `change archive --json`
563
+ returns the serializable `state`, `reason_codes`, `diagnostics`, and `repair` fields. Corruption
564
+ or truncation in any ledger fails closed before mutation. `--force` does not bypass provenance,
565
+ integrity, package, verdict, corruption, or truncation; the exact recovery is the recapture above.
566
+
567
+ Archive sealing uses the runtime lock and a private ASCII transaction at
568
+ `.brain/runtime/archive-transactions/<uuid>/{original,authorized}`: it atomically renames the live
569
+ change to `original`, checks the digest, and promotes only `authorized`. On a seal or divergence
570
+ failure, it removes the snapshot and restores `original` without partial promotion. Multi-spec
571
+ promotion is one atomic unit: it captures before-images/digests, rolls back before/after writes,
572
+ and permits retry only after reconciliation and fresh verification. The post-release finalizer
573
+ validates original/destination digests, but the `completed` journal keeps the `original` retained;
574
+ no destructive cleanup is automatic. A failure leaves `published-recovery-required`. Text and --json
575
+ keep the same sanitized diagnostic (code, operation, state, blocker, expected, observed, recovery).
576
+
577
+ The archive uses a `directory lock` with a token-specific marker and lease: acquisition prepares a
578
+ sibling `.pending` directory and publishes it by atomic rename, uses no hardlink, and allows at most
579
+ 3 topology attempts. A live owner returns `WENDKEEP_ARCHIVE_BUSY`, a dead owner is safely reaped,
580
+ an invalid marker returns `WENDKEEP_ARCHIVE_LOCK_UNAVAILABLE`, and ownership loss returns
581
+ `WENDKEEP_ARCHIVE_LOCK_OWNERSHIP_LOST`. The transaction keeps `archive-transaction.json` with
582
+ phases `prepared` → `isolated` → `copied` → `sealed` → `published` → `promotion-prepared` →
583
+ `promotion-applied` → `completed` or `recovery-required`. A pending journal blocks a new archive for
584
+ the same slug before the gate. On
585
+ a collision/post-publication failure, `original` is retained and the state is
586
+ `published-recovery-required`; `operation_id` and `transaction_phase` are sanitized. Inspect it
587
+ with `wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]`:
588
+ without `--spec-action`, this is a read-only, fail-closed, idempotent operation that returns
589
+ sanitized actions without promoting or deleting. `rollback` restores before-images and `resume`
590
+ converges after-images for a `promotion-prepared` promotion, while retaining the journal for
591
+ reconciliation. When an operation ID exists, `repair.command` points to that recovery; do not treat
592
+ `command:null` as the normal flow.
593
+
539
594
  `wendkeep init` seeds process skills into the vault's `.brain/skills` and delivers identical copies to `.claude/skills/` and `.agents/skills/`; Codex gets the agent definitions (`.brain/agents/*.toml` → `.codex/agents/`) plus a managed section in `AGENTS.md` that indexes the skills. Every skill carries source hash/version metadata; `doctor` warns when reseed + agent restart is required.
540
595
 
541
596
  ### The loop in five minutes
@@ -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
  ## Options and exit codes
@@ -47,6 +48,10 @@ npx wendkeep change archive <slug> [--session <id>]
47
48
  only one unambiguous active context for the worktree is accepted; ambiguity returns exit `2`.
48
49
  - `change relink [--apply]` and `change backlink [--apply]` repair graph links; preview is default.
49
50
  - `change abandon <slug>` drops work without an ADR; `archive --force` needs explicit human choice.
51
+ - `change archive recover <operation-id> --change <slug> [--spec-action rollback|resume]` inspects a
52
+ pending transaction by default; with `rollback` or `resume`, it converges only the spec
53
+ promotion prepared in the journal, under the operation lock and validation. It never promotes the
54
+ change, deletes the journal, or invents reconciliation.
50
55
  - `wendkeep spec list|show|effective|migrate|rebase` manages living contracts and deltas.
51
56
  - `wendkeep sensors list|add` manages executable proof.
52
57
  - Exit `0` means completion; gates use exit `1` for red proof and exit `2` for invalid
@@ -76,7 +81,72 @@ npx wendkeep sensors add api-contracts "npm run test:contracts" --severity criti
76
81
  An archived change promotes its delta into the living spec when applicable and preserves proposal,
77
82
  tasks/proof, and design when present. GOVERN/ASSURE mint an ADR; compact GUIDE with no contract
78
83
  impact does not mint one automatically. Archive passes only with closed tasks, green required
79
- sensors, and a fresh verdict.
84
+ sensors, and a fresh verdict bound to the same Evidence Envelope v2. V1 evidence is reported as
85
+ `legacy-unbound`; `change status <slug>` also diagnoses `bound`, `stale`, and `context-mismatch`.
86
+ Archive compares the package/verdict `evidenceEnvelopeId` and complete `evidenceBinding` with the
87
+ proven checkout. On a mismatch, return to the correct worktree/session and rerun `verify`,
88
+ `verify --deep`, and `wk-verify`. Fields, text/binary normalization, error codes, and recovery are
89
+ detailed in the [verify guide](verify.md).
90
+
91
+ The common gate reclassifies the envelope, package, and verdict as `verified`, `reported`,
92
+ `legacy-unbound`, `stale`, `conflict`, or `unproven`; only `verified` permits archive. A block
93
+ returns `WENDKEEP_PROVENANCE_GATE_BLOCKED`: stabilize/recover the context, run `verify`, then
94
+ `verify --deep`, and request a fresh `wk-verify` pass. `--force` may waive only an open task; for
95
+ provenance, integrity, package, and verdict it does **not** change the result or promote a spec/ADR.
96
+ Ledger errors are `WENDKEEP_RECEIPT_LEDGER_BUSY`, `WENDKEEP_RECEIPT_LEDGER_CONFLICT`,
97
+ `WENDKEEP_RECEIPT_LEDGER_CORRUPT`, and `WENDKEEP_RECEIPT_LEDGER_TRUNCATED`. On a block, use the
98
+ sanitized `--json` output (`state`, `reasonCodes`, `diagnostics`, `repair.command`), execute the
99
+ indicated recovery, and run `npx --no-install wendkeep verify --deep --json`; preserve and recapture
100
+ proof without editing the ledger/checkpoint or exposing stderr, tokens, private URLs, or Vault paths.
101
+
102
+ ### Post-fix archive contract
103
+
104
+ Before mutation, perform the final recapture with `wendkeep verify --deep --change <slug>`. The
105
+ package and verdict must be complete and canonical, bound to the same checkout, change, tasks,
106
+ spec, and sensors. Archive first writes an authorization receipt to the separate
107
+ `change-archive-receipts-v2` ledger; only after it validates may it promote the spec/ADR or move
108
+ the change. `change archive --json` returns the serializable `state`, `reason_codes`,
109
+ `diagnostics`, and `repair` fields. Corruption or truncation in the proof or archive ledger fails
110
+ closed before any write. `--force` does not bypass provenance or integrity, package/verdict,
111
+ corruption, or truncation. The exact recovery is to repeat
112
+ `wendkeep verify --deep --change <slug>` in the correct checkout.
113
+
114
+ The mutation acquires the runtime lock `.brain/runtime/change-archive-operation.lock` and opens a
115
+ private ASCII transaction at `.brain/runtime/archive-transactions/<uuid>/{original,authorized}`.
116
+ It atomically renames the live change to `original`, checks the digest, and promotes only the
117
+ `authorized` copy; the public namespace is never a publication source. On a seal or divergence
118
+ failure with `WENDKEEP_ARCHIVE_INPUT_CHANGED` before promotion, the `authorized` snapshot is
119
+ removed and `original` is restored without partial promotion. A successful archive keeps the
120
+ `completed` journal; the post-release finalizer validates the digests of `original` and the
121
+ published destination but retains `original` and the transaction, with no automatic destructive
122
+ cleanup.
123
+
124
+ The archive lock is a `directory lock`: the canonical directory contains a token-specific marker
125
+ and lease. Acquisition prepares a sibling `.pending` directory, writes owner/lease, and publishes
126
+ it by atomic rename; it uses no hardlink and re-observes collisions for at most 3 topology attempts.
127
+ A live owner returns `WENDKEEP_ARCHIVE_BUSY`; a dead owner may be safely reaped without deleting a
128
+ successor. Invalid structure or marker returns `WENDKEEP_ARCHIVE_LOCK_UNAVAILABLE`; ownership loss
129
+ returns `WENDKEEP_ARCHIVE_LOCK_OWNERSHIP_LOST`.
130
+
131
+ Each operation keeps an `archive-transaction.json` manifest with phases `prepared` → `isolated` →
132
+ `copied` → `sealed` → `published` → `promotion-prepared` → `promotion-applied` → `completed` or
133
+ `recovery-required`. A pending journal blocks a new archive for the same slug before the gate. On a
134
+ collision or post-publication failure, `original` is retained and the state is
135
+ `published-recovery-required`. Use the fail-closed, idempotent inspection
136
+ `wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]`;
137
+ without `--spec-action` it only returns sanitized actions. `rollback` converges before-images and
138
+ `resume` converges after-images for a `promotion-prepared` promotion; both retain the journal for
139
+ further reconciliation.
140
+
141
+ Multi-spec promotion is one atomic unit: it captures before-images/digests for every capability,
142
+ rolls back every target (including state/README) on a before- or after-write failure, and permits a
143
+ retry only after journal reconciliation and fresh verification. The post-release finalizer validates
144
+ the original/destination digests but retains the `completed` journal and `original`; no destructive
145
+ cleanup is automatic. Sanitized `operation_id` and
146
+ `transaction_phase` fields accompany the diagnostic; `repair.command` points to
147
+ `wendkeep change archive recover <operation-id> --change <slug>` when an operation is identified.
148
+ Text and --json use the same sanitized diagnostic with code, operation, state, blocker, expected,
149
+ observed, recovery, reason_codes, diagnostics, and repair.
80
150
 
81
151
  ## Tool-scope fence
82
152
 
@@ -105,6 +175,8 @@ selection/lease; never carry authorization from another conversation.
105
175
  - Sensor not executed: keep one or more `[sensor:id]` tags on the same checkbox line. Every
106
176
  distinct ID on that line is required and runs once, in declaration order.
107
177
  - Stale evidence: rerun `verify` and `verify --deep` after task/spec edits.
178
+ - Evidence from another worktree/session: return to the correct causal context; it cannot satisfy
179
+ the current archive even when every sensor is green.
108
180
  - Rebase conflict: resolve the delta or use `--accept-current` only when that is the decision.
109
181
 
110
182
  ## Next steps
@@ -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 <text> [--session <id>]
64
64
  ```
65
65
 
@@ -180,13 +180,36 @@ ownership to the native LLM harness.
180
180
  `contract_impact`, and `operation_risk` are independent dimensions. `delivery start` captures
181
181
  repo, branch/worktree, SHA, source change, and capabilities in `.brain/runtime/deliveries/`;
182
182
  it creates no `08-Changes` folder, delta, spec, or ADR.
183
- - `delivery finish` requires a clean worktree, proves that the target contains the source commit,
184
- and for `publish` requires CI, version, npm integrity, and GitHub Release evidence. Receipts are
185
- append-only in `.brain/runtime/delivery-receipts.jsonl`. If code/config must change, delivery
186
- stops with `WENDKEEP_DELIVERY_IMPLEMENTATION_REQUIRED` and work returns to implementation.
183
+ - For `git:merge` and `git:push` capabilities, `delivery finish` requires `--target
184
+ <remote>/<branch>` (for example, `--target origin/main`). `delivery start` binds the `origin`
185
+ remote to the expected `repository`; `finish` resolves the target with `git ls-remote` and blocks
186
+ the delivery before provenance adapters if the target cannot be resolved or the binding diverges.
187
+ - `delivery finish` requires a clean worktree and re-derives source/target. Merge/push proves
188
+ ancestry; tag proves package/version and the target tag; `publish` queries CI, NPM, and GitHub
189
+ Release bound to the same commit, version, integrity, and notes. Offline, a claim remains
190
+ `reported` and never becomes `verified`; completion blocks without writing a receipt. New
191
+ receipts form `.brain/runtime/delivery-receipts-v2.jsonl`, with a hash chain and checkpoint; v1
192
+ is only `legacy-unbound`. `WENDKEEP_PROVENANCE_GATE_BLOCKED` provides recovery. If code/config
193
+ must change, `WENDKEEP_DELIVERY_IMPLEMENTATION_REQUIRED` returns work to implementation.
194
+ The gate uses the same taxonomy: `verified`, `reported`, `legacy-unbound`, `stale`, `conflict`, and
195
+ `unproven`. Ledger errors are `WENDKEEP_RECEIPT_LEDGER_BUSY`,
196
+ `WENDKEEP_RECEIPT_LEDGER_CONFLICT`, `WENDKEEP_RECEIPT_LEDGER_CORRUPT`, and
197
+ `WENDKEEP_RECEIPT_LEDGER_TRUNCATED`; inspect sanitized `state`, `reasonCodes`, `diagnostics`, and
198
+ `repair.command` in `--json`, execute the indicated recovery, and recapture proof without editing
199
+ the ledger/checkpoint or exposing stderr, tokens, private URLs, or Vault paths.
187
200
  - In a multi-context Vault, `active_contexts[].delivery_id` is authoritative. `--session <id>`
188
201
  selects the work session explicitly; without it, only one unambiguous active context for the
189
202
  worktree may be used. Implicit status, finish, and abandon resolve that binding, not a global pointer.
203
+ - `delivery` failures expose the same PROV-8 diagnostic in text and in `delivery --json`: a stable
204
+ `code`, `operation`, `state`, first `blocker`, sanitized `expected`/`observed`, and an objective
205
+ `recovery`. Git stderr, tokens, private URLs, and private paths are not propagated.
206
+ - `delivery.completed` and `delivery.abandoned` receipts bind `repository_id`, the public
207
+ `repository` in `owner/repo` form, `worktree_id`, `work_session_id`, `change_slug`, and `branch`.
208
+ The private worktree path never enters the receipt. During contextual finalization, the receipt
209
+ enters the ledger and durable state is written before clearing `active_contexts[].delivery_id`.
210
+ A retry converges to the same receipt whether the binding is already clear or still bound. For
211
+ `delivery abandon`, the free-form reason becomes `reason_digest`; raw text does not enter the
212
+ ledger or state.
190
213
  - `CURRENT_DELIVERY` is only a derived projection: it contains the ID for one single, unambiguous
191
214
  active context with delivery and stays empty with zero or multiple contexts.
192
215
  `WENDKEEP_DELIVERY_CONTEXT_MISMATCH` means the explicit ID belongs to another context; neither
@@ -275,6 +298,27 @@ remain available and run their own contracts. A completed FLOW leaves a durable,
275
298
  receipt; a promoted FLOW enters the normal change lifecycle. Completed delivery leaves a receipt
276
299
  without an ADR; compact GUIDE archives its result without artificial spec/design/ADR.
277
300
 
301
+ For archive in GOVERN/ASSURE, the `directory lock` uses a token-specific marker and lease:
302
+ acquisition prepares a sibling `.pending` directory and publishes it by atomic rename, uses no
303
+ hardlink, and allows at most 3 topology attempts. A live owner returns `WENDKEEP_ARCHIVE_BUSY`, a
304
+ dead owner may be safely reaped, an invalid marker returns `WENDKEEP_ARCHIVE_LOCK_UNAVAILABLE`, and
305
+ ownership loss returns `WENDKEEP_ARCHIVE_LOCK_OWNERSHIP_LOST`. The `archive-transaction.json`
306
+ journal moves through `prepared` → `isolated` → `copied` → `sealed` → `published` →
307
+ `promotion-prepared` → `promotion-applied` → `completed` or `recovery-required`; a pending journal
308
+ blocks a new archive for the same slug before the gate.
309
+ `original` is retained on collision/post-publication failure and `published-recovery-required`
310
+ requires inspection. `operation_id` and `transaction_phase` appear only sanitized. Use
311
+ `wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]`:
312
+ without `--spec-action`, read-only, fail-closed, idempotent inspection with no promotion, deletion,
313
+ or invented reconciliation; `rollback` restores before-images and `resume` converges after-images
314
+ for `promotion-prepared`, retaining the journal. When an operation ID exists, `repair.command` points
315
+ to that recovery; do not treat `command:null` as the normal flow.
316
+
317
+ Multi-spec promotion is atomic, with before-images/digests, rollback of targets before/after writes,
318
+ and retry only after reconciliation and fresh verification. The post-release finalizer validates
319
+ original/destination digests, but the `completed` journal keeps the `original` retained; no
320
+ destructive cleanup is automatic.
321
+
278
322
  ## Common errors and diagnosis
279
323
 
280
324
  - Unknown profile: use exactly `OFF`, `FLOW`, `GUIDE`, `GOVERN`, or `ASSURE`.
@@ -42,7 +42,8 @@ npx wendkeep change use <slug>
42
42
  - **Exit 0:** all required sensors passed and evidence was written.
43
43
  - **Exit 1:** the gate ran, but at least one critical sensor was red or a mutant survived.
44
44
  - **Exit 2:** invalid usage/context, including `no change (--change or active)`, missing vault,
45
- unknown change, or invalid `wendkeep.sensors.json`.
45
+ unknown change, a project outside a Git repository, invalid `wendkeep.sensors.json`, or
46
+ `WENDKEEP_EVIDENCE_HEAD_CHANGED`.
46
47
 
47
48
  `verify --deep` writes `verificacao.json`; it does not replace the reviewer. The `wk-verify` skill
48
49
  must be run by a different author and writes `verdict.json`.
@@ -72,10 +73,60 @@ npx wendkeep memory status --gate --vault .MyApp-vault
72
73
 
73
74
  ## Expected result
74
75
 
75
- `evidencia.json` contains sensor results and a seal binds proof to the current `tarefas.md` hash.
76
- When a sensor is red, its entry receives only a local, sanitized diagnostic bounded to 2,000
77
- characters; stdout/stderr from green sensors is not persisted. Deep mode packages requirements,
78
- tasks, and evidence for read-only review; the verdict covers every `[req:]` before archive.
76
+ `evidencia.json` follows the [public v2 schema](../../../schema/wendkeep.evidence-envelope-v2.schema.json).
77
+ The envelope binds `project_id`, `repository_id`, `worktree_id`, `work_session_id`, change, and
78
+ branch to `base_sha`, `head_sha`, `index_tree_sha`, `worktree_digest`, tasks, effective spec, and
79
+ sensor configuration with complete SHA-256 digests. The worktree digest covers staged, unstaged,
80
+ untracked, rename, and delete state; paths use `/`, text normalizes CRLF/CR to LF, and binaries keep
81
+ their bytes. Binary classification honors Git `binary`/`-text` attributes and known binary
82
+ extensions (including `.bin`); ignored files are excluded.
83
+
84
+ Each sensor records its sanitized command and hash, start/end, duration, exit code, output digest,
85
+ and a sanitized tail bounded to 2,000 characters. Authority artifacts publish through a path-safe
86
+ temporary in the same directory and an atomic rename. In deep mode, `verificacao.json` and
87
+ `verdict.json` carry the same `evidenceEnvelopeId` and complete `evidenceBinding`; the independent
88
+ reviewer must preserve both.
89
+
90
+ V1 evidence remains readable as `legacy-unbound`, never as equivalent authority. Run
91
+ `wendkeep change status <slug>` to inspect `bound`, `stale`, or `context-mismatch`.
92
+
93
+ The provenance gate normalizes that legacy view into one taxonomy: `verified` when every required
94
+ proof is fresh and bound; `reported` for a recorded claim without an authoritative observation;
95
+ `legacy-unbound` for v1; `stale` for an earlier snapshot; `conflict` for incompatible identity or
96
+ content; and `unproven` for missing or insufficient proof. Precedence is `conflict` > `stale` >
97
+ `legacy-unbound` > `unproven` > `reported` > `verified`, and only `verified` closes the gate.
98
+
99
+ For post-fix archive, the final pass is `wendkeep verify --deep --change <slug>`. It must leave a
100
+ complete and canonical package and verdict bound to the same checkout, change, tasks, spec, and
101
+ sensors. Archive writes the authorization receipt before mutation to the separate
102
+ `change-archive-receipts-v2` ledger. Its `change archive --json` output is serializable and
103
+ exposes `state`, `reason_codes`, `diagnostics`, and `repair`; ledger corruption or truncation
104
+ fails closed. `--force` does not bypass provenance or integrity. The exact recovery is to repeat
105
+ `wendkeep verify --deep --change <slug>` after stabilizing the context.
106
+
107
+ Archive uses a `directory lock` with a token-specific marker and lease. Acquisition prepares a
108
+ sibling `.pending` directory and publishes it by atomic rename, uses no hardlink, and allows at most
109
+ 3 topology attempts. A live owner produces `WENDKEEP_ARCHIVE_BUSY`; a dead owner is reaped only
110
+ after safe observation; invalid marker/structure produces `WENDKEEP_ARCHIVE_LOCK_UNAVAILABLE`;
111
+ ownership loss produces `WENDKEEP_ARCHIVE_LOCK_OWNERSHIP_LOST`. The `archive-transaction.json`
112
+ manifest records `prepared` → `isolated` → `copied` → `sealed` → `published` → `promotion-prepared` →
113
+ `promotion-applied` → `completed` or `recovery-required`. A pending journal blocks a new archive for
114
+ the same slug before the gate. On a
115
+ collision or post-publication failure, `original` is retained and the
116
+ `published-recovery-required` state blocks destructive retry. `operation_id` and `transaction_phase`
117
+ are sanitized fields. Inspect it with
118
+ `wendkeep change archive recover <operation-id> --change <slug> [--spec-action rollback|resume] [--json]`:
119
+ without `--spec-action`, this is a read-only, fail-closed, idempotent operation with no promotion,
120
+ deletion, or invented reconciliation. `rollback` restores before-images and `resume` converges
121
+ after-images for a `promotion-prepared` promotion while retaining the journal for reconciliation.
122
+ When an operation ID exists, `repair.command` points to `wendkeep change archive recover <operation-id>
123
+ --change <slug>`; do not treat `command:null` as the normal flow.
124
+
125
+ Multi-spec promotion is one atomic unit: it captures before-images/digests for every capability,
126
+ rolls back every target (including state/README) on a before- or after-write failure, and permits a
127
+ retry only after journal reconciliation and fresh verification. The post-release finalizer validates
128
+ original/destination digests, but the `completed` journal keeps the `original` retained; no
129
+ destructive cleanup is automatic. A failure retains `published-recovery-required`.
79
130
 
80
131
  ## Common errors and diagnosis
81
132
 
@@ -85,6 +136,17 @@ tasks, and evidence for read-only review; the verdict covers every `[req:]` befo
85
136
  - Red gate: inspect the bounded `note` field on the `evidencia.json` entry, fix the cause, and
86
137
  rerun; never choose `archive --force` on your own.
87
138
  - Missing/stale verdict: regenerate `--deep` and request a fresh independent pass.
139
+ - `WENDKEEP_EVIDENCE_HEAD_CHANGED`: HEAD moved while sensors ran; stabilize the checkout and rerun.
140
+ The previous evidence was not replaced.
141
+ - `legacy-unbound`, `stale`, or `context-mismatch`: return to the correct worktree/session, recover
142
+ the context when needed, and rerun `verify` plus `verify --deep`.
143
+ - `WENDKEEP_PROVENANCE_GATE_BLOCKED`: inspect `state`, `reasonCodes`, and `repair`; do not reuse
144
+ proof from another branch/worktree/session. Run the proposed command and recapture the envelope.
145
+ - `WENDKEEP_RECEIPT_LEDGER_BUSY`, `WENDKEEP_RECEIPT_LEDGER_CONFLICT`,
146
+ `WENDKEEP_RECEIPT_LEDGER_CORRUPT`, and `WENDKEEP_RECEIPT_LEDGER_TRUNCATED` require preserving
147
+ the ledger/checkpoint and executing the objective recovery in `repair.command` (or
148
+ `npx --no-install wendkeep verify --deep --json` for fresh proof); text/JSON output remains
149
+ sanitized and contains no raw stderr, tokens, private URLs, or Vault paths.
88
150
  - Surviving mutants: strengthen the discriminating test; after three rounds, review manually.
89
151
 
90
152
  ## Next steps
@@ -58,6 +58,31 @@ idempotent; when the directory vanished between steps, the interrupted reservati
58
58
  the proven head; divergence or an unavailable network blocks the operation. An already-absent branch
59
59
  is idempotent success. `--open-main` opens the main worktree only after completion.
60
60
 
61
+ ### Post-fix cleanup: crash-safe resume
62
+
63
+ Cleanup is **crash-safe** and resumable before the receipt, after the receipt and before
64
+ finalize, and after finalize: a crash at any boundary preserves operation/state and lets the same
65
+ proof be retried without duplicating removal or a receipt. Every operation subject includes all
66
+ active contexts, actor, pr, head, and merge. The canonical PR authority is the PR resolved by the
67
+ GitHub adapter; caller-provided text cannot replace that authority.
68
+
69
+ HEAD is re-derived before finalize from the checkout and compared with the proven head/merge. The
70
+ reason is sanitized and receives a digest for audit, without storing private paths, tokens, or
71
+ stderr. An absent or invalid checkpoint is WENDKEEP_RECEIPT_LEDGER_TRUNCATED. V1 remains
72
+ legacy-unbound and never authorizes cleanup.
73
+
74
+ Text and --json always expose operation, state, blocker, recovery, and the stable codes
75
+ WENDKEEP_WORKTREE_CLEANUP_BUSY, WENDKEEP_RECEIPT_LEDGER_CORRUPT, and
76
+ WENDKEEP_RECEIPT_LEDGER_TRUNCATED; recovery resumes the reservation or names the objective repair.
77
+
78
+ The common cleanup gate classifies the operation and blocks before mutation, including finish,
79
+ remove, and cleanup --apply. After append, the receipt is classified by the same gate before
80
+ finalize; a provenance failure neither finalizes nor reports success. A cleaned state without a v2
81
+ receipt is blocked as unproven; a v1 receipt never authorizes and remains legacy-unbound.
82
+
83
+ Text and --json blockers keep the same sanitized diagnostic: code, operation, state, blocker,
84
+ expected, observed, recovery, reason_codes, diagnostics, and repair.
85
+
61
86
  ## Cleanup, remove, and prune
62
87
 
63
88
  `cleanup --merged` and `prune` are dry-run by default. `--dry-run` makes that intent explicit; only
@@ -70,10 +95,20 @@ keeps every preflight and preserves both local and remote branches.
70
95
 
71
96
  The registry lives in the Git common-dir at `wendkeep/worktrees-v1.json`, protected by a
72
97
  multi-process lock. It stores repository/worktree identity, canonical binding, PR, and transient
73
- cleanup state; `.wendkeep.json` stays unchanged. Receipts live at
74
- `wendkeep/worktree-cleanup-receipts-v1.jsonl`. `.worktrees/` is added to both the versioned ignore
75
- and the repository-private exclude. JSON `list`/`status` output exposes neither Vault paths nor
76
- contents.
98
+ cleanup state; `.wendkeep.json` stays unchanged. New receipts live at
99
+ `wendkeep/worktree-cleanup-receipts-v2.jsonl`: every line carries `previous_hash` and
100
+ `receipt_hash`, while a separate checkpoint fixes the last validated sequence/hash/byte length.
101
+ V1 remains readable as `legacy-unbound`, with no silent append or rewrite.
102
+ `WENDKEEP_RECEIPT_LEDGER_CORRUPT` reports tampering/partial JSON and
103
+ `WENDKEEP_RECEIPT_LEDGER_TRUNCATED` reports a removed tail. Both block before removal and require
104
+ diagnosing the store, never inventing a receipt. `.worktrees/` is added to the versioned ignore and
105
+ repository-private exclude; JSON `list`/`status` exposes neither Vault paths nor contents.
106
+ Cleanup uses the `verified`, `reported`, `legacy-unbound`, `stale`, `conflict`, and `unproven` states;
107
+ `WENDKEEP_PROVENANCE_GATE_BLOCKED` and `WENDKEEP_RECEIPT_LEDGER_BUSY`,
108
+ `WENDKEEP_RECEIPT_LEDGER_CONFLICT`, `WENDKEEP_RECEIPT_LEDGER_CORRUPT`, and
109
+ `WENDKEEP_RECEIPT_LEDGER_TRUNCATED` fail closed. Objective recovery reads sanitized
110
+ `worktree status <slug> --json`, executes `repair.command` when present, and recaptures proof; never
111
+ edit the ledger/checkpoint or expose stderr, tokens, private URLs, or Vault paths.
77
112
 
78
113
  `create` is idempotent when slug, path, and branch already match. Collisions fail closed. Failures
79
114
  after reservation remain `failed`; run `worktree status <slug>` and follow `recovery`. `doctor`