Commit graph

928 commits

Author SHA1 Message Date
Kent Overstreet
603d58e686 Fix Thinking/Log panics: skip entries with empty token_ids
Entries with empty token_ids (Thinking, Log) are not part of the
prompt and don't have messages. Skip them in streaming_index(),
route_entry(), and sync_from_agent() instead of calling .message()
which panics.

Using token_ids.is_empty() as the guard in streaming_index means
the check is tied to the data, not the type — any entry that
doesn't produce tokens is safely skipped.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 12:05:49 -04:00
Kent Overstreet
cb64cdf5fe Init tokenizer in consciousness binary main
The consciousness binary has its own main() separate from poc-memory.
Agent::new() creates ContextEntries which need the tokenizer, so it
must be initialized before Mind::new().

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 11:55:32 -04:00
Kent Overstreet
f458af6dec Add /v1/completions streaming path with raw token IDs
New stream_completions() in openai.rs sends prompt as token IDs to
the completions endpoint instead of JSON messages to chat/completions.
Handles <think> tags in the response (split into Reasoning events)
and stops on <|im_end|> token.

start_stream_completions() on ApiClient provides the same interface
as start_stream() but takes token IDs instead of Messages.

The turn loop in Agent::turn() uses completions when the tokenizer
is initialized, falling back to the chat API otherwise. This allows
gradual migration — consciousness uses completions (Qwen tokenizer),
Claude Code hook still uses chat API (Anthropic).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 11:42:22 -04:00
Kent Overstreet
e9765799c4 Move tool definitions into ContextState as system entries
Tool definitions are now pushed as a ContextEntry in the system
section at Agent construction time, formatted in the Qwen chat
template style. They're tokenized, scored, and treated like any
other context entry.

assemble_prompt_tokens() no longer takes a tools parameter —
tools are already in the context. This prepares for the switch
to /v1/completions where tools aren't a separate API field.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 11:36:33 -04:00
Kent Overstreet
67e3228c32 Kill tiktoken — all token counting now uses Qwen 3.5 tokenizer
Remove tiktoken-rs dependency, CoreBPE field on Agent, and the
msg_token_count() function. All tokenization now goes through the
global HuggingFace tokenizer in agent/tokenizer.rs.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 11:25:28 -04:00
Kent Overstreet
5e4067c04f Replace token counting with token generation via HuggingFace tokenizer
Add agent/tokenizer.rs with global Qwen 3.5 tokenizer that generates
actual token IDs including chat template wrapping. ContextEntry now
stores token_ids: Vec<u32> instead of tokens: usize — the count is
derived from the length.

ContextEntry::new() tokenizes automatically via the global tokenizer.
ContextSection::push_entry() takes a raw ConversationEntry and
tokenizes it. set_message() re-tokenizes without needing an external
tokenizer parameter.

Token IDs include the full chat template: <|im_start|>role\ncontent
<|im_end|>\n — so concatenating token_ids across entries produces a
ready-to-send prompt for vLLM's /v1/completions endpoint.

The old tiktoken CoreBPE is now unused on Agent (will be removed in
a followup). Token counts are now exact for Qwen 3.5 instead of the
~85-90% approximation from cl100k_base.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 11:20:03 -04:00
Kent Overstreet
70ee7abea5 Fix restore_from_log panic on Thinking entries, fix bail nullglob
restore_from_log called .message() on all entries including Thinking
entries, which panic. Filter them out alongside Log entries.

Also fix bail-no-competing.sh: without nullglob, when no pid-* files
exist the glob stays literal and always triggers a false bail.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 10:39:07 -04:00
Kent Overstreet
06176201da Fix bail script: pass own pid file so it can exclude itself
The bail-no-competing.sh script expects $1 to be the path to the
current agent's pid file so it can skip it when checking for
competing processes. But the runner wasn't passing any arguments,
so $1 was empty and the script treated every pid file (including
the agent's own) as a competing process — bailing every time.

This caused surface-observe to always bail at step 2, preventing
all memory graph maintenance (organize, observe phases) from
running.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 09:35:52 -04:00
Kent Overstreet
6ce3f78e0a Fix stale pid reaper: check /proc/pid/cmdline to detect PID reuse
The reaper checks if agent PIDs are alive via kill(pid, 0), but if
the PID was reused by an unrelated process, the check succeeds and
the stale pid file blocks the agent from re-launching indefinitely.

Fix: read /proc/pid/cmdline and verify the process is actually a
claude/poc-memory process. If not, remove the pid file.

This caused memory surfacing to stop working for the entire April 7
session — a dead surface-observe process's PID was reused, blocking
all subsequent surfacing attempts with "already running".

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-08 09:18:21 -04:00
Kent Overstreet
7ecc50d2e4 Capture reasoning/thinking from API stream into Thinking entries
StreamResult now includes accumulated reasoning text. After each
stream completes, if reasoning was produced, a Thinking entry is
pushed to the conversation before the response message.

Reasoning content is visible in the context tree UI but not sent
back to the API and doesn't count against the token budget.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 22:49:35 -04:00
Kent Overstreet
e0ee441aec Add ConversationEntry::Thinking — 0 tokens, not sent to API
Thinking/reasoning content is now a first-class entry type:
- Serialized as {"thinking": "..."} in conversation log
- 0 tokens for budgeting (doesn't count against context window)
- Filtered from assemble_api_messages (not sent back to model)
- Displayed in UI with "thinking: ..." label and expandable content

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 22:46:06 -04:00
Kent Overstreet
7c5fddcb19 Fix input blocked during scoring: release agent lock before disk write
The scoring callback was holding the agent lock while doing a
synchronous file write (save_memory_scores). This blocked the event
loop from acquiring the lock to process user input.

Fix: collect the scores snapshot while holding the lock, drop the
lock, then write to disk.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 22:32:10 -04:00
Kent Overstreet
1be16b9f7b Move memory scores to status column for consistent alignment
Individual memory nodes now show their score in the status column
after the token count, not embedded in the name. Unscored memories
have an empty status column.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 22:28:14 -04:00
Kent Overstreet
c7c69a8f06 Add status column to context tree with tab-stop alignment
SectionView gains a status field for extra info displayed after the
token count column. Memory nodes section shows "N scored, M unscored"
in the status column instead of burying it in the title.

Renderer uses fixed-width columns (40 name, 16 tokens, status) for
consistent alignment across sections.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 22:13:27 -04:00
Kent Overstreet
07b400c95c Restore context tree display with SectionView UI type
Introduced SectionView {name, tokens, content, children} as a
UI-only tree node, separate from the data ContextSection. The widget
SectionTree renders SectionView with the old recursive expand/collapse
behavior — children for sub-sections, content for text expansion.

section_to_view() converts data sections to UI views, using
ConversationEntry::label() for names and content_text() for
expandable content.

read_context_views() builds the same tree the old context_state_summary
did: System, Identity, Journal, Memory nodes (scored/unscored counts,
expandable to show content), Conversation entries.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 22:06:10 -04:00
Kent Overstreet
613704720b Score memories in first 60% of conversation by tokens
Use cumulative token position instead of entry index for the scoring
cutoff. This reflects actual context usage — a few large entries
near the end won't skew the boundary.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2026-04-07 21:43:59 -04:00
Kent Overstreet
fd58386951 Incremental memory scoring with per-score persistence
score_memories_incremental now takes an async callback that fires
after each memory is scored. The callback:
- Writes the score to the conversation entry via set_score()
- Persists to memory-scores.json immediately
- Notifies the UI so the context screen updates live

Scoring no longer batches — each score is visible and persisted
as it completes. Does not touch the memory store.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 21:34:14 -04:00
Kent Overstreet
e213644514 Fix: only evict scored memories, not unscored
lowest_scored_memory() now skips memories with score=None. Unscored
memories haven't been evaluated — dropping them before scored
low-value ones loses potentially important context.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 21:06:45 -04:00
Kent Overstreet
a20f3e3642 Restore entry labels in context tree: role, tool calls, memory keys
ConversationEntry::label() provides descriptive labels matching the
old entry_sections format:
- "Kent: what about..." / "Aria: [tool_call: memory_search, ...]"
- "mem: [memory: key-name score:0.73]"
- "dmn: [heartbeat]" / "system: [system prompt]"

Uses config names (assistant_name, user_name) not generic "asst"/"user".
Widget renderer uses label() instead of raw content preview.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 21:04:41 -04:00
Kent Overstreet
5523752a15 Memory nodes section in F2 context screen with scoring visibility
Build a synthetic "Memory nodes (N scored, M unscored)" section in
the context screen by extracting Memory entries from the conversation
section. Each node shows its key and score. Inserted before the
conversation section so scores are visible at a glance.

This makes it easy to see whether scoring is keeping up — if unscored
count is high relative to scored, scoring needs to run more often.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 21:03:05 -04:00
Kent Overstreet
b892cae2be Simplify trim_entries, kill ContextBudget
trim_entries is now a simple loop:
1. Drop duplicate memories and DMN entries
2. While over budget: if memories > 50% of entry tokens, drop
   lowest-scored memory; otherwise drop oldest conversation entry
3. Snap to user message boundary

ContextBudget is gone — sections already have cached token totals:
- total_tokens() on ContextState replaces budget.total()
- format_budget() on ContextState replaces budget.format()
- trim() takes fixed_tokens: usize (system + identity + journal)

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2026-04-07 20:58:06 -04:00
Kent Overstreet
62996e27d7 WIP: ContextEntry/ContextSection data structures for incremental token counting
New types — not yet wired to callers:

- ContextEntry: wraps ConversationEntry with cached token count and
  timestamp
- ContextSection: named group of entries with cached token total.
  Private entries/tokens, read via entries()/tokens().
  Mutation via push(entry), set(index, entry), del(index).
- ContextState: system/identity/journal/conversation sections + working_stack
- ConversationEntry::System variant for system prompt entries

Token counting happens once at push time. Sections maintain their
totals incrementally via push/set/del. No more recomputing from
scratch on every budget check.

Does not compile — callers need updating.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 20:48:08 -04:00
Kent Overstreet
776ac527f1 trim_entries: take ContextBudget instead of recomputing
compact() already computes context_budget() — pass it to trim_entries
so it has access to all budget components without recomputing them.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:43:39 -04:00
Kent Overstreet
df62b7ceaa Persist memory scores, use them for eviction in trim_entries
Scores are saved to memory-scores.json alongside the conversation log
after each scoring run, and loaded on startup — no more re-scoring
on restart.

trim_entries now evicts lowest-scored memories first (instead of
oldest-first) when memories exceed 50% of context. The 50% threshold
stays as a heuristic for memory-vs-conversation balance until we have
a scoring signal for conversation entries too. Unscored memories get
0.0, so they're evicted before scored ones.

save_memory_scores rebuilds from current entries, so evicted memories
are automatically expired from the scores file.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:39:08 -04:00
Kent Overstreet
bef1bfbb33 Fix deadlock: lock subconscious before store (store is bottom-most)
subconscious_snapshots() was acquiring store→subconscious while
collect_results() holds subconscious→store — classic ABBA deadlock.

Fix: always acquire subconscious first, store second. Store is the
bottom-most lock in the ordering.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:27:36 -04:00
Kent Overstreet
27ca3c058d Shared persistent state across all subconscious agents
Moved persistent_state from per-agent to a single shared BTreeMap on
Subconscious. All agents read/write the same state — surface's walked
keys are visible to observe and reflect, etc.

- Subconscious.state: shared BTreeMap<String, String>
- walked() derives from state["walked"] instead of separate Vec
- subconscious-state.json is now a flat key-value map
- All agent outputs merge into the shared state on completion
- Loaded on startup, saved after any agent completes

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:23:08 -04:00
Kent Overstreet
578be807e7 Add expand/collapse all, per-pane key legends
SectionTree:
- 'e': expand all nodes
- 'c': collapse all nodes
- Home/End already wired from previous commit

Key legend shown at bottom border of each focused pane:
- Tree panes: nav, expand/collapse, expand/collapse all, paging
- Agent list: select, tab
- History: scroll, paging

Legend only appears on the focused pane to avoid clutter.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:09:04 -04:00
Kent Overstreet
19bb6d02e3 Fix scroll: PgUp/PgDn move cursor in place, add Scrollbar widget
SectionTree.handle_nav() now takes viewport height:
- PgUp/PgDn move both cursor and viewport by one page, keeping the
  cursor at the same screen position
- Home/End jump to first/last item
- scroll_to_selected() uses actual viewport height instead of
  hardcoded 30

Added render_scrollable() in widgets.rs: renders a Paragraph with a
vertical Scrollbar when content exceeds the viewport. Used by the
conscious and subconscious screens.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:07:00 -04:00
Kent Overstreet
818cdcc4e5 Three-pane subconscious debug screen with shared widgets
New layout for F3 screen:
- Top-left: agent list using ratatui List widget with ListState
- Middle-left: expandable agent state (persistent across runs)
- Bottom-left: memory store activity by provenance, walked keys
- Right: context tree from fork point, reusing SectionTree

Tab/Shift-Tab cycles focus clockwise between panes; focused pane
gets white border. Each pane handles its own input when focused.

Extracted user/widgets.rs:
- SectionTree (moved from mod.rs): expand/collapse tree for ContextSection
- pane_block_focused(): standard bordered block with focus indicator
- format_age()/format_ts_age(): shared duration formatting

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:03:14 -04:00
Kent Overstreet
edfa1c37f5 Subconscious: persistent agent state, store activity queries
- Agent state (outputs) persists across runs in subconscious-state.json,
  loaded on startup, saved after each run completes
- Merge semantics: each run's outputs accumulate into persistent_state
  rather than replacing
- Walked keys restored from surface agent state on load
- Store::recent_by_provenance() queries nodes by agent provenance for
  the store activity view
- Switch outputs from HashMap to BTreeMap for stable display ordering

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:03:05 -04:00
Kent Overstreet
cf1c64f936 Split context_state_summary: ContextBudget for compaction, UI-only for display
context_state_summary() was used for both compaction decisions (just
needs token counts) and debug screen display (needs full tree with
labels). Split into:

- Agent::context_budget() -> ContextBudget: cheap token counting by
  category, used by compact(), restore_from_log(), mind event loop
- ContextBudget::format(): replaces sections_budget_string() which
  fragily pattern-matched on section name strings
- context_state_summary(): now UI-only, formatting code stays here

Also extracted entry_sections() as shared helper with include_memories
param — false for context_state_summary (memories have own section),
true for conversation_sections_from() (subconscious screen shows all).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 19:02:58 -04:00
Kent Overstreet
9e49398689 Agent-aware provenance for memory tools
Add provenance field to Agent, set to "agent:{name}" for forked
subconscious agents. Memory tools (write, link_add, supersede,
journal_new, journal_update) now read provenance from the Agent
context when available, falling back to "manual" for interactive use.

AutoAgent passes the forked agent to dispatch_with_agent so tools
can access it.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 17:46:40 -04:00
Kent Overstreet
74f8952399 Fix: push all responses to forked agent entries
The final assistant response in run_with_backend wasn't being pushed
to the backend — only intermediate step responses were. This meant
the subconscious debug screen only showed the prompt, not the full
conversation.

Now push assistant response immediately after receiving it, before
checking for next steps. Remove the duplicate push in the multi-step
path.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 17:38:23 -04:00
Kent Overstreet
1f873140ae Reduce pub visibility: hippocampus, subconscious internals
hippocampus: cursor navigation, transcript parsing, similarity
functions to pub(crate). counters::open() made private.

subconscious: all format_* prompts helpers to pub(super),
load_defs and keys_to_replay_items made private,
consolidate_full_with_progress made private.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 17:29:12 -04:00
Kent Overstreet
9737641c86 Fix build warnings across workspace
- Remove redundant token fields from StreamEvent::Finished (data
  already delivered via Usage event)
- Remove dead hotkey_adjust_sampling, MAX_HISTORY, now()
- Fix unused variable warnings (delta, log)
- Suppress deserialization-only field warnings (jsonrpc, role)
- Make start_stream/chat_completion_stream_temp pub(crate)
- Remove unnecessary pub(crate) re-export of internal types

Remaining warnings are TODO items: SkipIndex (scoring not wired),
notify (MCP notifications not wired).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:55:30 -04:00
Kent Overstreet
c64295ddb2 Reduce pub visibility in agent::api and user modules
api/: parsing module private, SamplingParams/StreamEvent/StreamResult/
AbortOnDrop/build_response_message/collect_stream to pub(crate).
Internal types (ChatRequest, ChunkChoice, Delta, etc.) to pub(crate).
StreamResult fields to pub(crate). Parsing functions to pub(super).

user/: context, subconscious, unconscious, thalamus modules private
(only chat needs pub(crate) for mind/ access).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:43:25 -04:00
Kent Overstreet
f33b1767da Restrict API types visibility — types module is now private
Only Message, Role, MessageContent, ContentPart, ToolCall,
FunctionCall, Usage, ImageUrl are pub-exported from agent::api.

Internal types (ChatRequest, ChatCompletionChunk, ChunkChoice,
Delta, ReasoningConfig, ToolCallDelta, FunctionCallDelta) are
pub(crate) — invisible outside the crate.

All callers updated to import from agent::api:: instead of
agent::api::types::.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:39:20 -04:00
Kent Overstreet
25f4cfabbb Remove dead functions from spectral.rs and identity.rs
spectral.rs: remove print_summary, to_embedding, save_embedding,
nearest_neighbors, unlinked_neighbors, dominant_dimensions,
SpectralResult, shorten_key. Core functions (load_embedding,
nearest_to_seeds_weighted, analyze_positions, etc.) kept.

identity.rs: remove context_file_info (zero callers).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:33:45 -04:00
Kent Overstreet
f4def8d03b Fix: reap stale agent pid files in poc-hook
scan_pid_files was removed as dead code but it was actually needed
by the hook path — the bug was that it was never wired in. Add
reap_agent_pids() directly to poc-hook.rs and call it on every
UserPromptSubmit. Kills timed-out agents (10min) and cleans up
pid files for dead processes.

Also remove dead subconscious/subconscious.rs (420 lines) — was
forked to claude/agent_cycles.rs and never removed.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:27:59 -04:00
Kent Overstreet
39965556dd Remove dead code: scan_pid_files, backend_label, entries_mut, post_json
All confirmed unused anywhere in src/ or channels/.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:25:18 -04:00
Kent Overstreet
9598e8b86c Remove dead files: parse-claude-conversation.rs, test-conversation.rs
Orphaned binaries — not in Cargo.toml, not declared as modules.
~395 lines of dead code.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:22:35 -04:00
Kent Overstreet
7de816022a kill off pub in src/usr/mod.rs
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2026-04-07 13:19:08 -04:00
Kent Overstreet
d7c93ffdf1 Upgrade redb 2 → 4, slim down tui-markdown
redb: add ReadableDatabase trait import for begin_read().
tui-markdown: disable highlight-code (drops syntect), fix
test deps leaking into normal dependencies.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:06:02 -04:00
Kent Overstreet
61b0a43cf5 Use tui-markdown fork — tracing fully eliminated
Point to koverstreet/tui-markdown which replaces tracing with log.
tracing is now completely gone from the dependency tree.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 13:00:29 -04:00
Kent Overstreet
3625764ca5 organize cargo deps 2026-04-07 12:54:23 -04:00
Kent Overstreet
1cf4f504c0 Kill reqwest — minimal HTTP client on raw hyper + tokio-rustls
New src/agent/api/http.rs: ~240 lines, supports GET/POST, JSON/form
bodies, SSE streaming via chunk(), TLS via rustls. No tracing dep.

Removes reqwest from the main crate and telegram channel crate.
Cargo.lock drops ~900 lines of transitive dependencies.

tracing now only pulled in by tui-markdown.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 12:50:40 -04:00
Kent Overstreet
a421c3c9f3 Upgrade capnp 0.20 → 0.25, capnp-rpc 0.20 → 0.25
RPC trait methods changed from &mut self to self: Rc<Self> and
return types from Promise<(), Error> to impl Future<Output = Result<...>>.

Updated all Server impls across 6 files: DaemonImpl (rpc.rs),
NotifyForwarder (channels.rs), and ChannelServerImpl in all channel
crates (irc, telegram, tmux, socat). Local pry! macro replaces
capnp_rpc::pry to match the new impl Future return type.

Warning-clean workspace build.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 12:29:44 -04:00
Kent Overstreet
382ebc95aa Analysis notes: UI desync pop/push line count mismatch
Documents the root cause of the streaming display bug —
pop removes 1 line per entry but push produces N lines
(markdown, tool results). Includes concrete fix approach
using per-entry line count tracking.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 11:54:30 -04:00
Kent Overstreet
f387041aca Replace unreachable!() with proper error in retry loop
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 03:50:57 -04:00
Kent Overstreet
c2eb9c53cb Remove dead Backend::log() stub
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-07 03:50:19 -04:00