feat(engine): Engine::reconcile_commit and probe_manual_drift#70
Merged
Conversation
Adds two `Vec<String>` fields to `pearlite_state::ReconciliationEntry`, both `#[serde(default)]` so pre-ADR `[[reconciliations]]` rows deserialize cleanly with empty vectors. Tightens `package_count`'s docstring to name it as the audit denominator (ADR-0014 §9). Backfills three round-trip tests in `reconciliation::tests`: - legacy entry without decision vectors deserializes with empty `[]`, - populated decision vectors round-trip through TOML, - AdoptAll with empty `skipped` round-trips. Schema change is additive; the `ReconciliationAction` unit-variant enum (AdoptAll / Interactive / Skipped) keeps its existing TOML representation per ADR-0014 §7. Refs: ADR-0014, PRD §7.3 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 7, 2026
Adds the write-side of reconcile (ADR-0014, M4 W1):
- `Engine::reconcile_commit(state_path, &decisions, threshold)` —
probes via the existing adapter, classifies Manual drift through
`pearlite_diff::{classify_pacman, classify_cargo}` against an empty
declared `PackageSet` (the fresh-import path from PRD §11), enforces
the `Some(N)` threshold defensively, unions adopted names into
`state.adopted.{pacman,cargo}`, and appends one `[[reconciliations]]`
row with a fresh `Uuid::now_v7()`. Atomic write via `StateStore`;
`state.last_modified` set, `state.last_apply` deliberately untouched.
- `Engine::probe_manual_drift(state_path)` — read-only helper that
returns the merged sorted-deduplicated Manual list. The CLI uses it
to drive the threshold pre-check and per-package prompt loop without
reaching into the engine's private probe accessor.
- `ReconcileDecisions` enum (`AdoptAll` / `Selective { adopt }`) and
`ReconcileCommitOutcome` mirror the ADR §7 split: enum carries the
*policy*, vectors carry the *decisions*.
- `ReconcileCommitError::{Probe, State, ThresholdExceeded}` for the
three failure modes; threshold variant carries `count` and
`threshold` so the CLI can surface ADR-0014 §2 wording verbatim.
Module doc now describes both reconcile entry points (read-only
import + commit). Ten new tests in `reconcile::tests`: AdoptAll happy
path, Selective partition, threshold exceeded refuses without
writing, threshold boundary allowed, `state.managed` packages stay
classified as Forgotten (not adopted), existing `state.adopted`
preserved on union, no-Manual-drift still records empty entry,
probe / state-read failure propagation, fresh `plan_id` per call.
Refs: ADR-0014, PRD §11
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
UnbreakableMJ
force-pushed
the
feat/m4-w1-reconcile-commit-engine
branch
from
May 7, 2026 15:20
02817be to
4f4c491
Compare
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.
Summary
Adds the write-side of reconcile (ADR-0014, M4 W1):
Engine::reconcile_commit(state_path, &decisions, threshold)— probes via the existing adapter, classifies Manual drift throughpearlite_diff::{classify_pacman, classify_cargo}against an empty declaredPackageSet(the fresh-import path from PRD §11), enforces theSome(N)threshold defensively, unions adopted names intostate.adopted.{pacman,cargo}, and appends one[[reconciliations]]row with a freshUuid::now_v7(). Atomic write viaStateStore;state.last_modifiedset,state.last_applydeliberately untouched.Engine::probe_manual_drift(state_path)— read-only helper returning the merged sorted-deduped Manual list. The CLI uses it (in chunk C) to drive its threshold pre-check and per-package prompt loop without reaching into the engine's private probe accessor.ReconcileDecisions { AdoptAll, Selective { adopt: BTreeSet<String> } }andReconcileCommitOutcome { plan_id, committed_at, action, considered, adopted, skipped }.ReconcileCommitError { Probe, State, ThresholdExceeded { count, threshold } }.Stacked on #69
This PR builds on the new
adopted/skippedvectors landed in #69. Until #69 merges, the diff here will show those state-side changes too; once #69 merges, GitHub will auto-rebase this PR's diff againstmain.Test plan
cargo test -p pearlite-engine --features test-mocks— 60/60 passing (10 new inreconcile::tests).cargo clippy --workspace --all-targets -- -D warnings— clean.cargo run -p pearlite-audit -- check .— 0 violations.New tests cover: AdoptAll happy path, Selective partition, threshold exceeded refuses without writing, threshold boundary allowed,
state.managedpackages stay classified as Forgotten (not adopted), existingstate.adoptedpreserved on union, no-Manual-drift records empty entry, probe / state-read failure propagation, freshplan_idper call.Refs: ADR-0014, PRD §11
🤖 Generated with Claude Code