## Summary - add the workspace-scoped findings hygiene report, overview signal, and supporting classification service for broken assignments and stale in-progress work - add Spec 225 artifacts and focused findings hygiene test coverage alongside the new Filament page and workspace overview wiring - align product roadmap and spec candidates around the layered canonical control catalog, CIS library, and readiness model - extend SpecKit constitution and templates with the XCUT-001 shared-pattern reuse guidance ## Notes - validation commands and implementation close-out notes are documented in `specs/225-assignment-hygiene/plan.md` and `specs/225-assignment-hygiene/quickstart.md` - this PR targets `dev` from `225-assignment-hygiene` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #264
5.7 KiB
Data Model: Assignment Hygiene & Stale Work Detection
Overview
This feature introduces no new persisted business entity. Existing finding truth, audit logs, tenant memberships, and user lifecycle truth remain canonical. The new work is one bounded derived hygiene layer over those existing records.
Existing Persistent Entities
Finding
Purpose: Canonical tenant-scoped findings workflow truth for ownership, lifecycle, and timing.
Key fields used by this feature:
idworkspace_idtenant_idstatusowner_user_idassignee_user_iddue_atin_progress_atreopened_atresolved_atclosed_atlast_seen_attimes_seen
Relationships:
- belongs to one workspace
- belongs to one tenant
- may reference one current owner user
- may reference one current assignee user
Rules relevant to hygiene:
- Only non-terminal findings participate in hygiene evaluation.
- Owner-only findings are not hygiene issues by themselves.
- Unassigned intake findings are not hygiene issues by themselves.
last_seen_atremains observation truth and must not reset the stale operator-work window.
AuditLog
Purpose: Existing audit truth for workflow actions and responsibility changes.
Key fields used by this feature:
idworkspace_idtenant_idauditable_typeauditable_idactioncreated_at
Rules relevant to hygiene:
- Existing finding workflow audit actions provide one source of workflow-activity timestamps.
- No new audit action id is required for this feature because the report is read-only.
User
Purpose: Canonical operator identity record.
Key fields used by this feature:
iddeleted_at
Rules relevant to hygiene:
- Soft-deleted users are treated as unavailable for current assignment execution.
- The feature does not add a separate availability state.
Tenant Membership / Tenant Entitlement Truth
Purpose: Current authorization truth for whether an assignee can still work inside the tenant.
Key inputs used by this feature:
- membership existence for the tenant
- current tenant visibility
- current findings-view capability in the referenced tenant
Rules relevant to hygiene:
- Broken assignment is derived from current workability, not historical assignment legitimacy.
- Hidden tenants remain excluded from rows, counts, and filters.
Derived Models
FindingHygieneIssue
Purpose: Canonical derived issue envelope used by both the report and the overview signal.
Fields:
finding_idworkspace_idtenant_idtenant_namefinding_summarystatusowner_user_idowner_nameassignee_user_idassignee_namereasons: list of hygiene reasonslast_workflow_activity_atdue_atis_overdue
Validation rules:
- The finding must be non-terminal.
finding_summary,owner_name, andassignee_nameare display-ready values resolved from the current finding and loaded user relationships; they remain derived, not persisted.reasonscontains one or more of the allowed hygiene reasons.last_workflow_activity_atis derived from workflow anchors only and must not come from observation freshness.- One finding produces one issue row even when multiple reasons apply.
HygieneReason
Purpose: Bounded derived reason vocabulary for this feature.
Allowed values:
broken_assignmentstale_in_progress
Rules:
- Reasons are derived labels, not persisted finding status.
- Reasons exist because they change operator routing and filter behavior on the hygiene surface.
FindingsHygieneOverviewSignal
Purpose: Workspace overview summary projection for fast discovery.
Fields:
headlinedescriptionunique_issue_countbroken_assignment_countstale_in_progress_countis_calmcta_labelcta_url
Rules:
- Counts are based on unique visible finding issues, not duplicated reason rows.
descriptionis a short operator-facing summary derived from broken-assignment and stale-in-progress counts; no separate severity ordering is introduced.- When
unique_issue_count = 0, the signal remains visible in a calm state with zero issues, calm descriptive copy, and the canonical CTA into the report. - The signal uses the same source query and tenant visibility truth as the canonical report.
Classification Matrix
| Reason | Trigger | Required finding state | Required visibility truth | Exclusions |
|---|---|---|---|---|
broken_assignment |
Assignee can no longer act | non-terminal, assignee_user_id present |
current user may see the finding and the assigned user is either soft-deleted or no longer tenant-entitled | owner-only, unassigned, hidden tenant |
stale_in_progress |
No meaningful workflow movement for 7 days | status = in_progress and non-terminal |
current user may see the finding | merely overdue, recently reassigned, recently reopened, or recently moved into progress |
Workflow Activity Anchor Rules
in_progress_atis the baseline activity anchor for work that actually started.reopened_atcan reset the stale window when the finding re-enters active lifecycle.- Existing workflow audit rows for
finding.assigned,finding.in_progress, andfinding.reopenedcan supersede the baseline anchor when they are newer. last_seen_atandtimes_seenremain observation truth only and must not reset the stale-work window.
Persistence Boundaries
- No new table, enum-backed persistence, or report snapshot is introduced.
- The hygiene report and overview signal are recalculated from current truth at read time.
- Repair continues through the existing finding detail mutation path and its current audit behavior.