| name | flux-epic-review |
| description | Epic completion review - adversarial dual-model review, external bot self-heal, browser QA, and learning capture. Full thorough review at epic level. Triggers on /flux:epic-review. |
| user-invocable | false |
Epic Completion Review Mode
Read workflow.md for detailed phases and anti-patterns.
Thorough review at epic completion. Combines adversarial dual-model review (two different models reach consensus), external bot self-heal (Greptile/CodeRabbit), browser QA, and learning capture. Cross-lab pairs (Anthropic + OpenAI) are strongest, but same-provider pairs work too. Per-task lightweight reviews happen via /flux:impl-review โ this is the heavy-weight pass.
Role: Epic Review Coordinator (NOT the reviewer)
Backends: RepoPrompt (rp) or Codex CLI (codex)
Session Phase Tracking
On entry (after FLUXCTL is resolved), set the session phase:
$FLUXCTL session-phase set epic_review
On completion, reset:
$FLUXCTL session-phase set idle
CRITICAL: fluxctl is BUNDLED โ NOT installed globally. which fluxctl will fail (expected). Always use:
PLUGIN_ROOT="${DROID_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}}"
[ ! -d "$PLUGIN_ROOT/scripts" ] && PLUGIN_ROOT=$(ls -td ~/.claude/plugins/cache/nairon-flux/flux/*/ 2>/dev/null | head -1)
FLUXCTL="${PLUGIN_ROOT}/scripts/fluxctl"
Backend Selection
Priority (first match wins):
--review=rp|codex|none argument
FLUX_REVIEW_BACKEND env var (rp, codex, none)
.flux/config.json โ review.backend
- Error - no auto-detection
Parse from arguments first
Check $ARGUMENTS for:
--review=rp or --review rp โ use rp
--review=codex or --review codex โ use codex
--review=none or --review none โ skip review
If found, use that backend and skip all other detection.
Otherwise read from config
BACKEND=$($FLUXCTL review-backend)
if [[ "$BACKEND" == "ASK" ]]; then
echo "Error: No review backend configured."
echo "Run /flux:setup to configure, or pass --review=rp|codex|none"
exit 1
fi
echo "Review backend: $BACKEND (override: --review=rp|codex|none)"
Critical Rules
For rp backend:
- DO NOT REVIEW CODE YOURSELF - you coordinate, RepoPrompt reviews
- MUST WAIT for actual RP response - never simulate/skip the review
- MUST use
setup-review - handles window selection + builder atomically
- DO NOT add --json flag to chat-send - it suppresses the review response
- Re-reviews MUST stay in SAME chat - omit
--new-chat after first review
For codex backend:
- Use
$FLUXCTL codex completion-review exclusively
- Pass
--receipt for session continuity on re-reviews
- Parse verdict from command output
For all backends:
- If
REVIEW_RECEIPT_PATH set: write receipt after SHIP verdict (RP writes manually after fix loop; codex writes automatically via --receipt)
- Any failure โ output
<promise>RETRY</promise> and stop
- Use
flux-receive-review when sorting valid issues from reviewer or bot feedback.
FORBIDDEN:
- Self-declaring SHIP without actual backend verdict
- Mixing backends mid-review (stick to one)
- Skipping review silently (must inform user and exit cleanly when backend is "none")
Input
Arguments: $ARGUMENTS
Format: <epic-id> [--review=rp|codex|none]
- Epic ID - Required, e.g.
fn-1 or fn-22-53k
--review - Optional backend override
Workflow Overview
See workflow.md for full details on each phase.
The epic review is a multi-phase pipeline:
- Spec Compliance Review โ verify all epic requirements are implemented (via backend)
- Adversarial Review โ dual-model consensus review (if reviewer1 + reviewer2 configured)
- Severity Filtering โ split issues into fix-list vs log-only based on configured threshold
- Fix Loop โ auto-fix issues at/above threshold, re-review until SHIP
- Security Scan โ STRIDE-based vulnerability scan on changed files (auto-triggered for security-sensitive changes)
- External Bot Self-Heal โ poll Greptile/CodeRabbit for additional issues (if configured)
- Browser QA โ test acceptance criteria via QA checklist from scoping (if agent-browser available)
- Learning Capture โ extract patterns from NEEDS_WORK iterations and human-confirmed review anti-patterns to
.flux/brain/pitfalls/ or structural rule candidates
- Desloppify Scan โ lightweight quality scan on changed files (if desloppify installed)
- Frustration Signal โ auto-trigger recommendation search if friction score >= 3
PLUGIN_ROOT="${DROID_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}}"
[ ! -d "$PLUGIN_ROOT/scripts" ] && PLUGIN_ROOT=$(ls -td ~/.claude/plugins/cache/nairon-flux/flux/*/ 2>/dev/null | head -1)
FLUXCTL="${PLUGIN_ROOT}/scripts/fluxctl"
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
$FLUXCTL architecture status --json
Step 0: Parse Arguments
Parse $ARGUMENTS for:
- First positional arg matching
fn-* โ EPIC_ID
--review=<backend> โ backend override
- Remaining args โ focus areas
Step 1: Load Review Config
REVIEWER1=$($FLUXCTL config get review.reviewer1 2>/dev/null || echo "")
REVIEWER2=$($FLUXCTL config get review.reviewer2 2>/dev/null || echo "")
REVIEW_BOT=$($FLUXCTL config get review.bot 2>/dev/null || echo "")
SEVERITIES=$($FLUXCTL config get review.severities 2>/dev/null || echo "critical,major")
REVIEWER1: First review model (e.g., claude-sonnet-4-6, gpt-5.4)
REVIEWER2: Second review model โ must be different from REVIEWER1 (e.g., gpt-5.3-codex, claude-opus-4-6)
REVIEW_BOT: greptile, coderabbit, or empty
SEVERITIES: comma-separated list of severity levels to auto-fix (e.g., critical,major)
Step 2: Detect Backend & Run Spec Compliance Review
Run backend detection from above. Then branch:
Codex Backend
RECEIPT_PATH="${REVIEW_RECEIPT_PATH:-/tmp/completion-review-receipt.json}"
$FLUXCTL codex completion-review "$EPIC_ID" --receipt "$RECEIPT_PATH"
On NEEDS_WORK: fix code, commit, re-run (receipt enables session continuity).
Missing architecture-diagram updates are in scope here when the epic changed the product's
high-level architecture. .flux/brain/codebase/architecture.md is a canonical artifact, not optional docs.
RepoPrompt Backend
Stop: You MUST read and execute workflow.md now.
Go to the "RepoPrompt Backend Workflow" section in workflow.md and execute those steps. Do not proceed here until workflow.md phases are complete.
Return here only after workflow.md spec compliance review is complete.
Step 3: Adversarial Review (if configured)
Only runs if BOTH reviewer1 AND reviewer2 are configured.
If only one reviewer or neither is configured, skip to Step 4.
See workflow.md "Adversarial Review Phase" for full details. Summary:
- Reviewer 1 reviews the diff independently via Codex/RP
- Reviewer 2 reviews the same diff independently via Codex/RP
- Consensus merge: Issues flagged by BOTH reviewers = high-confidence (auto-fix). Issues flagged by only one = log-only (unless at/above severity threshold).
The adversarial approach catches more issues than a single model while reducing false positives through consensus.
Step 4: Severity Filtering
Split all issues (from spec review + adversarial review) into two buckets:
- Fix list: Issues at or above the configured severity threshold โ auto-fix
- Log only: Issues below threshold โ log to review output but don't fix
Severity ranking: critical > major > minor > style
If SEVERITIES = ["critical", "major"], then critical and major issues are auto-fixed; minor and style are logged only.
Step 5: Fix Loop (INTERNAL - do not exit to Ralph)
CRITICAL: Do NOT ask user for confirmation. Automatically fix ALL issues in the fix-list and re-review. Never use AskUserQuestion in this loop.
If verdict is NEEDS_WORK and fix-list is non-empty, loop internally until SHIP:
- Parse issues from reviewer feedback (filter by severity threshold)
- Fix code and run tests/lints
- Commit fixes (mandatory before re-review)
- Re-review:
- Codex: Re-run
fluxctl codex completion-review (receipt enables context)
- RP:
$FLUXCTL rp chat-send --window "$W" --tab "$T" --message-file /tmp/re-review.md (NO --new-chat)
- Repeat until
<verdict>SHIP</verdict>
CRITICAL: For RP, re-reviews must stay in the SAME chat so reviewer has context. Only use --new-chat on the FIRST review.
MAX ITERATIONS: Limit fix+re-review cycles to ${MAX_REVIEW_ITERATIONS:-3} iterations. If still NEEDS_WORK after max rounds, output <promise>RETRY</promise> and stop.
Before declaring SHIP at any phase boundary, apply flux-verify-claims.
Step 6: Security Scan (auto-triggered)
Runs automatically when changed files touch security-sensitive areas.
Detect if the epic's changed files include security-sensitive patterns:
CHANGED_FILES="$(git diff main..HEAD --name-only 2>/dev/null || git diff master..HEAD --name-only)"
SECURITY_FILES=$(echo "$CHANGED_FILES" | grep -iE '(auth|login|session|token|middleware|permission|rbac|acl|secret|credential|api[-_]?key|security|crypto|encrypt|password|oauth|jwt|cors|csrf|sanitiz|valid)' || echo "")
If SECURITY_FILES is non-empty: Run the flux-security-review skill in staged mode against the branch diff. This invokes the full STRIDE scan (Spoofing, Tampering, Repudiation, Information Disclosure, DoS, Elevation of Privilege) with exploitability validation.
If SECURITY_FILES is empty: Skip security scan (pure UI or non-security changes).
After scan:
- Parse
validated-findings.json for confirmed vulnerabilities (confidence >= 0.8)
- Filter by severity threshold (same
SEVERITIES config)
- Auto-fix findings in fix-list
- Commit:
git commit -m "fix: address security scan findings"
- Re-scan if critical findings were found (max 1 re-scan)
Security findings are also captured in the Learning Capture phase.
Step 7: External Bot Self-Heal (if configured)
Only runs if review.bot is configured AND a PR exists for the branch.
See workflow.md "External Bot Self-Heal Phase" for full details. Summary:
Greptile
- Push branch and ensure PR exists
- Poll PR description for Greptile confidence summary (check every 15s, timeout 5 min)
- Parse confidence score and issue list
- Fix any issues at/above severity threshold
- Push fixes and re-poll until confidence is acceptable
CodeRabbit
- Push branch and ensure PR exists
- Run
coderabbit review CLI or poll PR comments for CodeRabbit review
- Parse issue list from review output
- Fix any issues at/above severity threshold
- Push fixes and wait for re-review
Step 8: Browser QA (if applicable)
Only runs if agent-browser is detected on PATH AND a Browser QA Checklist task exists for this epic.
During scoping (/flux:scope), Flux auto-creates a "Browser QA Checklist" task for epics that involve frontend/web changes. This task contains testable criteria โ URLs, expected elements, user flows โ that the browser QA phase follows.
See workflow.md "Browser QA Phase" for full details. Summary:
- Check if
agent-browser is available: command -v agent-browser >/dev/null 2>&1
- Look for a Browser QA Checklist task in the epic:
$FLUXCTL tasks --epic "$EPIC_ID" --json | jq '.[] | select(.title | test("Browser QA|browser.qa"; "i"))'
- If no checklist task exists, skip browser QA
- Read the checklist task's acceptance criteria
- For each criterion:
- Open URL with
agent-browser open <url>
- Take snapshot with
agent-browser snapshot -i
- Verify expected elements/text exist
- Take screenshot for evidence:
agent-browser screenshot "/tmp/qa-${EPIC_ID}-${n}.png"
- If any criterion fails: fix code, commit, re-test (max 2 iterations)
- Close browser session:
agent-browser close
Step 9: Learning Capture
After the full review pipeline reaches SHIP, extract learnings from any NEEDS_WORK iterations and persist them to the brain vault.
Pitfalls are organized by area of concern under .flux/brain/pitfalls/<area>/. The agent decides the area intelligently based on the pitfall's domain.
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
PITFALLS_DIR="$REPO_ROOT/.flux/brain/pitfalls"
AREA="<area>"
mkdir -p "$PITFALLS_DIR/$AREA"
cat > "$PITFALLS_DIR/$AREA/<pattern-slug>.md" << 'EOF'
<description>
**Source**: epic-review (<epic-id>)
**Date**: <date>
EOF
Area selection rules:
- Check existing area directories in
.flux/brain/pitfalls/ โ use one if it fits
- If no existing area matches, create a new directory with a short, descriptive slug
- Keep areas broad enough to group related pitfalls (e.g.,
frontend not react-forms)
- When in doubt, check what's already there:
ls .flux/brain/pitfalls/
Update .flux/brain/index.md to include new pitfall area entries.
Format: one file per pattern, organized by area (e.g., .flux/brain/pitfalls/frontend/missing-error-states.md).
What to capture:
- Spec compliance gaps โ requirements that drifted from spec
- Adversarial consensus patterns โ issues both models flagged (high-signal)
- Security scan findings โ STRIDE vulnerabilities caught post-implementation
- External bot patterns โ recurring issues caught by Greptile/CodeRabbit
- Browser QA failures โ UI/UX issues missed during implementation
Only capture generalizable patterns, not one-off fixes. These feed back into the worker via .flux/brain/pitfalls/ which is read during re-anchor โ but only the relevant area subdirectories are loaded, keeping context lean. Over time, /flux:meditate promotes recurring pitfalls into proper principles and prunes one-offs.
Step 10: Desloppify Scan (optional)
Only runs if desloppify is installed. This is a scan-only pass โ no fix loop, no auto-fix. The purpose is to surface quality regressions introduced during the epic.
if command -v desloppify >/dev/null 2>&1; then
CHANGED_DIRS=$(git diff "${DIFF_BASE}"..HEAD --name-only | xargs -I{} dirname {} | sort -u | grep -v '^\.$')
if [ -n "$CHANGED_DIRS" ]; then
for DIR in $CHANGED_DIRS; do
desloppify scan --path "$DIR" 2>/dev/null
done
fi
fi
- If score is below 85, suggest:
"Consider running /flux:desloppify to address quality issues introduced in this epic."
- Do NOT auto-install desloppify. Skip silently if not available.
- Do NOT enter a fix loop โ this is informational only.
Step 11: Frustration Signal
See workflow.md "Frustration Signal" for full detection logic (quantitative + qualitative).
Two-part detection system:
Part 1 โ Quantitative friction score from pipeline counters:
FRICTION_SCORE = NEEDS_WORK_COUNT + SECURITY_FINDINGS + BROWSER_QA_FAILURES + (SAME_CATEGORY_PITFALLS * 2)
Part 2 โ Qualitative friction analysis from three sources:
- Developer messages during fix loops โ scan for frustration language and extract the topic (e.g., "wtf is this UI? Still not responsive" โ
responsive, css_issues, ui_issues)
- Review issue categories โ classify reviewer feedback into domains (CSS/auth/testing/etc.)
- Pitfall areas from learning capture โ
.flux/brain/pitfalls/frontend/ โ frontend, ui_issues
Combined into FRICTION_DOMAINS (what's broken) and FRICTION_SIGNALS (what /flux:improve should search for).
If FRICTION_SCORE >= 3, auto-trigger /flux:improve with the detected friction context:
- Tell the user what friction was detected:
---
**Friction detected** (score: {FRICTION_SCORE}):
Quantitative:
- Review iterations: {NEEDS_WORK_COUNT}
- Security findings: {SECURITY_FINDINGS}
- Browser QA failures: {BROWSER_QA_FAILURES}
- Repeated pitfall categories: {SAME_CATEGORY_PITFALLS} (2x weight)
Diagnosis: {primary friction domain} โ {one-sentence summary}
Evidence:
{top 2-3 quotes/issues/pitfalls}
Auto-searching for recommendations to address this...
---
- Fresh-fetch the latest recommendations index (with timeout and error handling):
RECS_RAW=$(curl -sL --connect-timeout 10 --max-time 30 "https://raw.githubusercontent.com/Nairon-AI/flux-recommendations/main/recommendations.json")
CURL_EXIT=$?
If CURL_EXIT != 0 or RECS_RAW is empty, tell the user recommendations are unavailable and skip steps 3-4. Do not fail the entire epic review.
-
Guard against empty friction domains โ if FRICTION_DOMAINS is empty but score >= 3 (can happen when score comes purely from quantitative counters), use the quantitative signal types as search terms instead (e.g., NEEDS_WORK โ "linting, formatting", SECURITY_FINDINGS โ "security scanning", BROWSER_QA_FAILURES โ "visual regression testing").
-
Search the recommendations for entries matching FRICTION_DOMAINS and FRICTION_SIGNALS. Score each recommendation by how many friction signals it addresses. Present the top 3-5 matches with:
- Tool name and what it does
- Which specific friction it addresses
- Install command or setup steps
-
Ask the user which (if any) to install now. Do not auto-install โ the user picks.
The --user-context flag pre-fills the detected friction domains so /flux:improve's matching engine can skip discovery and go straight to relevant tool recommendations.
Update Check (End of Command)
ALWAYS run at the very end of command execution:
PLUGIN_ROOT="${DROID_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}}"
[ ! -d "$PLUGIN_ROOT/scripts" ] && PLUGIN_ROOT=$(ls -td ~/.claude/plugins/cache/nairon-flux/flux/*/ 2>/dev/null | head -1)
UPDATE_JSON=$("$PLUGIN_ROOT/scripts/version-check.sh" 2>/dev/null || echo '{"update_available":false}')
UPDATE_AVAILABLE=$(echo "$UPDATE_JSON" | jq -r '.update_available')
LOCAL_VER=$(echo "$UPDATE_JSON" | jq -r '.local_version')
REMOTE_VER=$(echo "$UPDATE_JSON" | jq -r '.remote_version')
If update available, append to output:
---
Flux update available: v${LOCAL_VER} โ v${REMOTE_VER}
Update Flux from the same source you installed it from, then restart your agent session.
---