2.6.2 Default-workflow graph-conformance suite (vitest, constant-derived)
Estimate: 30m · Depends on: 2.6.1
Add tests/workflows/transition-conformance.test.ts — a graph-complete conformance guard over the default workflow, consolidating what transition-validation.test.ts only SAMPLES. The suite derives the edge set from the defaultWorkflow.ts constant (NOT a hardcoded copy), so any future edit that adds/drops a status or transition is caught.
Drive everything through the shipped path — workItemsService.updateStatus validated by workflowsService.canTransition, against a createTestProject project (which auto-seeds the six default statuses + fifteen transitions). Assertions:
- Restricted mode (the default): for EVERY one of the 15 default transition edges, a work item sitting in the
fromstatus transitions to thetostatus successfully (and records exactly oneupdatedrevision). For EVERY non-edge in the 6×6 grid that is neither a default edge nor a self-loop,updateStatusis rejected withIllegalTransitionError. Both loops are generated from the constant — the test body enumerates statuses × statuses and partitions by membership in the default edge set. - No-op self-transitions (status → same status) succeed WITHOUT writing a revision, for all six statuses.
- Open mode: after flipping the project policy to
open(viaworkflowsService/ the 2.2 management path), the full cartesian product of (real status → real status) is accepted — proving open mode bypasses the edge set — while an unknown target key still raisesUnknownStatusError. - Terminal-set conformance: the statuses with
category: doneexactly match{ done, cancelled }(the readiness predicate’s terminal set, finding #21), derived from the seeded statuses, not hardcoded.
Keep it complementary to transition-validation.test.ts (which keeps its hand-picked cases + the atomicity/tenant-gate cases) — this file owns the exhaustive graph sweep. Do not duplicate the atomicity / cross-workspace cases.
Acceptance criteria
- New file
tests/workflows/transition-conformance.test.ts; passes underpnpm teston real Postgres. - The legal-edge and illegal-non-edge sets are computed FROM the default workflow constant; locally deleting one edge from
defaultWorkflow.tsmakes the suite fail (manually verified, noted in the PR). - All 15 default edges are each exercised through
updateStatus; every non-edge non-self pair is asserted to raiseIllegalTransitionError. - Self-transitions write no revision; open-mode accepts the full real×real product; unknown key →
UnknownStatusError. - Terminal
category: doneset asserted to equal{ done, cancelled }. - Each test
describenames the invariant it protects (per the project test convention).
Context refs
lib/workflows/defaultWorkflow.ts— the 6 statuses + 15 transitions the suite derives fromlib/services/workflowsService.ts(canTransition, policy-mode toggle),lib/services/workItemsService.ts(updateStatus)lib/workItems/errors.ts(IllegalTransitionError,UnknownStatusError)tests/workflows/transition-validation.test.ts(2.2.4) +tests/workflows/default-workflow.test.ts— the sampled coverage this completestests/fixtures/projectFixtures.ts(createTestProject),tests/helpers/db.ts