## 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.6 KiB
Research: Assignment Hygiene & Stale Work Detection
Decision 1: Add a dedicated hygiene report instead of stretching My Findings or intake
Decision: Create a new canonical admin-plane page at /admin/findings/hygiene rather than adding one more fixed view to My Findings or the intake queue.
Rationale: My Findings already answers the personal execution question and intake already answers the shared unassigned-backlog question. Hygiene is a third operator question: which assigned or in-progress findings are no longer in a healthy workflow path across visible tenants. Mixing that into either existing surface would blur their current decision role.
Alternatives considered:
- Add a
Needs repairfilter toMy Findings. Rejected because broken assignments often no longer belong to the current operator, so the personal queue would still miss the cross-tenant repair problem. - Add another fixed mode to intake. Rejected because intake is explicitly about pre-assignment backlog, not unhealthy assigned work.
Decision 2: Reuse the existing workspace overview signal pattern
Decision: Extend WorkspaceOverviewBuilder with one findings hygiene signal rather than creating a new dashboard widget family.
Rationale: The repository already exposes my_findings_signal from WorkspaceOverviewBuilder, and /admin is already the accepted discoverability surface for workspace-wide findings follow-up. A second signal in the same builder keeps counts, phrasing, and drill-in behavior in one place.
Alternatives considered:
- Build a dedicated Livewire widget. Rejected because the current overview already has a signal builder pattern and this feature does not need a new widget framework.
- Make the report discoverable only through navigation. Rejected because the spec explicitly wants a small overview signal that exposes hidden workflow decay before operators start browsing deeper pages.
Decision 3: Use one narrow FindingAssignmentHygieneService
Decision: Add one focused service that owns hygiene classification, filtering, and unique-count aggregation for both the report and the overview signal.
Rationale: This feature has two real concrete consumers of the same derived truth: the canonical report and the overview signal. Duplicating issue classification in both places would drift quickly. A narrow service is the smallest justified shared seam and does not require a generic workflow-health framework.
Alternatives considered:
- Duplicate the queries in the report page and
WorkspaceOverviewBuilder. Rejected because tenant-visible scope, multi-reason counting, and stale-work anchoring would diverge under maintenance. - Introduce a broader workflow-health engine. Rejected because findings are the only real consumer today.
Decision 4: Keep broken-assignment truth bounded to current entitlement and existing user lifecycle
Decision: In v1, classify broken assignment from two existing truths only: the assignee no longer has current tenant entitlement, or the assignee user record is soft-deleted. Do not introduce absence, capacity, or shift scheduling models.
Rationale: The repository already enforces tenant membership as the true work boundary, and User already uses SoftDeletes. Those are real current truths. Anything broader would require new product modeling and would violate the spec's narrow scope.
Alternatives considered:
- Add an explicit operator-availability state or calendar. Rejected because it introduces a new workflow domain and new persistence unrelated to the current slice.
- Treat every owner-only finding as broken. Rejected because owner-only accountability is already a valid state under Spec 219 and belongs outside this hygiene slice unless assignment is actually broken.
Decision 5: Derive stale work from workflow activity, not observation freshness
Decision: Derive stale in progress from workflow activity anchors such as in_progress_at, reopened_at, and the latest existing finding workflow audit event (finding.assigned, finding.in_progress, finding.reopened) rather than from last_seen_at or generic updated_at.
Rationale: Observation pipelines update last_seen_at and may touch the record during recurring detection, which would falsely calm truly stale operator work. The stale question here is whether workflow moved, not whether the problem was re-observed by the system.
Alternatives considered:
- Use
last_seen_at. Rejected because recurring detection would reset the stale window even when no operator work happened. - Use
updated_at. Rejected because model updates are broader than workflow activity and would make stale classification depend on incidental writes. - Add a new
last_workflow_activity_atcolumn. Rejected because the spec explicitly prefers derivation over new persistence.
Decision 6: Keep repair on the existing finding detail surface
Decision: The hygiene report remains read-first and uses row click to drill into the existing tenant finding detail route for repair.
Rationale: The current findings workflow already has audited assignment and lifecycle actions on the detail surface. Recreating those actions on the hygiene report would create a second mutation surface and complicate action hierarchy, RBAC, and audit semantics.
Alternatives considered:
- Add inline reassignment actions to the report. Rejected because the report would stop being a pure repair-identification surface and would duplicate the existing finding workflow UI.
- Add a bulk repair action. Rejected because the spec explicitly keeps automation and redistribution out of scope for v1.