fix(storage): preserve packed Bundle cleanup outcome - #4419
Conversation
Astro-Han
left a comment
There was a problem hiding this comment.
Thanks for turning these around so quickly. Verified against head b621c4e67d.
All three fixes hold up:
- Pack cleanup outcome.
ProductionSessionBundleArtifactcarriessnapshotCleanupalongside the ordinary artifact fields, so a successful Bundle survives a failed staging release instead of being thrown away, while a genuine pack failure still surfaces as the primary error. The regression test drives it through the realrelease()identity check by displacing the staging root from an injectedbundleFileService, so it exercises the production owner rather than a stubbed cleanup, and it would fail on the previous behavior. - Cancellation normalization. Dropping the blanket rewrite and rethrowing lets
normalizePreparationErrorsee the bareAbortErroragain and classify it assnapshot_cancelled. The new runtime test asserts the pass-through directly. - Portability diagnostics.
unsupported_portable_pathcleanly separates USTAR-V1-unrepresentable names from symlinks and hard links, on both the policy and the preparer side.
One thing to fix before this can merge — it is mechanical, not a design issue:
- CI
testis red onCheck Windows test inventory: "Windows test skip inventory is stale; runnpm run windows:inventory:write". The new{ skip: process.platform === 'win32' }case needs the inventory regenerated and committed.
Non-blocking observations, fine to leave or fold in while you are here:
details.observed: 1is a constant. Elsewhereobservedmeans the measured value that breached a limit; here it never varies, so it adds no locating power that the newpolicyCategorydoes not already give. Dropping it would keep the field's meaning consistent.packconsumes thepreparedhandle, so a caller holdingpending_recoveryhas no in-process way to retry the release — andrecover()deliberately skips this process's own lease (session-copy-cleanup.ts:197), so the staging necessarily waits for a restart. The comment is honest about this, butPreparedSessionBundleHandledocuments release failures as retryable; aretry()on the cleanup object would restore that.production-session-snapshot.ts:544-547runsassertWorkspacePathBudgetbeforepolicy.classify, so the preparer's ownisSessionBundleUstarPathV1check always wins and the policy's newunsupported_portable_pathreject branch is unreachable on this production path (the two also report different codes:unsafe_sourcevspolicy_rejected). Since the coordinator defines the preparer as the policy's enforcement point, the convergent shape is to delete the duplicate check and let the policy decision stand.- The fourth observation from #4361 (collapsing the staging-root-keyed budget
Mapinto a closure variable) is still open — the summary says three, there were four. Entirely optional.
Also worth deciding: this branch and #4361 both start flat from main and touch the same files, so whichever lands first will require the other to rebase.
Review assistance: Claude (Claude Code) diffed this branch against #4361, re-checked the cleanup path, the cancellation normalization, and the preparer/policy ordering against current main, and read the failing CI job; I reviewed and confirmed those findings myself and own this approval.
|
Looking at the three fixes together instead of one at a time — they are the same bug, not three. All three are the composition layer deciding something a composed part already owns, and every time the downstream branch went dead:
The first two you fixed by deleting code. The third is still there, and it is in files this PR already touches: Drop the Worth knowing this hits the tests too — the five Sorry for filing these as three separate nits the first time round; the shape only showed up once they were side by side. Also, CI is still red on |
* fix(storage): preserve packed Bundle cleanup outcome * test: update Windows skip inventory
Summary
Follow-up to #4361 addressing the three non-blocking review observations for #2369:
Tests
AI usage
This PR was developed with AI assistance and reviewed and validated by the author.