Skip to content

refactor(characters): extract shared preparation-context pipeline#154

Merged
QMalcolm merged 1 commit into
mainfrom
qmalcolm--refactor-prep-context
Jul 19, 2026
Merged

refactor(characters): extract shared preparation-context pipeline#154
QMalcolm merged 1 commit into
mainfrom
qmalcolm--refactor-prep-context

Conversation

@QMalcolm

@QMalcolm QMalcolm commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Closes #126

What

The preparation-context derivation (class lookup → mode → DAG evaluation → cap → max level → pool config → eligible pool) existed twice: tolerantly in build_prep_state_map (read path) and strictly in activate's with-chain (write path), with opt_activation_cap / pool_eligible existing solely to soften the strict versions.

Now one shared pipeline in two stages:

  1. prep_class_and_mode/3 — active class + preparation mode; cheap, no DAG evaluation.
  2. prep_context/4 — resolved cap, max prepared level, pool config, eligible pool. Fallible steps stay tagged ({:ok, _} | {:error, _}) so activate pattern-matches them strictly while preparation_state degrades tolerantly.

opt_activation_cap and pool_eligible are deleted; both ad-hoc context map shapes are gone (one carried a pool_name key its consumer never read).

Why two stages

activate must reject a wrong preparation mode before any DAG evaluation. My first single-stage version evaluated eagerly — and the existing mode-rejection test caught it, because its fixture deliberately has no graph, encoding exactly that ordering contract. The split preserves original error precedence (no-class → wrong-mode → cap → pool → eligibility → cap-limit) and avoids wasted evaluation on mode errors.

Verification

No behavior change: full suite passes unchanged (311 + 55 tests), credo, dialyzer, CodeScene delta all green.

Summary by Bito

  • Refactored the character preparation pipeline into a shared, two-stage process to unify logic between read (preparation_state) and write (activate) paths.
  • Introduced `prep_class_and_mode/3` to perform a lightweight check of the preparation class and mode before expensive evaluation.
  • Introduced `prep_context/4` to centralize the resolution of activation caps, pool configurations, and eligible items, ensuring consistent behavior across the system.
  • Improved error handling in the activation path by leveraging the structured context returned by the new pipeline.

The prep-context derivation (class lookup, mode, DAG evaluation,
activation cap, max prepared level, pool name/config, eligible pool)
was written twice: tolerantly in build_prep_state_map for the read
path, and strictly inside activate's with-chain for the write path.
The wrappers opt_activation_cap and pool_eligible existed solely to
soften the strict versions for the read path, and the two ad-hoc
context map shapes (ctx/pool_ctx) carried overlapping fields — one
including a pool_name key its consumer never read.

The pipeline now lives in two shared stages:

- prep_class_and_mode/3 — active class and its preparation mode; cheap,
  no DAG evaluation.
- prep_context/4 — everything else, with fallible steps (cap,
  pool_config) kept as tagged results so activate pattern-matches
  errors strictly while preparation_state degrades tolerantly.

opt_activation_cap and pool_eligible are deleted; build_prep_state_map
shrinks to consuming the context.

The two-stage split (rather than one function) is deliberate: activate
must reject a wrong preparation mode before any DAG evaluation
happens. A first single-stage version evaluated eagerly and was caught
by the existing mode-rejection test, whose fixture has no graph —
encoding exactly that ordering contract.

No behavior change; existing tests pass unchanged.

Closes #126
@QMalcolm
QMalcolm merged commit 8b45cd6 into main Jul 19, 2026
6 checks passed
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.

refactor(characters): extract shared preparation-context pipeline

1 participant