a2d8517668511f15f2e9dca26d46c2ec91ed3251
Adversarial review of Phase 6 found the engine's coupling had relocated rather than dissolved: every wizard consumer had to hand-build a decode allowlist, re-implement the open-handler modal wrap, mint temp ids for added rows, and hand-roll the nav buttons + Enter guard. The engine had the information to prevent all four. Now it does: - handle-step-submit strips its own nav fields (wizard-id/current-step/direction) from form-params before calling a step's :decode -- no per-consumer allowlist, and they can no longer leak into the saved entity (the Phase-6 "500 on save" class of bug is structurally impossible). - open-wizard takes an :open-response config fn and owns the create!/render/wrap/thread flow, so modal wizards route through (partial wizard2/open-wizard config) directly. - wizard2/blank-row supplies a temp :db/id (+ :new?) so an added row passes schema validation and the step actually advances. - wizard2/nav-footer emits the direction buttons (Back/advance/Save), marks the primary, and wizard-form guards Enter to trigger the primary button. Consumer (transaction_rules.clj) gets correspondingly leaner: deleted rule-form-keys + the decode allowlist, rule-nav, and the hand-rolled open-rule-wizard; new/edit routes are now (partial wizard2/open-wizard config). A new wizard is now just a config map + the step :render fns. LOC 964 -> 932, and the deleted code was exactly the cross-consumer boilerplate, not modal-specific logic. Verification: rule spec 4/4; full suite 55/55; cljfmt clean. Skill gotchas updated from "three traps" to "use the engine's primitives" (the engine now absorbs them). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Description
No description provided
Languages
Clojure
90.9%
CSS
4.2%
Sass
2.3%
HTML
1.3%
HCL
0.4%
Other
0.7%