OverviewFilesCommitsIssuesDocsReleasesPeers

favela-markdown commits / aba1773

spec: close STRIP_VERSION, dialect and grapheme-as-consensus-hazard
All three existed to make repeated derivation agree. The projection is stored at authoring, so it is never re-derived and none of them are needed. The strip leaves the signing path; STRIP_VERSION survives only as provenance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
aba17737949214ab39daa870e0f40563ee0f5523
by plankatron <fleeky@gmail.com> · 2026-09-05T23:12:33.000Z

Changed files (2) +38 -16

spec/library.md +33 -10
……@@ -267,7 +267,24 @@ signed MST commits to and what any atproto reader sees. `record-vocabulary.md`
267267(delete cascades in the same batch, edit re-derives, the projection is never a source of truth,
268268`sign()` materialises both before signing) are **sync** requirements, not tidiness.
269269
270### 10.3 The strip is consensus-critical — version it, and guard it in band
270### 10.3 ~~The strip is consensus-critical~~ — RESOLVED 2026-09-05: it leaves the signing path
271
272⛔ **Superseded by `record-vocabulary.md` §7.2.** The atproto projection is now a **stored record**,
273derived once at authoring on the author's device. A signer materialises it from a file and **strips
274nothing**, so the strip is no longer inside the signing path and is no longer consensus-critical.
275
276`STRIP_VERSION` survives only as **provenance** — a stamp recording which strip produced a stored
277projection, useful for diagnosis. It is **not** an in-band guard, and an under-versioned peer does not
278refuse the signer role, because there is nothing left for it to get wrong.
279
280`markdown-strip.md` §1's cross-*implementation* determinism argument still stands on its own terms: a
281second implementation must reproduce the vectors to be conformant. That is a **conformance**
282requirement, not a consensus one.
283
284The superseded reasoning follows, because it is why the mechanism was designed and why removing it is
285safe rather than merely convenient:
286
287#### 10.3.1 (superseded) The strip was consensus-critical
271288
272289`signer.js:1-5`: *"because ECDSA here is RFC6979-deterministic, any lease-holder that signs the
273290same linearized view + rev/prev produces byte-identical output."* That byte-identity is what makes
……@@ -287,10 +304,11 @@ OrgEventLog, and the autobee migration guard. It converts a silent fork into a l
287304
288305### 10.4 Two open questions become consensus hazards
289306
290- **Grapheme segmentation is unpinned** (`markdown-strip.md` §9 item 1) and the 300-grapheme
291 truncation (§4.3) happens inside the record that gets **signed**. Two runtimes on different
292 Unicode versions truncate at different byte counts and produce different CIDs. Pin the
293 segmentation algorithm and its Unicode version; treat a bump as a `STRIP_VERSION` bump.
307- ~~**Grapheme segmentation is unpinned**~~ **DOWNGRADED 2026-09-05** — it was a consensus hazard
308 only while every sign re-derived the projection. With the projection **stored** at authoring
309 (`record-vocabulary.md` §7.2) no other peer ever re-derives it, so a runtime with different Unicode
310 tables cannot produce a competing CID. What remains is a **quality** concern: a user editing from a
311 second device may truncate differently. Pinning is still worth doing; it is no longer load-bearing.
294312- **Round-trip byte-identity is not free** the way DAG-CBOR's is. `migrateInline` leans on
295313 *"DAG-CBOR is canonical so the rewrite is byte-identical"* and **asserts** it, skipping any key
296314 whose re-encoded oid differs rather than republishing changed content. Markdown's equivalent —
……@@ -309,12 +327,17 @@ OrgEventLog, and the autobee migration guard. It converts a silent fork into a l
3093273. **Community and list URIs** for `visibility` (§11 #4).
3103284. **Reply visibility inheritance** (§11 #5) — almost certainly inherit, but the failure mode is
311329 publishing to the wrong people, so it must be explicit rather than emergent.
3125. ⚠ **Where `STRIP_VERSION` is stamped — RESOLVED 2026-09-05, but it is only HALF the answer.**
313 hyper-social #43 (2026-08-11) decided **per-record `dialect` versioning** and it was never
314 written. The two are not alternatives:
3305. ~~**Where `STRIP_VERSION` is stamped**~~ **CLOSED 2026-09-05 — the question dissolved.**
331 It was resolved twice in one day and both answers are superseded: first "the room's StateBase",
332 then "that is only half — hyper-social #43 also decided per-record `dialect`". **Neither is
333 needed.** Both existed to make *repeated derivation* agree, and the projection is now derived
334 **once, at authoring, and stored** (`record-vocabulary.md` §7.2). `STRIP_VERSION` remains as
335 provenance on a stored projection; there is no in-band guard and no per-record dialect.
336
337 ★ The lesson worth keeping: **two mechanisms for making a recomputation deterministic were
338 cheaper to delete than to specify — by not recomputing.**
315339
316 | | guards against | scope |
317 |---|---|---|
340---|---|---|
318341 | `STRIP_VERSION` | two peers on different strips signing one room ⇒ **fork** | concurrency, per room |
319342 | per-record `dialect` | a record authored under v1 being re-stripped under v2 | **history**, per record |
320343
spec/markdown-strip.md +5 -6
……@@ -212,12 +212,11 @@ facets that land on the wrong characters only for non-ASCII authors.
212212
213213## 9. Open
214214
2150. ⛔ **Per-record `dialect` versioning — decided 2026-08-11 (hyper-social #43), never written.**
216 Every rule in this document is normative *for one dialect*, and §2.1 says adding an extension is a
217 spec change "because it changes the bytes of every record that uses it". It does worse than that:
218 because the projection is derived on read, a dialect bump **re-strips every record ever written**.
219 A record must therefore state the dialect it was authored under, and `strip()` must take it as an
220 argument. See `library.md` §11 #5. This is a **signature change** to the shipped `strip(source)`.
2150. ~~**Per-record `dialect` versioning**~~ **CLOSED 2026-09-05 — not needed.** hyper-social #43
216 decided it because a dialect bump would re-strip every record. The atproto projection is now
217 **stored** at authoring rather than re-derived at every sign (`record-vocabulary.md` §7.2), so a
218 bump changes what *new* posts strip to and leaves published bytes untouched. `strip()` keeps its
219 `strip(source)` signature — no dialect argument.
221220
2222210b. **"Unknown syntax degrades to literal text" — decided 2026-08-11 (#43), stated but not
223222 normative.** §2 makes the function total and the implementation's fallback branches do emit