Skip to content

broomva/p9

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

p9 — bstack P9: productive-wait primitive (the wait optimizer)

Never sleep on a blocking wait. P9 is a wait optimizer — turn any blocking external operation (PR CI, push-triggered deploys, builds, long indexing) into work on the next priority. PR CI is the canonical implementation today; the primitive is broader.

Why P9 exists

When an agent kicks off a long external operation and waits for it, the dumb pattern is sleep. P9 replaces it with productive-wait discipline:

  1. Notification via run_in_background — for PR CI, the observer is gh pr checks --watch. No polling.
  2. Productive wait — the agent drains a context-scoped queue (session → memory → graph → docs → Linear) while the operation runs.
  3. Self-heal — when CI fails for known categories (lint, format, codegen drift, flaky tests), P9 classifies and applies the heal command. Unknown failures escalate to a Linear ticket.
  4. Merge stays governed — P9 emits MERGE_READY; the existing .control/policy.yaml + control-gate-hook authorizes the actual merge. P9 owns mechanism, not policy.

Scope today vs. on roadmap

P9 currently tracks PR-scoped waits through the p9 watch <pr> CLI. That covers ~95% of agent waits in a typical session.

The remaining 5% — non-PR waits — are not yet wired into p9 watch. These include:

  • Push-triggered deploys — a push to main that fires a Vercel/Cloudflare deploy hook without opening a PR
  • Long-running test suites or builds — outside the CI surface
  • External index / sync operations — content pipelines, embeddings, search-index rebuilds

For these, the productive-wait discipline still applies: kick off next-priority work, then do one direct check on the operation's completion. Never sleep. Wiring these into p9 watch <kind> <ref> is on the roadmap.

Quick start

# 1. Install dependencies (stdlib-only at runtime; pytest for tests)
python3 -m venv .venv && source .venv/bin/activate
pip install -r tests/requirements-dev.txt

# 2. Wire policy blocks
# Add ci_watch: and ci_heal: to your .control/policy.yaml. See
# tests/fixtures/policy-good.yaml for a complete example.

# 3. Verify install
python3 scripts/p9.py doctor
# → p9 doctor: ok

# 4. Use it
gh pr create ... ; PR=42
python3 scripts/p9.py watch $PR --background
# In parallel: pull productive work while CI runs
python3 scripts/p9.py wait-queue pop
# When the bg-task notification fires, check terminal state:
python3 scripts/p9.py status --pr $PR --json

Subcommands

Command Purpose
p9 watch <pr> Spawn gh pr checks --watch in background, transition to WATCHING.
p9 status [--pr N] Show in-flight PRs and their state-machine position.
p9 wait-queue {push,pop,list,clear} Manage the productive-wait queue (5 sources, priority-ordered).
p9 heal <pr> --classify Read failure log, classify against the rubric (read-only — does not execute heals).
p9 events tail Stream P9 events (P1 conversation-bridge consumes these).
p9 merge-ready <pr> Mark a green PR as ready for metalayer-authorized merge.
p9 doctor Health-check: gh auth, state directory, policy blocks, rubric.

Architecture (one paragraph)

Pure Python, stdlib-only at runtime. State lives in ~/.config/broomva/p9/state.jsonl (append-only, JSONL with flock serialization, partial-write recovery on read). Failure classification is regex-only — no LLM in the hot path — driven by references/scoring-rubric.md (markdown is human-canonical; _builtin_rubric() in scripts/p9.py is code-canonical; a unit test asserts they stay in sync). The evaluator scores progress with a four-term weighted sum (signature change + failures decreased + budget remaining + classifier confidence) and forces escalation after two consecutive sub-floor cycles. Multi-PR concurrency is bounded by ci_watch.max_concurrent_prs (default 1). Everything fails closed on missing or malformed policy blocks.

Cardinal invariant

P9 never silently drops state. Every failure produces (a) a state.jsonl event, (b) a Linear ticket via the escalation channel, or (c) both. If neither write succeeds, P9 crashes loudly (exit 99) — degraded silent operation is forbidden.

Where it fits in the bstack

P3 (Linear ticket) → P4 (PR pipeline) → P9 (CI watcher + heal) → metalayer authorizes merge
                                              ↓ drains during wait
                                      {context queue, P5 worktree, P6 bookkeeping}

Composes with — does not duplicate — existing primitives. See AGENTS.md in the workspace repo for the full bstack specification.

Spec & design

The full design lives at broomva/workspace under docs/superpowers/specs/2026-05-04-p9-ci-watcher-design.md. Seven rounds of clarifying Q&A locked the architecture before a line of code was written.

Tests

python3 -m pytest tests/
# 46 passed

License

MIT — see LICENSE.

Related

About

bstack P9 — CI watcher + productive-wait primitive. Replaces sleep-based CI waits with an event-driven control loop, drains a context-scoped wait-queue while CI runs, classifies failures, and self-heals known categories. Merge authorization stays with the control metalayer.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors