feat(uat-validate): add human intervention detection and enhanced fix context

- Add human intervention detection with BLOCKING/WARNING pattern matching
  - Detects .env issues, API keys, permissions, connection failures
  - Categorizes issues for Barry to handle appropriately

- Add story context extraction for fix documents
  - Extracts acceptance criteria from story files
  - Includes Dev Agent Record (implementation notes)

- Enhance fix context generation
  - Includes human intervention items section
  - Adds root cause hints for each failure
  - Appends story context with AC mapping

- Add human actions file generation
  - Creates epic-{id}-human-actions.md with actionable checklist
  - Provides specific guidance per issue type

- Add timing metrics to track UAT evaluation duration
  - Captures start_time, end_time, duration_seconds
  - Shows duration in summary output

- Update output signals with human action flags
  - UAT_HUMAN_ACTION_REQUIRED: true/false
  - UAT_HUMAN_ACTION_COUNT: N
  - UAT_HUMAN_ACTION_FILE: path

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Caleb 2026-01-19 04:37:29 -06:00
parent 2326f72803
commit 9f532eff65
2 changed files with 515 additions and 24 deletions

View File

@ -288,6 +288,181 @@ classify_single_scenario() {
fi
}
# =============================================================================
# Section 5.5: Human Intervention Detection
# =============================================================================
# Arrays to store human intervention items
declare -a HUMAN_INTERVENTION_BLOCKING
declare -a HUMAN_INTERVENTION_WARNING
# Patterns that indicate human intervention is required
BLOCKING_PATTERNS=(
"EACCES|permission denied"
"\.env|environment variable|not set|undefined|not defined"
"API[_-]?KEY|SECRET|TOKEN.*required|missing|invalid"
"authentication failed|unauthorized|401|403"
"license|subscription|quota exceeded"
"EPERM|operation not permitted"
"credentials.*required|credentials.*missing"
)
WARNING_PATTERNS=(
"connection refused|ECONNREFUSED|ETIMEDOUT|timeout"
"check.*inbox|verify.*email|manual.*verification"
"relation.*does not exist|migration|table.*not found"
"deprecated|warning:"
"rate limit|throttl"
"service unavailable|503"
"could not connect|connection failed"
)
detect_human_intervention() {
local error_output="$1"
local scenario_id="$2"
local scenario_name="$3"
# Check for BLOCKING patterns
for pattern in "${BLOCKING_PATTERNS[@]}"; do
if echo "$error_output" | grep -qiE "$pattern"; then
local matched_line
matched_line=$(echo "$error_output" | grep -iE "$pattern" | head -1)
HUMAN_INTERVENTION_BLOCKING+=("$scenario_id|$scenario_name|$matched_line")
[ "$VERBOSE" = true ] && log_warn " [BLOCKING] Detected: $matched_line"
fi
done
# Check for WARNING patterns
for pattern in "${WARNING_PATTERNS[@]}"; do
if echo "$error_output" | grep -qiE "$pattern"; then
local matched_line
matched_line=$(echo "$error_output" | grep -iE "$pattern" | head -1)
HUMAN_INTERVENTION_WARNING+=("$scenario_id|$scenario_name|$matched_line")
[ "$VERBOSE" = true ] && log_warn " [WARNING] Detected: $matched_line"
fi
done
}
analyze_root_cause() {
local error_output="$1"
local exit_code="$2"
# Analyze error patterns and return a hint
if echo "$error_output" | grep -qiE "\.env|environment variable|not set"; then
echo "Missing environment configuration. Check .env file or .env.example for required variables."
elif echo "$error_output" | grep -qiE "API[_-]?KEY|SECRET|TOKEN"; then
echo "Missing or invalid API credentials. Verify API keys are correctly configured."
elif echo "$error_output" | grep -qiE "connection refused|ECONNREFUSED"; then
echo "Service connection failed. Ensure the required service is running (database, redis, etc.)."
elif echo "$error_output" | grep -qiE "relation.*does not exist|table.*not found"; then
echo "Database schema issue. Run migrations or check database setup."
elif echo "$error_output" | grep -qiE "permission denied|EACCES|EPERM"; then
echo "Permission issue. Check file/directory permissions or run with appropriate privileges."
elif echo "$error_output" | grep -qiE "timeout|ETIMEDOUT"; then
echo "Operation timed out. Check network connectivity or increase timeout."
elif [ "$exit_code" -eq 1 ]; then
echo "Command failed with exit code 1. Check the error output for specific details."
elif [ "$exit_code" -eq 124 ]; then
echo "Command timed out. Consider increasing timeout or checking for blocking operations."
else
echo "Analyze error output above. Exit code: $exit_code"
fi
}
# =============================================================================
# Section 5.6: Story Context Extraction
# =============================================================================
extract_story_context() {
local epic_id="$1"
local output_file="$2"
log "Extracting story context for Epic $epic_id..."
# Find story files for this epic
local story_files=()
for pattern in "${epic_id}-" "epic-${epic_id}-" "0${epic_id}-"; do
while IFS= read -r -d '' file; do
story_files+=("$file")
done < <(find "$STORIES_DIR" -name "${pattern}*.md" -print0 2>/dev/null)
done
if [ ${#story_files[@]} -eq 0 ]; then
log_warn "No story files found for Epic $epic_id in $STORIES_DIR"
echo "No story files found for this epic." >> "$output_file"
return 1
fi
log "Found ${#story_files[@]} story file(s)"
echo "## Story Context" >> "$output_file"
echo "" >> "$output_file"
for story_file in "${story_files[@]}"; do
local story_name
story_name=$(basename "$story_file" .md)
echo "### $story_name" >> "$output_file"
echo "" >> "$output_file"
# Extract acceptance criteria section
local in_ac_section=false
local ac_content=""
while IFS= read -r line; do
# Detect start of acceptance criteria section
if echo "$line" | grep -qiE "^##.*[Aa]cceptance [Cc]riteria|^##.*AC"; then
in_ac_section=true
ac_content="**Acceptance Criteria:**"$'\n'
continue
fi
# Detect end of section (next ## header)
if [ "$in_ac_section" = true ] && echo "$line" | grep -qE "^##[^#]"; then
in_ac_section=false
fi
# Accumulate content
if [ "$in_ac_section" = true ]; then
ac_content+="$line"$'\n'
fi
done < "$story_file"
if [ -n "$ac_content" ]; then
echo "$ac_content" >> "$output_file"
else
echo "*No acceptance criteria section found in this story.*" >> "$output_file"
fi
echo "" >> "$output_file"
# Extract Dev Agent Record section (implementation notes)
local in_dar_section=false
local dar_content=""
while IFS= read -r line; do
# Detect start of Dev Agent Record section
if echo "$line" | grep -qiE "^##.*[Dd]ev [Aa]gent [Rr]ecord|^##.*Implementation [Nn]otes"; then
in_dar_section=true
dar_content="**Dev Agent Record (Implementation Notes):**"$'\n'
continue
fi
# Detect end of section (next ## header)
if [ "$in_dar_section" = true ] && echo "$line" | grep -qE "^##[^#]"; then
in_dar_section=false
fi
# Accumulate content
if [ "$in_dar_section" = true ]; then
dar_content+="$line"$'\n'
fi
done < "$story_file"
if [ -n "$dar_content" ]; then
echo "$dar_content" >> "$output_file"
fi
echo "" >> "$output_file"
echo "---" >> "$output_file"
echo "" >> "$output_file"
done
return 0
}
# =============================================================================
# Section 6: Scenario Execution
# =============================================================================
@ -415,6 +590,8 @@ execute_single_scenario() {
log_error " Scenario $scenario_id: FAIL (timeout after ${TIMEOUT_SECONDS}s)"
FAILED_SCENARIOS+=("$scenario_id")
FAILED_DETAILS+=("$scenario_id|$scenario_name|$scenario_cmd|timeout|$exit_code|$output|$stderr")
# Detect human intervention needs from output
detect_human_intervention "$output$stderr" "$scenario_id" "$scenario_name"
else
log_error " Scenario $scenario_id: FAIL (exit code $exit_code)"
if [ -n "$stderr" ] && [ "$VERBOSE" = true ]; then
@ -422,6 +599,8 @@ execute_single_scenario() {
fi
FAILED_SCENARIOS+=("$scenario_id")
FAILED_DETAILS+=("$scenario_id|$scenario_name|$scenario_cmd|error|$exit_code|$output|$stderr")
# Detect human intervention needs from error output
detect_human_intervention "$output$stderr" "$scenario_id" "$scenario_name"
fi
return $exit_code
@ -496,7 +675,41 @@ This document contains the context needed to fix UAT failures for Epic $epic_id.
EOF
fi
# Append failed scenarios details
# Add human intervention section
echo "" >> "$fix_file"
echo "## Human Intervention Items" >> "$fix_file"
echo "" >> "$fix_file"
if [ ${#HUMAN_INTERVENTION_BLOCKING[@]} -gt 0 ]; then
echo "### BLOCKING (likely requires human action)" >> "$fix_file"
echo "" >> "$fix_file"
for item in "${HUMAN_INTERVENTION_BLOCKING[@]}"; do
IFS='|' read -r scenario_id scenario_name matched_line <<< "$item"
echo "- [ ] **Scenario $scenario_id ($scenario_name):** $matched_line" >> "$fix_file"
done
echo "" >> "$fix_file"
fi
if [ ${#HUMAN_INTERVENTION_WARNING[@]} -gt 0 ]; then
echo "### WARNING (may need attention)" >> "$fix_file"
echo "" >> "$fix_file"
for item in "${HUMAN_INTERVENTION_WARNING[@]}"; do
IFS='|' read -r scenario_id scenario_name matched_line <<< "$item"
echo "- [ ] **Scenario $scenario_id ($scenario_name):** $matched_line" >> "$fix_file"
done
echo "" >> "$fix_file"
fi
if [ ${#HUMAN_INTERVENTION_BLOCKING[@]} -eq 0 ] && [ ${#HUMAN_INTERVENTION_WARNING[@]} -eq 0 ]; then
echo "*No human intervention items detected. All failures appear to be code-fixable.*" >> "$fix_file"
echo "" >> "$fix_file"
fi
echo "**Instructions for Barry:** Attempt to fix what you can. For items you cannot resolve programmatically, document them clearly in the fix commit message and update the human-actions file." >> "$fix_file"
echo "" >> "$fix_file"
echo "---" >> "$fix_file"
# Append failed scenarios details with root cause hints
echo "" >> "$fix_file"
echo "## Failed Scenarios" >> "$fix_file"
echo "" >> "$fix_file"
@ -504,6 +717,10 @@ EOF
for detail in "${FAILED_DETAILS[@]}"; do
IFS='|' read -r scenario_id scenario_name cmd error_type exit_code output stderr <<< "$detail"
# Generate root cause hint for this failure
local root_cause_hint
root_cause_hint=$(analyze_root_cause "$output$stderr" "$exit_code")
cat >> "$fix_file" << EOF
### Scenario $scenario_id: $scenario_name
@ -525,11 +742,17 @@ $output
$stderr
\`\`\`
**Root Cause Hint:** $root_cause_hint
---
EOF
done
# Extract and append story context (acceptance criteria + dev agent record)
echo "" >> "$fix_file"
extract_story_context "$epic_id" "$fix_file"
# Add context references section
cat >> "$fix_file" << EOF
@ -586,26 +809,47 @@ run_quick_dev_fix() {
log "Spawning quick-dev fix session (attempt $attempt/$MAX_RETRIES)"
# Build human intervention summary for prompt
local human_intervention_note=""
if [ ${#HUMAN_INTERVENTION_BLOCKING[@]} -gt 0 ] || [ ${#HUMAN_INTERVENTION_WARNING[@]} -gt 0 ]; then
human_intervention_note="
IMPORTANT: Some failures may require human intervention (marked in the fix context).
- For items you CANNOT fix programmatically (missing API keys, .env configuration, etc.):
Document them clearly and proceed with what you CAN fix.
- Do NOT attempt to create fake credentials or placeholder values.
- Focus on code-level fixes that don't require external configuration."
fi
local fix_prompt="You are Barry, the Quick Flow Solo Dev.
Load and process this fix context document:
FIRST: Read the fix context document at:
$fix_context_file
Your task:
1. Read the failed scenarios and error details from the fix context
2. Analyze root cause for each failure
3. Implement targeted fixes
4. Run the failing commands to verify fixes
5. Stage changes: git add -A
6. Commit with message: fix(epic-${epic_id}): UAT fix #${attempt}
This document contains:
1. Human Intervention Items - issues that may require human action
2. Failed Scenarios - with commands, errors, and root cause hints
3. Story Context - acceptance criteria and implementation notes from the original stories
Your task:
1. Read the fix context document completely before starting
2. Review the Human Intervention Items section - note which issues you CAN vs CANNOT fix
3. For each failed scenario:
a. Check the root cause hint
b. Review the related acceptance criteria
c. Implement targeted fixes for code-level issues
4. Run the failing commands to verify your fixes work
5. Stage changes: git add -A
6. Commit with message: fix(epic-${epic_id}): UAT fix #${attempt} - {brief description}
$human_intervention_note
Constraints:
- Only fix the identified failures
- Do not refactor unrelated code
- Run tests after fixes
- Only fix the identified failures - do not refactor unrelated code
- Run the specific failing commands to verify each fix
- Run project tests after all fixes: npm test
- If a fix requires external configuration (API keys, .env), document it but don't block on it
When done, output exactly:
FIX_COMPLETE: {number_fixed}/${#FAILED_SCENARIOS[@]}"
FIX_COMPLETE: {number_fixed}/${#FAILED_SCENARIOS[@]}
HUMAN_ACTION_NEEDED: {yes/no}"
if [ "$DRY_RUN" = true ]; then
echo "[DRY RUN] Would spawn Claude for fixes with prompt:"
@ -621,6 +865,10 @@ FIX_COMPLETE: {number_fixed}/${#FAILED_SCENARIOS[@]}"
if echo "$result" | grep -q "FIX_COMPLETE"; then
log_success "Quick-dev fix session completed"
# Check if human action was flagged
if echo "$result" | grep -q "HUMAN_ACTION_NEEDED: yes"; then
log_warn "Barry indicated human action is needed for some issues"
fi
return 0
else
log_warn "Quick-dev fix session may not have completed cleanly"
@ -628,6 +876,140 @@ FIX_COMPLETE: {number_fixed}/${#FAILED_SCENARIOS[@]}"
fi
}
generate_human_actions_file() {
local epic_id="$1"
local final_attempt="$2"
local human_actions_file="$FIX_DIR/epic-${epic_id}-human-actions.md"
local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Only generate if there are human intervention items
if [ ${#HUMAN_INTERVENTION_BLOCKING[@]} -eq 0 ] && [ ${#HUMAN_INTERVENTION_WARNING[@]} -eq 0 ]; then
log "No human actions required"
return 0
fi
log "Generating human actions file: $human_actions_file"
cat > "$human_actions_file" << EOF
# Human Actions Required - Epic $epic_id
**Generated:** $timestamp
**After:** Fix attempt $final_attempt of $MAX_RETRIES
**UAT Result:** FAIL (${#PASSED_SCENARIOS[@]}/${#AUTOMATABLE_SCENARIOS[@]} scenarios passed)
---
## Required Actions
The following items could not be automatically fixed and require human intervention.
EOF
local action_num=0
# Add BLOCKING items
if [ ${#HUMAN_INTERVENTION_BLOCKING[@]} -gt 0 ]; then
for item in "${HUMAN_INTERVENTION_BLOCKING[@]}"; do
((action_num++))
IFS='|' read -r scenario_id scenario_name matched_line <<< "$item"
cat >> "$human_actions_file" << EOF
### $action_num. $scenario_name (Scenario $scenario_id)
**Priority:** High (BLOCKING)
**Issue:** $matched_line
**Suggested Action:**
EOF
# Add specific guidance based on pattern
if echo "$matched_line" | grep -qiE "\.env|environment variable"; then
cat >> "$human_actions_file" << EOF
Check your \`.env\` file and ensure all required environment variables are set.
Reference \`.env.example\` if available.
EOF
elif echo "$matched_line" | grep -qiE "API[_-]?KEY|SECRET|TOKEN"; then
cat >> "$human_actions_file" << EOF
Verify your API credentials are correctly configured.
Check the service dashboard for valid keys.
EOF
elif echo "$matched_line" | grep -qiE "permission denied|EACCES"; then
cat >> "$human_actions_file" << EOF
Check file/directory permissions. You may need to run with elevated privileges
or adjust ownership/permissions on the affected files.
EOF
else
echo "Review the error message and take appropriate action." >> "$human_actions_file"
echo "" >> "$human_actions_file"
fi
done
fi
# Add WARNING items
if [ ${#HUMAN_INTERVENTION_WARNING[@]} -gt 0 ]; then
for item in "${HUMAN_INTERVENTION_WARNING[@]}"; do
((action_num++))
IFS='|' read -r scenario_id scenario_name matched_line <<< "$item"
cat >> "$human_actions_file" << EOF
### $action_num. $scenario_name (Scenario $scenario_id)
**Priority:** Medium (WARNING)
**Issue:** $matched_line
**Suggested Action:**
EOF
# Add specific guidance based on pattern
if echo "$matched_line" | grep -qiE "connection refused|ECONNREFUSED"; then
cat >> "$human_actions_file" << EOF
Ensure the required service is running (database, Redis, etc.).
Check service logs for startup errors.
EOF
elif echo "$matched_line" | grep -qiE "inbox|email|manual.*verification"; then
cat >> "$human_actions_file" << EOF
Manual verification required. Check the relevant inbox or UI to confirm
the expected behavior.
EOF
elif echo "$matched_line" | grep -qiE "migration|relation.*does not exist"; then
cat >> "$human_actions_file" << EOF
Database schema may need updating. Run migrations:
\`\`\`bash
npm run db:migrate # or your project's migration command
\`\`\`
EOF
else
echo "Review the warning and take appropriate action if needed." >> "$human_actions_file"
echo "" >> "$human_actions_file"
fi
done
fi
cat >> "$human_actions_file" << EOF
---
## After Completing Actions
Re-run UAT validation:
\`\`\`bash
./scripts/uat-validate.sh $epic_id --gate-mode=$UAT_GATE_MODE
\`\`\`
---
*Generated by UAT Validate Workflow*
*BMAD Method - Epic Chain Self-Healing*
EOF
echo "$human_actions_file"
}
self_healing_loop() {
local epic_id="$1"
local attempt=0
@ -637,10 +1019,22 @@ self_healing_loop() {
log_section "Self-Healing Fix Loop (Attempt $attempt/$MAX_RETRIES)"
# Generate fix context
# Reset human intervention arrays for this attempt
HUMAN_INTERVENTION_BLOCKING=()
HUMAN_INTERVENTION_WARNING=()
# Generate fix context (this will detect human intervention items)
local fix_file
fix_file=$(generate_fix_context "$epic_id" "$attempt")
# Log human intervention summary
if [ ${#HUMAN_INTERVENTION_BLOCKING[@]} -gt 0 ]; then
log_warn "Detected ${#HUMAN_INTERVENTION_BLOCKING[@]} BLOCKING human intervention item(s)"
fi
if [ ${#HUMAN_INTERVENTION_WARNING[@]} -gt 0 ]; then
log_warn "Detected ${#HUMAN_INTERVENTION_WARNING[@]} WARNING human intervention item(s)"
fi
# Run quick-dev fix
if ! run_quick_dev_fix "$fix_file" "$epic_id" "$attempt"; then
log_warn "Fix attempt $attempt may have issues"
@ -649,7 +1043,7 @@ self_healing_loop() {
# Re-run validation
log "Re-validating after fix attempt $attempt..."
# Reset and re-execute
# Reset scenario results but preserve human intervention items
PASSED_SCENARIOS=()
FAILED_SCENARIOS=()
FAILED_DETAILS=()
@ -662,6 +1056,9 @@ self_healing_loop() {
log_warn "UAT still failing after attempt $attempt"
done
# Generate human actions file for remaining issues
generate_human_actions_file "$epic_id" "$MAX_RETRIES"
log_error "Max retries ($MAX_RETRIES) exceeded"
return 2
}
@ -678,7 +1075,15 @@ update_metrics() {
mkdir -p "$METRICS_DIR"
local metrics_file="$METRICS_DIR/epic-${epic_id}-metrics.yaml"
local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Calculate timing
local end_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
local end_epoch=$(date +%s)
local duration_seconds=$((end_epoch - UAT_START_EPOCH))
# Calculate human intervention counts
local blocking_count=${#HUMAN_INTERVENTION_BLOCKING[@]}
local warning_count=${#HUMAN_INTERVENTION_WARNING[@]}
# Check if yq is available for YAML manipulation
if command -v yq >/dev/null 2>&1; then
@ -688,7 +1093,11 @@ update_metrics() {
yq -i ".validation.fix_attempts = $fix_attempts" "$metrics_file"
yq -i ".validation.scenarios_passed = ${#PASSED_SCENARIOS[@]}" "$metrics_file"
yq -i ".validation.scenarios_failed = ${#FAILED_SCENARIOS[@]}" "$metrics_file"
yq -i ".validation.timestamp = \"$timestamp\"" "$metrics_file"
yq -i ".validation.start_time = \"$UAT_START_TIME\"" "$metrics_file"
yq -i ".validation.end_time = \"$end_time\"" "$metrics_file"
yq -i ".validation.duration_seconds = $duration_seconds" "$metrics_file"
yq -i ".validation.human_intervention.blocking = $blocking_count" "$metrics_file"
yq -i ".validation.human_intervention.warning = $warning_count" "$metrics_file"
else
# Create new metrics file
cat > "$metrics_file" << EOF
@ -699,7 +1108,12 @@ validation:
fix_attempts: $fix_attempts
scenarios_passed: ${#PASSED_SCENARIOS[@]}
scenarios_failed: ${#FAILED_SCENARIOS[@]}
timestamp: "$timestamp"
start_time: "$UAT_START_TIME"
end_time: "$end_time"
duration_seconds: $duration_seconds
human_intervention:
blocking: $blocking_count
warning: $warning_count
EOF
fi
else
@ -713,7 +1127,12 @@ validation:
fix_attempts: $fix_attempts
scenarios_passed: ${#PASSED_SCENARIOS[@]}
scenarios_failed: ${#FAILED_SCENARIOS[@]}
timestamp: "$timestamp"
start_time: "$UAT_START_TIME"
end_time: "$end_time"
duration_seconds: $duration_seconds
human_intervention:
blocking: $blocking_count
warning: $warning_count
EOF
else
# Simple append for validation section
@ -722,6 +1141,7 @@ EOF
fi
log "Metrics updated: $metrics_file"
log " Duration: ${duration_seconds}s"
}
output_signals() {
@ -730,22 +1150,43 @@ output_signals() {
local total=${#AUTOMATABLE_SCENARIOS[@]}
local passed=${#PASSED_SCENARIOS[@]}
local human_action_count=$((${#HUMAN_INTERVENTION_BLOCKING[@]} + ${#HUMAN_INTERVENTION_WARNING[@]}))
local human_action_required="false"
[ $human_action_count -gt 0 ] && human_action_required="true"
echo ""
echo "UAT_GATE_RESULT: $gate_status"
echo "UAT_FIX_ATTEMPTS: $fix_attempts"
echo "UAT_SCENARIOS_PASSED: $passed/$total"
echo "UAT_HUMAN_ACTION_REQUIRED: $human_action_required"
echo "UAT_HUMAN_ACTION_COUNT: $human_action_count"
if [ "$human_action_required" = "true" ]; then
echo "UAT_HUMAN_ACTION_FILE: $FIX_DIR/epic-${EPIC_ID}-human-actions.md"
fi
}
print_summary() {
local gate_status="$1"
local fix_attempts="$2"
local human_action_count=$((${#HUMAN_INTERVENTION_BLOCKING[@]} + ${#HUMAN_INTERVENTION_WARNING[@]}))
# Calculate duration
local end_epoch=$(date +%s)
local duration_seconds=$((end_epoch - UAT_START_EPOCH))
local duration_display="${duration_seconds}s"
if [ $duration_seconds -ge 60 ]; then
local minutes=$((duration_seconds / 60))
local seconds=$((duration_seconds % 60))
duration_display="${minutes}m ${seconds}s"
fi
log_header "UAT VALIDATION COMPLETE"
echo " Epic: $EPIC_ID"
echo " Gate Mode: $UAT_GATE_MODE"
echo " Gate Result: $gate_status"
echo " Duration: $duration_display"
echo ""
echo " Scenarios:"
echo " Automatable: ${#AUTOMATABLE_SCENARIOS[@]}"
@ -757,23 +1198,57 @@ print_summary() {
echo " Failed: ${#FAILED_SCENARIOS[@]}"
echo " Fix Attempts: $fix_attempts"
echo ""
echo " Human Intervention:"
echo " Blocking Items: ${#HUMAN_INTERVENTION_BLOCKING[@]}"
echo " Warning Items: ${#HUMAN_INTERVENTION_WARNING[@]}"
echo ""
echo " Artifacts:"
echo " Log: $LOG_FILE"
echo " UAT Document: $UAT_FILE"
if [ ${#FAILED_SCENARIOS[@]} -gt 0 ] && [ -d "$FIX_DIR" ]; then
echo " Fix Contexts: $FIX_DIR/"
fi
if [ $human_action_count -gt 0 ]; then
echo " Human Actions: $FIX_DIR/epic-${EPIC_ID}-human-actions.md"
fi
echo ""
# Print human intervention summary if any
if [ $human_action_count -gt 0 ]; then
echo -e "${YELLOW}${BOLD} ⚠ Human Action Required:${NC}"
if [ ${#HUMAN_INTERVENTION_BLOCKING[@]} -gt 0 ]; then
echo -e " ${RED}BLOCKING:${NC}"
for item in "${HUMAN_INTERVENTION_BLOCKING[@]}"; do
IFS='|' read -r scenario_id scenario_name matched_line <<< "$item"
echo " - Scenario $scenario_id: $matched_line"
done
fi
if [ ${#HUMAN_INTERVENTION_WARNING[@]} -gt 0 ]; then
echo -e " ${YELLOW}WARNING:${NC}"
for item in "${HUMAN_INTERVENTION_WARNING[@]}"; do
IFS='|' read -r scenario_id scenario_name matched_line <<< "$item"
echo " - Scenario $scenario_id: $matched_line"
done
fi
echo ""
echo " See $FIX_DIR/epic-${EPIC_ID}-human-actions.md for details."
echo ""
fi
}
# =============================================================================
# Main Execution
# =============================================================================
# Capture UAT evaluation start time
UAT_START_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
UAT_START_EPOCH=$(date +%s)
log_header "UAT VALIDATION: Epic $EPIC_ID"
log "Gate mode: $UAT_GATE_MODE"
log "Max retries: $MAX_RETRIES"
log "Timeout: ${TIMEOUT_SECONDS}s"
log "Started: $UAT_START_TIME"
# Ensure directories exist
mkdir -p "$METRICS_DIR"

View File

@ -18,10 +18,26 @@ This document contains the context needed to fix UAT failures for Epic {epic_id}
## Quick Start
1. Read each failed scenario below
2. Identify root cause from error output
3. Locate and fix the relevant code
4. Verify fix: run the failing command
5. Commit: `fix(epic-{epic_id}): {description}`
1. Review the **Human Intervention Items** section first
2. Read each **Failed Scenario** with its root cause hint
3. Check the **Story Context** for acceptance criteria and implementation notes
4. Implement targeted fixes for code-level issues
5. Verify: run the failing command
6. Commit: `fix(epic-{epic_id}): {description}`
---
## Document Structure
This fix context includes:
1. **Human Intervention Items** - Issues that may require human action (env vars, API keys, etc.)
2. **Failed Scenarios** - Detailed failure information with root cause hints
3. **Story Context** - Acceptance criteria and Dev Agent Record from original stories
For items marked as BLOCKING or WARNING that require human configuration:
- Document what configuration is needed
- Proceed with code fixes you CAN make
- Do not create placeholder credentials or fake values
---