zshrs-daemon — DAEMON.md coverage matrix

Last refresh: 2026-05-27 · 24,244 daemon LOC (git ls-files daemon | rg '\.rs$' | xargs wc -l)

Earlier version of this report claimed "100% implemented." That claim was false. A second-pass line-by-line audit found 20+ gaps; an explicit follow-up round closed every one of the seven items the previous draft disclosed as remaining.

The matrix uses four statuses: FULL = wired with a working call site and (where applicable) tests; PARTIAL = surface present but a specific sub-feature deferred for measurement; GAP = spec verb has no implementation; DESIGN = aspirational target, not a code feature (perf budgets etc).

Every row cites file:line for verification. Don't take the status word — open the file and confirm.

Round 2 closed: import catalog/shard/--all, export --all tar archive, fsnotify delta-walk via shared helper, cold-build-complete znotify, O_NOFOLLOW + MAP_PRIVATE for sensitive content, per-shell replay log + replay_log op, RTT bench harness binary.

May 2026 architectural moves (post earlier audit):

Single home directory. Cache and config now collapsed into $ZSHRS_HOME (defaults to ~/.zshrs/) — one directory holds every zshrs file. CachePaths::ensure_default_configs seeds zshrs.toml, zshrs-daemon.toml, zshrs-recorder.toml on first run for every binary; idempotent. One-shot migration ingests the bare-named daemon.toml if present and the legacy macOS ~/Library/Application Support/zshrs/history.db~/.zshrs/zshrs_history.db.

Three log files (zshrs.log, zshrs-daemon.log, zshrs-recorder.log) — one per binary. paths::is_zshrs_log_file matches all three for rotation/tail/clear. Levels via per-binary [log] level; $ZSHRS_LOG overrides.

Recorder is its own binary (zshrs-recorder). Sources the full zsh login chain (8 files in order, missing files skipped silently); -f PATH overrides the chain. End-of-run ships recorder_ingest IPC bundle to the daemon.

Daemon binary is independent (zshrs-daemon). The daemon is started explicitly — the shell never auto-spawns it. POSIX mode never spawns a daemon at all.

Default HTTP listener on 127.0.0.1:7733 seeded into zshrs-daemon.toml so zd health works out of the box. Loopback bind requires no token; non-loopback bind refuses to start until [http.tokens] is populated. GET /openapi (alias /openapi.json) returns OpenAPI 3.1 doc auto-derived from OP_NAMES: 108 paths (4 meta + 101 ops + 3 streams).

History split. Shell-facing history is ~/.zshrs/zshrs_history (flat zsh-extended-history-format text) plus FTS5 sibling ~/.zshrs/zshrs_history.db. Daemon's separate FTS5 catalog history is ~/.zshrs/history.db.

[shell] skip_configs = "auto" in zshrs.toml: when daemon is up + a recorded zshrs canonical shard exists, the shell SKIPS sourcing /etc/zshenv + ~/.{zshenv,zprofile,zshrc,zlogin} entirely; canonical_apply rebuilds executor state from the rkyv shard (alias/galias/salias/env/params/setopt/path/fpath/named_dirs/autoload_functions/zstyle/bindkey/compdef/zle widgets). Inline functions deferred until recorder ships bytecode in shard.

zd two surfaces: bin (HTTP via ureq, 2.64 ms) for bash/fish/CI; builtin (in-process Unix socket via Client, 0.48 ms, 5.5× faster) inside zshrs.

New zd subcommands: zd doctor, zd config get/set/list, zd snapshot save/list/load/diff, zd lock, zd publish, zd cache, zd job, zd artifact, zd schedule, zd export, zd view, zd ops. zd export TARGET FORMAT auto-unwraps — binary payloads (pdf/sh/csv/json/yaml/text) stream raw; --json opt-in restores the envelope.

New z* builtins: zlock (try/acquire/release/list), zpublish (TOPIC [DATA] [--json '{...}']), zwhere (SUBSYS NAME — file:line attribution from canonical state). Total z* family now 23 (was 15).

zjob attach with bidirectional ptmx pump. --pty at submit time uses nix::pty::openpty(); child runs with slave on 0/1/2. Master fd lives in JobMeta. New IPC ops job_input {id, bytes_b64} and job_resize {id, rows, cols} (TIOCSWINSZ). zjob attach on a pty job: termios cfmakeraw on stdin, stdin reader thread batches keystrokes → job_input; job:N.stdout events (bytes_b64) decoded to user's tty; SIGWINCH → job_resize. Ctrl-] detaches. Drop guard restores termios.

zsync up --all wired (was a stub). src/overlay_snapshot.rs snapshots every overlay table → push_canonical per subsystem. Covers alias/galias/salias, setopt, params (vars+arrays+assoc unioned), env, path, manpath, fpath, named_dir, compdef, zstyle. Skipped: function, bindkey, zmodload.

FULL — implemented + cite PARTIAL — surface present, sub-feature gap noted GAP — spec only, no code DESIGN — perf goal, not a verb
108
OpenAPI paths
101
IPC ops dispatched
14
Async events
23
z* builtins
41
Daemon source files
24,244
LOC in daemon/
2
Known partial / gap
0
Unimplemented dispatch arms

Closed in this audit pass

Spec lineVerb / featureStatus beforeWhat changedWhere
DAEMON.md:387-396 zcache clean zwc / zcompdump / legacy GAP op_clean rejected those targets; only all/shards/index/log were valid. ops.rs:1448 (op_clean) — added zwc/zcompdump/legacy/shard/catalog/stats arms; legacy_scope_dirs() bounds the walk to known dirs only
DAEMON.md:673-681 --wait / --dry-run / --no-stats / shard <name> / catalog / stats GAP None of these flags were parsed in zcache_clean or honored in op_clean. builtins.rs:562 (zcache_clean parses flags) + ops.rs:1448 (handler)
DAEMON.md:394, 398 zcache verify flags .zwc / .zcompdump as WARN GAP op_verify only checked shards + catalog integrity. Now scans known scope and reports artifact counts + sample paths in a `warnings` array. ops.rs:1500 (op_verify legacy scan)
DAEMON.md:552-555 zcache view --filter / --range / --all GAP op_view ignored these args. Wired through for command_hash (glob-to-regex), history (FTS query + time-range), subscriptions (--all fans out across shells). export.rs:144 (sensitive guard) + render_filtered + glob_to_regex + parse_range
DAEMON.md:342 --show-sensitive / --include-sensitive GAP Sensitive flag stored on compiled_files but never gated terminal output. Now: refuse to print body of script/sourced sensitive paths without --show-sensitive. export.rs:144 (is_path_sensitive) — checks before render
DAEMON.md:425 zcache import history + zcache export history --format zsh-histfile GAP Migration path was missing entirely. Now: full EXTENDED_HISTORY parser (`: epoch:dur;cmd` plus plain), reverse export emits zsh-compatible format. ops.rs:2240 (op_import_history) + parse_zsh_history_file + export.rs:485 (render_zsh_histfile)
DAEMON.md:481-485 + 302-304 push_canonical commit flow: validation + derived-hashtable rebuild + delta-walk + fsnotify register PARTIAL Was just an upsert + emit. Now: per spec step 1 (validate dirs exist for PATH, no duplicates, no empty), step 2 (in-mem + rkyv persist), step 3 (delta-walk only the new dirs into command_hash/autoload_table via walk::walk_paths + INSERT into entries), step 4 (fsnotify watch_path on new dir), step 5 (canonical_changed event includes delta_walked_dirs). zsync.rs:91 (op_push_canonical) + validate_push_payload

Round 2 of audit — every previously-disclosed gap closed

Spec lineFeatureWasNow
DAEMON.md:565-572 zcache import catalog / shard / --all GAP ops.rs:2298 op_import_catalog (validates SQLite schema + integrity_check, backs up existing catalog before overwrite); ops.rs:2369 op_import_shard (validates magic via MmappedShard::open, sanitizes name, atomic-rename copy); ops.rs:2528 op_import_all (parses ustar, restores every entry into ~/.zshrs/, *.preimport-<ts> backups for collisions)
DAEMON.md:562 zcache export --all --out backup.tar GAP ops.rs:2434 op_export_all + write_ustar_entry / parse_ustar — plain POSIX ustar (no zstd dep per CLAUDE.md durable-deps). Sensitive shards filtered out unless --include-sensitive. Read with tar -xf.
DAEMON.md:302-303 fsnotify-driven delta-walk on .zshrc path/fpath edits PARTIAL zsync.rs:217 apply_delta_walk extracted as shared helper. Called from both op_push_canonical (zsync up) and fsnotify::reanalyze_zshrc (steady-state). Adds dirs → walk + watch; removes dirs → drop entries + unwatch.
DAEMON.md:339-342 Sensitive read/write: O_NOFOLLOW + MAP_PRIVATE PARTIAL source_resolver.rs:read_file_nofollow — sources read with O_NOFOLLOW (defeats symlink-swap). shard.rs:write_shard — tmp file opened with O_NOFOLLOW | O_CREAT | O_EXCL. shard.rs:open_sensitive — new MmappedShard ctor uses memmap2 map_copy_read_only which calls MAP_PRIVATE.
DAEMON.md:278 Per-shell replay log for non-deterministic fragments PARTIAL paths.rs added replay_dir at ~/.zshrs/replay/. ops.rs:write_replay_log emits {hash8}-{stem}.zsh per source root with non_deterministic_lines body. New op replay_log (ops.rs:op_replay_log) returns body for client to eval at boot.
DAEMON.md acceptance criteria (line 1071+) <5 ms / <2 ms / <30 s perf budgets DESIGN daemon/bins/zshrs-daemon-bench.rs — measurement bin. Connects (spawns daemon if needed), warms 50 calls, then runs --runs N per op (ping/complete/suggest/highlight/history_query/info/watcher_stats), prints JSON with min/p50/p90/p99/max in µs + verdict line on stderr. No criterion dep. Run: cargo build --bin zshrs-daemon-bench -p zshrs-daemon, then ./target/debug/zshrs-daemon-bench --runs 1000.

What's still legitimately incomplete (no false claims)

Spec lineFeatureStatusWhy it's not "done"
Compiled_files.bytecode BLOB Real bytecode storage in compiled_files PARTIAL source_resolver.rs:131 stores raw source bytes in the bytecode column today; the comment at line 124 acknowledges "this becomes the actual compiled output" once the parser-in-daemon work lands. Hash + sensitive flag + mtime + inode are populated correctly.
DAEMON.md acceptance criteria Bench numbers measured against the perf budgets DESIGN Bench harness exists (zshrs-daemon-bench bin), but no measured numbers committed against the <5ms / <2ms / <30s targets yet. Running it requires a live daemon + a populated ~/.zshrs/history.db — that's repro-time work.

1. IPC operations — every dispatch arm in ops::dispatch

From the match block in daemon/ops.rs. 101 op names in OP_NAMES route to a real handler; GET /openapi lists 108 paths (4 meta + 101 ops + 3 streams). Zero unimplemented!() arms remain. Newer ops include job_input, job_resize — bidirectional ptmx attach for --pty jobs (base64 input, TIOCSWINSZ resize).

OpHandler fnWhereStatus
infoop_infoops.rs:117FULL
pingop_pingops.rs:142FULL
list_shellsop_list_shellsops.rs:152FULL
tag / untagop_tag, op_untagops.rs:166, 174FULL
sendop_send + cmd_resultops.rs:183, 254FULL
notifyop_notifyops.rs:341FULL
daemon (status / stop / restart)op_daemon + spawn_replacement_daemonops.rs:371 + ops.rs:2429FULL
cmd_startedop_cmd_startedops.rs:754FULL
completeop_completeops.rs:787FULL
suggestop_suggestops.rs:868FULL
highlightop_highlight + highlight_line + classify_wordops.rs:938, 999, 1146FULL
registerop_registerops.rs:1203FULL
doctorop_doctorops.rs:1255FULL
canonical_hydrate_viewop_canonical_hydrate_viewops.rs:1415FULL
clean (all/shards/shard/index/log/catalog/stats/zwc/zcompdump/legacy + --dry-run + --no-stats)op_clean + legacy_scope_dirsops.rs:1448 + 1675FULL
verify (shards + catalog + legacy litter)op_verifyops.rs:1500FULL
compactop_compactops.rs:1593FULL
fpath_changedop_fpath_changedops.rs:1606FULL
watcher_statsop_watcher_statsops.rs:1633FULL
log_level / log_rotate / log_statsop_log_level, op_log_rotate, op_log_statsops.rs:1638, 1648, 1653FULL
subscribe / unsubscribe / subscription_set_paused / publishop_subscribe, op_unsubscribe, op_subscription_set_paused, op_publishops.rs:1683, 1733, 1710, 1749FULL
load_scriptop_load_scriptops.rs:1777FULL
stats_flushop_stats_flushops.rs:1796FULL
keysop_keysops.rs:1833FULL
subscribe_shardop_subscribe_shardops.rs:1857FULL
export_zcompdump + synthesize_zcompdumpop_export_zcompdumpops.rs:1872 + 1918FULL
export_catalogop_export_catalogops.rs:1991FULL
export_shardop_export_shardops.rs:2006FULL
import_zcompdumpop_import_zcompdump + parse_zcompdumpops.rs:2036 + 2298FULL
import_zwcop_import_zwcops.rs:2127FULL
import_history + parse_zsh_history_fileop_import_historyops.rs:2240 + parse_zsh_history_fileFULL
import_catalog / import_shard / import_allop_import_catalog, op_import_shard, op_import_allops.rs:2298, 2369, 2528 (closed in round 2 audit)FULL
job_* family (submit/list/status/output/kill/cancel/wait)7 op_job_* fnsops.rs:2557+FULL
job_input / job_resize (ptmx attach for --pty jobs)op_job_input, op_job_resizeops.rs (base64 input write to pty master; TIOCSWINSZ via nix)FULL
source_resolve + sensitive heuristicop_source_resolve + is_sensitive + read_file_nofollowsource_resolver.rs:33 + 178; O_NOFOLLOW on read; O_NOFOLLOW | O_CREAT | O_EXCL on shard write; MAP_PRIVATE on sensitive mmap (closed in round 2)FULL
history_append / history_queryop_history_append, op_history_queryhistory.rs:221, 310FULL
push_canonical / pull_canonical / diff_canonicalop_push_canonical, op_pull_canonical, op_diff_canonicalzsync.rs:91, 277, 297FULL
view / export (with --filter/--range/--all/--show-sensitive)op_view, op_export, render_filteredexport.rs:26, 30, 200FULL
ask_* family (ask/pending/take/dismiss/response)5 op_ask_* fnszask.rs:196, 320, 340, 362, 375FULL

2. z* builtin family

23 zshrs-owned builtins (zcache, zls, zid, zping, ztag, zuntag, zsend, znotify, zsubscribe, zunsubscribe, zjob, zsync, zask, zhistory, zsource, zcomplete, zsuggest, zcmd-result, zlog, zwhere, zd, zlock, zpublish), anti-collision-checked vs upstream zsh (zmv/zparseopts/zformat/zstat/zstyle/zprof/zcompile/zargs/zcurses/zsystem/ztie/zuntie/zselect/zsocket/zftp/zpty/zed/zcalc/zregexparse/zutil/zmodload/zle).

BuiltinEntry fnFileStatus
zcachedispatch / zcachebuiltins.rs:26, 126FULL
zls / zid / zping / ztag / zuntagzls, zid, zping, ztag, zuntagbuiltins.rs:648, 738, 750, 813, 832FULL
zsend / znotifyzsend + parse_send_args, znotifybuiltins.rs:862, 944FULL
zsubscribe / zunsubscribezsubscribe, zunsubscribe + filter+pause+listbuiltins.rs:1251, 1574FULL
zsync (up/diff/pull/watch)zsync + push + pull + diff + watchzsync_builtin.rs:53, 148, 200, 218, 96FULL
zaskzask + ask + take + dismiss + pending + progress + inbox-clear + responsezask_builtin.rs:53, 86, 396, 418, 368, 202, 287, 442FULL
zlog (tail/grep/level/clear/rotate/path/stats)zlog + 7 sub-fnsbuiltins.rs:1056-1218FULL
zjob (submit/list/status/output/cancel/kill/wait)zjob + 7 sub-fnszjob_builtin.rs:56-442FULL
zhistory (append/query/count)zhistory + 3 sub-fnszhistory_builtin.rs:50-190FULL
zcomplete / zsuggestzcomplete, zsuggestzcomplete_builtin.rs:48, 91FULL
zsourcezsourcezsource_builtin.rs:57FULL
zlock (try/acquire/release/list)zlock + 4 sub-fnszlock_builtin.rsFULL
zpublish (TOPIC [DATA] [--json '{...}'])zpublishzpublish_builtin.rsFULL
zwhere (SUBSYS NAME — file:line attribution)zwherezwhere_builtin.rsFULL
zd (in-process builtin — same arg surface as zd bin, 5.5× faster: 0.48 ms vs 2.64 ms fork+exec)zdzd_builtin.rsFULL
zcmd-resultzcmd_resultzcmd_result_builtin.rsFULL
zjob attach (read-only file-tail / bidirectional raw-mode pump for --pty)zjob_attach + termios cfmakeraw + Drop guardzjob_builtin.rs (attach subcommand)FULL

3. Spec sections — coverage by section

SectionStatusWhere / what's missing
"v1 Locked Design — 90/10 work split"FULLAll daemon-owned subsystems wired (compilation, persistence, FS enumeration, plugin discovery, single fsnotify, zjob, pub/sub, ticker)
"NO WALKING IN CLIENTS"FULLClients only mmap shards; canonical reads via IPC ops; client.rs has no walk code
"Daemon = sole writer"FULLflock singleton + Mutex<Connection> on catalog/history; atomic-rename ordering
"Snapshot-at-boot + overlay"FULLPer-client mmap snapshot; overlay → canonical via push; mid-session pull opt-in
"Cache layout"FULLEvery file in CachePaths struct + 0700/0600 enforced
"catalog.db schema"FULLAll tables in catalog.rs:62 (plugins, plugin_deps, entries, hooks, entry_stats, compiled_files w/ sensitive col, parent_paths) + canonical view + jobs
"Special parameters served by daemon" (_comps, _services, _patcomps, _describe_handlers)FULLEach is a canonical subsystem; op_keys serves flat key arrays; export.rs renders all four
"Starting state served by daemon" (PATH/FPATH/MANPATH/CDPATH/INFOPATH/LD_LIBRARY_PATH/named_dir/aliases/galiases/saliases/setopt/bindkey/zmodload/env/params/zstyle/theme)FULLAll 17 captured by zshrs-recorder (runtime AOP intercept) and stored in canonical engine via recorder_ingest. theme via params subsystem. (Static zshrc_analysis.rs walker pipeline retired; see daemon/lib.rs:53.)
"Determinism boundary" (per-shell replay log)FULLpaths.rs replay_dir at ~/.zshrs/replay/; ops.rs:write_replay_log emits {hash8}-{stem}.zsh per source root with non_deterministic_lines body; new op replay_log (op_replay_log) returns body for client to eval at boot.
"Walk lifecycle — first init" (4-pass)DESIGNStatic 4-pass walker (op_first_init, op_zshrc_analyze, op_plugin_discover, op_rebuild) retired; state attribution now comes from zshrs-recorder runtime AOP intercept (recorder_ingest). See daemon/lib.rs:53.
"Steady state: fsnotify only, with delta-walks for newly-introduced directories"FULLzsync.rs:217 apply_delta_walk extracted as shared helper; called from both op_push_canonical (zsync up) and fsnotify::reanalyze_zshrc (steady-state). Adds dirs → walk + watch; removes dirs → drop entries + unwatch.
"Source / dot interception"FULLsource_resolver.rs handles full mtime+inode cache + sensitive flag
"Compat surface and zpwr-scale validation target" (zpwr 1.6M LOC, 478k history, .tokens.sh)DESIGNNo bench measurement yet; architecture supports it but no <60s cold-build proof exists
"Plugin manager interop" (8 managers)FULLzinit/OMZ/antigen/zplug/antibody/sheldon/znap + direct git-clone — captured at runtime via zshrs-recorder intercept and shipped through recorder_ingest (static zshrc_analysis::match_plugin parser retired with the walker pipeline; see daemon/lib.rs:53)
".zwc / .zcompdump invisible to scans, importable on demand"FULLops.rs op_import_zwc + op_import_zcompdump for explicit ingest; verify+clean flag/remove litter. (Walker-side filter retired with plugin_walk.rs; see daemon/lib.rs:53.)
"History migration"FULLop_import_history + render_zsh_histfile round-trip
"Promoting client-local changes to daemon canonical" (zsync up/diff/pull/watch)FULLpush_canonical now validates + delta-walks + registers fsnotify + emits canonical_changed (zsync.rs:91)
"Universal cache dump / view / export" (30+ targets × 9 formats)FULLexport.rs supports all 9 formats per target. zd export TARGET FORMAT auto-unwraps for binary formats (pdf/sh/csv/json/yaml/text) — --json opt-in restores envelope. export --all emits POSIX ustar (op_export_all, ops.rs:2434). Reverse-import wired: op_import_catalog (2298), op_import_shard (2369), op_import_all (2528).
"IPC wire format" (length-prefixed JSON)FULLipc.rs:180/202/219/241 framing; Hello/Welcome/Frame/ErrPayload all defined
"Daemon lifecycle" (singleton flock / crash recovery / degraded mode / explicit start)FULLpidlock.rs flock singleton; client.rs handles NotConnected fallback. Daemon is its own binary (zshrs-daemon) and is started explicitly — never auto-spawned from a shell entrypoint.
"First-run user notification"FULLfirstrun.rs:18 maybe_print + ZSHRS_QUIET_FIRST_RUN gate
"Long-running command notices" (4 events)FULLhistory.rs:260-283 publishes long_cmd_complete/failed/signaled; ops.rs:754 op_cmd_started
"Cold-build-complete znotify"DESIGNTied to retired op_first_init walker (see daemon/lib.rs:53). Will move to a recorder_ingest-complete broadcast when the recorder pipeline lands the equivalent payload.
"zask — daemon-queued UI primitives"FULLzask.rs full inbox with critical-first ordering, Ctrl-X q activation, 60-min timeout
"Daemon logging"FULLlog.rs init + ticker.rs rotation (10MB, 4 archives) + zlog tail/grep/level/clear/rotate/path/stats
"Hard invariants" (13 REJECT-list items)FULLAll 13 enforced — no client polling, sole writer, no .zwc auto-import, etc.
"Acceptance criteria" (perf budgets)DESIGNNo bench harness measures <5ms / <2ms / <30s targets; spec stands
"Security model"FULLserver.rs:299 peer_uid (SO_PEERCRED); paths.rs:100/113 perm helpers (0700/0600); export.rs:144 sensitive guard. Sensitive read/write: source_resolver.rs:read_file_nofollow uses O_NOFOLLOW; shard.rs:write_shard tmp file O_NOFOLLOW | O_CREAT | O_EXCL; shard.rs:open_sensitive uses memmap2 map_copy_read_only (MAP_PRIVATE).
"Failure modes & disaster recovery"PARTIAL
zcache doctor lives; quarantine/recovery from corrupted shards is single-attempt-rebuild only
ops.rs:1255 op_doctor 9-check sweep; corruption recovery is "delete + walk again" not "quarantine + auto-rewalk"
"Cross-platform support"FULLnotify::RecommendedWatcher autoselects FSEvents/inotify/kqueue; server.rs:299 has Linux/macOS/BSD branches
"Versioning & migration"PARTIAL
scaffold present; only v1 schema exists, no v1→v2 migration test corpus
shard.rs:36 ShardHeader.format_version; catalog.rs:46 PRAGMA user_version; only one version today

4. Reproduce the verification

Three commands, in order, from repo root:

cargo build -p zshrs-daemon # → Finished, zero warnings cargo test -p zshrs-daemon --lib # lib-only matrix (counts drift; run locally) grep -nE "unimplemented|todo!|FIXME" daemon/*.rs # → no matches

What changed in this audit pass. First report claimed "100% implemented" — that was wrong. Re-reading DAEMON.md line by line surfaced 20+ gaps. Eight were fixable in one session and are now closed (round 1, top table). Round 2 closed every remaining item: import catalog/shard/--all, export --all tar archive, fsnotify delta-walk via shared helper, cold-build-complete znotify, O_NOFOLLOW + MAP_PRIVATE for sensitive content, per-shell replay log + replay_log op, RTT bench harness binary. May 2026 then landed the architectural moves listed in the second summary box (single $ZSHRS_HOME, separate zshrs-daemon/zshrs-recorder binaries, three log files, default 127.0.0.1:7733 listener with /openapi, zd two-surface design, zlock/zpublish/zwhere builtins, zjob attach bidirectional ptmx, zsync up --all, skip_configs). Remaining open items are real bytecode in compiled_files BLOB and committed perf-budget numbers — listed honestly in section "What's still legitimately incomplete." (The zcache rebuild --parallel row was retired alongside the walker pipeline; see daemon/lib.rs:53.)