@inetafrica/open-claudia 2.6.57 → 2.6.59

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
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v2.6.58
4
+ - **Tiered recall gate — stop paying 15 seconds for "thanks".** Measured over 700+ live turns, the old discoverer pre-gate returned true whenever *any* seed matched, so it gated just 0.4% of turns — a bare "ok" with an incidental keyword hit still paid the full seed → graph → walker pass (p50 ~15s). A new `recallTier()` classifies each turn into three tiers: **skip** (pleasantries/acks up to 4 words *regardless of seeds*, emoji-only, or ≤2 words with no seeds — no recall at all), **seeds** (short command-like turns ≤4 words — user-origin keyword seeds inject directly with no graph expansion, no walker, no excerpts; the classic-engine baseline at ~ms cost), and **full** (substantive turns — the whole pipeline). The tier is logged per turn and the metrics summary now tracks the seeds-only share alongside the gated share.
5
+ - **Walker candidate cap.** The latency deep-dive showed the walk itself dominates, not process spawn: 15–40 candidates × 600-char excerpts = 10–25KB prompts to the haiku judge on every substantive turn. Full-tier candidates are now priority-ordered — user-origin seeds by match score, then context seeds, then graph-activated nodes by activation — and capped at `RECALL_WALKER_MAX_CANDIDATES` (default 14), so the judge reads the strongest few instead of everything the graph touched.
6
+ - **Episodic memory — recall now remembers how it did things last time.** The discoverer gains a transcript hop: on full-tier turns it queries the project-transcript FTS index (up to `RECALL_EPISODE_LIMIT`, default 3; `RECALL_EPISODES=off` disables) and offers the hits to the walker as `episode:` candidates with their matched snippets. The walker keeps one only if that past exchange holds a decision, method, or outcome directly reusable for the current message — and the fail-open path (walker off/failed) *drops* episodes rather than injecting unjudged snippets. Kept episodes render as a "Past work that looks related" block with the snippet plus a ready-to-run `open-claudia transcript-search … --all` pointer for the full context, and surface in the `/recall` banner as 📓 lines.
7
+ - **Real cost + phase telemetry for recall.** The warm walker's stream-json `total_cost_usd` is cumulative per session; it now tracks the running total and reports the per-walk *delta*, which flows into `recall-metrics.jsonl` per turn (`costUsd`) instead of the flat 0 logged before. Each turn also records `seedMs` / `expandMs` / `walkerMs` and which walker path ran (`warm`/`cold`/`off`/`failed`), so the p50 can be decomposed instead of guessed at.
8
+ - **Weak-use signal from the post-turn reviewer.** Precision metrics only counted explicit 📖 opens as "used". Now, when the reviewer decides a turn's work updated pack X or entity Y, that adjudication is logged as use (`source: "reviewer"`) and co-updated nodes get a Hebbian co-work reinforcement — so packs that quietly shape work without being re-opened stop looking like noise.
9
+ - **Journal dedupe.** The reviewer could append near-identical Journal lines turn after turn (observed: 28 same-day duplicates on one busy pack). `updatePack` now token-Jaccard-compares a new journal line (dates stripped) against the last 5 entries and skips appends at ≥0.75 similarity, flagging `journalDeduped` instead. Adds `test-journal-dedupe.js`.
10
+
3
11
  ## v2.6.57
4
12
  - **Move the inactivity watchdog into the live runner.** Deep review found v2.6.56 put the watchdog in the legacy `bot-agent.js` monolith, but the LaunchAgent runs `bot.js`, which delegates heavy turns through `core/runner.js`. That meant the installed live path still only had the 6-hour hard timeout and could still wedge on a silent child. This release ports the watchdog to `core/runner.js`, updates activity on child stdout/stderr, terminates the process tree after `OC_TURN_IDLE_MS` of silence, suppresses the confusing partial/no-output final message, clears stuck busy state with a failsafe, and drains any queued follow-up messages instead of stranding them. Adds a static regression test that fails if the watchdog only exists in `bot-agent.js` again.
5
13
 
package/README.md CHANGED
@@ -267,7 +267,7 @@ Open Claudia layers three memory systems on top of the backend's native sessions
267
267
 
268
268
  **Recall engines** — how packs and entities get matched and surfaced is pluggable per chat via `/engine` (or the `RECALL_ENGINE` env default). **classic** (the default) is keyword FTS plus a relevance judge with headline injection — stable and unchanged. **discoverer** (opt-in) adds a typed-edge graph over the same corpus (`parent`/`governed-by`/`related` edges with weights in `recall-graph.db`) and runs: a pre-gate that skips recall on trivial turns → FTS seeding → spreading activation across the graph (1–2 hops — auto-pulls cross-cutting concerns the query never named) → a walker that reads each candidate and returns the genuinely-relevant set with one-line why-bullets (fail-open to keyword seeds, so it never recalls worse than classic). Edges form structurally from pack `parent` frontmatter and `[[links]]`, and strengthen via Hebbian co-use when the agent opens packs together (📖); weights decay over time. Inspect with `open-claudia recall-stats` and `open-claudia recall graph [--sync]`, or flip on `/recall` to watch — per turn — which packs/entities surfaced and why, right in the chat. Switch back any time with `/engine classic`.
269
269
 
270
- **Dream consolidation** — while the per-turn reviewer takes quick notes, *dream* is the slow overnight pass (default 4am, on a high-tier model — opus by default, set `DREAM_TIER` or `DREAM_MODEL`): it merges packs that drifted into the same topic, builds parent/sub pack trees with umbrella summaries, tightens descriptions and tags so the router matches with less noise, dedupes entities, cross-links notes, and tends the recall graph (structural sync, weight decay, orphan prune). Anything merged away is backed up under `~/.open-claudia/backup/dream-<stamp>/` first, and every dream that changes something reports in chat. Configure with `DREAM_CRON` / `DREAM_MODEL`, disable with `DREAM=off`.
270
+ **Dream consolidation** — while the per-turn reviewer takes quick notes, *dream* is the slow overnight pass (default 4am, on a high-tier model — opus by default, set `DREAM_TIER` or `DREAM_MODEL`): it merges packs that drifted into the same topic, builds parent/sub pack trees with umbrella summaries, tightens descriptions and tags so the router matches with less noise, dedupes entities, cross-links notes, and tends the recall graph (structural sync, weight decay, orphan prune). The pass is *evidence-grounded*: per-turn recall telemetry (what surfaced, what got kept, what the agent actually opened) feeds the prompt, so archive/merge calls rest on usage numbers rather than vibes. Most nights run as cheap *deltas* — full pack bodies only for what changed since the last dream plus graph neighbours and pre-computed merge candidates; a full-corpus sweep runs every `DREAM_FULL_SWEEP_DAYS` (30). Deterministic phases run even if the model call fails: journal backfill dedupe, weakening of graph nodes that keep arriving but never get kept, co-rescue edge reinforcement, episodic index tending, and a memory-health report (rescue rate, noise, latency, spend) in the morning chat summary. Dream may also tune one bounded recall knob per night (`recall-tuning.json`) — every change is checked against the next window's health and auto-rolled-back if rescue drops or noise rises; env pins always win. Anything merged away is backed up under `~/.open-claudia/backup/dream-<stamp>/` first, and every dream that changes something reports in chat. Configure with `DREAM_CRON` / `DREAM_MODEL`, disable with `DREAM=off`.
271
271
 
272
272
  **Personality** — your `soul.md` holds identity and hard rules; `~/.open-claudia/persona.md` holds the voice on top — tone, quirks, emoji habits. It feeds into the system prompt and the dream pass may evolve it gently (bounded, backed up, announced). Edit it directly any time.
273
273
 
@@ -279,6 +279,7 @@ open-claudia entity list|show <slug>|match "<text>"|note <name> "<text>"|remove
279
279
  open-claudia dream [--dry-run] # run the consolidation pass now
280
280
  open-claudia recall-stats # discoverer-engine metrics summary
281
281
  open-claudia recall graph [--sync] # recall-graph node/edge stats; --sync rebuilds structural edges
282
+ open-claudia kpi [--json|--html|--knobs] # harness KPIs by version+model; --html writes a chart report, --knobs shows dream-tuned knob state
282
283
  open-claudia transcript-search "<query>" # alias: ts; --all for every project
283
284
  open-claudia transcript-window "<pattern>" # alias: tw; hits with surrounding turns
284
285
  ```
@@ -436,6 +437,11 @@ All stored in `~/.open-claudia/`:
436
437
  | `MEMORY_RECALL_MAX_CHARS` | No | Hard cap for auto-injected pack/entity memory per turn (default `9000`, `off` disables auto recall injection) |
437
438
  | `RECALL_ENGINE` | No | Default recall engine when a chat hasn't set one via `/engine` (`classic` or `discoverer`, default `classic`) |
438
439
  | `RECALL_GRAPH_DB` / `RECALL_METRICS` | No | Override the discoverer graph DB path; `off` on metrics disables per-turn recall logging |
440
+ | `RECALL_WALKER_MAX_CANDIDATES` | No | Cap on candidates sent to the discoverer's walker judge per turn (default `14`; dream-tunable 8–20, env pins it) |
441
+ | `RECALL_EPISODES` / `RECALL_EPISODE_LIMIT` | No | `off` disables episodic transcript candidates in recall; limit caps transcript hits per turn (default `3`; dream-tunable 1–5) |
442
+ | `RECALL_SEEDS_TIER_MAX_WORDS` | No | Turns at or under this word count take the fast seeds-only recall path (default `4`; dream-tunable 2–6) |
443
+ | `RECALL_DECAY_HALF_LIFE_DAYS` | No | Half-life for recall-graph edge decay during dream tending (default `60`; dream-tunable 10–90) |
444
+ | `RECALL_CASCADE` / `RECALL_CASCADE_SHADOW_RATE` | No | `off` disables the deterministic keep/drop cascade before the walker judge; shadow rate is the fraction of cascade verdicts also judged to audit agreement (default `0.1`) |
439
445
  | `PROJECT_TRANSCRIPTS` | No | Enable redacted project transcripts (default `true`) |
440
446
  | `TRANSCRIPT_MAX_ENTRY_CHARS` | No | Max chars per transcript entry (default `12000`) |
441
447
  | `TRANSCRIPTS_DIR` / `PACKS_DIR` / `ENTITIES_DIR` | No | Override storage directories |
@@ -446,6 +452,7 @@ All stored in `~/.open-claudia/`:
446
452
  | `DREAM_CRON` | No | Schedule for the dream pass (default `0 4 * * *`) |
447
453
  | `DREAM_MODEL` | No | Explicit model override for the dream pass (otherwise picked from `DREAM_TIER`) |
448
454
  | `DREAM_TIER` | No | Model tier for the dream pass: `low` (haiku) / `medium` (sonnet) / `high` (opus, default) |
455
+ | `DREAM_FULL_SWEEP_DAYS` | No | Days between full-corpus dream sweeps; other nights are cheap deltas over recently-touched packs (default `30`) |
449
456
  | `PERSONA_FILE` | No | Override the persona file location |
450
457
  | `WEB_UI` / `WEB_PORT` / `WEB_PASSWORD` | No | Web UI toggle, port, and password |
451
458
  | `WHISPER_CLI` / `WHISPER_MODEL` | No | whisper.cpp binary and model for voice notes |
package/bin/cli.js CHANGED
@@ -318,6 +318,10 @@ switch (command) {
318
318
  require("./recall").run(["stats", ...args.slice(1)]);
319
319
  break;
320
320
  }
321
+ case "kpi": {
322
+ require("./kpi").run(args.slice(1));
323
+ break;
324
+ }
321
325
  case "recall": {
322
326
  require("./recall").run(args.slice(1));
323
327
  break;
package/bin/kpi.js ADDED
@@ -0,0 +1,55 @@
1
+ // open-claudia kpi [--json] [--html [--out <path>]] [--knobs]
2
+ //
3
+ // Compare harness performance across versions and models: rescue rate, noise,
4
+ // latency by tier, cost/turn, cascade + walker health — aggregated from the
5
+ // version-stamped recall telemetry, plus the nightly dream KPI snapshots.
6
+
7
+ const path = require("path");
8
+
9
+ const HELP = `
10
+ Harness KPIs by version.
11
+
12
+ open-claudia kpi Version-vs-version table
13
+ open-claudia kpi --json Raw aggregates
14
+ open-claudia kpi --html Write a self-contained HTML report (charts), print its path
15
+ open-claudia kpi --html --out p Write the report to a specific path
16
+ open-claudia kpi --knobs Current recall-knob values + dream tuning history
17
+
18
+ Data sources: recall-metrics.jsonl (per-turn, version+model stamped) and
19
+ recall-kpi.jsonl (one snapshot per dream night).
20
+ `;
21
+
22
+ function run(args) {
23
+ if (args.includes("--help") || args[0] === "help") { console.log(HELP); return; }
24
+ const kpi = require(path.join(__dirname, "..", "core", "recall", "kpi"));
25
+
26
+ if (args.includes("--knobs")) {
27
+ const tuning = require(path.join(__dirname, "..", "core", "recall", "tuning"));
28
+ console.log("Recall knobs (env pin > dream tuning > default)");
29
+ console.log("───────────────────────────────────────────────");
30
+ for (const k of tuning.knobTable()) {
31
+ console.log(`${k.name.padEnd(22)} ${String(k.current).padEnd(6)}${k.pinned ? " [pinned by env]" : k.current !== k.default ? " [dream-tuned]" : ""}`);
32
+ }
33
+ const hist = tuning.history();
34
+ if (hist.length) {
35
+ console.log("\nTuning history");
36
+ for (const h of hist.slice(-10)) console.log(` ${h.ts.slice(0, 10)} ${h.knob}: ${h.from} → ${h.to} — ${h.reason}`);
37
+ }
38
+ return;
39
+ }
40
+
41
+ if (args.includes("--html")) {
42
+ const i = args.indexOf("--out");
43
+ const out = i !== -1 ? args[i + 1] : undefined;
44
+ console.log(kpi.writeHtmlReport(out));
45
+ return;
46
+ }
47
+
48
+ const rows = kpi.aggregate();
49
+ if (args.includes("--json")) { console.log(JSON.stringify({ versions: rows, snapshots: kpi.trend() }, null, 2)); return; }
50
+ console.log(kpi.renderTable(rows));
51
+ const snaps = kpi.trend();
52
+ if (snaps.length) console.log(`\n${snaps.length} nightly snapshot(s) in recall-kpi.jsonl — \`open-claudia kpi --html\` for charts.`);
53
+ }
54
+
55
+ module.exports = { run, HELP };