wendkeep 0.70.0 → 0.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.en.md +7 -3
- package/README.md +7 -3
- package/docs/en/commands/observer.md +80 -35
- package/docs/pt-BR/commands/observer.md +82 -37
- package/hooks/observer-publish.mjs +1 -0
- package/package.json +3 -2
- package/packages/integrations/src/host-hooks.mjs +2 -0
- package/schema/observer/001-authority.sql +107 -0
- package/schema/observer/002-usage.sql +72 -0
- package/schema/observer/003-transcripts.sql +21 -0
- package/src/observer-memory-publish.mjs +335 -0
- package/src/observer-memory.mjs +308 -0
- package/src/observer-publish.mjs +23 -9
- package/src/observer-server.mjs +335 -22
- package/src/observer-sql-migrate.mjs +335 -0
- package/src/observer-sql-publish.mjs +398 -0
- package/src/observer-sql-store.mjs +542 -0
- package/src/observer-transcript-store.mjs +49 -0
- package/src/observer.mjs +72 -16
- package/web/observer/app.mjs +858 -0
- package/web/observer/favicon.svg +5 -0
- package/web/observer/index.html +126 -0
- package/web/observer/styles.css +262 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,63 @@ 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.0] — 2026-08-17
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Observer SQL authority.** O volume Docker agora usa `/data/observer.sqlite` como
|
|
12
|
+
autoridade única para documentos, sessões, agentes, uso, chamadas LLM e transcripts
|
|
13
|
+
comprimidos; as migrações SQL são versionadas e idempotentes.
|
|
14
|
+
- **Ingestão resiliente.** Hooks de sessão e subagentes enviam eventos idempotentes ao
|
|
15
|
+
Observer, preservam custos registrados e usam outbox local quando o container está
|
|
16
|
+
indisponível.
|
|
17
|
+
- **Dashboard de Consumo.** Cada projeto ganhou resumo de tokens/custos, filtros,
|
|
18
|
+
hierarquia agente/subagente/modelo, tendência diária, chamadas e leitura de transcript.
|
|
19
|
+
- **Migração sem perda.** Conteúdo legado do volume, `MEMORY_EVENTS.jsonl`, frontmatter de
|
|
20
|
+
custo e históricos sem transcript são importados sem apagar as fontes existentes;
|
|
21
|
+
históricos incompletos são marcados como `summary_only`; divergências entre frontmatter e
|
|
22
|
+
ledger ficam em linhas explícitas de reconciliação e `session_id` duplicado é desambiguado
|
|
23
|
+
por arquivo.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Markdown deixou de ser autoridade operacional no container. Ele permanece armazenado como
|
|
28
|
+
conteúdo documental no SQLite e só é materializado por exportação explícita.
|
|
29
|
+
- O transporte divide lotes por quantidade e tamanho, reconhece retries do hash legado e
|
|
30
|
+
preserva transcripts grandes dentro do limite HTTP do Observer.
|
|
31
|
+
- Lotes SQL agora usam gzip no transporte e são expandidos com limite controlado no Observer,
|
|
32
|
+
permitindo importar transcripts históricos que excedem 64 MB em JSON puro sem aumentar
|
|
33
|
+
indiscriminadamente o limite de requisição.
|
|
34
|
+
|
|
35
|
+
## [0.71.1] — 2026-08-17
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- **Observer memory authority.** O container local agora recebe a cópia integral das sessões,
|
|
40
|
+
decisões, bugs, aprendizados, specs, changes, CORE, DIGEST, SHARED_MEMORY e estado do brain.
|
|
41
|
+
A API oferece árvore, leitura completa, busca por corpo, sincronização, modos
|
|
42
|
+
`mirror`/`container-read`/`container-authority` e exportação read-only.
|
|
43
|
+
- **Workspace de memória no navegador.** O painel local navega por projeto, sessões, memória,
|
|
44
|
+
changes, sincronização e leitor Markdown completo, sem formulário ou token no loopback.
|
|
45
|
+
- **Importação do WendKeep.** `observer memory import` registra a carga inicial e informa paridade
|
|
46
|
+
por arquivo e hash; o volume Docker permanece preservado em rebuild e reinício.
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- **Observer local abre diretamente.** O dashboard não exige mais token, formulário ou
|
|
51
|
+
`Authorization` para consultar a projeção no loopback; o compose também inicia sem variável de
|
|
52
|
+
token obrigatória.
|
|
53
|
+
|
|
54
|
+
## [0.71.0] — 2026-08-17
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **Painel web local do Observer.** O servidor agora entrega uma interface read-only no navegador
|
|
59
|
+
para consultar projetos, saúde, sessões, changes e snapshots sanitizados da última captura. A interface é empacotada no
|
|
60
|
+
npm e na imagem Docker, exige o token local para consultar `/v1`, mantém o token somente no
|
|
61
|
+
`sessionStorage` da aba e
|
|
62
|
+
não amplia o contrato de dados sanitizados.
|
|
63
|
+
|
|
7
64
|
## [0.70.0] — 2026-08-17
|
|
8
65
|
|
|
9
66
|
### Added
|
package/README.en.md
CHANGED
|
@@ -78,7 +78,7 @@ npx wendkeep import # backfill past Claude + Codex sess
|
|
|
78
78
|
|
|
79
79
|
## The problem: the context dies when the window closes
|
|
80
80
|
|
|
81
|
-
Decisions, dead ends, the reason you chose X over Y — gone next session. The pieces to fix that exist but are scattered (qmd‑sessions, memsearch, Nexus, hand‑written hooks). wendkeep ships
|
|
81
|
+
Decisions, dead ends, the reason you chose X over Y — gone next session. The pieces to fix that exist but are scattered (qmd‑sessions, memsearch, Nexus, hand‑written hooks). wendkeep ships local capture plus an optional Docker Observer that keeps complete memory browsable without depending on Obsidian.
|
|
82
82
|
|
|
83
83
|
| | |
|
|
84
84
|
|---|---|
|
|
@@ -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
|
|
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`** —
|
|
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
|
@@ -78,7 +78,7 @@ npx wendkeep import # backfill past Claude + Codex sess
|
|
|
78
78
|
|
|
79
79
|
## The problem: the context dies when the window closes
|
|
80
80
|
|
|
81
|
-
Decisions, dead ends, the reason you chose X over Y — gone next session. The pieces to fix that exist but are scattered (qmd‑sessions, memsearch, Nexus, hand‑written hooks). wendkeep ships
|
|
81
|
+
Decisions, dead ends, the reason you chose X over Y — gone next session. The pieces to fix that exist but are scattered (qmd‑sessions, memsearch, Nexus, hand‑written hooks). wendkeep ships local capture plus an optional Docker Observer that keeps complete memory browsable without depending on Obsidian.
|
|
82
82
|
|
|
83
83
|
| | |
|
|
84
84
|
|---|---|
|
|
@@ -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
|
|
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`** —
|
|
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,23 +4,28 @@
|
|
|
4
4
|
|
|
5
5
|
## Purpose
|
|
6
6
|
|
|
7
|
-
The Observer consolidates observability for multiple WendKeep projects in a local service
|
|
8
|
-
|
|
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, calls, and complete transcripts. The content can be browsed and searched in the
|
|
10
|
+
container without depending on Obsidian for queries.
|
|
9
11
|
|
|
10
12
|
## When to use
|
|
11
13
|
|
|
12
|
-
Use it to query
|
|
13
|
-
|
|
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.
|
|
14
18
|
|
|
15
19
|
## When not to use
|
|
16
20
|
|
|
17
|
-
Do not use the Observer to edit, complete, or archive changes, curate memory,
|
|
18
|
-
|
|
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.
|
|
19
24
|
|
|
20
25
|
## Prerequisites
|
|
21
26
|
|
|
22
|
-
Initialize projects with WendKeep
|
|
23
|
-
|
|
27
|
+
Initialize projects with WendKeep and explicitly register each project before starting the HTTP
|
|
28
|
+
server. The default local mode has no token to configure.
|
|
24
29
|
|
|
25
30
|
## Syntax
|
|
26
31
|
|
|
@@ -28,6 +33,7 @@ starting the HTTP server.
|
|
|
28
33
|
npx wendkeep observer status --data-dir <directory> --json
|
|
29
34
|
npx wendkeep observer register --project <project> --vault <vault> --data-dir <directory>
|
|
30
35
|
npx wendkeep observer publish --project <project> --vault <vault> --data-dir <directory>
|
|
36
|
+
npx wendkeep observer memory import --project <project> --vault <vault> --url http://127.0.0.1:8787 --json
|
|
31
37
|
npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <directory>
|
|
32
38
|
```
|
|
33
39
|
|
|
@@ -35,17 +41,17 @@ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <directory>
|
|
|
35
41
|
|
|
36
42
|
- `--data-dir` selects the local event and index directory; the default is
|
|
37
43
|
`WENDKEEP_OBSERVER_DATA_DIR` or `~/.wendkeep-observer`.
|
|
38
|
-
- `--project` and `--vault` identify a project
|
|
44
|
+
- `--project` and `--vault` identify a project for `register`, `publish`, and `memory import`.
|
|
39
45
|
- `--host` accepts only `127.0.0.1`, `localhost`, or `::1`; other hosts are rejected before
|
|
40
46
|
listening.
|
|
41
|
-
-
|
|
47
|
+
- `/v1` is open in the default local mode; keep `--host 127.0.0.1` and do not publish the port on
|
|
48
|
+
a network address.
|
|
42
49
|
- Exit `0` means success; exit `1` means configuration or operation failure; the publisher hook
|
|
43
50
|
also returns `0` when the Observer is unavailable.
|
|
44
51
|
|
|
45
52
|
## Examples
|
|
46
53
|
|
|
47
54
|
```powershell
|
|
48
|
-
$env:WENDKEEP_OBSERVER_TOKEN = '<local-token>'
|
|
49
55
|
npx wendkeep observer register --project C:\GitHub\WendKeep --vault C:\GitHub\WendKeep\.WendKeep-vault --data-dir C:\WendKeepObserver
|
|
50
56
|
npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir C:\WendKeepObserver
|
|
51
57
|
$env:WENDKEEP_OBSERVER_URL = 'http://127.0.0.1:8787'
|
|
@@ -54,30 +60,53 @@ $env:WENDKEEP_OBSERVER_URL = 'http://127.0.0.1:8787'
|
|
|
54
60
|
For local Docker:
|
|
55
61
|
|
|
56
62
|
```powershell
|
|
57
|
-
$env:WENDKEEP_OBSERVER_TOKEN = '<local-token>'
|
|
58
63
|
docker compose -f docker/wendkeep-observer/compose.yaml up -d --build
|
|
59
64
|
```
|
|
60
65
|
|
|
61
|
-
##
|
|
66
|
+
## Local web dashboard
|
|
67
|
+
|
|
68
|
+
With the server running, open [http://127.0.0.1:8787/](http://127.0.0.1:8787/) in a browser. The
|
|
69
|
+
dashboard is served by the same process and opens directly, without a form or token. Keep the port
|
|
70
|
+
bound to the computer loopback; do not expose this address on a network interface.
|
|
71
|
+
|
|
72
|
+
The dashboard shows the multi-project list, version, health, latest session, active change, change
|
|
73
|
+
count, and last capture time. Opening a project exposes Overview, Consumption, Sessions, Memory,
|
|
74
|
+
Changes, and Sync screens. Consumption shows total cost, token categories, primary agents,
|
|
75
|
+
subagents, providers, models, daily trend, historical coverage, and calls with prompt, response,
|
|
76
|
+
and complete transcript. Loading, empty, unavailable-server, conflict, no-pricing, and stale-data
|
|
77
|
+
states are visible, with manual refresh and an automatic 15-second refresh.
|
|
62
78
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
only `EVENTS.jsonl` and `INDEX.json` in the `observer-data` volume; it does not mount `C:\GitHub`
|
|
66
|
-
or any `.WendKeep-vault`.
|
|
79
|
+
If the browser shows the shell but the list fails, check the service health at
|
|
80
|
+
`http://127.0.0.1:8787/healthz` and confirm that the container is running.
|
|
67
81
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
82
|
+
## Expected result
|
|
83
|
+
|
|
84
|
+
`register` stores `project_id`, name, version, and registration time. `publish` reads the local
|
|
85
|
+
vault, produces the snapshot, and sends idempotent events to SQLite containing the complete content
|
|
86
|
+
of sessions, decisions, bugs, learnings, specs, changes, CORE, DIGEST, SHARED_MEMORY, brain state,
|
|
87
|
+
agent sessions, cost rollups, calls, and transcripts. The container stores everything in
|
|
88
|
+
`/data/observer.sqlite`; it does not mount `C:\GitHub` or any `.WendKeep-vault`. Markdown is only
|
|
89
|
+
the text held in SQL and is recreated as files only by an explicit read-only export.
|
|
90
|
+
`memory import` performs the initial load and returns file/hash parity. During migration, the
|
|
91
|
+
cost/token total recorded in frontmatter is preserved through an explicit reconciliation row when
|
|
92
|
+
the detailed ledger does not add up; that row does not invent calls. Historical sessions sharing
|
|
93
|
+
one `session_id` receive a canonical per-file identity so one rollup cannot overwrite the other.
|
|
94
|
+
|
|
95
|
+
`init` projects `observer-publish` into `SessionStart`, `Stop`, and `SubagentStop` after the primary
|
|
96
|
+
hooks. When the server is unavailable, it writes snapshots to `.brain/observer-outbox/` and SQL
|
|
97
|
+
events to `.brain/observer-sql-outbox/` without blocking the session; a later run retries the
|
|
98
|
+
batches. SQL batches use gzip so complete transcripts larger than 64 MB as plain JSON remain within
|
|
99
|
+
the transport limit; the Observer decompresses and validates the body before ingesting it. The
|
|
100
|
+
outbox is temporary transport, not authority.
|
|
71
101
|
|
|
72
102
|
## Common errors and diagnosis
|
|
73
103
|
|
|
74
104
|
- `project_not_registered`: run `observer register` before publishing.
|
|
75
|
-
- `unauthorized`: check `Authorization: Bearer <token>` and `WENDKEEP_OBSERVER_TOKEN`.
|
|
76
105
|
- `host loopback`: replace `0.0.0.0` or a LAN address with `127.0.0.1`.
|
|
77
|
-
- Pending outbox: the service was unavailable; preserve `.brain/observer-outbox/` and
|
|
78
|
-
publisher. Do not delete events manually.
|
|
79
|
-
-
|
|
80
|
-
|
|
106
|
+
- Pending outbox: the service was unavailable; preserve `.brain/observer-outbox/` and
|
|
107
|
+
`.brain/observer-sql-outbox/`, then rerun the publisher. Do not delete events manually.
|
|
108
|
+
- If memory or usage is incomplete, check the Sync screen, preserve the outbox, and run
|
|
109
|
+
`observer memory import` to rebuild the load from the vault.
|
|
81
110
|
|
|
82
111
|
## Next steps
|
|
83
112
|
|
|
@@ -87,18 +116,34 @@ projection.
|
|
|
87
116
|
|
|
88
117
|
## Data authority
|
|
89
118
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
119
|
+
The container SQLite database is canonical for Observer queries and stores the complete published
|
|
120
|
+
content. The vault and any legacy `/data/memory` remain preserved during migration as a transition
|
|
121
|
+
and recovery copy; hooks do not update container Markdown after cutover. Observer screens do not
|
|
122
|
+
complete, archive, repair, or promote state.
|
|
93
123
|
|
|
94
124
|
## Minimal API
|
|
95
125
|
|
|
96
|
-
- `GET /healthz` — availability
|
|
97
|
-
- `GET /v1/projects` — projects with
|
|
126
|
+
- `GET /healthz` — availability, SQLite migration version, and legacy migration state.
|
|
127
|
+
- `GET /v1/projects` — projects registered in SQLite, with a snapshot when available.
|
|
98
128
|
- `GET /v1/projects/:project_id` — the latest project snapshot.
|
|
99
129
|
- `GET /v1/projects/:project_id/changes` — change summary from the snapshot.
|
|
100
|
-
- `PUT /v1/projects/:project_id` —
|
|
101
|
-
- `POST /v1/projects/:project_id/snapshot` —
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
memory
|
|
130
|
+
- `PUT /v1/projects/:project_id` — explicit local registration.
|
|
131
|
+
- `POST /v1/projects/:project_id/snapshot` — idempotent local ingestion.
|
|
132
|
+
- `POST /v1/projects/:project_id/ingest` — idempotent batches of documents, sessions, agents,
|
|
133
|
+
rollups, calls, and transcripts.
|
|
134
|
+
- `GET /v1/projects/:project_id/memory/tree` — document tree and metadata.
|
|
135
|
+
- `GET /v1/projects/:project_id/memory/document?path=...` — complete Markdown content.
|
|
136
|
+
- `GET /v1/projects/:project_id/memory/search?q=...` — path and body search.
|
|
137
|
+
- `GET /v1/projects/:project_id/sync` — mode, counts, conflicts, and latest event.
|
|
138
|
+
- `PUT /v1/projects/:project_id/sync` — compatibility configuration; SQL remains authoritative.
|
|
139
|
+
- `GET /v1/projects/:project_id/memory/export` — read-only export with complete content.
|
|
140
|
+
- `POST /v1/projects/:project_id/memory/events` — idempotent batch ingestion.
|
|
141
|
+
- `GET /v1/projects/:project_id/usage/summary` — filterable totals by period, change, session,
|
|
142
|
+
agent, provider, model, and role.
|
|
143
|
+
- `GET /v1/projects/:project_id/usage/breakdown` — agent, subagent, and model hierarchy.
|
|
144
|
+
- `GET /v1/projects/:project_id/usage/calls` — individual calls with prompt and response.
|
|
145
|
+
- `GET /v1/projects/:project_id/transcripts/:transcript_id` — compressed transcript validated by hash.
|
|
146
|
+
|
|
147
|
+
The `/v1` routes reject transported or expanded bodies above their limits and validate project,
|
|
148
|
+
path, revision, hash, idempotency, and isolation before writing to SQLite. Use `memory/export` for
|
|
149
|
+
a Markdown copy; it does not alter SQL authority.
|
|
@@ -4,23 +4,28 @@
|
|
|
4
4
|
|
|
5
5
|
## Objetivo
|
|
6
6
|
|
|
7
|
-
O Observer consolida a observabilidade de vários projetos WendKeep em um serviço local
|
|
8
|
-
|
|
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, chamadas e transcripts completos. O conteúdo fica disponível para navegação e busca
|
|
10
|
+
no próprio container, sem depender do Obsidian para consulta.
|
|
9
11
|
|
|
10
12
|
## Quando usar
|
|
11
13
|
|
|
12
|
-
Use para consultar changes, sessões,
|
|
13
|
-
|
|
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.
|
|
14
18
|
|
|
15
19
|
## Quando não usar
|
|
16
20
|
|
|
17
|
-
Não use o Observer para editar, concluir ou arquivar changes, curar memória,
|
|
18
|
-
|
|
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.
|
|
19
24
|
|
|
20
25
|
## Pré-requisitos
|
|
21
26
|
|
|
22
|
-
Tenha os projetos inicializados com WendKeep
|
|
23
|
-
|
|
27
|
+
Tenha os projetos inicializados com WendKeep e registre explicitamente cada projeto antes de
|
|
28
|
+
iniciar o servidor HTTP. No modo local padrão não há token para configurar.
|
|
24
29
|
|
|
25
30
|
## Sintaxe
|
|
26
31
|
|
|
@@ -28,6 +33,7 @@ token local antes de iniciar o servidor HTTP.
|
|
|
28
33
|
npx wendkeep observer status --data-dir <diretório> --json
|
|
29
34
|
npx wendkeep observer register --project <projeto> --vault <vault> --data-dir <diretório>
|
|
30
35
|
npx wendkeep observer publish --project <projeto> --vault <vault> --data-dir <diretório>
|
|
36
|
+
npx wendkeep observer memory import --project <projeto> --vault <vault> --url http://127.0.0.1:8787 --json
|
|
31
37
|
npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <diretório>
|
|
32
38
|
```
|
|
33
39
|
|
|
@@ -35,18 +41,17 @@ npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir <diretório>
|
|
|
35
41
|
|
|
36
42
|
- `--data-dir` escolhe o diretório local de eventos e índice; o padrão é
|
|
37
43
|
`WENDKEEP_OBSERVER_DATA_DIR` ou `~/.wendkeep-observer`.
|
|
38
|
-
- `--project` e `--vault` identificam o projeto
|
|
44
|
+
- `--project` e `--vault` identificam o projeto nos comandos `register`, `publish` e `memory import`.
|
|
39
45
|
- `--host` aceita somente `127.0.0.1`, `localhost` ou `::1`; outros hosts são recusados antes do
|
|
40
46
|
listen.
|
|
41
|
-
-
|
|
42
|
-
|
|
47
|
+
- as rotas `/v1` ficam abertas no modo local padrão; mantenha `--host 127.0.0.1` e não publique a
|
|
48
|
+
porta em um endereço de rede.
|
|
43
49
|
- Exit `0` indica sucesso; exit `1` indica falha de configuração ou operação; o hook publisher
|
|
44
50
|
também retorna `0` quando o Observer está indisponível.
|
|
45
51
|
|
|
46
52
|
## Exemplos
|
|
47
53
|
|
|
48
54
|
```powershell
|
|
49
|
-
$env:WENDKEEP_OBSERVER_TOKEN = '<token-local>'
|
|
50
55
|
npx wendkeep observer register --project C:\GitHub\WendKeep --vault C:\GitHub\WendKeep\.WendKeep-vault --data-dir C:\WendKeepObserver
|
|
51
56
|
npx wendkeep observer serve --host 127.0.0.1 --port 8787 --data-dir C:\WendKeepObserver
|
|
52
57
|
$env:WENDKEEP_OBSERVER_URL = 'http://127.0.0.1:8787'
|
|
@@ -55,31 +60,55 @@ $env:WENDKEEP_OBSERVER_URL = 'http://127.0.0.1:8787'
|
|
|
55
60
|
Para Docker local:
|
|
56
61
|
|
|
57
62
|
```powershell
|
|
58
|
-
$env:WENDKEEP_OBSERVER_TOKEN = '<token-local>'
|
|
59
63
|
docker compose -f docker/wendkeep-observer/compose.yaml up -d --build
|
|
60
64
|
```
|
|
61
65
|
|
|
62
|
-
##
|
|
66
|
+
## Painel web local
|
|
67
|
+
|
|
68
|
+
Com o servidor em execução, abra [http://127.0.0.1:8787/](http://127.0.0.1:8787/) no navegador.
|
|
69
|
+
O painel é servido pelo mesmo processo e abre diretamente, sem formulário ou token. A porta fica
|
|
70
|
+
presa ao loopback do computador; não coloque o endereço em uma interface de rede.
|
|
71
|
+
|
|
72
|
+
O painel mostra a lista multi-projeto, versão, saúde, sessão mais recente, change ativa, contagem
|
|
73
|
+
de changes e data da última captura. Ao abrir um projeto, o workspace oferece Overview, Consumo,
|
|
74
|
+
Sessões, Memória, Changes e Sincronização. A aba Consumo mostra custo total, tokens por categoria,
|
|
75
|
+
agentes principais, subagentes, provedores, modelos, tendência diária, cobertura histórica e
|
|
76
|
+
chamadas com prompt, resposta e transcript completo. Os estados de carregamento, vazio, servidor
|
|
77
|
+
indisponível, conflito, modelo sem tarifa e dados desatualizados ficam visíveis, e a atualização
|
|
78
|
+
pode ser manual ou automática a cada 15 segundos.
|
|
63
79
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
`EVENTS.jsonl` e `INDEX.json` no volume `observer-data`; não monta `C:\GitHub` nem qualquer
|
|
67
|
-
`.WendKeep-vault`.
|
|
80
|
+
Se o navegador mostrar a tela mas a lista falhar, confirme a saúde em
|
|
81
|
+
`http://127.0.0.1:8787/healthz` e verifique se o container está em execução.
|
|
68
82
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
83
|
+
## Resultado esperado
|
|
84
|
+
|
|
85
|
+
`register` grava `project_id`, nome, versão e data de registro. `publish` lê o vault local,
|
|
86
|
+
produz o snapshot e envia eventos idempotentes para o SQLite com o conteúdo integral das sessões,
|
|
87
|
+
decisões, bugs, aprendizados, specs, changes, CORE, DIGEST, SHARED_MEMORY, estado do brain,
|
|
88
|
+
sessões de agentes, rollups de custo, chamadas e transcripts. O container grava tudo em
|
|
89
|
+
`/data/observer.sqlite`; não monta `C:\GitHub` nem qualquer `.WendKeep-vault`. Markdown é aceito
|
|
90
|
+
somente como conteúdo de uma coluna SQL e volta a existir como arquivo apenas pela exportação
|
|
91
|
+
read-only sob demanda. `memory import` faz a carga inicial e retorna a paridade por arquivo e hash.
|
|
92
|
+
Na migração, o total de custo/token registrado no frontmatter é preservado por uma linha de
|
|
93
|
+
reconciliação quando o ledger detalhado não fecha com ele; essa linha não inventa chamadas.
|
|
94
|
+
Sessões históricas com o mesmo `session_id` recebem uma identidade canônica por arquivo para
|
|
95
|
+
evitar que um rollup sobrescreva o outro.
|
|
96
|
+
|
|
97
|
+
O `init` projeta `observer-publish` para `SessionStart`, `Stop` e `SubagentStop` depois dos hooks
|
|
98
|
+
principais. Sem servidor disponível, ele grava snapshots em `.brain/observer-outbox/` e eventos
|
|
99
|
+
SQL em `.brain/observer-sql-outbox/`, sem bloquear a sessão; uma execução posterior tenta
|
|
100
|
+
reenviar os lotes. Os lotes SQL são enviados com gzip para que transcripts completos maiores que
|
|
101
|
+
64 MB em JSON puro continuem dentro do limite do transporte; o Observer descomprime e valida o
|
|
102
|
+
corpo antes de ingerir. O outbox é transporte temporário, não autoridade.
|
|
73
103
|
|
|
74
104
|
## Erros comuns e diagnóstico
|
|
75
105
|
|
|
76
106
|
- `project_not_registered`: rode `observer register` antes de publicar.
|
|
77
|
-
- `unauthorized`: confira `Authorization: Bearer <token>` e `WENDKEEP_OBSERVER_TOKEN`.
|
|
78
107
|
- `host loopback`: troque `0.0.0.0` ou endereço LAN por `127.0.0.1`.
|
|
79
|
-
- Outbox pendente: o serviço estava indisponível; preserve `.brain/observer-outbox/` e
|
|
80
|
-
publisher. Não apague eventos manualmente.
|
|
81
|
-
-
|
|
82
|
-
|
|
108
|
+
- Outbox pendente: o serviço estava indisponível; preserve `.brain/observer-outbox/` e
|
|
109
|
+
`.brain/observer-sql-outbox/` e repita o publisher. Não apague eventos manualmente.
|
|
110
|
+
- Se a memória ou o consumo ficarem incompletos, verifique a tela Sincronização, preserve o
|
|
111
|
+
outbox e rode `observer memory import` para reconstruir a carga a partir do vault.
|
|
83
112
|
|
|
84
113
|
## Próximos passos
|
|
85
114
|
|
|
@@ -88,18 +117,34 @@ removido com `docker compose down -v` durante a operação normal, pois isso apa
|
|
|
88
117
|
|
|
89
118
|
## Autoridade dos dados
|
|
90
119
|
|
|
91
|
-
O
|
|
92
|
-
|
|
93
|
-
|
|
120
|
+
O SQLite do container é a memória canônica para consultas do Observer e guarda o conteúdo integral
|
|
121
|
+
publicado. O vault e qualquer `/data/memory` legado continuam preservados durante a migração como
|
|
122
|
+
cópia de transição e fonte de recuperação; os hooks não atualizam Markdown no container depois do
|
|
123
|
+
corte. As telas do Observer não concluem, arquivam, reparam ou promovem estado.
|
|
94
124
|
|
|
95
125
|
## API mínima
|
|
96
126
|
|
|
97
|
-
- `GET /healthz` — disponibilidade
|
|
98
|
-
- `GET /v1/projects` — projetos com snapshot
|
|
127
|
+
- `GET /healthz` — disponibilidade, versão das migrações SQLite e estado da migração legada.
|
|
128
|
+
- `GET /v1/projects` — projetos registrados no SQLite, com snapshot quando houver.
|
|
99
129
|
- `GET /v1/projects/:project_id` — último snapshot do projeto.
|
|
100
130
|
- `GET /v1/projects/:project_id/changes` — resumo das changes do snapshot.
|
|
101
|
-
- `PUT /v1/projects/:project_id` — registro explícito
|
|
102
|
-
- `POST /v1/projects/:project_id/snapshot` — ingestão
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
131
|
+
- `PUT /v1/projects/:project_id` — registro explícito local.
|
|
132
|
+
- `POST /v1/projects/:project_id/snapshot` — ingestão local idempotente.
|
|
133
|
+
- `POST /v1/projects/:project_id/ingest` — lote idempotente de documentos, sessões, agentes, rollups,
|
|
134
|
+
chamadas e transcripts.
|
|
135
|
+
- `GET /v1/projects/:project_id/memory/tree` — árvore e metadados dos documentos.
|
|
136
|
+
- `GET /v1/projects/:project_id/memory/document?path=...` — conteúdo Markdown integral.
|
|
137
|
+
- `GET /v1/projects/:project_id/memory/search?q=...` — busca no caminho e no corpo.
|
|
138
|
+
- `GET /v1/projects/:project_id/sync` — modo, contagem, conflitos e último evento.
|
|
139
|
+
- `PUT /v1/projects/:project_id/sync` — compatibilidade de configuração; a autoridade continua SQL.
|
|
140
|
+
- `GET /v1/projects/:project_id/memory/export` — exportação read-only com conteúdo completo.
|
|
141
|
+
- `POST /v1/projects/:project_id/memory/events` — ingestão idempotente em lote.
|
|
142
|
+
- `GET /v1/projects/:project_id/usage/summary` — totais filtráveis por período, change, sessão,
|
|
143
|
+
agente, provedor, modelo e papel.
|
|
144
|
+
- `GET /v1/projects/:project_id/usage/breakdown` — hierarquia de agentes, subagentes e modelos.
|
|
145
|
+
- `GET /v1/projects/:project_id/usage/calls` — chamadas individuais com prompt e resposta.
|
|
146
|
+
- `GET /v1/projects/:project_id/transcripts/:transcript_id` — transcript comprimido, validado por hash.
|
|
147
|
+
|
|
148
|
+
As rotas `/v1` rejeitam corpo transportado ou expandido acima do limite e validam projeto, caminho,
|
|
149
|
+
revisão, hash, idempotência e isolamento antes de gravar o conteúdo no SQLite. Para preservar uma
|
|
150
|
+
cópia Markdown, use a rota `memory/export`; ela não altera a autoridade SQL.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wendkeep",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.72.0",
|
|
4
4
|
"description": "Vault-first persistent memory for AI coding agents, with an optional profile-aware governance runtime: OFF, FLOW, GUIDE, GOVERN, or ASSURE. Local-first and agent-agnostic (Claude Code, Codex, Cursor…).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"workspaces": [
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"hooks",
|
|
31
31
|
"packages",
|
|
32
32
|
"schema",
|
|
33
|
+
"web/observer",
|
|
33
34
|
"docs/pt-BR/commands/*.md",
|
|
34
35
|
"docs/en/commands/*.md",
|
|
35
36
|
"README.md",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"node": ">=18"
|
|
41
42
|
},
|
|
42
43
|
"scripts": {
|
|
43
|
-
"check": "node --check scripts/release.mjs && node --check scripts/release-plan.mjs && node --check bin/wendkeep.mjs && node --check packages/cli/src/index.mjs && node --check src/init.mjs && node --check src/doctor.mjs && node --check src/project-vault.mjs && node --check src/observer-snapshot.mjs && node --check src/observer-store.mjs && node --check src/observer-server.mjs && node --check src/observer.mjs && node --check src/observer-publish.mjs && node --check src/operating-profile.mjs && node --check src/profile.mjs && node --check src/flow.mjs && node --check hooks/observer-publish.mjs && node --check hooks/operating-profile-runtime.mjs && node --check hooks/operating-profile-task-store.mjs && node --check hooks/flow-core.mjs && node --check hooks/flow-protected-policy.mjs && node --check hooks/git-snapshot.mjs && node --check hooks/vault-path-safety.mjs && node --check hooks/vault-runtime-store.mjs && node --check packages/harness/src/index.mjs && node --check packages/harness/src/flow-store.mjs && node --check packages/harness/src/operating-profile.mjs && node --check packages/harness/src/sensors-core.mjs && node --check packages/integrations/src/host-hooks.mjs && node --check packages/integrations/src/hook-envelope.mjs && node --check packages/integrations/src/prompt-content.mjs && node --check packages/integrations/src/transcript-usage.mjs && node --check packages/integrations/src/transcripts.mjs && node --check packages/integrations/src/session-identity.mjs && node --check packages/integrations/src/index.mjs && node --check packages/mcp/src/config.mjs && node --check packages/mcp/src/index.mjs && node --check packages/vault/src/index.mjs && node --check packages/vault/src/project-vault.mjs && node --check packages/vault/src/vault-path-safety.mjs && node --check packages/vault/src/locale.mjs && node --check packages/vault/src/memory-schema.mjs && node --check packages/vault/src/memory-mode.mjs && node --check packages/vault/src/memory-handoff.mjs && node --check packages/vault/src/memory-store.mjs && node --check packages/vault/src/validate-core.mjs && node --check packages/vault/src/validate-memory.mjs",
|
|
44
|
+
"check": "node --check scripts/release.mjs && node --check scripts/release-plan.mjs && node --check bin/wendkeep.mjs && node --check packages/cli/src/index.mjs && node --check src/init.mjs && node --check src/doctor.mjs && node --check src/project-vault.mjs && node --check src/observer-snapshot.mjs && node --check src/observer-store.mjs && node --check src/observer-memory.mjs && node --check src/observer-memory-publish.mjs && node --check src/observer-sql-store.mjs && node --check src/observer-sql-migrate.mjs && node --check src/observer-sql-publish.mjs && node --check src/observer-transcript-store.mjs && node --check src/observer-server.mjs && node --check src/observer.mjs && node --check src/observer-publish.mjs && node --check src/operating-profile.mjs && node --check src/profile.mjs && node --check src/flow.mjs && node --check web/observer/app.mjs && node --check hooks/observer-publish.mjs && node --check hooks/operating-profile-runtime.mjs && node --check hooks/operating-profile-task-store.mjs && node --check hooks/flow-core.mjs && node --check hooks/flow-protected-policy.mjs && node --check hooks/git-snapshot.mjs && node --check hooks/vault-path-safety.mjs && node --check hooks/vault-runtime-store.mjs && node --check packages/harness/src/index.mjs && node --check packages/harness/src/flow-store.mjs && node --check packages/harness/src/operating-profile.mjs && node --check packages/harness/src/sensors-core.mjs && node --check packages/integrations/src/host-hooks.mjs && node --check packages/integrations/src/hook-envelope.mjs && node --check packages/integrations/src/prompt-content.mjs && node --check packages/integrations/src/transcript-usage.mjs && node --check packages/integrations/src/transcripts.mjs && node --check packages/integrations/src/session-identity.mjs && node --check packages/integrations/src/index.mjs && node --check packages/mcp/src/config.mjs && node --check packages/mcp/src/index.mjs && node --check packages/vault/src/index.mjs && node --check packages/vault/src/project-vault.mjs && node --check packages/vault/src/vault-path-safety.mjs && node --check packages/vault/src/locale.mjs && node --check packages/vault/src/memory-schema.mjs && node --check packages/vault/src/memory-mode.mjs && node --check packages/vault/src/memory-handoff.mjs && node --check packages/vault/src/memory-store.mjs && node --check packages/vault/src/validate-core.mjs && node --check packages/vault/src/validate-memory.mjs",
|
|
44
45
|
"test": "node --test --test-concurrency=2",
|
|
45
46
|
"release": "node scripts/release.mjs",
|
|
46
47
|
"release:dry": "node scripts/release.mjs --dry-run",
|
|
@@ -24,6 +24,8 @@ export const SESSION_HOOKS = [
|
|
|
24
24
|
{ event: 'PostToolUse', matcher: 'AskUserQuestion', name: 'decision-capture', timeout: 15, statusMessage: 'wendkeep: recording decision' },
|
|
25
25
|
// Refresh subagent/workflow telemetry as each subagent finishes (resilient to a missed Stop).
|
|
26
26
|
{ event: 'SubagentStop', matcher: null, name: 'subagent-stop', timeout: 20, codex: true, statusMessage: 'wendkeep: subagent telemetry' },
|
|
27
|
+
// Publish the SQL observer projection after the subagent telemetry is settled.
|
|
28
|
+
{ event: 'SubagentStop', matcher: null, name: 'observer-publish', timeout: 5, order: 20, codex: true, statusMessage: 'wendkeep: publishing local observer usage' },
|
|
27
29
|
// Log plan/task progress into the active session note when a task is marked complete.
|
|
28
30
|
// codex: TaskCompleted is not in Codex's hook event enum.
|
|
29
31
|
{ event: 'TaskCompleted', matcher: null, name: 'task-log', timeout: 10, statusMessage: 'wendkeep: plan progress' },
|