wendkeep 0.71.1 → 0.72.1

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,67 @@ 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.72.1] — 2026-08-20
8
+
9
+ ### Added
10
+
11
+ - **Proveniência verificável de release.** A publicação gera um receipt com commit, versão, tag,
12
+ integridade npm, execução do workflow e GitHub Release, e recusa divergências entre o SHA testado,
13
+ a tag e o tarball publicado.
14
+ - **Contrato seguro do Observer.** O Keep Core permanece em Node.js 18+, enquanto comandos SQL
15
+ diagnosticam `WENDKEEP_OBSERVER_NODE_UNSUPPORTED` abaixo do Node.js 22.13. Mutações exigem Bearer,
16
+ non-loopback exige token e requisições validam Host e Origin.
17
+ - **Níveis de captura.** `metadata` é o padrão sem mensagens; `messages` e `full-transcript` são
18
+ opt-in. Caminhos absolutos não são publicados e init recomenda ignorar state e outbox SQL.
19
+
20
+ ### Changed
21
+
22
+ - **Release somente após CI verde.** O workflow publica o SHA aprovado pela matriz Core (Node 18/20)
23
+ e Observer (Node 22.13/24), cria a tag no mesmo commit e pode reconciliar execuções repetidas.
24
+ - **Dogfooding pelo working tree.** O repositório não depende mais de `wendkeep` em devDependencies;
25
+ seus hooks chamam `node ./bin/wendkeep.mjs`, enquanto projetos consumidores usam
26
+ `npx --no-install wendkeep` e o tarball continua testado isoladamente.
27
+
28
+ ### Fixed
29
+
30
+ - **Identidade de arquivos de memória no Windows.** A revalidação compara o índice do arquivo como
31
+ inteiro exato e tolera a inconsistência conhecida do serial de volume do libuv antigo, evitando
32
+ falsos `VAULT_PATH_UNSAFE` no Node.js 22.13 sem relaxar a rejeição de hardlinks ou reparses.
33
+ - **Ingestão SQL grande em runners lentos.** O timeout HTTP cresce com o tamanho bruto do lote até
34
+ 120 segundos, preservando 15 segundos para payloads vazios/pequenos e evitando outbox falsa para
35
+ lotes gzip válidos acima de 64 MB.
36
+ - **Trusted Publisher preservado após o gate de CI.** `auto-tag.yml`, o workflow já autorizado no
37
+ npm, passa a executar a matriz da `main` e mantém o publish em um job com `needs: test`;
38
+ `test.yml` fica exclusivo para pull requests.
39
+
40
+ ## [0.72.0] — 2026-08-17
41
+
42
+ ### Added
43
+
44
+ - **Observer SQL authority.** O volume Docker agora usa `/data/observer.sqlite` como
45
+ autoridade única para documentos, sessões, agentes, uso, chamadas LLM e transcripts
46
+ comprimidos; as migrações SQL são versionadas e idempotentes.
47
+ - **Ingestão resiliente.** Hooks de sessão e subagentes enviam eventos idempotentes ao
48
+ Observer, preservam custos registrados e usam outbox local quando o container está
49
+ indisponível.
50
+ - **Dashboard de Consumo.** Cada projeto ganhou resumo de tokens/custos, filtros,
51
+ hierarquia agente/subagente/modelo, tendência diária, chamadas e leitura de transcript.
52
+ - **Migração sem perda.** Conteúdo legado do volume, `MEMORY_EVENTS.jsonl`, frontmatter de
53
+ custo e históricos sem transcript são importados sem apagar as fontes existentes;
54
+ históricos incompletos são marcados como `summary_only`; divergências entre frontmatter e
55
+ ledger ficam em linhas explícitas de reconciliação e `session_id` duplicado é desambiguado
56
+ por arquivo.
57
+
58
+ ### Changed
59
+
60
+ - Markdown deixou de ser autoridade operacional no container. Ele permanece armazenado como
61
+ conteúdo documental no SQLite e só é materializado por exportação explícita.
62
+ - O transporte divide lotes por quantidade e tamanho, reconhece retries do hash legado e
63
+ preserva transcripts grandes dentro do limite HTTP do Observer.
64
+ - Lotes SQL agora usam gzip no transporte e são expandidos com limite controlado no Observer,
65
+ permitindo importar transcripts históricos que excedem 64 MB em JSON puro sem aumentar
66
+ indiscriminadamente o limite de requisição.
67
+
7
68
  ## [0.71.1] — 2026-08-17
8
69
 
9
70
  ### Added
@@ -1001,7 +1062,7 @@ All notable changes to **wendkeep** are documented here. Format based on
1001
1062
  enum de eventos de hook do Codex.
1002
1063
  - A projeção Codex tem três diferenças em relação ao formato do `settings.json`, todas
1003
1064
  **silenciosas quando erradas** — daí valerem registro. (1) A chave de timeout é `timeoutSec`,
1004
- não `timeout`. (2) O comando é sempre `npx wendkeep hook <nome>`, nunca a forma node-direta:
1065
+ não `timeout`. (2) O comando é sempre `npx --no-install wendkeep hook <nome>`, nunca a forma node-direta:
1005
1066
  aquela emite `${CLAUDE_PROJECT_DIR}`, que não existe no Codex, então a flag `preferLocal` é
1006
1067
  ignorada de propósito na projeção. (3) As chaves de evento são PascalCase — o snake_case que
1007
1068
  se vê em `[hooks.state]` no `~/.codex/config.toml` é o rótulo interno do evento, não a chave
@@ -1585,7 +1646,7 @@ they only read + append.
1585
1646
 
1586
1647
  ### Note
1587
1648
  - You do **not** need `wendkeep init` for a routine update: the hooks live in the package
1588
- (`settings.json` calls `npx wendkeep hook …`), so `npm i -D wendkeep@latest` updates them.
1649
+ (`settings.json` calls `npx --no-install wendkeep hook …`), so `npm i -D wendkeep@latest` updates them.
1589
1650
  Re-run `init` only when a release adds new wiring (the CHANGELOG says so); it's idempotent.
1590
1651
 
1591
1652
  ## [0.26.0] — 2026-07-08
@@ -1765,7 +1826,7 @@ Fix: memory + active-change injection wired by default.
1765
1826
 
1766
1827
  ### Upgrade
1767
1828
  - Existing installs pick it up by re-running `wendkeep init --force` (idempotent — it only adds the
1768
- missing hook), or by adding `npx wendkeep hook brain-inject` to the SessionStart hooks manually.
1829
+ missing hook), or by adding `npx --no-install wendkeep hook brain-inject` to the SessionStart hooks manually.
1769
1830
 
1770
1831
  ## [0.18.0] — 2026-07-06
1771
1832
 
package/README.en.md CHANGED
@@ -88,7 +88,11 @@ Decisions, dead ends, the reason you chose X over Y — gone next session. The p
88
88
  | **Cost** — what it all cost | Per‑model, cache‑aware token pricing per session — plus `cost --trend` with a run‑rate projection across the whole vault; research previews without a final rate remain unestimated. |
89
89
  | **Multi‑agent** — one vault, both agents | `init` wires the session hooks into `.claude/settings.json` *and* `.codex/hooks.json`, and every note is tagged with the agent that wrote it: Claude Code is detected from its environment, anything else is recorded as Codex. One shared graph, whichever agent you are in. |
90
90
  | **Local‑first** — no cloud, no account | Everything is plain Markdown on your disk. An optional MCP server (`@bitbonsai/mcpvault`) lets the agent read/write the vault. |
91
- | **Local Observer** — many projects, one view | `wendkeep observer` keeps snapshots plus a complete copy of sessions, decisions, bugs, learnings, specs, and changes in the Docker volume; the read-only dashboard opens directly at `http://127.0.0.1:8787/`, local mode has no token, and unavailable hooks use an outbox without blocking the session. |
91
+ | **Local Observer** — many projects, one view | `wendkeep observer` keeps documents, sessions, agents, tokens, costs, calls, and transcripts in the Docker volume SQLite database; every project gets a **Consumption** tab in the read-only dashboard at `http://127.0.0.1:8787/`, loopback has no token, and unavailable hooks use a gzip outbox without blocking the session, including large transcripts. |
92
+
93
+ During historical migration, the Observer preserves differences between frontmatter totals and the
94
+ ledger as explicit reconciliation rows, and disambiguates duplicate `session_id` values per file
95
+ without inventing calls.
92
96
 
93
97
  ## Requirements
94
98
 
@@ -111,7 +115,7 @@ npx wendkeep init
111
115
 
112
116
  1. Create the vault folder taxonomy and a templated `README.md` (default vault: `<project>/.<project-name>-vault`, e.g. `.MyApp-vault`; override with `--vault`).
113
117
  2. Write a provider-neutral **`.wendkeep.json`** binding at the project root and a matching `.brain/PROJECT.json` marker in the vault, then merge the session hooks into **`.claude/settings.json`**. The binding is provider-neutral by design: any agent resolves the same vault from its session `cwd`, with no machine-global environment variable. Older registrations already in `.claude/settings.json` are adopted automatically.
114
- 3. Wire the Codex hooks in **`.codex/hooks.json`** — ten compatible entries: `brain-inject` + `session-start` + `observer-publish` on `SessionStart`, `session-ensure` + `change-context` on `UserPromptSubmit`, `session-stop` + `observer-publish` + `change-nag` on `Stop`, `subagent-stop` on `SubagentStop`, and `change-guard` on `PreToolUse` for `Bash`, `exec_command`, `apply_patch`, and mutable MCP tools, always in the `npx wendkeep hook <name>` form. `observer-publish` only publishes a sanitized, fail-open projection; it does not replace the local lifecycle. The guard accepts object, raw-string, and argv Codex payloads; before a mutation it compares the session with the project, Git root, remote, branch, and worktree, denying missing or divergent targets. The other four stay out because Codex offers no equivalent payload, tool, or event: `change-warn` (no reliable `tool_input.file_path`), `plan-capture` (no `ExitPlanMode`), `decision-capture` (`AskUserQuestion` is Claude-only), and `task-log` (`TaskCompleted` is not in Codex's event enum). Codex scope blocks use `permissionDecision: "deny"`; `ask` is never emitted in `PreToolUse`. The merge remains non-destructive, preserves third-party hooks, and migrates legacy `timeout` to `timeoutSec`. **Codex enumerates every hook as untrusted and runs none until you approve the “Hooks need review” prompt at startup — `init` cannot pre-approve them**.
118
+ 3. Wire the Codex hooks in **`.codex/hooks.json`** — eleven compatible entries: `brain-inject` + `session-start` + `observer-publish` on `SessionStart`, `session-ensure` + `change-context` on `UserPromptSubmit`, `session-stop` + `observer-publish` + `change-nag` on `Stop`, `subagent-stop` + `observer-publish` on `SubagentStop`, and `change-guard` on `PreToolUse` for `Bash`, `exec_command`, `apply_patch`, and mutable MCP tools, always in the `npx wendkeep hook <name>` form. `observer-publish` keeps the sanitized index projection and also sends the local SQL authority with documents, consumption, and transcripts; it does not replace the local lifecycle. The guard accepts object, raw-string, and argv Codex payloads; before a mutation it compares the session with the project, Git root, remote, branch, and worktree, denying missing or divergent targets. The other four stay out because Codex offers no equivalent payload, tool, or event: `change-warn` (no reliable `tool_input.file_path`), `plan-capture` (no `ExitPlanMode`), `decision-capture` (`AskUserQuestion` is Claude-only), and `task-log` (`TaskCompleted` is not in Codex's event enum). Codex scope blocks use `permissionDecision: "deny"`; `ask` is never emitted in `PreToolUse`. The merge remains non-destructive, preserves third-party hooks, and migrates legacy `timeout` to `timeoutSec`. **Codex enumerates every hook as untrusted and runs none until you approve the “Hooks need review” prompt at startup — `init` cannot pre-approve them**.
115
119
  4. Add the **`wendkeep-vault`** MCP server to `.mcp.json` so the agent can read/write the vault. Skip with `--no-mcp` — e.g. when the agent already has a vault MCP. (`--no-mcp` skips *only wendkeep's own* MCP; companion MCPs still follow `--companions`.)
116
120
  5. Offer to pin **companion** plugins/MCP (multi-choice; **none** pre-checked — wendkeep is a neutral harness and presumes no third-party plugin). Each is wired the most agent-agnostic way it supports:
117
121
  - **`context-mode`** — context optimizer + FTS5 memory, wired as a Claude Code plugin. It ships its own MCP server, so wendkeep deliberately adds no `.mcp.json` entry (registering both cold-started two servers at once). On non-Claude agents, add the MCP by hand: `npx -y context-mode`.
package/README.md CHANGED
@@ -88,7 +88,11 @@ Decisions, dead ends, the reason you chose X over Y — gone next session. The p
88
88
  | **Cost** — what it all cost | Per‑model, cache‑aware token pricing per session — plus `cost --trend` with a run‑rate projection across the whole vault; research previews without a final rate remain unestimated. |
89
89
  | **Multi‑agent** — one vault, both agents | `init` wires the session hooks into `.claude/settings.json` *and* `.codex/hooks.json`, and every note is tagged with the agent that wrote it: Claude Code is detected from its environment, anything else is recorded as Codex. One shared graph, whichever agent you are in. |
90
90
  | **Local‑first** — no cloud, no account | Everything is plain Markdown on your disk. An optional MCP server (`@bitbonsai/mcpvault`) lets the agent read/write the vault. |
91
- | **Local Observer** — many projects, one view | `wendkeep observer` keeps snapshots plus a complete copy of sessions, decisions, bugs, learnings, specs, and changes in the Docker volume; the read-only dashboard opens directly at `http://127.0.0.1:8787/`, local mode has no token, and unavailable hooks use an outbox without blocking the session. |
91
+ | **Local Observer** — many projects, one view | `wendkeep observer` keeps documents, sessions, agents, tokens, costs, calls, and transcripts in the Docker volume SQLite database; every project gets a **Consumption** tab in the read-only dashboard at `http://127.0.0.1:8787/`, loopback has no token, and unavailable hooks use a gzip outbox without blocking the session, including large transcripts. |
92
+
93
+ During historical migration, the Observer preserves differences between frontmatter totals and the
94
+ ledger as explicit reconciliation rows, and disambiguates duplicate `session_id` values per file
95
+ without inventing calls.
92
96
 
93
97
  ## Requirements
94
98
 
@@ -111,7 +115,7 @@ npx wendkeep init
111
115
 
112
116
  1. Create the vault folder taxonomy and a templated `README.md` (default vault: `<project>/.<project-name>-vault`, e.g. `.MyApp-vault`; override with `--vault`).
113
117
  2. Write a provider-neutral **`.wendkeep.json`** binding at the project root and a matching `.brain/PROJECT.json` marker in the vault, then merge the session hooks into **`.claude/settings.json`**. The binding is provider-neutral by design: any agent resolves the same vault from its session `cwd`, with no machine-global environment variable. Older registrations already in `.claude/settings.json` are adopted automatically.
114
- 3. Wire the Codex hooks in **`.codex/hooks.json`** — ten compatible entries: `brain-inject` + `session-start` + `observer-publish` on `SessionStart`, `session-ensure` + `change-context` on `UserPromptSubmit`, `session-stop` + `observer-publish` + `change-nag` on `Stop`, `subagent-stop` on `SubagentStop`, and `change-guard` on `PreToolUse` for `Bash`, `exec_command`, `apply_patch`, and mutable MCP tools, always in the `npx wendkeep hook <name>` form. `observer-publish` only publishes a sanitized, fail-open projection; it does not replace the local lifecycle. The guard accepts object, raw-string, and argv Codex payloads; before a mutation it compares the session with the project, Git root, remote, branch, and worktree, denying missing or divergent targets. The other four stay out because Codex offers no equivalent payload, tool, or event: `change-warn` (no reliable `tool_input.file_path`), `plan-capture` (no `ExitPlanMode`), `decision-capture` (`AskUserQuestion` is Claude-only), and `task-log` (`TaskCompleted` is not in Codex's event enum). Codex scope blocks use `permissionDecision: "deny"`; `ask` is never emitted in `PreToolUse`. The merge remains non-destructive, preserves third-party hooks, and migrates legacy `timeout` to `timeoutSec`. **Codex enumerates every hook as untrusted and runs none until you approve the “Hooks need review” prompt at startup — `init` cannot pre-approve them**.
118
+ 3. Wire the Codex hooks in **`.codex/hooks.json`** — eleven compatible entries: `brain-inject` + `session-start` + `observer-publish` on `SessionStart`, `session-ensure` + `change-context` on `UserPromptSubmit`, `session-stop` + `observer-publish` + `change-nag` on `Stop`, `subagent-stop` + `observer-publish` on `SubagentStop`, and `change-guard` on `PreToolUse` for `Bash`, `exec_command`, `apply_patch`, and mutable MCP tools, always in the `npx wendkeep hook <name>` form. `observer-publish` keeps the sanitized index projection and also sends the local SQL authority with documents, consumption, and transcripts; it does not replace the local lifecycle. The guard accepts object, raw-string, and argv Codex payloads; before a mutation it compares the session with the project, Git root, remote, branch, and worktree, denying missing or divergent targets. The other four stay out because Codex offers no equivalent payload, tool, or event: `change-warn` (no reliable `tool_input.file_path`), `plan-capture` (no `ExitPlanMode`), `decision-capture` (`AskUserQuestion` is Claude-only), and `task-log` (`TaskCompleted` is not in Codex's event enum). Codex scope blocks use `permissionDecision: "deny"`; `ask` is never emitted in `PreToolUse`. The merge remains non-destructive, preserves third-party hooks, and migrates legacy `timeout` to `timeoutSec`. **Codex enumerates every hook as untrusted and runs none until you approve the “Hooks need review” prompt at startup — `init` cannot pre-approve them**.
115
119
  4. Add the **`wendkeep-vault`** MCP server to `.mcp.json` so the agent can read/write the vault. Skip with `--no-mcp` — e.g. when the agent already has a vault MCP. (`--no-mcp` skips *only wendkeep's own* MCP; companion MCPs still follow `--companions`.)
116
120
  5. Offer to pin **companion** plugins/MCP (multi-choice; **none** pre-checked — wendkeep is a neutral harness and presumes no third-party plugin). Each is wired the most agent-agnostic way it supports:
117
121
  - **`context-mode`** — context optimizer + FTS5 memory, wired as a Claude Code plugin. It ships its own MCP server, so wendkeep deliberately adds no `.mcp.json` entry (registering both cold-started two servers at once). On non-Claude agents, add the MCP by hand: `npx -y context-mode`.
@@ -4,25 +4,29 @@
4
4
 
5
5
  ## Purpose
6
6
 
7
- The Observer consolidates observability for multiple WendKeep projects in a local service and
8
- stores a complete copy of the memory published by hooks in the Docker volume. The content can be
9
- browsed and searched in the container without depending on Obsidian for queries.
7
+ The Observer consolidates observability for multiple WendKeep projects in a local service. The
8
+ Docker volume keeps `/data/observer.sqlite` as the single authority for documents, sessions,
9
+ agents, usage, and calls. Complete transcripts are optional and require explicit capture. The content can be browsed and searched in the
10
+ container without depending on Obsidian for queries.
10
11
 
11
12
  ## When to use
12
13
 
13
- Use it to query changes, sessions, decisions, bugs, learnings, specs, brain documents, and health
14
- across projects through one local memory. During the transition, the vault is preserved as a
15
- recovery copy; the Observer is authoritative for queries made through its container.
14
+ Use it to query changes, sessions, decisions, bugs, learnings, specs, brain documents, per-agent
15
+ and per-model consumption, and health across projects through one local memory. During the
16
+ transition, the vault and legacy Markdown files remain a recovery copy; the Observer is
17
+ authoritative for queries made through its container.
16
18
 
17
19
  ## When not to use
18
20
 
19
- Do not use the Observer to edit, complete, or archive changes, curate memory, store transcripts,
20
- or expose the service to the network. Edits still go through local WendKeep hooks.
21
+ Do not use the Observer to edit, complete, or archive changes, curate memory, automatically export
22
+ the authority back to Markdown, or expose the service to the network. Edits still go through local
23
+ WendKeep hooks.
21
24
 
22
25
  ## Prerequisites
23
26
 
24
- Initialize projects with WendKeep and explicitly register each project before starting the HTTP
25
- server. The default local mode has no token to configure.
27
+ Use Node.js 22.13 or newer for the SQL Observer. Keep Core and the remaining commands continue to
28
+ support Node.js 18 or newer. Explicitly register each project and set `WENDKEEP_OBSERVER_TOKEN`;
29
+ loopback reads remain open, while every mutation requires a Bearer token.
26
30
 
27
31
  ## Syntax
28
32
 
@@ -30,8 +34,8 @@ server. The default local mode has no token to configure.
30
34
  npx wendkeep observer status --data-dir <directory> --json
31
35
  npx wendkeep observer register --project <project> --vault <vault> --data-dir <directory>
32
36
  npx wendkeep observer publish --project <project> --vault <vault> --data-dir <directory>
33
- npx wendkeep observer memory import --project <project> --vault <vault> --url http://127.0.0.1:8787 --json
34
- npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <directory>
37
+ npx wendkeep observer memory import --project <project> --vault <vault> --url http://127.0.0.1:8787 --token <token> --json
38
+ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <directory> --token <token>
35
39
  ```
36
40
 
37
41
  ## Options and exit codes
@@ -41,8 +45,9 @@ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <directory>
41
45
  - `--project` and `--vault` identify a project for `register`, `publish`, and `memory import`.
42
46
  - `--host` accepts only `127.0.0.1`, `localhost`, or `::1`; other hosts are rejected before
43
47
  listening.
44
- - `/v1` is open in the default local mode; keep `--host 127.0.0.1` and do not publish the port on
45
- a network address.
48
+ - `--token` or `WENDKEEP_OBSERVER_TOKEN` authenticates mutations; `--allow-non-loopback` fails without one.
49
+ - `WENDKEEP_OBSERVER_CAPTURE_LEVEL` accepts `metadata` (default, no messages), `messages`, or
50
+ `full-transcript`. Absolute local paths are never published.
46
51
  - Exit `0` means success; exit `1` means configuration or operation failure; the publisher hook
47
52
  also returns `0` when the Observer is unavailable.
48
53
 
@@ -50,7 +55,8 @@ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <directory>
50
55
 
51
56
  ```powershell
52
57
  npx wendkeep observer register --project C:\GitHub\WendKeep --vault C:\GitHub\WendKeep\.WendKeep-vault --data-dir C:\WendKeepObserver
53
- npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir C:\WendKeepObserver
58
+ $env:WENDKEEP_OBSERVER_TOKEN = '<strong-local-token>'
59
+ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir C:\WendKeepObserver --token $env:WENDKEEP_OBSERVER_TOKEN
54
60
  $env:WENDKEEP_OBSERVER_URL = 'http://127.0.0.1:8787'
55
61
  ```
56
62
 
@@ -63,14 +69,15 @@ docker compose -f docker/wendkeep-observer/compose.yaml up -d --build
63
69
  ## Local web dashboard
64
70
 
65
71
  With the server running, open [http://127.0.0.1:8787/](http://127.0.0.1:8787/) in a browser. The
66
- dashboard is served by the same process and opens directly, without a form or token. Keep the port
72
+ dashboard is served by the same process and opens directly for reads, without a form or token. Keep the port
67
73
  bound to the computer loopback; do not expose this address on a network interface.
68
74
 
69
75
  The dashboard shows the multi-project list, version, health, latest session, active change, change
70
- count, and last capture time. Opening a project exposes Overview, Sessions, Memory, Changes, and
71
- Sync screens. Each list opens the complete Markdown document in a read-only reader, with local
72
- filtering, body search, and a source toggle. Loading, empty, unavailable-server, conflict, and
73
- stale-data states are visible, with manual refresh and an automatic 15-second refresh.
76
+ count, and last capture time. Opening a project exposes Overview, Consumption, Sessions, Memory,
77
+ Changes, and Sync screens. Consumption shows total cost, token categories, primary agents,
78
+ subagents, providers, models, daily trend, historical coverage, and calls with prompt, response,
79
+ and transcript content according to the selected capture level. Loading, empty, unavailable-server, conflict, no-pricing, and stale-data
80
+ states are visible, with manual refresh and an automatic 15-second refresh.
74
81
 
75
82
  If the browser shows the shell but the list fails, check the service health at
76
83
  `http://127.0.0.1:8787/healthz` and confirm that the container is running.
@@ -78,25 +85,34 @@ If the browser shows the shell but the list fails, check the service health at
78
85
  ## Expected result
79
86
 
80
87
  `register` stores `project_id`, name, version, and registration time. `publish` reads the local
81
- vault, produces the snapshot, and also sends idempotent events containing the complete content of
82
- sessions, decisions, bugs, learnings, specs, changes, CORE, DIGEST, SHARED_MEMORY, and brain
83
- state. The container stores Markdown under `/data/memory` plus `MEMORY_EVENTS.jsonl` and
84
- `MEMORY_INDEX.json` in the `observer-data` volume; it does not mount `C:\GitHub` or any
85
- `.WendKeep-vault`. `memory import` performs the initial load and returns file/hash parity.
86
-
87
- `init` projects `observer-publish` into `SessionStart` and `Stop` after the primary hooks. Without
88
- `WENDKEEP_OBSERVER_URL`, the hook is a no-op. When the server is stopped, it writes snapshots to
89
- `.brain/observer-outbox/` and complete memory to `.brain/observer-memory-outbox/` without blocking
90
- the session; a later run retries both event types.
88
+ vault, produces the snapshot, and sends idempotent events to SQLite containing the complete content
89
+ of sessions, decisions, bugs, learnings, specs, changes, CORE, DIGEST, SHARED_MEMORY, brain state,
90
+ agent sessions, cost rollups, and calls. Messages and transcripts are only sent by capture levels
91
+ that explicitly enable them. The container stores everything in
92
+ `/data/observer.sqlite`; it does not mount `C:\GitHub` or any `.WendKeep-vault`. Markdown is only
93
+ the text held in SQL and is recreated as files only by an explicit read-only export.
94
+ `memory import` performs the initial load and returns file/hash parity. During migration, the
95
+ cost/token total recorded in frontmatter is preserved through an explicit reconciliation row when
96
+ the detailed ledger does not add up; that row does not invent calls. Historical sessions sharing
97
+ one `session_id` receive a canonical per-file identity so one rollup cannot overwrite the other.
98
+
99
+ `init` projects `observer-publish` into `SessionStart`, `Stop`, and `SubagentStop` after the primary
100
+ hooks. When the server is unavailable, it writes snapshots to `.brain/observer-outbox/` and SQL
101
+ events to `.brain/observer-sql-outbox/` without blocking the session; a later run retries the
102
+ batches. SQL batches use gzip so complete transcripts larger than 64 MB as plain JSON remain within
103
+ the transport limit; the Observer decompresses and validates the body before ingesting it. The
104
+ outbox is temporary transport, not authority.
91
105
 
92
106
  ## Common errors and diagnosis
93
107
 
94
108
  - `project_not_registered`: run `observer register` before publishing.
95
109
  - `host loopback`: replace `0.0.0.0` or a LAN address with `127.0.0.1`.
96
- - Pending outbox: the service was unavailable; preserve `.brain/observer-outbox/` and rerun the
97
- publisher. Do not delete events manually.
98
- - If memory is incomplete, check the Sync screen, preserve the outbox, and run
99
- `observer memory import` to rebuild the copy from the vault.
110
+ - Pending outbox: the service was unavailable; preserve `.brain/observer-outbox/` and
111
+ `.brain/observer-sql-outbox/`, then rerun the publisher. Also ignore
112
+ `.brain/observer-sql-state.json` and `.brain/observer-sql-outbox/` in a versioned vault. Do not delete events manually.
113
+ - `WENDKEEP_OBSERVER_NODE_UNSUPPORTED`: run the Observer on Node.js 22.13 or newer.
114
+ - If memory or usage is incomplete, check the Sync screen, preserve the outbox, and run
115
+ `observer memory import` to rebuild the load from the vault.
100
116
 
101
117
  ## Next steps
102
118
 
@@ -106,25 +122,34 @@ projection.
106
122
 
107
123
  ## Data authority
108
124
 
109
- The container is canonical for Observer queries and stores the complete published content. The
110
- vault remains preserved locally during migration as a transition and recovery copy; Observer
111
- screens do not complete, archive, repair, or promote state.
125
+ The container SQLite database is canonical for Observer queries and stores the complete published
126
+ content. The vault and any legacy `/data/memory` remain preserved during migration as a transition
127
+ and recovery copy; hooks do not update container Markdown after cutover. Observer screens do not
128
+ complete, archive, repair, or promote state.
112
129
 
113
130
  ## Minimal API
114
131
 
115
- - `GET /healthz` — availability without project data.
116
- - `GET /v1/projects` — projects with an accepted snapshot.
132
+ - `GET /healthz` — availability, SQLite migration version, and legacy migration state.
133
+ - `GET /v1/projects` — projects registered in SQLite, with a snapshot when available.
117
134
  - `GET /v1/projects/:project_id` — the latest project snapshot.
118
135
  - `GET /v1/projects/:project_id/changes` — change summary from the snapshot.
119
136
  - `PUT /v1/projects/:project_id` — explicit local registration.
120
137
  - `POST /v1/projects/:project_id/snapshot` — idempotent local ingestion.
138
+ - `POST /v1/projects/:project_id/ingest` — idempotent batches of documents, sessions, agents,
139
+ rollups, calls, and transcripts.
121
140
  - `GET /v1/projects/:project_id/memory/tree` — document tree and metadata.
122
141
  - `GET /v1/projects/:project_id/memory/document?path=...` — complete Markdown content.
123
142
  - `GET /v1/projects/:project_id/memory/search?q=...` — path and body search.
124
143
  - `GET /v1/projects/:project_id/sync` — mode, counts, conflicts, and latest event.
125
- - `PUT /v1/projects/:project_id/sync` — explicitly changes the local mode.
144
+ - `PUT /v1/projects/:project_id/sync` — compatibility configuration; SQL remains authoritative.
126
145
  - `GET /v1/projects/:project_id/memory/export` — read-only export with complete content.
127
146
  - `POST /v1/projects/:project_id/memory/events` — idempotent batch ingestion.
128
-
129
- The `/v1` routes reject oversized bodies and validate project, path, revision, hash, and
130
- isolation before writing content to the volume.
147
+ - `GET /v1/projects/:project_id/usage/summary` — filterable totals by period, change, session,
148
+ agent, provider, model, and role.
149
+ - `GET /v1/projects/:project_id/usage/breakdown` agent, subagent, and model hierarchy.
150
+ - `GET /v1/projects/:project_id/usage/calls` — individual calls with prompt and response.
151
+ - `GET /v1/projects/:project_id/transcripts/:transcript_id` — compressed transcript validated by hash.
152
+
153
+ The `/v1` routes reject transported or expanded bodies above their limits and validate project,
154
+ path, revision, hash, idempotency, and isolation before writing to SQLite. Use `memory/export` for
155
+ a Markdown copy; it does not alter SQL authority.
@@ -26,11 +26,11 @@ and a vault bound to the correct project.
26
26
  ## Syntax
27
27
 
28
28
  ```bash
29
- npx wendkeep hook <name>
29
+ npx --no-install wendkeep hook <name>
30
30
  npx wendkeep session list
31
31
  npx wendkeep session show <id>
32
32
  npx wendkeep session use <id>
33
- npx wendkeep hook session-backfill --session <id> [--write]
33
+ npx --no-install wendkeep hook session-backfill --session <id> [--write]
34
34
  npx wendkeep import [options]
35
35
  ```
36
36
 
@@ -96,8 +96,8 @@ npx wendkeep import [options]
96
96
  ```bash
97
97
  npx wendkeep session list
98
98
  npx wendkeep session show 019abc-session-id
99
- npx wendkeep hook session-backfill --session 019abc-session-id
100
- npx wendkeep hook session-backfill --session 019abc-session-id --write
99
+ npx --no-install wendkeep hook session-backfill --session 019abc-session-id
100
+ npx --no-install wendkeep hook session-backfill --session 019abc-session-id --write
101
101
  npx wendkeep import --source codex --since 2026-07-01 --dry-run --json
102
102
  ```
103
103
 
@@ -4,26 +4,29 @@
4
4
 
5
5
  ## Objetivo
6
6
 
7
- O Observer consolida a observabilidade de vários projetos WendKeep em um serviço local e grava no
8
- volume Docker uma cópia integral da memória publicada pelos hooks. O conteúdo fica disponível
9
- para navegação e busca no próprio container, sem depender do Obsidian para consulta.
7
+ O Observer consolida a observabilidade de vários projetos WendKeep em um serviço local. O volume
8
+ Docker mantém o SQLite `/data/observer.sqlite` como autoridade única para documentos, sessões,
9
+ agentes, uso e chamadas. Transcripts completos são opcionais e exigem captura explícita. O conteúdo fica disponível para navegação e busca
10
+ no próprio container, sem depender do Obsidian para consulta.
10
11
 
11
12
  ## Quando usar
12
13
 
13
- Use para consultar changes, sessões, decisões, bugs, aprendizados, specs, documentos do brain e
14
- saúde de vários projetos em uma única memória local. Durante a transição, o vault continua sendo
15
- preservado como cópia de origem para recuperação; o Observer é a autoridade de consulta do seu
16
- container.
14
+ Use para consultar changes, sessões, decisões, bugs, aprendizados, specs, documentos do brain,
15
+ consumo por agente/modelo e saúde de vários projetos em uma única memória local. Durante a
16
+ transição, o vault e os arquivos Markdown legados continuam preservados como cópia de origem para
17
+ recuperação; o Observer é a autoridade de consulta do seu container.
17
18
 
18
19
  ## Quando não usar
19
20
 
20
- Não use o Observer para editar, concluir ou arquivar changes, curar memória, armazenar transcripts
21
- ou expor o serviço na rede. As edições continuam passando pelos hooks e pelo WendKeep local.
21
+ Não use o Observer para editar, concluir ou arquivar changes, curar memória, exportar a autoridade
22
+ de volta para Markdown automaticamente ou expor o serviço na rede. As edições continuam passando
23
+ pelos hooks e pelo WendKeep local.
22
24
 
23
25
  ## Pré-requisitos
24
26
 
25
- Tenha os projetos inicializados com WendKeep e registre explicitamente cada projeto antes de
26
- iniciar o servidor HTTP. No modo local padrão não token para configurar.
27
+ Tenha Node.js 22.13 ou mais recente para executar o Observer SQL. O Keep Core e os demais comandos
28
+ continuam compatíveis com Node.js 18 ou mais recente. Registre explicitamente cada projeto e defina
29
+ `WENDKEEP_OBSERVER_TOKEN`; leituras no loopback permanecem abertas, mas toda mutação exige Bearer.
27
30
 
28
31
  ## Sintaxe
29
32
 
@@ -31,8 +34,8 @@ iniciar o servidor HTTP. No modo local padrão não há token para configurar.
31
34
  npx wendkeep observer status --data-dir <diretório> --json
32
35
  npx wendkeep observer register --project <projeto> --vault <vault> --data-dir <diretório>
33
36
  npx wendkeep observer publish --project <projeto> --vault <vault> --data-dir <diretório>
34
- npx wendkeep observer memory import --project <projeto> --vault <vault> --url http://127.0.0.1:8787 --json
35
- npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <diretório>
37
+ npx wendkeep observer memory import --project <projeto> --vault <vault> --url http://127.0.0.1:8787 --token <token> --json
38
+ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <diretório> --token <token>
36
39
  ```
37
40
 
38
41
  ## Opções e códigos de saída
@@ -42,8 +45,9 @@ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <diretório>
42
45
  - `--project` e `--vault` identificam o projeto nos comandos `register`, `publish` e `memory import`.
43
46
  - `--host` aceita somente `127.0.0.1`, `localhost` ou `::1`; outros hosts são recusados antes do
44
47
  listen.
45
- - as rotas `/v1` ficam abertas no modo local padrão; mantenha `--host 127.0.0.1` e não publique a
46
- porta em um endereço de rede.
48
+ - `--token` ou `WENDKEEP_OBSERVER_TOKEN` autentica mutações; `--allow-non-loopback` falha sem token.
49
+ - `WENDKEEP_OBSERVER_CAPTURE_LEVEL` aceita `metadata` (padrão, sem mensagens), `messages` ou
50
+ `full-transcript`. Caminhos locais absolutos nunca são publicados.
47
51
  - Exit `0` indica sucesso; exit `1` indica falha de configuração ou operação; o hook publisher
48
52
  também retorna `0` quando o Observer está indisponível.
49
53
 
@@ -51,7 +55,8 @@ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <diretório>
51
55
 
52
56
  ```powershell
53
57
  npx wendkeep observer register --project C:\GitHub\WendKeep --vault C:\GitHub\WendKeep\.WendKeep-vault --data-dir C:\WendKeepObserver
54
- npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir C:\WendKeepObserver
58
+ $env:WENDKEEP_OBSERVER_TOKEN = '<token-local-forte>'
59
+ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir C:\WendKeepObserver --token $env:WENDKEEP_OBSERVER_TOKEN
55
60
  $env:WENDKEEP_OBSERVER_URL = 'http://127.0.0.1:8787'
56
61
  ```
57
62
 
@@ -64,15 +69,16 @@ docker compose -f docker/wendkeep-observer/compose.yaml up -d --build
64
69
  ## Painel web local
65
70
 
66
71
  Com o servidor em execução, abra [http://127.0.0.1:8787/](http://127.0.0.1:8787/) no navegador.
67
- O painel é servido pelo mesmo processo e abre diretamente, sem formulário ou token. A porta fica
72
+ O painel é servido pelo mesmo processo e abre diretamente para consultas, sem formulário ou token. A porta fica
68
73
  presa ao loopback do computador; não coloque o endereço em uma interface de rede.
69
74
 
70
75
  O painel mostra a lista multi-projeto, versão, saúde, sessão mais recente, change ativa, contagem
71
- de changes e data da última captura. Ao abrir um projeto, o workspace oferece as telas Overview,
72
- Sessões, Memória, Changes e Sincronização. Cada lista abre o documento Markdown completo em um
73
- leitor read-only, com filtro local, busca no corpo e alternância para a fonte. Os estados de
74
- carregamento, vazio, servidor indisponível, conflito e dados desatualizados ficam visíveis, e a
75
- atualização pode ser manual ou automática a cada 15 segundos.
76
+ de changes e data da última captura. Ao abrir um projeto, o workspace oferece Overview, Consumo,
77
+ Sessões, Memória, Changes e Sincronização. A aba Consumo mostra custo total, tokens por categoria,
78
+ agentes principais, subagentes, provedores, modelos, tendência diária, cobertura histórica e
79
+ chamadas conforme o nível de captura escolhido. Os estados de carregamento, vazio, servidor
80
+ indisponível, conflito, modelo sem tarifa e dados desatualizados ficam visíveis, e a atualização
81
+ pode ser manual ou automática a cada 15 segundos.
76
82
 
77
83
  Se o navegador mostrar a tela mas a lista falhar, confirme a saúde em
78
84
  `http://127.0.0.1:8787/healthz` e verifique se o container está em execução.
@@ -80,25 +86,35 @@ Se o navegador mostrar a tela mas a lista falhar, confirme a saúde em
80
86
  ## Resultado esperado
81
87
 
82
88
  `register` grava `project_id`, nome, versão e data de registro. `publish` lê o vault local,
83
- produz o snapshot e também envia eventos idempotentes com o conteúdo integral das sessões,
84
- decisões, bugs, aprendizados, specs, changes, CORE, DIGEST, SHARED_MEMORY e estado do brain. O
85
- container grava os Markdown em `/data/memory` e mantém `MEMORY_EVENTS.jsonl` e
86
- `MEMORY_INDEX.json` no volume `observer-data`; não monta `C:\GitHub` nem qualquer
87
- `.WendKeep-vault`. `memory import` faz a carga inicial e retorna a paridade por arquivo e hash.
88
-
89
- O `init` projeta `observer-publish` para `SessionStart` e `Stop` depois dos hooks principais. Sem
90
- `WENDKEEP_OBSERVER_URL`, o hook é no-op. Com o servidor parado, ele grava os snapshots em
91
- `.brain/observer-outbox/` e a memória integral em `.brain/observer-memory-outbox/`, sem bloquear a
92
- sessão; uma execução posterior tenta reenviar os dois tipos de evento.
89
+ produz o snapshot e envia eventos idempotentes para o SQLite com o conteúdo integral das sessões,
90
+ decisões, bugs, aprendizados, specs, changes, CORE, DIGEST, SHARED_MEMORY, estado do brain,
91
+ sessões de agentes, rollups de custo e chamadas. Mensagens e transcripts só são enviados nos
92
+ níveis de captura que os habilitam. O container grava tudo em
93
+ `/data/observer.sqlite`; não monta `C:\GitHub` nem qualquer `.WendKeep-vault`. Markdown é aceito
94
+ somente como conteúdo de uma coluna SQL e volta a existir como arquivo apenas pela exportação
95
+ read-only sob demanda. `memory import` faz a carga inicial e retorna a paridade por arquivo e hash.
96
+ Na migração, o total de custo/token registrado no frontmatter é preservado por uma linha de
97
+ reconciliação quando o ledger detalhado não fecha com ele; essa linha não inventa chamadas.
98
+ Sessões históricas com o mesmo `session_id` recebem uma identidade canônica por arquivo para
99
+ evitar que um rollup sobrescreva o outro.
100
+
101
+ O `init` projeta `observer-publish` para `SessionStart`, `Stop` e `SubagentStop` depois dos hooks
102
+ principais. Sem servidor disponível, ele grava snapshots em `.brain/observer-outbox/` e eventos
103
+ SQL em `.brain/observer-sql-outbox/`, sem bloquear a sessão; uma execução posterior tenta
104
+ reenviar os lotes. Os lotes SQL são enviados com gzip para que transcripts completos maiores que
105
+ 64 MB em JSON puro continuem dentro do limite do transporte; o Observer descomprime e valida o
106
+ corpo antes de ingerir. O outbox é transporte temporário, não autoridade.
93
107
 
94
108
  ## Erros comuns e diagnóstico
95
109
 
96
110
  - `project_not_registered`: rode `observer register` antes de publicar.
97
111
  - `host loopback`: troque `0.0.0.0` ou endereço LAN por `127.0.0.1`.
98
- - Outbox pendente: o serviço estava indisponível; preserve `.brain/observer-outbox/` e repita o
99
- publisher. Não apague eventos manualmente.
100
- - Se a memória ficar incompleta, verifique a tela Sincronização, preserve o outbox e rode
101
- `observer memory import` para reconstruir a cópia a partir do vault.
112
+ - Outbox pendente: o serviço estava indisponível; preserve `.brain/observer-outbox/` e
113
+ `.brain/observer-sql-outbox/` e repita o publisher. Adicione também
114
+ `.brain/observer-sql-state.json` e `.brain/observer-sql-outbox/` ao ignore do Vault. Não apague eventos manualmente.
115
+ - `WENDKEEP_OBSERVER_NODE_UNSUPPORTED`: execute o Observer em Node.js 22.13 ou mais recente.
116
+ - Se a memória ou o consumo ficarem incompletos, verifique a tela Sincronização, preserve o
117
+ outbox e rode `observer memory import` para reconstruir a carga a partir do vault.
102
118
 
103
119
  ## Próximos passos
104
120
 
@@ -107,25 +123,34 @@ removido com `docker compose down -v` durante a operação normal, pois isso apa
107
123
 
108
124
  ## Autoridade dos dados
109
125
 
110
- O container é a memória canônica para consultas do Observer e guarda o conteúdo integral
111
- publicado. O vault continua preservado localmente durante a migração como cópia de transição e
112
- fonte de recuperação; as telas do Observer não concluem, arquivam, reparam ou promovem estado.
126
+ O SQLite do container é a memória canônica para consultas do Observer e guarda o conteúdo integral
127
+ publicado. O vault e qualquer `/data/memory` legado continuam preservados durante a migração como
128
+ cópia de transição e fonte de recuperação; os hooks não atualizam Markdown no container depois do
129
+ corte. As telas do Observer não concluem, arquivam, reparam ou promovem estado.
113
130
 
114
131
  ## API mínima
115
132
 
116
- - `GET /healthz` — disponibilidade sem dados de projeto.
117
- - `GET /v1/projects` — projetos com snapshot aceito.
133
+ - `GET /healthz` — disponibilidade, versão das migrações SQLite e estado da migração legada.
134
+ - `GET /v1/projects` — projetos registrados no SQLite, com snapshot quando houver.
118
135
  - `GET /v1/projects/:project_id` — último snapshot do projeto.
119
136
  - `GET /v1/projects/:project_id/changes` — resumo das changes do snapshot.
120
137
  - `PUT /v1/projects/:project_id` — registro explícito local.
121
138
  - `POST /v1/projects/:project_id/snapshot` — ingestão local idempotente.
139
+ - `POST /v1/projects/:project_id/ingest` — lote idempotente de documentos, sessões, agentes, rollups,
140
+ chamadas e transcripts.
122
141
  - `GET /v1/projects/:project_id/memory/tree` — árvore e metadados dos documentos.
123
142
  - `GET /v1/projects/:project_id/memory/document?path=...` — conteúdo Markdown integral.
124
143
  - `GET /v1/projects/:project_id/memory/search?q=...` — busca no caminho e no corpo.
125
144
  - `GET /v1/projects/:project_id/sync` — modo, contagem, conflitos e último evento.
126
- - `PUT /v1/projects/:project_id/sync` — altera explicitamente o modo local.
145
+ - `PUT /v1/projects/:project_id/sync` — compatibilidade de configuração; a autoridade continua SQL.
127
146
  - `GET /v1/projects/:project_id/memory/export` — exportação read-only com conteúdo completo.
128
147
  - `POST /v1/projects/:project_id/memory/events` — ingestão idempotente em lote.
129
-
130
- As rotas `/v1` rejeitam corpo acima do limite e validam projeto, caminho, revisão, hash e
131
- isolamento antes de gravar o conteúdo no volume.
148
+ - `GET /v1/projects/:project_id/usage/summary` — totais filtráveis por período, change, sessão,
149
+ agente, provedor, modelo e papel.
150
+ - `GET /v1/projects/:project_id/usage/breakdown` — hierarquia de agentes, subagentes e modelos.
151
+ - `GET /v1/projects/:project_id/usage/calls` — chamadas individuais com prompt e resposta.
152
+ - `GET /v1/projects/:project_id/transcripts/:transcript_id` — transcript comprimido, validado por hash.
153
+
154
+ As rotas `/v1` rejeitam corpo transportado ou expandido acima do limite e validam projeto, caminho,
155
+ revisão, hash, idempotência e isolamento antes de gravar o conteúdo no SQLite. Para preservar uma
156
+ cópia Markdown, use a rota `memory/export`; ela não altera a autoridade SQL.
@@ -26,11 +26,11 @@ Claude/Codex e um vault vinculado ao projeto correto.
26
26
  ## Sintaxe
27
27
 
28
28
  ```bash
29
- npx wendkeep hook <nome>
29
+ npx --no-install wendkeep hook <nome>
30
30
  npx wendkeep session list
31
31
  npx wendkeep session show <id>
32
32
  npx wendkeep session use <id>
33
- npx wendkeep hook session-backfill --session <id> [--write]
33
+ npx --no-install wendkeep hook session-backfill --session <id> [--write]
34
34
  npx wendkeep import [opções]
35
35
  ```
36
36
 
@@ -95,8 +95,8 @@ npx wendkeep import [opções]
95
95
  ```bash
96
96
  npx wendkeep session list
97
97
  npx wendkeep session show 019abc-session-id
98
- npx wendkeep hook session-backfill --session 019abc-session-id
99
- npx wendkeep hook session-backfill --session 019abc-session-id --write
98
+ npx --no-install wendkeep hook session-backfill --session 019abc-session-id
99
+ npx --no-install wendkeep hook session-backfill --session 019abc-session-id --write
100
100
  npx wendkeep import --source codex --since 2026-07-01 --dry-run --json
101
101
  ```
102
102
 
@@ -9,6 +9,7 @@ async function main() {
9
9
  const result = await publishObserverSnapshot({
10
10
  vaultBase: resolved.base,
11
11
  projectRoot: resolved.projectRoot,
12
+ input,
12
13
  });
13
14
  if (!result.ok && result.error) debugLog('Observer publish fail-open:', result.error);
14
15
  }
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // understand-inject — SessionStart hook (agent-agnostic, run via `npx wendkeep hook
2
+ // understand-inject — SessionStart hook (agent-agnostic, run via `npx --no-install wendkeep hook
3
3
  // understand-inject`). If the Understand-Anything domain graph has been generated
4
4
  // (`.understand-anything/knowledge-graph.json` at the project root), inject a cheap
5
5
  // slice of it into the session; otherwise stay silent. Never breaks the session.