- gotchas.md: de-faking a cursor is not a drop-in -- with-field-default mutates the cursor (transact!) as a render side effect and broke the simple-mode swap; the de-fake belongs with the render-fn rewrite, verified against the swap spec. - scorecard.md: append the Phase 2 (in-progress) Transaction Edit row -- no-cursor 1->0, LOC 1608->1555, parity held (swap 6/6 + Shared Location). Faked roots / snapshot / Selmer / route-collapse remain as the wholesale-rendering continuation of Phase 2.
3.2 KiB
Quality scorecard (the ratchet)
Cheap to measure (grep -c, wc -l, clj-kondo), recorded before/after each
migration in the commit message and in the results table below. No metric may regress
for the touched modal without a written exception in gotchas.md. These are directional
evidence, not targets to game — always paired with the e2e parity gate.
Heuristics
| # | Heuristic | Measure | Target |
|---|---|---|---|
| 1 | Faked cursor positions (not cursors themselves) | grep -cE 'with-cursor|MapCursor\.' re-roots + grep -c 'defn.*-no-cursor' |
→ 0 (top-rooted cursors are fine) |
| 2 | Implicit state merges (snapshot/cursor) | count merge sites | → 0 (forms); explicit put-step only (wizards) |
| 3 | Branching complexity | clj-kondo, or count cond/condp/case/nested if + max depth |
net ↓ |
| 4 | Lines of code | wc -l on the modal's file(s) |
net ↓ |
| 5 | Reuse / cross-form similarity | cookbook components reused; duplicated-block count | reuse ↑, dup ↓ |
| 6 | Route count | count routes for the modal | → 2 (+1 for add-row) |
| 7 | OOB swaps | grep -c hx-swap-oob |
→ 0 unless a justified disjoint-region case is documented |
| 8 | Attribute consistency | mixed :x-/"x-" encodings in migrated template |
→ 0 |
How to measure (copy/paste)
F=src/clj/auto_ap/ssr/<modal>.clj
echo "LOC $(wc -l < $F)"
echo "no-cursor twins $(grep -c 'defn.*-no-cursor' $F)"
echo "faked-cursor roots $(grep -cE 'with-cursor|MapCursor\.' $F)"
echo "snapshot merges $(grep -c ':multi-form-state :snapshot' $F)"
echo "branch forms $(grep -cE '\(cond |\(condp |\(case |\(when-not ' $F)"
echo "hx-swap-oob $(grep -c 'hx-swap-oob' $F)"
echo "mixed string hx- $(grep -cE '\"hx-[a-z]' $F)"
# route count: count this modal's entries in src/cljc/auto_ap/routes/*.cljc
Results
Each migration appends one row (after-numbers), referencing the before in the diff.
| Phase | Modal | LOC | Routes | no-cursor twins | faked roots | snapshot merges | OOB | mixed hx- | cookbook reused / added |
|---|---|---|---|---|---|---|---|---|---|
| 1 (baseline) | Transaction Edit transaction/edit.clj |
1608 | ~12 | 1 | 2 | ~75 | 0 | 8 | — / seeded 7 entries |
| 2 (in progress) | Transaction Edit transaction/edit.clj |
1555 | ~12 | 0 | 2 | ~75 | 0 | 8 | — / 0 |
Phase 2 progress (partial). Achieved with parity held (swap spec 6/6 + Shared Location green): deleted the dead
*-no-cursor*twin (no-cursor 1→0, −53 LOC) and fixed a real production bug (:modeleaking into the upsert → 500 on every advanced manual save). Still open for this modal — and intentionally not forced under parity risk: faked cursor roots (2 — de-faking needs the render-fn rewrite, seegotchas.md), the snapshot round-trip (~75 — removed by the wizard→plain-form reclassification), Selmer conversion of the render fns, and route collapse (~12 → ~3). These are the bulk of the modal migration and require restructuring the modal's rendering wholesale rather than isolated edits; track as the continuation of Phase 2.