disinto/formulas/run-architect.toml
Claude e31a2d5c88
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
fix: refactor: architect design phase should be bash-driven with stateful session resumption (#491)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 10:15:17 +00:00

241 lines
8.4 KiB
TOML

# 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 - <number of open architect PRs remaining after handling>
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: <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>
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}
```
"""