Commit Graph
2 Commits
Author SHA1 Message Date
Omar Sobh 5c19c60292 Phase 1a: cluster module + LAN-first peer probe
First cut of the v2 distributed FS. Captures the architecture design
in ARCHITECTURE-v2.md and lands the smallest useful new capability:
probing cluster peers with a LAN-first policy so subsequent transport
+ gossip layers (Phase 1b, 1c) can build on a real routing decision.

New:
- ARCHITECTURE-v2.md: zones (fabric-10g/lan-1g/roaming), tier
  lifecycle (hot/warm/cold), fingerprint-keyed build cache design,
  smart-clean policy, phase plan, explicit non-goals.
- claw-store/src/cluster.rs: RouteKind, RouteWinner, LanFirstProbe.
  LAN 200ms timeout, Tailscale 500ms fallback. 8 tests use real
  TCP listeners on 127.0.0.1 (no mocks); cover happy path,
  fall-through, both-fail, single-address, and elapsed reporting.
- claw-store/src/config.rs: ClusterConfig + PeerEntry with
  validation (bind-address presence, no duplicate peer names,
  per-peer reachable address required). Optional at top level so
  pre-v2 configs still load unchanged. 6 new tests.
- claw-store/src/main.rs: `claw-store cluster-probe <peer>` CLI
  subcommand that reads config, resolves the peer, probes, prints
  the winning route + elapsed time.

All 16 new tests pass. Existing 45 pass. Sole failure
(hot::tests::test_project_target_size_bytes) is a pre-existing
macOS-only issue with `du -sb`; Linux CI unaffected.

Follow-on Phase 1 cuts (subsequent sessions):
- 1b: chitchat SWIM gossip for live membership state
- 1c: quinn QUIC transport with fleet-CA mTLS
- 1d: `claw-store cluster status` — live membership view

Every file well under the 1300-line ceiling
(cluster.rs 268, config.rs 428, main.rs 450).
2026-07-11 21:30:50 -07:00
Omar Sobh 643ba170b6 daemon: proactively deactivate stale (>48h idle) projects each tick
Answers a real operational question — 'why does /hot/targets stay near
full even when I haven't touched most of these projects for weeks?'
Previously the stale sweep was gated behind 'hot tier > 90% full', so
an idle project held NVMe until the operator manually deactivated it
or space ran out and LRU came for it.

The change:
  * new claw-store/src/actions.rs — shared deactivate_project(cfg,
    manifest_path, project) with the FULL flow: sync-to-peer +
    hot rm + .cargo/config.toml removal + manifest update, plus a
    DeactivateOutcome { synced, sync_error, freed_bytes } return.
    Extracted from main.rs::cmd_deactivate so both CLI and daemon
    run the same code — no drift between manual and auto semantics.
  * daemon.rs poll_tick now runs the stale sweep on EVERY tick,
    independent of space pressure. Each project idle > stale_hours
    (48 by config) goes through the full deactivate, logs
    'stale-gc: X freed N MB (synced=Y)'.
  * gc_by_space (LRU) still gates on >90% full — it's the emergency
    'even after the stale sweep we're still tight' path.
  * main.rs cmd_deactivate is now a thin CLI wrapper that adds
    println! feedback + reports freed MB in the terminal output.

Space-pressure LRU keeps its original .cargo/config.toml-preserving
semantics (rm hot only, not the shim) so a project marked 'active'
by manual activation but hard-evicted for space can still be
re-activated cheaply. Stale sweep is the aggressive one because the
project genuinely hasn't been touched.

Tests: two new unit tests in actions.rs cover the full flow +
idempotency; the freed_bytes assertion is Linux-only-safe (BSD du
returns 0 for -sb, same limitation as the existing hot test).
2026-07-02 16:57:44 -07:00