# formulas/run-planner.toml — Strategic planning formula (v4: graph-driven) # # Executed directly by planner-run.sh via cron — no action issues. # planner-run.sh creates a tmux session with Claude (opus) and injects # this formula as context, plus the graph report from build-graph.py. # # Steps: preflight → triage-and-plan → journal-and-commit # # v4 changes from v3: # - Graph report (orphans, cycles, thin objectives, bottlenecks) replaces # manual repo scanning and hardcoded constraint patterns. # - tea CLI helpers replace inline curl commands. # - 3 steps instead of 6. # # AGENTS.md maintenance is handled by the gardener (#246). # All git writes (tree, journal, memory) happen in one commit at the end. name = "run-planner" description = "Planner v4: graph-driven planning with tea helpers" version = 4 model = "opus" [context] files = ["VISION.md", "AGENTS.md"] # RESOURCES.md and prerequisites.md loaded from ops repo (ops: prefix) # Recent journal/planner/*.md files + graph report loaded by planner-run.sh [[steps]] id = "preflight" title = "Pull latest code, run graph, load context" description = """ 1. Change to the project repository: cd "$PROJECT_REPO_ROOT" 2. Pull the latest code: git fetch origin "$PRIMARY_BRANCH" --quiet git checkout "$PRIMARY_BRANCH" --quiet git pull --ff-only origin "$PRIMARY_BRANCH" --quiet 3. Record the current HEAD SHA: HEAD_SHA=$(git rev-parse HEAD) echo "$HEAD_SHA" > /tmp/planner-head-sha 4. Read the planner memory file at: $OPS_REPO_ROOT/knowledge/planner-memory.md If it does not exist, this is the first planning run. 5. Read the prerequisite tree at: $OPS_REPO_ROOT/prerequisites.md If it does not exist, create an initial tree from VISION.md in the next step. 6. Read the graph report injected into the prompt (## Structural analysis). This JSON contains: orphans, cycles, disconnected clusters, thin_objectives, bottlenecks (by betweenness centrality). Use it instead of manual file scanning. """ [[steps]] id = "triage-and-plan" title = "Triage predictions, update tree, file at constraints" description = """ One unified step replacing the former prediction-triage, update-prerequisite-tree, and file-at-constraints steps. ### Part A: Triage predictions 1. Fetch unreviewed predictions: curl -sf -H "Authorization: token $FORGE_TOKEN" \ "$FORGE_API/issues?state=open&type=issues&labels=prediction%2Funreviewed&limit=50" If none, skip to Part B. 2. Fetch all open issues (for overlap check): curl -sf -H "Authorization: token $FORGE_TOKEN" \ "$FORGE_API/issues?state=open&type=issues&limit=50" 3. Read available formulas: $FACTORY_ROOT/formulas/*.toml and $PROJECT_REPO_ROOT/formulas/*.toml 4. For each prediction, choose one of two actions (no fence-sitting): - ACTION: agree with the prediction -> create a backlog or action issue, relabel to prediction/actioned, close the prediction - DISMISS: disagree or noise -> comment reasoning, relabel to prediction/dismissed, close the prediction If a dismissed prediction is real, the predictor will re-file it with stronger evidence next run. The issue history is the predictor's memory. 5. Execute triage using tea helpers: - Create issues: tea_file_issue "" "<body>" "backlog" (or "action") - Relabel: tea_relabel <num> "prediction/actioned" (or "prediction/dismissed") - Comment: tea_comment <num> "<reasoning>" - Close: tea_close <num> Issue body template (gardener quality gate requires these sections): ## Problem <what the prediction identified> ## Proposed solution <approach> ## Affected files - <file1> ## Acceptance criteria - [ ] <criterion> - [ ] CI green Every decision MUST include reasoning in a comment on the prediction issue. ### Part B: Update prerequisite tree Read these inputs: - VISION.md, RESOURCES.md, planner memory (from preflight) - Graph report: orphans, cycles, thin_objectives, bottlenecks, disconnected - Portfolio: ## Addressables and ## Observables tables in AGENTS.md — use these as the concrete inventory of what the factory has produced. Plan toward making addressables observable (measurement wired). Vision changes (#733) should trigger a review of these tables. - Open issues (from Part A or fresh fetch) - Recently closed issues: curl -sf -H "Authorization: token $FORGE_TOKEN" \ "$FORGE_API/issues?state=closed&type=issues&limit=50&sort=updated&direction=desc" Update the tree: 1. Mark resolved prerequisites ([x]) — check if issue closed or capability present 2. Recalculate objective status (READY/BLOCKED/DONE) 3. Add new prerequisites discovered from graph report 4. Add new objectives from VISION.md not yet in tree 5. Check vault state: $OPS_REPO_ROOT/vault/pending/*.md + $OPS_REPO_ROOT/vault/approved/*.md (blocked-on-vault), $OPS_REPO_ROOT/vault/fired/*.md (resolved?) 6. Check RESOURCES.md for newly available capabilities Bounce/stuck detection — for issues in the tree, fetch recent comments: curl -sf -H "Authorization: token $FORGE_TOKEN" \ "$FORGE_API/issues/<number>/comments?limit=10" Signals: BOUNCED (too_large, underspecified), LABEL_CHURN (3+ relabels between backlog/underspecified). If an issue needs a human decision or external resource, it is HUMAN_BLOCKED. Track as stuck_issues[] for constraint filing below. Hold the updated tree in memory — written to disk in journal-and-commit. Tree format: # Prerequisite Tree <!-- Last updated: YYYY-MM-DD --> ## Objective: <name> (#issue or description) - [x] Resolved prerequisite (reference) - [ ] Unresolved prerequisite (#issue or description) - [ ] Resource need blocked-on-vault ($OPS_REPO_ROOT/vault/pending/<id>.md) Status: READY | BLOCKED — <reason> | DONE ### Part C: File at constraints From the updated tree + graph bottlenecks, identify the top 5 constraints. A constraint is an unresolved prerequisite blocking the most downstream objectives. Graph bottlenecks (high betweenness centrality) and thin objectives inform ranking. Stuck issue handling: - BOUNCED/LABEL_CHURN: do NOT re-promote. Dispatch groom-backlog formula instead: tea_file_issue "chore: break down #<N> — bounced <count>x" "<body>" "action" - HUMAN_BLOCKED (needs human decision or external resource): file a vault procurement item instead of skipping. First check for duplicates across ALL vault directories (pending/, approved/, fired/) — if a file with the same slug already exists in any of them, do NOT create a new one. Naming: $OPS_REPO_ROOT/vault/pending/<project>-<slug>.md (e.g. disinto-github-org.md). Write with this template: # Request: <short description> ## What <description of the resource or decision needed> ## Why Blocks #<issue> (<title>), which blocks <downstream objective>. Waiting since <date constraint was first identified>. ## Human action 1. <concrete step> 2. <concrete step> 3. Paste result here or in #<issue> ## Factory will then - <what the factory does once the resource is available> - <downstream work that unblocks> ## Unblocks - #<issue> — <title> Then mark the prerequisite in the tree as "blocked-on-vault ($OPS_REPO_ROOT/vault/pending/<id>.md)". Do NOT skip or mark as "awaiting human decision" — the vault owns the human interface. Filing gate (for non-stuck constraints): 1. Check if issue already exists (match by #number in tree or title search) 2. If no issue, create one with tea_file_issue using the template above 3. If issue exists and is open, skip — no duplicates Priority label sync: - Add priority to current top-5 constraint issues (if missing): tea_relabel <num> "backlog,priority" - Remove priority from issues no longer in top 5: curl -sf -X DELETE -H "Authorization: token $FORGE_TOKEN" \ "$FORGE_API/issues/<num>/labels/<priority_label_id>" Vault procurement: if a constraint needs a resource not in RESOURCES.md with recurring cost, create $OPS_REPO_ROOT/vault/pending/<project>-<slug>.md instead of an issue. Use the same template as HUMAN_BLOCKED above (What/Why/Human action/Factory will then/Unblocks). Dedup: check $OPS_REPO_ROOT/vault/pending/ + $OPS_REPO_ROOT/vault/approved/ + $OPS_REPO_ROOT/vault/fired/ before creating. Rules: - Action budget: the planner may create at most (predictions_addressed + 1) new issues per run if any predictions were triaged, or 4 if no predictions. This covers issues from Part A promotions + Part C constraint filing combined. - No issues filed past the bottleneck - Leave existing premature issues as-is - Only reference formulas that exist on disk - Do NOT file issues for objectives blocked on pending vault items - Promoted predictions may become constraints — rank them equally CRITICAL: If any part of this step fails, log the failure and continue. """ needs = ["preflight"] [[steps]] id = "journal-and-commit" title = "Write tree, journal, optional memory; commit and PR" description = """ ### 1. Write prerequisite tree Write to: $OPS_REPO_ROOT/prerequisites.md ### 2. Write journal entry Create/append to: $OPS_REPO_ROOT/journal/planner/$(date -u +%Y-%m-%d).md Format: # Planner run — YYYY-MM-DD HH:MM UTC ## Predictions triaged - #NNN: ACTION — reasoning (or "No unreviewed predictions") ## Prerequisite tree updates - Resolved: <list> - Discovered: <list> - Proposed: <list> ## Top 5 constraints 1. <prerequisite> — blocks N objectives — #NNN (existing|filed) ## Stuck issues detected - #NNN: BOUNCED (Nx) — dispatched groom-backlog as #MMM (or "No stuck issues detected") ## Vault items filed - $OPS_REPO_ROOT/vault/pending/<id>.md — <what> — blocks #NNN (or "No vault items filed") ## Issues created - #NNN: title — why (or "No new issues") ## Priority label changes - Added/removed priority: #NNN (or "No priority changes") ## Observations - Key patterns noticed this run ## Deferred - Items in tree beyond top 5, why not filed Keep concise — 30-50 lines max. ### 3. Memory update (every 5th run) Count "# Planner run —" headers across all journal files. Check "<!-- summarized-through-run: N -->" in planner-memory.md. If (count - N) >= 5 or planner-memory.md missing, write to: $OPS_REPO_ROOT/knowledge/planner-memory.md Include: run counter marker, date, constraint focus, patterns, direction. Keep under 100 lines. Replace entire file. ### 4. Commit ops repo changes Commit the ops repo changes (prerequisites, journal, memory, vault items): cd "$OPS_REPO_ROOT" git add prerequisites.md journal/planner/ knowledge/planner-memory.md vault/pending/ git add -u if ! git diff --cached --quiet; then git commit -m "chore: planner run $(date -u +%Y-%m-%d)" git push origin "$PRIMARY_BRANCH" fi cd "$PROJECT_REPO_ROOT" """ needs = ["triage-and-plan"]