jobkit-daemon is now an external git dependency with its own repo.
The local clone was only needed temporarily to fix a broken
Cargo.toml in the remote.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split poc-agent into lib + bin so its API client, types, and tool
dispatch can be imported by poc-memory. This is the foundation for
replacing claude CLI subprocess calls with direct API calls to
vllm/OpenAI-compatible endpoints.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Edition 2024 changes:
- gen is reserved: rename variable in query/engine.rs
- set_var is unsafe: wrap in unsafe block in cli/agent.rs
- match ergonomics: add explicit & in spectral.rs filter closure
New --local flag for `poc-memory agent run` bypasses the daemon and
runs the agent directly in-process. Useful for testing agent prompt
changes without waiting in the daemon queue.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace sort-based ranking with proper Elo system:
- Each agent TYPE has a persistent Elo rating (agent-elo.json)
- Each matchup: pick two random types, grab a recent action from
each, LLM compares, update ratings
- Ratings persist across daily evaluations — natural recency bias
from continuous updates against current opponents
- K=32 for fast adaptation to prompt changes
Usage: poc-memory agent evaluate --matchups 30 --model haiku
Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
Create jobkit-daemon crate with generic daemon infrastructure:
- event_log: JSONL append with size-based rotation
- socket: Unix domain socket RPC client and server with signal handling
- status: JSON status file read/write
Migrate daemon.rs to use the library:
- Worker pool setup via Daemon::new()
- Socket loop + signal handling via Daemon::run()
- RPC handlers as registered closures
- Logging, status writing, send_rpc all delegate to library
Migrate tui.rs to use socket::send_rpc() instead of inline UnixStream.
daemon.rs: 1952 → 1806 lines (-146), old status_socket_loop removed.
tui.rs: socket boilerplate removed.
Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
memory-search now records which nodes it finds via the daemon's
record-hits RPC endpoint. The daemon owns the redb database
exclusively, avoiding file locking between processes.
The rename agent reads hit counts to deprioritize nodes that are
actively being found by search — renaming them would break working
queries. Daily check decays counters by 10% so stale hits fade.
Also switched RPC command reading from fixed 256-byte buffer to
read_to_string for unbounded command sizes.
Per-agent-type tabs (health, replay, linker, separator, transfer,
apply, orphans, cap, digest, digest-links, knowledge) with dynamic
visibility — tabs only appear when tasks or log history exist.
Features:
- Overview tab: health gauges (α, gini, cc, episodic%), in-flight
tasks, and recent log entries
- Pipeline tab: table with phase ordering and status
- Per-agent tabs: active tasks, output logs, log history
- Log tab: auto-scrolling daemon.log tail
- Vim-style count prefix: e.g. 5r runs 5 iterations of the agent
- Flash messages for RPC feedback
- Tab/Shift-Tab navigation, number keys for tab selection
Also adds run-agent RPC to the daemon: accepts agent type and
iteration count, spawns chained tasks with LLM resource pool.
poc-memory status launches TUI when stdout is a terminal and daemon
is running, falls back to text output otherwise.
poc-daemon (notification routing, idle timer, IRC, Telegram) was already
fully self-contained with no imports from the poc-memory library. Now it's
a proper separate crate with its own Cargo.toml and capnp schema.
poc-memory retains the store, graph, search, neuro, knowledge, and the
jobkit-based memory maintenance daemon (daemon.rs).
Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
Replace manual arg parsing with clap derive for the full command set.
Single source of truth for command names, args, and help text.
Add notify_timeout (default 2min) — controls how long after last
response before notifications inject via tmux instead of waiting
for the hook. Separate from idle_timeout (5min) which controls
autonomous prompts.
Improve `poc-daemon status` to show both timers with elapsed/configured
and block reason, replacing the terse one-liner.
Add new Status fields over capnp: idleTimeout, notifyTimeout,
sinceActivity, sinceUser, blockReason.
ExecStart in poc-daemon.service now uses `daemon` subcommand.
Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
Move the notification daemon (IRC, Telegram, idle timer) and the
Claude Code hook binary into this repo as additional [[bin]] targets.
Single `cargo install --path .` now installs everything:
poc-memory — memory store CLI
memory-search — hook for memory retrieval
poc-daemon — notification/idle daemon (was claude-daemon)
poc-hook — Claude Code lifecycle hook (was claude-hook)
Renamed from claude-{daemon,hook} to poc-{daemon,hook} since the
infrastructure isn't tied to any specific AI assistant.
Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
Replace fragile cron+shell approach with `poc-memory daemon` — a single
long-running process using jobkit for worker pool, status tracking,
retry, cancellation, and resource pools.
Jobs:
- session-watcher: detects ended Claude sessions, triggers extraction
- scheduler: runs daily decay, consolidation, knowledge loop, digests
- health: periodic graph metrics check
- All Sonnet API calls serialized through a ResourcePool(1)
Status queryable via `poc-memory daemon status`, structured log via
`poc-memory daemon log`. Phase 1: shells out to existing subcommands.
Co-Authored-By: ProofOfConcept <poc@bcachefs.org>
Deleted iso_week_info() — dead code after week_dates() was rewritten.
Replaced remaining epoch_to_local/today/now_epoch calls with chrono
Local::now() and NaiveDate parsing. Month arg parsing now uses
NaiveDate instead of manual string splitting. Phase 3 month
comparison simplified to a single tuple comparison.
Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
Replace 130 lines of manual field-by-field capnp serialization with
two declarative macros:
capnp_enum! — generates to_capnp/from_capnp for enum types
capnp_message! — generates from_capnp/to_capnp for structs
Adding a field to the capnp schema now means adding it in one place;
both read and write directions are generated from the same declaration.
Eliminates: read_content_node, write_content_node, read_relation,
write_relation, read_provenance (5 functions → 2 macro invocations).
Callers updated to method syntax: Node::from_capnp() / node.to_capnp().
Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
- New spectral module: Laplacian eigendecomposition of the memory graph.
Commands: spectral, spectral-save, spectral-neighbors, spectral-positions,
spectral-suggest. Spectral neighbors expand search results beyond keyword
matching to structural proximity.
- Search: use StoreView trait to avoid 6MB state.bin rewrite on every query.
Append-only retrieval logging. Spectral expansion shows structurally
nearby nodes after text results.
- Fix panic in journal-tail: string truncation at byte 67 could land inside
a multi-byte character (em dash). Now walks back to char boundary.
- Replay queue: show classification and spectral outlier score.
- Knowledge agents: extractor, challenger, connector prompts and runner
scripts for automated graph enrichment.
- memory-search hook: stale state file cleanup (24h expiry).
Replace daily-digest.py, weekly-digest.py, monthly-digest.py with a
single digest.rs module. All three digest types now:
- Gather input directly from the Store (no subprocess calls)
- Build prompts in Rust (same templates as the Python versions)
- Call Sonnet via `claude -p --model sonnet`
- Import results back into the store automatically
- Extract links and save agent results
606 lines of Rust replaces 729 lines of Python + store_helpers.py
overhead. More importantly: this is now callable as a library from
poc-agent, and shares types/code with the rest of poc-memory.
Also adds `digest monthly [YYYY-MM]` subcommand (was Python-only).
Faster serialization/deserialization, smaller on disk (4.2MB vs 5.9MB).
Automatic migration from state.json on first load — reads the JSON,
writes state.bin, deletes the old file.
Added list-keys, list-edges, dump-json commands so Python scripts no
longer need to parse the cache directly. Updated bulk-categorize.py
and consolidation-loop.py to use the new CLI commands.