# LLM Codegen Standard: UI State Architecture

Use this file as a hard contract when generating UI code in this repository.

## Scope

- Applies to all generated UI code that manages shared state.
- Applies regardless of framework choice.
- If project constraints conflict, prefer this document and leave a TODO note for any unresolved conflict.

## Primary objective

Generate UI code with one clear source of truth for shared state, predictable DOM updates, and testable side effects.

## Non-negotiable rules

- MUST keep shared UI state in a reducer-style store.
- MUST keep local, transient widget/form values in the DOM unless multiple areas depend on them.
- MUST reconcile UI from current state after each dispatch.
- MUST isolate side effects from pure reconciliation logic.
- MUST keep reconciler sections small and concern-specific.
- MUST NOT duplicate the same state in both DOM and store without a documented reason.
- MUST NOT place service calls, auth logic, or network calls inside pure render reconciliation.
- MUST NOT depend on DOM reads as the normal source of state truth.

## State ownership contract

Classify every value before implementation:

- Store-managed values:
  - View/workflow mode.
  - Busy/loading/error flags that affect multiple elements.
  - Permission/editability constraints used by multiple sections.
  - Any value consumed by more than one component/section.

- DOM-owned values:
  - Input field values local to one form.
  - Local expand/collapse and helper control state.
  - Transient local interaction state not needed outside one component.

If uncertain: default to DOM-owned first, then lift to store only when cross-area coupling appears.

## Required architecture pattern

Generated code MUST include equivalent modules for:

1. State types
2. Action types
3. Reducer
4. Store (`dispatch`, `getState`, `subscribe`)
5. Reconciliation sections
6. Side-effect handler(s) keyed by action

Equivalent filenames are allowed based on the target language/project layout.

## Reconciliation contract

- MUST render from `(state, prevState, action)` inputs.
- MUST be idempotent.
- MUST only update elements owned by that section.
- SHOULD cache stable element references per section.
- SHOULD avoid one giant render function.

Recommended helper:

```ts
function makeSection<E>(
  resolve: () => E,
  render: (els: E, state: AppState, prev: AppState, action?: AppAction) => void
): (state: AppState, prev: AppState, action?: AppAction) => void {
  let els: E | null = null;
  return (state, prev, action) => {
    if (!els) els = resolve();
    render(els as E, state, prev, action);
  };
}
```

## Side-effects contract

- MUST run focus/scroll/init/reset only from explicit action transitions.
- MUST keep side effects outside pure render sections.
- SHOULD implement side effects in one dedicated module to simplify tests.
- MUST guard one-time initialization by action type or previous state checks.

## Action and naming rules

- Action names MUST be explicit and domain meaningful (for example, `SET_VIEW_MODE`, `SET_BUSY_STATE`, `SET_EDIT_MODE`).
- Boolean flags SHOULD use `is/has/can` prefixes.
- UI gating fields SHOULD be positive where possible (`canSubmit` instead of `cannotSubmit`).
- Event handlers MUST dispatch actions, then rely on reconciliation to update UI.

## Async and busy-state policy

- MUST represent async busy state in store when it affects more than one control.
- SHOULD use reference counting (`busyCount`) when concurrent operations are possible.
- MUST gate interactive controls through reconciliation, not ad hoc event-level disabling.

## Forbidden patterns

- Two-way binding every input to global store by default.
- Store updates triggered from inside presentational components without host dispatch.
- Mixing reducer mutation with DOM writes in one function.
- Global document broadcast events as the primary host-to-component state sync mechanism when direct APIs are available.

## Minimum test requirements for generated code

- Reducer tests:
  - initial state
  - each action transition
  - no-op and edge cases
- Reconciler tests:
  - visibility/enabled/text output for representative state snapshots
- Side-effect tests:
  - effects fire only on intended actions/transitions
- Integration tests:
  - user event -> dispatch -> reconciled output path

## Generation acceptance checklist

Before finalizing generated code, verify:

- Exactly one source of truth per state value.
- No side effects inside pure reconciliation functions.
- No service/auth/network calls in reducer/reconciliation.
- Reconciliation is sectioned by concern.
- Tests cover reducer, reconciliation, and side effects.

## Prompt contract for future LLM sessions

Use this prompt block when asking an LLM to generate UI state code:

```text
Follow repository standard: documentation/llm-codegen-standards/ui-state-architecture.md.
Generate reducer-style shared state, sectioned reconciliation, and action-scoped side effects.
Keep local form/widget values in DOM unless cross-area state is required.
Do not place service/auth/network logic inside reconciliation.
Include reducer tests, reconciliation tests, and side-effect tests.
```
