Estimate: 50m · Depends on: 2.7.3, 2.7.4, 2.7.5, 2.7.6
Lock the whole type/executor model with tests over a real Postgres (the project convention; tests/helpers/db.ts truncates between tests; the only allowed vi.mock is getSession()). Cover every piece the story adds:
defaultExecutorForType returns the right executor for EVERY one of the ten enum members (a table test over the full enum — proves the TOTAL function has no hole and matches 2.7.2’s map: code/test/deploy → coding_agent; manual/decision/review → human; the four "either" types → coding_agent).type + executor; setting type on an epic/story is rejected with the typed error; type defaults to null on a row that omits it.type/executor writes the STRUCTURED fields (asserted via a repository read) and the resulting description contains NO "Type:" / "Executor:" prose; a leaf with a type but no executor gets the default; an unknown type string aborts with a clear error.type = manual returns exactly the manual leaves; type in (code, test) composes; type is null returns epics/stories/untyped; a saved-view round-trip preserves the type predicate; an unknown type value in an AST is rejected.getSession()); the default-map test iterates the FULL enum (a new member with no mapping would fail the suite).motir-core/CLAUDE.md § coverage) — every branch of the empty-input guards has a direct test.motir-core/CLAUDE.md § tests-use-real-Postgres + § coverage gate.motir-core/lib/services/workItemsService.ts + the FilterAST translator — the units asserted against.