diff --git a/docs/workplan-state-model-proposal.md b/docs/workplan-state-model-proposal.md new file mode 100644 index 0000000..ed5144f --- /dev/null +++ b/docs/workplan-state-model-proposal.md @@ -0,0 +1,142 @@ +# Workplan State Model Proposal + +Date: 2026-05-17 +Status: proposed + +## Problem + +State Hub currently mixes three different vocabularies for the same lifecycle: + +- Workstream API/schema: `todo`, `active`, `blocked`, `completed`, `archived` +- Workplan consistency scripts: `active`, `completed`, `archived` +- Dashboard overview modes: `active`, `accepted`, `finished`, `blocked`, + `stalled`, `oldies` + +This makes file-backed workplans harder to reason about. A workplan can be a +good proposal but not ready to execute; a ready workplan can become stale after +the repo changes; parked backlog work should not clutter the current work view. + +Task status should remain separate. Tasks can keep using +`todo`, `in_progress`, `blocked`, `done`, and `cancelled`. + +## Proposed Canonical Workplan States + +These states should be valid in workplan frontmatter, the workstream API, the +database, consistency checks, and the dashboard. + +| State | Meaning | Current-view behavior | +|-------|---------|-----------------------| +| `proposed` | A plan exists, but it must be reviewed against the current repo state before execution. | Hidden from active execution views by default; visible in planning/review views. | +| `ready` | The plan has been reviewed and is ready to execute against the current repo state. | Visible in "ready to pick up" views. | +| `active` | Work has started and should appear in current work views. | Visible in current execution views. | +| `blocked` | Work cannot proceed until a dependency, decision, or human intervention clears. | Visible in current execution views and blocked views. | +| `backlog` | Intentionally parked for later; not currently being reviewed or executed. | Hidden from current work views by default. | +| `finished` | Implementation is complete and the workplan is closed. | Hidden from current work views; visible in completed/history views. | +| `archived` | Historical record, no longer part of normal planning or current execution. | Hidden except in archive/history views. | + +Recommended normal path: + +```text +backlog -> proposed -> ready -> active -> finished -> archived + \ \ + \ -> blocked -> active + -> backlog +``` + +## Staleness And Health Labels + +`stalled`, `oldies`, and `stale` should be derived health labels, not stored +lifecycle states. + +| Label | Derivation | Recommended UI name | +|-------|------------|---------------------| +| `stale` | `ready` workplan was reviewed against an older repo state. | Needs review | +| `stalled` | `active` or `blocked` workplan has had no meaningful progress after a threshold. | Stalled | +| `oldies` | Old planning item with no progress. | Replace with `proposed`, `backlog`, or `needs review` depending on intent. | + +For `ready` workplans, add optional frontmatter: + +```yaml +reviewed_at: "YYYY-MM-DD" +reviewed_by: "human-or-agent" +reviewed_against_commit: "" +context_paths: + - "path/or/glob" +``` + +Initial consistency behavior: + +- If a workplan is `ready` and `reviewed_against_commit` differs from repo + `HEAD`, report a warning: "ready workplan may be stale". +- If `context_paths` are present, only warn when files under those paths changed + since `reviewed_against_commit`. +- In `--fix` mode, optionally move stale `ready` workplans back to `proposed` + and record a progress event. This should be guarded behind an explicit flag at + first, because automatic demotion can be surprising. + +## UI Cleanup + +Replace the current overview mode set: + +```text +active, accepted, finished, blocked, stalled, oldies +``` + +with stored status filters plus health filters: + +```text +proposed, ready, active, blocked, backlog, finished, archived +needs review, stalled +``` + +Specific cleanup: + +- Rename `accepted` to `finished` if it currently means DB `completed`. +- Stop using `finished` as a derived "no open tasks" pseudo-state. Show that as + a badge such as `all tasks done` or `ready to close`. +- Remove `oldies` as a lifecycle term. It is charming, but it blurs backlog, + stale proposal, and neglected active work into one bucket. +- Keep `stalled` as a health filter/badge, not as a status value. + +## Compatibility And Migration + +For one migration window, accept legacy aliases in parsers and API clients: + +| Legacy value | Canonical value | +|--------------|-----------------| +| `todo` | `ready` for workstreams with no started tasks; otherwise `active` | +| `completed` | `finished` | +| `accepted` | `finished` | +| `oldies` | not stored; classify as `proposed` or `backlog` manually | +| `stalled` | not stored; derive from timestamps/progress | + +The consistency engine should normalize legacy file values before comparison, +but write back canonical values when it changes files. + +## Implementation Work + +1. Add a shared `WORKPLAN_STATUSES` / `WORKSTREAM_STATUSES` constant used by API + schemas, consistency scripts, validation scripts, and dashboard code. +2. Update `api/schemas/workstream.py` to allow the canonical state set. +3. Update `scripts/consistency_check.py` and `scripts/validate_repo_adr.py`: + accept the canonical states, map legacy aliases, and add stale-ready checks. +4. Add a migration that rewrites existing DB values: + `completed -> finished`; classify `todo` as `ready` or `active`. +5. Update dashboard overview modes and docs: + stored statuses become filters; `stalled` and `needs review` become health + filters. +6. Update project registration templates and AGENTS/CLAUDE guidance so new + repos use the canonical frontmatter states. +7. Add tests for parsing, normalization, stale-ready detection, API validation, + and dashboard filter classification. + +## Acceptance Criteria + +- A file-backed workplan can use `proposed`, `ready`, `active`, `blocked`, + `backlog`, `finished`, or `archived` without consistency warnings. +- Dashboard labels match stored lifecycle states and do not invent lifecycle + terms. +- `stalled` and `needs review` appear as derived health labels. +- A `ready` workplan can be flagged as stale after relevant repo changes. +- Legacy `completed` and `todo` workstreams are migrated or normalized without + breaking existing data.