diff --git a/agent-team/agent_team/dispatcher.py b/agent-team/agent_team/dispatcher.py index 82e682a..bc6a960 100644 --- a/agent-team/agent_team/dispatcher.py +++ b/agent-team/agent_team/dispatcher.py @@ -285,14 +285,6 @@ def _default_branch_pusher() -> BranchPusher: "-C", str(clone), "push", - # --no-verify: skip the operator's LOCAL pre-push dev hook (the - # secrev scanners backstop, which flags pre-existing whole-repo - # findings like the .env.example FP). The apply path's security - # is enforced CI-side — the agent-team-apply-verify workflow - # (guard denylist/scope/hash + the credential-less build-test) - # and the draft PR's own required checks scan the actual - # content. The local human-commit hook is not the apply gate. - "--no-verify", "--force-with-lease", "origin", head_branch, diff --git a/agent-team/ci/README.md b/agent-team/ci/README.md index 2964a2e..69e05d4 100644 --- a/agent-team/ci/README.md +++ b/agent-team/ci/README.md @@ -1,14 +1,7 @@ # agent-team/ci — split-job CI apply/verify workflow (Plane-2 leaf) -> **MOVED + LIVE (2026-06-22):** the workflow is now a registered GitHub Actions -> workflow at **`.github/workflows/agent-team-apply-verify.yml`** (repo root) — -> GitHub Actions only runs workflows under `.github/workflows/`, so the prior -> `agent-team/ci/` location was inert scaffolding. The privileged steps are -> flipped live, gated by the `agent-apply` environment's required reviewer; the -> trusted-dispatcher transport is `agent_team/dispatcher.py`. This directory now -> holds docs only. - -The **split-job CI apply/verify workflow** turns a builder agent's +Pre-deployment scaffolding for the R720 agent-team SDLC pipeline. This directory +holds the **split-job CI apply/verify workflow** that turns a builder agent's **untrusted candidate diff** into a verified **draft PR** — the §3.3.2 trust boundary, Phase P3 (§7.1) of `../../docs/r720-agent-team-design.md`. diff --git a/.github/workflows/agent-team-apply-verify.yml b/agent-team/ci/agent-team-apply-verify.yml similarity index 98% rename from .github/workflows/agent-team-apply-verify.yml rename to agent-team/ci/agent-team-apply-verify.yml index e18c6ee..d1392ed 100644 --- a/.github/workflows/agent-team-apply-verify.yml +++ b/agent-team/ci/agent-team-apply-verify.yml @@ -742,15 +742,8 @@ jobs: # mangling is done anywhere. A path that cannot be cleanly decoded is # treated as a VIOLATION (fail closed). git config core.quotepath false - # Write the scratch capture files OUTSIDE the checkout ($RUNNER_TEMP) so - # the `git status --untracked-files=all` below does not see — and flag — - # the check's OWN temp files as out-of-scope writes (they would otherwise - # appear as untracked and fail a narrow declared_scope). - _DIFF_Z="${RUNNER_TEMP:-/tmp}/_build_diff_z.bin" - _STATUS_Z="${RUNNER_TEMP:-/tmp}/_build_status_z.bin" - export _DIFF_Z _STATUS_Z - git diff -z --name-only HEAD > "$_DIFF_Z" || true - git status --porcelain=v1 -z --untracked-files=all > "$_STATUS_Z" || true + git diff -z --name-only HEAD > ./_build_diff_z.bin || true + git status --porcelain=v1 -z --untracked-files=all > ./_build_status_z.bin || true python3 - <<'PY' from __future__ import annotations @@ -892,7 +885,7 @@ jobs: """`git diff -z --name-only` records: each NUL field is one path.""" ok: list[str] = [] bad: list[bytes] = [] - for rec in _read_z(os.environ["_DIFF_Z"]): + for rec in _read_z("./_build_diff_z.bin"): dec = _decode(rec) (ok if dec is not None else bad).append(dec if dec is not None else rec) return ok, bad @@ -908,7 +901,7 @@ jobs: """ ok: list[str] = [] bad: list[bytes] = [] - recs = _read_z(os.environ["_STATUS_Z"]) + recs = _read_z("./_build_status_z.bin") i = 0 while i < len(recs): rec = recs[i] diff --git a/agent-team/tests/test_apply_verify_workflow_hardening.py b/agent-team/tests/test_apply_verify_workflow_hardening.py index e5f0d4c..41d06b9 100644 --- a/agent-team/tests/test_apply_verify_workflow_hardening.py +++ b/agent-team/tests/test_apply_verify_workflow_hardening.py @@ -34,12 +34,7 @@ import pytest yaml = pytest.importorskip("yaml") -_WORKFLOW = ( - Path(__file__).resolve().parents[2] - / ".github" - / "workflows" - / "agent-team-apply-verify.yml" -) +_WORKFLOW = Path(__file__).resolve().parents[1] / "ci" / "agent-team-apply-verify.yml" def _doc() -> dict: @@ -390,18 +385,9 @@ def _run_post_build( script = tmp_path / "post_build.py" script.write_text(_extract_post_build_script(), encoding="utf-8") - diff_z_path = tmp_path / "_build_diff_z.bin" - status_z_path = tmp_path / "_build_status_z.bin" - diff_z_path.write_bytes(diff_z) - status_z_path.write_bytes(status_z) - # The script now reads its capture files from $_DIFF_Z / $_STATUS_Z (written - # outside the checkout in CI so the check's own temp files are not flagged). - env = dict( - os.environ, - DECLARED_SCOPE=scope, - _DIFF_Z=str(diff_z_path), - _STATUS_Z=str(status_z_path), - ) + (tmp_path / "_build_diff_z.bin").write_bytes(diff_z) + (tmp_path / "_build_status_z.bin").write_bytes(status_z) + env = dict(os.environ, DECLARED_SCOPE=scope) result = subprocess.run( [sys.executable, str(script)], env=env, diff --git a/agent-team/tests/test_ci_gate_workflow.py b/agent-team/tests/test_ci_gate_workflow.py index 7511019..3a02fa4 100644 --- a/agent-team/tests/test_ci_gate_workflow.py +++ b/agent-team/tests/test_ci_gate_workflow.py @@ -23,12 +23,7 @@ from pathlib import Path import pytest -_WORKFLOW = ( - Path(__file__).resolve().parents[2] - / ".github" - / "workflows" - / "agent-team-apply-verify.yml" -) +_WORKFLOW = Path(__file__).resolve().parents[1] / "ci" / "agent-team-apply-verify.yml" def _extract_guard_script() -> str: diff --git a/docs/agent-team-smoke.md b/docs/agent-team-smoke.md new file mode 100644 index 0000000..9f119bf --- /dev/null +++ b/docs/agent-team-smoke.md @@ -0,0 +1 @@ +agent-team P3 live smoke test — safe to close/delete this PR.