Let a real format always supersede a payload-free stat record#68
Merged
Conversation
…cord A stat record's skip keyed off byte records (hashes/sources/resources) only, but addImport attests a resolve-hook target's format WITHOUT a byte record when the load hook never fires for it -- stasis-core's own preload-cached modules are exactly that shape. A --fs capture that then stat'd such a path (webpack's enhanced-resolve walking node_modules/@exodus/stasis-core/src/util.js) hit noupsert with 'stat:file' against the attested 'module' and aborted the whole capture; the reverse order (stat first, then the import attesting the real format) conflicted the same way. Route every live-map format merge through one shared rule, upsertFormat: a real format always takes priority over a 'stat:*' record -- it replaces a stat record already present and is never displaced by one arriving later -- while two divergent real formats, or a stat kind flip (stat:file vs stat:directory), stay fatal conflicts. Used by addFsStat, addImport, and #mergedFormats (whose local upgrade helper it replaces); addFile/addFsDir already drop a stale stat record in place before recording content. addFsStat also marks #observed only when a stat record actually landed, so a child never forwards an entry the shard replay would ignore. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017z3Eb4Udqc5BkdQtt2YA72
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a capture-aborting regression from #66, hit in real
--fsruns:Root cause
addFsStat's "already recorded" skip keyed off byte records (hashes/sources/resources) only — butaddImportattests a resolved target's format at resolve time, with no byte record when the load hook never fires for it. Stasis-core's own preload-cached modules are exactly that shape: the resolve hook recordsmodulefornode_modules/@exodus/stasis-core/src/util.js, the load hook is skipped (the module was cached before hooks registered), and when a bundler's enhanced-resolve under--fsthen stats that path, the stat record hitnoupsertagainst the attested'module'and aborted the whole capture. The reverse ordering (path stat'd first, then an import attesting its real format throughaddImport) conflicted symmetrically.Fix
One shared rule,
upsertFormat(map, file, format): a real format always takes priority over astat:*record — it replaces a stat record already present, and an arriving stat record yields to (never displaces, never conflicts with) an existing real format. Used byaddFsStat,addImport, and#mergedFormats(replacing its duplicate local upgrade helper);addFile/addFsDiralready drop a stale stat record in place before recording content. Genuine conflicts stay fatal: two divergent real formats, or a stat kind flip (stat:filevsstat:directory).Companion fix:
addFsStatmarks#observedonly when a stat record actually landed, so a child shard never forwards an entrymergeShard's stat replay would ignore.Tests
Four regression tests, each verified to fail on the pre-fix code (the forward-direction unit test reproduces the reported crash shape exactly,
Conflict for "src/foo.js"):addFsStatyields to a real formataddImportrecorded for a byte-less target (the production crash)addImportupgrades a stat record recorded before the target was ever resolvedlstatSync'd before it is ever imported upgrades to the real format and round-trips throughbundle=loadFull suite: 1390 tests, 0 failures; lint clean.
🤖 Generated with Claude Code
https://claude.ai/code/session_017z3Eb4Udqc5BkdQtt2YA72
Generated by Claude Code