wendkeep 0.12.0 → 0.14.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 CHANGED
@@ -4,6 +4,28 @@ All notable changes to **wendkeep** are documented here. Format based on
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this project follows
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.14.0] — 2026-07-06
8
+
9
+ ### Changed
10
+ - **dotcontext is no longer a default companion.** wendkeep's native a2 loop (`change` /
11
+ `verify` / gate) recreates dotcontext's execution/gate role, so pinning it duplicates the
12
+ harness. The interactive / `--yes` default is now **`context-mode` only**; dotcontext stays
13
+ selectable via `--companions dotcontext` for anyone already invested.
14
+ - **README:** rewrote "Install & set up" with a clear **`init` options table** and a
15
+ per-companion breakdown; clarified that `--no-mcp` skips **only wendkeep's own** vault MCP
16
+ (companion MCPs still follow `--companions`).
17
+
18
+ ## [0.13.0] — 2026-07-06
19
+
20
+ Cost intelligence: waste + average.
21
+
22
+ ### Added
23
+ - **Wasted-spend tracking:** a killed/failed workflow run's subagent cost is now recorded per
24
+ session (`subagents_wasted_usd` + a line in the note's `## Subagents & Workflows`) and rolled
25
+ up by `wendkeep cost` (`desperdiçado (runs killed/failed): $X`). Money burned on aborted runs
26
+ was invisible before.
27
+ - **`wendkeep cost` per-session average** (`$/sessão`) alongside the vault total.
28
+
7
29
  ## [0.12.0] — 2026-07-06
8
30
 
9
31
  Deeper subagent/workflow telemetry.
@@ -261,6 +283,8 @@ Initial release — the capture engine, extracted from a system in daily product
261
283
  - `wendkeep init` (cross-platform installer) + optional `@bitbonsai/mcpvault` MCP server.
262
284
 
263
285
  <!-- Only v0.4.0+ is tagged in git (history starts here); older versions link to npm. -->
286
+ [0.14.0]: https://github.com/rogersialves/wendkeep/releases/tag/v0.14.0
287
+ [0.13.0]: https://github.com/rogersialves/wendkeep/releases/tag/v0.13.0
264
288
  [0.12.0]: https://github.com/rogersialves/wendkeep/releases/tag/v0.12.0
265
289
  [0.11.0]: https://github.com/rogersialves/wendkeep/releases/tag/v0.11.0
266
290
  [0.10.0]: https://github.com/rogersialves/wendkeep/releases/tag/v0.10.0
package/README.md CHANGED
@@ -39,20 +39,40 @@ npx wendkeep init
39
39
 
40
40
  1. Create the vault folder taxonomy and a templated `README.md` (default vault: `<project>/.<project-name>-vault`, e.g. `.MyApp-vault`; override with `--vault`).
41
41
  2. **Merge** the three session hooks and `OBSIDIAN_VAULT_PATH` into `.claude/settings.json` — without clobbering your existing settings (a `.bak` is saved; an unparseable file is left untouched and a `.new` is written for you to merge).
42
- 3. Add the `wendkeep-vault` MCP server to `.mcp.json` (skip with `--no-mcp`).
43
- 4. Offer to pin **companion** plugins/MCP (multi-choice; `context-mode` + `dotcontext` pre-checked). Each is wired through the most agent-agnostic path it supports — `context-mode` and `dotcontext` as `.mcp.json` MCP servers (any agent), `understand-anything` via a `understand-inject` SessionStart hook that injects its domain graph when generated, and the Claude Code plugin layer (`extraKnownMarketplaces` + `enabledPlugins`) as a bonus. **`dotcontext`** (execution/PREVC harness) also gets its lifecycle hooks wired (SessionStart-last + Stop + PostToolUse, pinned CLI) and a starter `.context/config/sensors.json` seeded with a `wendkeep validate-memory` sensor plus one per detected `package.json` script (test/typecheck/lint/build) — add the `.context/runtime|cache|logs|plans|agents|skills/` paths to `.gitignore` (wendkeep doesn't touch git). If dotcontext is already configured globally (`~/.claude.json`), the project MCP entry is **skipped automatically** to avoid a duplicate; tune with `--dotcontext-mcp <auto|project|none>` and `--dotcontext-hooks <full|light|none>` (light drops PostToolUse). Control selection with `--companions <csv>` or `--no-companions`. (`caveman` additionally runs its own cross-agent installer on non-Claude agents.)
42
+ 3. 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`.)
43
+ 4. Offer to pin **companion** plugins/MCP (multi-choice; only `context-mode` pre-checked). Each is wired the most agent-agnostic way it supports:
44
+ - **`context-mode`** — context optimizer + FTS5 memory, as a `.mcp.json` MCP server (any agent). The recommended default.
45
+ - **`understand-anything`** — project domain graph, via a `understand-inject` SessionStart hook that injects the graph when generated.
46
+ - **`caveman`** — token-compression mode; runs its own cross-agent installer on non-Claude agents.
47
+ - **`dotcontext`** — *legacy, not recommended.* wendkeep's native a2 loop (`change` / `verify` / gate) already does its job, so installing it **duplicates the harness**. Still selectable via `--companions dotcontext` for anyone already invested (tune with `--dotcontext-mcp` / `--dotcontext-hooks`), but off by default.
48
+
49
+ Control with `--companions <csv>` or `--no-companions`. The Claude Code plugin layer (`extraKnownMarketplaces` + `enabledPlugins`) is wired as a bonus where the companion has one.
44
50
  5. Install a **color system** into the vault's `.obsidian/`: a CSS snippet that accents notes by type (session/decision/bug/learning, via the `cssclasses` the hooks emit) plus graph color groups by folder. Non-destructive merge into `appearance.json`/`graph.json`; skip with `--no-colors`.
45
51
  6. Seed the **curated memory layer**: `.brain/CORE.md` (the hand-curated hot layer, with the 3 required sections) and `.brain/COMPACTION_PROTOCOL.md` (the protocol guide). The auto layers (`DIGEST.md`, `index.jsonl`) are generated by the hooks. Validate the curated layer with `wendkeep validate-memory` (cap 25 lines, 3 sections, no secrets/PII).
46
52
  7. Seed the **definitions + skills layer**: `.brain/agents/` + `.brain/skills/` (versioned source of truth), including the native process skills `wk-workflow` / `wk-tdd` / `wk-debugging` / `wk-brainstorming` / `wk-planning`. `init` runs `wendkeep sync-defs` for you, delivering them to `.codex/agents/` + `.claude/skills/` (re‑run `sync-defs` after editing `.brain`).
47
53
  8. Seed the **change/spec lifecycle**: the `07-Specs/` + `08-Mudanças/` folders and a native `wendkeep.sensors.json` (a `validate-memory` sensor plus one per detected `package.json` script). Drives `wendkeep change` / `wendkeep verify` — see **Change lifecycle** below.
48
54
 
49
55
  ```bash
50
- npx wendkeep init --vault "~/vaults/work" --project . --yes # non-interactive (companions: context-mode,dotcontext)
51
- npx wendkeep init --companions "context-mode,caveman" --yes
52
- npx wendkeep init --no-companions --yes
56
+ npx wendkeep init --vault "~/vaults/work" --project . --yes # non-interactive (default companion: context-mode)
57
+ npx wendkeep init --companions "context-mode,understand-anything" --yes
58
+ npx wendkeep init --no-companions --no-mcp --yes # zero companions, no wendkeep MCP
53
59
  ```
54
60
 
55
- Then open the vault in Obsidian, send a test prompt in your agent, and confirm a note appears under `02-Sessões/…`.
61
+ ### `init` options
62
+
63
+ | Flag | What it does |
64
+ |---|---|
65
+ | `--vault <path>` | Vault folder. Default `<project>/.<project-name>-vault`; interactive init asks. Point it at an existing vault to install into it. |
66
+ | `--project <path>` | Project root to wire (default: current directory). |
67
+ | `--locale <pt-BR\|en>` | Vault language — folder names, scaffold, skills. Interactive init asks; locked at init. |
68
+ | `--companions <csv>` | Companions to pin: `context-mode,caveman,understand-anything` (default: `context-mode`; `dotcontext` is legacy). |
69
+ | `--no-companions` | Pin no companions. |
70
+ | `--no-mcp` | Skip **wendkeep's own** vault MCP (`wendkeep-vault`). Companion MCPs still follow `--companions`. |
71
+ | `--no-colors` | Skip the Obsidian color system (`.obsidian` snippet + graph groups). |
72
+ | `--yes`, `-y` | Non-interactive; accept defaults (skips the language / vault / companion prompts). |
73
+ | `--force` | Overwrite existing wendkeep config blocks. |
74
+
75
+ Then open the vault in Obsidian, send a test prompt in your agent, and confirm a note appears under `02-Sessões/…` (or `02-Sessions/…` for an `en` vault).
56
76
 
57
77
  ## Updating
58
78
 
package/bin/wendkeep.mjs CHANGED
@@ -29,8 +29,8 @@ Usage:
29
29
  --vault <path> Obsidian vault folder (default: <project>/.<project-name>-vault).
30
30
  --project <path> Project root to wire (default: current directory).
31
31
  --no-mcp Do not add the mcpvault MCP server to .mcp.json.
32
- --companions <csv> Companion plugins/MCP to pin: context-mode,dotcontext,caveman,understand-anything
33
- (default when interactive/--yes: context-mode,dotcontext).
32
+ --companions <csv> Companion plugins/MCP to pin: context-mode,caveman,understand-anything
33
+ (default: context-mode). dotcontext is legacy — the native a2 loop replaces it.
34
34
  --no-companions Skip companion plugins/MCP entirely.
35
35
  --no-colors Skip the Obsidian color system (.obsidian snippet + graph groups).
36
36
  --dotcontext-mcp <v> dotcontext MCP placement: auto (default; skip project entry
@@ -143,10 +143,15 @@ export function collectSubagentUsage(sessionDir) {
143
143
  };
144
144
  });
145
145
 
146
+ // Wasted spend: cost of workflow runs that did not complete (killed/failed/…). The
147
+ // subagents that ran before the kill still cost money — this makes that visible.
148
+ const WASTE = /^(killed|failed|error|aborted|cancel(l)?ed)$/i;
149
+ const wasted = round4(workflows.filter((w) => WASTE.test(w.status)).reduce((s, w) => s + w.cost, 0));
150
+
146
151
  return {
147
152
  subagents,
148
153
  workflows,
149
- aggregate: { count, calls, tokens: tokensTotal(usageAgg), cost: round4(cost), usage: usageAgg, tools: [...allTools] },
154
+ aggregate: { count, calls, tokens: tokensTotal(usageAgg), cost: round4(cost), wasted, usage: usageAgg, tools: [...allTools] },
150
155
  };
151
156
  }
152
157
 
@@ -167,13 +172,14 @@ export function renderSubagentSection(c) {
167
172
  const rows = c.subagents
168
173
  .map((s) => `| ${s.id} | ${s.agentType || '-'} | ${s.workflow || '-'} | ${s.model} | ${s.tools} | ${fmt(s.tokens)} | ${usd(s.cost)} |`)
169
174
  .join('\n');
175
+ const wasteLine = a.wasted ? `\n- **Desperdiçado (runs killed/failed):** ${usd(a.wasted)}` : '';
170
176
  return `## Subagents & Workflows
171
177
 
172
178
  > Custo de subagents/workflows desta sessão — NÃO incluído no total principal acima.
173
179
 
174
180
  - **Subagents:** ${a.count} · ${a.calls} chamadas · ${fmt(a.tokens)} tokens · ${usd(a.cost)}
175
181
  - **Workflows:** ${wf}
176
- - **Tools (subagents):** ${tools}
182
+ - **Tools (subagents):** ${tools}${wasteLine}
177
183
 
178
184
  <details><summary>Por subagent (${a.count})</summary>
179
185
 
@@ -220,6 +226,7 @@ export function upsertSubagentUsage(sessionPath, transcriptPath) {
220
226
  content = setFrontmatterField(content, 'subagents_tokens_total', a.tokens);
221
227
  content = setFrontmatterField(content, 'subagents_custo_usd', a.cost);
222
228
  content = setFrontmatterField(content, 'subagents_tools', `"${(a.tools || []).join(', ')}"`);
229
+ content = setFrontmatterField(content, 'subagents_wasted_usd', a.wasted || 0);
223
230
  content = setFrontmatterField(content, 'tokens_total_incl_subagents', frontmatterNumber(content, 'tokens_total') + a.tokens);
224
231
  content = upsertSection(content, '## Subagents & Workflows', renderSubagentSection(collected));
225
232
  writeFileSync(sessionPath, content, 'utf8');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wendkeep",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "description": "A persistent-memory harness for AI coding agents on your Obsidian vault: turn-by-turn session capture plus a native, zero-dependency spec→change→verify→archive loop (sensor-gated, independent verdict, mutation discrimination). Local-first, agent-agnostic (Claude Code, Codex, Cursor…).",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cost.mjs CHANGED
@@ -21,6 +21,7 @@ export function parseSessionCost(content) {
21
21
  model: fmValue(content, 'custo_modelo_label') || fmValue(content, 'modelo') || '?',
22
22
  mainCost: Number(fmValue(content, 'custo_modelo_usd')) || 0,
23
23
  subCost: Number(fmValue(content, 'subagents_custo_usd')) || 0,
24
+ wasted: Number(fmValue(content, 'subagents_wasted_usd')) || 0,
24
25
  tokens: Number(fmValue(content, 'tokens_total')) || 0,
25
26
  subTokens: Number(fmValue(content, 'subagents_tokens_total')) || 0,
26
27
  };
@@ -31,19 +32,22 @@ export function aggregateCosts(entries) {
31
32
  const byModel = {};
32
33
  let main = 0;
33
34
  let sub = 0;
35
+ let wasted = 0;
34
36
  let tokens = 0;
35
37
  let subTokens = 0;
36
38
  for (const e of entries) {
37
- main += e.mainCost; sub += e.subCost; tokens += e.tokens; subTokens += e.subTokens;
39
+ main += e.mainCost; sub += e.subCost; wasted += e.wasted || 0; tokens += e.tokens; subTokens += e.subTokens;
38
40
  const d = e.date || '?';
39
41
  (byDay[d] = byDay[d] || { cost: 0, count: 0 }).cost += e.mainCost + e.subCost;
40
42
  byDay[d].count += 1;
41
43
  (byModel[e.model] = byModel[e.model] || { cost: 0, count: 0 }).cost += e.mainCost + e.subCost;
42
44
  byModel[e.model].count += 1;
43
45
  }
46
+ const total = main + sub;
44
47
  return {
45
48
  count: entries.length,
46
- main: round4(main), sub: round4(sub), total: round4(main + sub),
49
+ main: round4(main), sub: round4(sub), total: round4(total), wasted: round4(wasted),
50
+ avg: round4(entries.length ? total / entries.length : 0),
47
51
  tokens, subTokens,
48
52
  byDay: Object.entries(byDay).sort().map(([date, v]) => ({ date, cost: round4(v.cost), count: v.count })),
49
53
  byModel: Object.entries(byModel).sort((a, b) => b[1].cost - a[1].cost).map(([model, v]) => ({ model, cost: round4(v.cost), count: v.count })),
@@ -93,8 +97,9 @@ export function runCost(argv) {
93
97
 
94
98
  if (argv.includes('--json')) { process.stdout.write(`${JSON.stringify(agg, null, 2)}\n`); process.exit(0); }
95
99
 
96
- process.stdout.write(`Custo total (vault): ${usd(agg.total)} — ${agg.count} sessão(ões)\n`);
100
+ process.stdout.write(`Custo total (vault): ${usd(agg.total)} — ${agg.count} sessão(ões) · ${usd(agg.avg)}/sessão\n`);
97
101
  process.stdout.write(` main: ${usd(agg.main)} · subagents: ${usd(agg.sub)}\n`);
102
+ if (agg.wasted) process.stdout.write(` desperdiçado (runs killed/failed): ${usd(agg.wasted)}\n`);
98
103
  if (agg.byModel.length) {
99
104
  process.stdout.write('\nPor modelo:\n');
100
105
  for (const m of agg.byModel) process.stdout.write(` ${m.model.padEnd(20)} ${usd(m.cost)} (${m.count})\n`);
package/src/taxonomy.mjs CHANGED
@@ -124,8 +124,11 @@ export const COMPANIONS = [
124
124
  },
125
125
  {
126
126
  id: 'dotcontext',
127
- label: 'dotcontext orquestração de execução (PREVC + sensores + gate E→V)',
128
- default: true,
127
+ // Legacy: wendkeep's native a2 loop (change/verify/gate) recreates dotcontext's role,
128
+ // so it is no longer recommended — installing it would duplicate the native harness.
129
+ // Kept selectable for anyone already invested in it; not a default.
130
+ label: 'dotcontext — legado (o loop a2 nativo do wendkeep substitui; não recomendado)',
131
+ default: false,
129
132
  // MCP-only (no Claude Code plugin). Agent-agnostic server, @latest surface.
130
133
  mcp: { key: 'dotcontext', entry: { type: 'stdio', command: 'npx', args: ['-y', '@dotcontext/mcp@latest'], env: {} } },
131
134
  // Lifecycle hooks via the pinned CLI; wired by wendkeep (single writer).