Skip to content
Merged
86 changes: 46 additions & 40 deletions ROADMAP.md

Large diffs are not rendered by default.

86 changes: 45 additions & 41 deletions dag/gunbc/roadmap_authority.dag

Large diffs are not rendered by default.

24 changes: 17 additions & 7 deletions dag/gunbc/roadmap_emit.dag
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,34 @@ import gunbc.roadmap_model {
SectionElement, Prose, Group, SectionProse, SectionGroup,
}

import gunbc.roadmap_status { RoadmapItem, DerivableLine, AuthoredLine, PlainLine, item_is_done, signoff_accepts, signoff_by }
import gunbc.roadmap_status { RoadmapItem, DerivableLine, AuthoredLine, PlainLine, SupersededLine, item_is_done, item_superseded_by, signoff_accepts, signoff_by }

fn roadmap_max_depth() -> Int { 8 }

fn node_is_superseded(rn: RoadmapNode) -> Bool {
!(item_superseded_by(item: rn.line) == "")
}

fn node_is_done(rn: RoadmapNode, merged: List<Int>) -> Bool {
signoff_accepts(s: rn.signoff)
signoff_accepts(s: rn.signoff) || node_is_superseded(rn: rn)
}

fn node_evidence_present(rn: RoadmapNode, merged: List<Int>) -> Bool {
item_is_done(item: rn.line, merged: merged)
}

fn signoff_suffix_inlines(rn: RoadmapNode, merged: List<Int>) -> List<MarkdownInline> {
if signoff_accepts(s: rn.signoff) {
[TextInline { text: concat(" — ✓ signed off: ", signoff_by(s: rn.signoff)) }]
if node_is_superseded(rn: rn) {
[]
} else {
if node_evidence_present(rn: rn, merged: merged) {
[TextInline { text: " — ⏳ awaiting sign-off" }]
if signoff_accepts(s: rn.signoff) {
[TextInline { text: concat(" — ✓ signed off: ", signoff_by(s: rn.signoff)) }]
} else {
[]
if node_evidence_present(rn: rn, merged: merged) {
[TextInline { text: " — ⏳ awaiting sign-off" }]
} else {
[]
}
}
}
}
Expand Down Expand Up @@ -67,6 +75,7 @@ fn line_inlines(line: RoadmapItem) -> List<MarkdownInline> {
)
AuthoredLine { done: _, content } => [TextInline { text: content }]
PlainLine { content } => [TextInline { text: content }]
SupersededLine { by, content } => [TextInline { text: concat(concat("~~", content), concat("~~ **superseded →** ", by)) }]
}
}

Expand All @@ -75,6 +84,7 @@ fn node_is_plain(rn: RoadmapNode) -> Bool {
PlainLine { content: _ } => true
DerivableLine { prs: _, title: _, description: _ } => false
AuthoredLine { done: _, content: _ } => false
SupersededLine { by: _, content: _ } => false
}
}

Expand Down
36 changes: 26 additions & 10 deletions dag/gunbc/roadmap_page.dag
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import gunbc.roadmap_model {
Intricacy, IntricacyLow, IntricacyMedium, IntricacyHigh,
Volume, VolumeSmall, VolumeMedium, VolumeLarge,
}
import gunbc.roadmap_status { RoadmapItem, DerivableLine, AuthoredLine, PlainLine, item_is_done, signoff_accepts, signoff_by }
import gunbc.roadmap_status { RoadmapItem, DerivableLine, AuthoredLine, PlainLine, SupersededLine, item_superseded_by, item_is_done, signoff_accepts, signoff_by }
import gunbc.roadmap_document { RoadmapDocument, RoadmapSection }
import gunbc.roadmap_authority { roadmap_authority, authored_merged_prs }
import gunbc.roadmap_spawner { spawn_frontier, SpawnFrontier }
Expand Down Expand Up @@ -164,14 +164,18 @@ fn el_class(tag: String, cls: String, children: List<MarkupNode>) -> MarkupNode
}

fn node_status_symbol(rn: RoadmapNode, merged: List<Int>) -> String {
if signoff_accepts(s: rn.signoff) {
"done"
} else {
if item_is_done(item: rn.line, merged: merged) {
"review"
if item_superseded_by(item: rn.line) == "" {
if signoff_accepts(s: rn.signoff) {
"done"
} else {
"open"
if item_is_done(item: rn.line, merged: merged) {
"review"
} else {
"open"
}
}
} else {
"superseded"
}
}

Expand Down Expand Up @@ -204,6 +208,7 @@ fn line_title(line: RoadmapItem) -> String {
DerivableLine { prs, title, description } => title
AuthoredLine { done, content } => content
PlainLine { content } => content
SupersededLine { by: _, content } => content
}
}

Expand Down Expand Up @@ -247,10 +252,20 @@ fn sizing_badge(rn: RoadmapNode) -> List<MarkupNode> {
}
}

fn superseded_badge(rn: RoadmapNode) -> List<MarkupNode> {
let by = item_superseded_by(item: rn.line)
if by == "" {
[]
} else {
[ el_class("span", "superseded-by", [ txt(concat("→ ", by)) ]) ]
}
}

data dispatch_button_note: String = "The launch button (roadmap belt A, operator 2026-07-20: manual click-to-dispatch). Rendered on every NOT-signoff-done node (open OR review -- DONE = the operator's signoff, never a merged PR), carrying data-node = the node id. The client script POSTs to /dispatch/NODE and reads belt B's response contract: the `status` member of belt_dispatch_result_json_value, with the ok-set DERIVED from belt_dispatch_ok_status_labels (one authority with the serve JSON -- DESIGN section 3). The retired belt-A `ok`/`node` shape is gone: reading it while B answered `status` made EVERY successful click render 'failed' (found live 2026-07-23; the page witness holds a RED on `j.ok` so the fork cannot silently return). The JS is authored escape-free (no < > &) so it survives std.markup text escaping intact -- the same way roadmap_css() rides inside <style>; no raw-text-element modeling needed for this payload."

fn dispatch_button_nodes(rn: RoadmapNode, merged: List<Int>) -> List<MarkupNode> {
if node_status_symbol(rn: rn, merged: merged) == "done" {
let status = node_status_symbol(rn: rn, merged: merged)
if status == "done" || status == "superseded" {
[]
} else {
[
Expand Down Expand Up @@ -303,7 +318,7 @@ fn node_li(rn: RoadmapNode, nodes: List<RoadmapNode>, edges: List<RoadmapEdge>,
el_class("span", concat("status status-", status), [ txt(status) ]),
el_class("span", "title", title_nodes(line: rn.line)),
],
owner_badge(rn: rn),
concat(superseded_badge(rn: rn), owner_badge(rn: rn)),
),
concat(sizing_badge(rn: rn), carrier_links(carriers: rn.carriers)),
)
Expand Down Expand Up @@ -368,7 +383,7 @@ fn frontier_flat_node_li(rn: RoadmapNode, merged: List<Int>) -> MarkupNode {
el_class("span", concat("status status-", status), [ txt(status) ]),
el_class("span", "title", title_nodes(line: rn.line)),
],
owner_badge(rn: rn),
concat(superseded_badge(rn: rn), owner_badge(rn: rn)),
),
concat(sizing_badge(rn: rn), carrier_links(carriers: rn.carriers)),
)
Expand All @@ -395,6 +410,7 @@ fn roadmap_frontier_markup(frontier: SpawnFrontier, merged: List<Int>) -> Markup
frontier_bucket_markup(label: "Ready", cls: "ready", items: frontier.ready, merged: merged),
frontier_bucket_markup(label: "Upcoming", cls: "upcoming", items: frontier.upcoming, merged: merged),
frontier_bucket_markup(label: "Done", cls: "done", items: frontier.done, merged: merged),
frontier_bucket_markup(label: "Superseded", cls: "superseded", items: frontier.superseded, merged: merged),
])
}

Expand Down
16 changes: 15 additions & 1 deletion dag/gunbc/roadmap_spawner.dag
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import gunbc.roadmap_model {
SectionElement, Prose, Group, SectionGroup,
RoadmapParent, TopLevel, UnderParent, roadmap_parent,
}
import gunbc.roadmap_status { RoadmapItem, DerivableLine, AuthoredLine, PlainLine, item_is_done }
import gunbc.roadmap_status { RoadmapItem, DerivableLine, AuthoredLine, PlainLine, SupersededLine, item_is_done, item_superseded_by }
import gunbc.roadmap_document { RoadmapDocument, RoadmapSection }
import gunbc.roadmap_authority { roadmap_authority, authored_merged_prs }
import extdeps.languages.json.emit {
Expand Down Expand Up @@ -102,6 +102,7 @@ type SpawnFrontier {
ready: List<RoadmapNode>
upcoming: List<RoadmapNode>
done: List<RoadmapNode>
superseded: List<RoadmapNode>
}

fn spawn_frontier(doc: RoadmapDocument, merged: List<Int>) -> SpawnFrontier {
Expand All @@ -111,6 +112,7 @@ fn spawn_frontier(doc: RoadmapDocument, merged: List<Int>) -> SpawnFrontier {
ready: next_spawnable(doc: doc, merged: merged),
upcoming: nodes |> filter(n => node_is_upcoming(n: n, nodes: nodes, edges: edges, merged: merged)),
done: nodes |> filter(n => node_is_frontier_done(n: n, merged: merged)),
superseded: nodes |> filter(n => !(item_superseded_by(item: n.line) == "")),
}
}

Expand Down Expand Up @@ -152,6 +154,11 @@ fn acceptance_json_value(a: Acceptance, line: RoadmapItem) -> JsonValue {
json_kv(key: "kind", value: json_string(s: "prs_merged_model_error")),
json_kv(key: "prs", value: json_array(elements: [])),
])
SupersededLine { by: _, content: _ } =>
json_object(members: [
json_kv(key: "kind", value: json_string(s: "prs_merged_model_error")),
json_kv(key: "prs", value: json_array(elements: [])),
])
}
ManualAcceptance =>
json_object(members: [
Expand All @@ -165,6 +172,7 @@ fn node_title(item: RoadmapItem) -> String {
DerivableLine { prs: _, title, description: _ } => title
AuthoredLine { done: _, content } => content
PlainLine { content } => content
SupersededLine { by: _, content } => content
}
}

Expand Down Expand Up @@ -276,6 +284,12 @@ fn roadmap_dispatch_json_value(doc: RoadmapDocument, merged: List<Int>) -> JsonV
])
))),
json_kv(key: "done", value: json_array(elements: frontier.done |> map(n => json_string(s: n.node)))),
json_kv(key: "superseded", value: json_array(elements: frontier.superseded |> map(n =>
json_object(members: [
json_kv(key: "node_id", value: json_string(s: n.node)),
json_kv(key: "superseded_by", value: json_string(s: item_superseded_by(item: n.line))),
])
))),
])
}

Expand Down
13 changes: 13 additions & 0 deletions dag/gunbc/roadmap_status.dag
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ type RoadmapItem

| PlainLine { content: String }

| SupersededLine { by: String, content: String }

type Signoff
= Unsigned
| SignedOff { by: String, works: Bool, scope_equivalent: Bool, as_expected: Bool }
Expand Down Expand Up @@ -55,6 +57,16 @@ fn item_is_done(item: RoadmapItem, merged: List<Int>) -> Bool {
DerivableLine { prs, title: _, description: _ } => prs_all_merged(prs: prs, merged: merged)
AuthoredLine { done, content: _ } => done
PlainLine { content: _ } => false
SupersededLine { by: _, content: _ } => true
}
}

fn item_superseded_by(item: RoadmapItem) -> String {
match item {
DerivableLine { prs: _, title: _, description: _ } => ""
AuthoredLine { done: _, content: _ } => ""
PlainLine { content: _ } => ""
SupersededLine { by, content: _ } => by
}
}

Expand All @@ -68,6 +80,7 @@ fn status_drift(item: RoadmapItem, committed_box: Bool, merged: List<Int>) -> Dr
match item {
AuthoredLine { done: _, content: _ } => Underivable
PlainLine { content: _ } => Underivable
SupersededLine { by: _, content: _ } => Underivable
DerivableLine { prs, title: _, description: _ } =>
if committed_box == prs_all_merged(prs: prs, merged: merged) {
Clean
Expand Down
14 changes: 14 additions & 0 deletions dag/gunbc/roadmap_style.dag
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ fn roadmap_instance_rules() -> List<BuildRule> {
StaticRule { selector: ".status-done", decls: [
role_decl(prop: "color", r: TextDimRole),
] },
StaticRule { selector: ".status-superseded", decls: [
role_decl(prop: "color", r: TextDimRole),
decl(prop: "border-style", value: "dashed"),
] },
StaticRule { selector: ".node-superseded > .title", decls: [
decl(prop: "text-decoration", value: "line-through"),
role_decl(prop: "color", r: TextDimRole),
] },
StaticRule { selector: ".superseded-by", decls: [
role_decl(prop: "color", r: TextDimRole),
decl(prop: "font-size", value: "11px"),
decl(prop: "font-family", value: "'JetBrains Mono', monospace"),
decl(prop: "margin-left", value: "6px"),
] },
StaticRule { selector: ".title", decls: [
decl(prop: "margin-right", value: "8px"),
] },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ data lift_parity_note: String = "Phase-A emission-identical witness (design-regi
data moodboard_css_lift_parity_digest: String = "5f2596b1693465d7"
data moodboard_html_lift_parity_digest: String = "9252e67e6cf24375"
data accent_study_html_lift_parity_digest: String = "90e876af9e5173db"
data roadmap_css_lift_parity_digest: String = "b314972719a0ed4e"
data roadmap_css_lift_parity_digest: String = "28052f4fb9e52624"
data moodboard_thesis_themes_lift_parity_digest: String = "69e68066c49667f9"

fn emission_content_digest(s: String) -> String {
Expand Down
4 changes: 2 additions & 2 deletions dag/test/claim/roadmap_authority_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ fn witness_a_prose_verbatim() -> Bool {
fn witness_b_ordered_interleaving() -> Bool {
let o = out()
string_contains(s: o, pattern: "[seed census](docs/plans/seed-shrink-census.md)\n\nGround truth (2026-07-05):")
&& string_contains(s: o, pattern: "until the §2 compile-clean work lands.\n\n**◆ Milestones:** front-end ✓")
&& string_contains(s: o, pattern: "so the walls are CI-proven now.\n\n**◆ Milestones:** front-end ✓")
&& string_contains(s: o, pattern: "[host-converge inventory](docs/plans/host-converge-inventory.md)\n\n**The core design rule (operator-signed, 2026-07-01):**")
&& string_contains(s: o, pattern: "Phase 2, earned by receipts.\n\n**◆ Milestones:** OOM root-caused")
}
Expand Down Expand Up @@ -103,7 +103,7 @@ fn witness_shelf_is_uncheckboxed() -> Bool {
fn witness_audit_lane_present() -> Bool {
let o = out()
string_contains(s: o, pattern: "**Audit — green by execution, red by perturbation:**")
&& string_contains(s: o, pattern: "**affected-set lens** *(the operator's named example)*")
&& string_contains(s: o, pattern: "**affected-set lens — discharged by a standing mechanism (audit 2026-07-23)**")
&& string_contains(s: o, pattern: "A mechanism claim without a red-control is *unverified*")
&& string_contains(s: o, pattern: "**artifact-freshness gate**")
&& string_contains(s: o, pattern: "**one tree, one verdict**")
Expand Down
2 changes: 1 addition & 1 deletion dag/test/claim/roadmap_belt_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fn ready_node(id: String) -> RoadmapNode {
}

fn frontier_ready(ids: List<String>) -> SpawnFrontier {
SpawnFrontier { ready: map(ids, id => ready_node(id: id)), upcoming: [], done: [] }
SpawnFrontier { ready: map(ids, id => ready_node(id: id)), upcoming: [], done: [], superseded: [] }
}

fn cap(n: Int) -> BeltCapacity { BeltCapacity { max_concurrent: n } }
Expand Down
20 changes: 19 additions & 1 deletion dag/test/claim/roadmap_emit_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module test.claim.roadmap_emit
import extdeps.languages.markdown { serialize_markdown_source }
import gunbc.roadmap_emit { project_roadmap_section }
import gunbc.roadmap_model { RoadmapNodeId, RoadmapNode, RoadmapEdge, Pointer, NodeSizing, Unsized, SectionElement, section_group }
import gunbc.roadmap_status { RoadmapItem, DerivableLine, AuthoredLine, Signoff, Unsigned, SignedOff }
import gunbc.roadmap_status { RoadmapItem, DerivableLine, AuthoredLine, SupersededLine, Signoff, Unsigned, SignedOff }
import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly }

data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly
Expand Down Expand Up @@ -89,10 +89,28 @@ fn witness_child_derived_unchecked_when_unmerged() -> Bool {
&& !string_contains(s: out, pattern: "⏳ awaiting sign-off")
}

fn superseded_child_node() -> RoadmapNode {
RoadmapNode {
node: child_id,
line: SupersededLine { by: "successor-lane", content: "**PR-checkbox status**" },
carriers: [],
sizing: Unsized,
owner: "",
signoff: Unsigned,
}
}

fn witness_superseded_checked_struck_no_signoff_suffix() -> Bool {
let out = emit_nodes(nodes: [parent_node(), superseded_child_node()], merged: [])
string_contains(s: out, pattern: "[x] ~~**PR-checkbox status**~~ **superseded →** successor-lane")
&& !string_contains(s: out, pattern: "⏳ awaiting sign-off")
}

test fn roadmap_emit_witnesses() -> Bool {
witness_heading()
&& witness_parent_authored_box_and_link()
&& witness_child_merged_unsigned_awaiting_signoff()
&& witness_child_signed_checked()
&& witness_child_derived_unchecked_when_unmerged()
&& witness_superseded_checked_struck_no_signoff_suffix()
}
Loading
Loading