# Canonical Workflow State Model

This standard defines the shared workflow state vocabulary for Requirements Intake, Requirements Review, Chunk Planning, Developer, QA, Orchestrator, Telegram, and future automation.

Markdown files remain the human-readable audit trail. Canonical state is the helper-derived orchestration truth used to decide next actions. If markdown and canonical state disagree, helpers must report the inconsistency and the Orchestrator must pause or request manual intervention instead of silently continuing.

## State Sources

Canonical state is derived only from fixed repository state:

- Requirements metadata and sections under `ai/requirements/{drafts,active,approved,completed}`.
- Chunk metadata and sections under `ai/chunks/{drafts,backlog,active,completed}`.
- Current `## Execution Notes`.
- Current `## Acceptance Criteria Verification`.
- Current `## QA Review`.
- Current `## Requirements Review`.
- `## Pass History`.
- Latest Developer, QA, Requirements Intake, Requirements Review, and Chunk Planning pass entries.
- Git status and diff summary when reporting commit readiness.

Do not derive canonical state from transient chat text, untrusted Telegram paths, arbitrary file reads, or arbitrary shell commands.

## Human Audit Sections

These sections stay as the readable audit/history layer:

- `## Execution Notes`: current Developer implementation summary.
- `## Acceptance Criteria Verification`: criterion-by-criterion acceptance status; every criterion must be marked `Verified`, `Blocked`, or `Not Applicable`, and every original `## Acceptance Criteria` bullet must be represented without materially changing its meaning.
- `## QA Review`: current QA verdict summary.
- `## Requirements Review`: current requirements verdict summary.
- `## Pass History`: chronological pass history for requirements and chunks.

Helpers should parse these sections to derive state, but humans should still keep them clear and current.

## Canonical States

Use lowercase snake_case in helper output and future JSON output.

| State | Meaning | Owner Role |
| --- | --- | --- |
| `requirements_intake` | A rough idea is being turned into a requirements draft. | Requirements Intake |
| `requirements_review` | A requirements draft is ready for review or currently blocked by review. | Requirements Review |
| `chunk_planning` | Requirements are approved and ready to become ordered implementation chunks. | Chunk Planner |
| `developer_pass` | Developer is implementing or fixing a chunk. | Developer |
| `ready_for_qa` | Developer pass is current and has validation, cleanup, and acceptance criteria verification recorded. | QA |
| `qa_blocked_fixable` | Current QA Review verdict is BLOCKED and QA classified the blocker as retry-safe/fixable. | Developer via Orchestrator |
| `qa_blocked_requires_decision` | Current QA Review verdict is BLOCKED and the blocker needs human, requirements, validation, or product clarification before retry. | Human or Requirements role |
| `qa_blocked_scope_change` | Current QA Review verdict is BLOCKED and the requested fix would change scope or acceptance criteria. | Human or Orchestrator |
| `retry_limit_reached` | The maximum Developer retry count has been reached after QA BLOCKED. | Human |
| `qa_passed` | Current QA Review verdict is PASS and no newer Developer pass exists, but completion readiness has not passed or still has blockers. | Orchestrator |
| `ready_to_complete` | QA passed and completion readiness checks passed; the next action is to complete/archive the chunk, then commit approved changes. | Orchestrator |
| `complete` | Chunk or requirements file is archived as completed. | Orchestrator |
| `commit_ready` | No active chunk remains and approved changes are ready to commit. | Orchestrator or Human |
| `manual_intervention_required` | State is ambiguous, unsafe, over retry limit, or requires unavailable services or human scope decisions. | Human |

## Requirements Transitions

| From | To | Required Condition | Owner Role |
| --- | --- | --- | --- |
| none | `requirements_intake` | New rough idea or active requirements draft. | Requirements Intake |
| `requirements_intake` | `requirements_review` | Draft has user workflow, scope, assumptions, open questions, acceptance criteria, and risks ready for review. | Requirements Intake |
| `requirements_review` | `requirements_intake` | Requirements Review returns BLOCKED with clarification questions. | Requirements Intake |
| `requirements_review` | `chunk_planning` | Requirements Review returns PASS and `approve-requirements.sh` moves the file to approved. | Requirements Review |
| `chunk_planning` | `complete` | Chunk plan is written or requirements are superseded. | Chunk Planner or Orchestrator |
| any | `manual_intervention_required` | Requirements are ambiguous, unsafe, contradictory, missing owner decisions, or cannot be validated. | Human |

## Chunk Transitions

| From | To | Required Condition | Owner Role |
| --- | --- | --- | --- |
| backlog/draft | `developer_pass` | Orchestrator activates or assigns a scoped chunk. | Orchestrator |
| `developer_pass` | `ready_for_qa` | Latest pass is Developer and includes validation, cleanup, and `## Acceptance Criteria Verification` that matches `## Acceptance Criteria`. | Developer |
| `ready_for_qa` | `qa_blocked_fixable` | QA Review verdict is BLOCKED and blocker classification is retry-safe/fixable. | QA |
| `ready_for_qa` | `qa_blocked_requires_decision` | QA Review verdict is BLOCKED and blocker classification requires a human or requirements decision, or is missing. | QA |
| `ready_for_qa` | `qa_blocked_scope_change` | QA Review verdict is BLOCKED and fix requires scope change. | QA |
| `ready_for_qa` | `retry_limit_reached` | QA Review verdict is BLOCKED after the maximum Developer attempts. | Orchestrator |
| `qa_blocked_fixable` | `developer_pass` | Orchestrator sends a focused Developer fix prompt. | Orchestrator |
| `ready_for_qa` | `qa_passed` | QA Review verdict is PASS and QA pass is newer than Developer pass, but completion readiness is not yet passed. | QA |
| `qa_passed` | `ready_to_complete` | Completion readiness checks pass. | Orchestrator |
| `ready_to_complete` | `complete` | Orchestrator runs the completion helper. | Orchestrator |
| `complete` | `commit_ready` | Chunk is archived and approved changes remain uncommitted. | Orchestrator |
| any | `manual_intervention_required` | State is ambiguous, over retry limit, validation unavailable, runtime smoke unavailable, or scope needs human decision. | Human |

## Stale Review Rules

- A QA Review is stale when the latest Developer pass is newer than the latest QA pass.
- A Requirements Review is stale when a newer Requirements Intake pass exists after the latest Requirements Review pass.
- A Chunk Plan is stale when a newer Requirements Review BLOCKED entry or Requirements Intake pass exists after the latest Chunk Planning pass.
- Stale PASS reviews must not allow completion, approval, or chunk planning.
- Helpers should report stale review risk explicitly and recommend Developer, QA, Requirements Review, or manual intervention as appropriate.

## QA Blocked Retry Rules

- QA BLOCKED reviews must include a blocker classification.
- `fixable` maps to `qa_blocked_fixable` and permits `ai/commands/prompt-synthesize.sh dev-fix`.
- `requires_decision` maps to `qa_blocked_requires_decision` and requires human or requirements clarification before retry.
- `scope_change` maps to `qa_blocked_scope_change` and requires human approval or a new chunk.
- Missing or unrecognized classification is treated as decision-required, not retry-safe.
- After three Developer passes, QA BLOCKED maps to `retry_limit_reached`.

## Pass Counters

- Developer iteration count is the number of `### Developer Pass N` entries in a chunk.
- QA pass count is the number of `### QA Pass N` entries in a chunk.
- Requirements intake pass count is the number of `### Requirements Intake Pass N` entries in requirements.
- Requirements review pass count is the number of `### Requirements Review Pass N` entries in requirements.
- Chunk planning pass count is the number of `### Chunk Planning Pass N` entries in requirements.

The default chunk retry limit is three Developer passes: the initial implementation plus two focused fixes. Exceeding the limit moves the canonical state to `manual_intervention_required`.

## Completion Readiness

A chunk is `ready_to_complete` only when:

- Exactly one active chunk exists.
- `## Execution Notes` exists.
- `## Acceptance Criteria Verification` exists.
- Every acceptance criterion is marked `Verified`, `Blocked`, or `Not Applicable`.
- `## Acceptance Criteria Verification` contains no `Blocked` items.
- `## Acceptance Criteria Verification` matches the original `## Acceptance Criteria` bullets closely enough that missing or extra verification items are readiness blockers.
- `## QA Review` exists.
- Current QA verdict is PASS.
- Latest pass is QA or QA is newer than Developer.
- `## Pass History` exists.
- Latest Developer and QA pass entries include validation, cleanup, and recommended next action.
- Required validation and runtime smoke decisions are documented.
- No stale QA risk exists.

When the completion gate passes, helper output should use:

- `Canonical state: ready_to_complete`
- `Completion gate: passed`
- `Recommended next action: complete/archive the chunk, then commit approved changes`

When QA has passed but the completion gate still has blockers, helper output should use:

- `Canonical state: qa_passed`
- `Completion gate: blocked`
- A recommended next action that tells the Orchestrator to resolve readiness blockers before archiving.

Requirements are ready for approval only when:

- Current Requirements Review verdict is PASS.
- Requirements gates pass or explicitly defer non-applicable items.
- Latest Requirements Review is not stale.

## Manual Intervention States

Canonical state must become `manual_intervention_required` when:

- Multiple active chunks exist in one workflow thread.
- Requirements are ambiguous or contradictory.
- QA and Developer disagree.
- Runtime smoke cannot be executed when required.
- Validation requires unavailable services.
- Scope must change to fix a blocker.
- Retry limits are reached.
- Helper parsing detects missing or contradictory state.

## Helper Expectations

- `ai/commands/workflow-state.sh` is the shared read-only chunk state helper.
- `ai/commands/requirements-state.sh` is the shared read-only requirements state helper.
- Future Telegram report commands should consume these helpers or match their state derivation exactly.
- Future JSON output should use the state names in this standard and must avoid secrets, tokens, and arbitrary file content.
