workplan: SHARD-WP-0008 write path (overlay engine, writable adapter, apply-under-drift)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 10:28:37 +02:00
parent 9fedb31d8b
commit b2ea276c00

View File

@@ -0,0 +1,135 @@
---
id: SHARD-WP-0008
type: workplan
title: "write path — overlay engine, writable adapter, apply-under-drift"
domain: whynot
repo: shard-wiki
status: active
owner: tegwick
topic_slug: whynot
created: "2026-06-15"
updated: "2026-06-15"
depends_on:
- SHARD-WP-0007
---
# SHARD-WP-0008 — Write path
## Goal
Implement the **write path** on top of the foundation slice (SHARD-WP-0007): the
**overlay-before-mutation** lifecycle (draft → patch → apply-under-drift) plus write-through
for capable shards, faithful to `FederationRequirements.md` ADR-05, `CoreArchitectureBlueprint`
§8.2 (overlay engine) / §8.6 (apply-under-drift) / §8.1 (overlays are coordination-canonical
events). Target capability: **edit a page → draft overlay recorded in the decision log →
apply (fast-forward) to a writable shard, or refuse on drift, or keep as local truth on a
read-only shard**, with `overlay_state` surfaced in provenance (union without erasure).
**Non-goal (this slice):** three-way/auto merge (refuse-on-conflict is enough now), federation
propagation, network API, lossy native-syntax overlays. Those are later.
## Guiding rules
- Overlay-before-mutation (I-5); no silent remote mutation. Detection is core, resolution is
policy (I-7). Overlays/decisions are coordination-canonical (the decision log, §8.1).
- Honour the §11 dependency rule and capability-as-data: write only where the verified profile
supports `WRITE`; everything below write-through degrades to overlay (I-8).
---
## Writable file-store adapter + positive write conformance
```task
id: SHARD-WP-0008-T1
status: todo
priority: high
```
Make `FolderAdapter` optionally **writable** (`writable=True`): declare `WRITE` +
`write_granularity=PER_PAGE` in the profile, implement `write(key, body)` (write-through to
disk, return the updated `Page` with a new rev), and `current_rev(key)` for drift detection.
Extend the conformance suite with a **positive, non-destructive write probe** for adapters that
claim `WRITE` (write a probe key, read back, clean up). Tests: writable round-trip; read-only
folder still rejects write; conformance passes for both.
## Overlay model + OverlayEngine.draft()
```task
id: SHARD-WP-0008-T2
status: todo
priority: high
```
`coordination/overlay.py`: an `Overlay` value type (id, target identity, base_rev, body, state)
and `OverlayEngine.draft(identity, body, base_rev)` that records an `OVERLAY_CREATED` event in
the decision log (coordination-canonical) and returns the draft. The log fold exposes open
overlays. Tests: draft recorded + retrievable via fold; overlay id stable.
## Patch rendering
```task
id: SHARD-WP-0008-T3
status: todo
priority: medium
```
Render an overlay as a reviewable **patch** (a `Patch` with a unified diff of base→overlay body,
Markdown/native). Pure function over (base body, overlay body). Tests: patch shows the change;
empty patch when unchanged.
## apply-under-drift
```task
id: SHARD-WP-0008-T4
status: todo
priority: high
```
`OverlayEngine.apply(overlay_id)` with §8.6 semantics: compare overlay `base_rev` to the
shard's `current_rev`; **unchanged → fast-forward** (write-through via the adapter, record an
applied/`MERGE_DECIDED` event, overlay state → APPLIED); **changed → refuse + re-present** as a
conflict (no silent clobber); **read-only target → stays DRAFT** (local truth, fully attributed).
Tests: ff apply mutates the shard; drift refuses; read-only keeps draft.
## Overlay-aware union read
```task
id: SHARD-WP-0008-T5
status: todo
priority: medium
```
When resolving a page that has an **open overlay**, surface it: the read reflects
`overlay_state=DRAFT` in the provenance envelope and (where policy shows drafts) the overlaid
body as a local projection over the canonical page — never hiding that it is an unapplied
overlay. Tests: page with a draft reads with overlay_state DRAFT; applied/none reads clean.
## Wiring into InformationSpace + integration
```task
id: SHARD-WP-0008-T6
status: todo
priority: medium
```
Add `InformationSpace.edit(name, body)` (write-through if the resolved shard supports WRITE,
else create an overlay), `overlay(name, body)`, and `apply_overlay(id)`. Integration test for
the full path (write-through on a writable shard; overlay→apply fast-forward; drift refusal;
read-only shard keeps a draft). Update SCOPE; `pytest` + pyflakes green.
---
## Acceptance criteria
- `pytest` green, pyflakes clean, no new runtime dependencies.
- Overlay lifecycle works: draft (logged) → patch → apply (fast-forward) / refuse-on-drift /
stay-draft-on-read-only; write-through works for capable shards.
- No silent remote mutation: applying against a drifted/read-only target never clobbers.
- Overlays are coordination-canonical (in the decision log); `overlay_state` is surfaced in
provenance (union without erasure).
- Each task committed; state-hub synced.
## Suggested task order
T1 writable adapter → T2 overlay/draft → T3 patch → T4 apply-under-drift → T5 overlay-aware
read → T6 wiring + integration.