A calm place to write long-form, and publish it to the open social web.
skypress.blog/
1# 0008 — Edit semantics (the "puppy problem")
2
3- **Status:** Accepted
4- **Date:** 2026-06-08
5- **Scope:** SP5 — editing and unpublishing a published article
6
7## Context (brief §3)
8
9Bluesky deliberately does **not** auto-refresh stale embeds. When a writer edits a
10published article, the brief asks us to choose and justify one of:
11
121. **Mutate** the existing record — simple, but silently changes shared context (anyone
13 who saw/shared the old version now sees new content under the same link).
142. **Create a new record** — preserves an audit trail, but loses URL stability (the
15 article gets a new rkey → a new URL; old links/cards break).
163. **Version with explicit "edited" markers** — mutate, but be transparent about it.
17
18## Decision
19
20**Mutate the existing record (option 1 + 3): `putRecord` on the same rkey, with an
21explicit `updatedAt` and an "Updated" marker on the reading page.**
22
23- **URL stability wins.** SkyPress URLs are `…/@<handle>/<rkey>` (Decision 0005/0006), and
24 the Bluesky post embeds that URL. Creating a new record would orphan the post's link
25 card and every shared link. Mutating keeps the one canonical URL working.
26- **Transparency mitigates the silent-change downside.** We set `updatedAt` on edit and
27 the reader shows "Updated <date>" alongside "Published <date>". Honest about edits
28 without breaking links.
29- **No new Bluesky post on edit.** Publishing creates the social post once; editing must
30 not spam the timeline. The original post keeps pointing at the (now-updated) article;
31 its card stays stale by Bluesky's design — that's the accepted "puppy problem" cost of
32 option 1, made visible by the `updatedAt` marker.
33- **`publishedAt` and `bskyPostRef` are preserved** across edits (only `content`,
34 `textContent`, `title`, `description`, `updatedAt` change).
35
36A future, heavier option (versioned history records) is left open by the lexicon's
37open-ended design, but is not warranted for v1.
38
39## Unpublish / delete
40
41Deleting an article removes **both** records it owns: the `site.standard.document` and the
42companion `app.bsky.feed.post` (via `deleteRecord`). The `site.standard.publication` is
43left intact (it may front other articles). Blobs become unreferenced and the PDS
44garbage-collects them in time. The UI confirms before deleting, since the Bluesky post
45disappears too.
46
47## Consequences
48
49- Editing requires loading a stored article back into the editor: stored `BlockNode[]`
50 → `@wordpress/blocks.serialize()` → the editor's `onLoad(parse)`. Core blocks are
51 globally registered by the time `onLoad` runs, so this round-trips.
52- `updatedAt` is additive to the lexicon (already a `site.standard.document` field) — no
53 schema change.