Classification Layers & Status Lifecycle
traceo beginner 4 min read
ELI5
The lifecycle is a recommended path: drafted, approved, built, verified, and eventually deprecated when something replaces it. Treat it as a convention the team follows. The server does not stop you skipping a step. The classification, L1 through L4, says which layer of the design a requirement belongs to, and you can edit it.
Technical Deep Dive
Source: traceo-cat/migrations/008_reconcile_schema.sql:99-113, traceo_mcp_server/traceo_mcp_server/models.py:50-59, server.py:663-715 (update_requirement), services/core.py:823-832 (analyze_impact status weights); traceo-cat origin/main 7d647ab, read 2026-10-25
Classification (5 layers, 6 values)
| Layer | Value(s) |
|---|---|
| L1, Strategic | L1-Strategic |
| L2, Functional / Performance | L2-Functional, L2-Performance |
| L3, System | L3-System |
| L4, Implementation / Verification | L4-Implementation, L4-Verification |
L2 and L4 each have two flavours, so a non-functional spec (L2-Performance) and a test-shaped requirement (L4-Verification) can be told apart without a second column. The column is nullable in 008. update_requirement accepts classification among its editable fields (server.py:690-701), so it is not immutable after creation.
Status lifecycle: intended order, not enforced
stateDiagram-v2 [*] --> draft draft --> candidate candidate --> approved approved --> active active --> implemented implemented --> verified draft --> deprecated candidate --> deprecated approved --> deprecated active --> deprecated implemented --> deprecated verified --> deprecated deprecated --> [*]The diagram shows the convention. Neither layer enforces it:
- Database:
requirement_statusis a plain enum with no transition CHECK and no trigger guarding order. - Application:
update_requirementvalidates thatstatusis a member of the enum and nothing more. A positive search on 2026-10-25 fortransition/forward/can_transitionacrossserver.py,services/andmodels.pyfound nothing. The v1.0 claim thatcore.pywalks transitions in order was false.
The one place status order carries meaning in code is analyze_impact. It weights the current and proposed status (status_weights, services/core.py:823-832) to score how disruptive a change is.
flowchart LR U["update_requirement {status: implemented}"] --> V{"value in RequirementStatus?"} V -- no --> E["ValidationError"] V -- yes --> W["written as-is, from any prior status"] W --> T["version trigger snapshots the row"]Deletion is soft
requirements.deleted_at exists, the uniqueness of external_id only counts rows where deleted_at IS NULL, and repository reads filter on deleted_at IS NULL. There is no rejected status. A requirement you never want is deleted. One you used to want is marked deprecated, so historical traceability still resolves.
Priority is orthogonal
requirement_priority (P0-critical … P3-low, default P2-medium) is independent of status.
Key Terms
- Classification → which design layer the requirement belongs to (L1–L4). It can be edited.
- Status → where the requirement is in the review, build and verify lifecycle. The order is a convention.
- Deprecated → the “do not use” state. The row stays so audits and traces still resolve.
Q&A
Q: Can a requirement transition directly from draft to implemented?
A: Yes. Nothing stops it: the enum has no transition constraint, and update_requirement only checks that the value is a valid status. The forward order is team practice, not server policy.
Q: What is the terminal status for an obsolete requirement?
A: deprecated. The row and its relationships remain, so traceability for past reviews still resolves. Removing a row outright is a soft delete via deleted_at.
Q: Which classifications live at L2?
A: L2-Functional and L2-Performance. They share a layer in the matrix and separate functional from non-functional concerns at query time.
Examples
A reviewer moves REQ-42 straight from draft to verified by mistake. The server accepts it, and the version trigger records the change in requirement_versions. To catch the slip, read that history (get_version_history) or review in the UI. Don’t expect the API to refuse it.
neighbors on the map
- Unit Lifecycle States deciding whether a unit can be imported
- Draft Isolation Rule (FM-07) promoting a unit from review to approved and seeing FM-07 fire