Files
integreat/.claude/skills/ssr-form-migration/reference/scorecard.md
Bryce 0f5650b73e refactor(ssr): collapse 5 manual-coding operation routes into edit-form-changed (heuristic 6)
The 5 manual-coding operations (vendor change, simple/advanced toggle, add row, remove
row, $/% toggle) each had their own route + handler, all doing "mutate form state ->
render-full-form". Fold them into the single edit-form-changed endpoint, which now
dispatches on an `op` form-param to the relevant pure apply-* mutation fn (apply-vendor-
changed / apply-toggle-mode / apply-new-account / apply-remove-account /
apply-toggle-amount-mode) then re-renders. A missing/unknown op (a plain dependent-field
change, e.g. account->location or amount->totals) just re-renders, as before.

- edit.clj: 6 handlers -> 1 dispatcher + 5 pure apply-* fns; markup posts to
  edit-form-changed with :hx-vals {:op "..."}.
- routes/transactions.cljc: remove the 5 now-unused route keys.
- e2e specs: retarget the vendor selector by op (div[hx-vals*="vendor-changed"]) and
  point the toggle-amount-mode / vendor response waits at edit-form-changed, since the
  old per-op route names are gone. (Behavioral assertions unchanged.)

Scorecard: manual-coding routes ~10 -> ~5 (operations now one dispatcher). Parity held:
swap spec 6/6, full suite 32 pass (Shared Location green; no new regression).
2026-06-03 07:07:52 -07:00

3.3 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 ~1530 ~5 0 0 ~75 0 8 — / 0

Phase 2 progress (partial). Achieved with parity held (swap spec 6/6 + Shared Location green, full suite 31 pass / no regression): deleted the dead *-no-cursor* twin (no-cursor 1→0), de-faked the simple-mode cursor (faked roots 2→0) by rendering the row from explicit data with explicit field names (account-field-name) + explicit error lookup — the render-fn rewrite the with-field-default shortcut couldn't do — and fixed a real production bug (:mode leaking into the upsert → 500 on every advanced manual save). Still open for this modal: the snapshot round-trip (~75 — removed by the wizard→plain-form reclassification), Selmer conversion of the render fns, and route collapse (~12 → ~3). These remain the bulk of the migration and need wholesale restructuring of the modal's rendering; track as the continuation of Phase 2.