T-14JA-capability-page-milestones-tasks
State: planning/draft · Impact: medium · Complexity: medium
A capability’s page shows only its own frontmatter and body. Show, on that page, the capabilities
it contains, the milestones that list it, and their open tasks, read through the API from
T-G5E8. This is the milestone’s “each capability shows its milestones and open tasks”.
- Capabilities have a detail page in the desktop app: route
/model/entities/capabilities/<id>, filesolutions/ontological/desktop/src-nuxt/app/pages/model/entities/[type]/[id].vue. It readsuseEntityDetailand rendersEntityDetailPanel(frontmatter table plus editable body) for any entity type. capabilitiesis onBROWSABLE_ENTITY_TYPESinapp/utils/entityRegistry.tswith prefixC, soresolveEntityLink('C-0001')returns/model/entities/capabilities/C-0001. Its test (entityRegistry.test.ts, “routes a capability to its detail page”) asserts that. So capability wikilinks already link; they do not render plain.- Two comments say the opposite and are stale: the
C… → null (capability, gated on M-0012)line in theresolveEntityLinkdoc inentityRegistry.ts, and “capability → gated plain text” in the header ofapp/components/entities/fixtures.ts. No code gates capability links now. TheentityRegistry.tscomment is fixed byT-KQ7W, which edits that file first; this task fixes only thefixtures.tsheader. - The System page graph already links to this page:
app/plugins/capability-graph.client.tssetsdetailHreftoentityDetailRoute('capabilities', node.basename, focusedProjectId). - The milestones page is
app/pages/model/milestones.vuewith detailapp/pages/model/milestones/[id].vue;withProjectinentityRegistry.tscarries?project=.resolveEntityLink('M-...')returns the milestones LIST (/model/milestones), not/model/milestones/<id>, so this task builds milestone links itself withwithProject('/model/milestones/<id>', project). - No client method returns a capability’s milestones today;
T-G5E8addsgetCapabilityRelations.
Proposed
Section titled “Proposed”The capability detail page gets a “Planning” section under the existing panel, shown only when the
entity type is capabilities. It lists:
- Contains: each direct child capability as a link to its detail page.
- Milestones: each milestone that lists the capability, with its state, linked to
/model/milestones/<id>, and under it its open tasks (state shown) linked to/model/tasks?focus=<id>. - An empty state for each list that says nothing is listed, not an error.
Chosen over the System page panel because every capability link already lands on this page (graph inspector, frontmatter wikilinks), it is keyed by project in the route, and it is a plain page that works without the graph canvas. The graph inspector keeps its link to this page and does not grow a second copy.
Approach
Section titled “Approach”- Fix the stale
fixtures.tsheader comment named in Today. TheentityRegistry.tscomment belongs toT-KQ7Wand is not touched here. - Add
useCapabilityRelations(id, project)inapp/composables/, in the style ofuseEntityDetailinuseEntities.ts(project from the route, else the focus; no ambient project; refuses withNO_PROJECT_MESSAGEwhen there is none). - Add
app/components/entities/CapabilityPlanning.vuerendering the three lists from aCapabilityRelationsvalue. Keep list shaping (sorting, empty states, link targets, milestone links built withwithProject) in a pure helper inapp/utils/so vitest covers it. - Render it from
[type]/[id].vuewhentype === 'capabilities'. - Add a story and fixture next to the other entity components.
- Add a vitest for the composable in the style of
useEntityDetail’s tests inapp/composables/useEntities.test.ts(stub client, mount a throwaway component).
| Area | Note |
|---|---|
solutions/ontological/desktop/src-nuxt/app/pages/model/entities/[type]/[id].vue | Mount the section |
solutions/ontological/desktop/src-nuxt/app/components/entities/ | New component, story, fixture |
solutions/ontological/desktop/src-nuxt/app/composables/ | New read composable |
solutions/ontological/desktop/src-nuxt/app/utils/entityRegistry.ts | Route helpers reused; comment fix is T-KQ7W’s |
solutions/ontological/desktop/src-nuxt/app/components/entities/fixtures.ts | Stale header comment |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Opening a capability that a milestone lists shows that milestone with its state, linked to its milestone page with the project carried.
- AC-2: Each open task of that milestone is listed with its state and links to
/model/tasks?focus=<id>; closed tasks are absent. - AC-3: Direct child capabilities are listed as links to their detail pages.
- AC-4: A capability with no milestones and no children shows an empty state for each list, not an error.
- AC-5: The section is not rendered for other entity types.
- AC-6: The read uses the project from the route or the focus and never an ambient one; with no project it shows the no-project message and sends no request; the composable test covers this.
- AC-7: A vitest test covers the pure helper (ordering, empty states, link targets).
- AC-8: The “capability → gated plain text” line in the
fixtures.tsheader comment is corrected. (TheentityRegistry.tscomment isT-KQ7W’s AC.) - AC-9: The component uses only
--d-*design tokens.
Verification
Section titled “Verification”- CI is the typecheck.
vue-tscis never run locally, and neither isnuxi typecheck. cd solutions/ontological/desktop/src-nuxt && bun run test(vitest)cd solutions/ontological/desktop/src-nuxt && bun run generate- Run
moon run sdf:serve(the headless server from open PR #2546, 127.0.0.1:16175), open a capability that a milestone lists (for example C-0063, listed by M-YX34) and check the section. Every/api/*request throughsdf-serveneeds thex-platform-tokenheader; paste the token in Settings first.
Out of scope
Section titled “Out of scope”- Rolling up milestones from descendant capabilities.
- Editing the capability’s
capabilitieslinks from the page. - Changes to the System page graph.
- The read API itself (
T-G5E8).
Dependencies
Section titled “Dependencies”T-G5E8provides the data.
Depends on
Section titled “Depends on”T-G5E8