Skip to content

New command group: hadron coding — lint the preflight router and the review checklist tree (coding review lint, coding preflight lint) #325

Description

@shadowbrush

Why

The review:* checklist trees and the preflight routers are executable infrastructure, not prose. tasks:review-changes triages checks by reading each one's Applies when … edge label back to the review parent; preflight routes symptom → finding via its outgoing edges. When one of those edges is malformed, the check or route is silently skipped. The node still exists, still looks maintained, and never fires again.

There is currently no way to detect that except by hand — which is how it went unnoticed. A manual audit of two memories this week found:

hadronmemory.com::hadron-portal — 7 of 24 checks had an edge label carrying no condition at all (bare applies-when, and one truncated Applies when with nothing after it). Every one was reachable only by opening the node, so a reviewer scanning the parent's Referenced-by list had nothing to match a diff against.

micromentor.org::mmdata — ~45 checks were fine, but 4 were broken in three distinct ways:

  • 2 labelled child-of instead of a trigger (posthog-backend-vs-app-event-routing, role-vs-group-ident-vocabulary)
  • 1 whose label was a raw derived edge loc, review:input-type-graphql-type:rel:review — with 4 more :rel:-shaped labels in the same branch, suggesting one bad batch
  • 1 (format-sources) triggered on "Applies when Dart sources change" while living in the TypeScript backend memory — it can never match a diff in the repo whose memory it's in

(Filed as micromentor-team/mmdata#1599.)

These are all mechanically detectable. That's the ask.

Proposed surface

A new top-level group alongside the existing task / node / edge / memory groups:

hadron coding review lint      [-m <memory>] [--json] [--fix]
hadron coding preflight lint   [-m <memory>] [--json]

coding as the parent because these lint the coding-workflow graph (review gates, preflight routing, coding-guidelines cross-links) rather than arbitrary nodes — leaving room for coding review ls, coding review add (the tasks:add-review-node procedure), coding preflight ls, etc.

coding review lint

For every node under the review parent in the target memory, check:

Check Rationale
Has an edge to the review parent at all Missing ⇒ the check is invisible to tasks:review-changes. The highest-severity finding.
Edge label is a condition — starts Applies when, more than the bare stem Catches child-of, applies-when, related, and the truncated Applies when.
Label isn't a loc — reject anything matching the <loc>:rel:<loc> shape Catches the leaked-identity batch above.
Label isn't a near-duplicate of another check's Two checks with the same trigger usually means one was cloned and not re-pointed.
Description carries the condition too hadron_find_nodes / list output surfaces the description, so a description without a trigger is a second blind spot (use-scoped-message-helpers had exactly this).
Trigger doesn't name a foreign toolchain Heuristic, warn-only: flag a Dart/Flutter trigger in a TS memory and vice-versa. Would have caught the misfiled format-sources.
seq is unique among siblings Duplicate seq makes ordering non-deterministic.

coding preflight lint

For the preflight node's outgoing routes:

  • every target resolves (no route to a deleted/superseded node — CLAUDE.md's own words: "stale routing is worse than missing routing")
  • labels are action-phrased (to do X …), matching preflight's convention
  • no route points at a node that has since been retired/tombstoned
  • flag routes to nodes that moved memory (the portal findings migrating out of ::dev is exactly this churn)

Flags

  • --json for CI consumption — this is the shape that lets a repo gate its own memory hygiene in a workflow.
  • --fix on coding review lint for the mechanical subset only: promote the node's description sentence into the edge label when the description carries a trigger and the label doesn't. That covers most of the portal's 7. Everything else (a child-of on a node whose description has no condition either) needs a human and should just be reported.
  • Non-zero exit when any error-severity finding is present; warnings alone exit 0.

⚠️ Implementation hazard: edges

Changing an edge label is currently dangerous. MCP exposes only hadron_create_edge — there is no update or delete — so the only route is hadron_update_node(edges:), which replaces the node's entire outgoing edge set. A naive --fix that rewrites one label will silently destroy the node's documented-by / relates-to edges. Four of the seven portal nodes had exactly those siblings.

The CLI talks to GraphQL directly, where updateEdge(edgeRef:) and deleteEdge(edgeRef:) do exist — so --fix should use updateEdge and must never go through a whole-node write. Tracked upstream as hadron-memory/hadron-server#835.

Prior art in this repo

hadron spec lint already exists for the spec corpus (per the add-spec skill). This is the same idea for the coding-workflow graph, and should match its output shape and exit-code conventions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions