8000 test(e2e): close the round-one arch conditions end to end (T56) by minimal-foundry[bot] · Pull Request #2604 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

test(e2e): close the round-one arch conditions end to end (T56) - #2604

Merged
norrietaylor merged 8 commits into
mainfrom
agent/2544-conditions-closed-end-to-end
Oct 27, 2026
Merged

norrietaylor merged 8 commits into
mainfrom
agent/2544-conditions-closed-end-to-end

Conversation

@minimal-foundry
@minimal-foundry minimal-foundry Bot commented Oct 26, 2026 •
Copy link
Copy Markdown
Contributor

T56 — Conditions closed, end to end

slice: S9
kind: integration
covers: BEP-015, BEP-061, BEP-018, BEP-034
size: M
est: 0 code, 220 tests
executor: agent
difficulty: needs care
model: standard
diagnostics: each e2e case prints PASS or NOT RUN with its gate, and the daemon log tail names the cohort flag changes
observability: none beyond the cases' own output
layers:
- e2e:
- scripts/session-e2e.sh: one walk that runs the helper, rotation and cohort cases on a lane with a sign-in and E2E_BEP_PRIVATE_REPO, and records NOT RUN elsewhere (#2500)
test: ./scripts/session-e2e.sh bep_conditions_closed_end_to_end
produces: none
consumes: none
proof: the residuals the arch left open at merge are done: git in a grant box sends a header the proxy substitutes, an operator rotates a running proxy's signing certificate and the box keeps pushing, a blocked host_ip cohort sends no UDP 443, every store reference is checked at creation, and the CA deny set is the decided one. Its tasks re-cover requirements whose origin tasks merged with an arch condition held on a filed residual; the owner accepted that double coverage on 2026-10-24 so the residuals dispatch as one slice.
depends on:
- blocked by T50
- blocked by T51
- blocked by T52
- blocked by T53
- blocked by T54
- blocked by T55
- blocked by T58
- blocked by T59
- blocked by T60
- blocked by T61
- blocked by T62
- blocked by T63

Proof

A person can run ./scripts/session-e2e.sh bep_conditions_closed_end_to_end. It runs the git credential helper case (a grant box clones and pushes, so git sent a header the proxy substituted), the signing rotation case (the box keeps pushing after bep --rotate-signing), and a new host_ip cohort case. In the cohort case, a quic443 = "block" box makes UDP 443 from every host-address box get ICMP port unreachable, and the block lifts when that box leaves. At the end the walk prints PASS or NOT RUN with its gate for each case. The daemon log tail names the cohort stance changes. The store-reference check at creation and the CA deny set are not part of this walk. Their own tasks (T50 to T63) carry the tests for them.

Notes from the agent: On this box all three cases recorded NOT RUN: no E2E_BEP_PRIVATE_REPO, the proxy lane is macOS only, and there is no nft for the classifier install. So no case body ran here. The new cohort case (bep_host_ip_cohort_blocks_udp_443) is unverified, and it needs a native Linux host with nft, ip and passwordless sudo. The helper and rotation cases need the macOS VM lane with a sign-in and E2E_BEP_PRIVATE_REPO. No lane runs all three cases at once, because the proxy runs on macOS only and the cohort block runs only in a native daemon's classifier. Each case gates on its own facts, and the cohort case needs no sign-in. (Round 1 put the cohort case in the named-case dispatch only. Round 2 also added it to the whole-lane order, after proof_host_ip_deny_all, as arch C1 asked, so the ci-linux-native lane runs it.) not_run now also records each gate in E2E_NOT_RUN_WHY, so the walk can print it. The cohort case declares quic443 = "block" for the blocking member and does not use a grant box. This follows the precedent of bep_dns_steering_fails_closed_end_to_end, and on Linux it needs no sign-in. The rotation case header still says that no box ships a git credential helper until #2499 lands. That comment can be stale, and I did not change it.

Tests

line exit tail
./scripts/session-e2e.sh bep_conditions_closed_end_to_end 0 ::group::GitHub grant box: the shipped git credential helper sends a header the proxy substitutes (BEP-015) bep_git_credential_helper_sends_header: NOT RUN (no private repository named: set E2E_BEP_PRIVATE_REPO to /, a private repository the signed-in account can push to) ::endgroup:: :
ci-linux-native native-daemon-e2e at 83231b37, whole-lane order (https://github.com/gominimal/minimal/actions/runs/40439201715/job/121975209521) 0 box A alone, UDP 192.0.2.1:443 -> rc=0 ms=3006 · log: the cohort's stance changed to blocked when box B joined · log: box A's (01a17b3d-8016-730f-8acb-eded55684a93) own leaf was added to the set that is refused UDP 443 · box A beside B -> rc=1 ms=3 (Operation not permitted) · box B -> rc=1 ms=3 · stance back to open when B left · box A after B left -> rc=0 ms=3006 · host-address cohort: UDP 443 open alone, rejected for every member while one blocks, open again after it leaves

Verify

min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.99.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

toredEnv {
    |        ^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
    |
402 + #[must_use]
403 | pub fn deferring_env() -> StoredEnv {
    |

error: this method could have a `#[must_use]` attribute
    --> crates/boxes/src/core/compose.rs:1019:12
     |
1019 |     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |            ^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
     |
1019 ~     #[must_use]
1020 ~     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1085:5
     |
1085 |     pub fn as_sandbox_path(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1084:5
     |
1084 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use
     = note: `-D clippy::double-must-use` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1302:5
     |
1302 |     pub fn host_path(&self) -> &HostAbsPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1301:5
     |
1301 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1309:5
     |
1309 |     pub fn destination(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1308:5
     |
1308 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: could not compile `boxes` (lib) due to 6 previous errors
warning: build failed, waiting for other jobs to finish...

Closes #2544


Generated by Claude Code

Add bep_conditions_closed_end_to_end, which runs the git credential
helper, signing rotation and host_ip cohort cases and prints PASS or
NOT RUN with its gate for each. Add bep_host_ip_cohort_blocks_udp_443:
under its own classifier install, a quic443 = "block" box blocks UDP
443 for the cohort, and the block lifts when it leaves. not_run now
records each gate, so the walk can name it.
@minimal-foundry
minimal-foundry Bot requested a review from a team as a code owner October 26, 2026 05:58
@coderabbitai
coderabbitai Bot commented Oct 26, 2026 •
Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7e823344-ca46-4d60-abf8-6347d0362626

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@minimal-foundry
minimal-foundry Bot commented Oct 26, 2026 •
Copy link
Copy Markdown
Contributor Author

Approved: every review thread resolved at 83231b37dc75.

@norrietaylor resolved the last thread, which releases the approval this review had withheld.

Nothing to do.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread scripts/session-e2e.sh Resolved
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: CONDITIONS · 2 conditions · the full ruling

The cohort case tests §5.3 line 150 correctly, but no lane runs it. It is in the named dispatch only, and it is not in the whole-lane order. On CI it records NOT RUN when a gate misses, but proof_host_ip_deny_all fails there. A NOT RUN leg is open, so T56 does not yet prove the cohort block. Add the case to the whole-lane order (C1). Make a missing gate on CI a failure (C2).

Ruled at e165543 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
Comment thread scripts/session-e2e.sh Resolved
Place proof_bep_host_ip_cohort_blocks_udp_443 in the whole-lane order,
after proof_host_ip_deny_all and before the daemon-fetch proof, so a
native lane runs it. On CI a missing classifier gate is now a lane fault,
as in proof_host_ip_deny_all. Off CI and on a VM lane it stays NOT RUN.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 1 of 10 on a failed check suite, pushed as 207e19e67854.

line exit tail
./scripts/session-e2e.sh bep_conditions_closed_end_to_end 0 ::group::GitHub grant box: the shipped git credential helper sends a header the proxy substitutes (BEP-015) bep_git_credential_helper_sends_header: NOT RUN (no private repository named: set E2E_BEP_PRIVATE_REPO to /, a private repository the signed-in account can push to) ::endgroup:: :

Verify min task run agent-verify exited 101 under rustc 1.98.1, which the repository does not pin (1.99.0 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.

toredEnv {
    |        ^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
    |
402 + #[must_use]
403 | pub fn deferring_env() -> StoredEnv {
    |

error: this method could have a `#[must_use]` attribute
    --> crates/boxes/src/core/compose.rs:1019:12
     |
1019 |     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |            ^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#must_use_candidate
help: add the attribute
     |
1019 ~     #[must_use]
1020 ~     pub fn lifecycle_hooks_teardown(&self) -> impl DoubleEndedIterator<Item = &ProvenancedHook> {
     |

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1085:5
     |
1085 |     pub fn as_sandbox_path(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1084:5
     |
1084 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use
     = note: `-D clippy::double-must-use` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::double_must_use)]`

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1302:5
     |
1302 |     pub fn host_path(&self) -> &HostAbsPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1301:5
     |
1301 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: this function has a `#[must_use]` attribute with no message, but returns a type already marked as `#[must_use]`
    --> crates/boxes/src/core/primitives.rs:1309:5
     |
1309 |     pub fn destination(&self) -> &SandboxRelPath {
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
help: remove `must_use`
    --> crates/boxes/src/core/primitives.rs:1308:5
     |
1308 |     #[must_use]
     |     ^^^^^^^^^^^
     = note: alternatively, you may add an explicit reason to the `must_use` attribute
     = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#double_must_use

error: could not compile `boxes` (lib) due to 6 previous errors
warning: build failed, waiting for other jobs to finish...

Review threads the coder judged:

  • 👍 valid — scripts/session-e2e.sh:24828: Added proof_bep_host_ip_cohort_blocks_udp_443 to the whole-lane order, after proof_host_ip_deny_all and before proof_daemon_fetch_under_deny_all_host_address_box, with a comment that says why it goes there.
  • 👍 valid — scripts/session-e2e.sh:24827: The whole-lane order now calls proof_bep_host_ip_cohort_blocks_udp_443 between proof_host_ip_deny_all and the daemon-fetch proof.
  • 👍 valid — scripts/session-e2e.sh:12913: When ${CI:-} is set, a missing classifier gate now prints '::error::a CI native lane must be able to load the classifier table: $cq_why' and calls fail. Off CI and on a VM lane it still records NOT RUN.

A person can run ./scripts/session-e2e.sh bep_conditions_closed_end_to_end. It runs the git credential helper, signing rotation and host_ip cohort cases, and prints PASS or NOT RUN with its gate for each. A native lane's whole walk now also runs the cohort UDP 443 block case. On this box all three cases are NOT RUN, so this branch does not show the residuals closed live. That evidence is still owed by the macOS lane with a sign-in and E2E_BEP_PRIVATE_REPO, and by a native CI lane that can load the classifier table. The store-reference check at creation and the CA deny set have their own unit tests in crates/bep, which earlier tasks added.

Notes from the agent: The failed checks: the directive's log excerpt for the 'tests' job shows only passing nextest lines and the job cleanup, not the test that failed. No Rust test reads scripts/session-e2e.sh, and this branch changes only that script, so I did not find a cause in this diff. ci-linux-native-success is the lane aggregator and fails because 'tests' failed. A re-run of the job, or the full job log, is needed to name the failing test. shellcheck -S warning reports nothing on the script.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 3 unresolved threads — minimal-foundry[bot] scripts/session-e2e.sh:24828, minimal-arch[bot] scripts/session-e2e.sh:24827, minimal-arch[bot] scripts/session-e2e.sh:12913. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The compare closes the baseline's gaps. The host_ip cohort case now runs in the native lane order, and a missing classifier gate fails on CI. The case proves the §5.3 line 150 rule: the cohort is blocked with an active reject while one member blocks, and the block lifts when it leaves. The helper and rotation legs (BEP-015, BEP-061) are NOT RUN on every lane, because no lane sets E2E_BEP_PRIVATE_REPO. C1 holds them open on #2500, so the change can merge.

Ruled at 207e19e against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 2 of 10 on a failed check suite: the coder changed nothing. No change this round, on purpose. Failed checks: (1) The tests excerpt shows only passing tests. This branch changes only scripts/session-e2e.sh. The two Rust gates that read it pass locally: shellcheck through scripts/lint-shell.sh --strict, and the retired-spelling scan in crates/common/tests/remedy_strings.rs (grep finds no hits). The other Rust tests do not read this script. I did not find a cause for the tests failure in this branch. (2) The native-daemon-e2e excerpt is cut, and it shows no ::error:: line. Its last lines are the expected refusals from the expose cases at 06:25:26, and job cleanup starts at 06:26:24. I compared proof_bep_host_ip_cohort_blocks_udp_443 against proof_host_ip_deny_all, which runs just before it: the gates, the residue check, the daemon warm-up and placement, the seed, the log reader, the blocked-leaf path (scripts/install-host-classifier.sh, crates/minimald/src/net/classifier.rs QUIC443_BLOCKED_DIR) and the log message text all match.…[truncated]

Review threads the coder judged:

  • 👎 invalid — scripts/session-e2e.sh:13157: Correct that BEP-015 and BEP-061 print NOT RUN on every lane, but this task cannot fix that. No workflow or justfile recipe sets E2E_BEP_PRIVATE_REPO, and the cases also need a sign-in on the macOS lane. That lane wiring lives under .github/workflows/, which is frozen and outside this task's layers.

Copy link
Copy Markdown
Member

/revise

Round 3 of #2604, on the red tests and native-daemon-e2e checks at 207e19e6. No round is in flight. Round 2 changed nothing because its log excerpt held neither failure, so both are quoted here. The size cap is lifted for this epic.

  1. Merge main. This branch is 17 commits behind. Main now has fix(minimald): close the race between the cohort lock and the shim's leaf join (T73) #2595 (T73: the cohort lock and the shim's leaf join no longer race) and feat(minimald): reject UDP 443 from a blocked cohort's own leaves (T72) #2601 (T72: a blocked cohort's own leaves reject UDP 443). The new e2e case depends on both.
  2. tests: FAIL common::shell_lint all_scripts_pass_shellcheck. CI's shellcheck 0.9.0 reports SC2002 (style): Useless cat at the two lines this PR adds to scripts/session-e2e.sh (about lines 13080 and 13122): cq_members="$(cat "$cq_blocked_leaf/cgroup.procs" 2>/dev/null | wc -l | tr -d ' ')". Replace each with wc -l < "$cq_blocked_leaf/cgroup.procs" 2>/dev/null | tr -d ' ' in the same command substitution. Shellcheck 0.11.0 does not report SC2002 by default, so a local pass with it proves nothing.
  3. native-daemon-e2e: the case proof_bep_host_ip_cohort_blocks_udp_443 fails with "the open-stance box 01a176e3-… was not launched into its own leaf boxes/allow/01a176e3-… with per-box enforcement: no launch record". If it still fails after the merge, do what proof_host_ip_deny_all on main does: first launch a throwaway box, check that it reports per-box enforcement, and only then launch the real box. Make cq_fail print the launch-record lines as well as the stance-change lines, so the next failure shows its cause.
  4. Change nothing else. Run just test-one all_scripts_pass_shellcheck (or cargo nextest run -p common all_scripts_pass_shellcheck) and ./scripts/session-e2e.sh proof_bep_host_ip_cohort_blocks_udp_443 where the host allows it.

Generated by Claude Code

Launch a throwaway host-address box first, as proof_host_ip_deny_all
does, so box A is created against a per_box fact. cq_fail now prints
the launch records too. The cgroup.procs counts read wc -l from a
redirect, which shellcheck 0.9.0 asks for (SC2002).
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 4 unresolved threads — minimal-foundry[bot] scripts/session-e2e.sh:25005, minimal-arch[bot] scripts/session-e2e.sh:25004, minimal-arch[bot] scripts/session-e2e.sh:13052, minimal-arch[bot] scripts/session-e2e.sh:13332. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The compare changes only the cohort case's setup and diagnostics. The warm-up box adds an assertion and relaxes no gate, because each launch re-reads the host. The cohort case still proves §5.3 line 150 as an active reject, in the whole lane. The BEP-015 and BEP-061 legs still record NOT RUN on every lane. C1 holds them open on #2500 until the macOS lane records PASS for both.

Ruled at a268042 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 3 of 10 on a /revise note, pushed as a26804270931.

line exit tail
./scripts/session-e2e.sh bep_conditions_closed_end_to_end 0 ::group::GitHub grant box: the shipped git credential helper sends a header the proxy substitutes (BEP-015) bep_git_credential_helper_sends_header: NOT RUN (no private repository named: set E2E_BEP_PRIVATE_REPO to /, a private repository the signed-in account can push to) ::endgroup:: :

Verify min task run agent-verify passed.

On a lane with a sign-in, E2E_BEP_PRIVATE_REPO and a classifier-capable host, ./scripts/session-e2e.sh bep_conditions_closed_end_to_end walks the helper, rotation and cohort cases. Elsewhere it prints NOT RUN with the gate for each case. This round makes the cohort case warm the daemon's per-box fact with a throwaway box before box A, and its failure output now shows the launch records. This box ran no case past its gate, so the cases themselves are not proved here.

Notes from the agent: Revise round 3. Item 1: the merge of main was already on the branch (95c6328), and origin/main has no commits past it. Item 2: both SC2002 lines now read wc -l 2>/dev/null <"$cq_blocked_leaf/cgroup.procs" | tr -d ' '. I put 2>/dev/null before the input redirect, unlike the directive's form, because redirects apply left to right. In the directive's order a missing file prints its error to stderr. The local shellcheck is 0.11.0, so its pass does not prove the 0.9.0 result. No cat of cgroup.procs is left in the case. Item 3: I could not reproduce the CI failure here (no nft, no sudo). I applied the fallback anyway: a throwaway host-address box e2e-cohort-warm launches first, its launch record must say per_box, and then it is destroyed before box A launches. cq_unwind also destroys it. cq_fail now prints the tail of the launch-record lines before the stance-change lines. The directive names the case as proof_bep_host_ip_cohort_blocks_udp_443. The script takes it as bep_host_ip_cohort_blocks_udp_443, and I ran that name.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Revise round 2 ran against ci-linux-native-success, native-daemon-e2e and left it red; a coder round cannot clear it, a person should look. No round was started for the failed suite on a26804270931.

Copy link
Copy Markdown
Member

/revise

Round 4 of #2604, on the red native-daemon-e2e check at a2680427. No round is in flight.

The failure. bep_host_ip_cohort_blocks_udp_443 still fails: "the open-stance box 01a17b00-a470-… was not launched into its own leaf boxes/allow/01a17b00-a470-… with per-box enforcement: no launch record". The warm-up box from round 3 has its record (e2e-cohort-warm, per_box, 01:36:41.41Z). Box A has no record of any kind, and the error comes 0.38 s after the warm-up line.

The cause. A session box launches on its first exec, not at activate. proof_host_ip_deny_all says this in a comment and runs mnl session exec "$hida_sid" 'true' (retried once) before it greps its launch record. In CI, e2e-hida's activate returned at 01:36:20.89 and its launch record is stamped 01:36:23.37, after the exec. proof_bep_host_ip_cohort_blocks_udp_443 execs the warm-up box before its grep, but greps for box A's boxes/allow/$cq_open_sid straight after mnl session activate. Box A's first exec is the later test -x /usr/bin/socat.

  1. In proof_bep_host_ip_cohort_blocks_udp_443 in scripts/session-e2e.sh, run mnl session exec "$cq_open_sid" 'true' with the same one retry after 1 s that proof_host_ip_deny_all uses, before the launch-record grep for box A. Do the same for every other box in the case whose launch record is grepped, box B included.
  2. Make cq_fail also print the box's activate stderr file ($WORK/bep_host_ip_cohort_blocks_udp_443.*.err) when it exists.
  3. Change nothing else. Run just test-one all_scripts_pass_shellcheck and ./scripts/session-e2e.sh bep_host_ip_cohort_blocks_udp_443 where the host allows it.

Generated by Claude Code

A session box launches on its first exec, not at activate. The cohort
case now runs one exec, with one retry, in box A and box B before it
greps their launch record or stance change. cq_fail also prints the
case's stderr files.
…-closed-end-to-end

# Conflicts:
#	scripts/session-e2e.sh
@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The compare adds one exec in each cohort box before the case reads the daemon log. It also prints the case's stderr files on a failure. Both make the BEP-018 proof stronger, and neither relaxes a gate. The ruling on a2680427 stands for the rest. C1 keeps the three e2e legs open until each one prints PASS on its lane. The PR body still says the cohort case is in the named-case dispatch only. That is stale. Update it to say the case runs in the whole-lane order.

Ruled at 9c35508 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — advisory review

Verdict COMMENT — 1 finding, 1 inline.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 4 of 10 on a /revise note, pushed as 9c355083336a.

Resolved conflicts in: scripts/session-e2e.sh

line exit tail
./scripts/session-e2e.sh bep_conditions_closed_end_to_end 0 ::group::GitHub grant box: the shipped git credential helper sends a header the proxy substitutes (BEP-015) bep_git_credential_helper_sends_header: NOT RUN (no private repository named: set E2E_BEP_PRIVATE_REPO to /, a private repository the signed-in account can push to) ::endgroup:: :

Verify min task run agent-verify passed.

Review threads the coder judged:

  • 👎 invalid — scripts/session-e2e.sh:13617: The fact is true: no lane sets E2E_BEP_PRIVATE_REPO, so the helper and rotation cases print NOT RUN. The fix is not in scripts/session-e2e.sh. The macOS lane must set E2E_BEP_PRIVATE_REPO and sign in, and that is a .github/ workflow change, which this task may not touch. The hold stays on T82 — Run the Box Egress Proxy legs on the macOS lane #2500 and

On a native lane with the classifier, the cohort case now runs a first exec in box A and in box B before it reads their launch record and stance change, so box A's launch record exists when the case reads it. When the case fails, it prints its stderr files, the activate stderr included.

Notes from the agent: Round 4 addresses only the directive's items 1 and 2. Box A and box B each get mnl session exec <sid> 'true' with one retry after 1 s, the same as proof_host_ip_deny_all, before the launch-record grep (box A) and the stance-change grep (box B). The warm-up box already had this exec. cq_fail now prints every non-empty $WORK/bep_host_ip_cohort_blocks_udp_443.*.err file. Some error paths also cat their own file before cq_fail, so that file prints twice on a failure. This box has no nft, so the cohort case reports NOT RUN here, and the fix is unproven until native-daemon-e2e runs it.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Revise round 2 ran against ci-linux-native-success, native-daemon-e2e and left it red; a coder round cannot clear it, a person should look. No round was started for the failed suite on 9c355083336a.

@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 5 of 10 on the runtime's review findings: the coder changed nothing. Revise round 5: no code change. Both open threads ask for something this session cannot deliver with a commit. This box has no sudo, no nft, no VM, no GitHub sign-in and no E2E_BEP_PRIVATE_REPO. So I could not run any of the three cases, and I report no PASS for them. The PASS for the cohort case is owed by the native Linux CI lane. The PASS for the helper and rotation cases is owed by the macOS VM lane with a sign-in and E2E_BEP_PRIVATE_REPO (#2500). The cohort case stays in the whole-lane order. Thread PRRT_kwDOPdfcxM6wJtCu (arch C1) asked for that placement, and it was answered valid in round 2.

Review threads the coder judged:

  • 👎 invalid — scripts/session-e2e.sh:13636: The walk already records PASS for each case on a lane that has the case's gates. A PASS can only come from running it on those lanes: the native Linux CI lane for the cohort case, and the macOS VM lane with a sign-in and E2E_BEP_PRIVATE_REPO for the helper and rotation cases. No commit gives that ev
  • 👎 invalid — scripts/session-e2e.sh:25233: The placement is deliberate. Round 2 added the call to the whole-lane order because arch C1 (PRRT_kwDOPdfcxM6wJtCu) asked for it. The PR body sentence about named dispatch only is from round 1 and is out of date. The cohort case's gates (nft, ip, passwordless sudo, no existing install, the installer

Copy link
Copy Markdown
Member

/revise

Round 5 of #2604, on the red native-daemon-e2e check at 9c355083. No round is in flight. Round 4's exec gate worked, and the case now reaches the block.

The failure. UDP to port 443 from box A was not rejected at once while box B's quic443 = "block" blocks the cohort (expected 'Connection refused' within 2000 ms). The block works. Alone, box A's probe waited the full 3003 ms. Beside box B, it failed in 3 ms with socat[12] E write(5, …, 1): Operation not permitted. The daemon logged the stance change, and the blocked leaf holds 4 processes. A host-address box's socket lives in the host netns, so the reject runs in the local OUTPUT hook. There, nft reject sends the ICMP error and drops the packet, and a dropped locally generated packet fails sendmsg at once with EPERM. ECONNREFUSED would come only on a later send or recv, and socat exits on the first write error. cq_rejected was copied from the gvproxy case, where a remote switch rejects and 'Connection refused' is right.

  1. In proof_bep_host_ip_cohort_blocks_udp_443 in scripts/session-e2e.sh, make cq_rejected accept Operation not permitted or Connection refused, and keep rc != 0 and ms < 2000. The timing tells a reject from the 3 s path where nothing answers. Make cq_not_rejected refuse Operation not permitted as well.
  2. An errno cannot tell reject from a silent drop, so also assert, while box B blocks, that box A's own leaf is in the set. Either grep the daemon log for the line "added a host-address box's own leaf to the set that is refused UDP 443" with box A's box_id, or run sudo -n nft list set inet minimal_class quic443_blocked_leaves and find A's leaf. Add that log line to cq_fail's dumps.
  3. Fix the cq_probe comment that says socat reads ECONNREFUSED at once, and the case header. Change both ::error:: texts to name 'Operation not permitted'.
  4. Change no daemon or ruleset code. Run just test-one all_scripts_pass_shellcheck.

Generated by Claude Code

A host-address box's socket is in the host netns, so the reject runs in
the local OUTPUT hook and socat's send fails with Operation not
permitted. Also assert that box A's own leaf is in the refused set, and
dump those log records on failure.
@minimal-foundry
Copy link
Copy Markdown
Contributor Author

Round 6 of 10 on a /revise note, pushed as 83231b37dc75.

line exit tail
./scripts/session-e2e.sh bep_conditions_closed_end_to_end 0 ::group::GitHub grant box: the shipped git credential helper sends a header the proxy substitutes (BEP-015) bep_git_credential_helper_sends_header: NOT RUN (no private repository named: set E2E_BEP_PRIVATE_REPO to /, a private repository the signed-in account can push to) ::endgroup:: :

Verify min task run agent-verify passed.

On a native lane with nft and passwordless sudo, the cohort case now accepts the reject as the host netns reports it. Box A's probe fails at once with 'Operation not permitted' or 'Connection refused' in under 2000 ms. The case also asserts that the daemon log records box A's own leaf added to the set that is refused UDP 443, so a silent drop cannot pass. The helper and rotation cases still need a lane with a sign-in and E2E_BEP_PRIVATE_REPO.

Notes from the agent: Round 6. Item 1: cq_rejected accepts 'Operation not permitted' or 'Connection refused' and keeps rc != 0 and ms < 2000. cq_not_rejected refuses both strings. Item 2: after box B joins, the case polls the daemon log (up to 10 s) for "added a host-address box's own leaf to the set that is refused UDP 443" with box A's box_id (crates/minimald/src/net/classifier.rs log_set_change). cq_fail dumps the tail of those records. Item 3: the cq_probe comment, the case header and both ::error:: texts now name 'Operation not permitted'. Item 4: no daemon or ruleset code changed. This box has no nft, so the cohort case records NOT RUN here. The new assertion is unverified until native-daemon-e2e runs it.

@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approval withheld

Verdict COMMENT — APPROVE withheld: 7 unresolved threads — minimal-foundry[bot] scripts/session-e2e.sh:25311, minimal-arch[bot] scripts/session-e2e.sh:25310, minimal-arch[bot] scripts/session-e2e.sh:13316, minimal-arch[bot] scripts/session-e2e.sh:13636, minimal-arch[bot] scripts/session-e2e.sh:13642, …. No findings.

Panel: 3 of 3 personas ran (correctness, security, supply-chain).

@minimal-arch minimal-arch Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-review: PASS_WITH_CONDITIONS · 1 condition · the full ruling

The compare changes only the cohort probe, and it conforms to §5.7 line 218. The probe now accepts EPERM, because the reject runs in the local OUTPUT hook. The new check on box A's leaf in the refused set, together with the pinned reject verb, still tells a reject from a drop. All three legs of the walk are still NOT RUN. C1 keeps them open. Record the ci-linux-native result for the cohort case on this head. The helper and rotation legs stay on #2500.

Ruled at 83231b3 against gominimal/arch@109541a48c31 by claude-opus-5-5.

Comment thread scripts/session-e2e.sh Resolved
@minimal-foundry minimal-foundry Bot left a comment
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minimal-review — approved

Verdict APPROVE — every review thread is resolved; @norrietaylor closed the last one. The review of 83231b37dc75 withheld this approval on the threads open then. Posted as a comment: the App cannot approve its own pull request; the check and the label carry it.

@minimal-foundry minimal-foundry Bot added the review:approved minimal-review approved the current head label Oct 27, 2026
@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Own review at 83231b3. bep_conditions_closed_end_to_end walks the helper, rotation and cohort cases, and the cohort case is in the whole-lane order. On the ci-linux-native lane at this head it PASSed. Box A alone waited 3 s. Beside box B with quic443 = "block", A's send failed in 3 ms with EPERM, which is the local OUTPUT-hook reject. The daemon logged A's own leaf added to the refused set, which tells the reject from a drop. After B left, A sent again. With CI set, a missing classifier gate fails the lane. The helper and rotation legs need the macOS VM lane with a sign-in, and they are held on #2500 (T82), as the arch ruling at 83231b3 allows.


Generated by Claude Code

@norrietaylor norrietaylor changed the title T56 — Conditions closed, end to end test(e2e): close the round-one arch conditions end to end (T56) Oct 27, 2026
@norrietaylor norrietaylor left a comment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Babysitter approval at 83231b3: every merge gate passes at this head (arch PASS at 83231b3, zero open threads, every lane aggregator green). Squash title test(e2e): close the round-one arch conditions end to end (T56) and the squashed message pass commitlint. Queued for squash merge.


Generated by Claude Code

@norrietaylor
norrietaylor added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit b3dd589 Oct 27, 2026
37 checks passed
@norrietaylor
norrietaylor deleted the agent/2544-conditions-closed-end-to-end branch October 27, 2026 05:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review:approved minimal-review approved the current head

Projects

None yet

Development

Successfully merging this pull request may close these issues.

T56 — Conditions closed, end to end

1 participant

0