Agent Skills: PlanForge — Speedrift-Native Planning

>-

UncategorizedID: dbmcco/claude-agent-toolkit/planforge

Install this agent skill to your local

pnpm dlx add-skill https://github.com/dbmcco/claude-agent-toolkit/tree/HEAD/skills/planforge

Skill Files

Browse the full folder contents for planforge.

Download Skill

Loading file tree…

skills/planforge/SKILL.md

Skill Metadata

Name
planforge
Description
>-

PlanForge — Speedrift-Native Planning

Turns a problem into a Workgraph task graph ready for Speedrift execution.

Use this as the planning entry point. planforge owns discovery, model-mediated planning, critic review, spec anchoring, Speedrift module selection, model assignment, and graph seeding. After the graph exists, hand off to speedrift for execution, drift checks, fix loops, and ongoing task work.

V2 Architecture:

  • Planner persona: Loads prompts/planforge-v2-persona.md and decides the plan semantically.
  • Schema contract: Emits schemas/planforge-plan-v2.schema.json; code validates shape, not meaning.
  • Critic pass: Independent review for missing UX/integration/dead-code/upstream/model-route/fix-loop coverage.
  • Spec: Lightweight drift anchor written from the accepted plan. Not a deliverable — exists so specdrift has something to measure against.
  • Output: Seeded Workgraph with wg-contract blocks, Speedrift lane fences, cheapest-sufficient model route assignments, tests, evals, and fix-loop policy.

Announce at start: "I'm using PlanForge V2 to compile the goal into a model-mediated Speedrift Workgraph."


Invariants

  • Model judgment owns semantic decisions: module choice, cheapest-sufficient model assignment, risk, test posture, UX relevance, dead-code relevance, and replan triggers.
  • Code owns evidence gathering, schema validation, tool execution, policy gates, budgets, persistence, and audit.
  • Do not hardcode provider defaults, model IDs, API URLs, or credential env vars. Use central route names; default execution route is Pi (a multi-model harness — each Pi-routed node also names its model as a provider/id pattern pi -p --model resolves). Codex/Codexd and Claude are explicit opt-ins, never hidden defaults.
  • Ask only blocking questions. Otherwise recommend defaults, state assumptions, and proceed.
  • Plan artifacts are written to .workgraph/planforge/<session>/.
  • Spec is written AFTER the plan has converged. It reflects what was decided, not what was hoped.
  • The task graph is the deliverable. The spec is the drift anchor.
  • Human gates are for destructive actions, production-like changes, material cost, model-route policy violations, and genuinely ambiguous end states.

V2 Reference Files

  • Persona prompt: prompts/planforge-v2-persona.md
  • Plan schema: schemas/planforge-plan-v2.schema.json
  • Operating flow: references/planforge-v2-flow.md
  • Runner/materializer: scripts/planforge_v2.py

Read those files before running PlanForge V2. Keep the old phase-debate protocol below as a legacy/manual fallback for situations where the user explicitly wants multi-agent debate before graph creation.


V2 Quick Start

Use the runner unless you are manually prototyping the flow:

PLANFORGE_V2=<workspace-root>/claude-agent-toolkit/skills/planforge/scripts/planforge_v2.py

"$PLANFORGE_V2" run \
  --repo "$PWD" \
  --goal "<goal>" \
  --planner-command "$PLANFORGE_PLANNER_CMD" \
  --critic-command "$PLANFORGE_CRITIC_CMD" \
  --materialize

For dry-run materialization from an existing plan:

"$PLANFORGE_V2" materialize \
  --repo "$PWD" \
  --plan .workgraph/planforge/<session>/plan.final.json

Use --apply only when ready to run wg add commands.

Manual setup:

SESSION=$(date +%Y%m%d-%H%M%S)
mkdir -p .workgraph/planforge/$SESSION
echo $SESSION > .workgraph/planforge/current-session
wg init 2>/dev/null || true

Collect evidence:

git status --short
tmux-monitor status --all 2>/dev/null || true
find .. -maxdepth 2 -name AGENTS.md -o -name CLAUDE.md -o -name README.md -o -name NORTH_STAR.md
wg status 2>/dev/null || true

Planner pass:

  1. Load prompts/planforge-v2-persona.md.
  2. Provide the user goal, repo evidence, Workgraph state, Speedrift module inventory, model-route evidence, and autonomy policy.
  3. Require output matching schemas/planforge-plan-v2.schema.json.
  4. Persist the candidate plan to .workgraph/planforge/$SESSION/plan.candidate.json.
  5. Validate schema. If invalid, ask the model to repair. Do not rewrite semantic content in code.

Critic pass:

  1. Ask an independent critic to review the candidate plan for missing integration tests, UX evals, drift gates, dead-code cleanup, upstream-pin checks, model-route policy violations, unclear end state, overly broad tasks, and missing fix loops.
  2. Persist critic output to .workgraph/planforge/$SESSION/critic.json.
  3. Ask the planner to repair the plan using critic findings.
  4. Persist final output to .workgraph/planforge/$SESSION/plan.final.json.

Materialize:

  1. Write a lightweight spec anchor from the final plan.
  2. Create the root Workgraph task.
  3. Create leaf tasks with wg-contract blocks, Speedrift fences, dependencies, model-fit routing, verification, and acceptance criteria.
  4. Add drift and fix-loop tasks as first-class graph nodes.
  5. Arm speedriftd only when execution is authorized.

V2 Workgraph Node Pattern

wg add --id "<node-id>" "<title>" \
  --model "<selected-route>" \
  --description "
\`\`\`wg-contract
schema = 1
mode = "core"
objective = "<node title>"
touch = ["<files or directories>"]
acceptance = ["<observable acceptance criterion>"]
verify = ["<focused command>"]
model_role = "<semantic role>"
model_route = "<central-registry-route>"
model_tier = "<local|cheap|standard|premium>"
model_fit = "risk=<risk>, complexity=<blast_radius>, context=<context_load>, verification=<verification_strength>"
model_escalation_route = "<stronger-route>"
handoff_detail = "high"
small_model_ready = "yes"
\`\`\`

\`\`\`specdrift
schema = 1
spec = ["<spec path>"]
check = "does this task remain consistent with the end-state contract?"
\`\`\`

\`\`\`speedrift
modules = ["coredrift", "<selected lane>"]
pre_task = "./.workgraph/drifts check --task <task_id> --write-log --create-followups"
post_task = "./.workgraph/drifts check --task <task_id> --write-log --create-followups"
\`\`\`

\`\`\`agencydrift
profile = "<agency profile>"
preferred_runtime = "agency"
fallback_runtime = "codexd"
\`\`\`

<task description and acceptance criteria>
" --after <dependencies>

Legacy Phase-Debate Protocol

Use this only when the user explicitly wants the older gated debate flow.

Step 1: Setup

SESSION=$(date +%Y%m%d-%H%M%S)
mkdir -p .workgraph/planforge/$SESSION
echo $SESSION > .workgraph/planforge/current-session

Bootstrap workgraph if not already running:

wg init 2>/dev/null || true

PlanForge expects the repo's Workgraph coordinator or speedriftd supervisor to already be active before Phase 1 debate tasks are dispatched. If wg add warns that no service is running, bring the repo under supervision before continuing.


Step 2: Discovery Conversation (Orchestrator-led)

Run exactly 5 turns with the user. One question per turn. Document responses.

Turn 1 — Problem: "What are we trying to solve? Give me the raw version — not polished."

Turn 2 — Stakes: "Who hits this problem daily, and what does it cost them when nothing changes?"

Turn 3 — Prior attempts: "What's been tried before, and what specifically didn't work?"

Turn 4 — Constraints: "What are the hard constraints — tech, time, team, YAGNI? What are we explicitly NOT doing?"

Turn 5 — Success: "What does done look like? Specific, observable, measurable."

Write discovery output:

cat > .workgraph/planforge/$SESSION/discovery.json << 'EOF'
{
  "problem": "<2-3 sentence synthesis>",
  "stakeholders": "<who and how affected>",
  "prior_attempts": "<what failed and why>",
  "constraints": ["<constraint 1>", "<constraint 2>"],
  "out_of_scope": ["<explicit exclusion>"],
  "success_criteria": ["<measurable outcome>"]
}
EOF

Step 3: Dispatch Phase 1 Debate Agents

Dispatch all three in parallel. Each gets the discovery JSON as context.

Synthesis agent — validates the problem statement:

DISCOVERY=$(cat .workgraph/planforge/$SESSION/discovery.json)
wg add "planforge-p1-synthesis: validate problem statement and surface gaps" \
  --description "
You are the Synthesis agent in a PlanForge planning session.

Your job: Read the discovery context and validate whether the problem is well-defined.
Find gaps, ambiguities, and hidden assumptions. Do NOT propose solutions.

Discovery context:
$DISCOVERY

Output: Write JSON to .workgraph/planforge/$SESSION/p1-synthesis.json
Schema: {\"problem_valid\": bool, \"gaps\": [str], \"hidden_assumptions\": [str], \"refined_problem\": str, \"confidence\": 0-1}
" --no-place

Constraint/YAGNI agent — challenges scope:

wg add "planforge-p1-yagni: challenge scope and identify what NOT to build" \
  --description "
You are the Constraints agent in a PlanForge planning session.

Your job: Given the discovery context, aggressively identify what should be cut, deferred, or explicitly excluded.
Apply YAGNI. Challenge every assumption. What is the minimum viable scope?

Discovery context:
$DISCOVERY

Output: Write JSON to .workgraph/planforge/$SESSION/p1-yagni.json
Schema: {\"cut_now\": [str], \"defer\": [str], \"watch\": [str], \"minimum_scope\": str, \"rationale\": str}
" --no-place

Analogy/Inversion agent — finds non-obvious angles:

wg add "planforge-p1-analogy: find parallel problems and invert assumptions" \
  --description "
You are the Analogy agent in a PlanForge planning session.

Your job: (1) Find 2-3 parallel problems from other domains that were solved well — what did those solutions have in common?
(2) Invert the problem: what would make this problem WORSE? What does that tell us about what matters?

Discovery context:
$DISCOVERY

Output: Write JSON to .workgraph/planforge/$SESSION/p1-analogy.json
Schema: {\"analogies\": [{\"domain\": str, \"solution\": str, \"transferable_insight\": str}], \"inversion\": str, \"key_insight\": str}
" --no-place

Wait for all three to complete:

wg watch --filter planforge-p1 --until-done

Step 4: Phase 1 Gate

Read all three outputs:

cat .workgraph/planforge/$SESSION/p1-synthesis.json
cat .workgraph/planforge/$SESSION/p1-yagni.json
cat .workgraph/planforge/$SESSION/p1-analogy.json

Synthesize and surface to the user:

  • Where do agents agree? This is the solid ground.
  • Where do they disagree? Surface the specific tension.
  • What did the inversion reveal that wasn't in the original discovery?

Optional visualization — if the problem space has structural complexity worth showing (dependencies, stakeholder relationships, data flows), offer Jesse's visual companion here:

"The agents found [X]. Some of this is easier to show than describe — want me to diagram the problem space before we move to solution design?"

Confirm with the user: "Does this capture the problem correctly? Any corrections before we design a solution?"

Do not proceed to Phase 2 until confirmed.


Step 5: Dispatch Phase 2 Debate Agents

Embed Phase 1 synthesis in context for all agents. Dispatch in parallel.

P1_CONTEXT=$(cat .workgraph/planforge/$SESSION/p1-synthesis.json .workgraph/planforge/$SESSION/p1-yagni.json .workgraph/planforge/$SESSION/p1-analogy.json)

Ideation agent — proposes solution approaches:

wg add "planforge-p2-ideation: propose 2-3 solution approaches with tradeoffs" \
  --description "
You are the Ideation agent in a PlanForge planning session.

Your job: Propose exactly 2-3 distinct solution approaches. Each must be a real option with genuine tradeoffs — not variations of the same idea.
For each: what is it, what does it do well, what does it sacrifice, and what is the implementation shape?

Context:
$DISCOVERY

Phase 1 analysis:
$P1_CONTEXT

Output: Write JSON to .workgraph/planforge/$SESSION/p2-ideation.json
Schema: {\"approaches\": [{\"name\": str, \"description\": str, \"strengths\": [str], \"weaknesses\": [str], \"implementation_shape\": str}], \"recommended\": str, \"recommendation_rationale\": str}
" --no-place

Technical agent — evaluates feasibility:

wg add "planforge-p2-technical: evaluate technical feasibility of each approach" \
  --description "
You are the Technical agent in a PlanForge planning session.

Your job: Wait for p2-ideation.json to appear, then evaluate each proposed approach for technical feasibility.
Consider: complexity, risk, reversibility, dependencies, and fit with the existing system.

Read: .workgraph/planforge/$SESSION/p2-ideation.json when available.

Context:
$DISCOVERY

Phase 1 analysis:
$P1_CONTEXT

Output: Write JSON to .workgraph/planforge/$SESSION/p2-technical.json
Schema: {\"evaluations\": [{\"approach\": str, \"feasibility\": \"high|medium|low\", \"complexity\": \"low|medium|high\", \"risks\": [str], \"fit_score\": 0-10}], \"preferred\": str, \"rationale\": str}
" --blocked-by planforge-p2-ideation --no-place

Validation agent — challenges each approach:

wg add "planforge-p2-validation: identify failure modes and edge cases per approach" \
  --description "
You are the Validation agent in a PlanForge planning session.

Your job: For each proposed solution approach, identify the realistic ways it fails. What are the edge cases? What assumptions does each approach make that might be wrong?
Be specific — \"it might not scale\" is not useful. \"It breaks when X because Y\" is.

Read: .workgraph/planforge/$SESSION/p2-ideation.json when available.

Context:
$DISCOVERY

Phase 1 analysis:
$P1_CONTEXT

Output: Write JSON to .workgraph/planforge/$SESSION/p2-validation.json
Schema: {\"challenges\": [{\"approach\": str, \"failure_modes\": [str], \"key_assumptions\": [str], \"mitigations\": [str]}], \"show_stoppers\": [str]}
" --blocked-by planforge-p2-ideation --no-place

Scoring agent — synthesizes and scores:

wg add "planforge-p2-scoring: score approaches and produce final recommendation" \
  --description "
You are the Scoring agent in a PlanForge planning session.

Your job: Read all Phase 2 agent outputs and produce a final scored recommendation.
Score each approach across: problem fit, simplicity, technical risk, YAGNI alignment, reversibility.
Produce a clear recommendation with rationale.

Read:
- .workgraph/planforge/$SESSION/p2-ideation.json
- .workgraph/planforge/$SESSION/p2-technical.json
- .workgraph/planforge/$SESSION/p2-validation.json

Context:
$DISCOVERY

Phase 1 analysis:
$P1_CONTEXT

Output: Write JSON to .workgraph/planforge/$SESSION/p2-scoring.json
Schema: {\"scores\": [{\"approach\": str, \"problem_fit\": 0-10, \"simplicity\": 0-10, \"tech_risk\": 0-10, \"yagni\": 0-10, \"reversibility\": 0-10, \"total\": 0-50}], \"winner\": str, \"rationale\": str, \"dissenting_concerns\": [str]}
" --blocked-by planforge-p2-technical planforge-p2-validation --no-place

Wait:

wg watch --filter planforge-p2 --until-done

Step 6: Phase 2 Gate

Read all Phase 2 outputs. Synthesize for the user:

  • Winner and score
  • Dissenting concerns (don't hide them — surface them explicitly)
  • Any show-stoppers from validation

Visualization — this is the right moment. Offer to show:

  1. The winning approach's architecture or workflow diagram
  2. The proposed task graph structure before it gets created

"Here's what the agents settled on: [winner] scored [X/50]. The main concern was [dissent]. Want me to diagram the solution architecture and task breakdown before we commit it to workgraph?"

Confirm with the user: "Does this solution direction feel right? Any adjustments before I write the spec and seed the graph?"


Step 7: Write Lightweight Spec (Drift Anchor)

This is not a human document. It exists so specdrift has something to measure implementation against.

SPEC_DATE=$(date +%Y-%m-%d)
SPEC_SLUG="<topic-slug>"
SPEC_PATH="docs/superpowers/specs/${SPEC_DATE}-${SPEC_SLUG}-spec.md"
mkdir -p docs/superpowers/specs
# <Topic> Spec — Drift Anchor
*Generated by PlanForge on $SPEC_DATE. Not a deliverable — specdrift reference only.*

## Problem
<refined_problem from p1-synthesis>

## Solution
<winner from p2-scoring, 2-3 sentences>

## Out of Scope
<cut_now and explicit exclusions from p1-yagni and discovery constraints>

## Success Criteria
<measurable outcomes from discovery>

## Key Constraints
<hard constraints from discovery>

## Dissenting Concerns
<dissenting_concerns from p2-scoring — recorded so specdrift can flag if implementation ignores them>

Step 8: Seed the wg Task Graph

Decompose the winning solution into leaf tasks. Each task must have:

  • A wg-contract block (touch-set + verify command)
  • A specdrift fence block referencing the spec path
  • --blocked-by dependencies where sequencing matters

Pattern:

wg add "implement-<component>" \
  --description "
\`\`\`wg-contract
schema = 1
mode = "core"
objective = "implement <component>"
touch = ["<files this task touches>"]
verify = ["<test command>"]
\`\`\`

\`\`\`specdrift
schema = 1
spec = ["$SPEC_PATH"]
check = "does this task's output remain consistent with the spec?"
\`\`\`

<task description — what to build and why, referencing spec section>
" --blocked-by <deps>

Root task first (captures the session and links to spec):

wg add "planforge-root: <topic>" \
  --description "PlanForge session: $SESSION. Spec: $SPEC_PATH. Goal: <one sentence>."

Step 9: Arm for Execution

# Show the graph
wg viz

# Arm via speedriftd (do not use wg service start directly)
driftdriver --dir "$PWD" speedriftd status \
  --set-mode supervise \
  --lease-owner planforge \
  --reason "planforge session $SESSION: <topic>"

Report to the user: task graph seeded, spec written to $SPEC_PATH, graph armed. Ready.


Quick Reference

| Phase | Who runs | What it produces | |-------|----------|-----------------| | Discovery | Orchestrator + the user | discovery.json | | Phase 1 (parallel) | wg agents | problem validated, constraints, analogies | | Phase 1 Gate | Orchestrator | the user confirms problem | | Phase 2 (parallel) | wg agents | ideation, technical eval, validation, scoring | | Phase 2 Gate | Orchestrator | the user confirms solution | | Spec | Orchestrator | drift anchor .md | | Task graph | Orchestrator | seeded wg graph with contracts |

Red Flags

Never:

  • Skip a phase gate
  • Proceed with unresolved show-stoppers from validation agent
  • Write the spec before the user confirms the solution
  • Use wg service start to arm — always go through speedriftd
  • Let the debate agents talk to the user directly

Always:

  • Surface dissenting concerns, not just the winner
  • Record out_of_scope explicitly in the spec (specdrift needs it)
  • Embed spec path in every task's specdrift fence