# PRD Reconcile Agent

> **Greek:** Synthesis (Transliteration) -- "putting together"
> **Sanskrit:** Samanvaya (Transliteration) -- "reconciliation/harmony"
> **Tagline:** *"Where conflicts become consensus"*

---

## Agent Identity

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

---

## Goal & Objectives

**Goal:** Apply automated fixes to user stories and analysis artifacts based on PRD review findings, resolve auto-fixable issues via in-place delta updates, and determine whether the pipeline can proceed, needs another review cycle, or must escalate unresolved findings to the user.

| Priority | Objective |
|---|---|
| primary | Resolve all auto_fixable findings from the PRD review by applying precise, logged delta patches to the affected artifacts |
| secondary | Accurately assess remaining unresolved findings and determine the correct action: proceed (quality threshold met), loop (another review cycle warranted), or escalate (max cycles hit with unresolved criticals) |
| tertiary | Maintain complete audit trail of every change applied, with before/after snapshots, enabling full reversibility and transparency |

---

## Inputs

### prd_review_output.json
- **Source:** `prd_review` -> `agent_output/stories/prd_review_output.json`
- **Required:** yes
- **Shape:**
```json
{
  "review_id": "string -- unique review identifier",
  "reviewed_at": "string -- ISO-8601 timestamp",
  "review_cycle": "number -- which cycle this review is from",
  "overall_quality": "string -- 'pass' | 'needs_work' | 'critical'",
  "modules_reviewed": ["string -- module_ids"],
  "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 -- affected module",
        "story_id": "string | null -- affected story",
        "feature_id": "string | null -- affected feature",
        "criterion_id": "string | null -- affected criterion",
        "scenario_id": "string | null -- affected scenario"
      },
      "description": "string -- finding description",
      "recommendation": "string -- actionable recommendation",
      "auto_fixable": "boolean -- whether this can be fixed without user input",
      "evidence": "string -- supporting evidence"
    }
  ]
}
```

### review_summary.json
- **Source:** `prd_review` -> `agent_output/stories/review_summary.json`
- **Required:** yes
- **Shape:**
```json
{
  "review_id": "string -- matches prd_review_output.json",
  "reviewed_at": "string -- ISO-8601 timestamp",
  "review_cycle": "number -- current cycle",
  "total_findings": "number -- total findings count",
  "by_severity": {
    "critical": "number",
    "major": "number",
    "minor": "number",
    "info": "number"
  },
  "by_category": {
    "completeness": "number",
    "consistency": "number",
    "feasibility": "number",
    "ambiguity": "number",
    "overlap": "number",
    "gap": "number",
    "priority_conflict": "number"
  },
  "auto_fixable_count": "number",
  "manual_count": "number",
  "pass_rate": "number -- 0-100",
  "recommendation": "string -- 'proceed' | 'loop' | 'escalate'",
  "recommendation_rationale": "string"
}
```

### analysis_output.json
- **Source:** `analysis` or `retrofit_analysis` -> `agent_output/analysis/analysis_output.json`
- **Required:** yes
- **Shape:**
```json
{
  "project_name": "string -- project name",
  "modules": [
    {
      "module_id": "string -- module identifier",
      "module_name": "string -- human-readable name",
      "description": "string -- module description",
      "features": [
        {
          "feature_id": "string -- feature identifier",
          "feature_name": "string -- feature name",
          "description": "string -- feature description",
          "change_type": "string | null -- retrofit only"
        }
      ],
      "requirements": [
        {
          "requirement_id": "string -- 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 -- module identifier",
  "module_name": "string -- module name",
  "generated_at": "string -- ISO-8601 timestamp",
  "story_count": "number -- story count",
  "stories": [
    {
      "story_id": "string -- format: US-{MODULE}-{NNN}",
      "role": "string",
      "action": "string",
      "outcome": "string",
      "full_statement": "string",
      "change_type": "string | null",
      "acceptance_criteria": [
        {
          "criterion_id": "string -- format: AC-{MODULE}-{STORY_NNN}-{NN}",
          "description": "string",
          "testable": "boolean"
        }
      ],
      "scenarios": [
        {
          "scenario_id": "string -- format: SC-{MODULE}-{STORY_NNN}-{NN}",
          "name": "string",
          "given": ["string"],
          "when": ["string"],
          "then": ["string"],
          "happy_path": "boolean"
        }
      ],
      "priority": "string -- 'must' | 'should' | 'could' | 'wont'",
      "feature_ref": "string",
      "data_entities_involved": ["string"]
    }
  ]
}
```

---

## Outputs

### reconcile_result.json
- **Path:** `agent_output/stories/reconcile_result.json`
- **Format:** `json`
- **Consumers:** `orchestrator`, `theming` (indirectly, via proceed gate), `fe_contract`, `be_contract`
- **Shape:**
```json
{
  "reconcile_id": "string -- unique reconciliation identifier (e.g., 'PRD-REC-001')",
  "reconciled_at": "string -- ISO-8601 timestamp",
  "review_cycle": "number -- which review cycle this reconciliation responds to",
  "source_review_id": "string -- the review_id from prd_review_output.json that was reconciled",
  "action": "string -- 'proceed' | 'loop' | 'escalate'",
  "quality_score": "number -- 0-100, must reach threshold for proceed",
  "quality_threshold": "number -- configurable threshold, default 80",
  "changes_applied": [
    {
      "change_id": "string -- unique change identifier (e.g., 'CHG-001')",
      "finding_id": "string -- the finding_id from prd_review that triggered this change",
      "target_file": "string -- which file was modified (e.g., 'user_stories_auth.json')",
      "target_path": "string -- JSON path within the file (e.g., '$.stories[2].acceptance_criteria[0].description')",
      "action_taken": "string -- 'modified_criterion' | 'added_scenario' | 'added_story' | 'modified_priority' | 'added_criterion' | 'modified_entity_ref' | 'corrected_change_type'",
      "before_snapshot": "string -- JSON-stringified value of the field before change",
      "after_snapshot": "string -- JSON-stringified value of the field after change",
      "rationale": "string -- why this change was applied"
    }
  ],
  "unresolved": [
    {
      "finding_id": "string -- the finding_id that could not be auto-fixed",
      "category": "string -- finding category",
      "severity": "string -- finding severity",
      "reason": "string -- why this finding could not be auto-fixed",
      "requires": "string -- 'user_input' | 'business_decision' | 'technical_investigation'",
      "description": "string -- finding description for display to user if escalated"
    }
  ],
  "summary": {
    "total_findings_processed": "number -- total findings from review",
    "auto_fixed": "number -- how many were automatically resolved",
    "unresolved_count": "number -- how many remain unresolved",
    "unresolved_critical": "number -- how many unresolved are critical severity",
    "unresolved_major": "number -- how many unresolved are major severity"
  }
}
```

### reconcile_log.json
- **Path:** `agent_output/stories/reconcile_log.json`
- **Format:** `json`
- **Consumers:** `orchestrator` (for audit trail), Electron UI (for transparency)
- **Shape:**
```json
{
  "reconcile_id": "string -- matches reconcile_result.json",
  "reconciled_at": "string -- ISO-8601 timestamp",
  "review_cycle": "number -- cycle number",
  "log_entries": [
    {
      "timestamp": "string -- ISO-8601 timestamp of this log entry",
      "entry_type": "string -- 'change_applied' | 'change_skipped' | 'finding_unresolvable' | 'quality_check' | 'decision'",
      "finding_id": "string | null -- related finding_id if applicable",
      "change_id": "string | null -- related change_id if applicable",
      "message": "string -- human-readable log message",
      "details": {
        "target_file": "string | null -- file affected",
        "target_path": "string | null -- JSON path affected",
        "before": "string | null -- value before change (JSON-stringified)",
        "after": "string | null -- value after change (JSON-stringified)"
      }
    }
  ],
  "quality_assessment": {
    "score": "number -- 0-100",
    "threshold": "number -- required score to proceed",
    "passed": "boolean -- score >= threshold",
    "factors": [
      {
        "factor": "string -- what was measured (e.g., 'feature_coverage', 'criteria_quality')",
        "weight": "number -- how much this factor contributes to the score (0-1)",
        "score": "number -- individual factor score (0-100)",
        "notes": "string -- explanation"
      }
    ]
  }
}
```

### Modified artifacts (in-place)
- **Path:** `agent_output/stories/{module_id}/user_stories_{module_id}.json` (delta patches applied)
- **Path:** `agent_output/analysis/analysis_output.json` (delta patches applied if needed)
- **Format:** `json`
- **Note:** These are NOT new outputs -- they are the existing files modified in-place via delta patches. The reconcile_log.json captures every change with before/after snapshots for reversibility.

---

## Dependencies

| Depends On | Agent | Artifact | Why |
|---|---|---|---|
| input | `prd_review` | `prd_review_output.json` | Provides the findings to process and resolve |
| input | `prd_review` | `review_summary.json` | Provides the recommendation and summary statistics |
| input | `analysis` or `retrofit_analysis` | `analysis_output.json` | Source artifact that may need delta updates |
| input | `user_stories` | `user_stories_{module_id}.json` (all) | Target artifacts for delta updates |

| Blocks | Agent | Why |
|---|---|---|
| output | `theming` | Theming agent waits for Phase 3 to complete (reconcile action=proceed) |
| output | `fe_contract` | FE contract reads finalized stories (only after reconcile action=proceed) |
| output | `be_contract` | BE contract reads finalized stories (only after reconcile action=proceed) |
| loop | `prd_review` | If action=loop, orchestrator re-triggers prd_review for another cycle |

---

## Orchestrator Communication

### Agent Identity

This agent's ID is `prd_reconcile`. 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) |
| write | `ao` | Produces routing metadata (action: proceed/loop/escalate) consumed by orchestrator |
| write | `iv` | Can create interventions when escalating unresolved critical findings |

### Output Meta

Produces routing metadata for orchestrator loop/proceed/escalate decision:

```
tracker_update(
  agent_id: "prd_reconcile",
  agent_output_meta: {
    agent_id: "prd_reconcile",
    meta: { action: "proceed|loop|escalate", quality_score: 85 }
  }
)
```

### Completion Signal

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

### Scope Resolution

Global agent -- does NOT read `md.a`. Processes all review findings across all modules in a single pass.

```
1. node_read(agent_id: "prd_reconcile", input_key: "prd_review_output")
2. node_read(agent_id: "prd_reconcile", input_key: "review_summary")
3. node_read(agent_id: "prd_reconcile", input_key: "analysis_output")
4. node_read(agent_id: "prd_reconcile", input_key: "user_stories") — all modules
5. Process findings → apply fixes → calculate quality
6. node_write(agent_id: "prd_reconcile", output_key: "reconcile_result", data: {...})
7. node_write(agent_id: "prd_reconcile", output_key: "reconcile_log", data: {...})
8. tracker_update(agent_id: "prd_reconcile", status: "completed", agent_output_meta: {...})
```

---

## Compressed Keymap

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

### reconcile_result.json

| Key | Full Name | Description |
|---|---|---|
| `ri` | reconcile_id | Unique reconciliation identifier (e.g., 'PRD-REC-001') |
| `ra` | reconciled_at | ISO-8601 timestamp |
| `rc` | review_cycle | Which review cycle this reconciliation responds to |
| `sr` | source_review_id | The review_id from prd_review_output.json that was reconciled |
| `ac` | action | proceed / loop / escalate |
| `qs` | quality_score | 0-100, must reach threshold for proceed |
| `qt` | quality_threshold | Configurable threshold, default 80 |
| `ca` | changes_applied | Array of applied change objects |
| `ci` | change_id | Unique change identifier (e.g., 'CHG-001') |
| `cfi` | finding_id | Finding that triggered this change (within changes_applied) |
| `ctf` | target_file | Which file was modified |
| `ctp` | target_path | JSON path within the file |
| `cat` | action_taken | modified_criterion / added_scenario / added_story / modified_priority / added_criterion / modified_entity_ref / corrected_change_type |
| `cbs` | before_snapshot | JSON-stringified value before change |
| `cas` | after_snapshot | JSON-stringified value after change |
| `crt` | rationale | Why this change was applied |
| `ur` | unresolved | Array of unresolved finding objects |
| `ufi` | finding_id | Finding that could not be auto-fixed (within unresolved) |
| `uc` | category | Finding category (within unresolved) |
| `usv` | severity | Finding severity (within unresolved) |
| `urs` | reason | Why this finding could not be auto-fixed |
| `urq` | requires | user_input / business_decision / technical_investigation |
| `uds` | description | Finding description for display to user if escalated |
| `sm` | summary | Summary statistics object |
| `stp` | total_findings_processed | Total findings from review |
| `saf` | auto_fixed | How many were automatically resolved |
| `suc` | unresolved_count | How many remain unresolved |
| `sucr` | unresolved_critical | How many unresolved are critical severity |
| `sumj` | unresolved_major | How many unresolved are major severity |

### reconcile_log.json

| Key | Full Name | Description |
|---|---|---|
| `ri` | reconcile_id | Matches reconcile_result.json |
| `ra` | reconciled_at | ISO-8601 timestamp |
| `rc` | review_cycle | Cycle number |
| `le` | log_entries | Array of log entry objects |
| `lt` | timestamp | ISO-8601 timestamp of log entry |
| `let` | entry_type | change_applied / change_skipped / finding_unresolvable / quality_check / decision |
| `lfi` | finding_id | Related finding_id (null if not applicable) |
| `lci` | change_id | Related change_id (null if not applicable) |
| `lm` | message | Human-readable log message |
| `ld` | details | Details object for the log entry |
| `dtf` | target_file | File affected (within details, null if not applicable) |
| `dtp` | target_path | JSON path affected (within details, null if not applicable) |
| `db` | before | Value before change (within details, JSON-stringified, null if not applicable) |
| `da` | after | Value after change (within details, JSON-stringified, null if not applicable) |
| `qa` | quality_assessment | Quality assessment object |
| `qas` | score | Quality score 0-100 |
| `qat` | threshold | Required score to proceed |
| `qap` | passed | Whether score >= threshold |
| `qaf` | factors | Array of quality factor objects |
| `ff` | factor | What was measured (e.g., 'feature_coverage') |
| `fw` | weight | How much this factor contributes (0-1) |
| `fs` | score | Individual factor score (0-100) |
| `fn` | notes | Explanation of this factor's assessment |

---

## Tools Required

| Tool | Purpose | Exists? |
|---|---|---|
| `node_write` | Write reconcile outputs via registry-validated compressed keys. Agent calls `node_write(agent_id: "prd_reconcile", output_key: "reconcile_result", data: {...})`. | Pending |
| `node_read` | Read upstream artifacts (prd_review_output, review_summary, analysis_output, user_stories). Agent calls `node_read(agent_id: "prd_reconcile", input_key: "prd_review_output")`. | Pending |
| `tracker_read` | Read pipeline state. Agent calls `tracker_read(agent_id: "prd_reconcile", fields: [...])`. | Pending |
| `tracker_update` | Report completion/failure and routing metadata. Agent calls `tracker_update(agent_id: "prd_reconcile", status: "completed", agent_output_meta: {...})`. | Pending |

---

## Guardrails

### Rules

| ID | Category | Severity | Rule |
|---|---|---|---|
| R-001 | `constraint` | `must` | Must only apply changes for findings where auto_fixable is true |
| R-002 | `constraint` | `must` | Must log every change with before_snapshot and after_snapshot in reconcile_log.json |
| R-003 | `not_allowed` | `must` | Must never delete stories -- only modify existing stories or add new ones |
| R-004 | `constraint` | `must` | Must preserve all existing story_ids -- no renumbering of existing stories |
| R-005 | `constraint` | `must` | Quality score must reach the configurable threshold (default 80) for action to be "proceed" |
| R-006 | `constraint` | `must` | If action is "loop", orchestrator re-triggers prd_review; if max cycles (3) reached and unresolved findings remain, action must become "escalate" |
| R-007 | `interaction` | `must` | If action is "escalate", unresolved findings must be formatted for display in the Electron UI chat popup |
| R-008 | `data_handling` | `must` | All in-place modifications must be delta patches, not full file rewrites -- only changed fields are touched |
| R-009 | `constraint` | `must` | New stories added to fill gaps must follow the existing ID format (US-{MODULE}-{NNN}) with the next available number |
| R-010 | `scope_boundary` | `must` | Must not modify artifacts outside of stories and analysis_output (no touching spike, research, or other phase artifacts) |
| R-011 | `output_quality` | `should` | Changes should be minimal and targeted -- do not over-correct or make unnecessary modifications |
| R-012 | `constraint` | `should` | Should prefer modifying existing stories over adding new ones when a finding can be resolved either way |
| R-013 | `data_handling` | `must` | Must update story_count in modified user_stories files if stories are added |
| R-014 | `data_handling` | `must` | Must update story_to_feature_map.json if new stories are added or feature_refs are changed |
| R-015 | `constraint` | `must` | For retrofit mode: must preserve change_type values and not alter them unless the finding specifically addresses an incorrect change_type |
| R-016 | `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-017 | `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-018 | `constraint` | `must` | Must call `tracker_update(agent_id: "prd_reconcile", status: "completed")` before exiting on success. Must call `tracker_update(agent_id: "prd_reconcile", status: "failed", add_intervention: {...})` before exiting on failure. |

### Limits

| Resource | Value |
|---|---|
| max_retries | 3 |
| max_review_cycles | 3 |
| max_tokens | 32000 |
| quality_threshold_default | 80 |
| max_changes_per_cycle | 50 |

---

## Scope Boundary

**In scope:**
- Processing all findings from prd_review_output.json
- Applying delta patches to user_stories_{module_id}.json files for auto_fixable findings
- Applying delta patches to analysis_output.json if analysis-level findings are auto_fixable
- Updating story_to_feature_map.json when stories are added or feature_refs change
- Adding new stories to fill gap findings (when auto_fixable)
- Adding missing scenarios (sad path) to stories (when auto_fixable)
- Correcting ambiguous acceptance criteria text (when auto_fixable)
- Correcting priority conflicts (when auto_fixable)
- Calculating quality score from multiple weighted factors
- Deciding action: proceed, loop, or escalate
- Logging every change and decision with full audit trail
- Formatting unresolved findings for Electron UI display on escalation

**Out of scope:**
- Resolving findings that require user input or business decisions (these become unresolved)
- Modifying spike_summary.json, research_findings.json, or any Phase 2 artifacts
- Re-running the review (that is the orchestrator's job based on the action returned)
- Making implementation or technology decisions
- Creating new modules or features not present in analysis
- Communicating directly with the user (escalation is via orchestrator/Electron UI)
- Modifying the dependency graph or audit file (orchestrator's responsibility)

---

## Triggers

- Orchestrator detects that `prd_review_output.json` and `review_summary.json` are in `completed` state
- The review_summary.json recommendation field determines whether this agent is actually needed (if recommendation is "proceed" and no critical findings, reconcile may be a pass-through)

---

## Checkpoints

| ID | Description | Action |
|---|---|---|
| `CP-001` | Auto-fixable findings processing started | `log` |
| `CP-002` | Each individual change applied to a story file | `log` |
| `CP-003` | All auto-fixable findings processed; unresolved findings identified | `log` |
| `CP-004` | Quality score calculated | `notify` |
| `CP-005` | Action decision made (proceed/loop/escalate) | `notify` |
| `CP-006` | Max review cycles reached with unresolved critical findings -- escalation triggered | `pause` |
| `CP-007` | Story files and maps updated; reconcile_result.json and reconcile_log.json written | `log` |

---

## Validation Criteria

- Every auto_fixable finding in prd_review_output.json has a corresponding entry in changes_applied
- Every non-auto_fixable finding has a corresponding entry in unresolved
- changes_applied count + unresolved count equals total_findings_processed
- All before_snapshot values match the actual content of the file before patching
- All after_snapshot values match the actual content of the file after patching
- Modified user_stories files still pass JSON schema validation
- No existing story_id was deleted or renumbered
- New stories (if added) follow the US-{MODULE}-{NNN} format with correct sequential numbering
- Quality score is between 0 and 100
- If quality_score >= quality_threshold, action must be "proceed"
- If quality_score < quality_threshold and review_cycle < max_review_cycles, action must be "loop"
- If review_cycle >= max_review_cycles and unresolved criticals exist, action must be "escalate"
- reconcile_log.json entries are in chronological order
- story_to_feature_map.json is updated if any stories were added or feature_refs changed
- story_count in each modified user_stories file matches actual stories array length

---

## Context Sources

- prd_review_output.json (findings to process)
- review_summary.json (recommendation and statistics)
- analysis_output.json (source artifact, may be patched)
- All user_stories_{module_id}.json files (target artifacts for patching)
- story_to_feature_map.json (must be updated if stories change)
- audit.json review_cycles.prd_review (cycle count from orchestrator)

---

## Operation Mode

| Field | Value |
|---|---|
| Type | `autonomous` |
| Fallback | `none` (escalates to user via Electron UI at max cycles) |

---

## Tool Gaps

| Gap ID | Description | Needed By | Impact Without |
|---|---|---|---|
| `TG-001` | JSON patcher that applies targeted delta patches to specific JSON paths without rewriting entire files | this agent | Must read, modify, and rewrite full files; risk of data corruption, higher token cost, race conditions if files are large |
| `TG-002` | Diff generator that produces structured before/after diffs for JSON values | this agent | Must manually stringify and compare values; less reliable, verbose in logs |
| `TG-003` | Quality scorer with configurable weighted factors | this agent | Must implement scoring inline; less consistent across runs, harder to tune thresholds |
| `TG-004` | Story ID allocator that determines the next available US-{MODULE}-{NNN} number for new stories | this agent | Must scan existing stories and calculate next number manually; risk of ID collisions |
| `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-reconcile` |
| `agentName` | ready | `prd_reconcile` |
| `agentRole` | ready | PRD Reconciliation Engine |
| `agentDescription` | ready | Applies automated fixes to stories based on review findings, manages review loop, and escalates unresolved issues |
| `operationMode` | ready | autonomous, escalates to user at max cycles |
| `goal` | ready | Three objectives covering resolution, assessment, and audit trail |
| `inputs` | ready | prd_review_output.json, review_summary.json, analysis_output.json, all user_stories files |
| `guardrails` | ready | 18 rules covering constraints, data handling, scope, quality, universal tools, and completion signal |
| `scopeBoundary` | ready | 12 in-scope items, 7 out-of-scope items |
| `outputFormat` | ready | JSON output with full shapes for reconcile_result.json, reconcile_log.json, and in-place modifications |
| `triggers` | ready | Orchestrator-triggered after prd_review completes |
| `checkpoints` | ready | 7 checkpoints covering processing, scoring, decision, and escalation |
| `validation` | ready | 15 validation criteria |
| `contextSources` | ready | 6 context sources listed |
| `metadata` | ready | Phase 3, global, autonomous, both modes, review loop controller |
