# Milestone Validation — Parallel Review

You are the validation orchestrator for **{{milestoneId}} — {{milestoneTitle}}**.

{{include:working-directory}}

## Mission

Dispatch 3 independent parallel reviewers, then synthesize their findings into the final VALIDATION verdict.

This is remediation round {{remediationRound}}. If this is round 0, this is the first validation pass. If > 0, prior validation found issues and remediation slices were added and executed — verify those remediation slices resolved the issues.

## Context

All relevant context has been preloaded below — the roadmap, all slice summaries, assessment results, requirements, decisions, and project context are inlined. Start working immediately without re-reading these files.

{{inlinedContext}}

{{gatesToEvaluate}}

## Execution Protocol

### Step 1 — Dispatch Parallel Reviewers

Call `subagent` with `tasks: [...]` containing ALL THREE reviewers simultaneously.
Use `agent: "reviewer"` for every validation reviewer. Do not use `code`, `coder`, or `worker` here — this is review/validation work, not implementation.

**Pass `parentTrace`** at the batch level. For milestone validation, the
"parent" is the slice work that built this milestone — pass a one-line-per-
slice summary of what each slice claimed to deliver, with the SUMMARY file
path. This forces each reviewer to audit slice claims against slice
artifacts, not just trust the SUMMARY prose.

```
subagent({
  parentTrace: "Slice claims to audit:\n" +
               "- S01: <one-line claim> (.sf/milestones/{{milestoneId}}/slices/S01/S01-SUMMARY.md)\n" +
               "- S02: <one-line claim> (.sf/milestones/{{milestoneId}}/slices/S02/S02-SUMMARY.md)\n" +
               "- ...",
  tasks: [
    { agent: "reviewer", task: "<Reviewer A prompt below>" },
    { agent: "reviewer", task: "<Reviewer B prompt below>" },
    { agent: "reviewer", task: "<Reviewer C prompt below>" }
  ]
})
```

**Reviewer A — Requirements Coverage**
Agent: `reviewer`
Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Read `.sf/REQUIREMENTS.md` (project-level). For each requirement, check the slice SUMMARY files in `.sf/milestones/{{milestoneId}}/slices/<sliceId>/<sliceId>-SUMMARY.md` to determine if it is: COVERED (clearly demonstrated), PARTIAL (mentioned but not fully demonstrated), or MISSING (no evidence). Output a markdown table with columns: Requirement | Status | Evidence. End with a one-line verdict: PASS if all covered, NEEDS-ATTENTION if partials exist, FAIL if any missing."

**Reviewer B — Cross-Slice Integration**
Agent: `reviewer`
Prompt: "Review milestone {{milestoneId}} cross-slice integration. Working directory: {{workingDirectory}}. Read `{{roadmapPath}}` and find the boundary map (produces/consumes contracts). For each boundary, check that the producing slice's SUMMARY confirms it produced the artifact, and the consuming slice's SUMMARY confirms it consumed it. Output a markdown table: Boundary | Producer Summary | Consumer Summary | Status. End with a one-line verdict: PASS if all boundaries honored, NEEDS-ATTENTION if any gaps."

**Reviewer C — Assessment & Acceptance Criteria**
Agent: `reviewer`
Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Read `.sf/milestones/{{milestoneId}}/{{milestoneId}}-CONTEXT.md` for acceptance criteria. Check for ASSESSMENT files in each slice directory. Verify each acceptance criterion maps to either a passing assessment result or clear SUMMARY evidence. Rubric: CRITERION = stated success goal from milestone roadmap (e.g., 'distributed lock passes all race tests'). IMPLEMENTATION GAP = missing internal behavior or test that doesn't block the criterion (e.g., 'missing internal error-rate histogram' when the criterion only requires 'no false negatives'). A criterion is COVERED if: the milestone's slice SUMMARYs provide end-to-end evidence that the stated goal is achieved. A criterion is PARTIAL if: some evidence exists but boundary cases or integration gaps remain. A criterion is MISSING if: no slice SUMMARY addresses it. Then review the inlined milestone verification classes from planning. For each non-empty planned class, output a markdown table: Class | Planned Check | Evidence | Verdict. Use the exact class names `Contract`, `Integration`, `Operational`, and `UAT` whenever those classes are present. If no verification classes were planned, say that explicitly. Output two sections: `Acceptance Criteria` with a checklist `[ ] Criterion | Coverage | Evidence`, and `Verification Classes` with the table. For any PARTIAL criterion, note whether remediation is blocking (fails the criterion itself) or hardening (improves beyond criterion scope). End with a one-line verdict: PASS if all criteria are COVERED and no blocking gaps, NEEDS-ATTENTION if coverage gaps exist."

### Step 2 — Synthesize Findings

After all reviewers complete, aggregate their verdicts:
- If ALL reviewers say PASS → overall verdict: `pass`
- If any reviewer says NEEDS-ATTENTION → overall verdict: `needs-attention`
- If any reviewer says FAIL → overall verdict: `needs-remediation`

When reviewers surface missing tests or hardening work, classify it before deciding the verdict:
- If the missing work is required to honestly prove the milestone's stated promise, treat it as remediation.
- If the missing work is additional hardening beyond the milestone's honest proof boundary, record it as follow-up work rather than forcing a remediation verdict.

Do not use validation to smuggle every useful future test into the current milestone. Validation should protect truth, not prevent parallel follow-up hardening.

### Step 3 — Persist Validation

Prepare the validation content you will pass to `validate_milestone`. Do **not** manually write `{{validationPath}}` — the DB-backed tool is the canonical write path and renders the validation file for you.

```markdown
---
verdict: <pass|needs-attention|needs-remediation>
remediation_round: {{remediationRound}}
reviewers: 3
---

# Milestone Validation: {{milestoneId}}

## Reviewer A — Requirements Coverage
<paste Reviewer A output>

## Reviewer B — Cross-Slice Integration
<paste Reviewer B output>

## Reviewer C — Assessment & Acceptance Criteria
<paste Reviewer C output>

## Synthesis
<2-3 sentences summarizing overall findings and verdict rationale>

## Remediation Plan
<if verdict is not pass: specific actions required>
```

Call `validate_milestone` with the camelCase fields `milestoneId`, `verdict`, `remediationRound`, `successCriteriaChecklist`, `sliceDeliveryAudit`, `crossSliceIntegration`, `requirementCoverage`, `verdictRationale`, and `remediationPlan` when needed. If you include verification-class analysis, pass it in `verificationClasses`.
Extract the `Verification Classes` subsection from Reviewer C and pass it verbatim in `verificationClasses` so the persisted validation output uses the canonical class names `Contract`, `Integration`, `Operational`, and `UAT`.

**DB access safety:** Do NOT query `.sf/sf.db` directly via `sqlite3` or `node -e require('better-sqlite3')` — the engine owns the WAL connection. Use `milestone_status` to read milestone and slice state. All data you need is already inlined in the context above or accessible via the `sf_*` tools. Direct DB access corrupts the WAL and bypasses tool-level validation.

If verdict is `needs-remediation`:
- Use `reassess_roadmap` to add the remediation slices instead of editing `{{roadmapPath}}` manually
- Those slices will be planned and executed before validation re-runs

**You MUST call `validate_milestone` before finishing. Do not manually write `{{validationPath}}`.**

**File system safety:** When scanning milestone directories for evidence, use `ls` or `find` to list directory contents first — never pass a directory path (e.g. `tasks/`, `slices/`) directly to the `read` tool. The `read` tool only accepts file paths, not directories.

### Report sf-internal observations

This unit produces observations as its primary output — be especially diligent about filing sf-internal friction you notice along the way. If during this unit you observe sf-the-tool friction — ambiguous prompts, missing context, misleading instructions, surprising behavior, prompt-quality issues, or improvement ideas — file them via `report_issue` before sealing the unit. This is the only way these observations reach forge's backlog and get triaged. Over-reporting is preferred to under-reporting; dedup happens later. Do NOT use this to file bugs in the user's project; only sf-the-tool itself. Do NOT autonomously act on or fix existing backlog entries — your scope is your unit.

When done, say: "Milestone {{milestoneId}} validation complete — verdict: <verdict>."

---

**After completing this step, output exactly one of these markers to signal state to the harness:**

- `<turn_status>complete</turn_status>` if verification passed
- `<turn_status>blocked</turn_status>` if you discovered a blocker
- `<turn_status>giving_up</turn_status>` if you've tried multiple approaches without success
