# PRD Review Agent

> **Greek:** Elenchos (Transliteration) -- "scrutiny/examination"
> **Sanskrit:** Samiksha (Transliteration) -- "critical review"
> **Tagline:** *"Trust, but verify"*

---

## Agent Identity

| Field | Value |
|---|---|
| ID | `prd_review` |
| Name | PRD Review Agent |
| Phase | 3 -- Stories & Review |
| Type | `pipeline` |
| Granularity | `global` |
| Interaction | `autonomous` |
| Mode | `all` |
| Domain | `dev` |

---

## Goal & Objectives

**Goal:** Perform a comprehensive quality review of all user stories against their source analysis, checking for completeness, consistency, feasibility, and clarity. Produce actionable findings that the reconcile agent can use to fix issues or escalate to the user.

| Priority | Objective |
|---|---|
| primary | Identify every gap, conflict, ambiguity, and feasibility issue across all modules' user stories and their source features |
| secondary | Classify findings by severity and category to enable automated resolution where possible |
| tertiary | Produce a clear recommendation (proceed, loop, or escalate) based on overall quality assessment |

---

## Inputs

### analysis_output.json
- **Source:** `analysis` or `retrofit_analysis` -> `agent_output/analysis/analysis_output.json`
- **Required:** yes
- **Shape:**
```json
{
  "project_name": "string -- name of the project",
  "modules": [
    {
      "module_id": "string -- unique module identifier",
      "module_name": "string -- human-readable module name",
      "description": "string -- module description",
      "features": [
        {
          "feature_id": "string -- unique feature identifier (e.g., 'F-AUTH-001')",
          "feature_name": "string -- human-readable feature name",
          "description": "string -- detailed feature description",
          "change_type": "string | null -- retrofit only: 'new' | 'modify_existing' | 'extend_existing' | 'no_change_reference'"
        }
      ],
      "requirements": [
        {
          "requirement_id": "string -- unique requirement identifier",
          "description": "string -- requirement text",
          "type": "string -- 'functional' | 'non_functional' | 'constraint'",
          "priority": "string -- 'must' | 'should' | 'could' | 'wont'"
        }
      ]
    }
  ]
}
```

### user_stories_{module_id}.json (all modules)
- **Source:** `user_stories` -> `agent_output/stories/{module_id}/user_stories_{module_id}.json`
- **Required:** yes
- **Shape:**
```json
{
  "module_id": "string -- the module these stories belong to",
  "module_name": "string -- human-readable module name",
  "generated_at": "string -- ISO-8601 timestamp",
  "story_count": "number -- total number of stories",
  "stories": [
    {
      "story_id": "string -- format: US-{MODULE}-{NNN}",
      "role": "string -- user role",
      "action": "string -- desired action",
      "outcome": "string -- expected benefit",
      "full_statement": "string -- complete user story statement",
      "change_type": "string | null -- retrofit only",
      "acceptance_criteria": [
        {
          "criterion_id": "string -- format: AC-{MODULE}-{STORY_NNN}-{NN}",
          "description": "string -- criterion statement",
          "testable": "boolean -- must be true"
        }
      ],
      "scenarios": [
        {
          "scenario_id": "string -- format: SC-{MODULE}-{STORY_NNN}-{NN}",
          "name": "string -- scenario name",
          "given": ["string -- precondition steps"],
          "when": ["string -- action steps"],
          "then": ["string -- outcome steps"],
          "happy_path": "boolean"
        }
      ],
      "priority": "string -- 'must' | 'should' | 'could' | 'wont'",
      "feature_ref": "string -- source feature_id",
      "data_entities_involved": ["string -- entity names"]
    }
  ]
}
```

### story_to_feature_map.json
- **Source:** `user_stories` -> `agent_output/stories/story_to_feature_map.json`
- **Required:** yes
- **Shape:**
```json
{
  "generated_at": "string -- ISO-8601 timestamp",
  "total_stories": "number -- total story count",
  "total_features": "number -- total feature count",
  "coverage": {
    "features_with_stories": "number -- features that have stories",
    "features_without_stories": "number -- features missing stories",
    "coverage_percentage": "number -- target: 100"
  },
  "mappings": [
    {
      "story_id": "string -- story identifier",
      "feature_id": "string -- feature identifier",
      "module_id": "string -- module identifier",
      "change_type": "string | null -- retrofit only"
    }
  ],
  "unmapped_features": ["string -- feature_ids with no stories"]
}
```

### research_findings.json
- **Source:** `research` -> `agent_output/research/research_findings.json`
- **Required:** yes
- **Shape:**
```json
{
  "research_id": "string -- research run identifier",
  "technical_risks": [
    {
      "risk_id": "string -- risk identifier",
      "description": "string -- risk description",
      "severity": "string -- 'high' | 'medium' | 'low'",
      "mitigation": "string -- mitigation strategy",
      "affects_modules": ["string -- module_ids"],
      "affects_features": ["string -- feature_ids"]
    }
  ]
}
```

---

## Outputs

### prd_review_output.json
- **Path:** `agent_output/stories/prd_review_output.json`
- **Format:** `json`
- **Consumers:** `prd_reconcile`
- **Shape:**
```json
{
  "review_id": "string -- unique review identifier (e.g., 'PRD-REV-001')",
  "reviewed_at": "string -- ISO-8601 timestamp of review completion",
  "review_cycle": "number -- which cycle of the review loop this is (1, 2, or 3)",
  "overall_quality": "string -- 'pass' | 'needs_work' | 'critical'",
  "modules_reviewed": ["string -- list of module_ids reviewed"],
  "findings": [
    {
      "finding_id": "string -- unique finding identifier (e.g., 'FND-001')",
      "category": "string -- 'completeness' | 'consistency' | 'feasibility' | 'ambiguity' | 'overlap' | 'gap' | 'priority_conflict'",
      "severity": "string -- 'critical' | 'major' | 'minor' | 'info'",
      "location": {
        "module_id": "string -- which module is affected",
        "story_id": "string | null -- which story is affected (null if module-level finding)",
        "feature_id": "string | null -- which feature is affected (null if story-level finding)",
        "criterion_id": "string | null -- which criterion is affected (null if not criterion-level)",
        "scenario_id": "string | null -- which scenario is affected (null if not scenario-level)"
      },
      "description": "string -- detailed description of the finding",
      "recommendation": "string -- specific actionable recommendation to resolve the finding",
      "auto_fixable": "boolean -- whether the reconcile agent can fix this without user input",
      "evidence": "string -- what data or cross-reference led to this finding"
    }
  ]
}
```

### review_summary.json
- **Path:** `agent_output/stories/review_summary.json`
- **Format:** `json`
- **Consumers:** `prd_reconcile`, `orchestrator`
- **Shape:**
```json
{
  "review_id": "string -- matches prd_review_output.json review_id",
  "reviewed_at": "string -- ISO-8601 timestamp",
  "review_cycle": "number -- current cycle number (1, 2, or 3)",
  "total_findings": "number -- total count of all findings",
  "by_severity": {
    "critical": "number -- count of critical findings",
    "major": "number -- count of major findings",
    "minor": "number -- count of minor findings",
    "info": "number -- count of informational findings"
  },
  "by_category": {
    "completeness": "number -- findings about missing stories or criteria",
    "consistency": "number -- findings about contradictions between stories",
    "feasibility": "number -- findings about stories that conflict with spike constraints",
    "ambiguity": "number -- findings about unclear or vague criteria",
    "overlap": "number -- findings about duplicate or overlapping stories",
    "gap": "number -- findings about features not covered by stories",
    "priority_conflict": "number -- findings about conflicting priority assignments"
  },
  "auto_fixable_count": "number -- how many findings can be automatically resolved",
  "manual_count": "number -- how many findings require user input",
  "pass_rate": "number -- percentage of checks that passed (0-100)",
  "recommendation": "string -- 'proceed' | 'loop' | 'escalate'",
  "recommendation_rationale": "string -- explanation of why this recommendation was made"
}
```

---

## Dependencies

| Depends On | Agent | Artifact | Why |
|---|---|---|---|
| input | `user_stories` | `user_stories_{module_id}.json` (all) | Stories to review |
| input | `user_stories` | `story_to_feature_map.json` | To validate completeness of feature-to-story coverage |
| input | `analysis` or `retrofit_analysis` | `analysis_output.json` | Source of truth for features and requirements to check stories against |
| input | `research` | `research_findings.json` | Technical risks to check feasibility of stories against |
| context | `spike` | `spike_summary.json` | Constraints that stories must not violate |

| Blocks | Agent | Why |
|---|---|---|
| output | `prd_reconcile` | Reconcile agent needs findings to apply fixes and decide proceed/loop/escalate |

---

## Orchestrator Communication

### Agent Identity

This agent's ID is `prd_review`. Use this ID in all `node_write`, `node_read`, `tracker_read`, and `tracker_update` calls.

### Tracker Access

| Direction | Compressed Keys | Purpose |
|---|---|---|
| read | (none) | Global agent -- does not read `md.a` |
| write | `ag` | Report agent status (completed/failed) |

### Output Meta

This agent does not produce routing/coordination metadata. `output_meta: null`.

### Completion Signal

- **On success:** `tracker_update(agent_id: "prd_review", status: "completed")`
- **On failure:** `tracker_update(agent_id: "prd_review", status: "failed", add_intervention: { id: "...", agent_id: "prd_review", type: "error", message: "..." })`

### Scope Resolution

Global agent -- does NOT read `md.a`. Reviews all user stories across all modules in a single pass.

```
1. node_read(agent_id: "prd_review", input_key: "analysis_output")
2. node_read(agent_id: "prd_review", input_key: "user_stories") — all modules
3. node_read(agent_id: "prd_review", input_key: "story_to_feature_map")
4. node_read(agent_id: "prd_review", input_key: "research_findings")
5. Perform review → generate findings
6. node_write(agent_id: "prd_review", output_key: "prd_review_output", data: {...})
7. node_write(agent_id: "prd_review", output_key: "review_summary", data: {...})
8. tracker_update(agent_id: "prd_review", status: "completed")
```

---

## Compressed Keymap

Use these compressed keys in all `node_write` calls. The registry validates against this map — unknown keys are rejected.

### prd_review_output.json

| Key | Full Name | Description |
|---|---|---|
| `rvi` | review_id | Unique review identifier (e.g., 'PRD-REV-001') |
| `ra` | reviewed_at | ISO-8601 timestamp of review completion |
| `rc` | review_cycle | Which cycle of the review loop (1, 2, or 3) |
| `oq` | overall_quality | pass / needs_work / critical |
| `mr` | modules_reviewed | Array of module_ids reviewed |
| `fd` | findings | Array of finding objects |
| `fi` | finding_id | Unique finding identifier (e.g., 'FND-001') |
| `fc` | category | completeness / consistency / feasibility / ambiguity / overlap / gap / priority_conflict |
| `sv` | severity | critical / major / minor / info |
| `lo` | location | Location object identifying the affected element |
| `lm` | module_id | Module affected (within location) |
| `ls` | story_id | Story affected (within location, null if module-level) |
| `lf` | feature_id | Feature affected (within location, null if story-level) |
| `lc` | criterion_id | Criterion affected (within location, null if not criterion-level) |
| `lsc` | scenario_id | Scenario affected (within location, null if not scenario-level) |
| `ds` | description | Detailed description of the finding |
| `rm` | recommendation | Specific actionable recommendation |
| `af` | auto_fixable | Whether reconcile agent can fix without user input |
| `ev` | evidence | Data or cross-reference that led to this finding |

### review_summary.json

| Key | Full Name | Description |
|---|---|---|
| `rvi` | review_id | Matches prd_review_output.json review_id |
| `ra` | reviewed_at | ISO-8601 timestamp |
| `rc` | review_cycle | Current cycle number (1, 2, or 3) |
| `tf` | total_findings | Total count of all findings |
| `bs` | by_severity | Severity breakdown object |
| `bsc` | critical | Count of critical findings (within by_severity) |
| `bsm` | major | Count of major findings (within by_severity) |
| `bsn` | minor | Count of minor findings (within by_severity) |
| `bsi` | info | Count of informational findings (within by_severity) |
| `bc` | by_category | Category breakdown object |
| `bcc` | completeness | Completeness findings count (within by_category) |
| `bcn` | consistency | Consistency findings count (within by_category) |
| `bcf` | feasibility | Feasibility findings count (within by_category) |
| `bca` | ambiguity | Ambiguity findings count (within by_category) |
| `bco` | overlap | Overlap findings count (within by_category) |
| `bcg` | gap | Gap findings count (within by_category) |
| `bcp` | priority_conflict | Priority conflict findings count (within by_category) |
| `afc` | auto_fixable_count | How many findings can be automatically resolved |
| `mc` | manual_count | How many findings require user input |
| `pr` | pass_rate | Percentage of checks that passed (0-100) |
| `rn` | recommendation | proceed / loop / escalate |
| `rr` | recommendation_rationale | Explanation of why this recommendation was made |

---

## Tools Required

| Tool | Purpose | Exists? |
|---|---|---|
| `node_write` | Write review output via registry-validated compressed keys. Agent calls `node_write(agent_id: "prd_review", output_key: "prd_review_output", data: {...})`. | Pending |
| `node_read` | Read upstream artifacts (analysis_output, user_stories, story_to_feature_map, research_findings). Agent calls `node_read(agent_id: "prd_review", input_key: "analysis_output")`. | Pending |
| `tracker_read` | Read pipeline state. Agent calls `tracker_read(agent_id: "prd_review", fields: [...])`. | Pending |
| `tracker_update` | Report completion/failure. Agent calls `tracker_update(agent_id: "prd_review", status: "completed")`. | Pending |

---

## Guardrails

### Rules

| ID | Category | Severity | Rule |
|---|---|---|---|
| R-001 | `constraint` | `must` | Must check completeness: every feature_id in analysis_output.json must appear in at least one story's feature_ref |
| R-002 | `constraint` | `must` | Must check consistency: no two stories within the same module should contradict each other in their outcomes or acceptance criteria |
| R-003 | `constraint` | `must` | Must check feasibility: stories must not require capabilities that spike constraints explicitly rule out |
| R-004 | `constraint` | `must` | Must flag ambiguous acceptance criteria: criteria with vague terms like "should work well", "fast enough", "user-friendly" without measurable thresholds |
| R-005 | `not_allowed` | `must` | Must not modify any source artifacts -- this agent is strictly read-only; all changes happen via the reconcile agent |
| R-006 | `constraint` | `must` | Must check scenario coverage: every story must have at least one happy path and one sad path scenario |
| R-007 | `constraint` | `should` | Should check for cross-module overlap: stories in different modules that describe the same functionality |
| R-008 | `constraint` | `should` | Should check priority conflicts: must-have stories that depend on could-have or wont-have stories |
| R-009 | `data_handling` | `must` | Must assign every finding a unique finding_id that is stable across review cycles |
| R-010 | `output_quality` | `must` | Must provide specific, actionable recommendations for each finding -- not vague suggestions |
| R-011 | `constraint` | `must` | Must correctly classify auto_fixable for each finding: only structural/format issues are auto_fixable, not semantic/business logic issues |
| R-012 | `scope_boundary` | `must` | Review runs up to 3 times maximum (orchestrator tracks cycle count in audit.review_cycles.prd_review) |
| R-013 | `constraint` | `should` | Should verify that data_entities_involved in stories reference plausible domain entities |
| R-014 | `constraint` | `must` | For retrofit: must verify every story with change_type carries the correct change_type from its source feature |
| R-015 | `constraint` | `must` | Must use compressed keys as defined in the Compressed Keymap section for all `node_write` / `node_read` calls. Never use expanded/full key names. |
| R-016 | `constraint` | `must` | Must use `node_write` to write output and `node_read` to read upstream artifacts. Must not use raw file writes, generic file_writer, or any other method. |
| R-017 | `constraint` | `must` | Must call `tracker_update(agent_id: "prd_review", status: "completed")` before exiting on success. Must call `tracker_update(agent_id: "prd_review", status: "failed", add_intervention: {...})` before exiting on failure. |

### Limits

| Resource | Value |
|---|---|
| max_retries | 3 |
| max_review_cycles | 3 |
| max_tokens | 32000 |
| max_findings | 200 |

---

## Scope Boundary

**In scope:**
- Reviewing all user stories across all modules for completeness against analysis features
- Checking consistency between stories within and across modules
- Checking feasibility of stories against spike constraints and technical risks
- Flagging ambiguous, untestable, or vague acceptance criteria
- Detecting overlapping or duplicate stories
- Detecting gaps where features have no stories
- Detecting priority conflicts (dependency ordering vs MoSCoW)
- Classifying each finding by category, severity, and auto-fixability
- Producing a proceed/loop/escalate recommendation

**Out of scope:**
- Modifying stories, analysis, or any source artifact (read-only agent)
- Writing new stories to fill gaps (reconcile agent's job)
- Making implementation decisions or technology choices
- Reviewing design tokens, wireframes, or contracts
- Communicating with the user (autonomous agent -- escalation goes through reconcile)
- Validating JSON schema compliance of input files (assumed valid from upstream)

---

## Triggers

- Orchestrator detects that ALL `user_stories_{module_id}.json` files and `story_to_feature_map.json` are in `completed` state for all active modules
- Re-triggered by orchestrator when `prd_reconcile` returns action `loop` and review_cycles.prd_review.current < review_cycles.prd_review.max

---

## Checkpoints

| ID | Description | Action |
|---|---|---|
| `CP-001` | Completeness check complete: all features verified against story mappings | `log` |
| `CP-002` | Consistency check complete: cross-story contradiction analysis done | `log` |
| `CP-003` | Feasibility check complete: stories verified against spike constraints | `log` |
| `CP-004` | Critical findings detected: one or more findings with severity=critical | `notify` |
| `CP-005` | Review complete: overall_quality and recommendation determined | `notify` |
| `CP-006` | Max review cycles approaching: review_cycle equals max_review_cycles | `notify` |

---

## Validation Criteria

- Every feature_id in analysis_output.json is checked (completeness scan is exhaustive)
- Every story in every module's stories file is reviewed
- Every finding has a unique finding_id
- Every finding has a valid category from the allowed set
- Every finding has a valid severity from the allowed set
- Every finding has a non-empty description and recommendation
- Every finding has auto_fixable set to a boolean (not null or undefined)
- review_summary.json totals match the actual findings count in prd_review_output.json
- by_severity and by_category breakdowns sum to total_findings
- recommendation is one of: proceed, loop, escalate
- pass_rate is calculated correctly (checks passed / total checks * 100)
- Review cycle number matches the orchestrator's tracked cycle count

---

## Context Sources

- analysis_output.json (the source of truth for features and requirements)
- All user_stories_{module_id}.json files (the artifacts being reviewed)
- story_to_feature_map.json (coverage mapping to verify)
- research_findings.json (technical risks for feasibility checks)
- spike_summary.json (constraints for feasibility checks)
- audit.json review_cycles.prd_review (current cycle count from orchestrator)

---

## Operation Mode

| Field | Value |
|---|---|
| Type | `autonomous` |
| Fallback | `none` |

---

## Tool Gaps

| Gap ID | Description | Needed By | Impact Without |
|---|---|---|---|
| `TG-001` | Cross-reference checker that programmatically validates feature-to-story mappings are complete and bidirectional | this agent | LLM must manually iterate all features and all stories; risk of missed gaps in large projects with 50+ features |
| `TG-002` | Constraint matcher that compares story requirements against spike constraints programmatically | this agent | LLM must hold all constraints in context and compare; risk of missing constraint violations |
| `TG-003` | Duplicate/overlap detector that uses semantic similarity to find stories describing the same functionality across modules | this agent | LLM must compare all story pairs; O(n^2) problem that degrades with scale |
| `TG-004` | Ambiguity scorer that identifies vague language patterns in acceptance criteria | this agent | LLM can catch obvious vagueness but may miss subtle cases |
| `TG-005` | `node_write` MCP tool not yet built | this agent | Cannot write output with registry validation — blocked |
| `TG-006` | `node_read` MCP tool not yet built | this agent | Cannot read upstream artifacts with field enforcement — blocked |
| `TG-007` | `tracker_read` MCP tool not yet built | this agent | Cannot read pipeline state — blocked |
| `TG-008` | `tracker_update` MCP tool not yet built | this agent | Cannot report completion — blocked |

---

## Generation Readiness

| `generate_agent` Param | Status | Notes |
|---|---|---|
| `fileName` | ready | `prd-review` |
| `agentName` | ready | `prd_review` |
| `agentRole` | ready | PRD Quality Reviewer |
| `agentDescription` | ready | Reviews all user stories for completeness, consistency, feasibility, and clarity against source analysis |
| `operationMode` | ready | autonomous, no fallback |
| `goal` | ready | Three objectives defined covering detection, classification, and recommendation |
| `inputs` | ready | analysis_output.json, all user_stories files, story_to_feature_map.json, research_findings.json |
| `guardrails` | ready | 17 rules covering constraints, quality, scope, data handling, universal tools, and completion signal |
| `scopeBoundary` | ready | 9 in-scope items, 6 out-of-scope items |
| `outputFormat` | ready | JSON output with full shapes for prd_review_output.json and review_summary.json |
| `triggers` | ready | Orchestrator-triggered after all stories complete; re-triggered on loop |
| `checkpoints` | ready | 6 checkpoints covering each review phase and critical findings |
| `validation` | ready | 12 validation criteria |
| `contextSources` | ready | 6 context sources listed |
| `metadata` | ready | Phase 3, global, autonomous, both modes, review loop participant |
