Repository navigation
Route inline BOM strips through formats::text (#905) - #1117
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Eight production sites decided for themselves what a leading UTF-8
BOM is: the hosted and shared requirements lexers, the manifest
reader, the hosted npm manifest decoder, the Gradle DSL decoder and
lexer, the socket.yml decoder and the hosted Pipenv remedy. They now
call formats::text::{split_bom, strip_bom} and a new strip_bom_bytes
for the two byte decoders, so the rule lives in one place.
A guard test fails when a new production file spells out its own BOM
handling. Files still changed by open PRs sit on a pending list.
User impact: none, except that the hosted Pipenv stale-install remedy
now reads a Pipfile.lock with two leading BOMs as unparseable (one
BOM is encoding, the second is content), like every other reader.
Refs #905
Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Assisted-by: Claude Code:claude-opus-5-5
The Audit GitHub Actions check (zizmor ref-version-mismatch) fails because the ci.yml pin's comment says v2 while the pinned commit is tagged 2.37.2. Same one-line change as #1118; it no-ops once that lands. Assisted-by: Claude Code:claude-opus-5-5
|
[agent] The I ported the one-line fix from #1118 as Generated by Claude Code |
|
BugBot review Generated by Claude Code |
#1057 added formats/yarn/blocks.rs and stanzas.rs with their own leading-BOM splits, which the new guard rejects once main is merged. Both now call formats::text::split_bom, whose BOM half is now &'static str (it is always "" or U+FEFF) so callers can store it. No behavior change. 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 f810607. Configure here.
|
[agent] The test binds No fix exists yet. A robust version would keep the listener bound and immediately close each accepted connection, or use a reserved unroutable address. That belongs in a separate PR, so I'm not widening this one. I'll re-run the failed job once when the run completes. Generated by Claude Code |
|
Ready for review (burn-down agent).
Nothing specific flagged for the reviewer beyond the PR description. Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Refs #905 (step 3, slice 1). The issue stays open for the inline sites in files that open PRs change.
Summary
This PR moves ten production sites that each spelled out "drop one leading UTF-8 BOM" onto
formats::text. It adds a guard test that fails when a new production file spells out its own BOM handling.Why
formats::text::{split_bom, strip_bom}, but about 50 inline strips remained, some with drifted counts (trim_start_matchesstrips any number of BOMs). #1057 added two more while this PR was open, which the guard caught.What changed
formats::text:strip_bom_bytes, for the byte decoders.split_bomnow returns its BOM half as&'static str. It is always""or U+FEFF, so callers can store it.patch/redirect/requirements.rs: 4 sites.utils/requirements.rs: 2 sites.manifest/operations.rshosted/npm_manifest.rsgradle/dsl.rs:decodeand the lexer's start offset.policy/socket_yml.rs:decode.formats/yarn/blocks.rsandformats/yarn/stanzas.rs(both from Move all yarn.lock parsing into formats/yarn and stop pinning non-registry copies #1057).scan/hosted/python.rs: Pipfile.lock for the stale-install remedy.production_bom_handling_goes_through_the_helpersguard:PENDING_INLINE_BOMSlists the 26 files still changed by open PRs.OWN_BOM_RULElists 2 deliberate exceptions, each with a reason:sbt_versionskips a BOM on any properties line, which its test pins, and the vlt sniff refuses a BOM lock because vlt can't read one.ci.ymlsetup-php pin comment# v2→# 2.37.2. TheAudit GitHub Actionscheck (zizmorref-version-mismatch) fails without it, and it no-ops once Label the setup-php pin in ci.yml with its real tag #1118 lands.main(b96a785).What was deleted
strip_prefix('\u{feff}')/starts_withcopies and the hand-builtbomselectors in the hosted requirements rewriter and the yarn stanza splitter.strip_bom_bytescases, and one-vs-two-BOM coverage for the hosted npm manifest decoder.Behavior
None for zero or one leading BOM. The one exact change: the hosted Pipenv stale-install remedy read a Pipfile.lock with two leading BOMs as JSON, because it used
trim_start_matches. It now treats the second BOM as content, as every other reader does and as #905 requires.Test evidence
f810607: all checks green (192 passed, 8 skipped).test-releasefirst failed inapi_retry_e2e::a_refused_connection_is_not_retried, a port-reuse race in that test that this PR doesn't touch. It passed on its one re-run. See the PR comments.cargo clippy --workspace --all-features -- -D warnings: clean, after the merge.cargo test -p socket-patch-core --lib: 5742 passed, 4 failed. The failures are the known root-only tests that also fail onmainin this sandbox:copy_tree::relax_loop_must_not_traverse_symlinked_root,vlt_heal::an_unremovable_hidden_lock_keeps_every_store_entry,pypi_poetry::wire_write_failure_maps_error_and_leaves_lock_untouchedandpypi_requirements::wire_failure_rolls_back_already_written_files.cargo test -p socket-patch-cli --all-features --lib: 875 passed.--test in_process_redirect_pipenv,policy_pypi_names,scan_requirements_lock_only,scan_vendor_requirements_unwiredande2e_socket_yml_policy: all pass.mainit caughtformats/yarn/{blocks,stanzas}.rs, which are now migrated. Locally, removing a pending entry fails it as expected.gradle::dsl::bom_is_skipped, the manifest reader's BOM and double-BOM tests, the socket.yml BOM bytes test, and the yarn BOM round-trips. The newreads_past_one_bom_onlycovers the hosted npm decoder.Risk
Low. The change is mechanical, apart from the double-BOM Pipfile.lock case above.
🤖 Generated with Claude Code
https://claude.ai/code/session_01PQTx5YVAZtPf1S2S5HYdQs
Note
Low Risk
Mostly mechanical refactors plus a guard test; the only intentional behavior change is double-BOM Pipfile.lock parsing in the hosted Python stale-install path.
Overview
Centralizes UTF-8 BOM handling in
formats::text(#905 step 3): addsstrip_bom_bytes, makessplit_bomreturn a'staticBOM prefix for callers that store it, and replaces inline BOM strips across requirements/manifest/Gradle/policy/yarn/npm hosted paths and the CLI Pipenv stale-install scan withstrip_bom/split_bom/strip_bom_bytes.Adds
production_bom_handling_goes_through_the_helpers, which fails CI if new production code spells out BOM bytes/literals instead of the helpers (with allowlists for files still migrating in other PRs and two deliberate exceptions).Behavior: unchanged for zero or one leading BOM. Pipfile.lock parsing no longer uses
trim_start_matches, so a second leading BOM is treated as content and JSON parse fails, matching other readers.Also updates the
setup-phppin comment inci.yml(# v2→# 2.37.2) for the zizmor ref-version check.Reviewed by Cursor Bugbot for commit f810607. Configure here.
Generated by Claude Code