Replace plan-phase.md §5.6 (a 6-branch inline UI gate) with a capability-driven
loop.render-hooks plan:pre dispatch — the FIRST gate dispatch in any workflow.
A step (ui-phase, when:workflow.ui_phase) + a new blocking gate
(when:workflow.ui_safety_gate). New ui.plan-gate check verb returns
{frontend, hasUiSpec, block}; the dispatch runs it unconditionally then fires
the active step (pipeline) or halts on the active blocking gate (manual). The
gate-handling (run check.query; halt if blocking+block) is the reusable
phase-6 template for blocking-gate cutovers.
Config semantics fixed per #1022 + maintainer call: ui_phase gates plan-time
UI-SPEC generation, ui_safety_gate gates the planning block. Common case + all
ui_phase=false cases are equivalence-preserving; the one intended change is
{ui_phase:true, ui_safety_gate:false} now auto-generating in pipelines.
Review found it broken twice (non-generic dispatch, phase-lookup divergence,
then the step-only check nested in a gate loop) — fixed; final Codex pass
verified all 8 (ui_phase,ui_safety_gate)x{pipeline,manual} cases correct.
gsd-ui-phase skill + autonomous §3a.5 untouched (§3a.5 deferred).
getRoadmapPhaseWithFallback mirrors cmdRoadmapGetPhase for lookup parity.
Closes #1026
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
438 lines
9.2 KiB
JavaScript
438 lines
9.2 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* capability-registry.cjs — generated by scripts/gen-capability-registry.cjs
|
|
* DO NOT EDIT BY HAND. Run: node scripts/gen-capability-registry.cjs --write
|
|
* ADR-894 §5 — role-partitioned Capability Registry.
|
|
*/
|
|
|
|
const capabilities = {
|
|
"audit": {
|
|
"id": "audit",
|
|
"role": "feature",
|
|
"title": "Audit",
|
|
"description": "Open-artifact audit and UAT-gap audit for milestone close gates; exposes `gsd-tools audit-uat` (cross-phase UAT outstanding items) and `gsd-tools audit-open` (structured open-artifact scan across debug, tasks, threads, todos, seeds, UAT, verification, context-questions).",
|
|
"tier": "full",
|
|
"requires": [],
|
|
"skills": [],
|
|
"agents": [],
|
|
"config": {},
|
|
"commands": [
|
|
{
|
|
"family": "audit-uat",
|
|
"module": "audit-command-router.cjs",
|
|
"router": "routeAuditUat"
|
|
},
|
|
{
|
|
"family": "audit-open",
|
|
"module": "audit-command-router.cjs",
|
|
"router": "routeAuditOpen"
|
|
}
|
|
],
|
|
"hooks": [],
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"graphify": {
|
|
"id": "graphify",
|
|
"role": "feature",
|
|
"title": "Knowledge graph",
|
|
"description": "Build, query, and inspect the project knowledge graph in `.planning/graphs/`; exposes graphify CLI subcommands (build, query, status, diff) and the /gsd-graphify skill.",
|
|
"tier": "full",
|
|
"requires": [],
|
|
"skills": [
|
|
"graphify"
|
|
],
|
|
"agents": [],
|
|
"config": {
|
|
"graphify.enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable the graphify knowledge-graph command + skill."
|
|
}
|
|
},
|
|
"commands": [
|
|
{
|
|
"family": "graphify",
|
|
"module": "graphify-command-router.cjs",
|
|
"router": "routeGraphifyCommand"
|
|
}
|
|
],
|
|
"hooks": [],
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"intel": {
|
|
"id": "intel",
|
|
"role": "feature",
|
|
"title": "Codebase intelligence",
|
|
"description": "Code-intelligence store for codebase querying, diff, snapshot, and API-surface extraction; exposes `gsd-tools intel` subcommands (query, status, update, diff, snapshot, patch-meta, validate, extract-exports, api-surface) and backs `/gsd-map-codebase` and `gsd-intel-updater`.",
|
|
"tier": "full",
|
|
"requires": [],
|
|
"skills": [],
|
|
"agents": [],
|
|
"config": {
|
|
"intel.enabled": {
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable the intel code-intelligence command."
|
|
}
|
|
},
|
|
"commands": [
|
|
{
|
|
"family": "intel",
|
|
"module": "intel-command-router.cjs",
|
|
"router": "routeIntelCommand"
|
|
}
|
|
],
|
|
"hooks": [],
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"ui": {
|
|
"id": "ui",
|
|
"role": "feature",
|
|
"title": "UI design contracts",
|
|
"description": "UI-SPEC design contract + retrospective UI audit for frontend phases.",
|
|
"tier": "full",
|
|
"requires": [],
|
|
"skills": [
|
|
"ui-phase",
|
|
"ui-review"
|
|
],
|
|
"agents": [
|
|
"gsd-ui-checker",
|
|
"gsd-ui-auditor"
|
|
],
|
|
"hooks": [],
|
|
"config": {
|
|
"workflow.ui_phase": {
|
|
"type": "boolean",
|
|
"default": true,
|
|
"description": "Enable the UI design-contract gate during planning."
|
|
},
|
|
"workflow.ui_review": {
|
|
"type": "boolean",
|
|
"default": true,
|
|
"description": "Enable the retrospective UI audit."
|
|
},
|
|
"workflow.ui_safety_gate": {
|
|
"type": "boolean",
|
|
"default": true,
|
|
"description": "Block execution on unmet UI-SPEC contracts."
|
|
}
|
|
},
|
|
"steps": [
|
|
{
|
|
"point": "plan:pre",
|
|
"ref": {
|
|
"skill": "ui-phase"
|
|
},
|
|
"produces": [
|
|
"UI-SPEC.md"
|
|
],
|
|
"consumes": [
|
|
"CONTEXT.md"
|
|
],
|
|
"when": "workflow.ui_phase",
|
|
"onError": "skip"
|
|
},
|
|
{
|
|
"point": "verify:post",
|
|
"ref": {
|
|
"skill": "ui-review"
|
|
},
|
|
"produces": [
|
|
"UI-REVIEW.md"
|
|
],
|
|
"consumes": [
|
|
"UI-SPEC.md"
|
|
],
|
|
"when": "workflow.ui_review",
|
|
"onError": "skip"
|
|
}
|
|
],
|
|
"contributions": [],
|
|
"gates": [
|
|
{
|
|
"point": "plan:pre",
|
|
"check": {
|
|
"query": "ui.plan-gate"
|
|
},
|
|
"when": "workflow.ui_safety_gate",
|
|
"blocking": true,
|
|
"onError": "halt"
|
|
},
|
|
{
|
|
"point": "execute:wave:post",
|
|
"check": {
|
|
"query": "ui.safety-gate"
|
|
},
|
|
"when": "workflow.ui_safety_gate",
|
|
"blocking": true,
|
|
"onError": "halt"
|
|
}
|
|
]
|
|
}
|
|
};
|
|
|
|
const bySkill = {
|
|
"graphify": "graphify",
|
|
"ui-phase": "ui",
|
|
"ui-review": "ui"
|
|
};
|
|
|
|
const byAgent = {
|
|
"gsd-ui-checker": "ui",
|
|
"gsd-ui-auditor": "ui"
|
|
};
|
|
|
|
const byLoopPoint = {
|
|
"discuss:pre": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"discuss:post": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"plan:pre": {
|
|
"steps": [
|
|
{
|
|
"capId": "ui",
|
|
"point": "plan:pre",
|
|
"ref": {
|
|
"skill": "ui-phase"
|
|
},
|
|
"produces": [
|
|
"UI-SPEC.md"
|
|
],
|
|
"consumes": [
|
|
"CONTEXT.md"
|
|
],
|
|
"when": "workflow.ui_phase",
|
|
"onError": "skip"
|
|
}
|
|
],
|
|
"contributions": [],
|
|
"gates": [
|
|
{
|
|
"capId": "ui",
|
|
"point": "plan:pre",
|
|
"check": {
|
|
"query": "ui.plan-gate"
|
|
},
|
|
"when": "workflow.ui_safety_gate",
|
|
"blocking": true,
|
|
"onError": "halt"
|
|
}
|
|
]
|
|
},
|
|
"plan:post": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"execute:pre": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"execute:wave:pre": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"execute:wave:post": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": [
|
|
{
|
|
"capId": "ui",
|
|
"point": "execute:wave:post",
|
|
"check": {
|
|
"query": "ui.safety-gate"
|
|
},
|
|
"when": "workflow.ui_safety_gate",
|
|
"blocking": true,
|
|
"onError": "halt"
|
|
}
|
|
]
|
|
},
|
|
"execute:post": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"verify:pre": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"verify:post": {
|
|
"steps": [
|
|
{
|
|
"capId": "ui",
|
|
"point": "verify:post",
|
|
"ref": {
|
|
"skill": "ui-review"
|
|
},
|
|
"produces": [
|
|
"UI-REVIEW.md"
|
|
],
|
|
"consumes": [
|
|
"UI-SPEC.md"
|
|
],
|
|
"when": "workflow.ui_review",
|
|
"onError": "skip"
|
|
}
|
|
],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"ship:pre": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
},
|
|
"ship:post": {
|
|
"steps": [],
|
|
"contributions": [],
|
|
"gates": []
|
|
}
|
|
};
|
|
|
|
const configKeys = {
|
|
"graphify.enabled": "graphify",
|
|
"intel.enabled": "intel",
|
|
"workflow.ui_phase": "ui",
|
|
"workflow.ui_review": "ui",
|
|
"workflow.ui_safety_gate": "ui"
|
|
};
|
|
|
|
const configSchema = {
|
|
"graphify.enabled": {
|
|
"owner": "graphify",
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable the graphify knowledge-graph command + skill."
|
|
},
|
|
"intel.enabled": {
|
|
"owner": "intel",
|
|
"type": "boolean",
|
|
"default": false,
|
|
"description": "Enable the intel code-intelligence command."
|
|
},
|
|
"workflow.ui_phase": {
|
|
"owner": "ui",
|
|
"type": "boolean",
|
|
"default": true,
|
|
"description": "Enable the UI design-contract gate during planning."
|
|
},
|
|
"workflow.ui_review": {
|
|
"owner": "ui",
|
|
"type": "boolean",
|
|
"default": true,
|
|
"description": "Enable the retrospective UI audit."
|
|
},
|
|
"workflow.ui_safety_gate": {
|
|
"owner": "ui",
|
|
"type": "boolean",
|
|
"default": true,
|
|
"description": "Block execution on unmet UI-SPEC contracts."
|
|
}
|
|
};
|
|
|
|
const runtimes = {};
|
|
|
|
const commandFamilies = {
|
|
"audit-open": {
|
|
"capId": "audit",
|
|
"module": "audit-command-router.cjs",
|
|
"router": "routeAuditOpen"
|
|
},
|
|
"audit-uat": {
|
|
"capId": "audit",
|
|
"module": "audit-command-router.cjs",
|
|
"router": "routeAuditUat"
|
|
},
|
|
"graphify": {
|
|
"capId": "graphify",
|
|
"module": "graphify-command-router.cjs",
|
|
"router": "routeGraphifyCommand"
|
|
},
|
|
"intel": {
|
|
"capId": "intel",
|
|
"module": "intel-command-router.cjs",
|
|
"router": "routeIntelCommand"
|
|
}
|
|
};
|
|
|
|
const capabilityClusters = {
|
|
"graphify": [
|
|
"graphify"
|
|
],
|
|
"ui": [
|
|
"ui-phase",
|
|
"ui-review"
|
|
]
|
|
};
|
|
|
|
const profileMembership = {
|
|
"graphify": {
|
|
"tier": "full",
|
|
"profiles": [
|
|
"full"
|
|
]
|
|
},
|
|
"ui": {
|
|
"tier": "full",
|
|
"profiles": [
|
|
"full"
|
|
]
|
|
}
|
|
};
|
|
|
|
const _requiresGraph = {
|
|
"audit": [],
|
|
"graphify": [],
|
|
"intel": [],
|
|
"ui": []
|
|
};
|
|
|
|
function requiresClosure(id) {
|
|
const visited = new Set();
|
|
const queue = [id];
|
|
while (queue.length > 0) {
|
|
const current = queue.shift();
|
|
const reqs = _requiresGraph[current] || [];
|
|
for (const req of reqs) {
|
|
if (!visited.has(req)) {
|
|
visited.add(req);
|
|
queue.push(req);
|
|
}
|
|
}
|
|
}
|
|
return visited;
|
|
}
|
|
|
|
module.exports = {
|
|
version: '1',
|
|
capabilities,
|
|
bySkill,
|
|
byAgent,
|
|
byLoopPoint,
|
|
configKeys,
|
|
configSchema,
|
|
runtimes,
|
|
commandFamilies,
|
|
capabilityClusters,
|
|
profileMembership,
|
|
requiresClosure,
|
|
};
|