generated from coulomb/repo-seed
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:
135
workplans/SHARD-WP-0008-write-path.md
Normal file
135
workplans/SHARD-WP-0008-write-path.md
Normal 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.
|
||||
Reference in New Issue
Block a user