A project management package for AI coding harnesses. It ships two complementary surfaces that share the same eight agents:
| Surface | Provider | Entry point | State store |
|---|---|---|---|
pm skill |
Any (Claude, AGY, OpenCode, Gemini, ...) | /pm in your harness |
beads + git |
auto-sprint workflow |
Claude Code only | /auto-sprint in Claude Code |
beads (no PLAN.md) |
The pm skill is the provider-agnostic path: invoke it in any harness and it
drives the full plan -> develop -> harvest lifecycle via natural language.
The auto-sprint workflow is Claude-only and fully deterministic: a JavaScript
loop drives eight agents through repeating cycles until a user-defined quality
bar (zero P1 issues, zero P1/P2 issues, etc.) is met or the cycle limit is reached.
No agent ever decides whether to continue -- all routing is in the workflow script.
while (open issues above goal threshold > 0 AND cycles < max):
Plan -- planner (opus) decomposes sprint goals into a feature+task DAG in beads
plan-reviewer validates coverage, acceptance criteria, and assigns
a complexity bucket (S/M/L) and model to every task
Develop -- doer works bd-ready tasks on the model the planner assigned;
reviewer approves or reopens (reviewer model >= sonnet)
Deploy -- deployer follows deploy.md (deploy + smoke test)
Test Run -- integ-test-runner runs integ-test-playbook.md end to end
(real functional suite, then sandbox up -> smoke sprint ->
teardown); closes passing features, files bugs for failures
Exit check -- beads query: are open issues above threshold? same set as last cycle?
CI check (haiku, non-blocking): polls after PR is created; annotates PR when not green
Harvest (once): harvester writes sprint analysis, updates docs/CHANGELOG, raises PR
After the plan is approved, the workflow produces a cost quote for the sprint -- three scenarios (optimistic / expected / pessimistic) -- using per-task complexity buckets and the model each task was assigned. All arithmetic is pure JavaScript; no agent does any calculation.
At sprint end, actual token spend (from the durable sprint log) is compared against
the quote and written to CHANGELOG. The harvester then updates
sprint-logs/calibration.json with rolling-average actuals, so each successive
sprint produces tighter estimates. The calibration loop targets +-50% accuracy;
500%+ deviation triggers a calibration failure flag.
Model prices used for estimation: haiku $5/M, sonnet $15/M, opus $25/M output tokens.
Sprint logs are durable per-branch outputs named
sprint-logs/<branch>-<yyyymmdd_hhmmss>.jsonl and are never deleted.
After the beads export/cleanup step and before PR creation, the Harvest phase
automatically runs bd dolt push to sync the Dolt remote. Failure is non-fatal
-- a missing remote or network error logs a warning and harvest continues.
The sprint analysis artifact (sprint-logs/<branch>-<timestamp>.analysis.md)
now includes a Sprint Execution Summary section: cycles run (with develop
iteration count, reviewer CHANGES NEEDED rounds, and plan re-rounds), per-phase
dispatch/token/cost breakdown, failures/retries, and remaining risks at close.
The summary is generated even when goalMet=false.
The develop loop includes three protections against doer context exhaustion:
- JIT task close -- the doer closes each task immediately after committing it, before claiming the next one. Completed work is always recorded even if the session ends mid-streak.
- Streak token-ceiling --
truncateStreakToCeiling()caps each streak to the longest prefix whose estimated output tokens fits undercalibration.doer_token_ceiling[tier](tunable per model tier insprint-logs/calibration.json). - Null-return recovery -- if the doer dispatch returns null, orphaned
in_progress tasks are reset to open and the loop retries instead of aborting.
The
MAX_DEV_ITER=20bound still applies.
The workflow logs structured entries at each develop iteration: task ids + estimated USD before the doer dispatch, ready-task count at iter entry, and reviewer verdict (APPROVED / CHANGES NEEDED) with task ids after review. Agent session labels carry the same task-id suffix for searchability.
parseBlockers() accepts an optional rootIds argument. When provided, only
open issues whose id is in the sprint's root set count as blockers. Unrelated
open P1 issues anywhere in the beads database do not prevent goalMet.
When no CI is configured for a project, the workflow creates a Add CI pipeline to project beads task. Before creating it, the workflow searches for an open
task with that name. If one already exists it is reused; a duplicate is never
filed. A previously closed task does not suppress creation of a new one -- the
guard is scoped to open tasks only.
See docs/sprint-workflow.md for the full user guide and docs/dispatch-patterns.md
for the architectural decisions governing agent dispatch, parallelism, and
develop-loop resilience.
The pm skill drives the same agents via natural language from any harness.
See skills/pm/SKILL.md and its sub-docs for the full workflow.
When running in fleet mode, the pm skill selects members by tags
(tags: ['doer'] / tags: ['reviewer']) rather than the legacy role
parameter. Multi-tag queries narrow selection by capability (e.g.
list_members(tags: ['reviewer', 'bitbucket'])); fall back to the single-tag
query when no member matches. compose_permissions must be called before every
fleet dispatch, and a tag switch always requires a fresh dispatch
(resume=false). See docs/pm-tag-dispatch.md for the full design and
invariants.
skills/pm/ the pm skill (SKILL.md + sub-docs)
agents/ eight sprint agent definitions (shared by both surfaces)
.claude/workflows/ auto-sprint.js -- deterministic Claude Code workflow
lib/ sprint-cost.mjs -- testable cost arithmetic module
test/ sprint-cost.test.mjs -- 45 unit tests (npm test)
sprint-logs/ calibration.json + per-sprint JSONL cost logs (durable)
install.mjs installer: copies skill + agents + workflow into provider config dir
e2e/ end-to-end suite: drive the skill headless on the toy repo
docs/ sprint-workflow.md user guide + design intent; dispatch-patterns.md
.githooks/ pre-commit (ASCII-only guard)
Installs the skill, agents, and (for Claude) the workflow into your harness config.
node install.mjs --llm claude # or: gemini | agy | opencode (default: claude)
This writes:
<configDir>/skills/pm/-- the pm skill<configDir>/agents/*.md-- eight agents<configDir>/settings.json-- minimal permissions (merged, non-destructive)~/.claude/workflows/auto-sprint.js-- the auto-sprint workflow (claude only)
Requires git, gh (GitHub CLI), and beads (bd) on PATH.
Claude Code -- trigger the deterministic multi-cycle workflow:
/auto-sprint {"branch": "feat/auth-overhaul", "issues": ["BD-12", "BD-15"], "goal": "P1/P2"}
| Argument | Required | Default | Description |
|---|---|---|---|
branch |
yes | -- | Sprint branch. Created if it does not exist. |
issues |
yes | -- | Beads sprint goal IDs to implement this sprint. |
goal |
no | P1/P2 |
Exit criterion: P1, P1/P2, or P1/P2/P3. |
max_cycles |
no | 5 |
Hard ceiling on sprint cycles. |
requirementsFile |
no | -- | Additional context file for the planner. |
base_branch |
no | main |
PR target branch. |
Deploy and integration test phases require deploy.md and integ-test-playbook.md
in the project root; without them the workflow skips those phases and proceeds
directly to harvest.
Other providers -- invoke the pm skill:
/pm implement the auth overhaul sprint goals (BD-12, BD-15) on branch feat/auth-overhaul
e2e/run-e2e.mjs clones the toy repo, renders the scenario with the repo path and
a unique branch, invokes the provider CLI headless with the skill installed, and
reads the checkpoints.json the orchestrator writes. The sprint runs the full
lifecycle -- it pushes the branch and raises a real PR on the toy (no merge); the
runner closes that PR and deletes the branch afterward (use --keep-pr to retain).
node install.mjs --llm claude
node e2e/run-e2e.mjs --provider claude # all claude suites for this host OS
node e2e/run-e2e.mjs --suite s1.2 # one suite
Suites are grouped by provider: s1=Claude, s7=Gemini, s8=AGY, with .1/.2/.3
as the Windows/Linux/macOS matrix (e2e/suites.json). CLI flags vary by tool;
override a provider's command with e.g.
PMLITE_E2E_CMD_CLAUDE="claude -p {PROMPT} --permission-mode acceptEdits".
Pushing the branch and opening the PR needs write access to the toy: set
GH_TOKEN / E2E_GH_TOKEN, or rely on the runner's ambient git + gh credentials.
CI: .github/workflows/pm-e2e.yml (manual trigger; needs a self-hosted runner
with the provider CLI authenticated, plus node 20+, bd, and secrets.E2E_GH_TOKEN).
See CONTRIBUTING.md. Enable the ASCII pre-commit guard once after cloning:
git config core.hooksPath .githooks
Please also read the Code of Conduct. Report security issues per the Security Policy.