Fix pnpm-workspace.yaml key detection and appends (#400, #402) - #414
Mikola Lysenko (mikolalysenko) wants to merge 8 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
The hosted trustLockfile write and the vendored overrides write found an existing key only by a literal line prefix and appended new keys at end of file. Quoted or space-before-colon keys were then duplicated, and flow-style or '...'-terminated files were corrupted, so every later pnpm install failed while the command reported success. Both editors now share one helper that recognises every key spelling pnpm reads and finds where a new key belongs. Keys go before a '...' marker. Shapes a line edit cannot extend are refused before anything is written, with the manual recoveries in the warning. Fixes #400, #402. Assisted-by: Claude Code:claude-opus-5-5
Runs scan --mode hosted over a quoted opt-out, a spaced opt-out, a flow-style file and a '...'-terminated file, and checks the workspace file is left as is (or gains the key inside the document) while the lock is still redirected. Assisted-by: Claude Code:claude-opus-5-5
Keeps the new regression tests inside the existing test module so the crate stays clean under clippy's items-after-test-module lint. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
A '#' comment at column 0 does not end a YAML block mapping, but the overrides section lookup treated it as the next key. Entries after such a comment were then invisible to the vendored conflict check, the edit and the revert. The lookup now skips comments and stray carriage returns. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
An earlier commit ran rustfmt across the whole workspace and swept import reordering and line wrapping in 120+ files that this fix does not touch. Restore those files to main so the change is reviewable; only the pnpm-workspace.yaml fix and its tests remain. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
The overrides section keeps column-0 comments now, but the entry indent was still taken from the first non-empty line. A leading comment then forced the 2-space default, so a 4-space section was skipped by the conflict check, the edit and the revert, and a duplicate key could be added. Comment lines are now skipped. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 3c5f8f8. Configure here.
|
[agent] One failing check on 3c5f8f8: Pipenv compatibility / 25 of 26 cells pass. The one failure is Pipenv 2022.12.19 / This isn't caused by this PR:
I don't have a fix to port, because none is needed in this PR. I'll re-run the failed job once when the run completes. If it fails again, I'll treat it as real and dig in. Generated by Claude Code |
|
[agent] A second failing check on 3c5f8f8: PDM patch compatibility / 1 of 47 cells fails: PDM 2.20.1 / This isn't caused by this PR:
I don't have a fix to port, because none is needed in this PR. Like the Pipenv job above, I'll re-run the failed job once when its run completes. If it fails again, I'll treat it as real and pull the cell's Generated by Claude Code |
|
[burn-down agent] Ready for review on
Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #400
Fixes #402
Summary
After a successful-looking
scan --mode hostedorvendor, a project'spnpm-workspace.yamlcould stop loading, and every laterpnpm installfailed. This happened in two cases:trustLockfile/overrideskey, and break every install #402). An explicit"trustLockfile": falseopt-out was also overridden rather than respected.{packages: [.]}) or ended with..., so the appended block lines produced invalid YAML or a second document (Hosted trustLockfile and vendored overrides appends corrupt a flow-style or...-terminated pnpm-workspace.yaml while reporting success #400).With this change, both editors read the file the way pnpm's YAML parser does. Existing keys are recognised in every spelling, new keys go inside the document (before a
...marker), and shapes a line edit can't safely extend are left untouched with a clear reason.Root cause
socket-patch edits
pnpm-workspace.yamlin two places: the hostedtrustLockfile: truewrite (plan_workspace_trustinhosted/guidance.rs) and the vendoredoverrides:mirror (check_workspace_override/apply_workspace_override/ revert invendor/pnpm_lock.rs). Both were line splices that:trustLockfile:,overrides:), andFix
crates/socket-patch-core/src/formats/pnpm/workspace.rsis a new shared helper:top_level_key: parses a column-0 mapping key that is plain, single-quoted (''escapes) or double-quoted (backslash escapes), allowing blanks before the colon. It returns the key and its inline value with any trailing comment stripped.block_insert_point: finds where a new top-level key belongs (after the last content line, before a...end marker). It returns an error for a flow-style root, a root on the---line, an indented or sequence root, or a second document.block_section_bounds: finds a block section under any key spelling. Column-0#comments and stray\rlines stay inside the section.Callers:
plan_workspace_trust): uses both helpers. The newTrustPlan::Unsupported(reason)writes nothing and emits theredirect_pnpm_trust_lockfilewarning with both manual recoveries (pnpm install --trust-lockfile, or add the key yourself) and the don't-rebuild caution (pnpm_trust_workspace_unsupported_detail).overridesmapping. The section lookup used by the check, the edit, the revert and the empty-section prune accepts every key spelling, and takes the entries' indent from the first non-comment line. The append is placed byblock_insert_point.pnpm_trust_lockfile_leftcheck (upstream/npm.rs) recognises the key in any spelling.CLI_CONTRACT.md: documents this behaviour.No wrapper changes are needed.
npm/,pypi/andgem/only dispatch to the binary.Test evidence
Red on main (commit d3fb884, tests only), green with the fix:
"trustLockfile": false,trustLockfile : false,'trustLockfile': false # c→ respected (UserSet)plan_workspace_trust_reads_quoted_and_spaced_keys(cli lib)'trustLockfile': true,"trustLockfile" : "true",trustLockfile: true # c→ no-op"overrides":,'overrides':,overrides :,overrides: # c→ entry inserted inside the sectionquoted_or_spaced_overrides_key_is_edited_in_placequoted_overrides_section_conflict_is_refusedquoted_inline_overrides_mapping_is_refusedrevert_removes_our_key_from_a_quoted_section...-terminated file → key inserted before...; flow root,--- {…}, multi-document → not appended, warning names the reasonplan_workspace_trust_respects_the_document_shape...→ section before the marker; leading---is finedocument_end_marker_keeps_the_section_in_the_document--- {…}, second document, indented root → refused before writingunspliceable_document_shapes_are_refused...file; the lock is redirected and the workspace file is untouched (or gains the key inside the document)in_process_redirect_pnpm::hosted_trust_edit_reads_the_workspace_yaml_shapeoverrides:doesn't hide later entries (check, edit, revert)column_zero_comment_inside_the_section_keeps_later_entriesleading_comment_does_not_set_the_entry_indentformats::pnpm::workspace::tests::*Red→green: on main, all 8 issue tests in the cli lib and core lib fail (6 vendored + 2 hosted). Each Bugbot test fails without its fix. All pass with the fix. The in-process test was added after the fix and wasn't run against main.
Local commands (Linux, Node 22, pnpm 10.28.0, toolchain 1.93.1):
cargo fmt --check: the files this PR changes are fmt-clean.mainitself isn't fmt-clean under the pinned toolchain (in about 120 files), and CI doesn't runcargo fmt, so this PR doesn't touch those files.cargo clippy --workspace --all-features -- -D warnings: okcargo test --workspace --all-features --no-fail-fast: everything passes except tests that rely onchmodto force a write failure (covgap_commands_vendorstate-write ×3,in_process_redirectwrite-failure ×3,repair×2, corecopy_tree/vlt_heal/pypi_poetry/pypi_requirementswrite-failure ×4). This sandbox runs as uid 0, which ignores read-only modes. None of these tests touch pnpm-workspace.yaml.--test e2e_vendor_pnpm_build: 15 passed.--test e2e_redirect_pnpm_build -- --ignored --skip pnpm_pinned_matrix: 8 passed.--test in_process_redirect_pnpm: 11 passed.e2e_safety_pnpm --ignoredcan't run here: the proxy refusespatches-api.socket.dev. CI covers it.CI on 3c5f8f8: every compatibility workflow is green (npm, pnpm, Bun, vlt, Composer, Go, Poetry, PDM, Pipenv). The Pipenv 2022.12.19
extrasand PDM 2.20.1static-urlscells failed once, in code this PR doesn't touch, and passed on their single re-run. Bugbot found no new issues on 3c5f8f8.🤖 Generated with Claude Code
https://claude.ai/code/session_01Kmie1ncmqvPzYfYc2ustqm
Generated by Claude Code