Skip to content

Plugin dashboard views have no per-task lane traits, so plugin-rendered cards read the legacy vocabulary #3003

Description

@gsxdsm

Surfaced by #3002, which widened check-inert-flag-seams to scan plugins/.

What

plugins/fusion-plugin-dependency-graph/src/GraphTaskNode.tsx:72 calls:

const isStuck = isTaskStuck(task, taskStuckTimeoutMs, lastFetchTimeMs);

Six of the seven other isTaskStuck call sites in the tree pass resolved column flags as the fourth argument. This one can't: the plugin has no lane-trait source anywhere.

  • DependencyGraph receives tasks: Task[] and nothing else;
  • the view is mounted through PluginDashboardViewContext, which carries no per-task traits;
  • TaskCardBridgeProps doesn't include them either.

So on a board with renamed lanes, stuck detection in the dependency-graph view falls back to the legacy ids and answers for a vocabulary the operator isn't using. Same class as the fan-out and ticker defects (#2993, #2996, #2997, #3001), one boundary out.

Why it wasn't just fixed in #3002

Passing the argument from what's currently in scope would pass undefined — an unsupplied optional parameter. That's the first failure shape in docs/solutions/workflow-learnings/lifecycle-conversions-that-score-as-wins.md: strictly worse than the literal it replaces, because it reads as converted, satisfies every instrument, and answers legacy forever. It's recorded as a bounded exemption in the gate with that reasoning rather than bodged.

What the fix needs

A decision from whoever owns the plugin view contract, because it changes a published surface:

  1. extend PluginDashboardViewContext (or TaskCardBridgeProps) with a per-task flags accessor — the host already builds one for the footer, footerColumnFlagsByTaskId in App.tsx:552;
  2. thread it through registerBundledPluginViewsDependencyGraphGraphTaskNode;
  3. drop the exemption in scripts/check-inert-flag-seams.mjs — it's count-bounded, so it fails the moment the site is fixed and left behind.

Per-task, not a board-wide union. blocker-fanout.ts documents why: a column id means something only relative to its own workflow, and a union serves one workflow's traits to another's card.

Scope check

The dependency-graph plugin is the only current instance — the glasses plugin references lane flags in src/cards.ts and src/routes/board-routes.ts but resolves them server-side, so it isn't affected. This is one site today and a contract gap that any future card-rendering plugin inherits.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions