From 107a02f4f1b24320721707a11163688131135edb Mon Sep 17 00:00:00 2001 From: Bryce Date: Thu, 25 Jun 2026 11:12:33 -0700 Subject: [PATCH] =?UTF-8?q?refactor(ssr):=20Phase=206b=20=E2=80=94=20migra?= =?UTF-8?q?te=20Transaction=20Rule=20wizard=20onto=20the=20session=20engin?= =?UTF-8?q?e;=20de-cursor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Proves the Phase-6a wizard engine against a real 2-step modal: the Transaction Rule wizard (edit step + read-only test/preview step) now runs on wizard2 / wizard-state, fully de-cursored. What changed - Wizard machinery removed: deleted the EditModal / TestModal / TransactionRuleWizard defrecords (mm/ModalWizardStep + LinearModalWizard), MultiStepFormState, the EDN snapshot, and the step-params[...] prefix. Replaced with a data-driven `transaction-rule-wizard-config` (two steps + init-fn + done-fn) driven by the engine. - De-cursored the whole edit form (82 fc/ refs -> 0): every field reads explicit data + path->name2; errors via a bound *errors* / ferr. The account row's Alpine cross-field dispatch wiring (clientId -> accountId -> location) is preserved verbatim — only the data plumbing moved off the cursor. - The test step's :render reads :all-data (the engine's get-all), so the formtools "combine at the end" mechanism feeds the preview table. - Routes 4 -> 2: open-rule-wizard (new + edit), save-step (every transition via the engine's `direction` field). The dedicated `navigate` route is deleted. - decode-rule-form select-keys to the schema's known keys so the engine's nav fields (wizard-id/current-step/direction) don't leak into the upserted entity. Scorecard (admin/transaction_rules.clj): fc/ 82->0, mm/ 20->0, defrecords 3->0, LOC 1000->964, routes 4->2. Scope note: the de-cursored edit step keeps com/* Hiccup leaf components (not yet sc/* Selmer); the value here was removing fc/ + mm/ and proving the engine, not re-templating the conditional/Alpine-cross-field layout. Hiccup-in-render is a documented partial; the com/ -> sc/ swap is a mechanical follow-up. Verification: rule spec 4/4 (new + edit dialogs, advance-to-test preview, save); full Playwright suite 55/55; cljfmt clean. Skill fed: scorecard row + narrative (engine's first real modal; generalizes for a one-data-step wizard); gotchas (strip engine nav fields in decode, new-row temp-id, direction-button nav). Co-Authored-By: Claude Opus 4.8 --- .../ssr-form-migration/reference/gotchas.md | 18 + .../ssr-form-migration/reference/scorecard.md | 26 + e2e/transaction-rule.spec.ts | 8 +- .../auto_ap/ssr/admin/transaction_rules.clj | 666 +++++++++--------- .../routes/admin/transaction_rules.cljc | 1 - 5 files changed, 363 insertions(+), 356 deletions(-) diff --git a/.claude/skills/ssr-form-migration/reference/gotchas.md b/.claude/skills/ssr-form-migration/reference/gotchas.md index 8881fbf6..8e62f904 100644 --- a/.claude/skills/ssr-form-migration/reference/gotchas.md +++ b/.claude/skills/ssr-form-migration/reference/gotchas.md @@ -265,6 +265,24 @@ carve-out. Verify with `load-file` (compile) + `lein cljfmt check`, not by eyeba diff is contained with `git diff -U0 | grep '^@@'` — the hunks should cluster only where you edited (requires + the modal region), nothing else. +## Wiring a modal onto the wizard2 engine — three traps that cost a debug cycle each + +1. **Strip the engine's nav fields in the step `:decode`.** The posted form carries + `wizard-id` / `current-step` / `direction` alongside the real fields. If the step schema is + an open `:map` (most are), `mc/decode` keeps them, they ride into `get-all`, and the save's + `:upsert-entity` dies with `:db.error/not-an-entity ... :current-step`. Fix: `select-keys` + the decode to the schema's known top-level keys (the same allowlist trick as the flat-form + migrations). Symptom is a **500 on save**, not a validation message. +2. **New repeated-row needs a temp `:db/id` or the step can't advance.** If the row schema + requires `[:db/id [:or entity-id temp-id]]`, an added row with no id fails per-step + validation, so the engine re-renders the *same* step instead of advancing — looks like "the + Next/Test button does nothing." Give new rows `(str (java.util.UUID/randomUUID))`. +3. **Nav is a `direction` field, and Back/Save are both submit buttons.** The footer buttons + are plain `