refactor(characters): extract shared preparation-context pipeline#154
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 inactivate's with-chain (write path), withopt_activation_cap/pool_eligibleexisting solely to soften the strict versions.Now one shared pipeline in two stages:
prep_class_and_mode/3— active class + preparation mode; cheap, no DAG evaluation.prep_context/4— resolved cap, max prepared level, pool config, eligible pool. Fallible steps stay tagged ({:ok, _} | {:error, _}) soactivatepattern-matches them strictly whilepreparation_statedegrades tolerantly.opt_activation_capandpool_eligibleare deleted; both ad-hoc context map shapes are gone (one carried apool_namekey its consumer never read).Why two stages
activatemust 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