--- id: STATE-WP-0047 type: workplan title: "Lifecycle Assertions and Renormalization" domain: custodian repo: state-hub status: finished owner: codex topic_slug: custodian planning_priority: high planning_order: 47 created: "2026-05-23" updated: "2026-05-23" state_hub_workstream_id: "1972d1d9-fc35-4912-8126-1fe64cc51425" --- # STATE-WP-0047 - Lifecycle Assertions and Renormalization ## Goal Make workplan and task lifecycle management deterministic: starting work should advance the workplan/workstream to `active`, finishing all executable work should make closure obvious, and any direct manipulation that violates the model should be detected and repaired by clear helper functions. ## Context The current canonical vocabulary is good, but enforcement is incomplete. A workstream can remain `proposed` while tasks are actively worked, as seen with `RAIL-FAB-WP-0016`. The flow engine can report blocked exit assertions, but the state changes themselves do not consistently use a shared transition layer. This workplan turns the vocabulary into executable rules and repair scaffolding. ## Lifecycle Invariants | Invariant | Classification | Repair Path | |-----------|----------------|-------------| | A task moving from `todo` to `in_progress` activates a parent workstream in `proposed`, `ready`, or `backlog`. | automatic repair | Set parent workstream status to `active` in the same transaction. | | A `blocked` parent workstream is not automatically unblocked by task start. | hard guard | Keep `blocked`; require explicit unblock transition or dependency/decision repair. | | `finished` and `archived` workstreams should not have open tasks unless explicitly grandfathered. | warning, then repair | Report via consistency tooling; close/cancel stale tasks or reopen parent with intent. | | `needs_review` and `stalled` remain derived health labels. | hard vocabulary guard | Do not write them to workplan frontmatter or `workstreams.status`. | | Archived workplan files must have closed lifecycle states. | hard consistency error | Move file back to active workplans or close the lifecycle state. | ## T01 - Define Lifecycle Invariants ```task id: STATE-WP-0047-T01 status: done priority: high state_hub_task_id: "28f28391-646c-4871-ae84-a1c1aae3f5bf" ``` Write a concise lifecycle invariant table for workplans/workstreams and tasks. Include rules such as: active tasks imply an active workstream; finished workstreams cannot have open tasks unless explicitly blocked/grandfathered; archived files must have closed states; and `needs_review`/`stalled` remain derived labels. Done when the invariant table is documented and each rule is classified as hard error, warning, automatic repair, or human-review item. Result 2026-05-23: added the initial invariant table above. The first automatic repair implemented in this slice is parent activation when real task work starts. ## T02 - Implement Shared Transition Helpers ```task id: STATE-WP-0047-T02 status: done priority: high state_hub_task_id: "56d9b6b9-fba1-4997-bdd5-875187cafa2d" ``` Add deterministic helper functions for task and workstream transitions instead of scattering direct status writes. The helpers should normalize aliases, check entry and exit assertions, and return concise repair/action results. Done when API routes, consistency tooling, and future UI actions can call one shared transition layer for lifecycle changes. Progress 2026-05-23: added `api.services.lifecycle` with shared status normalization and parent-activation helpers. The task API now uses the helper; consistency tooling and future UI actions still need to adopt the shared layer. Progress 2026-05-23: consistency tooling now uses the shared lifecycle helper to detect and repair planning-state workplans with active tasks. Future UI actions still need to route through the shared transition layer. Result 2026-05-23: expanded the shared lifecycle helper into canonical workstream/task transition functions with result metadata. Direct task and workstream routes, flow advancement, consistency tooling, and UI-originated reconciliation now route status changes through the shared layer. Task-start write-through also patches parent workplan frontmatter to `active` when the shared helper activates the parent workstream. ## T03 - Auto-Advance Workstream On Task Start ```task id: STATE-WP-0047-T03 status: done priority: high state_hub_task_id: "b0937fed-bd61-4f27-9586-8cebc6168827" ``` When a task moves from `todo` to `in_progress`, ensure the owning workstream advances from `proposed`, `ready`, or `backlog` to `active`, unless an explicit guard blocks the transition. Done when starting real task work cannot leave the parent workstream parked in planning states. Result 2026-05-23: task creation or update to `in_progress` activates a parent workstream from `proposed`, `ready`, or `backlog`, while leaving `blocked` parents blocked. ## T04 - Harden Flow Advancement Semantics ```task id: STATE-WP-0047-T04 status: done priority: high state_hub_task_id: "3f1e49fd-0600-4124-a7bc-0c75955bac8b" ``` Make flow advancement honor both current exit assertions and target entry assertions. Return actionable blocking assertions when a transition is refused. Done when `/flows/.../advance/...` cannot bypass the same assertions the flow state endpoint reports as blocking. Result 2026-05-23: `FlowEngine.can_reach()` now checks current exit assertions before target entry assertions for real transitions. The flow advance endpoint returns HTTP 409 when a dependency blocks leaving `active`, even if the target state entry assertions pass. ## T05 - Add Renormalization Checks And Repairs ```task id: STATE-WP-0047-T05 status: done priority: high state_hub_task_id: "611f0c22-34bc-494e-b520-068b4c3f0fec" ``` Extend consistency tooling with invariant checks that detect drift from clean workplan/task modelling and either repair it or report a precise fix. Include the `proposed workstream with in_progress task` case. Done when direct DB or file manipulation that breaks lifecycle invariants is caught by a repeatable repair path. Result 2026-05-23: added consistency rule C-23 for the `proposed`/`ready`/`backlog` workplan with an `in_progress` or `blocked` task case. The repair updates the DB workstream to `active`, patches workplan frontmatter to `status: active`, commits the writeback, and pushes through the existing consistency sync loop. ## T06 - Record Drift As Learning Input ```task id: STATE-WP-0047-T06 status: done priority: medium state_hub_task_id: "4b663fce-876c-4a52-955c-c754dbf44b0f" ``` When the system recognizes a new drift pattern, provide a lightweight way to turn that pattern into a new invariant, test, or consistency repair. Done when renormalization scaffolding has an explicit "add the next guard here" pattern instead of relying on ad hoc fixes. Result 2026-05-23: added a renormalization rule registry and `scripts/consistency_check.py --renormalization-guide`. The guide lists active repair rules and the concise checklist for turning the next recognized drift pattern into metadata, detection, repair, and tests. ## T07 - Regression Tests ```task id: STATE-WP-0047-T07 status: done priority: high state_hub_task_id: "def5ce49-1938-4c45-807d-78ac15c995cb" ``` Add tests for transition helpers, task-start parent activation, flow assertion enforcement, and consistency repairs. Done when lifecycle drift is hard to reintroduce accidentally. Progress 2026-05-23: added router regression tests for task-start activation from `proposed`, `ready`, and `backlog`, plus a guard test proving `blocked` parents stay blocked. Remaining coverage still needs flow assertion hardening and consistency repair tests. Progress 2026-05-23: added engine and router coverage proving flow advancement honors current exit assertions before moving to the target workstation. Progress 2026-05-23: added consistency checker coverage for lifecycle renormalization detection and repair, including a guard that C-23 takes precedence over generic C-04 status drift. Progress 2026-05-23: added guide coverage so the drift-learning scaffold has a stable test anchor. Result 2026-05-23: lifecycle coverage now spans direct helper tests, task-start parent activation route tests, flow exit assertion tests, and consistency repair/guide tests. ## Acceptance Criteria - Starting task work deterministically activates the parent workstream. - Flow transitions evaluate current exit assertions and target entry assertions. - Lifecycle invariants are documented, tested, and enforced through shared helpers. - Consistency tooling repairs or reports lifecycle drift with low-token, deterministic messages.