Task — engineering-spec@1

"1.5.0 — transition-locked state engine (close frontmatter bypass)"

doneTASK-IMP-144
module improvement · class product · priority p2 · created 2026-07-23 · shipped null
depends on TASK-CUO-303, TASK-IMP-143 · blocks none

TASK-IMP-144: 1.5.0 transition-locked state engine

Summary

Close the TASK-CUO-303 residual where an agent edits spec.md frontmatter status: and regenerates BACKLOG without ever calling flip. A single state-engine API owns status transitions; regenerators refuse to invent transition edges without an engine receipt.

Problem

backlog-mutate flip mechanically locks the two HITL gates, but editing frontmatter to done and running regen_backlog rewrites the index from frontmatter alone — R-EXT-01 / ship-tasks accepted residual.

Proposed Solution

  1. Receipts — every successful backlog-mutate flip writes a content-addressed receipt under docs/tasks/_state/receipts/<task>--<from>--<to>--<sha12>.json binding task_id, from, to, and (for HITL gates) verdict artifact coordinates.
  2. Regen refusalregen_backlog() parses the previous BACKLOG; when an existing stem's status would change to the frontmatter value, it requires a matching receipt for that (task_id, from, to) triple; otherwise it exits non-zero and writes nothing. New stems (inserts) and identical statuses do not need receipts.
  3. task-state.mjs transition — documented single API: validate args, write frontmatter status to <to>, invoke flip (HITL flags required for gate transitions; IMP-143 artifacts mint), which writes the receipt. Agents MUST use this path; raw FM+regen inventing edges is refused.

Alternatives Considered

Success Metrics

Scope

In scope

Out of scope / Non-Goals

Dependencies

depends_on: [TASK-CUO-303, TASK-IMP-143].

AI Authorship Disclosure

1. Description

Acceptance Criteria

Test plan

  1. bash tools/install/tests/test_task_state_engine.sh
  2. bash scripts/tests/test_regen_backlog.sh
  3. bash .cyberos/cuo/gates/run-gates.sh