Skip to content

feat(rollout): promotion gate — enforce a consumed APPROVE review verdict, seal to evidence - #11

Open
mdheller wants to merge 1 commit into
mainfrom
feat/promotion-gate-issue-10
Open

feat(rollout): promotion gate — enforce a consumed APPROVE review verdict, seal to evidence#11
mdheller wants to merge 1 commit into
mainfrom
feat/promotion-gate-issue-10

Conversation

@mdheller

Copy link
Copy Markdown
Contributor

Closes #10.

What

Continuum owns the rollout promotion gate and its per-action evidence (LIFECYCLE §4). The review verdict it gates on is consumed from prophet-platform (tools/review_gate.py, this repo's CapD links.integration_target) — nothing is reviewed here.

  • tools/promotion_gate.py — verifies the reviewer's sealed verdict recomputes, requires verdict == APPROVE, and emits the decision (allow or block) to artifacts/gate-decisions/. Fail-closed: a tampered, non-APPROVE, or unsealed verdict blocks promotion.
  • CapD composes_with.review_gate pins the reviewer (pin-not-vendor).
  • LIFECYCLE §4 documents the gate; make rollout now depends on promotion-gate and fails closed without an APPROVE VERDICT.
  • validate.py requires the gate tool.

Boundary (per CONTINUUM_SCOPE.md)

Owned here: the promotion gate + evidence. Consumed, not reimplemented: the review logic/model (prophet-platform), source/workspace/runtime-release/scale-up (their canonical owners).

Validation evidence

  • make validateok: sourceos-continuum validation passed
  • python3 -m pytest tools/test_promotion_gate.py7 passed (allow · reject · needs-human · tampered-approve-still-blocks · missing-seal · block-is-evidenced · exit codes)
  • End-to-end: make rollout (no verdict) → BLOCKED; make rollout VERDICT=<approve> → promotes, seal verified, evidence written.

Known gap (explicit)

The live pinned reviewer invocation runs in the rollout pipeline where prophet-platform's reviewer is available; this PR wires the gate + evidence contract and enforces a verdict it is handed. Pairs with prophet-platform#1125 (the reviewer).

…dict, seal to evidence

Closes #10. Continuum owns the rollout promotion gate and its per-action evidence
(LIFECYCLE §4); the review VERDICT is consumed from prophet-platform (CapD
links.integration_target), not reviewed here.

- tools/promotion_gate.py: verify the reviewer's sealed verdict recomputes, require
  verdict==APPROVE, and emit the decision (allow OR block) to artifacts/gate-decisions/.
  Fail-closed — a tampered, non-APPROVE, or unsealed verdict blocks promotion.
- CapD composes_with.review_gate pins the reviewer (pin-not-vendor).
- LIFECYCLE §4 documents the gate; `make rollout` now depends on `promotion-gate` and
  fails closed without an APPROVE VERDICT.
- validate.py requires the gate tool; `make validate` passes. 7 tests (allow, reject,
  needs-human, tampered-approve, missing-seal, block-evidenced, exit codes).

Known gap (explicit): the live pinned reviewer INVOCATION runs in the rollout pipeline
where prophet-platform's reviewer is available; this wires the gate + evidence contract
and enforces a verdict it is handed.
Copilot AI review requested due to automatic review settings July 30, 2026 08:49

Copilot AI 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.

Pull request overview

This PR adds a rollout promotion gate to Continuum that consumes a sealed review verdict (from the prophet-platform reviewer), requires an APPROVE outcome, and emits an allow/block decision into the per-action evidence bundle.

Changes:

  • Introduces tools/promotion_gate.py + pytest coverage to enforce verdict == APPROVE and emit gate decisions as evidence.
  • Wires the gate into make rollout (fail-closed if no verdict is provided) and repo validation (tools/validate.py).
  • Updates CapD + lifecycle documentation to reflect the consumed review-gate dependency and evidence emission location.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tools/validate.py Requires the new promotion gate tool to exist as part of validation.
tools/promotion_gate.py Implements the promotion gating logic and evidence emission.
tools/test_promotion_gate.py Adds tests for allow/block behavior, seal recomputation, and exit codes.
Makefile Adds promotion-gate target and makes rollout depend on it.
docs/LIFECYCLE.md Documents the rollout promotion gate behavior and evidence location.
capd/continuum.local-paas.capd.json Declares the composed review_gate dependency.
artifacts/gate-decisions/.gitkeep Keeps the evidence directory tracked in git.
.gitignore Prevents committing runtime-emitted gate decision JSON artifacts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/promotion_gate.py
Comment on lines +28 to +32
"""Recompute the reviewer's seal over the verdict body. This is an integrity check on
consumed evidence, not a reimplementation of the review — it only proves the verdict
bytes were not altered between the reviewer and this gate. The seal is a sha256 over the
canonical JSON of every field except the seal itself; that contract is shared with the
producer (prophet-platform review_gate._seal_review)."""
Comment thread tools/promotion_gate.py
Comment on lines +60 to +64
reviewed = verdict.get("reviewed") or {}
key = str(reviewed.get("idempotency_key", "unknown")).replace("/", "_").replace("@", "-at-")
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
path = evidence_dir / f"{key}.{stamp}.json"
path.write_text(json.dumps(decision, indent=2, sort_keys=True) + "\n")
Comment thread tools/promotion_gate.py
Comment on lines +78 to +82
try:
verdict = json.loads(args.verdict.read_text())
except (OSError, json.JSONDecodeError) as exc:
print(f"BLOCK: cannot read a review verdict from {args.verdict}: {exc}", file=sys.stderr)
return 1
Comment thread Makefile
@echo "[continuum] rollout — scaffold: promote via caps.infra.cluster-scaleup.hyperswarm"
promotion-gate: ## rollout gate: require an APPROVE review verdict (fail-closed, evidence-emitting)
@test -n "$(VERDICT)" || (echo "[continuum] promotion-gate BLOCKED: set VERDICT=<review-receipt.json>" && exit 1)
python3 tools/promotion_gate.py --verdict $(VERDICT)
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.

Promotion gate: enforce the consumed review verdict before rollout, seal it into evidence

2 participants