# Theme override maintainer guide

This directory owns the FI theme override contract and the package implementation that turns
persisted FI intent into concrete platform theme values. Consumer usage belongs in the
[`@cdx-ui/styles` README](../../README.md); the full payload and ownership contract is documented in
[Override Structure](../../../../docs/internal/token-architecture/14-override-structure.md).

## Runtime flow

The public path is parse → expand → evaluate → adapt:

1. `parseThemeOverride(unknown)` validates metadata and known fields, rejects unsafe structures,
   and preserves additive unknown fields for authoring tools.
2. `expandThemeOverride(unknown, platform)` parses when needed, loads the selected preset, applies
   inputs, expands named selections, applies direct overrides last, resolves references, and
   evaluates rules.
3. A successful expansion contains complete concrete `resolved` state, sparse `writes`, explicit
   `writtenKeys`, provenance, diagnostics, and the generated artifact revision.
4. Adapters outside this directory consume the expansion. `applyThemeOverride` writes valid sparse
   output through Uniwind; MUI and preview consumers use the same expanded state.

Parsing, expansion, and error-level rule evaluation finish before an adapter writes anything.
Invalid payloads therefore produce no partial theme writes.

## File ownership

Shared package infrastructure used by this directory:

- `../constants.ts` — package-wide preset, mode, platform, schema, default-preset, and protocol
  constants.
- `../utils/common.ts` — generic object/JSON helpers (`isRecord`, `hasOwn`, `hasExactKeys`, and
  `cloneJson`).
- `../utils/color.ts` — shared RGB/RGBA canonicalization, CSS color parsing, sRGB conversion,
  luminance, and contrast helpers.

Override-owned modules:

- `index.ts` — public override barrel used by the package entry points.
- `contracts.ts` — public payload, expansion, catalog, rule, diagnostic, and adapter types.
- `catalogDefinitions.ts` — authored input, source-set, selection, and recipe declarations.
- `catalogAuthoring.ts` — private authoring types and target-list builders used by the catalog.
- `ruleDefinitions.ts` — authored and catalog-derived package rule policy.
- `diagnostics.ts` — diagnostic registry and construction.
- `artifacts.ts` — generated artifact loading, runtime catalog queries, and runtime data assembly.
- `presetWalker.ts` — expression discovery from shipped preset JSON.
- `parser.ts` — validation and preservation of untrusted payloads.
- `expand.ts` — expansion orchestration, precedence, resolution, provenance, and output assembly.
- `recipeEngine.ts` — named-selection recipe algorithms.
- `ruleEvaluation.ts` — intent and resolved-state rule algorithms.
- `rules.ts` — public evaluator facade and candidate evaluation.
- `inputTransforms.ts` — input fallback transform registry.

Private override fixtures live under `src/__tests__/override/`, not in this production directory.

## Public and private boundaries

Only exports reachable through `override/index.ts` and the package entry points are supported
TypeScript API. The public surface includes contracts, parsing, expansion, runtime catalog queries,
rule evaluation, and adapter-facing data. Authored catalog/rule definitions, protocol metadata,
implementation algorithms, and shared utility modules are package-private even though the build
and generator consume them.

Do not expose a private module merely to reuse its implementation in a consumer. Add a deliberate
public facade or contract when a supported consumer capability is required.

## Generated artifacts

`scripts/generate-override-artifacts.mjs` validates authored definitions and materializes
`runtime/override-artifacts.json`. The artifact contains primitive values, target metadata,
catalogs, recipes, rules, font mappings, managed targets, and a deterministic SHA-256 revision.
The generator orchestrates this data; policy stays in `catalogDefinitions.ts` and
`ruleDefinitions.ts`.

Never edit `runtime/override-artifacts.json` directly. After changes to presets, catalogs, recipes,
rules, fonts, or generation logic, run:

```bash
pnpm tokens:check
```

If a refactor is intended to preserve behavior, both the generated JSON and its revision must
remain byte-for-byte unchanged.

## Routine changes

### Add an input

1. Add the declaration to `overrideCatalogDefinitions.inputs`, including its execution phase,
   priority, managed targets, and strategy.
2. Reuse an existing strategy when possible. Extend the authoring strategy types and expansion
   handling only when the input requires genuinely new behavior.
3. Update parser/expansion tests and all-preset conformance fixtures as needed.
4. Regenerate and verify artifacts with `pnpm tokens:check`.

### Add a selection or recipe

1. Add its source set and selection to `catalogDefinitions.ts` with a stable ID, value shape,
   mode policy, priority, managed targets, and recipe strategy.
2. Prefer an existing closed recipe strategy. If a new strategy is necessary, update
   `catalogAuthoring.ts`, the runtime contract, generator validation/materialization, and
   `recipeEngine.ts` together.
3. Add preset round-trip and expansion coverage, then run `pnpm tokens:check`.

### Add or change a rule

1. Author package policy in `ruleDefinitions.ts`.
2. Reuse an existing `RuleDefinition` variant. A new rule type also requires contract, generator
   validation, and `ruleEvaluation.ts` support.
3. Add intent or resolved-state tests, including severity/calibration behavior.
4. Run `pnpm tokens:check` because rules participate in the artifact revision.

### Add a schema version

1. Decide whether the payload change is backward compatible using the versioning policy in
   [Override Structure](../../../../docs/internal/token-architecture/14-override-structure.md).
2. Update `OVERRIDE_SCHEMA_VERSION` and `SUPPORTED_OVERRIDE_SCHEMA_VERSIONS` in `../constants.ts`,
   the derived public contract in `contracts.ts`, and parser/version tests.
3. For a breaking version, implement and test a complete transformation path before accepting old
   payloads. No transformer is currently exported.
4. Update consumer documentation and run the full styles test/build and artifact checks.

### Add a test fixture

Place private fixtures in `src/__tests__/override/` and import them only from tests. Do not add
fixtures to `override/index.ts`, package exports, production source, or the runtime artifact.

## Verification

For override changes, run the narrow styles tests while iterating and the repository gates before
handoff:

```bash
pnpm nx run @cdx-ui/styles:test
pnpm lint:affected
pnpm test:affected
pnpm --filter @cdx-ui/styles build
pnpm tokens:check
pnpm check:theme-override-target -- --strict-cutover
```
