# Lab Report — §EDITOR-01-D-FU (a): the visual drag-reorder chain editor **Original status:** DESIGN LOCKED → implementing · **Original date:** 2026-06-27 (mtime `2026-06-27 16:56:37 -0700`) **Ship record:** lock `2430dd0` → inc2 factory `78ca3ae` → inc3 Quest Creator `0198149` → inc4 CRUD form `c2e6892` (closes (a)) · item (b) closed same evening by `de64c16` **Verified:** 2026-08-17 (§DOC-02br) against HEAD and against the reference build `2430dd0` (`edit.html` 10,266 lines) **Verdict:** **SHIPPED IN FULL — 4 of 4 increments in order, in 10 h 11 m.** Every one of the report's **12 line citations is byte-exact**, and §3's integration recipe was executed line for line. Two findings: the "nothing changes on the server" claim is true of the path it measured and false of the one it did not (§7), and the widget's single stated reason to exist has **zero live users** ten weeks on (§11). --- ## Abstract §EDITOR-01-D made quest rewards *declarative*: an `itemChain` array of `grant` / `take` / `grantBit` / `takeBit` steps, applied on completion by `function _applyItemChain(q)@26169`. It shipped that field with a **textarea** and a pipe grammar — `grant|name|icon|type|sell|desc`, one step per line. This report locked the replacement: `buildChainEditor(host, opts)`, a **factory** (not a singleton) returning an independent instance per mount, rendering one `.chain-row` per step with a kind `` · fields container re-rendered on kind change, each input `data-cf=""` · ▲ ▼ · ✕ | | **Kinds** | `grant` (name\* icon type sell desc **once**) · `take` (name\* all) · `grantBit` (flag\* label) · `takeBit` (flag\*) | | **Drop rule** | a row whose required field is blank is dropped, mirroring the codec's `.filter(Boolean)` | | **`once`** | emit `once:false` **only when unchecked** — omission means `true`, keeping serialized JSON minimal | | **`sell`** | `+value \|\| 0`, only when non-empty | | **Reorder** | ▲/▼ canonical and testable; **drag additive** — "if it regresses, ▲/▼ still fully drive the feature" | | **Codec** | `parseItemChainText` / `itemChainToText` **kept** as the canonical Step[] ⇄ text mapping, plus a new parity assertion so widget and grammar cannot silently diverge | The parity clause is the load-bearing one: `buildChainEditor({initial: parseItemChainText(text)}).getSteps()` ≡ `parseItemChainText(text)`, with the widget a strict superset. It shipped as a test (§10). --- ## 5. Line citations — 12 of 12 byte-exact Resolved at `2430dd0`. This ties the corpus record, and it is arguably stronger than the tie: **every citation is the exact insertion point rather than a function declaration**, which is what a design lock is for. | # | Report's claim | Line | Found there | |---|---|---|---| | 1 | `#ed-itemChain` textarea | 8942 | `