2026-04-01 10:22:54 +00:00
# formulas/run-architect.toml — Architect formula
2026-04-01 09:53:47 +00:00
#
# Executed by architect-run.sh via cron — strategic decomposition of vision
# issues into development sprints.
#
2026-04-01 10:22:54 +00:00
# This formula orchestrates the architect agent's workflow:
# Step 1: Preflight — validate prerequisites and identify target issue
# Step 2: Research + pitch — analyze codebase and write sprint pitch
# Step 3: Sprint PR creation with questions (issue #101)
# Step 4: Answer parsing + sub-issue filing (issue #102)
2026-04-01 09:53:47 +00:00
#
# AGENTS.md maintenance is handled by the gardener (#246).
name = "run-architect"
description = "Architect: strategic decomposition of vision into sprints"
version = 1
model = "opus"
[ context ]
files = [ "VISION.md" , "AGENTS.md" ]
# Prerequisite tree loaded from ops repo (ops: prefix)
# Sprints directory tracked in ops repo
[ [ steps ] ]
2026-04-01 10:22:54 +00:00
id = "preflight"
title = "Preflight: validate prerequisites and identify target vision issue"
2026-04-01 09:53:47 +00:00
description = "" "
2026-04-01 10:22:54 +00:00
This step performs preflight checks and identifies the most unblocking vision issue .
2026-04-01 09:53:47 +00:00
2026-04-01 10:22:54 +00:00
Actions :
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 ( handled by #101/#102)
2026-04-01 10:38:28 +00:00
5 . If open architect PRs exist , handle accept / reject responses ( see Capability B below )
6 . If no vision issues , signal PHASE : done
2026-04-01 09:53:47 +00:00
2026-04-01 10:22:54 +00:00
Skip conditions :
- If no vision issues are found , signal PHASE : done
Output :
- Sets ARCHITECT_TARGET_ISSUE to the issue number of the selected vision issue
- Exports VISION_ISSUES as a JSON array of issue objects
2026-04-01 10:38:28 +00:00
## Capability B: Handle accept/reject on existing pitch PRs
When open architect PRs exist on the ops repo :
2026-04-08 19:02:55 +00:00
1 . Check for human response — reviews first , then comments .
2026-04-01 10:38:28 +00:00
2026-04-08 19:02:55 +00:00
* * Step 1 — Check PR reviews ( Forgejo review UI ) : * *
Fetch reviews via Forgejo API :
` ` `
GET / repos / { owner } / { repo } / pulls / { index } / reviews
` ` `
Scan the response array for reviews with non-bot authors :
- ` state : "APPROVED" ` → treat as * * ACCEPT * * . If the review has a non-empty ` body ` ,
use it as context ( e . g . "ACCEPT — focus on option B for Q1" ) .
- ` state : "REQUEST_CHANGES" ` → treat as * * REJECT * * with the review ` body ` as the reason .
- Other states ( COMMENT , PENDING ) → ignore , not a decision .
If multiple reviews exist , use the most recent one ( last in array ) .
* * Step 2 — Check PR comments ( fallback for backwards compat ) : * *
Fetch comments on each open architect PR via Forgejo API .
Scan for ACCEPT / REJECT text as described below .
* * Precedence : * * If both a review decision and a comment decision exist ,
the review takes precedence .
2 . Act on the human response :
* * ACCEPT * * ( case insensitive , from review APPROVED or comment text ) : Human wants to proceed
2026-04-01 10:38:28 +00:00
- Architect does deep research for design forks ( same as #100 research but now identifying decision points)
- Formulates multiple-choice questions ( Q1 , Q2 , Q3 . . . )
- Updates the sprint spec file on the PR branch :
- Adds ` ## Design forks` section with fork options
- Adds ` ## Proposed sub-issues` section with concrete issues per fork path
- Comments on the PR with the questions formatted as multiple choice
- Signal PHASE : done ( answer processing is #102)
2026-04-08 19:02:55 +00:00
* * REJECT : < reason > * * ( case insensitive , from review REQUEST_CHANGES or comment text ;
for reviews the reason is the review body , for comments the reason follows the colon ) :
2026-04-01 10:38:28 +00:00
- Journal the rejection reason via profile_write_journal ( if . profile exists )
— the architect learns what pitches fail
- Close the PR via Forgejo API ( do not merge — rejected pitches do not persist in sprints / )
- Remove the branch via Forgejo API
- Signal PHASE : done
* * No response yet * * : skip silently , signal PHASE : done
All git operations use the Forgejo API ( create branch , write / update file , create PR ,
close PR , delete branch ) . No SSH .
2026-04-01 10:22:54 +00:00
"" "
[ [ steps ] ]
id = "research_pitch"
title = "Research + pitch: analyze codebase and write sprint pitch"
description = "" "
This step performs deep codebase research and writes a sprint pitch for the
selected vision issue .
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 scratch file for PR creation step ( #101):
# 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 sprint pitch to $ SCRATCH_FILE ( / tmp / architect- { project } -scratch . md )
- The pitch serves as input for sprint PR creation step ( #101)
"" "
[ [ steps ] ]
id = "sprint_pr_creation"
title = "Sprint PR creation with questions (issue #101)"
description = "" "
2026-04-01 10:38:28 +00:00
This step creates a PR on the ops repo with the sprint proposal when no PR exists yet .
2026-04-01 10:22:54 +00:00
2026-04-01 10:38:28 +00:00
## Capability A: Create pitch PR (from research output)
2026-04-01 10:22:54 +00:00
2026-04-01 10:38:28 +00:00
If step 2 ( research / pitch ) produced a pitch and no PR exists yet :
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 > `
2026-04-08 18:54:40 +00:00
- 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 .
2026-04-01 10:38:28 +00:00
- 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 . 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
2026-04-08 18:54:40 +00:00
Body : { "title" : "architect: <sprint summary>" , "body" : "<markdown-text>" , "head" : "architect/<sprint-slug>" , "base" : "main" }
2026-04-01 10:38:28 +00:00
` ` `
2026-04-08 18:54:40 +00:00
* * 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
- Example : if the sprint pitch contains ` ## What this enables`, the PR body should render this as a markdown heading, not as literal `## What this enables` text
2026-04-01 10:38:28 +00:00
### Close PR
` ` `
PATCH / repos / { owner } / { repo } / pulls / { index }
Body : { "state" : "closed" }
` ` `
### Delete branch
` ` `
DELETE / repos / { owner } / { repo } / git / branches / < branch-name >
` ` `
2026-04-01 10:22:54 +00:00
"" "
[ [ steps ] ]
id = "answer_parsing"
title = "Answer parsing + sub-issue filing (issue #102)"
description = "" "
This step processes human answers to design questions and files sub-issues .
2026-04-08 19:30:25 +00:00
## Session resumption
When processing answers , the architect resumes the session from the research / questions
run ( step 2 ) to preserve codebase context . This ensures Claude has full understanding
of dispatcher . sh , vault . sh , branch-protection . sh , and all formulas when filing
sub-issues , resulting in more specific file references and implementation details .
The session ID is persisted to ` $ SID_FILE ` after the research / questions run . On
answer_parsing runs , if the PR is in the questions phase , the session is resumed
instead of starting fresh .
2026-04-01 10:57:26 +00:00
## Preflight: Detect PRs in question phase
2026-04-01 10:22:54 +00:00
2026-04-01 10:57:26 +00:00
An architect PR is in the question phase if ALL of the following are true :
- PR is open
- PR body or sprint spec file contains a ` ## Design forks` section (added by #101 after ACCEPT)
- PR has question comments ( Q1 , Q2 , Q3 . . . format )
## Answer parsing
Human comments on the PR use this format :
` ` `
Q1 : A
Q2 : B
Q3 : A
` ` `
Parser matches lines starting with ` Q ` + digit ( s ) + ` : ` + space + letter A-D ( case insensitive ) .
Ignore other content in the comment .
## Processing paths
### All questions answered (every `### Q` heading has a matching `Q<N>: <letter>` comment)
1 . Parse each answer ( e . g . ` Q1 : A ` , ` Q2 : C ` )
2 . Read the sprint spec from the PR branch
3 . Generate final sub-issues based on answers :
- Each sub-issue uses the appropriate issue template ( bug / feature / refactor from ` . codeberg / ISSUE_TEMPLATE / ` )
- Fill all template fields :
- Problem / motivation ( feature ) or What ' s broken ( bug / refactor )
- Proposed solution ( feature ) or Approach ( refactor ) or Steps to reproduce ( bug )
- Affected files ( max 3 )
- Acceptance criteria ( max 5 )
- Dependencies
- File via Forgejo API on the * * disinto repo * * ( not ops repo )
- Label as ` backlog `
4 . Comment on PR : "Sprint filed: #N, #N, #N"
5 . Merge the PR ( sprint spec with answers persists in ` ops / sprints / ` )
### Some questions answered, not all
1 . Acknowledge answers received
2 . Comment listing remaining unanswered questions
3 . Signal PHASE : done ( check again next poll )
### No answers yet (questions posted but human hasn't responded)
1 . Skip — signal PHASE : done
## Forgejo API for filing issues on disinto repo
All operations use the Forgejo API with ` Authorization : token $ { FORGE_TOKEN } ` header .
### Create issue
` ` `
POST / repos / { owner } / { repo } / issues
Body : {
"title" : "<issue title>" ,
"body" : "<issue body with template fields>" ,
"labels" : [ 123 ] , / / backlog label ID
"assignees" : [ "architect-bot" ]
}
` ` `
### Close PR
` ` `
PATCH / repos / { owner } / { repo } / pulls / { index }
Body : { "state" : "closed" }
` ` `
2026-04-01 11:08:37 +00:00
### Merge PR
2026-04-01 10:57:26 +00:00
` ` `
2026-04-01 11:08:37 +00:00
POST / repos / { owner } / { repo } / pulls / { index } / merge
Body : { "Do" : "merge" }
2026-04-01 10:57:26 +00:00
` ` `
2026-04-01 11:08:37 +00:00
### Post comment on PR (via issues endpoint)
2026-04-01 10:57:26 +00:00
` ` `
2026-04-01 11:08:37 +00:00
POST / repos / { owner } / { repo } / issues / { index } / comments
2026-04-01 10:57:26 +00:00
Body : { "body" : "<comment text>" }
` ` `
### Get label ID
` ` `
GET / repos / { owner } / { repo } / labels
` ` `
2026-04-01 09:53:47 +00:00
"" "