Skip to content

Grouped resolved config view + prove derived state is consistent - #26

Merged
DanMat merged 1 commit into
mainfrom
refactor/resolved-domain-model
Jul 26, 2026
Merged

Grouped resolved config view + prove derived state is consistent#26
DanMat merged 1 commit into
mainfrom
refactor/resolved-domain-model

Conversation

@DanMat

@DanMat DanMat commented Jul 26, 2026

Copy link
Copy Markdown
Owner

The config carries ~16 derived flags (isTs, hasApp, publishable, isReact, usesVite…). The architecture review's worry was that they can in principle contradict each other. Two changes address that — and I made a deliberate scope call on a third.

Structured view

normalizeConfig now attaches cfg.resolved — a grouped, read-only view of the same booleans, organized by concern:

cfg.resolved = { targets, language, framework, build, module, package }

Consumers that prefer structured access read cfg.resolved.targets.app instead of re-interpreting raw selections. deriveDeploymentContract now does, as the reference pattern.

Proof it can't contradict

test/invariants.test.js is the real answer to "flags can contradict." Across a broad matrix it asserts:

  • the grouped view never disagrees with the flat flags, and
  • the derived state is internally consistent: publishable exactly matches its definition, an app is always ESM and never publishable, a service is never publishable, at most one framework is active, and every gated option (pkgChecks/sizeLimit/sourcemaps/storybook/e2e/jsr/canary) is off when its precondition fails.

A future normalizeConfig change that introduces a contradiction fails here.

cfg.resolved is config-only — never emitted, and excluded from provenance, serialization, and the digest — so output and reproducibility are unaffected.

Deliberately not done

Mechanically rewriting every cfg.hasApp across the features to cfg.resolved.targets.app. It's byte-safe but pure cosmetic churn with zero functional gain; the flat flags stay supported and the invariants test guarantees the two never drift. Flagging the judgment call rather than burning a 300-site diff.

99 tests pass (2 new), lint clean, web configurator verified.

🤖 Generated with Claude Code

…stent

The config carries ~16 derived flags (isTs, hasApp, publishable, isReact,
usesVite…). The review's worry was that they can in principle contradict.
Two changes address that:

- normalizeConfig now attaches cfg.resolved — a grouped, read-only view
  of the same booleans, organized by concern (targets/language/framework/
  build/module/package). Consumers can read structured state instead of
  re-interpreting raw selections; deriveDeploymentContract now does.

- test/invariants.test.js proves the derived state can't silently
  contradict itself. Across a broad matrix it asserts the grouped view
  never disagrees with the flat flags, and that the state is internally
  consistent: publishable exactly matches its definition, an app is always
  ESM and never publishable, a service is never publishable, at most one
  framework, and every gated option (pkgChecks/sizeLimit/sourcemaps/
  storybook/e2e/jsr/canary) is off when its precondition fails.

cfg.resolved is config-only — never emitted, and excluded from
provenance, serialization, and the digest — so output and reproducibility
are unaffected.

Deliberately NOT done: mechanically rewriting every cfg.hasApp reference
across the features to cfg.resolved.targets.app. It's byte-safe but pure
cosmetic churn with no functional gain; the flat flags stay supported and
the invariants test guarantees the two never drift.

99 tests pass (2 new), lint clean, web configurator verified.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@DanMat
DanMat merged commit b85c06e into main Jul 26, 2026
37 checks passed
@DanMat
DanMat deleted the refactor/resolved-domain-model branch July 26, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant