Menu

#277 feat(triage): board hygiene — flag, fix, and write back to the tracker

closed
nobody
released (243)
2026-06-12
2026-06-12
Anonymous
No

Originally created by: adityaharishch

What

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.

Pieces

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:

  • Jira full (due / assignee / label add-op / priority / story-points discovery / parent / title / description / close-via-transition)
  • Linear GraphQL issueUpdate; GitHub Issues API + sub-issues for parent; Trello card edits; Azure work-item JSON-patch
  • Parent picker is level-aware per hierarchy: Jira Epic vs parent-task (by child type), Azure Task→Story→Feature→Epic, Linear/GitHub parent issue — plus a "create new parent" deep link
  • CLI: meridian ticket-update / ticket-parents

UI — 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.

Verification

  • 303 Rust lib tests + write-back/parents unit tests pass; clippy clean; UI builds
  • Jira verified live on the KAN board (set due date, parent/epic picker against the real instance)
  • Non-Jira write paths are unit-tested but not yet live — tracked in [#276] / KAN-228

Notes

  • No migrations to a previously-shipped file; new curation columns are additive
  • Per repo rules: not merging — leaving the merge to a human reviewer

Related

Tickets: #276

Discussion

  • Anonymous

    Anonymous - 2026-06-12

    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

    # File Fix
    1 store.rs record_decision Now errors when 0 rows match instead of silently dropping the decision on an un-triaged ticket.
    2 route.ts (triage and tasks) Snooze is now honoured — both reads filter 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.
    3 CleanupView.tsx ignore/snooze/keep now revert on a rejected response (e.g. the route's existing changes === 0 → 404), not only on network errors.
    5 run_task_linker_mlx.py _fetch_pm_tasks falls back to the unfiltered candidate query if pm_task_curation is absent, instead of crashing the whole /classify_sessions call on a pre-038 DB.
    7 store.rs prune_orphans Skips when pm_tasks is 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_row and prune_skips_when_board_empty.

    By design (not changed)

    • #4 — triage_after_sync swallows errors: intentionally best-effort. Triage must never fail a sync (the board stays usable); it logs at warn. Migration 038 ships with the daemon and runs at startup, so the missing-table case isn't reachable in practice.
    • #6 — active sprint blocks 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.
    • #8 — (-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; recent updated_at, due-soon, or sprint signals still rescue genuinely-active items.

    305 lib tests pass, clippy clean, UI builds, Python parses.

     
  • Anonymous

    Anonymous - 2026-06-12

    Ticket changed by: Akarsh-Hegde

    • status: open --> closed
     
  • Anonymous

    Anonymous - 2026-06-12

    Originally posted by: adityaharishch

    🎉 This PR is included in version 1.51.0 🎉

    The release is available on:

    Your semantic-release bot 📦🚀

     

Log in to post a comment.