From 4bbadee10082a52973e31e7cfdd18013b9b54215 Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 7 Jun 2026 07:42:41 +0000 Subject: [PATCH] =?UTF-8?q?content:=20crdt-blocks=20regression=20suite=20?= =?UTF-8?q?=E2=80=94=20non-core=20blocks=20through=20flat=20+=20tree=20CRD?= =?UTF-8?q?T=20(738/738)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/content/conformance.sh | 2 +- lib/content/scoreboard.json | 5 +- lib/content/scoreboard.md | 3 +- lib/content/tests/crdt-blocks.sx | 136 +++++++++++++++++++++++++++++++ plans/content-on-sx.md | 8 +- 5 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 lib/content/tests/crdt-blocks.sx diff --git a/lib/content/conformance.sh b/lib/content/conformance.sh index 52eae428..762ec963 100755 --- a/lib/content/conformance.sh +++ b/lib/content/conformance.sh @@ -15,7 +15,7 @@ if [ ! -x "$SX_SERVER" ]; then fi fi -SUITES=(block doc render api meta page page-full markdown text section compose tree-edit move clone query toc anchor outline flatten transform normalize find-replace stats summary index table callout media data wire validate store snapshot crdt crdt-tree crdt-store sync md-import md-doc fed) +SUITES=(block doc render api meta page page-full markdown text section compose tree-edit move clone query toc anchor outline flatten transform normalize find-replace stats summary index table callout media data wire validate store snapshot crdt crdt-tree crdt-blocks crdt-store sync md-import md-doc fed) OUT_JSON="lib/content/scoreboard.json" OUT_MD="lib/content/scoreboard.md" diff --git a/lib/content/scoreboard.json b/lib/content/scoreboard.json index bd3c1bc1..b8c4625b 100644 --- a/lib/content/scoreboard.json +++ b/lib/content/scoreboard.json @@ -35,13 +35,14 @@ "snapshot": {"pass": 20, "fail": 0}, "crdt": {"pass": 34, "fail": 0}, "crdt-tree": {"pass": 17, "fail": 0}, + "crdt-blocks": {"pass": 7, "fail": 0}, "crdt-store": {"pass": 14, "fail": 0}, "sync": {"pass": 14, "fail": 0}, "md-import": {"pass": 38, "fail": 0}, "md-doc": {"pass": 12, "fail": 0}, "fed": {"pass": 20, "fail": 0} }, - "total_pass": 731, + "total_pass": 738, "total_fail": 0, - "total": 731 + "total": 738 } diff --git a/lib/content/scoreboard.md b/lib/content/scoreboard.md index 65aeabd4..9cdf12c2 100644 --- a/lib/content/scoreboard.md +++ b/lib/content/scoreboard.md @@ -39,9 +39,10 @@ _Generated by `lib/content/conformance.sh`_ | snapshot | 20 | 0 | 20 | | crdt | 34 | 0 | 34 | | crdt-tree | 17 | 0 | 17 | +| crdt-blocks | 7 | 0 | 7 | | crdt-store | 14 | 0 | 14 | | sync | 14 | 0 | 14 | | md-import | 38 | 0 | 38 | | md-doc | 12 | 0 | 12 | | fed | 20 | 0 | 20 | -| **Total** | **731** | **0** | **731** | +| **Total** | **738** | **0** | **738** | diff --git a/lib/content/tests/crdt-blocks.sx b/lib/content/tests/crdt-blocks.sx new file mode 100644 index 00000000..7d4619ad --- /dev/null +++ b/lib/content/tests/crdt-blocks.sx @@ -0,0 +1,136 @@ +;; Hardening — non-core block types (callout/table/media/section) survive the +;; flat and tree CvRDT materialise paths (regression for the ct-class-for-type +;; fix: these route through crdt-element->block -> mk-block). + +(st-bootstrap-classes!) +(content-bootstrap-blocks!) +(content-bootstrap-doc!) +(content-bootstrap-render!) +(content-bootstrap-section!) +(content-bootstrap-callout!) +(content-bootstrap-table!) +(content-bootstrap-media!) + +;; ── flat CRDT: callout / table / media leaves ── +(define + s + (crdt-apply-all + (crdt-empty) + (list + (crdt-op-insert + "co" + "callout" + (crdt-pos 1 0) + (list (list "kind" "note") (list "text" "hi")) + 1 + 0) + (crdt-op-insert + "tb" + "table" + (crdt-pos 2 0) + (list (list "headers" (list "A")) (list "rows" (list (list "1")))) + 1 + 0) + (crdt-op-insert + "vid" + "media" + (crdt-pos 3 0) + (list (list "kind" "video") (list "src" "/v.mp4")) + 1 + 0)))) +(content-test + "flat crdt callout render" + (asHTML (crdt-materialize "d" s)) + "
A
1
") +(content-test "flat crdt order" (crdt-order s) (list "co" "tb" "vid")) + +;; ── flat CRDT: callout field via LWW update ── +(define s2 (crdt-update s "co" "text" "edited" 5 1)) +(content-test + "flat crdt callout update" + (str (blk-send (doc-find (crdt-materialize "d" s2) "co") "text")) + "edited") + +;; ── tree CRDT: callout/table inside a section ── +(define + t + (crdt-tree-apply-all + (crdt-empty) + (list + (crdt-tree-op-insert + "sec" + "section" + (crdt-pos 1 0) + "" + (list) + 1 + 0) + (crdt-tree-op-insert + "co" + "callout" + (crdt-pos 1 0) + "sec" + (list (list "kind" "tip") (list "text" "T")) + 1 + 0) + (crdt-tree-op-insert + "tb" + "table" + (crdt-pos 2 0) + "sec" + (list (list "headers" (list "H")) (list "rows" (list))) + 1 + 0)))) +(content-test + "tree crdt nested blocks" + (doc-tree-ids (crdt-tree-materialize "d" t)) + (list "sec" "co" "tb")) +(content-test + "tree crdt nested render" + (asHTML (crdt-tree-materialize "d" t)) + "
H
") + +;; ── tree CRDT: concurrent callout inserts into a section converge ── +(define + base + (crdt-tree-insert + (crdt-empty) + "sec" + "section" + (crdt-pos 1 0) + "" + (list) + 1 + 0)) +(define + rA + (crdt-tree-insert + base + "x" + "callout" + (crdt-pos 5 1) + "sec" + (list (list "kind" "note") (list "text" "A")) + 2 + 1)) +(define + rB + (crdt-tree-insert + base + "y" + "media" + (crdt-pos 5 2) + "sec" + (list (list "kind" "audio") (list "src" "/a.mp3")) + 2 + 2)) +(content-test + "tree crdt mixed converge" + (= + (get (crdt-tree-merge rA rB) :elements) + (get (crdt-tree-merge rB rA) :elements)) + true) +(content-test + "tree crdt mixed ids" + (doc-tree-ids (crdt-tree-materialize "d" (crdt-tree-merge rA rB))) + (list "sec" "x" "y")) diff --git a/plans/content-on-sx.md b/plans/content-on-sx.md index d30126bc..69d5cb74 100644 --- a/plans/content-on-sx.md +++ b/plans/content-on-sx.md @@ -19,7 +19,7 @@ injected adapter, not core. ## Status (rolling) -`bash lib/content/conformance.sh` → **731/731** (Phases 1–4 COMPLETE + ~34 extensions: HTML/SX escaping, Markdown render + import/export incl. tables & frontmatter (full round-trip), CvRDT flat + nested-tree + durable replication, tree-aware validation, snapshot cache, doc metadata, plain-text render, nested block trees + deep editing + flatten + relative reorder, doc stats + summary + multi-doc index, table + callout + media blocks, HTML page wrapper + SEO page, doc composition + id-remap, portable data + wire serialization, block query + transforms + find/replace, TOC + anchored headings + outline, normalization) +`bash lib/content/conformance.sh` → **738/738** (Phases 1–4 COMPLETE + ~34 extensions, hardened: HTML/SX escaping, Markdown render + import/export incl. tables & frontmatter (full round-trip), CvRDT flat + nested-tree + durable replication, tree-aware validation, snapshot cache, doc metadata, plain-text render, nested block trees + deep editing + flatten + relative reorder, doc stats + summary + multi-doc index, table + callout + media blocks, HTML page wrapper + SEO page, doc composition + id-remap, portable data + wire serialization, block query + transforms + find/replace, TOC + anchored headings + outline, normalization) ## Ground rules @@ -113,6 +113,12 @@ lib/content/api.sx ── (content/edit) (content/render) (content/history) ─ ## Progress log +- 2026-06-07 — Hardening: regression suite `crdt-blocks` (7 tests) locking that + non-core block types (callout/table/media/section) survive both the flat and + nested-tree CvRDT materialise paths (insert → merge → materialise → render), + the integration the ct-class-for-type fix repaired. Verified flat + tree, + including concurrent mixed-type inserts into a section converging. Suite + 738/738. - 2026-06-07 — Hardening: fixed `ct-class-for-type` (block.sx) to map all block tags (added section/table/callout/media). Latent bug: `content/from-data` and CRDT materialise of callout/media blocks failed with "unknown block type" (they