Distributed project state — verified landing
The monolithic project index was replaced as the write store by independently versioned semantic resources. Compatibility reads remain composed; aggregate writes are rejected after marker activation.
Storage and composition
| Resource | Canonical store | Concurrency |
|---|---|---|
| Sprint | docs/sprints/<id>.html | Independent version + narrow file lock |
| Milestone | docs/milestones/<id>.html | Independent version + narrow file lock |
| Blocker | docs/blockers/<id>.html | Independent version; reference count derived |
| Timeline | docs/state/<project>/timeline.html | Append-only events with deterministic ids |
| Project | docs/state/<project>/project.json | Identity and presentation only |
Sprint item lifecycle status and implementation fraction are resolved from live plan HTML. The active sprint id is derived from the unique active sprint; zero is valid and multiple active resources fail audit/composition.
Migration evidence
- Source index SHA-256:
f6aa91f66811d4b1f6ee6898ad0d081a2c41523fe029933105cc3182877e915e. - Snapshot is byte-identical under
docs/.reckon/snapshots/project-state/. - Composed durable-state parity SHA-256:
11edeeebb748…. - Seven installed resources: four sprints, one blocker, one timeline, and one project manifest.
- The completion marker is the strict read/write boundary and is published last; source mutation and installation-failure tests restore every destination and leave legacy mode canonical.
- Recovery journals contain validated resource identities rather than repository-controlled paths, are durably published, and never roll back a committed move.
Verification
Independent review identified format-boundary, rollback, recovery-race, durability, HTTP symmetry, parity, and reference-validation gaps in the initial landing. Commit 40e6cd6 closes those findings with regression coverage.
Final review found three narrower boundaries: markerless discovery still preferred project.json, simultaneous activation could race across different sprint files, and a static projection suppressed discovery failures other than 404. Commit a837fc7 makes the legacy index exclusive, locks only transitions into active status, and behavior-tests explicit static-hosting fallback.
| Gate | Result |
|---|---|
| Distributed storage/concurrency/migration tests | 41 included in full suite |
| Targeted concurrency and legacy precedence | 5 passed in 8.73 s |
| Executable SPA fallback scenarios | 2 passed in 0.58 s |
| Storage, typed-resource, MCP, edit, and build integration | 146 passed |
| Complete test suite | 1,349 passed in 29.86 s |
| Ruff | clean |
| Schema regeneration | committed parity |
| Legacy index preservation | byte-identical |
Concurrent same-resource writers produce exactly one winner and one version conflict. Concurrent migrations serialize globally, concurrent recovery readers restore a prepared move exactly once, and committed journals are removed without rollback. HTTP, MCP, and SPA paths reject stale legacy fallback after distributed activation.