tasks.md 3.3 KB

1. Lib: repair primitive (src/event_graph/mod.rs)

  • 1.1 Add EventGraph::dag_repair(dag_ts) reusing sync_impl's peer-query/body-fetch machinery but skipping the missing-tips early return (always issue HeaderReq(our_tips) to all peers, insert returned headers via header_dag_insert, then run fetch_missing_events). Verify with a unit test in src/event_graph/tests.rs: node A and B hold a DAG where B is missing a mid-history branch (not an ancestor of B's tips) but holds all tips; dag_repair commits the branch on B.
  • 1.2 Make per-event commit failures in the repair body-fetch phase lenient (log + skip + count, return Ok with counts) instead of the strict DagSyncFailed used by initial sync. Verify with a unit test: one peer serves a header but no blob for one event; repair commits the rest and reports the skip.
  • 1.3 Run make test (proofs + contracts must be prebuilt) and confirm the full event_graph test suite passes, including existing dag_sync/fetch_missing_events strict-path tests (behavior of initial sync unchanged).

2. App: repair task and triggers (bin/app/src/plugin/darkirc.rs)

  • 2.1 Add a repair_sync task mirroring catch_up_sync's shape: waits on an in-flight guard + trigger latch, requires event_graph.is_synced(), calls dag_repair for current_genesis, never touches the synced flag. Verify by code review against design D3 and by a desktop debug run (make compile-dev) showing the repair start/complete log lines.
  • 2.2 Wire triggers: screen_changed(screen_on=true), darkirc_start slot, a subscribe_channel watcher firing on peers 0→≥1, and a periodic timer (REPAIR_INTERVAL, 15 min constant). Triggers during an in-flight round are latched, not dropped. Verify with a debug build log showing coalescing (one round despite three simultaneous triggers) and periodic rounds firing idle.
  • 2.3 Emit observability per spec: round start (slot id + trigger source) and completion (headers gained, bodies committed, skipped count). Verify the log lines appear in a debug run.

3. End-to-end verification

  • 3.1 Reproduce the incident shape locally (models both mobile screen-off and laptop lid-close resume): run two desktop nodes + seed, suspend node B's connections entirely (stop outbound), generate traffic on a branch B will not receive via gossip, resume B, and verify B's history converges to A's within one repair round (diff the two nodes' order_events() output). Repeat with B's process itself frozen (SIGSTOP) across the gap to model OS suspend with no wake signal, verifying the peer-recovery/periodic triggers fire the repair.
  • 3.2 Verify no regression on resume cost: with no gap (B current), a repair round issues only the header exchange and fetches zero bodies (log shows 0 committed), and live EventPut ingestion is never blocked during a round (send traffic through B while a round runs; messages relay to the UI).
  • 3.3 Compile checks: make compile-dev (desktop) and make compile-apk (android) both succeed; make clippy clean.