···11+## Context
22+33+The project’s most behavior-heavy paths now sit inside a small number of very large files. `lib/forms.ts` mixes persistence, validation, submission, response review shaping, and export-adjacent concerns. The builder is split across two large, state-heavy components. The public runner combines route state, validation, draft persistence, keyboard behavior, submission, and rendering in one component. Test coverage exists for some pure helpers, but coverage is still sparse around these critical surfaces.
44+55+This change is intentionally phased. The goal is to reduce complexity without introducing large behavior shifts or destabilizing the app. The safest path is to add or strengthen behavior-focused tests first, then extract cohesive seams, then simplify the largest UI surfaces around those seams.
66+77+## Goals / Non-Goals
88+99+**Goals:**
1010+- Reduce responsibility concentration in `lib/forms.ts` by extracting cohesive domain helpers.
1111+- Create smaller, more focused seams inside builder and runner code so future changes do not require editing giant files.
1212+- Add regression coverage around current high-risk form behavior before and during refactors.
1313+- Keep existing user-visible behavior stable while refactoring.
1414+- Sequence work in reviewable phases with clear checkpoints.
1515+1616+**Non-Goals:**
1717+- Re-designing the builder UX or public runner UX.
1818+- Changing persistence models, response schemas, or public API contracts.
1919+- Replacing the current builder or runner architecture in one large rewrite.
2020+- Solving all UI duplication and infrastructure cleanup in the same change.
2121+2222+## Decisions
2323+2424+### 1. Use a test-first seam-extraction approach
2525+Start each phase by locking current behavior with focused tests, then extract the underlying logic into smaller modules.
2626+2727+Why:
2828+- Reduces regression risk while moving logic out of large files.
2929+- Lets the refactor stay product-behavior based rather than implementation-led.
3030+- Makes it easier to stop after each phase with a stable intermediate state.
3131+3232+Alternatives considered:
3333+- Refactor first and backfill tests later: faster initially, but too risky for these high-behavior surfaces.
3434+- Full rewrite of builder/runner: too disruptive and difficult to review safely.
3535+3636+### 2. Start with `lib/forms.ts` before builder and runner splits
3737+Begin by extracting the most cohesive, testable domains out of `lib/forms.ts`, especially response review/response detail shaping and submission-adjacent helpers.
3838+3939+Why:
4040+- `lib/forms.ts` is the central domain bottleneck and affects multiple downstream surfaces.
4141+- Shared helpers created here can simplify both builder and runner work later.
4242+- This phase is lower-risk than starting with the most stateful client components.
4343+4444+Alternatives considered:
4545+- Start with builder splitting: valuable, but the builder depends on several domain helpers that are still too concentrated.
4646+- Start with runner splitting: valuable, but runner state changes are harder to test safely before domain seams improve.
4747+4848+### 3. Split UI surfaces by stateful behavior boundaries, not purely by JSX size
4949+When refactoring builder and runner, split along meaningful responsibility lines such as route state, submission behavior, draft persistence, editor section behavior, and specialized rendering.
5050+5151+Why:
5252+- Avoids moving complexity into many shallow presentational files without reducing coupling.
5353+- Produces seams that are easier to test and reuse.
5454+5555+Alternatives considered:
5656+- Split by arbitrary visual sections only: reduces file size, but often preserves hidden coupling and cross-component state churn.
5757+5858+### 4. Prefer pure helper modules for behavior that feeds multiple UI surfaces
5959+If logic is shared across review pages, exports, builder state mapping, or runner state mapping, extract a pure helper module and test it directly.
6060+6161+Why:
6262+- Shared pure modules give the best payoff for regression coverage.
6363+- Prevents drift between summary/detail/export or between client/server validation paths.
6464+6565+Alternatives considered:
6666+- Keep logic inline near each caller: simpler short term, but increases drift and maintenance cost.
6767+6868+## Risks / Trade-offs
6969+7070+- **Incremental refactors can leave temporary intermediate seams** → Mitigation: keep phases small and behavior-locked with tests before/after extraction.
7171+- **Additional tests may initially feel slower than direct code cleanup** → Mitigation: focus coverage on high-risk behavior rather than snapshot-heavy or implementation-coupled tests.
7272+- **Large files may still remain large after first-phase extractions** → Mitigation: treat the change as phased and measure progress by responsibility reduction, not only raw line count.
7373+- **Builder and runner client-component tests can become brittle** → Mitigation: favor pure helper extraction first and add UI tests only around stable user contracts.
7474+7575+## Migration Plan
7676+7777+1. Add or strengthen behavior-focused tests around existing form-domain behavior.
7878+2. Extract cohesive helpers from `lib/forms.ts` into focused modules with direct tests.
7979+3. Update callers to use the extracted modules while preserving output shapes.
8080+4. Apply the same pattern to builder seams, starting with draft/state mapping logic before larger component splits.
8181+5. Apply the same pattern to public runner seams, starting with route/progress/validation-adjacent helpers where practical.
8282+6. Keep checks green after each phase (`format`, `lint`, `typecheck`, targeted tests, build when needed).
8383+8484+Rollback strategy:
8585+- Because the change is phased and intended to preserve behavior, each phase can be reverted independently by restoring the previous module wiring and keeping the added tests as regression references where still applicable.
8686+8787+## Open Questions
8888+8989+- Which builder subdomain should be extracted first after `lib/forms.ts`: metadata editor behavior, choice/branch rule drafting, or mutation orchestration?
9090+- How much of runner behavior should move into pure helpers versus smaller local hooks/components?
9191+- Whether to add lightweight route-level/API tests during this change or defer them until the core extractions are complete.
···11+## Why
22+33+The core form domain is now concentrated in a few oversized modules: `lib/forms.ts`, the builder surfaces, and the public runner. These areas carry most of the product’s behavior but do not yet have matching module boundaries or regression coverage, which makes routine changes riskier and slows down follow-up work.
44+55+## What Changes
66+77+- Add a phased refactor plan that reduces the size and responsibility spread of `lib/forms.ts`, `components/form-builder.tsx`, `components/form-builder-panels.tsx`, and `components/public-form-runner.tsx`.
88+- Extract cohesive domain helpers from `lib/forms.ts` into smaller, focused modules with stable interfaces.
99+- Break builder and runner behavior into smaller units so state, rendering, and side effects are easier to reason about and test.
1010+- Expand automated test coverage around the current high-risk surfaces before and during refactoring so behavior remains stable.
1111+- Preserve existing user-facing behavior while improving maintainability and regression protection.
1212+1313+## Capabilities
1414+1515+### New Capabilities
1616+- `core-form-maintainability`: Internal quality requirements for module boundaries and regression coverage around the app’s core form flows.
1717+1818+### Modified Capabilities
1919+- None.
2020+2121+## Impact
2222+2323+- Affected code: `lib/forms.ts`, `components/form-builder.tsx`, `components/form-builder-panels.tsx`, `components/public-form-runner.tsx`, related response review/export helpers, and new focused helper modules/tests.
2424+- Affected systems: creator builder flow, public runner flow, response review shaping, and automated test suite coverage.
2525+- No intended API, schema, or user-facing behavior changes.
···11+## ADDED Requirements
22+33+### Requirement: Core form domain logic is isolated into focused modules
44+The system SHALL organize the app’s core form behavior into focused modules so persistence orchestration, submission behavior, response review shaping, builder state logic, and runner state logic are not all concentrated in a single oversized module or component.
55+66+#### Scenario: Domain extraction preserves behavior while reducing responsibility spread
77+- **WHEN** a core form surface is refactored
88+- **THEN** the behavior previously provided by that surface remains available through smaller, focused modules or components with stable inputs and outputs
99+1010+### Requirement: High-risk form flows are protected by behavior-focused automated tests
1111+The system SHALL maintain automated tests around the app’s highest-risk form flows before and during major refactors, especially around form-domain shaping, builder behavior, and public runner behavior.
1212+1313+#### Scenario: Refactor of a high-risk form surface
1414+- **WHEN** a large core form module or component is being decomposed
1515+- **THEN** behavior-focused automated tests cover the affected contracts closely enough to detect regressions during the refactor
1616+1717+### Requirement: Shared answer and route behavior stays consistent across surfaces
1818+The system SHALL keep shared form behavior consistent across the server and UI surfaces that depend on it, including response shaping, route reconstruction, and answer presentation.
1919+2020+#### Scenario: Shared form behavior is used by multiple surfaces
2121+- **WHEN** review pages, exports, builder helpers, or runner helpers rely on the same form-domain behavior
2222+- **THEN** that behavior is provided through shared tested logic rather than reimplemented separately in each surface
···11+## 1. Lock behavior with tests
22+33+- [x] 1.1 Add focused regression tests around the first `lib/forms.ts` behavior slice selected for extraction
44+- [x] 1.2 Add or strengthen tests around the next builder seam selected for extraction
55+- [x] 1.3 Add or strengthen tests around the next public runner seam selected for extraction
66+77+## 2. Reduce `lib/forms.ts` responsibility spread
88+99+- [x] 2.1 Extract a cohesive response/review or submission helper module out of `lib/forms.ts`
1010+- [x] 2.2 Update existing callers to use the new helper module without changing behavior
1111+- [x] 2.3 Remove obsolete duplication or inline logic from `lib/forms.ts`
1212+1313+## 3. Reduce builder complexity
1414+1515+- [x] 3.1 Extract the first focused builder seam into a smaller helper, hook, or component boundary
1616+- [x] 3.2 Keep builder state and mutation behavior covered by tests while simplifying the parent surfaces
1717+- [x] 3.3 Remove obsolete duplication or inline logic from the builder files
1818+1919+## 4. Reduce runner complexity
2020+2121+- [x] 4.1 Extract the first focused runner seam into a smaller helper, hook, or component boundary
2222+- [x] 4.2 Keep runner route, validation, and submission behavior covered by tests while simplifying the parent surface
2323+- [x] 4.3 Remove obsolete duplication or inline logic from the runner file
2424+2525+## 5. Verify stability
2626+2727+- [x] 5.1 Run targeted tests for the extracted seams
2828+- [x] 5.2 Run format, lint, and typecheck
2929+- [x] 5.3 Run a production build before finalizing the change
+26
openspec/specs/core-form-maintainability/spec.md
···11+# core-form-maintainability Specification
22+33+## Purpose
44+TBD - created by archiving change reduce-core-form-complexity. Update Purpose after archive.
55+## Requirements
66+### Requirement: Core form domain logic is isolated into focused modules
77+The system SHALL organize the app’s core form behavior into focused modules so persistence orchestration, submission behavior, response review shaping, builder state logic, and runner state logic are not all concentrated in a single oversized module or component.
88+99+#### Scenario: Domain extraction preserves behavior while reducing responsibility spread
1010+- **WHEN** a core form surface is refactored
1111+- **THEN** the behavior previously provided by that surface remains available through smaller, focused modules or components with stable inputs and outputs
1212+1313+### Requirement: High-risk form flows are protected by behavior-focused automated tests
1414+The system SHALL maintain automated tests around the app’s highest-risk form flows before and during major refactors, especially around form-domain shaping, builder behavior, and public runner behavior.
1515+1616+#### Scenario: Refactor of a high-risk form surface
1717+- **WHEN** a large core form module or component is being decomposed
1818+- **THEN** behavior-focused automated tests cover the affected contracts closely enough to detect regressions during the refactor
1919+2020+### Requirement: Shared answer and route behavior stays consistent across surfaces
2121+The system SHALL keep shared form behavior consistent across the server and UI surfaces that depend on it, including response shaping, route reconstruction, and answer presentation.
2222+2323+#### Scenario: Shared form behavior is used by multiple surfaces
2424+- **WHEN** review pages, exports, builder helpers, or runner helpers rely on the same form-domain behavior
2525+- **THEN** that behavior is provided through shared tested logic rather than reimplemented separately in each surface
2626+