Merge pull request 'fix: bug: architect has no path for approved PRs awaiting initial design questions (#570)' (#598) from fix/issue-570 into main
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
This commit is contained in:
commit
2d372679d4
3 changed files with 186 additions and 12 deletions
|
|
@ -51,9 +51,11 @@ Bash in `architect-run.sh` handles state detection and orchestration:
|
|||
```
|
||||
New vision issue → pitch PR (model generates pitch, bash creates PR)
|
||||
↓
|
||||
ACCEPT review → research + questions (model, session saved to $SID_FILE)
|
||||
APPROVED review → start design questions (model posts Q1:, adds Design forks section)
|
||||
↓
|
||||
Answers received → sub-issue filing (model, session resumed via --resume)
|
||||
Answers received → continue Q&A (model processes answers, posts follow-ups)
|
||||
↓
|
||||
All forks resolved → sub-issue filing (model files implementation issues)
|
||||
↓
|
||||
REJECT review → close PR + journal (model processes rejection, bash merges PR)
|
||||
```
|
||||
|
|
|
|||
|
|
@ -129,7 +129,88 @@ ${PROMPT_FOOTER}
|
|||
_PROMPT_EOF_
|
||||
}
|
||||
|
||||
PROMPT=$(build_architect_prompt)
|
||||
# ── Build prompt for specific session mode ───────────────────────────────
|
||||
# Args: session_mode (pitch / questions_phase / start_questions)
|
||||
# Returns: prompt text via stdout
|
||||
build_architect_prompt_for_mode() {
|
||||
local session_mode="$1"
|
||||
|
||||
case "$session_mode" in
|
||||
"start_questions")
|
||||
cat <<_PROMPT_EOF_
|
||||
You are the architect agent for ${FORGE_REPO}. Work through the formula below.
|
||||
|
||||
Your role: strategic decomposition of vision issues into development sprints.
|
||||
Propose sprints via PRs on the ops repo, converse with humans through PR comments,
|
||||
and file sub-issues after design forks are resolved.
|
||||
|
||||
## CURRENT STATE: Approved PR awaiting initial design questions
|
||||
|
||||
A sprint pitch PR has been approved by the human (via APPROVED review), but the
|
||||
design conversation has not yet started. Your task is to:
|
||||
|
||||
1. Read the approved sprint pitch from the PR body
|
||||
2. Identify the key design decisions that need human input
|
||||
3. Post initial design questions (Q1:, Q2:, etc.) as comments on the PR
|
||||
4. Add a `## Design forks` section to the PR body documenting the design decisions
|
||||
5. File sub-issues for each design fork path if applicable
|
||||
|
||||
This is NOT a pitch phase — the pitch is already approved. This is the START
|
||||
of the design Q&A phase.
|
||||
|
||||
## Project context
|
||||
${CONTEXT_BLOCK}
|
||||
${GRAPH_SECTION}
|
||||
${SCRATCH_CONTEXT}
|
||||
$(formula_lessons_block)
|
||||
## Formula
|
||||
${FORMULA_CONTENT}
|
||||
|
||||
${SCRATCH_INSTRUCTION}
|
||||
${PROMPT_FOOTER}
|
||||
_PROMPT_EOF_
|
||||
;;
|
||||
"questions_phase")
|
||||
cat <<_PROMPT_EOF_
|
||||
You are the architect agent for ${FORGE_REPO}. Work through the formula below.
|
||||
|
||||
Your role: strategic decomposition of vision issues into development sprints.
|
||||
Propose sprints via PRs on the ops repo, converse with humans through PR comments,
|
||||
and file sub-issues after design forks are resolved.
|
||||
|
||||
## CURRENT STATE: Design Q&A in progress
|
||||
|
||||
A sprint pitch PR is in the questions phase:
|
||||
- The PR has a `## Design forks` section
|
||||
- Initial questions (Q1:, Q2:, etc.) have been posted
|
||||
- Humans may have posted answers or follow-up questions
|
||||
|
||||
Your task is to:
|
||||
1. Read the existing questions and the PR body
|
||||
2. Read human answers from PR comments
|
||||
3. Parse the answers and determine next steps
|
||||
4. Post follow-up questions if needed (Q3:, Q4:, etc.)
|
||||
5. If all design forks are resolved, file sub-issues for each path
|
||||
6. Update the `## Design forks` section as you progress
|
||||
|
||||
## Project context
|
||||
${CONTEXT_BLOCK}
|
||||
${GRAPH_SECTION}
|
||||
${SCRATCH_CONTEXT}
|
||||
$(formula_lessons_block)
|
||||
## Formula
|
||||
${FORMULA_CONTENT}
|
||||
|
||||
${SCRATCH_INSTRUCTION}
|
||||
${PROMPT_FOOTER}
|
||||
_PROMPT_EOF_
|
||||
;;
|
||||
"pitch"|*)
|
||||
# Default: pitch new sprints (original behavior)
|
||||
build_architect_prompt
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ── Create worktree ──────────────────────────────────────────────────────
|
||||
formula_worktree_setup "$WORKTREE"
|
||||
|
|
@ -184,6 +265,71 @@ detect_questions_phase() {
|
|||
return 0
|
||||
}
|
||||
|
||||
# ── Detect if PR is approved and awaiting initial design questions ────────
|
||||
# A PR is in this state when:
|
||||
# - It's an open architect PR on ops repo
|
||||
# - It has an APPROVED review (from human acceptance)
|
||||
# - It has NO `## Design forks` section yet
|
||||
# - It has NO Q1:, Q2:, etc. comments yet
|
||||
# This means the human accepted the pitch and we need to start the design
|
||||
# conversation by posting initial questions and adding the Design forks section.
|
||||
detect_approved_pending_questions() {
|
||||
local pr_number=""
|
||||
local pr_body=""
|
||||
|
||||
# Get open architect PRs on ops repo
|
||||
local ops_repo="${OPS_REPO_ROOT:-/home/agent/data/ops}"
|
||||
if [ ! -d "${ops_repo}/.git" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Use Forgejo API to find open architect PRs
|
||||
local response
|
||||
response=$(curl -sf -H "Authorization: token ${FORGE_TOKEN}" \
|
||||
"${FORGE_API}/repos/${FORGE_OPS_REPO}/pulls?state=open" 2>/dev/null) || return 1
|
||||
|
||||
# Check each open PR for architect markers
|
||||
pr_number=$(printf '%s' "$response" | jq -r '.[] | select(.title | contains("architect:")) | .number' 2>/dev/null | head -1) || return 1
|
||||
|
||||
if [ -z "$pr_number" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Fetch PR body
|
||||
pr_body=$(curl -sf -H "Authorization: token ${FORGE_TOKEN}" \
|
||||
"${FORGE_API}/repos/${FORGE_OPS_REPO}/pulls/${pr_number}" 2>/dev/null | jq -r '.body // empty') || return 1
|
||||
|
||||
# Check for APPROVED review
|
||||
local reviews
|
||||
reviews=$(curl -sf -H "Authorization: token ${FORGE_TOKEN}" \
|
||||
"${FORGE_API}/repos/${FORGE_OPS_REPO}/pulls/${pr_number}/reviews" 2>/dev/null) || return 1
|
||||
|
||||
if ! printf '%s' "$reviews" | jq -e '.[] | select(.state == "APPROVED")' >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check that PR does NOT have `## Design forks` section yet
|
||||
# (we're in the "start questions" phase, not "process answers" phase)
|
||||
if printf '%s' "$pr_body" | grep -q "## Design forks"; then
|
||||
# Has design forks section — this is either in questions phase or past it
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check that PR has NO question comments yet (Q1:, Q2:, etc.)
|
||||
local comments
|
||||
comments=$(curl -sf -H "Authorization: token ${FORGE_TOKEN}" \
|
||||
"${FORGE_API}/repos/${FORGE_OPS_REPO}/issues/${pr_number}/comments" 2>/dev/null) || return 1
|
||||
|
||||
if printf '%s' "$comments" | jq -r '.[].body // empty' | grep -qE 'Q[0-9]+:'; then
|
||||
# Has question comments — this is either in questions phase or past it
|
||||
return 1
|
||||
fi
|
||||
|
||||
# PR is approved and awaiting initial design questions
|
||||
log "Detected PR #${pr_number} approved and awaiting initial design questions"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ── Sub-issue existence check ────────────────────────────────────────────
|
||||
# Check if a vision issue already has sub-issues filed from it.
|
||||
# Returns 0 if sub-issues exist and are open, 1 otherwise.
|
||||
|
|
@ -717,19 +863,32 @@ if [ "${has_responses_to_process:-false}" = "true" ]; then
|
|||
|
||||
# Run agent only if there are responses to process
|
||||
if [ "$needs_agent" = "true" ]; then
|
||||
# Determine whether to resume session
|
||||
# Determine session handling based on PR state
|
||||
RESUME_ARGS=()
|
||||
if detect_questions_phase && [ -f "$SID_FILE" ]; then
|
||||
RESUME_SESSION=$(cat "$SID_FILE")
|
||||
RESUME_ARGS=(--resume "$RESUME_SESSION")
|
||||
log "Resuming session from questions phase run: ${RESUME_SESSION:0:12}..."
|
||||
elif ! detect_questions_phase; then
|
||||
SESSION_MODE="fresh"
|
||||
|
||||
if detect_questions_phase; then
|
||||
# PR is in questions-awaiting-answers phase — resume from that session
|
||||
if [ -f "$SID_FILE" ]; then
|
||||
RESUME_SESSION=$(cat "$SID_FILE")
|
||||
RESUME_ARGS=(--resume "$RESUME_SESSION")
|
||||
SESSION_MODE="questions_phase"
|
||||
log "PR in questions-awaiting-answers phase — resuming session: ${RESUME_SESSION:0:12}..."
|
||||
else
|
||||
log "PR in questions phase but no session file — starting fresh session"
|
||||
fi
|
||||
elif detect_approved_pending_questions; then
|
||||
# PR is approved but awaiting initial design questions — start fresh with special prompt
|
||||
SESSION_MODE="start_questions"
|
||||
log "PR approved and awaiting initial design questions — starting fresh session"
|
||||
else
|
||||
log "PR not in questions phase — starting fresh session"
|
||||
elif [ ! -f "$SID_FILE" ]; then
|
||||
log "No session ID found for questions phase — starting fresh session"
|
||||
fi
|
||||
|
||||
agent_run "${RESUME_ARGS[@]}" --worktree "$WORKTREE" "$PROMPT"
|
||||
# Build prompt with appropriate mode
|
||||
PROMPT_FOR_MODE=$(build_architect_prompt_for_mode "$SESSION_MODE")
|
||||
|
||||
agent_run "${RESUME_ARGS[@]}" --worktree "$WORKTREE" "$PROMPT_FOR_MODE"
|
||||
log "agent_run complete"
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -169,6 +169,19 @@ description = """
|
|||
IMPORTANT: PR creation is handled by bash (architect-run.sh) during the pitch step.
|
||||
This step is for documentation only — the actual PR creation happens in research_pitch.
|
||||
|
||||
## Approved PR → Initial design questions (issue #570)
|
||||
|
||||
When a sprint pitch PR receives an APPROVED review but has no `## Design forks`
|
||||
section and no Q1:, Q2: comments yet, the architect enters a new state:
|
||||
|
||||
1. detect_approved_pending_questions() identifies this state
|
||||
2. A fresh agent session starts with a special prompt
|
||||
3. The agent reads the approved pitch, posts initial design questions (Q1:, Q2:, etc.)
|
||||
4. The agent adds a `## Design forks` section to the PR body
|
||||
5. The PR transitions into the questions phase, where the existing Q&A loop takes over
|
||||
|
||||
This ensures approved PRs don't sit indefinitely without design conversation.
|
||||
|
||||
Architecture:
|
||||
- Bash creates PRs during stateless pitch generation (step 2)
|
||||
- Model has no role in PR creation — no Forgejo API access
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue