From 8bbf6cbb2fc75565b1e740bac2fcc3f8afb7d42a Mon Sep 17 00:00:00 2001 From: Paul O'Reilly Date: Mon, 4 May 2026 18:29:47 +1200 Subject: [PATCH] BUG-5/BUG-20 fixes: pre_test.sh, output validation, push retry, workflow output tags - pre_test.sh: harness-level test folder revert script, replaces inline _revert_test_folders() in entrypoint. Writes {"reverted": N} atomically. - finalize.sh: set -x debug tracing; push retry (AGENT_PUSH_RETRIES, default 1 retry after 5s); output validation (AGENT_EXPECTED_OUTPUT env var); wrong-path detection moves .agent-output/ files to working dir and writes .correction-prompt.txt for entrypoint re-invoke - harness.yaml: add scripts.pre_test - spec-planning.yaml: all 17 nodes tagged with output:{path,min_bytes} Co-Authored-By: Claude Opus 4.7 --- harnesses/contexts/agent-repo/v1/finalize.sh | 116 +- harnesses/contexts/agent-repo/v1/harness.yaml | 1 + harnesses/contexts/agent-repo/v1/pre_test.sh | 64 + workflows/spec-planning.yaml | 1408 ++++++++++------- 4 files changed, 972 insertions(+), 617 deletions(-) create mode 100644 harnesses/contexts/agent-repo/v1/pre_test.sh diff --git a/harnesses/contexts/agent-repo/v1/finalize.sh b/harnesses/contexts/agent-repo/v1/finalize.sh index 9056bf1..cf7e99d 100644 --- a/harnesses/contexts/agent-repo/v1/finalize.sh +++ b/harnesses/contexts/agent-repo/v1/finalize.sh @@ -1,6 +1,6 @@ #!/bin/bash # Agent repo finalize script — auto-commit and push changes -# AR-19, AR-20, AR-8, AR-32, F66 +# AR-19, AR-20, AR-8, AR-32, F66, BUG-5, BUG-20 set -euo pipefail # --------------------------------------------------------------------------- @@ -48,6 +48,7 @@ if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then fi echo "=== agent-repo/v1 finalize.sh ===" +set -x # BUG-20: trace all commands for diagnostic visibility WORKING_DIR="${AGENT_WORKING_DIR:-/workspace/project}" AGENT_OUTPUT_DIR="${AGENT_OUTPUT_DIR:-/workspace/.agent-output}" @@ -56,6 +57,8 @@ AGENT_EXIT="${AGENT_EXIT_CODE:-0}" TASK_ID="${AGENT_TASK_ID:-unknown}" BRANCH="${AGENT_BRANCH:-}" REPO_URL="${AGENT_REPO_URL:-}" +# BUG-20: Push retry +PUSH_RETRIES="${AGENT_PUSH_RETRIES:-1}" mkdir -p "$AGENT_OUTPUT_DIR" @@ -83,13 +86,8 @@ if [ -f "$HARNESS_GITIGNORE" ]; then cat "$HARNESS_GITIGNORE" >> .gitignore fi -# AR-8: Check if there are any changes to commit -git add -A - # AR-37/F73-10: Exclude protected test folders from commit. # PROTECTED_TEST_FOLDERS is set by entrypoint.py when test_pass_required is active. -# This is defense-in-depth: prevents test file changes reaching the agent branch even -# if the entrypoint revert had a window between the last test run and finalize. if [ -n "${PROTECTED_TEST_FOLDERS:-}" ]; then IFS=',' read -ra _PROTECTED_FOLDERS <<< "$PROTECTED_TEST_FOLDERS" for _folder in "${_PROTECTED_FOLDERS[@]}"; do @@ -109,9 +107,45 @@ if [ -n "${PROTECTED_TEST_FOLDERS:-}" ]; then done fi +# AR-8: Check if there are any changes to commit +echo "Running: git add -A" +git add -A + +# BUG-5 correction: detect wrong-path writes to .agent-output/ +# These files are gitignored and will not be committed — move them to working dir +if [ -d "$WORKING_DIR/.agent-output" ]; then + # Find files in .agent-output/ that are NOT metadata/sentinel files + CORRECTION_FILES=$(ls "$WORKING_DIR/.agent-output/" 2>/dev/null | grep -v -E '^(ci_metadata|finalize-error|correction-prompt|pre-test-result)' || true) + if [ -n "$CORRECTION_FILES" ]; then + echo "WARNING: Files found in .agent-output/ — moving to working directory for commit" + echo "Offending files:" + echo "$CORRECTION_FILES" + for _f in $CORRECTION_FILES; do + if [ -f "$WORKING_DIR/.agent-output/$_f" ]; then + cp "$WORKING_DIR/.agent-output/$_f" "$WORKING_DIR/$_f" + echo " Moved: $_f -> $WORKING_DIR/$_f" + fi + done + # Write correction notice that will trigger re-invoke in entrypoint + cat > "$AGENT_OUTPUT_DIR/.correction-prompt.txt" << 'CORRECTION' +NOTE: You wrote output to /workspace/.agent-output/ instead of /workspace/project/. +Those files are gitignored and will NOT be committed automatically. + +The following files have been moved to /workspace/project/ and WILL be committed: +CORRECTION + echo "$CORRECTION_FILES" >> "$AGENT_OUTPUT_DIR/.correction-prompt.txt" + cat >> "$AGENT_OUTPUT_DIR/.correction-prompt.txt" << 'CORRECTION' + +ALWAYS write deliverable output directly to /workspace/project/. +Never use /workspace/.agent-output/ when /workspace/project/ exists. +CORRECTION + echo "Correction prompt written to $AGENT_OUTPUT_DIR/.correction-prompt.txt" + fi +fi + +# Check again after potential moves if [ -z "$(git status --porcelain)" ]; then echo "No changes to commit — skipping push (AR-8)" - # Write metadata with agent_branch_pushed=false python3 -c " import json, os out = '$METADATA_FILE' @@ -143,7 +177,6 @@ set -e if [ "$SCAN_EXIT" -ne 0 ]; then echo "SECRET SCAN BLOCKED COMMIT — credentials detected in staged content" echo "$SCAN_FINDINGS" - # Write metadata indicating scan blocked the commit python3 -c " import json, os out = '$METADATA_FILE' @@ -198,20 +231,65 @@ else fi # Commit +echo "Running: git commit" git commit -F "$COMMIT_MSG_FILE" # Get commit SHA COMMIT_SHA=$(git rev-parse HEAD) +echo "Committed as: $COMMIT_SHA" -# AR-19: Always push — even if tests failed, partial work is better than lost work. -# The task exit code and ci_metadata.json track whether tests passed. +# BUG-20: Output validation — check expected output file exists and is non-empty +# AGENT_EXPECTED_OUTPUT: absolute path to required output file (e.g., /workspace/project/spec/f94-auth.md) +# AGENT_MIN_OUTPUT_BYTES: minimum size in bytes (default 0 = any non-empty) +OUTPUT_VALIDATED=true +OUTPUT_MISSING="" +if [ -n "${AGENT_EXPECTED_OUTPUT:-}" ]; then + echo "Validating expected output: $AGENT_EXPECTED_OUTPUT" + if [ ! -f "$AGENT_EXPECTED_OUTPUT" ]; then + echo "ERROR: Expected output file missing: $AGENT_EXPECTED_OUTPUT" + OUTPUT_VALIDATED=false + OUTPUT_MISSING="$AGENT_EXPECTED_OUTPUT" + else + SIZE=$(stat -c%s "$AGENT_EXPECTED_OUTPUT" 2>/dev/null || stat -f%z "$AGENT_EXPECTED_OUTPUT" 2>/dev/null || echo "0") + MIN_SIZE="${AGENT_MIN_OUTPUT_BYTES:-0}" + if [ "$SIZE" -lt "$MIN_SIZE" ]; then + echo "WARNING: Output file $AGENT_EXPECTED_OUTPUT is ${SIZE} bytes (minimum: ${MIN_SIZE})" + else + echo "Output validated: $AGENT_EXPECTED_OUTPUT (${SIZE} bytes)" + fi + fi +fi + +# AR-19: Push with retry — attempt up to PUSH_RETRIES+1 times (default 2: initial + 1 retry) echo "Pushing branch $BRANCH to $REPO_URL..." -if timeout 120 git push "$REPO_URL" "HEAD:refs/heads/$BRANCH" --force; then - echo "Push succeeded" - PUSHED=true -else - echo "ERROR: Push failed" >&2 - PUSHED=false +PUSHED=false +PUSH_EXIT=0 +for attempt in $(seq 1 $((PUSH_RETRIES + 1))); do + if [ "$attempt" -gt 1 ]; then + echo "Push attempt $attempt — sleeping 5s before retry" + sleep 5 + echo "Retry $attempt: git push $REPO_URL HEAD:refs/heads/$BRANCH --force" + fi + if timeout 120 git push "$REPO_URL" "HEAD:refs/heads/$BRANCH" --force 2>&1; then + echo "Push succeeded (attempt $attempt)" + PUSHED=true + PUSH_EXIT=0 + break + else + PUSH_EXIT=$? + echo "Push attempt $attempt failed with exit code $PUSH_EXIT" + if [ "$attempt" -lt $((PUSH_RETRIES + 1)) ]; then + echo "Will retry..." + fi + fi +done + +# Log committed files for diagnosis +echo "Files in commit:" +git diff-tree --no-commit-id --name-only -r "$COMMIT_SHA" | while read f; do echo " $f"; done + +if [ "$PUSHED" = "false" ]; then + echo "ERROR: Push failed after $((PUSH_RETRIES + 1)) attempt(s) — branch $BRANCH was committed but not pushed" >&2 fi # Write ci_metadata.json @@ -230,14 +308,16 @@ meta['agent_sha'] = '$COMMIT_SHA' meta['agent_repo_url'] = '$REPO_URL' meta['agent_branch_pushed'] = $( [ '$PUSHED' = 'true' ] && echo 'True' || echo 'False' ) meta['diff_kb'] = float('$DIFF_KB') if '$DIFF_KB' else 0.0 +meta['output_validated'] = $( [ '$OUTPUT_VALIDATED' = 'true' ] && echo 'True' || echo 'False' ) +if '$OUTPUT_MISSING': + meta['output_missing'] = '$OUTPUT_MISSING' with open(out, 'w') as f: json.dump(meta, f) print('Wrote ci_metadata.json') " if [ "$PUSHED" = "false" ]; then - echo "ERROR: Push failed — branch $BRANCH was committed but not pushed" >&2 exit 1 fi -echo "=== agent-repo/v1 finalize.sh complete ===" +echo "=== agent-repo/v1 finalize.sh complete ===" \ No newline at end of file diff --git a/harnesses/contexts/agent-repo/v1/harness.yaml b/harnesses/contexts/agent-repo/v1/harness.yaml index afea853..ba7ebb9 100644 --- a/harnesses/contexts/agent-repo/v1/harness.yaml +++ b/harnesses/contexts/agent-repo/v1/harness.yaml @@ -8,6 +8,7 @@ provides: [project-repo] scripts: init: "./init.sh" finalize: "./finalize.sh" + pre_test: "./pre_test.sh" env: AGENT_WORKING_DIR: "/workspace/project" diff --git a/harnesses/contexts/agent-repo/v1/pre_test.sh b/harnesses/contexts/agent-repo/v1/pre_test.sh new file mode 100644 index 0000000..62ffff7 --- /dev/null +++ b/harnesses/contexts/agent-repo/v1/pre_test.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# pre_test.sh — Revert agent modifications to test folders before each test run +# F73 / pre_test spec +set -euo pipefail + +echo "=== agent-repo/v1 pre_test.sh ===" + +WORKING_DIR="${AGENT_WORKING_DIR:-/workspace/project}" +AGENT_OUTPUT_DIR="${AGENT_OUTPUT_DIR:-/workspace/.agent-output}" +PROTECTED_FOLDERS="${PROTECTED_TEST_FOLDERS:-}" + +mkdir -p "$AGENT_OUTPUT_DIR" + +if [ -z "$PROTECTED_FOLDERS" ]; then + echo "No PROTECTED_TEST_FOLDERS set — nothing to revert" + echo '{"reverted": 0}' > "$AGENT_OUTPUT_DIR/.pre-test-result.json" + exit 0 +fi + +total_reverted=0 + +IFS=',' read -ra FOLDERS <<< "$PROTECTED_FOLDERS" +for folder in "${FOLDERS[@]}"; do + folder=$(echo "$folder" | xargs) # trim whitespace + [ -z "$folder" ] && continue + + echo "Reverting: $folder" + + # Revert tracked modifications + git -C "$WORKING_DIR" reset HEAD -- "$folder" 2>/dev/null || true + git -C "$WORKING_DIR" checkout HEAD -- "$folder" 2>/dev/null || true + + # Remove untracked files + git -C "$WORKING_DIR" clean -fd -- "$folder" 2>/dev/null || true + + # Count what was reverted + modified=$(git -C "$WORKING_DIR" diff --name-only HEAD -- "$folder" 2>/dev/null | wc -l) + untracked=$(git -C "$WORKING_DIR" ls-files --others --exclude-standard -- "$folder" 2>/dev/null | wc -l) + count=$((modified + untracked)) + if [ "$count" -gt 0 ]; then + echo " Reverted $count item(s) from $folder" + total_reverted=$((total_reverted + count)) + fi +done + +# Also revert test infrastructure files +for infra in conftest.py pyproject.toml pytest.ini setup.cfg tox.ini; do + if git -C "$WORKING_DIR" diff --name-only HEAD -- "$infra" 2>/dev/null | grep -q .; then + git -C "$WORKING_DIR" checkout HEAD -- "$infra" 2>/dev/null || true + echo " Reverted infrastructure file: $infra" + total_reverted=$((total_reverted + 1)) + fi +done + +echo "Total reverted: $total_reverted" + +# Atomic write via mktemp + mv (required contract) +RESULT_FILE=$(mktemp) +echo "{\"reverted\": $total_reverted}" > "$RESULT_FILE" +mv "$RESULT_FILE" "$AGENT_OUTPUT_DIR/.pre-test-result.json" +chmod 0644 "$AGENT_OUTPUT_DIR/.pre-test-result.json" + +echo "=== pre_test.sh complete ===" +exit 0 \ No newline at end of file diff --git a/workflows/spec-planning.yaml b/workflows/spec-planning.yaml index ec7f1d4..3d1b800 100644 --- a/workflows/spec-planning.yaml +++ b/workflows/spec-planning.yaml @@ -1,854 +1,1064 @@ name: spec-planning version: 4 -description: > - Multi-model spec planning with interview, cross-model reviews, human gates, - and post-synthesis security review with auto-fix. - 17-node DAG: 2 interviews, 1 question consolidation, 2 plans, 6 cross-model - reviews (3 disciplines x 2 models — each reviews the OTHER's plan), - 1 escalation with human decision points, 1 final synthesis by best-scoring model, - 2 post-synthesis security reviews (parallel, cross-model), 1 auto-fix for - non-escalated findings, 1 final fix implementation after human review of escalations. +description: 'Multi-model spec planning with interview, cross-model reviews, human + gates, and post-synthesis security review with auto-fix. 17-node DAG: 2 interviews, + 1 question consolidation, 2 plans, 6 cross-model reviews (3 disciplines x 2 models + — each reviews the OTHER''s plan), 1 escalation with human decision points, 1 final + synthesis by best-scoring model, 2 post-synthesis security reviews (parallel, cross-model), + 1 auto-fix for non-escalated findings, 1 final fix implementation after human review + of escalations. + ' params: required: task_description: type: string - description: "What to spec — the feature or subsystem to design" + description: What to spec — the feature or subsystem to design project_id: type: string - description: "Target project identifier" + description: Target project identifier optional: model_a: type: string default: null - description: "Override model A endpoint (auto-selected from registry if omitted)" + description: Override model A endpoint (auto-selected from registry if omitted) model_b: type: string default: null - description: "Override model B endpoint (auto-selected from registry if omitted)" + description: Override model B endpoint (auto-selected from registry if omitted) best_model: type: string default: null - description: "Model override for final synthesis — set after reading escalation output (the best-scoring model)" + description: Model override for final synthesis — set after reading escalation + output (the best-scoring model) repo: type: string default: null - description: "Git repo URL to clone for project context (optional)" + description: Git repo URL to clone for project context (optional) existing_specs: type: string - default: "" - description: "Paste existing spec content for context (e.g., current WF-1..WF-22)" + default: '' + description: Paste existing spec content for context (e.g., current WF-1..WF-22) scope_notes: type: string - default: "" - description: "Any constraints, prior decisions, or scope boundaries from the human" - + default: '' + description: Any constraints, prior decisions, or scope boundaries from the + human nodes: - # ── Phase 0: Interview ─────────────────────────────────────────────── - # - # Both models independently review the task and generate clarifying - # questions. Each sees the task description, scope notes, existing - # specs, and best practices (via the planning harness). If a repo is - # provided, they can also read the project's CLAUDE.md and specs. - interview_a: - name: "Interview Questions ({{ model_a or 'auto' }})" - prompt: &interview_prompt | - You are a senior software architect preparing to write a detailed specification. - Before you start, you need to ask clarifying questions to avoid costly assumptions. - - ## Task to Spec - {{ task_description }} - - {% if scope_notes %} - ## Scope Notes from Human - {{ scope_notes }} - {% endif %} - - {% if existing_specs %} - ## Existing Specifications (for context) - {{ existing_specs }} - {% endif %} - - ## Best Practices - Read these files from `/opt/harness/context/planning/best-practices/`: - 1. `spec-driven-development.md` — spec structure, requirement numbering, scenarios - 2. `test-driven-development.md` — deriving tests from specs, edge case discovery - 3. `security-architecture.md` — server boundary rule, defense in depth, auth patterns - 4. `llm-code-security.md` — injection flaws, input validation, OWASP for AI code - - {% if repo %} - ## Project Context - The project repo has been cloned. Read `CLAUDE.md` and any existing `spec/` files - to understand the current architecture, conventions, and design decisions. - {% endif %} - - ## Your Task - Generate questions that will improve the quality of the spec you'll write later. - Think about what you'd ask a product owner, tech lead, or domain expert before - committing to a design. - - Focus on: - - **Ambiguous requirements** — what does X mean in this context? - - **Missing scope boundaries** — is Y in or out of scope? - - **Business logic decisions** — should Z behave as A or B? - - **Technical constraints** — performance targets, compatibility, resource limits? - - **Dependencies and integration** — how does this interact with existing subsystems? - - **Priority and phasing** — which parts are essential vs nice-to-have? - - **Security implications** — who are the threat actors, what's the trust boundary? - - **Testing strategy** — what's the expected test infrastructure? - - ## Output Format - Write a numbered list of questions to `/workspace/project/output.md`: - - ``` - ## Clarifying Questions - - 1. **[Question]** - Why it matters: [what design decision hinges on the answer] - Suggested default: [what you'd assume if no answer is given] - - 2. **[Question]** - ... - ``` - - Aim for 8-20 questions. Prioritize questions whose answers would change the most - design decisions. Don't ask about things that are clearly stated in the task - description or scope notes. + name: Interview Questions ({{ model_a or 'auto' }}) + prompt: "You are a senior software architect preparing to write a detailed specification.\n\ + Before you start, you need to ask clarifying questions to avoid costly assumptions.\n\ + \n## Task to Spec\n{{ task_description }}\n\n{% if scope_notes %}\n## Scope\ + \ Notes from Human\n{{ scope_notes }}\n{% endif %}\n\n{% if existing_specs %}\n\ + ## Existing Specifications (for context)\n{{ existing_specs }}\n{% endif %}\n\ + \n## Best Practices\nRead these files from `/opt/harness/context/planning/best-practices/`:\n\ + 1. `spec-driven-development.md` — spec structure, requirement numbering, scenarios\n\ + 2. `test-driven-development.md` — deriving tests from specs, edge case discovery\n\ + 3. `security-architecture.md` — server boundary rule, defense in depth, auth\ + \ patterns\n4. `llm-code-security.md` — injection flaws, input validation, OWASP\ + \ for AI code\n\n{% if repo %}\n## Project Context\nThe project repo has been\ + \ cloned. Read `CLAUDE.md` and any existing `spec/` files\nto understand the\ + \ current architecture, conventions, and design decisions.\n{% endif %}\n\n\ + ## Your Task\nGenerate questions that will improve the quality of the spec you'll\ + \ write later.\nThink about what you'd ask a product owner, tech lead, or domain\ + \ expert before\ncommitting to a design.\n\nFocus on:\n- **Ambiguous requirements**\ + \ — what does X mean in this context?\n- **Missing scope boundaries** — is Y\ + \ in or out of scope?\n- **Business logic decisions** — should Z behave as A\ + \ or B?\n- **Technical constraints** — performance targets, compatibility, resource\ + \ limits?\n- **Dependencies and integration** — how does this interact with\ + \ existing subsystems?\n- **Priority and phasing** — which parts are essential\ + \ vs nice-to-have?\n- **Security implications** — who are the threat actors,\ + \ what's the trust boundary?\n- **Testing strategy** — what's the expected test\ + \ infrastructure?\n\n## Output Format\nWrite a numbered list of questions to\ + \ `/workspace/project/output.md`:\n\n```\n## Clarifying Questions\n\n1. **[Question]**\n\ + \ Why it matters: [what design decision hinges on the answer]\n Suggested\ + \ default: [what you'd assume if no answer is given]\n\n2. **[Question]**\n\ + \ ...\n```\n\nAim for 8-20 questions. Prioritize questions whose answers would\ + \ change the most\ndesign decisions. Don't ask about things that are clearly\ + \ stated in the task\ndescription or scope notes.\n" harness: planning/v1 requirements: - min_scores: { complexity: 7, spec_adherence: 8 } - model_override: "{{ model_a }}" - + min_scores: + complexity: 7 + spec_adherence: 8 + model_override: '{{ model_a }}' + output: + path: /workspace/project/output.md + min_bytes: 500 interview_b: - name: "Interview Questions ({{ model_b or 'auto' }})" - prompt: *interview_prompt + name: Interview Questions ({{ model_b or 'auto' }}) + prompt: "You are a senior software architect preparing to write a detailed specification.\n\ + Before you start, you need to ask clarifying questions to avoid costly assumptions.\n\ + \n## Task to Spec\n{{ task_description }}\n\n{% if scope_notes %}\n## Scope\ + \ Notes from Human\n{{ scope_notes }}\n{% endif %}\n\n{% if existing_specs %}\n\ + ## Existing Specifications (for context)\n{{ existing_specs }}\n{% endif %}\n\ + \n## Best Practices\nRead these files from `/opt/harness/context/planning/best-practices/`:\n\ + 1. `spec-driven-development.md` — spec structure, requirement numbering, scenarios\n\ + 2. `test-driven-development.md` — deriving tests from specs, edge case discovery\n\ + 3. `security-architecture.md` — server boundary rule, defense in depth, auth\ + \ patterns\n4. `llm-code-security.md` — injection flaws, input validation, OWASP\ + \ for AI code\n\n{% if repo %}\n## Project Context\nThe project repo has been\ + \ cloned. Read `CLAUDE.md` and any existing `spec/` files\nto understand the\ + \ current architecture, conventions, and design decisions.\n{% endif %}\n\n\ + ## Your Task\nGenerate questions that will improve the quality of the spec you'll\ + \ write later.\nThink about what you'd ask a product owner, tech lead, or domain\ + \ expert before\ncommitting to a design.\n\nFocus on:\n- **Ambiguous requirements**\ + \ — what does X mean in this context?\n- **Missing scope boundaries** — is Y\ + \ in or out of scope?\n- **Business logic decisions** — should Z behave as A\ + \ or B?\n- **Technical constraints** — performance targets, compatibility, resource\ + \ limits?\n- **Dependencies and integration** — how does this interact with\ + \ existing subsystems?\n- **Priority and phasing** — which parts are essential\ + \ vs nice-to-have?\n- **Security implications** — who are the threat actors,\ + \ what's the trust boundary?\n- **Testing strategy** — what's the expected test\ + \ infrastructure?\n\n## Output Format\nWrite a numbered list of questions to\ + \ `/workspace/project/output.md`:\n\n```\n## Clarifying Questions\n\n1. **[Question]**\n\ + \ Why it matters: [what design decision hinges on the answer]\n Suggested\ + \ default: [what you'd assume if no answer is given]\n\n2. **[Question]**\n\ + \ ...\n```\n\nAim for 8-20 questions. Prioritize questions whose answers would\ + \ change the most\ndesign decisions. Don't ask about things that are clearly\ + \ stated in the task\ndescription or scope notes.\n" harness: planning/v1 requirements: - min_scores: { complexity: 7, spec_adherence: 8 } - model_override: "{{ model_b }}" - - # ── Phase 0.5: Question Consolidation ──────────────────────────────── - # - # A single model deduplicates and organizes questions from both - # interviewers. Questions asked by both models are flagged as - # high-signal. Output goes through a human gate — the human answers - # the questions, and their answers are appended to the artifact. - + min_scores: + complexity: 7 + spec_adherence: 8 + model_override: '{{ model_b }}' + output: + path: /workspace/project/output.md + min_bytes: 500 consolidate_questions: - name: "Consolidate Interview Questions" - depends_on: [interview_a, interview_b] - prompt: | - You are consolidating clarifying questions from two independent reviewers - into a single, organized list for a human to answer. - - ## Questions from Model A - <> - - ## Questions from Model B - <> - - ## Instructions - 1. **Deduplicate** — merge questions that ask the same thing in different words - 2. **Flag consensus** — when both models asked the same question, note "(Asked by both)" - as this is a strong signal the question matters - 3. **Group by theme** — organize into sections (Scope, Architecture, Security, - Testing, Integration, Priority, etc.) - 4. **Preserve context** — keep each question's "why it matters" and "suggested default" - 5. **Order by impact** — within each group, questions whose answers change the most - design decisions come first - - ## Output Format - Write to `/workspace/project/output.md`: - - ``` - ## Questions for Human Review - - ### High Impact (answers change multiple design decisions) - 1. **[Question]** (Asked by: A / B / both) - Why it matters: [explanation] - Suggested default: [what to assume if unanswered] - - ### Medium Impact - ... - - ### Low Impact / Confirmations - ... - ``` - - Do not add your own questions — only consolidate what the two models asked. - Do not answer the questions — that's the human's job. + name: Consolidate Interview Questions + depends_on: + - interview_a + - interview_b + prompt: "You are consolidating clarifying questions from two independent reviewers\n\ + into a single, organized list for a human to answer.\n\n## Questions from Model\ + \ A\n<>\n\n## Questions from Model B\n<>\n\ + \n## Instructions\n1. **Deduplicate** — merge questions that ask the same thing\ + \ in different words\n2. **Flag consensus** — when both models asked the same\ + \ question, note \"(Asked by both)\"\n as this is a strong signal the question\ + \ matters\n3. **Group by theme** — organize into sections (Scope, Architecture,\ + \ Security,\n Testing, Integration, Priority, etc.)\n4. **Preserve context**\ + \ — keep each question's \"why it matters\" and \"suggested default\"\n5. **Order\ + \ by impact** — within each group, questions whose answers change the most\n\ + \ design decisions come first\n\n## Output Format\nWrite to `/workspace/project/output.md`:\n\ + \n```\n## Questions for Human Review\n\n### High Impact (answers change multiple\ + \ design decisions)\n1. **[Question]** (Asked by: A / B / both)\n Why it matters:\ + \ [explanation]\n Suggested default: [what to assume if unanswered]\n\n###\ + \ Medium Impact\n...\n\n### Low Impact / Confirmations\n...\n```\n\nDo not add\ + \ your own questions — only consolidate what the two models asked.\nDo not answer\ + \ the questions — that's the human's job.\n" harness: planning/v1 requirements: - min_scores: { spec_adherence: 7 } - - # ── Phase 1: Independent Planning ────────────────────────────────── - # - # Two models write specs independently. Both get ALL four best-practice - # docs, the interview answers (via the consolidated questions artifact, - # which the human has annotated with answers), and project context. - # Differences reflect genuine design disagreements, not knowledge gaps. - + min_scores: + spec_adherence: 7 + output: + path: /workspace/project/output.md + min_bytes: 1000 plan_a: - name: "Spec Draft A ({{ model_a or 'auto' }})" - depends_on: [consolidate_questions] - prompt: &plan_prompt | - You are a senior software architect writing a detailed specification. + name: Spec Draft A ({{ model_a or 'auto' }}) + depends_on: + - consolidate_questions + prompt: 'You are a senior software architect writing a detailed specification. + ## Task + {{ task_description }} + {% if scope_notes %} + ## Scope Notes from Human + {{ scope_notes }} + {% endif %} + {% if existing_specs %} - ## Existing Specifications (for context — extend, don't duplicate) + + ## Existing Specifications (for context — extend, don''t duplicate) + {{ existing_specs }} + {% endif %} + ## Interview Answers + The following questions were asked during the interview phase. + The human has provided answers — use them to guide your design decisions. + Where a question has no answer, use the suggested default. + <> + ## Methodology + Read and apply these best-practice documents from `/opt/harness/context/planning/best-practices/`: + 1. `spec-driven-development.md` — spec structure, requirement numbering, scenarios + 2. `test-driven-development.md` — deriving tests from specs, edge case discovery - 3. `security-architecture.md` — server boundary rule, defense in depth, auth patterns - 4. `llm-code-security.md` — injection flaws, input validation, OWASP for AI code + + 3. `security-architecture.md` — server boundary rule, defense in depth, auth + patterns + + 4. `llm-code-security.md` — injection flaws, input validation, OWASP for AI + code + {% if repo %} + ## Project Context - The project repo has been cloned. Read `CLAUDE.md` and any existing `spec/` files + + The project repo has been cloned. Read `CLAUDE.md` and any existing `spec/` + files + to understand the current architecture and conventions. + {% endif %} + ## Output Requirements + Write a complete spec with these sections: + 1. **Overview** — 2-3 sentences on what this subsystem does + 2. **Responsibilities** — what it owns vs delegates + 3. **Dependencies** — other specs to read + 4. **Data Model** — types, schemas, with concrete JSON/YAML examples - 5. **Requirements** — numbered (e.g., XX-1, XX-2), each independently testable, each with a "Why:" rationale + + 5. **Requirements** — numbered (e.g., XX-1, XX-2), each independently testable, + each with a "Why:" rationale + 6. **Scenarios** — given/when/then for every requirement - 7. **Security Considerations** — input validation, injection risks, access control, resource limits + + 7. **Security Considerations** — input validation, injection risks, access control, + resource limits + 8. **Test Strategy** — how each requirement maps to tests, edge cases to cover + Be opinionated. Make concrete design decisions with rationale. Call out trade-offs. - Do NOT leave things vague ("handle errors appropriately") — be specific ("return HTTP 413 with error body"). + + Do NOT leave things vague ("handle errors appropriately") — be specific ("return + HTTP 413 with error body"). + Write the complete spec to /workspace/project/output.md + + ' harness: planning/v1 requirements: - min_scores: { complexity: 7, spec_adherence: 8 } - model_override: "{{ model_a }}" - + min_scores: + complexity: 7 + spec_adherence: 8 + model_override: '{{ model_a }}' + output: + path: /workspace/project/output.md + min_bytes: 3000 plan_b: - name: "Spec Draft B ({{ model_b or 'auto' }})" - depends_on: [consolidate_questions] - prompt: *plan_prompt + name: Spec Draft B ({{ model_b or 'auto' }}) + depends_on: + - consolidate_questions + prompt: 'You are a senior software architect writing a detailed specification. + + + ## Task + + {{ task_description }} + + + {% if scope_notes %} + + ## Scope Notes from Human + + {{ scope_notes }} + + {% endif %} + + + {% if existing_specs %} + + ## Existing Specifications (for context — extend, don''t duplicate) + + {{ existing_specs }} + + {% endif %} + + + ## Interview Answers + + The following questions were asked during the interview phase. + + The human has provided answers — use them to guide your design decisions. + + Where a question has no answer, use the suggested default. + + + <> + + + ## Methodology + + Read and apply these best-practice documents from `/opt/harness/context/planning/best-practices/`: + + 1. `spec-driven-development.md` — spec structure, requirement numbering, scenarios + + 2. `test-driven-development.md` — deriving tests from specs, edge case discovery + + 3. `security-architecture.md` — server boundary rule, defense in depth, auth + patterns + + 4. `llm-code-security.md` — injection flaws, input validation, OWASP for AI + code + + + {% if repo %} + + ## Project Context + + The project repo has been cloned. Read `CLAUDE.md` and any existing `spec/` + files + + to understand the current architecture and conventions. + + {% endif %} + + + ## Output Requirements + + Write a complete spec with these sections: + + 1. **Overview** — 2-3 sentences on what this subsystem does + + 2. **Responsibilities** — what it owns vs delegates + + 3. **Dependencies** — other specs to read + + 4. **Data Model** — types, schemas, with concrete JSON/YAML examples + + 5. **Requirements** — numbered (e.g., XX-1, XX-2), each independently testable, + each with a "Why:" rationale + + 6. **Scenarios** — given/when/then for every requirement + + 7. **Security Considerations** — input validation, injection risks, access control, + resource limits + + 8. **Test Strategy** — how each requirement maps to tests, edge cases to cover + + + Be opinionated. Make concrete design decisions with rationale. Call out trade-offs. + + Do NOT leave things vague ("handle errors appropriately") — be specific ("return + HTTP 413 with error body"). + + + Write the complete spec to /workspace/project/output.md + + ' harness: planning/v1 requirements: - min_scores: { complexity: 7, spec_adherence: 8 } - model_override: "{{ model_b }}" - - # ── Phase 2: Cross-Model Reviews ─────────────────────────────────── - # - # 6 review nodes: 3 disciplines x 2 models. Each model reviews ONLY - # the OTHER model's plan. This eliminates self-review bias — a model - # reviewing its own plan tends to confirm its own decisions. - + min_scores: + complexity: 7 + spec_adherence: 8 + model_override: '{{ model_b }}' + output: + path: /workspace/project/output.md + min_bytes: 3000 spec_review_a: - name: "Spec Review by A (of Plan B)" - depends_on: [plan_b] - prompt: | - You are reviewing a specification for adherence to spec-driven development practices. + name: Spec Review by A (of Plan B) + depends_on: + - plan_b + prompt: 'You are reviewing a specification for adherence to spec-driven development + practices. + You did NOT write this plan. Review it critically. + ## Best Practice Reference - Read `/opt/harness/context/planning/best-practices/spec-driven-development.md` thoroughly before reviewing. + + Read `/opt/harness/context/planning/best-practices/spec-driven-development.md` + thoroughly before reviewing. + ## Spec Under Review (written by another model) + <> + ## Review Checklist + Evaluate: - 1. **Structure** — Does it have all required sections (Overview, Responsibilities, Dependencies, Data Model, Requirements, Scenarios)? - 2. **Requirements quality** — Are they numbered, independently testable, unambiguous? Does each have a "Why:" rationale? - 3. **Scenarios** — Does every requirement have at least one given/when/then? Are edge cases covered? + + 1. **Structure** — Does it have all required sections (Overview, Responsibilities, + Dependencies, Data Model, Requirements, Scenarios)? + + 2. **Requirements quality** — Are they numbered, independently testable, unambiguous? + Does each have a "Why:" rationale? + + 3. **Scenarios** — Does every requirement have at least one given/when/then? + Are edge cases covered? + 4. **Cross-references** — Does it reference other specs correctly without duplicating? - 5. **Concrete examples** — Are data models shown with realistic JSON/code, not just abstract schemas? - 6. **Completeness** — Are there gaps? Requirements that should exist but don't? + + 5. **Concrete examples** — Are data models shown with realistic JSON/code, not + just abstract schemas? + + 6. **Completeness** — Are there gaps? Requirements that should exist but don''t? + ## Output Format + List numbered improvement points with severity (CRITICAL/HIGH/MEDIUM/LOW). - Then: "## Questions for Human Review" — decisions needing human input (unclear requirements, business logic, scope). + + Then: "## Questions for Human Review" — decisions needing human input (unclear + requirements, business logic, scope). + Write to /workspace/project/output.md + + ' harness: planning/v1 requirements: - min_scores: { spec_adherence: 9 } - model_override: "{{ model_a }}" - + min_scores: + spec_adherence: 9 + model_override: '{{ model_a }}' + output: + path: /workspace/project/output.md + min_bytes: 1500 spec_review_b: - name: "Spec Review by B (of Plan A)" - depends_on: [plan_a] - prompt: | - You are reviewing a specification for adherence to spec-driven development practices. + name: Spec Review by B (of Plan A) + depends_on: + - plan_a + prompt: 'You are reviewing a specification for adherence to spec-driven development + practices. + You did NOT write this plan. Review it critically. + ## Best Practice Reference - Read `/opt/harness/context/planning/best-practices/spec-driven-development.md` thoroughly before reviewing. + + Read `/opt/harness/context/planning/best-practices/spec-driven-development.md` + thoroughly before reviewing. + ## Spec Under Review (written by another model) + <> + ## Review Checklist + Evaluate: - 1. **Structure** — Does it have all required sections (Overview, Responsibilities, Dependencies, Data Model, Requirements, Scenarios)? - 2. **Requirements quality** — Are they numbered, independently testable, unambiguous? Does each have a "Why:" rationale? - 3. **Scenarios** — Does every requirement have at least one given/when/then? Are edge cases covered? + + 1. **Structure** — Does it have all required sections (Overview, Responsibilities, + Dependencies, Data Model, Requirements, Scenarios)? + + 2. **Requirements quality** — Are they numbered, independently testable, unambiguous? + Does each have a "Why:" rationale? + + 3. **Scenarios** — Does every requirement have at least one given/when/then? + Are edge cases covered? + 4. **Cross-references** — Does it reference other specs correctly without duplicating? - 5. **Concrete examples** — Are data models shown with realistic JSON/code, not just abstract schemas? - 6. **Completeness** — Are there gaps? Requirements that should exist but don't? + + 5. **Concrete examples** — Are data models shown with realistic JSON/code, not + just abstract schemas? + + 6. **Completeness** — Are there gaps? Requirements that should exist but don''t? + ## Output Format + List numbered improvement points with severity (CRITICAL/HIGH/MEDIUM/LOW). - Then: "## Questions for Human Review" — decisions needing human input (unclear requirements, business logic, scope). + + Then: "## Questions for Human Review" — decisions needing human input (unclear + requirements, business logic, scope). + Write to /workspace/project/output.md + + ' harness: planning/v1 requirements: - min_scores: { spec_adherence: 9 } - model_override: "{{ model_b }}" - + min_scores: + spec_adherence: 9 + model_override: '{{ model_b }}' + output: + path: /workspace/project/output.md + min_bytes: 1500 security_review_a: - name: "Security Review by A (of Plan B)" - depends_on: [plan_b] - prompt: | - You are performing a security review of a specification. + name: Security Review by A (of Plan B) + depends_on: + - plan_b + prompt: 'You are performing a security review of a specification. + You did NOT write this plan. Review it critically. + ## Best Practice References + Read these thoroughly before reviewing: - - `/opt/harness/context/planning/best-practices/security-architecture.md` — server boundary rule, defense in depth, proxy patterns - - `/opt/harness/context/planning/best-practices/llm-code-security.md` — injection flaws, OWASP for AI code, hallucinated packages + + - `/opt/harness/context/planning/best-practices/security-architecture.md` — + server boundary rule, defense in depth, proxy patterns + + - `/opt/harness/context/planning/best-practices/llm-code-security.md` — injection + flaws, OWASP for AI code, hallucinated packages + ## Spec Under Review (written by another model) + <> + ## Review Focus + Evaluate: + 1. **Injection risks** — SQL, command, template, prompt, SSRF, path traversal - 2. **Input validation** — are all inputs validated at system boundaries? Size limits? + + 2. **Input validation** — are all inputs validated at system boundaries? Size + limits? + 3. **Authentication/Authorization** — who can access what? Multi-tenancy isolation? - 4. **Secret handling** — are credentials ever exposed? Server boundary rule compliance? + + 4. **Secret handling** — are credentials ever exposed? Server boundary rule + compliance? + 5. **Resource exhaustion** — unbounded loops, unlimited sizes, missing timeouts? + 6. **Data integrity** — race conditions, TOCTOU, atomic operations? - 7. **LLM-specific risks** — prompt injection via user input, hallucinated dependencies, over-permissive defaults + + 7. **LLM-specific risks** — prompt injection via user input, hallucinated dependencies, + over-permissive defaults + ## Output Format - For each finding: Severity (CRITICAL/HIGH/MEDIUM/LOW/INFO), attack vector, affected requirement ID, concrete fix. + + For each finding: Severity (CRITICAL/HIGH/MEDIUM/LOW/INFO), attack vector, affected + requirement ID, concrete fix. + Then: "## Questions for Human Review" — security decisions needing human judgement. + Write to /workspace/project/output.md + + ' harness: planning/v1 requirements: - min_scores: { spec_adherence: 8 } - model_override: "{{ model_a }}" - + min_scores: + spec_adherence: 8 + model_override: '{{ model_a }}' + output: + path: /workspace/project/output.md + min_bytes: 1500 security_review_b: - name: "Security Review by B (of Plan A)" - depends_on: [plan_a] - prompt: | - You are performing a security review of a specification. + name: Security Review by B (of Plan A) + depends_on: + - plan_a + prompt: 'You are performing a security review of a specification. + You did NOT write this plan. Review it critically. + ## Best Practice References + Read these thoroughly before reviewing: - - `/opt/harness/context/planning/best-practices/security-architecture.md` — server boundary rule, defense in depth, proxy patterns - - `/opt/harness/context/planning/best-practices/llm-code-security.md` — injection flaws, OWASP for AI code, hallucinated packages + + - `/opt/harness/context/planning/best-practices/security-architecture.md` — + server boundary rule, defense in depth, proxy patterns + + - `/opt/harness/context/planning/best-practices/llm-code-security.md` — injection + flaws, OWASP for AI code, hallucinated packages + ## Spec Under Review (written by another model) + <> + ## Review Focus + Evaluate: + 1. **Injection risks** — SQL, command, template, prompt, SSRF, path traversal - 2. **Input validation** — are all inputs validated at system boundaries? Size limits? + + 2. **Input validation** — are all inputs validated at system boundaries? Size + limits? + 3. **Authentication/Authorization** — who can access what? Multi-tenancy isolation? - 4. **Secret handling** — are credentials ever exposed? Server boundary rule compliance? + + 4. **Secret handling** — are credentials ever exposed? Server boundary rule + compliance? + 5. **Resource exhaustion** — unbounded loops, unlimited sizes, missing timeouts? + 6. **Data integrity** — race conditions, TOCTOU, atomic operations? - 7. **LLM-specific risks** — prompt injection via user input, hallucinated dependencies, over-permissive defaults + + 7. **LLM-specific risks** — prompt injection via user input, hallucinated dependencies, + over-permissive defaults + ## Output Format - For each finding: Severity (CRITICAL/HIGH/MEDIUM/LOW/INFO), attack vector, affected requirement ID, concrete fix. + + For each finding: Severity (CRITICAL/HIGH/MEDIUM/LOW/INFO), attack vector, affected + requirement ID, concrete fix. + Then: "## Questions for Human Review" — security decisions needing human judgement. + Write to /workspace/project/output.md + + ' harness: planning/v1 requirements: - min_scores: { spec_adherence: 8 } - model_override: "{{ model_b }}" - + min_scores: + spec_adherence: 8 + model_override: '{{ model_b }}' + output: + path: /workspace/project/output.md + min_bytes: 1500 tdd_review_a: - name: "TDD Review by A (of Plan B)" - depends_on: [plan_b] - prompt: | - You are reviewing a specification for testability and test strategy quality. - You did NOT write this plan. Review it critically. - - ## Best Practice Reference - Read `/opt/harness/context/planning/best-practices/test-driven-development.md` thoroughly before reviewing. - - ## Spec Under Review (written by another model) - <> - - ## Review Focus - Evaluate: - 1. **Requirement testability** — Can each requirement be tested without human judgement? - Flag requirements that say "appropriate", "reasonable", "as needed". - 2. **Test coverage plan** — Does the test strategy cover all requirements? Any gaps? - 3. **Edge cases** — Are boundary conditions, error paths, and concurrency scenarios covered? - 4. **Test naming** — Do proposed test names include requirement IDs (e.g., test_wf23_artifact_upload)? - 5. **Parameterised tests** — Where specs enumerate valid values, are parameterised tests suggested? - 6. **Integration test boundary** — Is the line between unit and integration tests clear? - 7. **Property-based testing** — Are there invariants that would benefit from hypothesis/property testing? - 8. **Mock boundaries** — What should be mocked vs tested with real dependencies? - - ## Output Format - List numbered improvement points with severity. - Then: "## Questions for Human Review" — test scope decisions needing human input. - - Write to /workspace/project/output.md + name: TDD Review by A (of Plan B) + depends_on: + - plan_b + prompt: "You are reviewing a specification for testability and test strategy quality.\n\ + You did NOT write this plan. Review it critically.\n\n## Best Practice Reference\n\ + Read `/opt/harness/context/planning/best-practices/test-driven-development.md`\ + \ thoroughly before reviewing.\n\n## Spec Under Review (written by another model)\n\ + <>\n\n## Review Focus\nEvaluate:\n1. **Requirement testability**\ + \ — Can each requirement be tested without human judgement?\n Flag requirements\ + \ that say \"appropriate\", \"reasonable\", \"as needed\".\n2. **Test coverage\ + \ plan** — Does the test strategy cover all requirements? Any gaps?\n3. **Edge\ + \ cases** — Are boundary conditions, error paths, and concurrency scenarios\ + \ covered?\n4. **Test naming** — Do proposed test names include requirement\ + \ IDs (e.g., test_wf23_artifact_upload)?\n5. **Parameterised tests** — Where\ + \ specs enumerate valid values, are parameterised tests suggested?\n6. **Integration\ + \ test boundary** — Is the line between unit and integration tests clear?\n\ + 7. **Property-based testing** — Are there invariants that would benefit from\ + \ hypothesis/property testing?\n8. **Mock boundaries** — What should be mocked\ + \ vs tested with real dependencies?\n\n## Output Format\nList numbered improvement\ + \ points with severity.\nThen: \"## Questions for Human Review\" — test scope\ + \ decisions needing human input.\n\nWrite to /workspace/project/output.md\n" harness: planning/v1 requirements: - min_scores: { spec_adherence: 8 } - model_override: "{{ model_a }}" - + min_scores: + spec_adherence: 8 + model_override: '{{ model_a }}' + output: + path: /workspace/project/output.md + min_bytes: 1500 tdd_review_b: - name: "TDD Review by B (of Plan A)" - depends_on: [plan_a] - prompt: | - You are reviewing a specification for testability and test strategy quality. - You did NOT write this plan. Review it critically. - - ## Best Practice Reference - Read `/opt/harness/context/planning/best-practices/test-driven-development.md` thoroughly before reviewing. - - ## Spec Under Review (written by another model) - <> - - ## Review Focus - Evaluate: - 1. **Requirement testability** — Can each requirement be tested without human judgement? - Flag requirements that say "appropriate", "reasonable", "as needed". - 2. **Test coverage plan** — Does the test strategy cover all requirements? Any gaps? - 3. **Edge cases** — Are boundary conditions, error paths, and concurrency scenarios covered? - 4. **Test naming** — Do proposed test names include requirement IDs (e.g., test_wf23_artifact_upload)? - 5. **Parameterised tests** — Where specs enumerate valid values, are parameterised tests suggested? - 6. **Integration test boundary** — Is the line between unit and integration tests clear? - 7. **Property-based testing** — Are there invariants that would benefit from hypothesis/property testing? - 8. **Mock boundaries** — What should be mocked vs tested with real dependencies? - - ## Output Format - List numbered improvement points with severity. - Then: "## Questions for Human Review" — test scope decisions needing human input. - - Write to /workspace/project/output.md + name: TDD Review by B (of Plan A) + depends_on: + - plan_a + prompt: "You are reviewing a specification for testability and test strategy quality.\n\ + You did NOT write this plan. Review it critically.\n\n## Best Practice Reference\n\ + Read `/opt/harness/context/planning/best-practices/test-driven-development.md`\ + \ thoroughly before reviewing.\n\n## Spec Under Review (written by another model)\n\ + <>\n\n## Review Focus\nEvaluate:\n1. **Requirement testability**\ + \ — Can each requirement be tested without human judgement?\n Flag requirements\ + \ that say \"appropriate\", \"reasonable\", \"as needed\".\n2. **Test coverage\ + \ plan** — Does the test strategy cover all requirements? Any gaps?\n3. **Edge\ + \ cases** — Are boundary conditions, error paths, and concurrency scenarios\ + \ covered?\n4. **Test naming** — Do proposed test names include requirement\ + \ IDs (e.g., test_wf23_artifact_upload)?\n5. **Parameterised tests** — Where\ + \ specs enumerate valid values, are parameterised tests suggested?\n6. **Integration\ + \ test boundary** — Is the line between unit and integration tests clear?\n\ + 7. **Property-based testing** — Are there invariants that would benefit from\ + \ hypothesis/property testing?\n8. **Mock boundaries** — What should be mocked\ + \ vs tested with real dependencies?\n\n## Output Format\nList numbered improvement\ + \ points with severity.\nThen: \"## Questions for Human Review\" — test scope\ + \ decisions needing human input.\n\nWrite to /workspace/project/output.md\n" harness: planning/v1 requirements: - min_scores: { spec_adherence: 8 } - model_override: "{{ model_b }}" - - # ── Phase 3: Escalation ──────────────────────────────────────────── - # - # Reads both plans AND all six cross-reviews. Since each model only - # reviewed the OTHER's plan, the escalation must correlate findings: - # "Model A found X in Plan B; Model B found Y in Plan A — is this - # the same underlying issue?" Also recommends which model should - # write the final synthesis based on review quality. - + min_scores: + spec_adherence: 8 + model_override: '{{ model_b }}' + output: + path: /workspace/project/output.md + min_bytes: 1500 escalate: - name: "Decision Briefing for Human" - depends_on: [spec_review_a, spec_review_b, security_review_a, security_review_b, tdd_review_a, tdd_review_b] - prompt: | - You are preparing a decision briefing for a human reviewer. + name: Decision Briefing for Human + depends_on: + - spec_review_a + - spec_review_b + - security_review_a + - security_review_b + - tdd_review_a + - tdd_review_b + prompt: 'You are preparing a decision briefing for a human reviewer. + You have two spec drafts and SIX cross-model reviews (each model reviewed - only the OTHER model's plan — no self-review). Your job: surface what needs + + only the OTHER model''s plan — no self-review). Your job: surface what needs + human decisions vs what the reviewers agree on. + ## Plan A (written by Model A, reviewed by Model B) + <> + ## Plan B (written by Model B, reviewed by Model A) + <> + ## Reviews of Plan B (by Model A) + ### Spec Review + <> + ### Security Review + <> + ### TDD Review + <> + ## Reviews of Plan A (by Model B) + ### Spec Review + <> + ### Security Review + <> + ### TDD Review + <> + ## Output Format + ### 1. Design Disagreements + For each disagreement between Plan A and Plan B: + - **Topic:** (e.g., "Artifact storage: dedicated table vs metadata inline") + - **Plan A approach:** (summary) + - **Plan B approach:** (summary) - - **What A's reviewer of B said:** (summary) - - **What B's reviewer of A said:** (summary) + + - **What A''s reviewer of B said:** (summary) + + - **What B''s reviewer of A said:** (summary) + - **Recommendation:** (your assessment, with rationale) - - **Decision needed:** YES / NO (YES if reviewers disagree or reasonable people could disagree) + + - **Decision needed:** YES / NO (YES if reviewers disagree or reasonable people + could disagree) + ### 2. Correlated Findings - Where Model A's review of Plan B and Model B's review of Plan A found + + Where Model A''s review of Plan B and Model B''s review of Plan A found + related issues (same underlying problem manifesting in both plans): + - **Issue:** (description) - - **In Plan A:** (what B's reviewer found) - - **In Plan B:** (what A's reviewer found) + + - **In Plan A:** (what B''s reviewer found) + + - **In Plan B:** (what A''s reviewer found) + - **Fix:** (recommended resolution) + ### 3. Open Questions + Consolidate all "Questions for Human Review" from all six reviews. + Deduplicate. For each: + - **Question:** (clear, actionable) + - **Context:** (why this matters) + - **Options:** (concrete choices) + - **Default if no answer:** (what the synthesizer would pick) + ### 4. Security Decisions + All CRITICAL and HIGH findings from both security reviews. + Note whether the finding affects Plan A, Plan B, or both. + ### 5. Consensus Items + Areas where both plans agree AND reviewers found no issues. - These don't need human review. + + These don''t need human review. + ### 6. Model Scoring Recommendation + Based on review findings, recommend which model should write the final synthesis: + - **Plan A review score:** (fewer/less severe findings = better) + - **Plan B review score:** (fewer/less severe findings = better) + - **Recommendation:** Model A or Model B for final synthesis, with rationale + Be concise. Lead with decisions, not context. + Write to /workspace/project/output.md + + ' harness: planning/v1 requirements: - min_scores: { complexity: 9, spec_adherence: 9 } - - # ── Phase 4: Final Synthesis ─────────────────────────────────────── - # - # In manual-workflow mode, the human reviews the escalation output, - # answers open questions, resolves conflicts, and sets best_model - # before this node runs. The best-scoring model writes the final spec. - + min_scores: + complexity: 9 + spec_adherence: 9 + output: + path: /workspace/project/output.md + min_bytes: 2000 synthesize: - name: "Final Spec Synthesis" - depends_on: [escalate] - prompt: | - You are producing the FINAL specification by combining two competing - drafts, six cross-model reviews, and an escalation briefing with human decisions. - - ## Plan A - <> - - ## Plan B - <> - - ## Reviews of Plan B (by Model A) - <> - <> - <> - - ## Reviews of Plan A (by Model B) - <> - <> - <> - - ## Escalation Briefing (with human decisions) - <> - - ## Best Practice References - Read ALL of these from `/opt/harness/context/planning/best-practices/`: - - `spec-driven-development.md` - - `test-driven-development.md` - - `security-architecture.md` - - `llm-code-security.md` - - ## Instructions - - 1. **Start from the stronger plan** — the one with fewer and less severe review findings. - Don't average; pick the better foundation and incorporate the best from the other. - - 2. **Resolve all disagreements** using the escalation briefing. - Where the briefing says "Decision needed: YES" and human decisions are present, - follow the human's choice. Where no human response is present, - use the briefing's "Default if no answer" and mark with - ``. - - 3. **Address correlated findings** — issues found in both plans indicate a - fundamental problem that needs a different approach, not just a patch. - - 4. **Address all CRITICAL and HIGH security findings** as concrete requirement changes. - - 5. **Every requirement must have:** unique ID, "Why:" rationale, given/when/then scenario, test mapping. - - 6. **Include a Security Requirements section** and a **Test Strategy section**. - - 7. **Do NOT include** review commentary, improvement points, or process notes. - - Write the complete final spec to /workspace/project/output.md + name: Final Spec Synthesis + depends_on: + - escalate + prompt: "You are producing the FINAL specification by combining two competing\n\ + drafts, six cross-model reviews, and an escalation briefing with human decisions.\n\ + \n## Plan A\n<>\n\n## Plan B\n<>\n\ + \n## Reviews of Plan B (by Model A)\n<>\n<>\n\ + <>\n\n## Reviews of Plan A (by Model B)\n<>\n\ + <>\n<>\n\n\ + ## Escalation Briefing (with human decisions)\n<>\n\ + \n## Best Practice References\nRead ALL of these from `/opt/harness/context/planning/best-practices/`:\n\ + - `spec-driven-development.md`\n- `test-driven-development.md`\n- `security-architecture.md`\n\ + - `llm-code-security.md`\n\n## Instructions\n\n1. **Start from the stronger\ + \ plan** — the one with fewer and less severe review findings.\n Don't average;\ + \ pick the better foundation and incorporate the best from the other.\n\n2.\ + \ **Resolve all disagreements** using the escalation briefing.\n Where the\ + \ briefing says \"Decision needed: YES\" and human decisions are present,\n\ + \ follow the human's choice. Where no human response is present,\n use the\ + \ briefing's \"Default if no answer\" and mark with\n ``.\n\n3. **Address correlated findings** — issues found\ + \ in both plans indicate a\n fundamental problem that needs a different approach,\ + \ not just a patch.\n\n4. **Address all CRITICAL and HIGH security findings**\ + \ as concrete requirement changes.\n\n5. **Every requirement must have:** unique\ + \ ID, \"Why:\" rationale, given/when/then scenario, test mapping.\n\n6. **Include\ + \ a Security Requirements section** and a **Test Strategy section**.\n\n7. **Do\ + \ NOT include** review commentary, improvement points, or process notes.\n\n\ + Write the complete final spec to /workspace/project/output.md\n" harness: planning/v1 requirements: - min_scores: { complexity: 9, spec_adherence: 9, creativity: 7 } - model_override: "{{ best_model }}" - - # ── Phase 4.5: Post-Synthesis Security Reviews ───────────────────── - # - # Two models independently review the FINAL synthesized spec for - # security issues. This catches problems introduced during synthesis - # (merging two plans can create inconsistencies, gaps, or new attack - # surfaces that weren't in either original plan). Each model reviews - # the same spec — not cross-review, because there's only one spec now. - + min_scores: + complexity: 9 + spec_adherence: 9 + creativity: 7 + model_override: '{{ best_model }}' + output: + path: /workspace/project/output.md + min_bytes: 3000 post_security_a: - name: "Post-Synthesis Security Review ({{ model_a or 'auto' }})" - depends_on: [synthesize] - prompt: &post_security_prompt | - You are performing a security review of a FINAL synthesized specification. - This spec was produced by merging two competing drafts and applying - review feedback. Your job: find security issues that survived synthesis - or were introduced by the merge process. - - ## Synthesized Spec - <> - - ## Best Practice References - Read these thoroughly before reviewing: - - `/opt/harness/context/planning/best-practices/security-architecture.md` - - `/opt/harness/context/planning/best-practices/llm-code-security.md` - - `/opt/harness/context/planning/best-practices/api-design.md` (if it exists) - - {% if repo %} - ## Project Context - The project repo has been cloned. Read `CLAUDE.md` and any existing `spec/` files - for architectural context (existing auth patterns, data flows, trust boundaries). - {% endif %} - - ## Review Focus - 1. **Injection risks** — SQL, command, template, prompt, SSRF, path traversal - 2. **Input validation** — all inputs validated at system boundaries? Size limits? - 3. **Authentication/Authorization** — who can access what? Identity spoofing? - 4. **Secret handling** — credentials exposed? Server boundary rule? - 5. **Resource exhaustion** — unbounded loops, unlimited sizes, missing timeouts? - 6. **Data integrity** — race conditions, TOCTOU, atomic operations? - 7. **LLM-specific risks** — prompt injection, hallucinated deps, over-permissive defaults - 8. **Synthesis artifacts** — inconsistencies between merged sections, conflicting - requirements, gaps where one plan's approach was dropped but the replacement - was incomplete - - ## Output Format - Structure your output into two clear sections: - - ### Fixes (implement directly — no human decision needed) - For each finding that has an unambiguous fix: - - **ID:** F-NN - - **Severity:** CRITICAL / HIGH / MEDIUM / LOW / INFO - - **Requirement:** affected requirement ID(s) - - **Issue:** what's wrong - - **Current text:** quote the problematic spec text - - **Fixed text:** exact replacement text - - **Why:** rationale for the fix - - ### Escalations (need human decision) - For each finding where reasonable people could disagree on the fix: - - **ID:** E-NN - - **Severity:** CRITICAL / HIGH / MEDIUM / LOW - - **Requirement:** affected requirement ID(s) - - **Issue:** what's wrong - - **Options:** concrete choices (A, B, C) with trade-offs - - **Default recommendation:** what you'd pick and why - - Be specific. Quote exact spec text. Provide exact replacement text for fixes. - Do NOT suggest vague improvements ("consider adding validation") — specify - exactly what validation, on what field, with what error code. - - Write to /workspace/project/output.md + name: Post-Synthesis Security Review ({{ model_a or 'auto' }}) + depends_on: + - synthesize + prompt: "You are performing a security review of a FINAL synthesized specification.\n\ + This spec was produced by merging two competing drafts and applying\nreview\ + \ feedback. Your job: find security issues that survived synthesis\nor were\ + \ introduced by the merge process.\n\n## Synthesized Spec\n<>\n\ + \n## Best Practice References\nRead these thoroughly before reviewing:\n- `/opt/harness/context/planning/best-practices/security-architecture.md`\n\ + - `/opt/harness/context/planning/best-practices/llm-code-security.md`\n- `/opt/harness/context/planning/best-practices/api-design.md`\ + \ (if it exists)\n\n{% if repo %}\n## Project Context\nThe project repo has\ + \ been cloned. Read `CLAUDE.md` and any existing `spec/` files\nfor architectural\ + \ context (existing auth patterns, data flows, trust boundaries).\n{% endif\ + \ %}\n\n## Review Focus\n1. **Injection risks** — SQL, command, template, prompt,\ + \ SSRF, path traversal\n2. **Input validation** — all inputs validated at system\ + \ boundaries? Size limits?\n3. **Authentication/Authorization** — who can access\ + \ what? Identity spoofing?\n4. **Secret handling** — credentials exposed? Server\ + \ boundary rule?\n5. **Resource exhaustion** — unbounded loops, unlimited sizes,\ + \ missing timeouts?\n6. **Data integrity** — race conditions, TOCTOU, atomic\ + \ operations?\n7. **LLM-specific risks** — prompt injection, hallucinated deps,\ + \ over-permissive defaults\n8. **Synthesis artifacts** — inconsistencies between\ + \ merged sections, conflicting\n requirements, gaps where one plan's approach\ + \ was dropped but the replacement\n was incomplete\n\n## Output Format\nStructure\ + \ your output into two clear sections:\n\n### Fixes (implement directly — no\ + \ human decision needed)\nFor each finding that has an unambiguous fix:\n- **ID:**\ + \ F-NN\n- **Severity:** CRITICAL / HIGH / MEDIUM / LOW / INFO\n- **Requirement:**\ + \ affected requirement ID(s)\n- **Issue:** what's wrong\n- **Current text:**\ + \ quote the problematic spec text\n- **Fixed text:** exact replacement text\n\ + - **Why:** rationale for the fix\n\n### Escalations (need human decision)\n\ + For each finding where reasonable people could disagree on the fix:\n- **ID:**\ + \ E-NN\n- **Severity:** CRITICAL / HIGH / MEDIUM / LOW\n- **Requirement:** affected\ + \ requirement ID(s)\n- **Issue:** what's wrong\n- **Options:** concrete choices\ + \ (A, B, C) with trade-offs\n- **Default recommendation:** what you'd pick and\ + \ why\n\nBe specific. Quote exact spec text. Provide exact replacement text\ + \ for fixes.\nDo NOT suggest vague improvements (\"consider adding validation\"\ + ) — specify\nexactly what validation, on what field, with what error code.\n\ + \nWrite to /workspace/project/output.md\n" harness: planning/v1 requirements: - min_scores: { spec_adherence: 8 } - model_override: "{{ model_a }}" - + min_scores: + spec_adherence: 8 + model_override: '{{ model_a }}' + output: + path: /workspace/project/output.md + min_bytes: 1500 post_security_b: - name: "Post-Synthesis Security Review ({{ model_b or 'auto' }})" - depends_on: [synthesize] - prompt: *post_security_prompt + name: Post-Synthesis Security Review ({{ model_b or 'auto' }}) + depends_on: + - synthesize + prompt: "You are performing a security review of a FINAL synthesized specification.\n\ + This spec was produced by merging two competing drafts and applying\nreview\ + \ feedback. Your job: find security issues that survived synthesis\nor were\ + \ introduced by the merge process.\n\n## Synthesized Spec\n<>\n\ + \n## Best Practice References\nRead these thoroughly before reviewing:\n- `/opt/harness/context/planning/best-practices/security-architecture.md`\n\ + - `/opt/harness/context/planning/best-practices/llm-code-security.md`\n- `/opt/harness/context/planning/best-practices/api-design.md`\ + \ (if it exists)\n\n{% if repo %}\n## Project Context\nThe project repo has\ + \ been cloned. Read `CLAUDE.md` and any existing `spec/` files\nfor architectural\ + \ context (existing auth patterns, data flows, trust boundaries).\n{% endif\ + \ %}\n\n## Review Focus\n1. **Injection risks** — SQL, command, template, prompt,\ + \ SSRF, path traversal\n2. **Input validation** — all inputs validated at system\ + \ boundaries? Size limits?\n3. **Authentication/Authorization** — who can access\ + \ what? Identity spoofing?\n4. **Secret handling** — credentials exposed? Server\ + \ boundary rule?\n5. **Resource exhaustion** — unbounded loops, unlimited sizes,\ + \ missing timeouts?\n6. **Data integrity** — race conditions, TOCTOU, atomic\ + \ operations?\n7. **LLM-specific risks** — prompt injection, hallucinated deps,\ + \ over-permissive defaults\n8. **Synthesis artifacts** — inconsistencies between\ + \ merged sections, conflicting\n requirements, gaps where one plan's approach\ + \ was dropped but the replacement\n was incomplete\n\n## Output Format\nStructure\ + \ your output into two clear sections:\n\n### Fixes (implement directly — no\ + \ human decision needed)\nFor each finding that has an unambiguous fix:\n- **ID:**\ + \ F-NN\n- **Severity:** CRITICAL / HIGH / MEDIUM / LOW / INFO\n- **Requirement:**\ + \ affected requirement ID(s)\n- **Issue:** what's wrong\n- **Current text:**\ + \ quote the problematic spec text\n- **Fixed text:** exact replacement text\n\ + - **Why:** rationale for the fix\n\n### Escalations (need human decision)\n\ + For each finding where reasonable people could disagree on the fix:\n- **ID:**\ + \ E-NN\n- **Severity:** CRITICAL / HIGH / MEDIUM / LOW\n- **Requirement:** affected\ + \ requirement ID(s)\n- **Issue:** what's wrong\n- **Options:** concrete choices\ + \ (A, B, C) with trade-offs\n- **Default recommendation:** what you'd pick and\ + \ why\n\nBe specific. Quote exact spec text. Provide exact replacement text\ + \ for fixes.\nDo NOT suggest vague improvements (\"consider adding validation\"\ + ) — specify\nexactly what validation, on what field, with what error code.\n\ + \nWrite to /workspace/project/output.md\n" harness: planning/v1 requirements: - min_scores: { spec_adherence: 8 } - model_override: "{{ model_b }}" - - # ── Phase 4.6: Auto-Fix (non-escalated findings) ────────────────── - # - # A single agent reads both security reviews, deduplicates findings, - # applies all fixes that don't need human decisions directly to the - # spec text, and collects escalations into a briefing for the human. - # Output: the updated spec + an escalation summary. - + min_scores: + spec_adherence: 8 + model_override: '{{ model_b }}' + output: + path: /workspace/project/output.md + min_bytes: 1500 auto_fix: - name: "Apply Security Fixes" - depends_on: [post_security_a, post_security_b] - prompt: | - You are implementing security fixes on a specification. - Two independent security reviews have been performed on the synthesized spec. - Your job: apply all non-controversial fixes and prepare escalations for human review. - - ## Synthesized Spec (the document to modify) - <> - - ## Security Review A - <> - - ## Security Review B - <> - - ## Instructions - - ### Step 1: Triage and Deduplicate - Compare both reviews. Many findings will overlap (same issue found by both). - Create a single merged list with: - - Deduplicated findings (note when both reviewers found the same issue) - - Severity from the stricter reviewer (if A says HIGH and B says MEDIUM, use HIGH) - - ### Step 2: Categorize - Split findings into: - - **Fixes** — clear, unambiguous improvements. Apply these directly. - - **Escalations** — findings where the fix involves a design trade-off, - changes the external API, or where the two reviewers disagree on the approach. - - ### Step 3: Apply Fixes - For each fix, modify the spec text directly. Track what you changed: - - Requirement ID - - What changed (old text → new text, summarized) - - Which review(s) identified the issue - - ### Step 4: Write Escalation Summary - For each escalation, include: - - Finding description - - Which reviewer(s) raised it - - Options with trade-offs - - Default recommendation - - ## Output - Write TWO files: - - **`/workspace/project/output.md`** — The complete updated spec with all - non-escalated fixes applied. This should be the full spec text, ready to save - as the final spec file. Include a comment at the top: - `` - - **`/workspace/project/escalations.md`** — Escalation summary for human - review. Include: - - Total findings: N (X fixes applied, Y escalations) - - Deduplication stats (how many found by both reviewers) - - Each escalation with options and default recommendation - - "Accepted risks" section for INFO-level findings that don't need action + name: Apply Security Fixes + depends_on: + - post_security_a + - post_security_b + prompt: "You are implementing security fixes on a specification.\nTwo independent\ + \ security reviews have been performed on the synthesized spec.\nYour job: apply\ + \ all non-controversial fixes and prepare escalations for human review.\n\n\ + ## Synthesized Spec (the document to modify)\n<>\n\ + \n## Security Review A\n<>\n\n## Security Review\ + \ B\n<>\n\n## Instructions\n\n### Step 1: Triage\ + \ and Deduplicate\nCompare both reviews. Many findings will overlap (same issue\ + \ found by both).\nCreate a single merged list with:\n- Deduplicated findings\ + \ (note when both reviewers found the same issue)\n- Severity from the stricter\ + \ reviewer (if A says HIGH and B says MEDIUM, use HIGH)\n\n### Step 2: Categorize\n\ + Split findings into:\n- **Fixes** — clear, unambiguous improvements. Apply these\ + \ directly.\n- **Escalations** — findings where the fix involves a design trade-off,\n\ + \ changes the external API, or where the two reviewers disagree on the approach.\n\ + \n### Step 3: Apply Fixes\nFor each fix, modify the spec text directly. Track\ + \ what you changed:\n- Requirement ID\n- What changed (old text → new text,\ + \ summarized)\n- Which review(s) identified the issue\n\n### Step 4: Write Escalation\ + \ Summary\nFor each escalation, include:\n- Finding description\n- Which reviewer(s)\ + \ raised it\n- Options with trade-offs\n- Default recommendation\n\n## Output\n\ + Write TWO files:\n\n**`/workspace/project/output.md`** — The complete updated\ + \ spec with all\nnon-escalated fixes applied. This should be the full spec text,\ + \ ready to save\nas the final spec file. Include a comment at the top:\n``\n\n**`/workspace/project/escalations.md`** — Escalation\ + \ summary for human\nreview. Include:\n- Total findings: N (X fixes applied,\ + \ Y escalations)\n- Deduplication stats (how many found by both reviewers)\n\ + - Each escalation with options and default recommendation\n- \"Accepted risks\"\ + \ section for INFO-level findings that don't need action\n" harness: planning/v1 requirements: - min_scores: { complexity: 9, spec_adherence: 9 } - - # ── Phase 4.7: Final Fix Implementation ──────────────────────────── - # - # After the human reviews escalations (via the human gate between - # auto_fix and final_fix in manual-workflow mode), this agent applies - # the human's decisions to the spec. The human annotates the - # escalations artifact with their choices before this node runs. - + min_scores: + complexity: 9 + spec_adherence: 9 + output: + path: /workspace/project/output.md + min_bytes: 500 final_fix: - name: "Apply Escalation Decisions" - depends_on: [auto_fix] - prompt: | - You are applying human decisions to a specification that has already had - non-controversial security fixes applied. - - ## Spec with Auto-Fixes Applied - <> - - ## Escalation Summary (with human decisions) - <> - - ## Instructions - - 1. Read the escalation summary. The human has annotated each escalation - with their decision (which option to implement, or a custom approach). - - 2. For each escalation where the human provided a decision: - - Apply the chosen fix to the spec text - - If the human chose a custom approach, implement it faithfully - - 3. For escalations where the human did NOT provide a decision: - - Apply the default recommendation noted in the escalation - - Mark with `` - - 4. For any "Accepted risks" the human flagged as needing action after all: - - Implement the fix - - 5. Verify requirement ID uniqueness — no duplicate IDs after all changes. - - 6. Verify all scenarios still match their requirements after text changes. - - ## Output - Write the FINAL spec to `/workspace/project/output.md`. - This is the production-ready spec. No review commentary, no TODOs, - no pending decisions. Every requirement has an ID, rationale, and scenario. - - At the top, include a summary comment: - `` + name: Apply Escalation Decisions + depends_on: + - auto_fix + prompt: "You are applying human decisions to a specification that has already\ + \ had\nnon-controversial security fixes applied.\n\n## Spec with Auto-Fixes\ + \ Applied\n<>\n\n## Escalation Summary (with human\ + \ decisions)\n<>\n\n## Instructions\n\n1. Read\ + \ the escalation summary. The human has annotated each escalation\n with their\ + \ decision (which option to implement, or a custom approach).\n\n2. For each\ + \ escalation where the human provided a decision:\n - Apply the chosen fix\ + \ to the spec text\n - If the human chose a custom approach, implement it\ + \ faithfully\n\n3. For escalations where the human did NOT provide a decision:\n\ + \ - Apply the default recommendation noted in the escalation\n - Mark with\ + \ ``\n\n4. For any\ + \ \"Accepted risks\" the human flagged as needing action after all:\n - Implement\ + \ the fix\n\n5. Verify requirement ID uniqueness — no duplicate IDs after all\ + \ changes.\n\n6. Verify all scenarios still match their requirements after text\ + \ changes.\n\n## Output\nWrite the FINAL spec to `/workspace/project/output.md`.\n\ + This is the production-ready spec. No review commentary, no TODOs,\nno pending\ + \ decisions. Every requirement has an ID, rationale, and scenario.\n\nAt the\ + \ top, include a summary comment:\n``\n" harness: planning/v1 requirements: - min_scores: { complexity: 9, spec_adherence: 9 } - model_override: "{{ best_model }}" - + min_scores: + complexity: 9 + spec_adherence: 9 + model_override: '{{ best_model }}' + output: + path: /workspace/project/output.md + min_bytes: 500 scoring: type: comparative_review reviews: - # Model A reviewed Plan B (spec, security, TDD) - - review_node: spec_review_a - scored_model_node: plan_b - dimension: spec_adherence - - review_node: security_review_a - scored_model_node: plan_b - dimension: spec_adherence - - review_node: tdd_review_a - scored_model_node: plan_b - dimension: test_pass_rate - # Model B reviewed Plan A (spec, security, TDD) - - review_node: spec_review_b - scored_model_node: plan_a - dimension: spec_adherence - - review_node: security_review_b - scored_model_node: plan_a - dimension: spec_adherence - - review_node: tdd_review_b - scored_model_node: plan_a - dimension: test_pass_rate + - review_node: spec_review_a + scored_model_node: plan_b + dimension: spec_adherence + - review_node: security_review_a + scored_model_node: plan_b + dimension: spec_adherence + - review_node: tdd_review_a + scored_model_node: plan_b + dimension: test_pass_rate + - review_node: spec_review_b + scored_model_node: plan_a + dimension: spec_adherence + - review_node: security_review_b + scored_model_node: plan_a + dimension: spec_adherence + - review_node: tdd_review_b + scored_model_node: plan_a + dimension: test_pass_rate method: fewer_improvement_points_wins