jera-coverage audit — 2026-08-21
Question. Rickard's rule: shared OPERATIONS (populating/registering repos, and operation-shaped work generally) SHALL live in jera (the shared runtime in edda); dwarves-server and dwarves-ui CALL jera, they do not hand-roll twins (LAW 5:
10 duplicated lines = share). This audit measures dwarves against that rule.
Method. Code read at dwarves 0cf9dda (primary checkout == this worktree), edda d7ce541, nornir HEAD, workspace_nordisk cec2b62. Every file:line below was re-grepped at those commits (MEASURED). Line-count estimates for duplication are marked ~ (INFERRED). Live probes were read-only: ss, systemctl show, stat/ find on the server user's ledgers — nothing on :7900/:7878 was mutated. Docs-only change; no production code touched.
House columns: subject — STATUS — detail.
0. Verdict in one paragraph
jera is LIVE across the constellation (workspace_nordisk cec2b62, MEASURED here too: 9 manifest deps at Cargo.toml depth-any across dwarves/korp/holger/nornir/edda by this count — cec2b62 says 10; the one-manifest difference does not move the verdict — and jera:: appears in 16 dwarves / 11 korp / 8 holger / 2 nornir source files; nornir consumes it through the nornir-jobs facade, see §1.1. Outside those five, Skidbladnir, modgunn, ordning-demo and skade/bench also declare jera). dwarves depends on jera and uses it for placement, containers and VM boot — but the server side writes ZERO rows to the jera job ledger, and no code in any dwarves crate touches jera's progress API (Reporter/ReportSink/JobReports/DaemonPhase/start_or_resume_daemon: 0 hits outside tests). Progress is re-invented three times instead (BuildRun mpsc, AddWarehouse
- PopulateProgress, step_board populate_steps), and the one UI pane that reads the jera ledger reads a local path the live server never writes. Meanwhile the embedded nornir (
:7878) DOES write a live jera ledger on the server host — the UI just cannot see it.
1. jera's actual surface (edda crates/jera, MEASURED)
src/lib.rs:26-34 — modules jobs, boot, container, policy, vm, agent, agent_grpc (feature agent-grpc). Features (Cargo.toml): default = [], vm-tunnr, container-oci, agent-grpc — every live engine routes THROUGH draupnir.
1.1 jobs — the durable job ledger (src/jobs.rs, 1970 lines)
kind::*—jobs.rs:96-212— 40+ job kinds incl.WORKSPACE_FETCH/_POPULATE/_CLONE(:100,:106,:112),KNOWLEDGE_SCAN :117,SCIP_INGEST :118,VECTOR_EMBED :152,COVERAGE :156,CONTAINER :160,BOOT_EXE/_CONTAINER/_VM :166-174,CI_BUILD :199,DAEMON :212. dwarves uses exactly ONE:kind::CI_BUILD(8 sites).status::{QUEUED,RUNNING,DONE,FAILED,STOPPED}:68-81,is_terminal :83.JobClass/class_of/is_exclusive/is_daemon:225-269.DaemonPhase:302+fraction() :319.JobRecord:331(is_terminal :383,daemon_phase :391),JobSelector :398.JobSink:430—redb :436,remote :453,noop :459(fat/thin client seam).JobHandle:476—start :496,start_child :513,start_daemon :542,resume_daemon :557,on_node :648,with_reports :667,reporter :676,finish :681,stop :691,fail :696,fail_with_detail :705, Drop-guard:721.JobStore:757—open :772,open_read_only :792,sink :817,report_sink :826,daemon_report_sink :843,report_registry :879,job_reports :886,reports_snapshot :894,start :906,start_child :920,start_daemon :936,start_or_resume_daemon :963,submit :1022,list :1031,prune :1050.workspace_ledger_path :1198,workspace_sink :1222.jobs/report.rs—Health :47,JobReport :75,JobReports :123(progress :133,health :138,phase :148,progress_fraction :170,progress_indeterminate :182,progress_meta :192),ReportSink :232,Reporter :274(progress :298,progress_note :303,health :308,gauge :313,message :318,phase :326).- nornir facade (the grep-trap, cec2b62):
nornir/crates/nornir-jobs/src/lib.rs:22-23pub use jera::container::*; pub use jera::jobs::*;(depCargo.toml:20). nornir's rootCargo.tomlhas 0 mentions of jera andnornir/srchas 0jera::strings yet 36jobs::JobHandle/JobSink/JobStorecall sites — a root-manifest+src grep undercounts. Every count in this report was taken over<repo>/crates/**as well.
1.2 agent — placement (src/agent.rs, 1281 lines)
AgentSpec :41, ProcessSpec :86, WorkPayload :143, ResourceReq :188, WorkUnit :240, WorkStatus :318, WorkResult :358 (to_job_record :444), WorkHandle :473, Agent :483, LocalRunner :507 = Arc<dyn Fn(&WorkUnit,&AtomicBool)->bool> (jera ships NO process spawner — the runner closure IS the seam), LocalAgent :531, AgentTransport :622, GrpcAgent :635, LoopbackTransport :696, Scheduler :762 (register :789, match_agent :799, dispatch :810, state_json :859); agent/roster.rs Roster :52; agent_grpc.rs AgentWorkerSvc :51, GrpcTransport :200.
1.3 boot / container / vm / policy
boot.rs:BootMode :36(job_kind :56),BootStatus :68,BootTarget :105,BootProc :143,BootRunner :178,ExeBootRunner :299,DispatchBootRunner :354,BootJobs :432(new(sink,..) :449,with_runner :454,with_reports :470,boot :519,poll :635,kill :656) — "start X as a tracked job".container.rs:ContainerSpec :197(to_draupnir :389),submit_container_job :470,connect_default_runner :488,DraupnirContainerBootRunner :524(spawn_spec_with_reporter :551),run_container :734,run_container_with_reports :747.vm.rs:BootSpec :33,VmBootRunner :88,DraupnirVmBootRunner :116,default_vm_runner :223.policy.rs:JobPolicy :26.
What jera does NOT ship (so these are seams, not twins): git clone/fetch (that is nornir-git), workspace register/populate (nornir server RPCs Workspaces.Register/Fetch, monitor.rs fetch_workspace_with_progress :77 / republish_with :420 taking Option<&PhaseJobs>), a process spawner (LocalRunner closure), an HTTP/SSE surface. edda's progress convention today is Option<&PhaseJobs> / trailing impl FnMut(&Outcome) (nornir monitor) or sink-injected-at-construction (nornir-fleet/src/lib.rs:165-167), not a Reporter trait in signatures — but JobHandle::with_reports + reporter() is the jera-native way and nothing in dwarves uses it.
2. What dwarves DOES route through jera (16 files, MEASURED)
| subject — STATUS — detail |
agent_bridge.rs / server.rs:891 scheduler_with_local_default — WIRED (placement) — jera::agent::Scheduler used at 12 sites; AgentPool RPC (server.rs:577-585) is the ONE real jera read the server exposes |
engine.rs:41,:97 JobHandle::start(sink, kind::CI_BUILD, …) — PARTIAL — good seam, but NO .with_reports(store.report_sink()), NO job.reporter() into run_pipeline*: per-step progress dies in the local mpsc; and the server never hands it a sink (§3) |
runa_exec.rs:387 JobHandle::start(… CI_BUILD …) — PARTIAL — same; ctx.sink is Some only from the CLI (main.rs:1487, :1755) |
sindri.rs:485-493 tick_scheduled(.., sink: Option<&JobSink>, ..) → :620-628 branches Some ⇒ run_pipeline_cached_job (jera) / None ⇒ run_pipeline_cached — PARTIAL — the seam exists; every server caller passes None |
runa_backend.rs:181,:466 spawn_process / streamed container exec — WIRED (legit) — implements jera::agent::LocalRunner; :424 jera::container::connect_default_runner, :581 jera::vm::default_vm_runner, :639 jera::boot::BootProc; vault.rs:717 injects into jera::container::ContainerSpec |
main.rs:1477,:1743,:1911 JobStore::open(&warehouse.join("jobs")) — WIRED (CLI only) — the only ledger WRITERS in the whole dwarves tree |
dwarves-embed/src/jobsfleet.rs:78 JobStore::open_read_only → Jera tab (dwarves-gui/src/jera.rs:117-128, 2 s poll :31) — BLIND — reads $DWARVES_WAREHOUSE/jobs LOCALLY; mapper jobsfleet.rs:114-133 drops every progress field (no job_reports, no fraction, no phase); falls back to a fixture jera.rs:184-187 and prints "fixture (ledger empty)" :242 |
dwarves-embed/src/pipeline.rs:325-333 — BLIND — second ledger reader, manual reload only (:277,:518,:594) |
dwarves-gui/src/boot_run.rs:2698-2805 jera::container::{ContainerSpec,connect_default_runner}, jera::boot::{BootTarget,BootProc,BootStatus} — PARTIAL — jera as OCI engine behind feature container-run (dwarves-gui/Cargo.toml:201,:313, OFF by default); log drain is live, zero jera jobs rows |
dupes/normalize.rs:495-496 — n/a — test fixture strings mentioning JobStore |
Imported jera items (count of jera::x::Y strings across dwarves): agent::Scheduler 12, container::ContainerSpec 9, jobs::JobSink 7, boot::BootProc 7, jobs::JobStore 5, agent::WorkUnit 5, boot::BootStatus 4, container::connect_default_runner 3, jobs::kind 2, vm::* 5, policy::JobPolicy 1. Zero jobs::Reporter, ReportSink, JobReports, DaemonPhase, BootJobs.
3. THE LIST (a): should-go-through-jera-but-doesn't — with duplication evidence
Server-side None sinks (MEASURED): server.rs:414 (Trigger), server.rs:460 (Webhook), server_cron.rs:106 (cron sweep). sindri.rs:620-628 therefore always takes the non-jera branch in the server.
| subject — STATUS — detail |
crates/dwarves/src/build_thing.rs:936 BuildRun — TWIN (~400-450 lines, INFERRED) — own thread :961/:1189, own mpsc<BuildEvent> :952/:1183, own status fields :941-949, own API is_running :1406/elapsed_ms :1412/status_line :1418/state_json :1428, LOG_CAP :968, side-channels :958,:963. Re-derives JobRecord + Reporter + JobReports + the Drop-guard. Shared vocabulary only (nornir_build_thing::progress::BuildEvent). A 40-min holger build ⇒ NO jobs.redb row |
crates/nornir-warehouse-embed/src/lib.rs:1560 AddWarehouse{status,registered,last_fetch,last_add,last_removed,…} + add :1617/populate :1680/populate_named :1695/remove_named :1652/state_json :1722 — TWIN (~200 lines) — JobRecord{status,detail_json,result_ref} re-typed one field per verb; add() is fully synchronous, no job row, no cancel, no resume |
nornir-warehouse-embed/src/lib.rs:1238 Counter{Known,Pending,Unavailable} + :1287 PopulateProgress (fraction :1332, counters_line :1341) + :1485 poll_populate_progress — TWIN (~165 lines) — line-for-line re-derivation of JobReports::progress_fraction/phase/health + Reporter::progress/phase/health/gauge; fraction is INFERRED from sync_state=="fetching" strings, bytes permanently Unavailable (BYTES_UNAVAILABLE_WHY :1279) because no reporter ever reports them |
dwarves-gui/src/populate_steps.rs:101-282 Phase+phase_of+observe — TWIN (182 lines core of 444) — a stateless phase-INFERENCE machine over edda step-board (shared registry, reused correctly) because the run's position is not durable on a ledger row; the :265-273 "furthest step reached" clamp exists only to paper over that (2026-08-08 red). Dead half :315-346 (to_job_entry/job_entries/state_json, 32 lines): sole caller dwarves-gui/tests/populate_steps_red.rs:384 — the one op with real live step progress is INVISIBLE in the jobs surface (bar lives only in warehouse_select.rs:460-464) |
crates/dwarves/src/server_cron.rs:36-86 CronStore (redb open :41/load :63/save :74) — TWIN (51 lines) — header :16-17 admits "mirroring jera's single-writer jobs.redb pattern"; jera ships JobStore::start_or_resume_daemon (jobs.rs:963) + DaemonPhase + daemon_report_sink (:843). MEASURED live: /home/dwarves/.dwarves/warehouse/ holds cron.redb (mtime 20:18 today) and NO jobs/ — the server writes its twin, never the ledger |
crates/dwarves/src/server.rs:896-921 cron daemon — TWIN (~29 lines) — bare thread::spawn + sleep(60s) :918 + eprintln! :914; should be a jera daemon job (heartbeat/phase/health/last-ran). jera Scheduler used for placement (:891), ledger half absent |
crates/dwarves/src/store.rs:224-300 JSONL run history (append_history :224, read_runs :256, read_steps :276) — TWIN (~80 lines) — self-declared placeholder :9-12; still the ONLY durable record of a server-side run; History RPC (server.rs:245) re-reads+re-sorts the file per call |
crates/dwarves/src/service.rs:579-640 deregister_workspaces_in — TWIN (~62 lines) — opens nornir's "workspaces" redb table directly (:586-587) and wipes trees (:621); Workspaces.Remove{purge} exists and is even proxied (warehouse_proxy.rs:249, client nornir-warehouse-embed/src/lib.rs:1195). Callers service.rs:941,:978 |
crates/dwarves/src/buildthing.rs:603-680 build_cells — TWIN (~60 lines) — own deadline :642, poll loop :644-660 with sleep(POLL_MS) :659, own DWARVES_BUILD_TIMEOUT_SECS :575; ≡ JobStore::list + JobRecord::is_terminal |
SSH-url guard ×3 — TWIN (~40 lines ×2 extra) — repo.rs:146-154 (calls nornir_git::gitio::is_ssh_url/ssh::parse_ssh_url, correct), pipeline_wizard.rs:721 is_blocked_remote/:82 is_ssh_remote, nornir-warehouse-embed/src/lib.rs:772 validate_ssh_remote + :804/:816 name splits; nornir-warehouse-embed/Cargo.toml declares NO nornir-git, NO nornir-workspace dep |
nornir-warehouse-embed/src/lib.rs:829 descriptor_for_ssh — TWIN (~7 lines) — format!-interpolated nornir-workspace.toml, no quoting/validation; nornir_workspace::WorkspaceDescriptor (edda/crates/nornir-workspace/src/descriptor.rs:30) is the type |
coverage/local.rs:35,:81 vs dupes/local.rs:41,:96 read_table/parquet_files — TWIN (~100 lines, self-documented coverage/local.rs:19-23) — not jera, but LAW-5; both bypass the catalog RPC |
server.rs:307 RegisterPipeline → repo.rs:228 add_repo → nornir_git::gitio::clone_or_fetch :230 — NOT-JERA — shared crate YES, no shell; but multi-minute clone in one spawn_blocking :333, no job row, no cancel; registry is in-memory Arc<Mutex<Vec<_>>> :49, lost on restart |
mcp.rs:330/:760 autonom_kick, mcp.rs:259/:284 funnel_submit_idea/funnel_decompose — NOT-JERA — bare spawn_blocking :334/:290; partial failure smuggled as persisted/persist_error :315-321 (ad-hoc fail_with_detail) |
service.rs:393 run_refresh → :487 build_and_pack_head → :530 Command::new("cargo")…status() — NOT-JERA — lifecycle via skidbladnir::install::refresh_product :446 (shared, good); progress println! :526,:551,:558 only |
release_doctor/* cargo shell-outs (publish.rs:784,:1488, cargo.rs:131,:663,:1313, rehearse.rs:412, preflight.rs:2281, undo.rs:342, semver_checks.rs:150, packaging_lint.rs:594, binary_gate.rs:144, release.rs:449) + own pool release_doctor/mod.rs:572,:594 — NOT-JERA — progress ledger IS shared (mod.rs:123 re-exports nornir_release_core::progress) but not jera |
runner.rs:164-172, runa_backend.rs:284-291, build_thing.rs:1117-1125, bench.rs:252 build-record/bench writes via NornirWarehouseSink — GOOD PATH, NOT-JERA — correct Telemetry/Bench RPCs; outcome kept in a bespoke 4-field BuildRecordReceipt (build_thing.rs:606,:907-913) instead of JobHandle::finish/fail_with_detail |
depview.rs:46 discover_repos vs sindri.rs:673 discover_suite_members — TWIN (two dir walks, same rule; sindri.rs doc says "Mirrors the dwarves deps scan") |
main.rs:5951, release_doctor/publish.rs:936 gix::open + status(gix::progress::Discard) — NOT-JERA — progress thrown away rather than piped to a Reporter; bin/dwarves-server.rs:269 own HEAD reader |
Tally (INFERRED): ~1,200 lines of operation plumbing that jera or a shared edda crate already owns. Positive: dwarves never shells git in production code (all Command::new("git") hits are #[cfg(test)]).
4. THE LIST (b): does-go-through-jera — UI progress verdict, naming the seam
| subject — STATUS — detail |
Forge.Trigger/Webhook (server.rs:373,:435) — BLIND — fresh Sindri per call (:409,:456), tick_scheduled(..,None,..); handler blocks for the whole run then re-reads JSONL (:417-422,:461-466); Sindri::state_json (sindri.rs:639) discarded with the closure. No UI affordance calls these RPCs at all — the one server op on the jera scheduler is unreachable from the UI |
cron sweep (server_cron.rs:95) — BLIND — selftest::emit :107-113 is `cfg(testmatrix |
CI/CD wizard "▶ Run (dry)" (dwarves-embed/src/cicdwizard.rs:439-444 → pipeline_wizard::run_preview_with_env → runa_exec) — BLIND + MISLABELLED — hover :442 "dispatch … as jera jobs", :417 "see the Jobs pane (shared jera ledger)", yet pipeline_wizard.rs:497-500 sink: None; :200 prints "ran (dry): N jera job(s) dispatched" from an in-memory report |
Jera tab (dwarves-gui/src/jera.rs) — BLIND — polls a real JobStore every 2 s but (i) the path is LOCAL $DWARVES_WAREHOUSE/jobs (jobsfleet.rs:54-68), (ii) the live server writes nothing there (§3), (iii) mapper drops progress; steady state = "fixture (ledger empty)" |
Pipeline pane ledger read (pipeline.rs:325-333) — BLIND — manual reload only |
Container boot via jera OCI (boot_run.rs:2741-2860) — PARTIAL — LogConsole/ServiceLogConsole drain the jera BootProc live; BootStatus phase text; zero jobs rows (no BootJobs) |
AgentPool RPC (server.rs:577) — WIRED (read) — scheduler.state_json(); consumed by dwarves_embed::holger_build_panel auto-poll viewer (holgerbuild.rs:438-446) |
Seam naming. The wire to close (b) is threefold: (1) a JobStore opened once in serve() (server.rs:873, before the cron thread at :896) whose sink() replaces the three Nones; (2) engine.rs:41/:97 chaining .with_reports(store.report_sink()) and passing job.reporter() into run_pipeline/run_pipeline_cached; (3) a remote read path — either proxy nornir's Viz.Jobs (edda/crates/nornir-wire/proto/nornir.proto:897/:950) and Release.Progress stream (:332) the way warehouse_proxy.rs:245-252 proxies Workspaces.* (today warehouse_proxy.rs has 0 Viz hits; server.rs:1003-1010 mounts Dwarf/Warehouse/Workspaces/Mimir/Telemetry/Bench/Funnel only), or serve a JobSink::remote-backed Jobs RPC on :7900. There is no HTTP/SSE/websocket surface anywhere (tonic + grpc-web only, server.rs:993-1013).
5. Live probe (read-only, MEASURED 2026-08-21 ~20:20 UTC)
| subject — STATUS — detail |
dwarves-server.service — RUNNING — pid 2188704, user dwarves, ExecStart=/home/rickard/git/dwarves/target/release/dwarves-server, started 20:18:49; env DWARVES_WAREHOUSE=/home/dwarves/.dwarves/warehouse, NORNIR_SERVER=http://127.0.0.1:7878, NORNIR_WORKSPACE=nordisk, DWARVES_REAL_RUNNER=1; listens 0.0.0.0:7900 (forge) + 127.0.0.1:7878 (embedded nornir, FAT shape server.rs:763,:862) |
/home/dwarves/.dwarves/warehouse/ — ONLY cron.redb (1.5 MiB, mtime 20:18) — no jobs/, no jobs.redb, no history*.jsonl yet: the server's twin ledger is written on every start; the jera ledger never |
/home/dwarves/.nornir/workspaces/nordisk/builds/jobs.redb — LIVE jera ledger (2.1 MiB, mtime 20:21) — written by the embedded nornir (nornir/src/server_grpc.rs:5936 JobStore::open(warehouse.root()); fetch :5024 wires fetch_workspace_with_progress :4884 + PhaseJobs :4940, republish_with :6165). The populate phases the UI infers by string-matching ALREADY exist as jera rows on the server host — dwarves neither proxies a read of them nor points the Jera tab at them |
/home/rickard/.dwarves/warehouse/ (the desktop user) — cron.redb (2026-08-06), no jobs/ — so the Jera tab on this box reads an absent ledger ⇒ fixture |
Workspaces.PopulateStatus (nornir.proto:1090) — the only server-exposed populate progress read; implemented from the registry (server_grpc.rs:5112 self.reg()?.list()), NOT the jobs ledger — hence the string-matching in PopulateProgress |
6. UI operations sweep (dwarves-gui + embeds), condensed — 29 ops
| subject — STATUS — detail |
Add warehouse (register+populate) warehouse_select.rs:748/:771 → own thread :290-297 → AddWarehouse::add → Workspaces.Register — WIRED (hand-rolled) — step bar :460-464 + clone N% :485-487, repaint :410-412, poll 1.5 s :31; 1 of 3 phases measured (populate_steps.rs:17-26,:210); NOT jera |
Re-sync warehouse_select.rs:619/:634 → Workspaces.Fetch — WIRED (same bar) — NOT jera |
Remove warehouse warehouse_select.rs:803/:820 — PARTIAL — spinner + label :677-681, no phases |
Data view Scan / Run SQL dataview.rs:459,:515 — BLIND + FREEZES UI THREAD — inline in ui(), N sequential gRPC scans |
Dupes Scan / Dry-run / Execute dupes.rs:488,:600,:603 — BLIND + FREEZES |
Coverage Scan coverage.rs:376 — BLIND + FREEZES |
Mímir Lenses Scan mimir_lens.rs:1780 (11 folds) — BLIND + FREEZES |
Warehouse-nav world scan warehouse_nav.rs:73-110 — BLIND + FREEZES (first world build) |
BYGG build_scene.rs:909 → build_forge.rs:401 BuildRun::spawn_with_params — PARTIAL — "BYGGER {s}" build_scene.rs:1019 + log tail (build_forge.rs:697), repaint 120 ms :1226; BuildRun.units/.current/status_line() NEVER read by the demo; no ledger row |
KÖR / START / BOOTA OM / STOPP (boot_run.rs:450-611,:2038) — PARTIAL — live console + BootPhase text; VM legs shell QEMU via tunnr_vm::boot_test :1029..; no ledger row |
edda RAID harness boot_run.rs:2545-2631 — PARTIAL — cargo test stdout streamed |
feature-axis worker build_forge.rs:372 — PARTIAL — Axis::Working only |
Coderoom snapshot-diff / what-breaks coderoom.rs:270-277,:287-299 — BLIND + FREEZES — Command::new(nornir).output() on the render path |
CI/CD Run (dry) cicdwizard.rs:443 — BLIND + mislabelled (§4) |
Funnel Submit nornir-funnel-embed/src/lib.rs:1888 → :1391 + blocking refresh :1406 — BLIND + FREEZES |
Deploy-key probe sweep deploy_key.rs:271-273 — PARTIAL — spinner :117, per-remote mpsc, no N-of-19 |
| Vault unlock/lock, Save .runa.ron, Release Rescan — BLIND (instant, acceptable) |
Pipeline Reload pipeline.rs:505 — BLIND — manual ledger re-read |
Jera Refresh/live jera.rs:225,:234 — viewer (see §4) |
Score: of the ops the rule names (populate/register, workspace add, scan/index, clone, warehouse writes, long jobs) zero route through jera::jobs; every scan is BLIND and blocks the egui thread; build/boot is PARTIAL over a private channel.
7. Ranked gaps (by user-visible pain)
- Server never writes the jera ledger —
server.rs:414,:460,server_cron.rs:106passNone; live/home/dwarves/.dwarves/warehouse/hascron.redbonly. Every Trigger/Webhook/cron run is invisible to any jobs reader; the Jera tab is a fixture by construction. Fix seam: openJobStoreonce inserve()(server.rs:873), threadsink(). - Per-step progress dies in mpsc —
engine.rs:41/:97start aJobHandlewithout.with_reports(store.report_sink())and never passjob.reporter()intorun_pipeline*; 0 uses ofReporter/JobReportsin dwarves. This is the change that makesPopulateProgress/BuildRun's inference deletable rather than merely twinned. - The UI reads the wrong ledger —
jobsfleet.rs:54-68local$DWARVES_WAREHOUSE/jobswhile ops run on the remote host; nornir's live ledger (/home/dwarves/.nornir/workspaces/nordisk/builds/jobs.redb) already has the populate phases. Seam: proxyViz.Jobs(+Release.Progressstream) on:7900likeWorkspaces.*, or aJobSink::remoteJobs RPC; mapper must readjob_reports. - Scans freeze the egui thread —
dataview.rs:459/:515,dupes.rs:488/:600/:603,coverage.rs:376,mimir_lens.rs:1780,coderoom.rs:270-299, funnel:1888: no thread, no spinner, no repaint. Cheapest win: aJobHandle-wrapped worker per scan and a jobs-row spinner; even without jera, off-thread. - Hand-rolled twins (~1,200 lines) —
BuildRun(~450),AddWarehouse+PopulateProgress(~365),populate_stepsinference (182 core + 32 dead),CronStore(51) + cron thread (29), JSONL history (80),deregister_workspaces_in(62),build_cells(60), SSH-guard ×3,descriptor_for_ssh,read_table×2. Plus the false label incicdwizard.rs:417/:442("jera jobs … shared jera ledger") whilepipeline_wizard.rs:499issink: None.
8. Provenance
Inputs: three read-only sweeps (server-side ops; dwarves-ui ops+progress; edda shared- crate surface) reconciled and re-verified by grep at dwarves 0cf9dda in this worktree; facade counts re-measured over <repo>/crates/** per workspace_nordisk cec2b62 (this report does not contradict it: jera is live, dwarves is a heavy consumer for placement/containers/VM; the gap is the ledger + reports half, not adoption). Line estimates prefixed ~ are INFERRED; everything else MEASURED.