Repository navigation
fix(deps): let a Monty fork dependency move ahead of upstream when marked - #2876
Conversation
…rked The forks must match upstream Monty 1.4.0, and the drift check reads that strictly for `Cargo.toml` dependencies. But nine crates are declared both in a fork and in bashkit's own crates, and Dependabot deliberately does not ignore those: bashkit has to be able to move them and to receive their advisories. A proposal for one edits the fork manifest too, so every such bump was unmergeable — #2860 (fancy-regex 0.17 -> 0.20, getrandom 0.3 -> 0.4) is the shape, and it would have returned every week. Holding the fork at upstream's version was not free either: two majors of fancy-regex sat in the graph. A fork dependency's version may now diverge when its line carries a `bashkit fork:` marker, the same mechanism source edits use. Adding or dropping a dependency stays unmarkable, since re-sync cannot reconcile a crate upstream does not have, and a marker on a dependency that already matches upstream is an error so a note left behind by a re-sync cannot excuse the next bump. The marker window is the comment block above the line plus the line itself, with no few-lines fallback: a dependency table is one entry per line, and the fallback let one note cover its neighbours. With that, this takes #2860's content: fancy-regex 0.20 and getrandom 0.4 in `bashkit-monty`, which drops fancy-regex 0.17 and its regex tree from the graph (777 -> 776 crates) and retires the now-unused vet exemption. fancy-regex 0.20 made `Captures` generic over the haystack type, so two marked `Captures<'_, str>` edits come with it. `re` is reachable from untrusted Python, so the behavior 0.20 changed is pinned rather than assumed: `regex_semantics` asserts `\xHH` above 0x7F matches the codepoint and word-boundary alternation still matches, both against what CPython prints. fancy-regex's subroutine calls are not in the fork's feature set, so 0.20's `max_prog_size` guards a blowup that is not reachable here. Claude-Session: https://claude.ai/code/session_01Wy7MByvAMwapenBYpmq9HN
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
bashkit | 43c7520 | Commit Preview URL Branch Preview URL |
Nov 07 2026, 01:18 PM |
Review verdict, push
|
…urces Two precision gaps in the marker logic, both found in review of this change. `marked_deps` keyed markers by bare dependency name while `manifest_errors` checked per (table, name), so a note on `[dependencies] serde` also silenced a `[build-dependencies] serde` drift — compile-time code behind a runtime note. Markers are now keyed by (table, name). Target tables key the same in both places: `marked_deps` reads raw header text, `dep_tables` keys from parsed TOML, and `normalize_table` strips quotes so `[target.'cfg(...)'.dependencies]` agrees with `target.cfg(...).dependencies`. `dep_spec` compared only version, features, default-features and optional, so the keys that decide *which* crate is built were invisible: an unmarked edit keeping version and features identical while adding `path = "../evil"`, a git source, or a different `package` passed silently. Those keys are now compared on their own and are never markable — a marker records a reviewed version move, and re-sync cannot reconcile a different source. The declared renames keep their `package`/`path`; the existing rename check still validates them. Pre-existing for the source keys, but this change makes the manifest comparison the load-bearing control for version policy, so it is closed here. Claude-Session: https://claude.ai/code/session_01Wy7MByvAMwapenBYpmq9HN
`[patch.crates-io]` and `[replace]` redirect a crate's source without touching the dependency line, so the per-dependency source check never sees them: a fork could point `serde` at a git fork while its `[dependencies]` line stayed identical to upstream's and the drift check passed clean. Rejected on sight rather than compared, and no marker covers them. Upstream Monty 1.4 has neither table and a fork has no reason to, so comparing versions inside one would be code for a case that should not exist. `[patch]` in a non-root manifest is inert today, but the forks are published crates and a consumer may build one as its own workspace root, so this does not rest on that. Claude-Session: https://claude.ai/code/session_01Wy7MByvAMwapenBYpmq9HN
The fork-drift check rejected jiter 0.18 in bashkit-monty because upstream Monty 1.4.0 pins 0.17. #2876 made a marked version divergence legal, so the line now carries its reason: upstream's 0.17 declares pyo3 ^0.29.2, the Python binding is on 0.30, and the two collide on links=pyo3-python, so cargo cannot resolve the workspace at all. jiter 0.18 moves its pyo3 requirement to ^0.30.1 and unifies the graph on one major; 0.19 exists but is not needed. Cargo.lock now holds a single pyo3 (0.30.1), jiter 0.18.0 and pyo3-async-runtimes 0.30.0. Claude-Session: https://claude.ai/code/session_01Wy7MByvAMwapenBYpmq9HN
What changed
A dependency's version in a Monty fork
Cargo.tomlmay now diverge from upstream when its line carries abashkit fork: <why>marker — the same mechanism source edits already use. Adding or dropping a dependency stays unmarkable, and a marker on a dependency that already matches upstream is itself an error.With that unblocked, this takes the content of dependabot #2860:
fancy-regex0.20 andgetrandom0.4 inbashkit-monty.Why
Two rules on
maincontradicted each other, and the contradiction produced an unmergeable PR every week.Cargo.tomldependency differing from upstream.Nine crates are declared both in a fork and in bashkit's own crates (
chrono,fancy-regex,getrandom,indexmap,num-bigint,num-traits,serde,sha1,sha2). A Dependabot proposal for one of those edits the fork manifest too, which the drift check then rejects — #2860 is exactly that shape, and it would have come back on every weekly run.Closing the gap by ignoring those names instead was not an option: it would freeze
serde,chronoandsha2for bashkit as well, which are the ones advisories matter most for.Holding the fork at upstream's version was not free either — it put two majors of
fancy-regexin the graph.Before / After
Drift check, fork moved to the workspace's
fancy-regex:Duplicate major gone from the graph (777 → 776 crates), and the now-unused vet exemption retired:
getrandom0.3 stays in the lock viaahash,fastbloomandrand_core, so that bump aligns the declaration rather than shrinking the graph — the win there is that Dependabot stops re-proposing it.rebehavior is pinned, not assumedreis reachable from untrusted Python, andfancy-regex0.20 changed two things that reach it. Each case below was run through bashkit and through real CPython 3.11; all five agree, and they are now regression tests (python_integration_tests::regex_semantics):re.match('\xff', '\xff')— codepoint, not raw byteTrueTruere.search('[\xe0-\xff]', 'z\xe9z')TrueTruere.search(r'\b(?:foo|bar|baz)\b', 'a bar b')TrueTruere.sub(r'(\w)\1', 'X', 'aabb')XXXXre.search(r'(?<=ab)c', 'abc')TrueTruefancy-regex0.20 also addsmax_prog_sizeto bound compile-time inlining of subroutine calls. Those are not in the fork's default feature set —Regex::new("(a(?1)?)")fails withUnknown group flag: (?1— so no new compile-time blowup is reachable and nothing needs wiring up. TM-PY-033 still covers runtime backtracking.Risk
rebehavior change 0.20 made that the five pinned cases miss. The 312python_*tests andpython_fuzz/python_diff_fuzzare the rest of the net.Checklist
reparity casescheck_monty_fork.pyclean,cargo clippy -D warningsclean,cargo fmt --checkcleanbashkit-montylib tests, 312python_*integration tests greenSupersedes #2860.
<a href="
https://backend.blacksmith.sh/track/enable-autofix?expires=1796648328&installation_model_id=447267&pr_number=2876&ref=codesmith_pr_footer&repository=everruns%2Fbashkit&return_to=https%3A%2F%2Fgithub.com%2Feverruns%2Fbashkit%2Fpull%2F2876&signature=b1007db579d1a6caa1ab163eaae59a0060eab386834bc5948fb71b675dde3964"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png" width="190" height="28">Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.Generated by Claude Code