MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-400

6.11.3 Schema + the read-exclusion-everywhere invariant

Done
Description

Estimate: 70m · Depends on: 6.11.2

⚠️ Partially superseded (Yue, 2026-06-14). The externalSubmitter embedded columns added here are now dead — intake is signed-in only, so attribution is always a real submittedByUserId. The columns remain in the DB until 6.11.10 drops them (ADR amend + migration); this card kept as the record of what shipped. submittedByUserId + snoozedUntil + the exclusion invariant are unchanged.

Implement the triage marker on work_item and enforce the exclusion invariant across EVERY normal read (the load-bearing correctness work of this story). Per 6.11.2:

  • Schema: add the triage marker (a triagedAt: DateTime? / isTriage column per the ADR) + snoozedUntil: DateTime? + the submitter-attribution columns (submittedByUserId nullable @relation; externalSubmitter embedded fields) to work_item, with a migration and a partial index supporting the cheap exclusion predicate + the queue read. Model every FK as a Prisma @relation (CLAUDE.md migration rule — no raw-SQL-only FK).
  • Central exclusion: thread a single shared "not-in-triage" where fragment (or a repository default scope) through EVERY normal list read so the predicate is defined once: the issue tree, every board column read, every list/saved-view read, the ready-set read, and the 6.1.1 FilterAST search compilation. A triage item (and a snoozed item, in the inbox sense) is absent from all of them.
  • The queue read: a new repository read + service method returning ONLY triage items for a project, paginated/cursor’d (finding #57 — never load-all), excluding currently-snoozed items, newest-first, with submitter attribution.

All reads stay 4-layer (Route→Service→Repository→Prisma); the queue and exclusion live in the repository read layer so no future read can bypass them.

Acceptance criteria

  • The migration adds the triage marker + snooze + submitter columns with the supporting index; prisma migrate dev reports no drift (every FK modelled as @relation).
  • The exclusion predicate is defined ONCE and applied to the tree, every board read, every list read, the ready set, and FilterAST search — verified by the 6.11.8 tests at each read.
  • The triage-queue read returns ONLY triage items for the project, paginated, excluding snoozed items, with submitter attribution; no load-all.
  • 4-layer respected; no raw Prisma outside repositories; the queue read goes through a service.

Context refs

  • 6.11.2 — the model decision this implements (marker shape + the reads-to-exclude checklist).
  • motir-core/lib/repositories/workItemRepository.ts + the tree / board / ready-set read paths — where the shared exclusion fragment threads in.
  • 6.1.1 FilterAST search compiler — the search read to extend with the exclusion.
  • motir-core/CLAUDE.md § 4-layer + § migration FK-as-relation rule.