aios-core
Version:
Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework
444 lines (353 loc) • 18.7 kB
YAML
workflow:
id: qa-loop
name: QA Loop Orchestrator - Review Fix Re-review Cycle
version: "1.0"
description: >-
Automated QA loop that orchestrates the review → fix → re-review cycle.
Runs up to maxIterations (default 5), tracking each iteration's results.
Escalates to human when max iterations reached or manual stop requested.
Part of Epic 6 - QA Evolution: Autonomous Development Engine (ADE).
type: loop
project_types:
- aios-development
- autonomous-development
- qa-automation
# ═══════════════════════════════════════════════════════════════════════════════════
# TRIGGER CONFIGURATION
# ═══════════════════════════════════════════════════════════════════════════════════
triggers:
# Primary trigger: Explicit command to start loop
- event: command
command: "*qa-loop"
action: start_loop
# Start from specific phase
- event: command
command: "*qa-loop-review"
action: run_step
step: review
- event: command
command: "*qa-loop-fix"
action: run_step
step: fix
# Stop command (AC5)
- event: command
command: "*stop-qa-loop"
action: stop_loop
# Resume command
- event: command
command: "*resume-qa-loop"
action: resume_loop
# Force escalation
- event: command
command: "*escalate-qa-loop"
action: escalate
# ═══════════════════════════════════════════════════════════════════════════════════
# CONFIGURATION
# ═══════════════════════════════════════════════════════════════════════════════════
config:
# AC2: Maximum iterations (configurable)
maxIterations: 5
configPath: autoClaude.qaLoop.maxIterations
# Progress tracking
showProgress: true
verbose: true
# Status file location (AC4)
statusFile: qa/loop-status.json
# Dashboard integration (AC7)
dashboardStatusPath: .aios/dashboard/status.json
legacyStatusPath: .aios/status.json
# Timeout per phase (milliseconds)
reviewTimeout: 1800000 # 30 minutes
fixTimeout: 3600000 # 60 minutes
# Retry configuration
maxRetries: 2
retryDelay: 5000
# ═══════════════════════════════════════════════════════════════════════════════════
# LOOP STATUS SCHEMA (AC4)
# ═══════════════════════════════════════════════════════════════════════════════════
status_schema:
storyId: string
currentIteration: number
maxIterations: number
status: "pending | in_progress | completed | stopped | escalated"
startedAt: ISO-8601
updatedAt: ISO-8601
history:
- iteration: number
reviewedAt: ISO-8601
verdict: "APPROVE | REJECT | BLOCKED"
issuesFound: number
fixedAt: ISO-8601 | null
issuesFixed: number | null
duration: number # milliseconds
# ═══════════════════════════════════════════════════════════════════════════════════
# WORKFLOW SEQUENCE
# ═══════════════════════════════════════════════════════════════════════════════════
sequence:
# ═════════════════════════════════════════════════════════════════════════════════
# STEP 1: REVIEW (QA Agent)
# ═════════════════════════════════════════════════════════════════════════════════
- step: review
phase: 1
phase_name: "QA Review"
agent: qa
description: >-
Execute comprehensive QA review of the story implementation.
Produces a verdict: APPROVE, REJECT, or BLOCKED.
task: qa-review-story.md
inputs:
storyId: "{storyId}"
iteration: "{currentIteration}"
previousIssues: "{history[-1].issuesFound|0}"
outputs:
- gate-file.yaml
- verdict
- issuesFound
timeout: "{config.reviewTimeout}"
on_success:
log: "Review complete: {verdict} ({issuesFound} issues)"
next: check_verdict
on_failure:
action: retry
max_retries: "{config.maxRetries}"
on_exhausted: escalate
# ═════════════════════════════════════════════════════════════════════════════════
# STEP 2: CHECK VERDICT (AC1)
# ═════════════════════════════════════════════════════════════════════════════════
- step: check_verdict
phase: 2
phase_name: "Verdict Check"
agent: system
description: >-
Evaluate the review verdict and determine next action.
APPROVE = complete, REJECT = continue to fix, BLOCKED = escalate.
condition_check:
- condition: verdict == "APPROVE"
action: complete
log: "Story APPROVED after {currentIteration} iteration(s)"
- condition: verdict == "BLOCKED"
action: escalate
reason: "QA review BLOCKED - requires human intervention"
- condition: verdict == "REJECT"
action: continue
next: create_fix_request
# ═════════════════════════════════════════════════════════════════════════════════
# STEP 3: CREATE FIX REQUEST (QA Agent)
# ═════════════════════════════════════════════════════════════════════════════════
- step: create_fix_request
phase: 3
phase_name: "Create Fix Request"
agent: qa
description: >-
Generate a structured fix request document from review findings.
Prioritizes issues and provides actionable fix instructions.
task: qa-create-fix-request.md
inputs:
storyId: "{storyId}"
gateFile: "{outputs.review.gate-file}"
iteration: "{currentIteration}"
outputs:
- fix-request.md
- prioritizedIssues
on_success:
log: "Fix request created with {prioritizedIssues.length} prioritized issues"
next: fix_issues
on_failure:
action: continue
fallback: "Use raw gate file for fixes"
# ═════════════════════════════════════════════════════════════════════════════════
# STEP 4: FIX ISSUES (Dev Agent)
# ═════════════════════════════════════════════════════════════════════════════════
- step: fix_issues
phase: 4
phase_name: "Apply Fixes"
agent: dev
description: >-
Developer agent applies fixes based on the fix request.
Runs tests and validates changes.
task: dev-apply-qa-fixes.md
inputs:
storyId: "{storyId}"
fixRequest: "{outputs.create_fix_request.fix-request}"
iteration: "{currentIteration}"
outputs:
- fixes-applied.json
- issuesFixed
timeout: "{config.fixTimeout}"
on_success:
log: "Fixed {issuesFixed} of {issuesFound} issues"
next: increment_iteration
on_failure:
action: retry
max_retries: "{config.maxRetries}"
on_exhausted:
action: escalate
reason: "Dev agent unable to apply fixes after retries"
# ═════════════════════════════════════════════════════════════════════════════════
# STEP 5: INCREMENT ITERATION (AC2)
# ═════════════════════════════════════════════════════════════════════════════════
- step: increment_iteration
phase: 5
phase_name: "Check Iteration"
agent: system
description: >-
Increment iteration counter and check against max.
If max reached, escalate to human (AC3).
action: increment_and_check
condition_check:
- condition: currentIteration >= maxIterations
action: escalate
reason: "Max iterations ({maxIterations}) reached without APPROVE"
log: "Max iterations reached - escalating to human"
- condition: currentIteration < maxIterations
action: continue
next: review
log: "Starting iteration {currentIteration + 1}/{maxIterations}"
# ═══════════════════════════════════════════════════════════════════════════════════
# ESCALATION (AC3)
# ═══════════════════════════════════════════════════════════════════════════════════
escalation:
enabled: true
triggers:
- max_iterations_reached
- verdict_blocked
- fix_failure
- manual_escalate
action:
log: "Escalating to human with full context"
status: "escalated"
context_package:
- loop-status.json
- all gate files from history
- all fix requests
- summary of iterations
notification:
message: |
QA Loop Escalation for {storyId}
Reason: {escalation.reason}
Iterations completed: {currentIteration}
Last verdict: {history[-1].verdict}
Outstanding issues: {history[-1].issuesFound - history[-1].issuesFixed}
Review the context package and decide:
1. Resume loop: *resume-qa-loop {storyId}
2. Manually fix and approve
3. Reject story and create follow-up
channels: [log, console]
# ═══════════════════════════════════════════════════════════════════════════════════
# WORKFLOW COMPLETION (AC6)
# ═══════════════════════════════════════════════════════════════════════════════════
completion:
success_message: |
╔══════════════════════════════════════════════════════════════╗
║ QA Loop Complete ║
╚══════════════════════════════════════════════════════════════╝
Story: {storyId}
Status: {status}
Iterations: {currentIteration}/{maxIterations}
Final Verdict: {history[-1].verdict}
Iteration History:
{history.map(h => ` ${h.iteration}. ${h.verdict} - ${h.issuesFound} found, ${h.issuesFixed || 0} fixed`).join('\n')}
Duration: {totalDuration}
summary:
storyId: "{storyId}"
status: "{status}"
iterations: "{currentIteration}"
finalVerdict: "{history[-1].verdict}"
totalIssuesFound: "{history.reduce((sum, h) => sum + h.issuesFound, 0)}"
totalIssuesFixed: "{history.reduce((sum, h) => sum + (h.issuesFixed || 0), 0)}"
duration: "{totalDuration}"
outputs:
- loop-status.json
- summary.md
# ═══════════════════════════════════════════════════════════════════════════════════
# ERROR HANDLING
# ═══════════════════════════════════════════════════════════════════════════════════
error_handling:
missing_story_id:
message: "Story ID is required"
suggestion: "Usage: *qa-loop STORY-42"
action: prompt
review_timeout:
message: "Review phase timed out"
suggestion: "Check QA agent status and retry: *resume-qa-loop {storyId}"
action: escalate
fix_timeout:
message: "Fix phase timed out"
suggestion: "Check Dev agent status and retry: *resume-qa-loop {storyId}"
action: escalate
invalid_status:
message: "Loop status file is corrupted or invalid"
suggestion: "Reset loop: *qa-loop {storyId} --reset"
action: halt
# ═══════════════════════════════════════════════════════════════════════════════════
# STOP/RESUME SUPPORT (AC5)
# ═══════════════════════════════════════════════════════════════════════════════════
control:
stop:
command: "*stop-qa-loop"
action: |
- Set status to "stopped"
- Save current state to loop-status.json
- Log: "QA loop stopped at iteration {currentIteration}"
- Allow resume later
resume:
command: "*resume-qa-loop"
action: |
- Load state from loop-status.json
- Verify status was "stopped" or "escalated"
- Set status to "in_progress"
- Continue from last step
- Log: "QA loop resumed at iteration {currentIteration}"
reset:
command: "*qa-loop --reset"
action: |
- Delete loop-status.json
- Start fresh loop
- Log: "QA loop reset for {storyId}"
# ═══════════════════════════════════════════════════════════════════════════════════
# DASHBOARD INTEGRATION (AC7)
# ═══════════════════════════════════════════════════════════════════════════════════
integration:
status_json:
track_loop: true
field: qaLoop
update_on_each_iteration: true
schema:
storyId: string
status: string
currentIteration: number
maxIterations: number
lastVerdict: string
lastIssuesFound: number
updatedAt: ISO-8601
project_status:
update_story_status: true
status_field: qaLoopStatus
notifications:
on_approve:
message: "QA Loop APPROVED: {storyId}"
channels: [log]
on_escalate:
message: "QA Loop ESCALATED: {storyId} - needs attention"
channels: [log]
on_stop:
message: "QA Loop STOPPED: {storyId}"
channels: [log]
# ═══════════════════════════════════════════════════════════════════════════════════
# METADATA
# ═══════════════════════════════════════════════════════════════════════════════════
metadata:
story: "6.5"
epic: "Epic 6 - QA Evolution"
created: "2026-01-29"
author: "@architect (Aria)"
dependencies:
- qa-review-story.md
- qa-create-fix-request.md
- dev-apply-qa-fixes.md
tags:
- qa-loop
- workflow
- orchestration
- ade
- autonomous