You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Vendored Poetry wires a 2.x lock through two different splicers depending on its line endings #936
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: register comment.
Kind: refactor (a duplicated splicer whose behavior has drifted, proven by execution). Source: new finding; register E66 (related to E23).
Problem
wire_poetry picks its forward splicer by the lock's line endings:
legacy locks (0/1.0/1.1) and any CRLF lock go through the shared toml_edit engine utils::poetry_lock::rewrite_poetry_lock_with_edits, which hosted mode uses too;
LF 2.x locks go through a private line scanner, rewrite_target_package_unit, built on toml_surgery::{find_unit_span, package_unit_lines, replace_files_array}.
The two have drifted. Proof: a throwaway test in pypi_poetry.rs's test module, run twice on 9c43dfc. It wired each of the module's 2.x fixtures (LOCK21_DIRECT_REGISTRY, LOCK21_TRANSITIVE_REGISTRY, LOCK20_DIRECT_REGISTRY) once as LF and once as CRLF, and compared the results after normalizing CRLF to LF.
The output shape differs for every fixture. LF writes Poetry's own multi-line array, which the fixture tests pin:
So the same project gets a different poetry.lock diff depending on core.autocrlf, and only the LF shape is fixture-proven.
The engine's input gates are skipped on LF.
The engine refuses a wheel whose filename doesn't match the locked package (poetry_lock.rs#L262). It also lowercases the digest, because "an uppercase digest would fail every install" (#L259-L261).``
In the test, wire_poetry with wheel evil-9.9-py3-none-any.whl succeeded on LF but failed on CRLF ("Poetry patch wheel does not match the locked package").
An uppercase digest was written uppercase on LF and lowercase on CRLF.
Today's orchestrator passes its own lowercase sha and a matching wheel name, so these two are latent. They show that the gates live in only one of the two paths.
The name matcher differs. The line scanner matches only the literal name = "…" spelling (common::unit_has_canon_name), so wire_fails_closed_when_text_surgery_cannot_find_the_parsed_unit pins a refusal for name="six". The engine reads the parsed TOML and accepts the same lock when it is CRLF. This was read from the code, not executed.
Symptoms / Impact
No open issue tracks this. The impact is moderate:
Vendored diffs depend on line endings, and hosted and vendored write different shapes for the same 2.x lock.
Two forward rewriters for one format must each be fixed when Poetry's shape changes.
Make the shared engine emit Poetry's own multi-line files = [\n {file = …, hash = …},\n] shape for 2.x locks. utils::poetry_lock::is_multiline_array and the legacy legacy_files_entry already do this for [metadata.files]. This also aligns hosted output with what Poetry writes.
Route every vendored Poetry lock through rewrite_poetry_lock_with_edits, and delete the LF branch.
Delete:rewrite_target_package_unit (pypi_poetry.rs), toml_surgery::replace_files_array and toml_surgery::package_unit_lines (Poetry-only), and common::unit_has_canon_name (Poetry-only). uv keeps find_unit_span and its other helpers.
Size and scope
Files: vendor/pypi_poetry.rs, vendor/toml_surgery.rs, vendor/common.rs and utils/poetry_lock.rs; roughly −120 / +40 production lines.
Out of scope: PDM (already engine-only), the revert path (revert_lock_fragment_splice_atomic, already shared) and the wider backend skeleton (E23).
wire_poetry calls only utils::poetry_lock for every lock version and line ending.
wiring_matches_fixtures_byte_identically_both_lock_versions stays green, with byte-identical fixture output.
New test: each 2.x fixture wired as LF and as CRLF gives the same lock after CRLF→LF normalization.
New test: hosted rewrite_poetry_lock on a 2.x fixture keeps the multi-line files shape.
wire_fails_closed_when_text_surgery_cannot_find_the_parsed_unit is rewritten to the engine's behavior for name="six" (accept, or refuse with a stated reason).
The CRLF, revert, legacy and files-keyed sub-table tests in pypi_poetry.rs and utils/poetry_lock.rs stay green.
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: register comment.
Kind: refactor (a duplicated splicer whose behavior has drifted, proven by execution). Source: new finding; register E66 (related to E23).
Problem
wire_poetrypicks its forward splicer by the lock's line endings:0/1.0/1.1) and any CRLF lock go through the sharedtoml_editengineutils::poetry_lock::rewrite_poetry_lock_with_edits, which hosted mode uses too;rewrite_target_package_unit, built ontoml_surgery::{find_unit_span, package_unit_lines, replace_files_array}.pypi_poetry.rs#L316-L349:``pypi_poetry.rs#L432-L476andtoml_surgery.rs#L82-L123.``poetry_lock.rs#L243-L346.The two have drifted. Proof: a throwaway test in
pypi_poetry.rs's test module, run twice on9c43dfc. It wired each of the module's 2.x fixtures (LOCK21_DIRECT_REGISTRY,LOCK21_TRANSITIVE_REGISTRY,LOCK20_DIRECT_REGISTRY) once as LF and once as CRLF, and compared the results after normalizing CRLF to LF.toml_editinline rendering:poetry.lockdiff depending oncore.autocrlf, and only the LF shape is fixture-proven.poetry_lock.rs#L262). It also lowercases the digest, because "an uppercase digest would fail every install" (#L259-L261).``wire_poetrywith wheelevil-9.9-py3-none-any.whlsucceeded on LF but failed on CRLF ("Poetry patch wheel does not match the locked package").name = "…"spelling (common::unit_has_canon_name), sowire_fails_closed_when_text_surgery_cannot_find_the_parsed_unitpins a refusal forname="six". The engine reads the parsed TOML and accepts the same lock when it is CRLF. This was read from the code, not executed.Symptoms / Impact
No open issue tracks this. The impact is moderate:
Proposed change
files = [\n {file = …, hash = …},\n]shape for 2.x locks.utils::poetry_lock::is_multiline_arrayand the legacylegacy_files_entryalready do this for[metadata.files]. This also aligns hosted output with what Poetry writes.rewrite_poetry_lock_with_edits, and delete the LF branch.rewrite_target_package_unit(pypi_poetry.rs),toml_surgery::replace_files_arrayandtoml_surgery::package_unit_lines(Poetry-only), andcommon::unit_has_canon_name(Poetry-only). uv keepsfind_unit_spanand its other helpers.Size and scope
vendor/pypi_poetry.rs,vendor/toml_surgery.rs,vendor/common.rsandutils/poetry_lock.rs; roughly −120 / +40 production lines.revert_lock_fragment_splice_atomic, already shared) and the wider backend skeleton (E23).utils/poetry_lock.rsfor parse reuse.Acceptance criteria
wire_poetrycalls onlyutils::poetry_lockfor every lock version and line ending.wiring_matches_fixtures_byte_identically_both_lock_versionsstays green, with byte-identical fixture output.rewrite_poetry_lockon a 2.x fixture keeps the multi-linefilesshape.wire_fails_closed_when_text_surgery_cannot_find_the_parsed_unitis rewritten to the engine's behavior forname="six"(accept, or refuse with a stated reason).files-keyed sub-table tests inpypi_poetry.rsandutils/poetry_lock.rsstay green.Dependencies