ci: add the blocking dep-sync gate for the three-grouping workspace#480
ci: add the blocking dep-sync gate for the three-grouping workspace#480mfw78 wants to merge 1 commit into
Conversation
scripts/check-dep-sync.sh asserts the crate DAG points strictly up across nexum, videre and shepherd for every workspace member (path deps and wit/ symlinks included), and that the carve dependency artefacts agree wherever they exist: umbrella [patch] entries target the owning grouping's in-tree crates and neutralise every written git-tag pin with no orphans, pins agree on one tag per upstream repo, each Cargo.repo.toml member list mirrors the umbrella, and wit-deps manifests and locks stay key-synced with tags matching the Rust pins. Artefacts a train wave has not written yet skip visibly and enforce the moment they land. Wired as the blocking dep-sync CI job and a just check-dep-sync recipe; the git-tag to crates.io and wkg/OCI convergence path is documented in docs/design/cross-repo-deps.md.
lgahdl
left a comment
There was a problem hiding this comment.
The core acyclicity direction logic is actually correct this time — verified gr > r (line 86) and the WIT/tag-sourcing rank comparisons all correctly flag only upstream-depends-on-downstream edges, with no inversion, unlike the polarity bugs I've found in several of the earlier boundary-check scripts this session. Skip-vs-pass is genuinely distinguishable and the existence checks use the exact filenames the design doc promises, so enforcement will correctly switch on once later-wave artifacts land rather than silently skipping forever. Two real latent bugs worth fixing before those artifacts actually show up (both are currently dormant since no git-pinned deps exist yet, per the PR's own "skip visibly" testing note — but they'll misfire exactly when the carve's git-tag pins get written, which is the highest-stakes moment for this gate):
| for slug in nexum-runtime videre-nexum-module; do | ||
| url="https://github.com/nullislabs/$slug" | ||
| owner="$(slug_owner "$slug")" | ||
| pins="$(rg -Hn --no-heading "git *= *\"${url}(\\.git)?\"" "${manifest_files[@]}" || true)" |
There was a problem hiding this comment.
This greps for the literal git = "..." line, then checks tag = "..." against that SAME matched line (line ~163 in the loop below). Cargo's expanded dotted-table style writes them as separate lines under [dependencies.<crate>] (git = "..." then tag = "..." on the next line) — under that style, the git= line never contains tag=, so this reports a false "git pin without an inline tag" failure on a perfectly valid pin, permanently blocking the gate for any pin written that way. Search the whole [dependencies.<crate>]/inline-table block for the tag, not just the single matched line.
Relatedly: the pin regex tolerates an optional .git suffix ("${url}(\.git)?"), but the corresponding [patch] header lookup built later (hdr="[patch.\"$url\"]") doesn't — if a pin is written .git-suffixed, the umbrella's matching [patch."....git"] header will never be found, reporting "umbrella [patch] section missing" on a working patch.
| rest = substr($0, i + 1 + length(root)) | ||
| sub(/\).*/, "", rest) | ||
| split(rest, a, "/") | ||
| gr = a[1] == "nexum" ? 0 : a[1] == "videre" ? 1 : a[1] == "shepherd" ? 2 : -1 |
There was a problem hiding this comment.
This AWK ternary hardcodes a second, independent group→rank mapping, duplicating whatever rank()/layers source of truth defines nexum/videre/shepherd's ranks elsewhere in the script (understandable since AWK can't call the bash function directly, but it's still a second copy of the same taxonomy). If a group is ever renamed and only the bash source of truth gets updated — the natural place to look — this literal falls out of sync, gr resolves to -1 for that group's crates, and gr > r never fires for it: the flagship acyclicity check silently stops catching real down-layer dependencies from that renamed group. Worth generating this ternary from the same source (e.g. passing the rank table in via -v from the bash function's output) instead of a second hardcoded literal.
What
Adds
scripts/check-dep-sync.sh, a blockingdep-syncCI job, ajust check-dep-syncrecipe, anddocs/design/cross-repo-deps.mddocumenting the convergence path (git-tag pins now, crates.io/wkg later).Why
The three-grouping workspace needs an enforcing check that the crate DAG stays acyclic (nexum <- videre <- shepherd) and that the carve dependency artefacts (umbrella
[patch], git-tag pins, per-groupCargo.repo.toml,wit-depsmanifests/locks) stay in agreement as later waves land them, per issue scope.Testing
nix develop -c ./scripts/check-dep-sync.sh: DAG and wit checks pass across 37 members; pin/Cargo.repo.toml/wit-deps checks skip visibly (not yet written by later waves).nix develop -c cargo fmt --all --check: clean.AI Assistance
Drafted with Claude Code assistance; reviewed and tested by the author.
Closes #403