Skip to content

capability-graph — One capability graph, two projections, and no second inventory of what this repository can do

One typed, deterministic capability graph composes the registries that already own their facts — it does not replace them — and adds typed relations between them that are inferred where a stable convention exists and declared where it does not. Both the running server and the published site render from that one graph: the static projection is the snapshot, the runtime projection is the snapshot plus live state. Navigation, overview, detail, search, the relation view and the coverage matrix are all derived, a dangling relation fails generation rather than rendering as a missing section, and a capability that exists with no documentation, no test or no enforcement is visible as such rather than indistinguishable from one that has them.

ACTIVE 6 of 31 issues done

ready
8
blocked
16
active
1
verify
0
done
6
cancelled
0

Problem

The executable already declares a capability once and projects it into MCP, HTTP, OpenAPI, Swagger, the command line and now the Cockpit (ADR 2, ADR 4, ADR 12). Everything the repository knows that is not a capability is outside that model: the skills, the rules, the decisions, the documents, the use cases, the examples, the benchmarks and the deployment are each authoritative in their own directory and related to the capabilities only in the reader's head. The Cockpit, the landing page, the navigation, the site indexes and the search each therefore assemble their own view of what exists, and every new subsystem costs an edit in each of them. The failure this produces is not visual: a capability with no documentation, no test and no enforcement looks exactly like one that has all three, because nothing resolves the relation.

Outcome

One typed, deterministic capability graph composes the registries that already own their facts — it does not replace them — and adds typed relations between them that are inferred where a stable convention exists and declared where it does not. Both the running server and the published site render from that one graph: the static projection is the snapshot, the runtime projection is the snapshot plus live state. Navigation, overview, detail, search, the relation view and the coverage matrix are all derived, a dangling relation fails generation rather than rendering as a missing section, and a capability that exists with no documentation, no test or no enforcement is visible as such rather than indistinguishable from one that has them.

Current state

The Cockpit is a projection of the registry and the index with its own graph derivation (ADR 12, feature/ai-artifacts). Web surfaces are being made discoverable from their producers (ADR 13, in flight). Skills, rules, decisions, use cases, documents, benchmarks and — after the deployment milestone — deployments are each indexed as kinds, and none of them is related to a capability by anything a machine reads.

Desired state

A contributor registers a capability in the subsystem that owns it, runs generation, and the Cockpit, the navigation, the search, the graph, the documentation index, the coverage matrix, the static snapshot and the runtime metadata all change. Nothing else has to be edited, and CI refuses a change that leaves any of them stale.

Scope

  • apps/majordomus-cli/src/graph.rs
  • apps/majordomus-cli/src/capability
  • apps/majordomus-cli/src/cockpit
  • apps/majordomus-cli/src/generate.rs
  • share/cockpit
  • site
  • docs
  • .ai/repo/rules/project
  • .ai/repo/adrs
  • .ai/repo/skills
  • test/cases
  • .github/workflows

Out of scope

  • A hand-maintained menu, page list or capability inventory in any format, including a YAML one
  • Replacing any registry that is already authoritative for what it owns
  • A client-side application framework; the Cockpit stays server-rendered with progressive enhancement
  • A layout description language with coordinates, columns or component trees as data
  • An external search service for a graph this size
  • Mutating controls in the Cockpit beyond what the existing authorisation architecture already makes safe

Acceptance criteria

  • The graph composes the existing authoritative registries and introduces no second store of what they own
  • Every node has a stable identity that survives a title change, identities are unique, and generation is deterministic over identical inputs
  • Relations are typed, inferred only from stable conventions, and a relation that does not resolve fails generation with a message naming both ends
  • The static and the runtime projections come from the same graph, and their representations are equal once runtime-only fields are removed
  • A surface that requires a running backend is not offered as usable in the static projection, and that decision comes from availability metadata rather than from any check on the page's location
  • Navigation, overview, detail, search and the coverage matrix are all derived, and adding a capability requires no edit to any of them
  • The coverage matrix reports documentation, tests, enforcement and benchmarks only where an artifact or a resolved relation supports the claim
  • The Cockpit is usable on a narrow phone viewport and its core information is present before JavaScript runs
  • Each enforcement rule introduced here has a check that CI executes, proved by a negative test

Validation

  • bash test/run.sh
  • bin/majordomus doctor
  • cargo test --workspace --all-features
  • majordomus generate --check
  • scripts/cockpit-probe

Evidence required

  • federated_graph
  • stable_identity
  • relations_resolve
  • dual_projection_parity
  • derived_surfaces
  • coverage_matrix
  • mobile_and_baseline
  • rules_enforced
  • extensibility_proved

Risks

  • Composing eight registries into one model invites a ninth store that holds the composition. The aggregate is derived on every build and committed only as a generated artifact; anything hand-edited in it is a defect.
  • Inference from names is fragile the day two subsystems name something the same way. Inference is allowed only over stable identities, and ambiguity is an explicit declaration rather than a heuristic.
  • A coverage matrix that reports what metadata claims rather than what exists is worse than no matrix, because it looks like evidence. Every green cell must resolve to an artifact.
  • The Cockpit and the web surfaces are being built on other branches right now. This milestone extends them and must land after them rather than beside them.
  • A graph view is the part everyone wants to build first and the part that matters least if the model underneath is wrong. The model comes first, and the visualisation reads it.

Issues

Each one is an execution contract with its own acceptance criteria, validation command and required evidence. The wave column is the layer of the dependency graph it sits in.

issuestatuswavedepends ontitle
I1001 DONE 0 One typed graph composes the registries that already own their facts
I1002 DONE 1 I1001 Relations are typed, inferred from stable identities, and never dangle
I1003 DONE 1 I1001 Skills, rules, decisions, documents, use cases and benchmarks enter the graph as themselves
I1004 DONE 1 I1001 Availability and visibility are metadata, not conditions in a template
I1005 DONE 2 I1002, I1004 The graph is a generated artifact with a schema and no unsafe field
I1006 READY 3 I1005 The runtime reads the graph through the registry, like every other read
I1007 READY 3 I1005 The site renders the same graph, generated once
I1008 BLOCKED 4 I1006, I1007 The two projections are proved to be the same model
I1009 READY 3 I1004, I1005 Every menu in this repository comes from one derivation
I1010 READY 3 I1005 The overview is what exists, counted rather than claimed
I1011 READY 2 I1002 The coverage matrix reports evidence, and never a green cell without one
I1012 READY 3 I1005 One detail view, assembled from what a node actually has
I1013 BLOCKED 4 I1007 Search over the graph, generated, with nothing to run
I1014 BLOCKED 4 I1002, I1007 The relation view reads the graph and holds no data of its own
I1015 ACTIVE 2 I1004 A surface with no server behind it is not offered as if it had one
I1016 BLOCKED 4 I1009 The Cockpit works on a phone and before JavaScript runs
I1017 BLOCKED 4 I1006 Live state is an overlay that degrades to nothing
I1018 BLOCKED 3 I1011, I1015 The surface rules exist as checks, proved by making them fail
I1019 BLOCKED 4 I1018 One skill runs the whole loop, and is itself in the graph
I1020 BLOCKED 4 I1002, I1007 The graph's health is answered by the doctor that already answers everything else
I1021 BLOCKED 5 I1014, I1015, I1016 A browser proves the interface, at the widths people use
I1022 BLOCKED 4 I1007 Drift in any derived surface fails the build
I1023 READY 3 I1005 Nothing private reaches a published page
I1024 BLOCKED 5 I1014 The interface has a weight, and it is measured
I1025 DONE 1 I1001 The federated model and its two projections are an architecture decision
I1026 BLOCKED 4 I1012, I1025 The architecture explains itself, from inside itself
I1027 BLOCKED 5 I1018, I1019 A synthetic capability proves the architecture instead of describing it
I1028 BLOCKED 4 I1009 The inventories this replaces are removed, not left running beside it
I1029 BLOCKED 6 I1021, I1022, I1023 The gate refuses what would silently break the interface
I1030 BLOCKED 7 I1010, I1013, I1017, I1020, I1024, I1026, I1027, I1028, I1029 The milestone is accepted on its evidence
I1031 READY 0 A served surface says which checkout it is serving

The graph

capability-graph dependency graphfrom .ai/repo/project
flowchart LR
    I1001["I1001<br/>One typed graph composes the registries that already own their facts"]:::done
    I1002["I1002<br/>Relations are typed, inferred from stable identities, and never dangle"]:::done
    I1003["I1003<br/>Skills, rules, decisions, documents, use cases and benchmarks enter the graph as themselves"]:::done
    I1004["I1004<br/>Availability and visibility are metadata, not conditions in a template"]:::done
    I1005["I1005<br/>The graph is a generated artifact with a schema and no unsafe field"]:::done
    I1006["I1006<br/>The runtime reads the graph through the registry, like every other read"]:::ready
    I1007["I1007<br/>The site renders the same graph, generated once"]:::ready
    I1008["I1008<br/>The two projections are proved to be the same model"]:::blocked
    I1009["I1009<br/>Every menu in this repository comes from one derivation"]:::ready
    I1010["I1010<br/>The overview is what exists, counted rather than claimed"]:::ready
    I1011["I1011<br/>The coverage matrix reports evidence, and never a green cell without one"]:::ready
    I1012["I1012<br/>One detail view, assembled from what a node actually has"]:::ready
    I1013["I1013<br/>Search over the graph, generated, with nothing to run"]:::blocked
    I1014["I1014<br/>The relation view reads the graph and holds no data of its own"]:::blocked
    I1015["I1015<br/>A surface with no server behind it is not offered as if it had one"]:::active
    I1016["I1016<br/>The Cockpit works on a phone and before JavaScript runs"]:::blocked
    I1017["I1017<br/>Live state is an overlay that degrades to nothing"]:::blocked
    I1018["I1018<br/>The surface rules exist as checks, proved by making them fail"]:::blocked
    I1019["I1019<br/>One skill runs the whole loop, and is itself in the graph"]:::blocked
    I1020["I1020<br/>The graph's health is answered by the doctor that already answers everything else"]:::blocked
    I1021["I1021<br/>A browser proves the interface, at the widths people use"]:::blocked
    I1022["I1022<br/>Drift in any derived surface fails the build"]:::blocked
    I1023["I1023<br/>Nothing private reaches a published page"]:::ready
    I1024["I1024<br/>The interface has a weight, and it is measured"]:::blocked
    I1025["I1025<br/>The federated model and its two projections are an architecture decision"]:::done
    I1026["I1026<br/>The architecture explains itself, from inside itself"]:::blocked
    I1027["I1027<br/>A synthetic capability proves the architecture instead of describing it"]:::blocked
    I1028["I1028<br/>The inventories this replaces are removed, not left running beside it"]:::blocked
    I1029["I1029<br/>The gate refuses what would silently break the interface"]:::blocked
    I1030["I1030<br/>The milestone is accepted on its evidence"]:::blocked
    I1031["I1031<br/>A served surface says which checkout it is serving"]:::ready
    I1001 --> I1002
    I1001 --> I1003
    I1001 --> I1004
    I1001 --> I1025
    I1002 --> I1005
    I1002 --> I1011
    I1002 --> I1014
    I1002 --> I1020
    I1004 --> I1005
    I1004 --> I1009
    I1004 --> I1015
    I1005 --> I1006
    I1005 --> I1007
    I1005 --> I1009
    I1005 --> I1010
    I1005 --> I1012
    I1005 --> I1023
    I1006 --> I1008
    I1006 --> I1017
    I1007 --> I1008
    I1007 --> I1013
    I1007 --> I1014
    I1007 --> I1020
    I1007 --> I1022
    I1009 --> I1016
    I1009 --> I1028
    I1010 --> I1030
    I1011 --> I1018
    I1012 --> I1026
    I1013 --> I1030
    I1014 --> I1021
    I1014 --> I1024
    I1015 --> I1018
    I1015 --> I1021
    I1016 --> I1021
    I1017 --> I1030
    I1018 --> I1019
    I1018 --> I1027
    I1019 --> I1027
    I1020 --> I1030
    I1021 --> I1029
    I1022 --> I1029
    I1023 --> I1029
    I1024 --> I1030
    I1025 --> I1026
    I1026 --> I1030
    I1027 --> I1030
    I1028 --> I1030
    I1029 --> I1030
    classDef done stroke:#16a34a,fill:#052e16,stroke-width:2px
    classDef active stroke:#2563eb,fill:#eff6ff,stroke-width:2px
    classDef verify stroke:#7c3aed,fill:#f5f3ff,stroke-width:2px
    classDef ready stroke:#0891b2,fill:#ecfeff,stroke-width:2px
    classDef blocked stroke:#b45309,fill:#fffbeb,stroke-width:2px
    classDef cancelled stroke:#6b7280,fill:#f9fafb,stroke-width:2px

Canonical record: .ai/repo/project/milestones/capability-graph.yaml. Read it back with majordomus plan show capability-graph.