Skip to content

v5.10.0 — Backend-aware harness state via the storage seam

Latest

Choose a tag to compare

@alexherrero alexherrero released this 19 Jun 21:13
· 42 commits to main since this release

MINOR. Harness state I/O is backend-aware again. harness_state_dir / read_state_file / write_state_file route to <vault>/projects/<slug>/_harness/ when a live synced backend is active and gracefully degrade to device-local <project_root>/.harness/ otherwise — reversing ADR 0018 DC-1's device-local-only state I/O while keeping every other V5-3 decision (DC-2–DC-7) intact.

The discriminator is backend.capabilities.sync on the backend resolve_project already returns (duck-typed — the kernel never imports the vault plugin), not the presence of a vault_path config key. Precedence: a .harness/.project-mode=local opt-out wins, then a synced backend → vault, else device-local. This is not a return to the pre-V5-3 vault_path() probe-and-prefer tier — it routes through the V5-6 resolve_project seam.

It fixes the surfacing regression where an operator on a synced backend kept their PLAN/ROADMAP/progress in the vault but the kernel read the empty device-local .harness/, so the SessionStart hook never injected them. Storage-seam no-Path-leak and import-direction gates remain green (the three state functions are outside the gate's routing-function set by design).

Changed

  • Backend-aware harness state — harness_state_dir / read_state_file / write_state_file (ADR 0020, reverses ADR 0018 DC-1). New private helper _state_backend_target(resolution) is the single routing decision: returns (backend, harness_locator, backend_root) when a synced backend should serve state, else None (device-local). Gated by _read_project_mode(resolution) == "local" (opt-out wins) → resolution["backend"].capabilities.sync (any exception → None, graceful degradation). Vault-absent / fresh-install / selection-raises all collapse to device-local through the existing resolve_project graceful path.

  • Session-start hooks co-locate progress.md with the resolved PLAN.md (.sh + .ps1). harness-context-session-start.{sh,ps1} previously hardcoded progress.md to the device-local <cwd>/.harness/, which blocked the singleton injection on a synced backend even after the kernel fix. They now derive progress.md as the sibling of whatever _harness/ the bridge resolved PLAN.md into, falling back to the device-local path only when no singleton plan resolved.

Internal

  • ADR 0020 — Backend-aware harness state. New decision record with DC-1–DC-6, full Consequences (positive / negative / load-bearing assumptions with re-audit triggers) and Related. ADR 0018 gains an Amendment — 2026-06-19 section recording that DC-1 is reversed while DC-2–DC-7 stand.

  • Tests — backend routing coverage. test_harness_memory.py gains TestStateBackendRouting (7 cases) plus a CLI vault-wins-over-stale-repo case with OBSIDIAN_VAULT_SCRIPTS pinned for deterministic plugin selection; test_queue_status_lite.py gains test_synced_backend_returns_vault. Vault fixtures seed LF-only bytes (write_bytes) so the byte-exact VaultBackend read is stable on Windows. CI green across Linux / Mac / Windows.