feat(agent-team): P5 cross-plane loop — checker finding -> pipeline task (opt-in) #18

Merged
amoussa1229 merged 2 commits from feature/agent-team-p5-crossplane into main 2026-06-18 19:56:53 +00:00
amoussa1229 commented 2026-06-18 19:54:46 +00:00 (Migrated from github.com)

What

Closes the Plane-1 -> Plane-2 cross-plane loop (P5): a confirmed Plane-1 checker FINDING becomes a Plane-2 human-gated pipeline TASK, so a high/critical drift or CVE finding can flow into the SDLC pipeline as a remediation task.

This is Plane-2 P5 (intake side), NOT the Plane-1 fixer. It is buildable now against the existing checker finding schema and the existing Plane-2 intake; the live end-to-end close needs the checkers provisioned (gated), so this ships the wiring + tests and stays OPT-IN / inert by default.

Files

  • agent-team/agent_team/transport/checker_intake.py — new intake module (mirrors github_intake).
  • agent-team/tests/test_checker_intake.py — 28 hermetic unit tests.
  • agent-team/run-team.py — new intake-checker subcommand (opt-in), plus docstring entry.

Mechanism reused

Calls the same committed coordinator intake entry github_intake uses:
Coordinator.start_task(*, task_text: str, transport_name: str) -> str.
Per the documented gotcha, task_text is coordinator-side intake metadata (logged, sanitized) — the graph builds its own INTAKE seed and takes only thread_id/transport. We do not reach past that contract.

Selection + de-dup

  • Selects findings where status == "confirmed" AND severity >= threshold (default high). Unverified/suppressed/below-threshold dropped; the schema's unverified severity marker never meets a real threshold; unknown threshold rejected.
  • De-dup keyed by stable identity: the finding id (checkers mint <repo>-<slug>), else a content-hash of checker+repo+title+severity. Identity recorded only after start_task returns (no silent drop on a failing intake — retryable next pass).
  • Durability caveat: de-dup is in-memory per process, matching the github_intake discipline — it does NOT survive a restart. A ledger-backed table of ingested finding ids (mirroring pending_questions) is the known FOLLOW-UP and is intentionally not shipped here.

Untrusted-input hygiene

Checker findings carry repo-controlled strings (title, proof summary, repo name). Every such field is run through _sanitize (newline/CR/tab/C0-control escaped to visible form, length-bounded) before it reaches the rendered task text OR the operator log — mirroring the coordinator's start_task log-injection hardening. Tests assert a forged multi-line title cannot inject a fake task/log line.

Opt-in confirmation

Exposed ONLY as the intake-checker run-team subcommand (like intake-github). NOT wired into Coordinator.serve or _cmd_serve — a test asserts neither references the checker intake. The always-on default path is unchanged.

Verify

  • ruff check . clean, ruff format --check . clean.
  • python -m pytest -q -> 823 passed (28 new in test_checker_intake.py).

Constraints honoured

  • requirements.txt NOT touched (no new dep — stdlib only: hashlib/json/logging/pathlib).
  • Bash checkers and checker_coordinator.sh NOT touched.

For a reviewer to scrutinise

  • The chosen transport for resulting tasks defaults to github (findings are about org repos). Confirm that's the desired clarifier channel.
  • Report shape assumption: top-level {..., "findings":[...]} matching the bash checker emit (bare array + dir-of-*.json also accepted). A malformed report file raises rather than silently skipping.
  • Pre-push scanner note: the global whole-worktree scan crashes with xargs: command line cannot be assembled, too long due to nested .claude/worktrees/ copies (environment artifact). Scoped to this PR's three files the scanners report 0 semgrep/gitleaks findings in changed code; the only BLOCK is the known machine-suppressed .env.example gitleaks false-positive in an untouched file. Pushed with --no-verify per task guidance.
## What Closes the **Plane-1 -> Plane-2 cross-plane loop (P5)**: a confirmed Plane-1 checker FINDING becomes a Plane-2 human-gated pipeline TASK, so a high/critical drift or CVE finding can flow into the SDLC pipeline as a remediation task. This is **Plane-2 P5** (intake side), NOT the Plane-1 fixer. It is buildable now against the existing checker finding schema and the existing Plane-2 intake; the live end-to-end close needs the checkers provisioned (gated), so this ships the wiring + tests and stays **OPT-IN / inert by default**. ## Files - `agent-team/agent_team/transport/checker_intake.py` — new intake module (mirrors `github_intake`). - `agent-team/tests/test_checker_intake.py` — 28 hermetic unit tests. - `agent-team/run-team.py` — new `intake-checker` subcommand (opt-in), plus docstring entry. ## Mechanism reused Calls the same committed coordinator intake entry `github_intake` uses: `Coordinator.start_task(*, task_text: str, transport_name: str) -> str`. Per the documented gotcha, `task_text` is coordinator-side intake metadata (logged, sanitized) — the graph builds its own INTAKE seed and takes only `thread_id`/`transport`. We do not reach past that contract. ## Selection + de-dup - Selects findings where `status == "confirmed"` AND `severity >= threshold` (default `high`). Unverified/suppressed/below-threshold dropped; the schema's `unverified` severity marker never meets a real threshold; unknown threshold rejected. - De-dup keyed by stable identity: the finding `id` (checkers mint `<repo>-<slug>`), else a content-hash of checker+repo+title+severity. Identity recorded only **after** `start_task` returns (no silent drop on a failing intake — retryable next pass). - **Durability caveat:** de-dup is **in-memory per process**, matching the `github_intake` discipline — it does NOT survive a restart. A ledger-backed table of ingested finding ids (mirroring `pending_questions`) is the known FOLLOW-UP and is intentionally not shipped here. ## Untrusted-input hygiene Checker findings carry repo-controlled strings (title, proof summary, repo name). Every such field is run through `_sanitize` (newline/CR/tab/C0-control escaped to visible form, length-bounded) before it reaches the rendered task text OR the operator log — mirroring the coordinator's `start_task` log-injection hardening. Tests assert a forged multi-line title cannot inject a fake task/log line. ## Opt-in confirmation Exposed ONLY as the `intake-checker` run-team subcommand (like `intake-github`). NOT wired into `Coordinator.serve` or `_cmd_serve` — a test asserts neither references the checker intake. The always-on default path is unchanged. ## Verify - `ruff check .` clean, `ruff format --check .` clean. - `python -m pytest -q` -> **823 passed** (28 new in `test_checker_intake.py`). ## Constraints honoured - `requirements.txt` NOT touched (no new dep — stdlib only: hashlib/json/logging/pathlib). - Bash checkers and `checker_coordinator.sh` NOT touched. ## For a reviewer to scrutinise - The chosen transport for resulting tasks defaults to `github` (findings are about org repos). Confirm that's the desired clarifier channel. - Report shape assumption: top-level `{..., "findings":[...]}` matching the bash checker emit (bare array + dir-of-`*.json` also accepted). A malformed report file raises rather than silently skipping. - Pre-push scanner note: the global whole-worktree scan crashes with `xargs: command line cannot be assembled, too long` due to nested `.claude/worktrees/` copies (environment artifact). Scoped to this PR's three files the scanners report **0** semgrep/gitleaks findings in changed code; the only BLOCK is the known machine-suppressed `.env.example` gitleaks false-positive in an untouched file. Pushed with `--no-verify` per task guidance.
This repo is archived. You cannot comment on pull requests.
No description provided.