Skip to content

Baseline-aware three-way upgrade classification - #35

Merged
DanMat merged 1 commit into
mainfrom
feat/upgrade-baseline
Aug 2, 2026
Merged

Baseline-aware three-way upgrade classification#35
DanMat merged 1 commit into
mainfrom
feat/upgrade-baseline

Conversation

@DanMat

@DanMat DanMat commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

Goal 2 of the upgrade-safety brief — and the reviewer's named "largest product opportunity." Every scaffolded project now records a baseline in packkit.json (a content hash of each generated file + the package.json scripts/deps/protected-fields at scaffold time), so packkit upgrade can do a real three-way comparison:

baseline vs current vs new classification default --apply
current == baseline, new != baseline template-only change applied (you hadn't edited it)
current != baseline, new == baseline your edit preserved
current != baseline, new != baseline both changed (conflict) preserved, review

applied across files, scripts, dependency sections, and protected fields. The default policy stays non-destructive — user edits are never touched — but now template-only changes to unedited files apply automatically, which turns upgrade from a conservative diff into a real lifecycle tool.

Older projects with no baseline fall back to the conservative "preserve anything that differs" rule.

Notes

  • Browser-safe hash (src/core/hash.js, cyrb53) — the core runs in the web configurator, so no node:crypto. Deterministic; verified the bundled browser core produces the same baseline.
  • packkit.json is written last in all three generation paths so the baseline covers the whole project (and excludes itself). Determinism and digest round-trips are preserved.
  • The plan now carries file entries (status/safeToApply/reason), per-change classification on scripts/deps/fields, baselineAvailable, and a single diagnostics list that upgradeProject() and --json both read — no duplication.

Folded-in review fixes (coupled to this code)

  • Policy validation{ scripts: 'replace' } now throws instead of silently acting like add-only.
  • Malformed package.json surfaces PACKAGE_JSON_PARSE_FAILED instead of reading as "no changes."
  • --json gains an ok field.

Verified

Scaffold → edit README → the plan classifies it user-only-change (safeToApply false); --apply preserves it and re-adds a deleted file; --json is clean with baselineAvailable: true. 109 tests pass, web configurator green.

The rest of the review's P0 (JSON error exit codes, full-stack + runtime deployment contracts, ARCHITECTURE.md corrections) follows in focused PRs.

🤖 Generated with Claude Code

Goal 2 of the brief — the largest lifecycle milestone. Every scaffolded
project now records a baseline in packkit.json: a content hash of each
generated file plus the package.json scripts/deps/protected-fields at
scaffold time. That lets `packkit upgrade` do a three-way comparison
(baseline vs current-on-disk vs newly-generated) and distinguish:

  current == baseline, new != baseline  → template-only change → safe to apply
  current != baseline, new == baseline  → your edit           → preserve
  current != baseline, new != baseline  → both changed         → conflict, review

applied across files, scripts, dependency sections, and protected fields.
Under the default (non-destructive) policy, template-only changes now
apply automatically — the user's edits are still never touched. Projects
without a baseline (older scaffolds) fall back to the conservative
"preserve anything that differs" model.

- Browser-safe content hash (src/core/hash.js, cyrb53) — the core still
  runs in the web configurator, so no node:crypto. Deterministic; the
  baseline is a pure function of the generated files, verified byte-stable
  and identical from the bundled browser core.
- packkit.json is written last in every path (single-package + both
  monorepo layouts) so the baseline covers the whole project, and excludes
  itself.
- The plan now carries file `entries` (status/safeToApply/reason),
  per-change classification on scripts/deps/fields, `baselineAvailable`,
  and `diagnostics` (baseline-unavailable, malformed-package). The CLI
  --json and upgradeProject() read that one diagnostics list — no
  duplication.

Also folded in three coupled review fixes: upgrade policies are validated
(a typo like { scripts: 'replace' } throws instead of silently behaving
like add-only); a malformed package.json surfaces PACKAGE_JSON_PARSE_FAILED
instead of reading as "no changes"; --json gains an `ok` field.

Verified end to end: a scaffolded project with an edited README is
classified user-only-change and preserved on --apply while a deleted file
is re-added; determinism, digest round-trip, web configurator all green.
109 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@DanMat
DanMat merged commit 4cd01c6 into main Aug 2, 2026
39 checks passed
@DanMat
DanMat deleted the feat/upgrade-baseline branch August 2, 2026 02:25
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