Skip to content

I3750 — The milestone graph reads each edge in the direction it means, in its text and in its detail panel

Make every reading of the roadmap's milestone graph say which milestone unblocks which: the edge a milestone's depends_on produces is named by the direction it is drawn in (the dependency unblocks the dependent), and the text fallback lists each edge under both of its ends, so no surface reads a dependency backwards.

READY wave 0 · p1 · implementation profile · parallel safe

Part of truthful-plan-surfaces — The plan's surfaces are inferred from delivery, and nothing they show is typed beside the repository.

Ready. Every dependency is done, so majordomus plan start I3750 will be accepted.

Objective

Make every reading of the roadmap's milestone graph say which milestone unblocks which: the edge a milestone's depends_on produces is named by the direction it is drawn in (the dependency unblocks the dependent), and the text fallback lists each edge under both of its ends, so no surface reads a dependency backwards.

Why

Found on 2026-10-20 by the owner-ordered audit of /roadmap/ (campaign defect D6). The text form of the graph on /roadmap/ and /cs/roadmap/ read 'foundation requires runtime-adapters' for all 39 edges, while runtime-adapters is the milestone that depends on foundation, and site/graph.js's detail panel read the same inversion ('requires -> runtime-adapters' under foundation).

Current state

scripts/generate-site-data:1861-1866 writes roadmap-graph.json with edges {source: <the dependency>, target: <the dependent>, kind: 'requires'} and defines requires as 'the target cannot begin until the source is accepted', a meaning read from the target. site/templates/partials/graph.html prints, under each node, its outgoing edges as '<kind> <target>', and site/graph.js prints '<kind> -> <target>' under the source, so both read 'source requires target'. Only the roadmap graph uses the requires kind.

Desired state

The roadmap's edges carry kind 'unblocks' (the source unblocks the target), which reads correctly from the source as every other graph's kinds do. The text fallback lists each edge under its source as 'unblocks -> <target>' and under its target as '<source> unblocks -> this', the same two readings graph.js's detail panel gives, each with a data-graph-edge attribute naming source, kind and target.

Scope

  • scripts/generate-site-data
  • site/templates/partials/graph.html
  • test/cases/3723_the_graph_text_reads_each_edge_its_way.sh

Out of scope

  • The edge kinds of the other graphs (map, evidence, why, features), which already read from their source
  • Which milestones depend on which, which stays the plan's

Dependencies

None. This issue is a root of the graph.

Acceptance criteria

  • Every edge of roadmap-graph.json has kind unblocks, and its target's depends_on names its source
  • On the rendered /roadmap/, every edge is listed under its source as 'unblocks -> target' and under its target as 'source unblocks -> this'
  • Negative: no edge listed in the text fallback carries the kind requires, so the inverted reading appears nowhere

Validation

  • bash test/run.sh 3723_the_graph_text_reads_each_edge_its_way 12_site_build
  • majordomus plan validate

Evidence required

  • test_the_graph_text_reads_each_edge_its_way

Evidence

None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.

Timeline

started
—
verified
—
completed
—

Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.

Canonical record: .ai/repo/project/issues/I3750.yaml. Read it back with majordomus plan show I3750.

Searches the titles and descriptions of every page this site publishes.