[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.
Kind: bug. Source: new finding (register E51). It is a symptom of the duplicated berry project gates (E09, filed alongside).
Problem
Yarn berry's project gates exist once per mode, and they disagree about the root package.json. Both modes edit that file: vendored mode writes its file: wiring, and hosted mode writes resolutions.
Repro (unit probe on 045d7ec, run twice, not committed). Input: a 10c0 berry lock plus package.json = "{\r\n \"name\": \"app\",\n \"version\": \"1.0.0\"\r\n}\r\n".
rewrite_yarn_berry: no warnings, yarn.lock is written, and package.json is rewritten all-CRLF with the resolutions added. preflight_yarn_berry_hosted returns Ok.
- Vendored mode, on the same shape (the existing test
vendor::yarn_berry_lock::tests::mixed_line_endings_refuse_before_any_write, case PACKAGE_JSON): refused with vendor_yarn_berry_mixed_line_endings, nothing written.
Symptoms and impact
I found no existing issue for this. A project gets a different answer in each mode for the same file. Hosted mode quietly rewrites lines the user never touched, which shows up as diff noise in the commit, and it breaks the byte-exact round trip that vendored mode promises. The risk is low and the fix is small.
Proposed change
Make the berry gate set decide this once, for both modes (see the E09 refactor issue), and give the root manifest one policy:
- Recommended: hosted mode refuses a mixed root
package.json with redirect_yarn_berry_mixed_line_endings, the same as vendored mode and the same as the lock. This means preflight_yarn_berry_hosted also takes the manifest text, so the vendored→hosted takeover checks it before reverting anything.
- Alternative: both modes accept it and normalize to the majority ending, as yarn's
persistManifest does. That would drop vendored mode's documented refusal, which is a contract change and would need a maintainer's call.
Size and scope
About 30 production lines in patch/redirect/mod.rs and the takeover caller in commands/scan/hosted.rs, plus tests and one sentence in CLI_CONTRACT.md (the hosted berry line-endings paragraph). Out of scope: the yarn classic mixed-lock behavior (#467).
Acceptance criteria
Dependencies
None. Best landed together with, or right after, the E09 shared-gate refactor so the rule lives in one place.
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.
Kind: bug. Source: new finding (register E51). It is a symptom of the duplicated berry project gates (E09, filed alongside).
Problem
Yarn berry's project gates exist once per mode, and they disagree about the root
package.json. Both modes edit that file: vendored mode writes itsfile:wiring, and hosted mode writesresolutions.package.jsonthat mixes CRLF and LF, withvendor_yarn_berry_mixed_line_endings. It does this in the vendor path (yarn_berry_lock.rs#L161) and in the takeover preflight (yarn_berry_lock.rs#L1090-L1103).``CLI_CONTRACT.mddocuments this (codes table, `vendor_yarn_berry_mixed_line_endings`: "`yarn.lock` or the root `package.json` mixes CRLF and LF").preflight_yarn_berry_hosted,only looks at `yarn.lock`. The rewriter then re-renders the manifest through `JsonLayout` ([`redirect/mod.rs#L3858-L3866`](https://github.com/SocketDev/socket-patch/blob/045d7ec783d788bf3c5a1310724b51e09fb6505d/crates/socket-patch-core/src/patch/redirect/mod.rs#L3858-L3866)).`` For a mixed file,JsonLayout::ofpicks the majority terminator (common.rs#L218-L222), so every minority line is rewritten silently. Hosted rollback re-renders the file again, so it can't give back the original bytes either.Repro (unit probe on
045d7ec, run twice, not committed). Input: a10c0berry lock pluspackage.json="{\r\n \"name\": \"app\",\n \"version\": \"1.0.0\"\r\n}\r\n".rewrite_yarn_berry: no warnings,yarn.lockis written, andpackage.jsonis rewritten all-CRLF with theresolutionsadded.preflight_yarn_berry_hostedreturnsOk.vendor::yarn_berry_lock::tests::mixed_line_endings_refuse_before_any_write, casePACKAGE_JSON): refused withvendor_yarn_berry_mixed_line_endings, nothing written.Symptoms and impact
I found no existing issue for this. A project gets a different answer in each mode for the same file. Hosted mode quietly rewrites lines the user never touched, which shows up as diff noise in the commit, and it breaks the byte-exact round trip that vendored mode promises. The risk is low and the fix is small.
Proposed change
Make the berry gate set decide this once, for both modes (see the E09 refactor issue), and give the root manifest one policy:
package.jsonwithredirect_yarn_berry_mixed_line_endings, the same as vendored mode and the same as the lock. This meanspreflight_yarn_berry_hostedalso takes the manifest text, so the vendored→hosted takeover checks it before reverting anything.persistManifestdoes. That would drop vendored mode's documented refusal, which is a contract change and would need a maintainer's call.Size and scope
About 30 production lines in
patch/redirect/mod.rsand the takeover caller incommands/scan/hosted.rs, plus tests and one sentence inCLI_CONTRACT.md(the hosted berry line-endings paragraph). Out of scope: the yarn classic mixed-lock behavior (#467).Acceptance criteria
package.jsontakes the same decision as vendored mode, with the mode's*_yarn_berry_mixed_line_endingscode, and writes nothing.package.jsonis refused before the revert (wet and--dry-run).mixed_line_endings_refuse_before_any_writestays green.Dependencies
None. Best landed together with, or right after, the E09 shared-gate refactor so the rule lives in one place.