Originally created by: adityaharishch
Deterministic ticket-triage + board-hygiene cleanup, ending in write-back to the user's real tracker. A stale or under-specified ticket is bad for the dev on their own board (and starves Meridian's classifier), so this surfaces hygiene defects and lets the dev fix them in-app — the fix lands on Jira/Linear/GitHub/Trello/Azure, not just our mirror.
Triage engine (src/intelligence/task_triage/) — pure, no LLM. 4 buckets (Ready/NeedsDetail/LooksStale/NotSure) over 10 Definition-of-Ready rules, board-usage-guarded (a field is only "missing" if the board actually uses it). Verdicts persist in pm_task_curation; re-runs preserve human decisions/ignores. Runs after every PM sync.
Write-back (src/intelligence/ticket_update/) — each defect maps to a provider API call, redirecting only what a provider genuinely can't do in-app:
issueUpdate; GitHub Issues API + sub-issues for parent; Trello card edits; Azure work-item JSON-patchmeridian ticket-update / ticket-parentsUI — hygiene flags inline in Tasks; redesigned HygieneDialog that actually applies fixes (with epic/parent picker); global must-fix banner; cleanup page rebuilt on the shared design atoms.
Originally posted by: adityaharishch
Thanks for the review — went through all 8. Fixed the 5 real bugs in
8d04264; 3 are by-design with rationale below.Fixed
store.rsrecord_decisionroute.ts(triage and tasks)snoozed_until. Worth flagging: the live cleanup page reads/api/tasks, not/api/triage, so that path was also a no-op on reload and is fixed too.CleanupView.tsxchanges === 0 → 404), not only on network errors.run_task_linker_mlx.py_fetch_pm_tasksfalls back to the unfiltered candidate query ifpm_task_curationis absent, instead of crashing the whole/classify_sessionscall on a pre-038 DB.store.rsprune_orphanspm_tasksis empty — a transient sync gap that momentarily empties the board no longer deletes every human decision.Added two regression tests:
record_decision_errors_when_no_curation_rowandprune_skips_when_board_empty.By design (not changed)
triage_after_syncswallows errors: intentionally best-effort. Triage must never fail a sync (the board stays usable); it logs atwarn. Migration 038 ships with the daemon and runs at startup, so the missing-table case isn't reachable in practice.LooksStale: active-sprint membership is a deliberate "current work" signal. Sprints are short-lived, so a 200-day-overdue ticket in an active sprint is a data anomaly, not a misclassification worth special-casing.(-90..=0)start-date window: a ticket whose start date was 200 days ago and still hasn't moved is correctly stale. The window is intentional; recentupdated_at, due-soon, or sprint signals still rescue genuinely-active items.305 lib tests pass, clippy clean, UI builds, Python parses.
Ticket changed by: Akarsh-Hegde
Originally posted by: adityaharishch
🎉 This PR is included in version 1.51.0 🎉
The release is available on:
v1.51.0Your semantic-release bot 📦🚀