Commit graph

5 commits

Author SHA1 Message Date
f46d691e36 docs(agent-team): document the plan-review decision gate (Phase C)
README: two human gates (clarifier + plan-decision), the approve/request-changes/
abandon verbs, free-text-defaults-to-request-changes, MAX_PLAN_GATE_VISITS, and
the planner max_turns reliability fix.
OPERATOR-RUNBOOK: how the gate appears in Slack, the three decision paths
(buttons/modal/free-text), the single-open-gate invariant, ceiling→PARKED, and
the 24h expiry→PARKED→recovery (re-assign / force-resume).
DEPLOY-R720: the pending_questions.kind ledger migration (SCHEMA_VERSION→4,
idempotent additive ALTER on startup) + rollback (restore the ledger backup
before restart if the migration fails).
2026-06-24 11:30:54 -04:00
a8f00ff676 feat(agent-team): operator dispatch command + runbook fixes
- run-team.py: add the 'dispatch <thread_id>' operator command (P3 option-b).
  The read-only box parks at DISPATCH; this completes it with a just-in-time
  WRITE token: reads candidate_diff + scope from the checkpoint (or --diff/--scope
  files), pushes the head branch + fires workflow_dispatch via dispatch_apply_verify,
  prints the located run_id, and (--write-back) writes it into the task checkpoint
  so VERIFY binds. +2 tests.
- OPERATOR-RUNBOOK: fix the misleading 'systemctl show -p Environment' check (it
  does NOT show EnvironmentFile= vars) -> use /proc/<MainPID>/environ +
  _p3_env_is_configured(); document the operator-initiated dispatch flow + the
  fine-grained-token write-probe caveat.

Suite green, ruff clean. Branch only; not merged.
2026-06-23 20:49:09 -04:00
cb84629c2b feat(agent-team): P3 Phases A/B/E — safety tooling, wiring, docs
Phase A (safety):
- scripts/p3_rollback.sh (+test): restore all privileged P3 surfaces from a
  recorded baseline; --dry-run default, --apply gated. Correct App-uninstall
  (App JWT) model; per-task env-reviewer restore by numeric id; real
  protection post-restore assert (normalize reads argv, fails loud, divergent
  state exits non-zero — regression-tested). KNOWN-LIMITATIONS header flags the
  branch-protection GET->PUT transform + live-validation for the C1 gate.
- scripts/assert_no_write_token.py (+test): box/CI audit that no write token
  (incl. ghu_/ghr_ prefixes + App PEM) lives on the box.
- draft_pr_monitor.py (+test): runaway (>3/15min) + stale (7d) draft-PR sweep,
  wired into tick() and bound a read-only provider in serve.

Phase B (wiring): systemd EnvironmentFile P3 vars + verification; new-draft-PR
lifecycle notice.

Phase E (docs): P3-LIVE-FLIP-PLAN/README/ci-README reflect CI-live-since-6/22 +
box-integration; runbook consolidated (rollback Incident 7 + box-env wiring);
removed a stray duplicate runbook.

Suite: 1360 passed, ruff clean. Branch only; not merged/deployed.
REMAINING HUMAN GATES: C1 /sh-security-review + GPT-4.1 cross-review on the
enabled workflow + rollback script; D box deploy + smoke + merge.
2026-06-23 19:52:04 -04:00
2e5972c476 docs(integration): document WS0-WS5 components + WS-rollout deploy 2026-06-23 15:49:40 -04:00
Adam Moussa
2d1dca0804
feat(agent-team): deploy-readiness — serve starts Slack listener + systemd + provisioning docs (#23)
* fix(agent-team): serve() starts the inbound Slack listener (D-1)

Coordinator.serve() now constructs and starts the SlackListener concurrently
with the tick/drain loop on a background daemon thread, but ONLY when the live
transport is a SlackTransport AND SLACK_APP_TOKEN is configured. When Slack is
not the transport or the app token is absent, serve() behaves exactly as before
(tick/recover only) — Slack is never made mandatory.

- New injectable build_listener seam + default_slack_listener_factory sharing
  the coordinator's own transport, ledger db_path, and resume_queue put.
- AUTHZ-01 owner-allowlist + open-status CAS untouched: serve() sources
  AGENT_TEAM_SLACK_OWNER_IDS in SlackListener.serve, which still fails closed.
- SlackListener.close() added for clean Socket Mode teardown on shutdown;
  serve() stops the listener + joins the thread in a finally.
- Tests: start-when-Slack+app-token, no-start otherwise, clean shutdown,
  idempotent start, serve start/stop around the loop, listener close().

* fix(agent-team): systemd unit loads ~/orchestrator/.env + uses venv python (D-2/D-7)

D-2: add EnvironmentFile=-/home/adam/orchestrator/.env (optional '-') so the P2
GPT-4.1 review loop's cross_reviewer sub-process can read the non-Claude provider
key once a task reaches REVIEW. Mirrors the sea-haven-secrev unit.

D-7: point ExecStart at the agent-team venv interpreter
(/home/adam/orchestrator/agent-team/.venv/bin/python) instead of
/usr/bin/env python3, which resolved the system interpreter without the
installed deps under systemd's PATH.

All hardening (NoNewPrivileges / ProtectSystem=full / ProtectHome=read-only /
ReadWritePaths) is retained unchanged (locked decision).

* docs(agent-team): land provisioning + operator runbooks under docs/provisioning

- PROVISIONING-RUNBOOK.md: merged final state (6 checkers, dep-bump fixer, P5
  intake-checker loop), SLACK_CHANNEL_ID, the gated P3-live flip steps (GitHub
  App + agent-apply env + gated_build_verify_wiring), and D-1/D-2/D-7 marked
  FIXED so the demo can use the live Slack answer path.
- P1-DEMO-SCRIPT.md: live Slack answer path now available (D-1 fixed); both the
  Slack and operator-CLI answer paths documented for all four exit criteria.
- DEPLOY-AUDIT.md: D-1/D-2/D-7 RESOLVED (this PR); D-4/D-5 dep pinning and the
  operator-CLI divergence kept as provisioning notes.
- OPERATOR-RUNBOOK.md (new): incident handling for pipeline stalls, parked tasks,
  failed HITL resumes, budget exhaustion, transport outages, and
  COMPLACENCY/COVERAGE alarms — each grounded in real run-team.py verbs, plus the
  re-alarm-backoff -> Jira-after-N-nights escalation ladder (design §5/§6.6).

* fix(agent-team): supervise the Slack listener thread — recurring ALARM + respawn

sh-security-review (logic) MEDIUM: a crashed listener thread was logged once,
then the daemon ran on 'deaf' — posting clarifier questions but receiving no
answers, every gate silently parking, process never exiting so systemd
Restart=on-failure never fired. serve() now calls _supervise_slack_listener()
each pass: when the listener is enabled but its thread is dead, it emits a
recurring ERROR ALARM and respawns via the idempotent starter (self-heal).
No-op when alive or disabled. +3 tests. (authz detector: wiring clean — AUTHZ-01
fail-closed allowlist + open-status CAS intact, dead listener fails SAFE.)
2026-06-18 16:56:21 -04:00