BOHICA-LABS / BOHICA-LABS/vsdd-factory

Phase-3 wave-close gate: require CI green before state-manager burst can advance state

Open
#492 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
2
Forks
1
Avg merge
6h 43m
Merged PRs (30d)
29

Description

## Summary

The Phase-3 wave-close gate currently marks a story CONVERGED when local `cargo test --workspace` is green and a PR is open. It does not require the PR's CI on GitHub Actions to be green before advancing state. This produced a false-convergence signal on STORY-017: 10 CLEAN adversarial passes, per-AC demo evidence recorded, PR opened — with CI red on macos-latest for 5 consecutive attempts. Only manual inspection surfaced the discrepancy; the state-manager burst was queued to close the story regardless.

## Observed instance

- Story: STORY-017 (akey — LOCAL_PEERPID peer PID capture on macOS)
- Adversarial: Pass 1..Pass 10 CLEAN
- Per-AC demos: recorded
- Local `cargo test --workspace`: green
- PR: open with `gh pr checks` reporting fail on macos-latest, 5 consecutive attempts
- State-manager burst: queued to advance the story to CONVERGED
- CI evidence: GHA run 28727397489 (AC-A1 integration test — `caller_pid = 0`)
- Downstream engine issue: see companion issue (tokio-worker starvation adversary rule)

The story looked ready to merge by every gate the engine checked. The only signal that would have caught the false convergence was `gh pr checks` on the PR — and the engine did not consult it.

## Root cause (engine)

The wave-close gate treats local test-suite success as sufficient evidence of runtime correctness. In practice, the release runs on GitHub Actions runners, not the developer's local machine. Scheduler behavior, kernel version, filesystem, resource contention, and macOS Gatekeeper posture all differ between local dev and CI. \"Green locally\" is a necessary but not sufficient condition for merge-readiness.

## Proposed engine rule

Add a `require-ci-green` gate to the `pr-manager` sub-flow. Gate contract:

1. Trigger: after PR is opened / updated by the story.
2. Command: `gh pr checks --watch` (or equivalent polling loop with a bounded timeout).
3. Success condition: all required checks report `SUCCESS` (or `NEUTRAL` where policy allows).
4. Failure condition: any required check reports `FAILURE`, `CANCELLED`, or `TIMED_OUT`.
5. On failure: block state-manager burst; return a pipeline error naming the failing check(s) and the run URL so the next agent can investigate.
6. On timeout: block with an explicit \"CI still running\" state rather than assuming success.

This gate is orthogonal to the story's own convergence criteria (adversarial passes, per-AC demos, local tests) — those measure the story's internal consistency. `require-ci-green` measures the story's compatibility with the runner the release actually uses. Both are required for correctness; neither substitutes for the other.

## Why this matters

Without this gate, the pipeline can produce a stream of \"CONVERGED\" stories whose PRs cannot be merged. This defeats the purpose of pipelined delivery: the state-manager tells downstream that the story is done, downstream schedules integration work, and the actual PR sits red for days. The engine's state and the repo's state diverge silently.

The fix is cheap: one `gh pr checks --watch` invocation gated behind PR-open. The cost is a delay proportional to CI runtime. The benefit is deterministic pipeline correctness.

## Cross-references

Precedents on engine methodology gaps discovered in the akey pipeline:

- #440
- #441
- #466
- #467
- #468

Companion issue in this batch: adversary rule for tokio-worker starvation (the substantive defect that STORY-017's CI-red PR exposed).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.