wendkeep 0.66.4 → 0.66.5

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/CHANGELOG.md CHANGED
@@ -4,6 +4,28 @@ 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.66.5] — 2026-08-01
8
+
9
+ ### Fixed
10
+
11
+ - **A observabilidade Codex passa a registrar o grafo completo de subagentes.** Metadata é
12
+ lida incrementalmente mesmo em rollouts grandes; descendentes em dias posteriores ou níveis
13
+ aninhados são atribuídos uma única vez, enquanto transcripts top-level permanecem no bucket
14
+ principal e sinais duplicados ou atrasados não regridem o snapshot publicado.
15
+ - **SessionStop e SubagentStop convergem sob frontier causal e estado explícito.** O schema 2
16
+ distingue `complete`, `none` e `degraded`, coalesce rajadas com lease, preserva o último
17
+ snapshot íntegro diante de fonte incompleta e mantém cache/runtime reconstruíveis sem publicar
18
+ zero silencioso.
19
+ - **Rebuild, import e doctor agora reconciliam a observabilidade persistida.** Preview permanece
20
+ sem escrita, apply rejeita resultado parcial, import atualiza notas completas porém stale e o
21
+ doctor correlaciona checkpoint, manifest e dirty para expor degradação real.
22
+
23
+ ### Security
24
+
25
+ - **Diagnostics e provas públicas aplicam uma fronteira de privacidade estável.** Somente pares
26
+ allowlisted `{code,count}` podem ser persistidos; paths, identificadores, prompts e exceções
27
+ brutas ficam fora de fixtures, evidências e notas de release.
28
+
7
29
  ## [0.66.4] — 2026-07-30
8
30
 
9
31
  ### Fixed
package/README.en.md CHANGED
@@ -211,10 +211,10 @@ The README is the map; the guides provide syntax, options, exit codes, examples,
211
211
  | **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) |
212
212
  | **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) |
213
213
  | **Shared memory** | CORE, SHARED, status, validation, repair, and curation | [Memory](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/memory.md) |
214
- | **Sessions and import** | hooks, registry, session focus, and Claude/Codex backfill | [Sessions and import](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/sessions-and-import.md) |
214
+ | **Sessions and import** | causal hooks, observability reconciliation, and Claude/Codex backfill | [Sessions and import](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/sessions-and-import.md) |
215
215
  | **Notes and knowledge** | BUG/APR/ADR, repairs, renumbering, lessons, and dashboard | [Notes and knowledge](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/notes-and-knowledge.md) |
216
- | **Costs and observability** | stats, aggregation, trends, and historical rebuild | [Costs and observability](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/costs-and-observability.md) |
217
- | **Maintenance and diagnostics** | doctor, definition drift, theme, version, and help | [Maintenance and diagnostics](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/maintenance-and-diagnostics.md) |
216
+ | **Costs and observability** | safe dry-run, tri-state, aggregation, trends, and historical rebuild | [Costs and observability](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/costs-and-observability.md) |
217
+ | **Maintenance and diagnostics** | doctor, frontier/manifest freshness, drift, version, and help | [Maintenance and diagnostics](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/maintenance-and-diagnostics.md) |
218
218
 
219
219
  Operations that deserve step-by-step guidance: [verify and exits 0/1/2](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/verify.md),
220
220
  [legacy-memory migration](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/memory-migration.md), and
package/README.md CHANGED
@@ -211,10 +211,10 @@ The README is the map; the guides provide syntax, options, exit codes, examples,
211
211
  | **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) |
212
212
  | **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) |
213
213
  | **Shared memory** | CORE, SHARED, status, validation, repair, and curation | [Memory](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/memory.md) |
214
- | **Sessions and import** | hooks, registry, session focus, and Claude/Codex backfill | [Sessions and import](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/sessions-and-import.md) |
214
+ | **Sessions and import** | causal hooks, observability reconciliation, and Claude/Codex backfill | [Sessions and import](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/sessions-and-import.md) |
215
215
  | **Notes and knowledge** | BUG/APR/ADR, repairs, renumbering, lessons, and dashboard | [Notes and knowledge](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/notes-and-knowledge.md) |
216
- | **Costs and observability** | stats, aggregation, trends, and historical rebuild | [Costs and observability](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/costs-and-observability.md) |
217
- | **Maintenance and diagnostics** | doctor, definition drift, theme, version, and help | [Maintenance and diagnostics](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/maintenance-and-diagnostics.md) |
216
+ | **Costs and observability** | safe dry-run, tri-state, aggregation, trends, and historical rebuild | [Costs and observability](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/costs-and-observability.md) |
217
+ | **Maintenance and diagnostics** | doctor, frontier/manifest freshness, drift, version, and help | [Maintenance and diagnostics](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/maintenance-and-diagnostics.md) |
218
218
 
219
219
  Operations that deserve step-by-step guidance: [verify and exits 0/1/2](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/verify.md),
220
220
  [legacy-memory migration](https://github.com/rogersialves/wendkeep/blob/main/docs/en/commands/memory-migration.md), and
@@ -26,7 +26,7 @@ A consistent registry, complete price table, and transcript access for rebuilt s
26
26
  ```bash
27
27
  npx wendkeep stats [--vault <vault>] [--json]
28
28
  npx wendkeep cost [--since <date>] [--top [N]] [--trend day|week|month] [--write] [--json]
29
- npx wendkeep cost rebuild [--session <id|file>] [--limit N] [--apply] [--json]
29
+ npx wendkeep cost rebuild [--session <id|file>] [--limit N] [--max-graph-nodes N] [--max-fallback-days N] [--max-fallback-candidates N] [--apply] [--json]
30
30
  ```
31
31
 
32
32
  ## Options and exit codes
@@ -34,10 +34,18 @@ npx wendkeep cost rebuild [--session <id|file>] [--limit N] [--apply] [--json]
34
34
  - `wendkeep stats` emits one shareable line or JSON.
35
35
  - `wendkeep cost` aggregates total/model/day; `--trend` adds projection and `--write` refreshes
36
36
  `00-Custo.md`.
37
- - `wendkeep cost rebuild` is dry-run by default; `--apply` writes notes and
38
- `.brain/COST_REBUILD.json`.
39
- - Exit `0` means a consistent calculation; non-zero reports insufficient registry, price,
40
- transcript, or parsing state.
37
+ - `wendkeep cost rebuild` is dry-run by default and performs **zero writes**: it acquires no write
38
+ lock, changes no note, registry, or runtime state, and does not create `.brain/COST_REBUILD.json`.
39
+ - `--apply` publishes only `complete` or `none` candidates. The `none` state clears the section
40
+ only after a stable offline scan proves that no subagent was started.
41
+ - A `degraded` or `stale` candidate returns exit `1` and preserves the note without changes; the
42
+ batch continues so other safe sessions can be processed and the report can expose sanitized
43
+ diagnostic codes.
44
+ - The `--max-graph-nodes`, `--max-fallback-days`, and `--max-fallback-candidates` overrides are
45
+ exclusively for a targeted rebuild with `--session`. Using them without `--session` is invalid
46
+ usage and returns exit `2`; hooks, import, and bulk rebuild retain the default limits.
47
+ - Exit `0` means a consistent preview/apply; exit `1` means a partial `degraded`/`stale` result;
48
+ exit `2` means invalid syntax or context.
41
49
 
42
50
  ## Examples
43
51
 
@@ -45,12 +53,16 @@ npx wendkeep cost rebuild [--session <id|file>] [--limit N] [--apply] [--json]
45
53
  npx wendkeep stats --vault .MyApp-vault
46
54
  npx wendkeep cost --since 2026-07-01 --top 10 --trend week
47
55
  npx wendkeep cost rebuild --session 019abc --json
56
+ npx wendkeep cost rebuild --session 019abc --max-graph-nodes 8192 --json
57
+ npx wendkeep cost rebuild --session 019abc --apply
48
58
  ```
49
59
 
50
60
  ## Expected result
51
61
 
52
- Totals retain input/output/cache/reasoning dimensions by model and period. Rebuild shows a preview
53
- before changing notes and leaves a reproducible report when applied.
62
+ Totals retain input/output/cache/reasoning dimensions by model and period. Tri-state composition
63
+ returns `complete`, `none`, or `degraded`, plus a frontier, manifest, and sanitized diagnostics.
64
+ Run and review the dry-run before repeating the same command with `--apply`; a semantically
65
+ identical second apply preserves the note, checkpoint, report, and mtime.
54
66
 
55
67
  ## Common errors and diagnosis
56
68
 
@@ -58,6 +70,8 @@ before changing notes and leaves a reproducible report when applied.
58
70
  - Wrong-provider costs: validate the session identity chain.
59
71
  - Missing transcript: do not estimate silently; keep the gap visible.
60
72
  - Duplicated parent/subagent/fork totals: verify registry relationships and deduplication.
73
+ - `degraded`/`stale`: preserve the note and inspect diagnostics/frontier before authorizing apply.
74
+ - Rejected override: add `--session <id|file>` or remove the three targeted limits.
61
75
 
62
76
  ## Next steps
63
77
 
@@ -39,6 +39,11 @@ npx wendkeep --help
39
39
  events remain durable in the outbox/ledger is a recoverable warning.
40
40
  - An ambiguous attempt, a lost event ID (absent from ledger and outbox), `projected` state found
41
41
  only in the outbox, or a mismatched checkpoint is blocking.
42
+ - For session observability, `legacy`, `degraded`, `stale`, and `manifest-unproven` require
43
+ reconciliation or more evidence. Only fresh `none` and fresh `complete` are healthy: frontier,
44
+ checkpoint, root stat, and source manifest must agree.
45
+ - `doctor` remains read-only. It recommends the targeted dry-run first and only advises repeating
46
+ the command with `--apply` after human review.
42
47
  - `sync-defs --check` detects drift without writes; `--reseed` restores packaged `wk-*` skills.
43
48
  - `theme sync` reapplies the CSS snippet and graph groups without recreating the vault.
44
49
  - `wendkeep --version` prints the running version; `wendkeep --help` lists the public interface.
@@ -52,6 +57,8 @@ npx wendkeep --version
52
57
  npx wendkeep sync-defs --check --vault .MyApp-vault --project .
53
58
  npx wendkeep doctor --vault .MyApp-vault
54
59
  npx wendkeep memory status --gate --vault .MyApp-vault
60
+ npx wendkeep cost rebuild --session <id> --json
61
+ npx wendkeep cost rebuild --session <id> --apply
55
62
  ```
56
63
 
57
64
  ## Expected result
@@ -59,7 +66,9 @@ npx wendkeep memory status --gate --vault .MyApp-vault
59
66
  Doctor names sessions, registry, links, notes, prices, derived sections, and memory as healthy or
60
67
  provides a specific diagnostic/repair command. For memory, it distinguishes a valid initial empty
61
68
  state, recoverable pending replay, and lost/divergent lifecycle state. It never repairs implicitly
62
- or echoes private projector-error content into its report.
69
+ or echoes private projector-error content into its report. For session observability, it separates
70
+ fresh `none`/`complete` from legacy, degraded, stale, or manifest-unproven state and gives a
71
+ dry-run path before any write.
63
72
 
64
73
  ## Common errors and diagnosis
65
74
 
@@ -70,6 +79,9 @@ or echoes private projector-error content into its report.
70
79
  - `ambiguous`, lost publication, or a mismatched checkpoint: blocking; preserve registry, ledger,
71
80
  outbox, and SHARED so `last_memory_attempt` can be correlated before repair.
72
81
  - Corrupt bundle: preserve evidence and run `memory status --gate` before `memory repair`.
82
+ - `legacy`/`degraded`/`stale`/`manifest-unproven` observability: run
83
+ `wendkeep cost rebuild --session <id> --json`, review diagnostics, and only then authorize
84
+ `--apply`.
73
85
 
74
86
  ## Next steps
75
87
 
@@ -46,6 +46,14 @@ npx wendkeep import [options]
46
46
  - `Stop` accepts only a transcript-proven turn from the compatible active activation. Duplicates
47
47
  are no-ops; stale/superseded Stops neither publish memory nor overwrite a newer epoch's
48
48
  checkpoint.
49
+ - `Stop` receives an absolute **45 s** deadline from hook entry. Reads check the clock between
50
+ rollouts and on every chunk; reaching the limit returns `degraded` before the host timeout.
51
+ - `SubagentStop` receives an absolute **15 s** deadline. Signals arriving within the **250 ms**
52
+ window are coalesced: only the highest sequence recomposes/publishes, without losing the last
53
+ child.
54
+ - Observability is tri-state: `complete` publishes the full snapshot; `none` means zero proven by
55
+ a causal Stop or stable offline scan; `degraded` preserves the previous snapshot and allowlisted
56
+ diagnostics. An isolated `SubagentStop` never publishes `none`.
49
57
  - When compacting conversations into `## Iterações`, the hook escapes code delimiters cut by the
50
58
  size limit; inline backticks and fences never remain open and consume the following line.
51
59
  - `session list` reads `SESSION_REGISTRY`; `show` displays one session and `use` only changes human
@@ -53,6 +61,9 @@ npx wendkeep import [options]
53
61
  - `import --source all|claude|codex`, `--since`, `--limit`, `--from`, and `--codex-from` bound scope.
54
62
  - `--dry-run`/`--json` support audit before writes; `--stamp-ids` and `--rescan-decisions` address
55
63
  specific historical gaps.
64
+ - `import` reconciles observability even when no `wk-turn` is missing: a legacy schema, stale
65
+ frontier, or unproven manifest triggers recomposition without duplicating iterations. A fresh
66
+ checkpoint remains byte-identical; `degraded` is reported and does not change the note.
56
67
  - Exit `0` means consistent processing; non-zero reports invalid source/config/write instead of
57
68
  presenting silent partial success.
58
69
 
@@ -71,6 +82,8 @@ registry keeps one `SessionStart` epoch per activation plus the latest native tu
71
82
  `Stop` events may acknowledge turns in that epoch without closing it. Repeated imports of the
72
83
  same `session_id` deduplicate; human focus does not close or re-identify live hooks. Every
73
84
  automatic iteration remains valid Markdown even when a message must be truncated.
85
+ Duplicate/stale hooks converge on the same frontier, and imports may refresh only observability
86
+ without creating a new turn block.
74
87
 
75
88
  ## Common errors and diagnosis
76
89
 
@@ -82,6 +95,8 @@ automatic iteration remains valid Markdown even when a message must be truncated
82
95
  - Fork duplicates: bound source/date and inspect `forked_from_id`/`source.subagent`.
83
96
  - Codex does not capture: approve hooks and start a new session after `sync`.
84
97
  - Contaminated cost: validate `session_id → session_file → transcript_path → provider`.
98
+ - `degraded` observability: preserve the note and run a targeted rebuild dry-run; never force a
99
+ partial snapshot over the last `complete` one.
85
100
 
86
101
  ## Next steps
87
102
 
@@ -26,7 +26,7 @@ Registry consistente, tabela de preços completa e acesso aos transcripts das se
26
26
  ```bash
27
27
  npx wendkeep stats [--vault <cofre>] [--json]
28
28
  npx wendkeep cost [--since <data>] [--top [N]] [--trend day|week|month] [--write] [--json]
29
- npx wendkeep cost rebuild [--session <id|arquivo>] [--limit N] [--apply] [--json]
29
+ npx wendkeep cost rebuild [--session <id|arquivo>] [--limit N] [--max-graph-nodes N] [--max-fallback-days N] [--max-fallback-candidates N] [--apply] [--json]
30
30
  ```
31
31
 
32
32
  ## Opções e códigos de saída
@@ -34,10 +34,18 @@ npx wendkeep cost rebuild [--session <id|arquivo>] [--limit N] [--apply] [--json
34
34
  - `wendkeep stats` gera uma linha compartilhável ou JSON.
35
35
  - `wendkeep cost` agrega total/modelo/dia; `--trend` inclui projeção e `--write` atualiza
36
36
  `00-Custo.md`.
37
- - `wendkeep cost rebuild` é dry-run por padrão; `--apply` grava notas e
38
- `.brain/COST_REBUILD.json`.
39
- - Exit `0` indica cálculo consistente; não zero indica registry, preço, transcript ou parsing
40
- insuficiente.
37
+ - `wendkeep cost rebuild` é dry-run por padrão e tem **zero escrita**: não adquire lock de
38
+ gravação, não altera nota, registry ou runtime e não cria `.brain/COST_REBUILD.json`.
39
+ - `--apply` publica somente candidatos `complete` ou `none`. O estado `none` zera a seção
40
+ quando um scan offline estável comprovou que nenhum subagente foi iniciado.
41
+ - Um candidato `degraded` ou `stale` produz exit `1` e preserva a nota sem alteração; o lote
42
+ continua para que outras sessões seguras possam ser processadas e o relatório exponha os
43
+ códigos sanitizados.
44
+ - Os overrides `--max-graph-nodes`, `--max-fallback-days` e `--max-fallback-candidates` são
45
+ exclusivamente para rebuild direcionado com `--session`. Usá-los sem `--session` é uso inválido
46
+ e produz exit `2`; hooks, import e rebuild em lote mantêm os limites padrão.
47
+ - Exit `0` significa preview/aplicação consistente; exit `1` indica resultado parcial
48
+ `degraded`/`stale`; exit `2` indica sintaxe ou contexto inválido.
41
49
 
42
50
  ## Exemplos
43
51
 
@@ -45,12 +53,16 @@ npx wendkeep cost rebuild [--session <id|arquivo>] [--limit N] [--apply] [--json
45
53
  npx wendkeep stats --vault .MeuApp-vault
46
54
  npx wendkeep cost --since 2026-07-01 --top 10 --trend week
47
55
  npx wendkeep cost rebuild --session 019abc --json
56
+ npx wendkeep cost rebuild --session 019abc --max-graph-nodes 8192 --json
57
+ npx wendkeep cost rebuild --session 019abc --apply
48
58
  ```
49
59
 
50
60
  ## Resultado esperado
51
61
 
52
- Totais preservam dimensões de input/output/cache/reasoning por modelo e período. Rebuild mostra a
53
- prévia antes de alterar notas e deixa um relatório reproduzível quando aplicado.
62
+ Totais preservam dimensões de input/output/cache/reasoning por modelo e período. A composição
63
+ tri-state devolve `complete`, `none` ou `degraded`, mais frontier, manifest e diagnostics
64
+ sanitizados. Rode e revise o dry-run antes de repetir o mesmo comando com `--apply`; uma segunda
65
+ aplicação semanticamente idêntica preserva nota, checkpoint, relatório e mtime.
54
66
 
55
67
  ## Erros comuns e diagnóstico
56
68
 
@@ -58,6 +70,8 @@ prévia antes de alterar notas e deixa um relatório reproduzível quando aplica
58
70
  - Custos de provider errado: valide a cadeia de identidade da sessão.
59
71
  - Transcript ausente: não estime silenciosamente; mantenha a lacuna visível.
60
72
  - Total duplicado por subagent/fork: confirme relação pai/subagent e deduplicação do registry.
73
+ - `degraded`/`stale`: preserve a nota e investigue diagnostics/frontier antes de autorizar apply.
74
+ - Override rejeitado: acrescente `--session <id|arquivo>` ou remova os três limites direcionados.
61
75
 
62
76
  ## Próximos passos
63
77
 
@@ -39,6 +39,11 @@ npx wendkeep --help
39
39
  continuam duráveis na outbox/ledger é warning recuperável.
40
40
  - Attempt ambíguo, event ID perdido (ausente de ledger e outbox), estado `projected` apenas na
41
41
  outbox ou checkpoint divergente são falhas bloqueantes.
42
+ - Para observabilidade de sessão, `legacy`, `degraded`, `stale` e `manifest-unproven` exigem
43
+ reconciliação ou evidência adicional. Somente `none` fresco e `complete` fresco são saudáveis:
44
+ frontier, checkpoint, root stat e source manifest precisam concordar.
45
+ - O `doctor` permanece somente leitura/read-only. Ele recomenda primeiro o dry-run direcionado;
46
+ somente depois da revisão humana orienta repetir com `--apply`.
42
47
  - `sync-defs --check` detecta drift sem gravar; `--reseed` restaura skills `wk-*` do pacote.
43
48
  - `theme sync` reaplica snippet CSS e grupos do grafo sem recriar o cofre.
44
49
  - `wendkeep --version` imprime a versão executada; `wendkeep --help` lista a interface pública.
@@ -52,6 +57,8 @@ npx wendkeep --version
52
57
  npx wendkeep sync-defs --check --vault .MeuApp-vault --project .
53
58
  npx wendkeep doctor --vault .MeuApp-vault
54
59
  npx wendkeep memory status --gate --vault .MeuApp-vault
60
+ npx wendkeep cost rebuild --session <id> --json
61
+ npx wendkeep cost rebuild --session <id> --apply
55
62
  ```
56
63
 
57
64
  ## Resultado esperado
@@ -59,7 +66,9 @@ npx wendkeep memory status --gate --vault .MeuApp-vault
59
66
  O doctor nomeia sessões, registry, links, notas, preços, derivadas e memória como saudáveis ou
60
67
  fornece um comando específico de diagnóstico/reparo. Na memória, ele distingue vazio inicial
61
68
  válido, replay pendente recuperável e lifecycle perdido/divergente. Nenhum reparo é aplicado
62
- implicitamente nem o conteúdo privado do erro do projector é reproduzido no relatório.
69
+ implicitamente nem o conteúdo privado do erro do projector é reproduzido no relatório. Na
70
+ observabilidade de sessão, ele separa `none`/`complete` frescos de estado legado, degradado, stale
71
+ ou sem manifest comprovado e oferece um caminho dry-run antes de qualquer escrita.
63
72
 
64
73
  ## Erros comuns e diagnóstico
65
74
 
@@ -70,6 +79,8 @@ implicitamente nem o conteúdo privado do erro do projector é reproduzido no re
70
79
  - `ambiguous`, publicação perdida ou checkpoint divergente: bloqueante; preserve registry, ledger,
71
80
  outbox e SHARED para correlacionar `last_memory_attempt` antes de reparar.
72
81
  - Bundle corrompido: preserve a evidência e use `memory status --gate` antes de `memory repair`.
82
+ - Observabilidade `legacy`/`degraded`/`stale`/`manifest-unproven`: rode
83
+ `wendkeep cost rebuild --session <id> --json`, revise diagnostics e só então autorize `--apply`.
73
84
 
74
85
  ## Próximos passos
75
86
 
@@ -46,6 +46,13 @@ npx wendkeep import [opções]
46
46
  - `Stop` aceita somente o turno comprovado pelo transcript e pela activation ativa compatível.
47
47
  Duplicatas são no-op; Stops stale/superseded não publicam memória nem sobrescrevem o checkpoint
48
48
  de um epoch mais novo.
49
+ - `Stop` recebe deadline absoluto de **45 s** desde a entrada do hook. A leitura verifica o relógio
50
+ entre rollouts e a cada chunk; ao atingir o limite, devolve `degraded` antes do timeout do host.
51
+ - `SubagentStop` recebe deadline absoluto de **15 s**. Sinais que chegam na janela de **250 ms**
52
+ são coalescidos: somente a maior sequência recompõe/publica, sem perder o último filho.
53
+ - A observabilidade usa tri-state: `complete` publica o snapshot integral; `none` representa zero
54
+ comprovado por Stop causal ou scan offline estável; `degraded` preserva o snapshot anterior e
55
+ diagnostics allowlisted. `SubagentStop` isolado nunca publica `none`.
49
56
  - Ao compactar conversas em `## Iterações`, o hook escapa delimitadores de código cortados pelo
50
57
  limite de tamanho; backticks inline ou fences nunca ficam abertos para engolir a linha seguinte.
51
58
  - `session list` lê `SESSION_REGISTRY`; `show` exibe uma sessão e `use` muda apenas o foco humano
@@ -53,6 +60,9 @@ npx wendkeep import [opções]
53
60
  - `import --source all|claude|codex`, `--since`, `--limit`, `--from` e `--codex-from` limitam escopo.
54
61
  - `--dry-run`/`--json` permitem auditar antes de gravar; `--stamp-ids` e `--rescan-decisions`
55
62
  corrigem históricos específicos.
63
+ - `import` reconcilia a observabilidade mesmo quando nenhum `wk-turn` está ausente: schema legado,
64
+ frontier stale ou manifest não comprovado disparam recomposição sem duplicar iterações. Um
65
+ checkpoint fresco permanece byte-idêntico; `degraded` é reportado e não altera a nota.
56
66
  - Exit `0` indica processamento consistente; exit não zero indica configuração, fonte ou escrita
57
67
  inválida sem transformar isso em sucesso parcial silencioso.
58
68
 
@@ -70,7 +80,9 @@ Cada sessão canônica aponta para provider, transcript, arquivo de nota e custo
70
80
  O registry mantém um epoch de `SessionStart` por activation e o turno nativo mais recente; vários
71
81
  `Stop` podem confirmar turnos do mesmo epoch sem fechá-lo. Importações repetidas do mesmo
72
82
  `session_id` são deduplicadas; o foco humano não encerra nem altera a identidade dos hooks. Cada
73
- iteração automática permanece Markdown válido mesmo quando uma fala precisa ser truncada.
83
+ iteração automática permanece Markdown válido mesmo quando uma fala precisa ser truncada. Hooks
84
+ duplicados/stale convergem no mesmo frontier, e importações podem atualizar só a observabilidade
85
+ sem criar um novo bloco de turno.
74
86
 
75
87
  ## Erros comuns e diagnóstico
76
88
 
@@ -82,6 +94,8 @@ iteração automática permanece Markdown válido mesmo quando uma fala precisa
82
94
  - Duplicatas de forks: limite por fonte/data e revise `forked_from_id`/`source.subagent`.
83
95
  - Codex não captura: aprove os hooks e reinicie a sessão após `sync`.
84
96
  - Custo contaminado: valide `session_id → session_file → transcript_path → provider`.
97
+ - Observabilidade `degraded`: preserve a nota e rode o rebuild direcionado em dry-run; não force
98
+ um snapshot parcial sobre o último `complete`.
85
99
 
86
100
  ## Próximos passos
87
101
 
@@ -0,0 +1,112 @@
1
+ import {
2
+ closeSync,
3
+ openSync,
4
+ readSync,
5
+ } from 'node:fs';
6
+
7
+ export const DEFAULT_CODEX_META_LINE_BYTES = 4 * 1024 * 1024;
8
+ const READ_CHUNK_BYTES = 64 * 1024;
9
+
10
+ function trimCarriageReturn(buffer) {
11
+ return buffer.length > 0 && buffer[buffer.length - 1] === 0x0d
12
+ ? buffer.subarray(0, buffer.length - 1)
13
+ : buffer;
14
+ }
15
+
16
+ // Codex writes session_meta as the first physical JSONL line. Read only that line: the
17
+ // transcript body can be hundreds of MiB and is irrelevant to identity/discovery.
18
+ export function readFirstJsonlLine(
19
+ path,
20
+ { maxBytes = DEFAULT_CODEX_META_LINE_BYTES } = {},
21
+ ) {
22
+ if (typeof path !== 'string' || !path) {
23
+ return { ok: false, reason: 'INVALID_PATH' };
24
+ }
25
+
26
+ const limit = Number(maxBytes);
27
+ if (!Number.isSafeInteger(limit) || limit <= 0) {
28
+ return { ok: false, reason: 'READ_ERROR' };
29
+ }
30
+
31
+ let fd;
32
+ try {
33
+ fd = openSync(path, 'r');
34
+ const parts = [];
35
+ let totalBytes = 0;
36
+
37
+ while (totalBytes <= limit) {
38
+ // The extra byte distinguishes an exactly-at-limit line followed by LF from a line
39
+ // whose content exceeds the limit.
40
+ const remaining = (limit + 1) - totalBytes;
41
+ const chunk = Buffer.allocUnsafe(Math.min(READ_CHUNK_BYTES, remaining));
42
+ const bytesRead = readSync(fd, chunk, 0, chunk.length, null);
43
+
44
+ if (bytesRead === 0) {
45
+ if (totalBytes === 0) return { ok: false, reason: 'EMPTY_FILE' };
46
+ const lineBuffer = trimCarriageReturn(Buffer.concat(parts, totalBytes));
47
+ return {
48
+ ok: true,
49
+ line: lineBuffer.toString('utf8'),
50
+ lineBytes: lineBuffer.length,
51
+ };
52
+ }
53
+
54
+ const bytes = chunk.subarray(0, bytesRead);
55
+ const newlineAt = bytes.indexOf(0x0a);
56
+ if (newlineAt !== -1) {
57
+ if (totalBytes + newlineAt > limit) {
58
+ return { ok: false, reason: 'LINE_TOO_LONG' };
59
+ }
60
+ parts.push(bytes.subarray(0, newlineAt));
61
+ const lineBuffer = trimCarriageReturn(Buffer.concat(parts, totalBytes + newlineAt));
62
+ if (lineBuffer.length === 0) return { ok: false, reason: 'EMPTY_FILE' };
63
+ return {
64
+ ok: true,
65
+ line: lineBuffer.toString('utf8'),
66
+ lineBytes: lineBuffer.length,
67
+ };
68
+ }
69
+
70
+ parts.push(bytes);
71
+ totalBytes += bytesRead;
72
+ if (totalBytes > limit) return { ok: false, reason: 'LINE_TOO_LONG' };
73
+ }
74
+
75
+ return { ok: false, reason: 'LINE_TOO_LONG' };
76
+ } catch {
77
+ return { ok: false, reason: 'READ_ERROR' };
78
+ } finally {
79
+ if (fd !== undefined) {
80
+ try { closeSync(fd); } catch { /* already closed */ }
81
+ }
82
+ }
83
+ }
84
+
85
+ export function readCodexRolloutMeta(
86
+ path,
87
+ { maxLineBytes = DEFAULT_CODEX_META_LINE_BYTES } = {},
88
+ ) {
89
+ const first = readFirstJsonlLine(path, { maxBytes: maxLineBytes });
90
+ if (!first.ok) return first;
91
+
92
+ let event;
93
+ try {
94
+ event = JSON.parse(first.line);
95
+ } catch {
96
+ return { ok: false, reason: 'INVALID_JSON' };
97
+ }
98
+
99
+ if (!event || typeof event !== 'object' || Array.isArray(event)
100
+ || event.type !== 'session_meta') {
101
+ return { ok: false, reason: 'NOT_SESSION_META' };
102
+ }
103
+ if (!event.payload || typeof event.payload !== 'object' || Array.isArray(event.payload)) {
104
+ return { ok: false, reason: 'INVALID_META' };
105
+ }
106
+
107
+ return {
108
+ ok: true,
109
+ meta: event.payload,
110
+ lineBytes: first.lineBytes,
111
+ };
112
+ }