# formulas/run-architect.toml — Architect formula # # Executed by architect-run.sh via cron — strategic decomposition of vision # issues into development sprints. # # This formula orchestrates the architect agent's pitching workflow: # Step 1: Preflight — validate prerequisites, select up to 3 target issues # Step 2: Research + pitch — analyze codebase and write sprint pitch (loop over selected issues) # Step 3: Sprint PR creation (one PR per pitch) # # Design phase (ACCEPT/REJECT handling, questions, answer processing) is # orchestrated by bash in architect-run.sh — not by this formula. # See architect-run.sh for the bash-driven state machine: # - Bash reads reviews API for ACCEPT/REJECT detection (deterministic) # - REJECT handled entirely in bash (close PR, delete branch, journal) # - ACCEPT: bash invokes model with human guidance injected # - Answers: bash resumes saved session with answers injected # # AGENTS.md maintenance is handled by the gardener (#246). name = "run-architect" description = "Architect: strategic decomposition of vision into sprints" version = 2 model = "opus" [context] files = ["VISION.md", "AGENTS.md"] # Prerequisite tree loaded from ops repo (ops: prefix) # Sprints directory tracked in ops repo [[steps]] id = "preflight" title = "Preflight: validate prerequisites, select up to 3 target issues" description = """ This step is performed by bash in architect-run.sh before the model is invoked. Bash handles: 1. Pull latest code from both disinto repo and ops repo 2. Read prerequisite tree from $OPS_REPO_ROOT/prerequisites.md 3. Fetch open issues labeled 'vision' from Forgejo API 4. Check for open architect PRs on ops repo 5. Process existing PRs via bash-driven design phase (ACCEPT/REJECT/answers) 6. After handling existing PRs, count remaining open architect PRs 7. Select up to (3 - open_architect_pr_count) vision issues for new pitches 8. If no vision issues, signal PHASE:done ## Multi-pitch selection (up to 3 per run) After handling existing PRs, determine how many new pitches can be created: pitch_budget = 3 - For each available pitch slot: 1. From the vision issues list, skip any issue that already has an open architect PR 2. Skip any issue that already has the `in-progress` label 3. Check for existing sub-issues filed from this vision issue 4. Check for merged sprint PRs referencing this vision issue 5. From remaining candidates, pick the most unblocking issue first 6. Add to ARCHITECT_TARGET_ISSUES array Skip conditions: - If no vision issues are found, signal PHASE:done - If pitch_budget <= 0 (already 3 open architect PRs), skip pitching - If all vision issues already have open architect PRs, signal PHASE:done - If all vision issues have open sub-issues, skip pitching - If all vision issues have merged sprint PRs, skip pitching Output: - Sets ARCHITECT_TARGET_ISSUES as a JSON array of issue numbers to pitch (up to 3) """ [[steps]] id = "research_pitch" title = "Research + pitch: analyze codebase and write sprint pitches (loop over selected issues)" description = """ This step performs deep codebase research and writes a sprint pitch for EACH vision issue in ARCHITECT_TARGET_ISSUES. For each issue in ARCHITECT_TARGET_ISSUES, perform the following: Actions: 1. Read the codebase deeply: - Read all files mentioned in the issue body - Search for existing interfaces that could be reused - Check what infrastructure already exists 2. Assess complexity and cost: - How many files/subsystems are touched? - What new infrastructure would need to be maintained after this sprint? - What are the risks (breaking changes, security implications, integration complexity)? - Is this mostly gluecode or greenfield? 3. Write sprint pitch to a per-issue scratch file for PR creation step: - File path: /tmp/architect-{project}-scratch-{issue_number}.md # Sprint pitch: ## Vision issues - #N — ## What this enables <what the project can do after this sprint that it can't do now> ## What exists today <current state — infrastructure, interfaces, code that can be reused> ## Complexity <number of files, subsystems, estimated sub-issues> <gluecode vs greenfield ratio> ## Risks <what could go wrong, what breaks if this is done badly> ## Cost — new infra to maintain <what ongoing maintenance burden does this sprint add> <new services, cron jobs, formulas, agent roles> ## Recommendation <architect's assessment: worth it / defer / alternative approach> IMPORTANT: Do NOT include design forks or questions yet. The pitch is a go/no-go decision for the human. Questions come only after acceptance. Output: - Writes one scratch file per vision issue: /tmp/architect-{project}-scratch-{issue_number}.md - Each pitch serves as input for sprint PR creation step - If ARCHITECT_TARGET_ISSUES is empty (budget exhausted or no candidates), skip this step """ [[steps]] id = "sprint_pr_creation" title = "Sprint PR creation (one PR per pitch)" description = """ This step creates a PR on the ops repo for EACH sprint pitch produced in step 2. One PR per vision issue — loop over all scratch files. ## Create pitch PRs (from research output) For each vision issue in ARCHITECT_TARGET_ISSUES that produced a scratch file (/tmp/architect-{project}-scratch-{issue_number}.md): 1. Create branch `architect/<sprint-slug>` on ops repo via Forgejo API - Sprint slug: lowercase, hyphenated version of sprint name - Use Forgejo API: POST /repos/{owner}/{repo}/git/branches 2. Write sprint spec file to sprints/<sprint-slug>.md on the new branch: # Sprint: <name> ## Vision issues - #N — <title> ## What this enables <what the project can do after this sprint that it can't do now> ## What exists today <current state — infrastructure, interfaces, code that can be reused> ## Complexity <number of files/subsystems, estimated sub-issues> <gluecode vs greenfield ratio> ## Risks <what could go wrong, what breaks if this is done badly> ## Cost — new infra to maintain <what ongoing maintenance burden does this sprint add> <new services, cron jobs, formulas, agent roles> ## Recommendation <architect's assessment: worth it / defer / alternative approach> 3. Create PR on ops repo via Forgejo API: - Title: `architect: <sprint summary>` - Body: **plain markdown text** from the scratch file (pitch content with sections: What this enables, Complexity, Risks, Cost, Recommendation). Preserve newlines as-is — do NOT JSON-encode the body. - Base branch: primary branch (main/master) - Head branch: architect/<sprint-slug> - Footer: "Reply `ACCEPT` to proceed with design questions, or `REJECT: <reason>` to decline." 4. Add `in-progress` label to the vision issue on the disinto repo: - Look up the `in-progress` label ID via `GET /repos/{owner}/{repo}/labels` - Add the label via `POST /repos/{owner}/{repo}/issues/{vision_issue_number}/labels` Body: `{"labels": [<in-progress-label-id>]}` 5. After creating all PRs, signal PHASE:done ## Forgejo API Reference All operations use the Forgejo API with `Authorization: token ${FORGE_TOKEN}` header. ### Create branch ``` POST /repos/{owner}/{repo}/branches Body: {"new_branch_name": "architect/<sprint-slug>", "old_branch_name": "main"} ``` ### Create/update file ``` PUT /repos/{owner}/{repo}/contents/<path> Body: {"message": "sprint: add <sprint-slug>.md", "content": "<base64-encoded-content>", "branch": "architect/<sprint-slug>"} ``` ### Create PR ``` POST /repos/{owner}/{repo}/pulls Body: {"title": "architect: <sprint summary>", "body": "<markdown-text>", "head": "architect/<sprint-slug>", "base": "main"} ``` **Important: PR body format** - The `body` field must contain **plain markdown text** (the raw content from the scratch file) - Do NOT JSON-encode or escape the body — pass it as a JSON string value - Newlines and markdown formatting (headings, lists, etc.) must be preserved as-is ### Close PR ``` PATCH /repos/{owner}/{repo}/pulls/{index} Body: {"state": "closed"} ``` ### Delete branch ``` DELETE /repos/{owner}/{repo}/git/branches/<branch-name> ``` ### Get labels (look up label IDs by name) ``` GET /repos/{owner}/{repo}/labels ``` ### Add label to issue (for in-progress on vision issue) ``` POST /repos/{owner}/{repo}/issues/{index}/labels Body: {"labels": [<label-id>]} ``` ### Remove label from issue (for in-progress removal on REJECT) ``` DELETE /repos/{owner}/{repo}/issues/{index}/labels/{label-id} ``` """