Skip to content

fix(doctor): refuse a stale Cargo registry before the gate drops its network - #265

Open
ebursztein wants to merge 6 commits into
mainfrom
fix/doctor-cargo-registry
Open

ebursztein wants to merge 6 commits into
mainfrom
fix/doctor-cargo-registry

Conversation

@ebursztein

Copy link
Copy Markdown
Collaborator

bootstrap.sh fetched workspace crates once and nothing re-checked them. When
Cargo.lock gained utoipa, a focus-test ran for minutes and died in
assets.recovery-dependencies inside the no-network sandbox with a wall of
"Could not resolve host: index.crates.io".

  • doctor: new offline check (cargo fetch --locked --offline) with a
    cargo-fetch fix-registry entry; just doctor fix runs cargo fetch --locked,
    and refuses inside a gate run. bootstrap fetches through that same fix.
  • gate: sandbox.applied probes the config-owned [sandbox].cargo_offline_probe
    before wrapping in Bubblewrap/Seatbelt and before starting the release
    egress helper, refusing with the missing crate and just doctor fix.
  • doctor now names just doctor fix instead of the nonexistent doctor-fix.

Found while reproducing the kingslanding reset-burst stall: origin/main's Cargo.lock gained utoipa, and a sandboxed focus-test died minutes in on a wall of Could not resolve host: index.crates.io. bootstrap fetched once; nothing re-checked.

Behaviour change: every sandboxed gate command now needs cargo and a complete registry up front (hosted jobs already run cargo fetch --locked first).

Tests: 14 new (offline/locked probe, refusal text, no probe when sandbox off/active, real cargo against an empty CARGO_HOME, doctor ordering, bootstrap has no own fetch); ownership + suite registration checked; ruff and capsem-gate lint clean.

🤖 Generated with Claude Code

…network

bootstrap.sh fetched workspace crates once and nothing re-checked them. When
Cargo.lock gained utoipa, a focus-test ran for minutes and died in
assets.recovery-dependencies inside the no-network sandbox with a wall of
"Could not resolve host: index.crates.io".

- doctor: new offline check (cargo fetch --locked --offline) with a
  cargo-fetch fix-registry entry; `just doctor fix` runs cargo fetch --locked,
  and refuses inside a gate run. bootstrap fetches through that same fix.
- gate: sandbox.applied probes the config-owned [sandbox].cargo_offline_probe
  before wrapping in Bubblewrap/Seatbelt and before starting the release
  egress helper, refusing with the missing crate and `just doctor fix`.
- doctor now names `just doctor fix` instead of the nonexistent doctor-fix.
@codecov-commenter

codecov-commenter commented Sep 27, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 23.07692% with 50 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.3%. Comparing base (9ed6941) to head (6c19aff).
⚠️ Report is 8 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
build_system/builder/gate/runhistory.py 26.0% 17 Missing ⚠️
build_system/builder/gate/runs.py 10.0% 9 Missing ⚠️
build_system/builder/gate/runledger.py 20.0% 8 Missing ⚠️
build_system/builder/gate/sandbox.py 12.5% 7 Missing ⚠️
build_system/builder/gate/timingratchet.py 25.0% 3 Missing ⚠️
build_system/builder/gate/testadmission.py 0.0% 2 Missing ⚠️
build_system/builder/gatelaunch.py 50.0% 2 Missing ⚠️
build_system/builder/gate/sandboxschema.py 66.6% 1 Missing ⚠️
...ystem/builder/gate/tools/ci/run_bounded_command.py 0.0% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             main     #265     +/-   ##
=========================================
- Coverage    65.4%    65.3%   -0.2%     
=========================================
  Files        1450     1452      +2     
  Lines      127617   127973    +356     
  Branches    91731    91872    +141     
=========================================
+ Hits        83554    83613     +59     
- Misses      39120    39366    +246     
- Partials     4943     4994     +51     
Flag Coverage Δ
integration 17.3% <ø> (+<0.1%) ⬆️
linux-unit 70.5% <ø> (-0.1%) ⬇️
mcp-server 93.8% <ø> (ø)
python-sdk 98.7% <ø> (ø)
typescript-sdk 97.8% <ø> (ø)
unit 63.4% <23.0%> (-0.2%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
TypeScript SDK 97.8% <ø> (ø)
Python SDK 98.7% <ø> (ø)
Network 84.5% <ø> (+<0.1%) ⬆️
Security 81.6% <ø> (ø)
Tooling 88.6% <ø> (ø)
Monitoring 87.5% <ø> (-0.1%) ⬇️
Virtualization 64.4% <ø> (ø)
Confined Port Router 76.9% <ø> (ø)
Private Network 79.3% <ø> (ø)
Assets 80.8% <ø> (ø)
Gateway API 96.7% <ø> (ø)
Rust SDK 96.3% <ø> (ø)
Configuration 86.8% <ø> (ø)
Credentials 80.7% <ø> (ø)
Host Foundation 76.3% <ø> (+<0.1%) ⬆️
Core Platform 55.8% <ø> (ø)
Runtime 60.6% <ø> (ø)
Daemon 41.6% <ø> (ø)
Service 71.5% <ø> (ø)
Process 48.5% <ø> (ø)
Admin 63.7% <ø> (ø)
CLI 47.9% <ø> (ø)
MCP Server 93.8% <ø> (ø)
MCP Aggregator 61.8% <ø> (ø)
MCP Builtin 57.4% <ø> (ø)
Gateway 78.9% <ø> (ø)
TUI 68.5% <ø> (ø)
System Tray 53.2% <ø> (ø)
Guard 92.2% <ø> (ø)
UI 86.6% <ø> (ø)
Release Site 15.0% <ø> (∅)
Builder 43.4% <23.0%> (-0.1%) ⬇️
Mock Server 59.0% <ø> (ø)
Bench 47.8% <ø> (ø)
Files with missing lines Coverage Δ
build_system/builder/gate/candidate.py 67.5% <ø> (+1.6%) ⬆️
build_system/builder/gate/sandboxschema.py 85.5% <66.6%> (-0.9%) ⬇️
...ystem/builder/gate/tools/ci/run_bounded_command.py 0.0% <0.0%> (ø)
build_system/builder/gate/testadmission.py 32.0% <0.0%> (+1.2%) ⬆️
build_system/builder/gatelaunch.py 29.1% <50.0%> (+0.4%) ⬆️
build_system/builder/gate/timingratchet.py 28.8% <25.0%> (-0.7%) ⬇️
build_system/builder/gate/sandbox.py 34.0% <12.5%> (-1.3%) ⬇️
build_system/builder/gate/runledger.py 25.2% <20.0%> (-0.3%) ⬇️
build_system/builder/gate/runs.py 20.2% <10.0%> (-1.0%) ⬇️
build_system/builder/gate/runhistory.py 27.7% <26.0%> (-0.3%) ⬇️

... and 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…stry

# Conflicts:
#	build_system/tests/test_ownership.toml
…aits for readiness

The bounded wrapper selected its bytecode generation (a SHA-256 of every
Python source in the checkout) and then held it by selecting it again, so
each bounded command read the tree twice before its child existed.
`hold_environment` now takes the environment that was selected: one hash,
and the lease always names the generation the child was given.

The interrupt test waited a fixed two seconds for the child group; on a
loaded CI runner the wrapper's start-up missed that window, and the pipes the
failed test left open surfaced in the next test as unraisable ResourceWarnings.
It now waits for the child's atomically published pids, bounded only by the
wrapper's own timeout, and closes its pipes with a `with`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants