Skip to content

Extract a shared plan→drift-classification walk for status/diff/reconcile/explain #229

Description

@spxrogers

Problem. The walk that turns a render.RenderPlan + state + on-disk destinations into classified items exists four times, hand-maintained:

  • buildStatusModel (internal/cli/status.go:283-348)
  • diff's inline RunE loop (internal/cli/diff.go:141-198)
  • collectItems (internal/cli/reconcile.go:610-677)
  • a variant in internal/cli/explain_model.go (buildExplainModel, key-merge branch)

All four do: plan.PerAgent → key-merge vs whole-file branch → json.Unmarshal(op.Content) / readDestFilerender.CollectPointers → hash triple → drift.Classify, plus per-path dedupe for whole-file ops and NO dedupe for key-merge ops. Each copy carries a comment warning it must match the others ("matching status's key loop and the apply pipeline", "Deduping by path here dropped the second section's drift…") — synchronization by comment. Orphan enumeration (render.OrphanFiles) is similarly repeated in status + reconcile.

Fix. One iterator in internal/render (or internal/drift) — e.g. WalkPlanItems(plan, reg, state, sc, projectRoot, userHome) yielding {agent, op, ptr, class, srcHash/destHash, srcText/dstText} — with orphan items included behind a flag. Every export it needs (IsKeyMerge, CollectPointers, OrphanFiles, the hash helpers) already exists; only the composition is copy-pasted. status/diff/reconcile/explain then only render.

Payoff. The next change to classification semantics (e.g. mode drift, which today only status layers on at status.go:312) lands in one place instead of one-of-four.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions