Skip to content

feat(engine): Engine::reconcile_commit and probe_manual_drift#70

Merged
UnbreakableMJ merged 2 commits into
mainfrom
feat/m4-w1-reconcile-commit-engine
May 7, 2026
Merged

feat(engine): Engine::reconcile_commit and probe_manual_drift#70
UnbreakableMJ merged 2 commits into
mainfrom
feat/m4-w1-reconcile-commit-engine

Conversation

@UnbreakableMJ

Copy link
Copy Markdown
Contributor

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 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 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.
  • New types: ReconcileDecisions { AdoptAll, Selective { adopt: BTreeSet<String> } } and ReconcileCommitOutcome { plan_id, committed_at, action, considered, adopted, skipped }.
  • New error: ReconcileCommitError { Probe, State, ThresholdExceeded { count, threshold } }.

Stacked on #69

This PR builds on the new adopted / skipped vectors 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 against main.

Test plan

New tests cover: 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 records empty entry, probe / state-read failure propagation, fresh plan_id per call.

Refs: ADR-0014, PRD §11

🤖 Generated with Claude Code

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>
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
UnbreakableMJ force-pushed the feat/m4-w1-reconcile-commit-engine branch from 02817be to 4f4c491 Compare May 7, 2026 15:20
@UnbreakableMJ
UnbreakableMJ merged commit 34f75f0 into main May 7, 2026
3 checks passed
@UnbreakableMJ
UnbreakableMJ deleted the feat/m4-w1-reconcile-commit-engine branch May 7, 2026 15:41
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