Skip to content

feat(pgpm-core): rebundlePlan — dependency-aware chunk/merge primitive with byte-identical gate#1411

Merged
pyramation merged 1 commit into
mainfrom
feat/rebundle-plan
Jul 22, 2026
Merged

feat(pgpm-core): rebundlePlan — dependency-aware chunk/merge primitive with byte-identical gate#1411
pyramation merged 1 commit into
mainfrom
feat/rebundle-plan

Conversation

@pyramation

Copy link
Copy Markdown
Contributor

Summary

Atom 4, first slice: the granularity dial between the two extremes we already have (one-file-per-change vs one giant pgpm package). rebundlePlan(moduleDir, strategy) groups a module's changes into fewer, larger chunks — but does so safely, respecting the three orderings the engine cares about (deploy topological, verify in deploy order, revert reversed).

Deliberately thin and additive — it reuses the existing plumbing rather than inventing a parallel model:

  • plan parsing via parsePlanFile / getChanges
  • graph + package-quotient machinery from slice/ (buildDependencyGraph, buildPackageDependencies, detectPackageCycle, computeDeployOrder, extractPackageFromPath)
  • SQL assembly via the same file-concatenation resolveWithPlan already uses

Key correctness idea — contiguity ⇒ byte-identical. Chunks are contiguous runs of the source plan order, not an independent topo sort:

walk changes in plan order:
  keep appending to current chunk while (same boundary key) && (size < cap)
  a member carrying a tag seals the chunk (tags must stay deploy --to seams)

Because chunks are contiguous, concatenating chunks in order — members in source order, reverse for revert — reproduces the original resolved output exactly, at any dial position. Cross-chunk edges only ever point backward, so the chunk quotient is a DAG by construction; if a boundary ever splits a back-edge, we surface a warning instead of silently reordering.

verifyRebundleInvariant(moduleDir, result) is the gate that makes any granularity choice safe:

assemble('deploy')  === resolveWithPlan(dir, 'deploy')
assemble('revert')  === resolveWithPlan(dir, 'revert')   // chunks reversed, members reversed
assemble('verify')  === concat(verify files in plan order)

Strategy surface (all optional):

  • boundary: 'folder' | 'none' (default folder, reusing slice's path extraction)
  • depth / prefixToStrip for the folder key
  • maxChunkSize to cap chunk size (splits a boundary group, still contiguous)

No behavior change anywhere else — new rebundle/ module exported from @pgpmjs/core, nothing consumes it yet. Actually merging chunk files / re-deparsing (the packageModule-per-chunk step) and the classifier-driven boundaries land in follow-ups; this PR establishes the chunk model + ordering + invariant.

Test plan

  • 11 new tests in __tests__/rebundle/ (no DB needed): folder grouping, verify==deploy / revert==reverse, cross-chunk dep derivation, single-chunk and size-capped dials, deploy/revert assembly order, and byte-identical invariant at all three dial positions.
  • tsc --noEmit and pnpm build clean.

Link to Devin session: https://app.devin.ai/sessions/ad40d16f38a349b48eb7ce9375e27e6e
Requested by: @pyramation

@pyramation pyramation self-assigned this Jul 22, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@pyramation
pyramation merged commit a766571 into main Jul 22, 2026
14 checks passed
@pyramation
pyramation deleted the feat/rebundle-plan branch July 22, 2026 04:52
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