@jakkrichm/create-nexus-devflow 2.0.27 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -7
- package/dist/bin/create-nexus-devflow.d.ts +5 -1
- package/dist/bin/create-nexus-devflow.js +247 -4
- package/dist/bin/create-nexus-devflow.js.map +1 -1
- package/dist/lib/branch-context.d.ts +39 -0
- package/dist/lib/branch-context.js +196 -0
- package/dist/lib/branch-context.js.map +1 -0
- package/dist/lib/code-graph.d.ts +30 -0
- package/dist/lib/code-graph.js +209 -0
- package/dist/lib/code-graph.js.map +1 -0
- package/dist/lib/context-slicer.d.ts +31 -0
- package/dist/lib/context-slicer.js +234 -0
- package/dist/lib/context-slicer.js.map +1 -0
- package/dist/lib/current-work.js +4 -2
- package/dist/lib/current-work.js.map +1 -1
- package/dist/lib/dashboard-page.d.ts +1 -1
- package/dist/lib/dashboard-page.js +140 -56
- package/dist/lib/dashboard-page.js.map +1 -1
- package/dist/lib/dashboard-snapshot.d.ts +13 -0
- package/dist/lib/dashboard-snapshot.js +24 -6
- package/dist/lib/dashboard-snapshot.js.map +1 -1
- package/dist/lib/dashboard.js +38 -0
- package/dist/lib/dashboard.js.map +1 -1
- package/dist/lib/drift-reconciler.d.ts +38 -0
- package/dist/lib/drift-reconciler.js +155 -0
- package/dist/lib/drift-reconciler.js.map +1 -0
- package/dist/lib/gatekeeper.d.ts +1 -0
- package/dist/lib/gatekeeper.js +30 -1
- package/dist/lib/gatekeeper.js.map +1 -1
- package/dist/lib/git-hooks.js +41 -16
- package/dist/lib/git-hooks.js.map +1 -1
- package/dist/lib/ide-extension.d.ts +38 -0
- package/dist/lib/ide-extension.js +61 -0
- package/dist/lib/ide-extension.js.map +1 -0
- package/dist/lib/mcp.d.ts +36 -0
- package/dist/lib/mcp.js +653 -0
- package/dist/lib/mcp.js.map +1 -0
- package/dist/lib/project-metadata.d.ts +1 -1
- package/dist/lib/project-metadata.js +3 -2
- package/dist/lib/project-metadata.js.map +1 -1
- package/dist/lib/status.d.ts +1 -1
- package/dist/lib/status.js +4 -4
- package/dist/lib/status.js.map +1 -1
- package/dist/lib/swarm-orchestrator.d.ts +31 -0
- package/dist/lib/swarm-orchestrator.js +134 -0
- package/dist/lib/swarm-orchestrator.js.map +1 -0
- package/dist/lib/update.js +7 -3
- package/dist/lib/update.js.map +1 -1
- package/dist/lib/webview-studio.d.ts +8 -0
- package/dist/lib/webview-studio.js +463 -0
- package/dist/lib/webview-studio.js.map +1 -0
- package/dist/lib/workflow-state.js +24 -8
- package/dist/lib/workflow-state.js.map +1 -1
- package/package.json +1 -1
- package/template/.agents/skills/adopt/SKILL.md +58 -5
- package/template/.agents/skills/doctor/SKILL.md +23 -16
- package/template/.agents/skills/implement/SKILL.md +2 -2
- package/template/.agents/skills/onboard/SKILL.md +18 -17
- package/template/.agents/skills/rollback/SKILL.md +1 -1
- package/template/.claude/skills/00-explore/SKILL.md +2 -2
- package/template/.claude/skills/10-define/SKILL.md +2 -2
- package/template/.claude/skills/20-spec/SKILL.md +1 -2
- package/template/.claude/skills/30-plan/SKILL.md +1 -2
- package/template/.claude/skills/40-execute/SKILL.md +2 -2
- package/template/.claude/skills/50-verify/SKILL.md +2 -2
- package/template/.claude/skills/60-report/SKILL.md +2 -2
- package/template/.claude/skills/70-deliver/SKILL.md +2 -2
- package/template/.claude/skills/adopt/SKILL.md +191 -75
- package/template/.claude/skills/audit/SKILL.md +267 -133
- package/template/.claude/skills/autopilot/SKILL.md +226 -167
- package/template/.claude/skills/brainstorm/SKILL.md +62 -0
- package/template/.claude/skills/brief/SKILL.md +93 -92
- package/template/.claude/skills/check/SKILL.md +96 -76
- package/template/.claude/skills/ci/SKILL.md +140 -61
- package/template/.claude/skills/complete/SKILL.md +156 -101
- package/template/.claude/skills/convert-any-to-md/SKILL.md +2 -2
- package/template/.claude/skills/convert-any-to-md/references/setup.md +29 -0
- package/template/.claude/skills/convert-any-to-md/scripts/convert_any_to_md.py +487 -0
- package/template/.claude/skills/convert-any-to-md/scripts/requirements.txt +3 -0
- package/template/.claude/skills/debug/SKILL.md +124 -49
- package/template/.claude/skills/devflow/SKILL.md +9 -3
- package/template/.claude/skills/discovery/SKILL.md +150 -129
- package/template/.claude/skills/doctor/SKILL.md +195 -72
- package/template/.claude/skills/feature/SKILL.md +195 -151
- package/template/.claude/skills/fix/SKILL.md +41 -90
- package/template/.claude/skills/idea/SKILL.md +2 -2
- package/template/.claude/skills/implement/SKILL.md +189 -46
- package/template/.claude/skills/onboard/SKILL.md +216 -85
- package/template/.claude/skills/overview/SKILL.md +44 -29
- package/template/.claude/skills/prototype/SKILL.md +82 -27
- package/template/.claude/skills/release/SKILL.md +119 -130
- package/template/.claude/skills/report-html/SKILL.md +2 -2
- package/template/.claude/skills/rollback/SKILL.md +123 -77
- package/template/.claude/skills/status/SKILL.md +109 -0
- package/template/.claude/skills/test/SKILL.md +2 -2
- package/template/.claude/skills/tests/SKILL.md +126 -0
- package/template/.claude/skills/try/SKILL.md +77 -65
- package/template/AGENTS.md +2 -1
- package/template/devflow/build-plan.md +50 -20
- package/template/devflow/history/features/README.md +5 -0
- package/template/devflow/history/fixes/README.md +5 -0
- package/template/devflow/history/rollbacks/README.md +5 -0
- package/template/devflow/project-plan.md +70 -18
- package/template/devflow/reference/studio.html +504 -0
|
@@ -3,7 +3,7 @@ const DASHBOARD_PAGE_HTML = `<!doctype html>
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>Nexus-DevFlow
|
|
6
|
+
<title>Nexus-DevFlow Enterprise Dashboard</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&family=Noto+Sans+Thai:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&display=swap" rel="stylesheet">
|
|
@@ -20,7 +20,7 @@ const DASHBOARD_PAGE_HTML = `<!doctype html>
|
|
|
20
20
|
*{box-sizing:border-box}
|
|
21
21
|
html{color-scheme:dark}
|
|
22
22
|
body{margin:0;min-height:100vh;background-color:var(--bg);color:var(--ink);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;background-image:linear-gradient(rgba(125,216,255,.065) 1px,transparent 1px),linear-gradient(90deg,rgba(125,216,255,.065) 1px,transparent 1px),radial-gradient(circle at 8% -5%,rgba(125,216,255,.16),transparent 42rem);background-size:34px 34px,34px 34px,auto}
|
|
23
|
-
button{font:inherit}
|
|
23
|
+
button,input{font:inherit}
|
|
24
24
|
code{font-family:var(--font-mono);color:var(--cyan)}
|
|
25
25
|
.sheet{width:min(1180px,calc(100% - 40px));margin:0 auto;padding:34px 0 64px}
|
|
26
26
|
.titleblock{display:flex;align-items:flex-end;justify-content:space-between;gap:26px;padding-bottom:20px;border-bottom:1px solid var(--line-strong);flex-wrap:wrap}
|
|
@@ -38,7 +38,7 @@ const DASHBOARD_PAGE_HTML = `<!doctype html>
|
|
|
38
38
|
#dual-track{overflow:hidden}
|
|
39
39
|
.stepper{justify-content:center}.step{display:flex;flex-direction:column;align-items:center;text-align:center}.step-icon{display:grid;place-items:center;width:30px;height:30px;margin:10px auto 8px;border:1px solid currentColor;border-radius:8px;background:rgba(255,255,255,.035)}.icon-glyph{display:block;font-size:17px;line-height:1}.step.flow-0,.step.flow-4{color:var(--cyan)}.step.flow-1,.step.flow-5{color:var(--violet)}.step.flow-2,.step.flow-6{color:var(--gold)}.step.flow-3,.step.flow-7{color:var(--mint)}.step .step-name{color:currentColor}.step .step-cmd{color:var(--muted)}
|
|
40
40
|
.panel{padding:24px 26px;margin-bottom:20px}.panel-head,.card-head{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap}.panel-head{margin-bottom:20px}.card-head{margin-bottom:17px}
|
|
41
|
-
.track-tabs{display:flex;gap:7px}.tab{display:inline-flex;align-items:center;gap:7px;padding:7px 13px;border:1px solid var(--line-strong);border-radius:99px;background:transparent;color:var(--muted);font:600 10px var(--font-mono);cursor:pointer}.tab:hover,.tab:focus-visible{border-color:var(--cyan);color:var(--cyan);outline:none}.tab.on{background:var(--cyan);border-color:var(--cyan);color:var(--bg-deep)}.tab-active-dot{display:none;padding:2px 6px;border-radius:99px;font:700 8px/1 var(--font-mono);letter-spacing:.05em;text-transform:uppercase;background:var(--mint);color:var(--bg-deep)}.tab.is-active-track .tab-active-dot{display:inline-flex;align-items:center;gap:3px;box-shadow:0 0 0 2px rgba(111,227,180,.25)}.tab.on.is-active-track .tab-active-dot{background:var(--bg-deep);color:var(--mint)}
|
|
41
|
+
.track-tabs{display:flex;gap:7px;flex-wrap:wrap}.tab{display:inline-flex;align-items:center;gap:7px;padding:7px 13px;border:1px solid var(--line-strong);border-radius:99px;background:transparent;color:var(--muted);font:600 10px var(--font-mono);cursor:pointer}.tab:hover,.tab:focus-visible{border-color:var(--cyan);color:var(--cyan);outline:none}.tab.on{background:var(--cyan);border-color:var(--cyan);color:var(--bg-deep)}.tab-active-dot{display:none;padding:2px 6px;border-radius:99px;font:700 8px/1 var(--font-mono);letter-spacing:.05em;text-transform:uppercase;background:var(--mint);color:var(--bg-deep)}.tab.is-active-track .tab-active-dot{display:inline-flex;align-items:center;gap:3px;box-shadow:0 0 0 2px rgba(111,227,180,.25)}.tab.on.is-active-track .tab-active-dot{background:var(--bg-deep);color:var(--mint)}
|
|
42
42
|
.track-view{display:none;min-width:0}.track-view.on{display:block}.stepper{display:flex;width:100%;max-width:100%;overflow-x:auto;padding:4px 0 7px}.step{flex:1 1 0;min-width:104px;position:relative;padding-right:12px}.step-line{position:absolute;top:10px;left:21px;right:0;height:1px;background:var(--line-strong)}.step:last-child .step-line{display:none}.step.done .step-line{background:var(--mint)}
|
|
43
43
|
.step-dot{position:relative;z-index:1;width:21px;height:21px;border-radius:50%;display:grid;place-items:center;border:2px solid var(--line-strong);background:var(--bg-deep);color:var(--muted);font:700 8px var(--font-mono)}.step.done .step-dot{border-color:var(--mint);color:var(--mint)}.step.active .step-dot{border-color:var(--gold);color:var(--gold);box-shadow:0 0 0 4px rgba(242,193,78,.16)}
|
|
44
44
|
.step-name{margin-top:9px;color:var(--soft);font:600 10px/1.35 var(--font-mono)}.step.active .step-name{color:var(--gold)}.step.done .step-name{color:var(--mint)}.step-cmd{margin-top:3px;color:var(--muted);font:9px/1.4 var(--font-mono)}.track-note{margin-top:12px;padding-top:12px;border-top:1px dashed var(--line);color:var(--muted);font:11px/1.65 var(--font-mono)}
|
|
@@ -50,76 +50,121 @@ const DASHBOARD_PAGE_HTML = `<!doctype html>
|
|
|
50
50
|
ul{list-style:none;margin:0;padding:0}li{padding:10px 0;border-bottom:1px dashed var(--line);color:var(--soft);font-size:12px;line-height:1.55}li:last-child{border:0}.empty{color:var(--muted)}
|
|
51
51
|
.severity{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.sev{padding:9px 6px;border:1px solid var(--line);border-radius:3px;text-align:center}.sev b{display:block;font:700 17px var(--font-display)}.sev small{color:var(--muted);font:9px var(--font-mono)}
|
|
52
52
|
.commands{display:flex;flex-wrap:wrap;gap:10px}.cmd{position:relative;padding:8px 13px;border:1px solid var(--line-strong);border-radius:3px;background:rgba(255,255,255,.025);color:var(--soft);font:11px var(--font-mono);cursor:pointer}.cmd:hover,.cmd:focus-visible,.cmd:focus{border-color:var(--cyan);color:var(--cyan);outline:2px solid rgba(125,216,255,.2);outline-offset:2px}.cmd:after{content:attr(data-tip);position:absolute;z-index:30;left:50%;bottom:calc(100% + 10px);width:max-content;max-width:min(300px,80vw);padding:9px 11px;border:1px solid var(--line-strong);border-radius:3px;background:#031421;color:var(--soft);font:10px/1.5 var(--font-mono);white-space:normal;text-align:left;opacity:0;visibility:hidden;transform:translate(-50%,5px);box-shadow:0 12px 30px rgba(0,0,0,.4);transition:.15s;pointer-events:none}.cmd:hover:after,.cmd:focus-visible:after,.cmd:focus:after{opacity:1;visibility:visible;transform:translate(-50%,0)}
|
|
53
|
-
.adapters{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}.adapter{padding:15px;border:1px solid var(--line);border-radius:
|
|
54
|
-
.
|
|
53
|
+
.adapters,.roster-grid,.mcp-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}.adapter,.roster-card,.mcp-card{padding:15px;border:1px solid var(--line);border-radius:4px;background:rgba(255,255,255,.02)}.adapter strong,.roster-card strong,.mcp-card strong{display:block;margin-bottom:6px;text-transform:capitalize}.adapter-path,.roster-desc,.mcp-desc{color:var(--muted);font:10px var(--font-mono);line-height:1.4}.adapter-state{margin-top:9px;font:10px var(--font-mono)}
|
|
54
|
+
.mcp-grid{grid-template-columns:repeat(3,1fr)}
|
|
55
|
+
.search-row{display:flex;gap:10px;margin-bottom:16px}.search-input{flex:1;padding:10px 14px;background:var(--bg-deep);border:1px solid var(--line-strong);border-radius:4px;color:var(--ink);font-family:var(--font-mono);font-size:12px}.search-btn{padding:10px 18px;border:1px solid var(--cyan);border-radius:4px;background:var(--cyan);color:var(--bg-deep);font-weight:700;cursor:pointer}
|
|
56
|
+
.blast-result{padding:16px;border:1px solid var(--line-strong);border-radius:4px;background:var(--bg-deep);margin-top:12px;display:none}
|
|
55
57
|
.section-note{margin:-2px 0 14px;color:var(--muted);font:10px/1.5 var(--font-mono)}.record-list{display:grid;gap:8px}.record-item{display:grid;grid-template-columns:38px minmax(0,1fr) auto;gap:13px;align-items:center;padding:13px 15px;border:1px solid var(--line);border-left:3px solid var(--record-color,var(--cyan));border-radius:3px;background:rgba(255,255,255,.02)}.record-icon{display:grid;place-items:center;width:31px;height:31px;border-radius:8px;background:color-mix(in srgb,var(--record-color,var(--cyan)) 14%,transparent)}.record-body{min-width:0}.record-meta{color:var(--record-color,var(--cyan));font:700 10px var(--font-mono);letter-spacing:.06em;text-transform:uppercase}.record-title{margin-top:3px;color:var(--ink);font-weight:650}.record-desc{margin-top:3px;color:var(--soft);font-size:12px}.record-desc:empty{display:none}.record-title strong,.record-desc strong{color:var(--record-color,var(--cyan));font-weight:750}.record-title em,.record-desc em{color:var(--gold)}.record-title code,.record-desc code{padding:1px 4px;border:1px solid var(--line);border-radius:3px;color:var(--cyan);font:10px var(--font-mono)}.record-title a,.record-desc a{color:var(--cyan);text-decoration:underline}.record-actions{display:flex;align-items:center;justify-content:flex-end;gap:7px;flex-wrap:wrap}.record-action{border:1px solid var(--record-color,var(--cyan));border-radius:3px;padding:8px 11px;background:transparent;color:var(--record-color,var(--cyan));font:700 10px var(--font-mono);cursor:pointer}.record-action:hover,.record-action:focus-visible{background:var(--record-color,var(--cyan));color:var(--bg)}.record-badge{align-self:start;border:1px solid rgba(111,227,180,.36);border-radius:99px;padding:4px 8px;background:var(--mint-soft);color:var(--mint);font:700 9px var(--font-mono);letter-spacing:.04em;text-transform:uppercase}.record-item.tone-cyan{--record-color:var(--cyan)}.record-item.tone-mint{--record-color:var(--mint)}.record-item.tone-gold{--record-color:var(--gold)}.record-item.tone-red{--record-color:var(--red)}.record-item.tone-violet{--record-color:var(--violet)}.stepper{gap:0;justify-content:center}.step{padding-right:0;overflow:visible}.step-line{left:calc(50% + 10px);right:calc(-50% + 10px);width:auto}#sev-p0{color:var(--red)}#sev-p1{color:var(--gold)}#sev-p2{color:var(--violet)}#sev-p3{color:var(--cyan)}#stat-runs.tone{color:var(--mint)}#stat-findings.tone-ok{color:var(--mint)}#stat-findings.tone-alert{color:var(--red)}#stat-ideas.tone-ok{color:var(--mint)}#stat-ideas.tone-pending{color:var(--gold)}#stat-adapters.tone-ok{color:var(--mint)}#stat-adapters.tone-partial{color:var(--gold)}#stat-state.tone-idle{color:var(--cyan)}#stat-state.tone-active{color:var(--violet)}#stat-state.tone-blocked{color:var(--red)}
|
|
56
58
|
footer{display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;margin-top:26px;padding-top:17px;border-top:1px solid var(--line);color:var(--muted);font:10px var(--font-mono)}
|
|
57
|
-
@media(max-width:920px){.grid .card,.grid .card.wide{grid-column:1/-1}.stats{grid-template-columns:repeat(2,1fr)}.adapters{grid-template-columns:repeat(2,1fr)}.titleblock{align-items:flex-start;flex-direction:column}.meta dd{text-align:left}.stepper{gap:0}.cmd:after{position:fixed;left:12px;right:12px;bottom:16px;width:auto;max-width:none;transform:translateY(5px)}.cmd:hover:after,.cmd:focus-visible:after,.cmd:focus:after{transform:none}}
|
|
58
|
-
@media(max-width:560px){.sheet{width:calc(100% - 24px);padding-top:22px}.panel,.card{padding:18px}.grid{gap:14px;margin-bottom:14px}.stats{margin-bottom:14px}.adapters{grid-template-columns:1fr}.cmd:after{position:fixed;left:12px;right:12px;bottom:16px;width:auto;max-width:none;transform:translateY(5px)}.cmd:hover:after,.cmd:focus-visible:after,.cmd:focus:after{transform:none}.meta{grid-template-columns:1fr}.track-tabs{width:100%}.tab{flex:1}.fact{align-items:flex-start}.record-item{grid-template-columns:34px minmax(0,1fr)}.record-action{grid-column:2;justify-self:start}}
|
|
59
|
+
@media(max-width:920px){.grid .card,.grid .card.wide{grid-column:1/-1}.stats{grid-template-columns:repeat(2,1fr)}.adapters,.roster-grid,.mcp-grid{grid-template-columns:repeat(2,1fr)}.titleblock{align-items:flex-start;flex-direction:column}.meta dd{text-align:left}.stepper{gap:0}.cmd:after{position:fixed;left:12px;right:12px;bottom:16px;width:auto;max-width:none;transform:translateY(5px)}.cmd:hover:after,.cmd:focus-visible:after,.cmd:focus:after{transform:none}}
|
|
60
|
+
@media(max-width:560px){.sheet{width:calc(100% - 24px);padding-top:22px}.panel,.card{padding:18px}.grid{gap:14px;margin-bottom:14px}.stats{margin-bottom:14px}.adapters,.roster-grid,.mcp-grid{grid-template-columns:1fr}.cmd:after{position:fixed;left:12px;right:12px;bottom:16px;width:auto;max-width:none;transform:translateY(5px)}.cmd:hover:after,.cmd:focus-visible:after,.cmd:focus:after{transform:none}.meta{grid-template-columns:1fr}.track-tabs{width:100%}.tab{flex:1}.fact{align-items:flex-start}.record-item{grid-template-columns:34px minmax(0,1fr)}.record-action{grid-column:2;justify-self:start}}
|
|
59
61
|
@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.001ms!important;transition-duration:.001ms!important}}
|
|
60
62
|
</style>
|
|
61
63
|
</head>
|
|
62
64
|
<body>
|
|
63
65
|
<main class="sheet">
|
|
64
66
|
<header class="titleblock">
|
|
65
|
-
<div
|
|
66
|
-
|
|
67
|
+
<div>
|
|
68
|
+
<div class="eyebrow">Nexus-DevFlow · Enterprise Workspace Status</div>
|
|
69
|
+
<h1 id="project-name">Nexus-DevFlow</h1>
|
|
70
|
+
<div class="path" id="project-path">Connecting...</div>
|
|
71
|
+
<div class="badges">
|
|
72
|
+
<span class="badge" id="version-badge">v2.1.0</span>
|
|
73
|
+
<span class="badge" id="health-badge">health</span>
|
|
74
|
+
<span class="badge" id="gate-badge">Gate: checking</span>
|
|
75
|
+
<span class="badge" id="drift-badge">Drift: checking</span>
|
|
76
|
+
<span class="badge" id="track-badge">track</span>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
<dl class="meta">
|
|
80
|
+
<dt>Package</dt><dd id="package-name">@jakkrichm/create-nexus-devflow</dd>
|
|
81
|
+
<dt>Adapters</dt><dd id="adapter-count">-</dd>
|
|
82
|
+
<dt>Branch</dt><dd id="header-branch">-</dd>
|
|
83
|
+
<dt>Snapshot</dt><dd id="generated-at">-</dd>
|
|
84
|
+
</dl>
|
|
67
85
|
</header>
|
|
68
86
|
<div class="live"><span class="live-dot" id="live-dot"></span><span id="live-label">Connecting to local dashboard...</span></div>
|
|
69
87
|
|
|
70
88
|
<section class="panel" id="dual-track">
|
|
71
|
-
<div class="panel-head"
|
|
72
|
-
|
|
73
|
-
|
|
89
|
+
<div class="panel-head">
|
|
90
|
+
<span class="label">Dual-Track Delivery Model</span>
|
|
91
|
+
<div class="track-tabs" role="tablist" aria-label="Delivery tracks">
|
|
92
|
+
<button class="tab on" id="tab-fast" role="tab" aria-selected="true" aria-controls="view-fast" data-track="fast"><span>🚀 Fast-Track · 4 steps</span><span class="tab-active-dot">● ACTIVE</span></button>
|
|
93
|
+
<button class="tab" id="tab-deep" role="tab" aria-selected="false" aria-controls="view-deep" data-track="deep"><span>♟️ Deep-Track · 8 stages</span><span class="tab-active-dot">● ACTIVE</span></button>
|
|
94
|
+
<button class="tab" id="tab-swarm" role="tab" aria-selected="false" aria-controls="view-swarm" data-track="swarm"><span>🤖 Multi-Agent Swarm</span></button>
|
|
95
|
+
<button class="tab" id="tab-graph" role="tab" aria-selected="false" aria-controls="view-graph" data-track="graph"><span>🗺️ Code Graph</span></button>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
<div class="track-view on" id="view-fast" role="tabpanel" aria-labelledby="tab-fast">
|
|
99
|
+
<div class="stepper" id="pipeline-fast"></div>
|
|
100
|
+
<div class="track-note" id="note-fast">Fast-Track for daily features, fixes, UI work and iterative refactoring.</div>
|
|
101
|
+
</div>
|
|
102
|
+
<div class="track-view" id="view-deep" role="tabpanel" aria-labelledby="tab-deep">
|
|
103
|
+
<div class="stepper" id="pipeline-deep"></div>
|
|
104
|
+
<div class="track-note" id="note-deep">Deep-Track for architecture, migrations, security audits and coordinated delivery.</div>
|
|
105
|
+
</div>
|
|
106
|
+
<div class="track-view" id="view-swarm" role="tabpanel" aria-labelledby="tab-swarm">
|
|
107
|
+
<div class="section-note">Role-based specialized AI Subagents roster & execution matrix</div>
|
|
108
|
+
<div class="roster-grid" id="swarm-roster"></div>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="track-view" id="view-graph" role="tabpanel" aria-labelledby="tab-graph">
|
|
111
|
+
<div class="section-note">Semantic dependency graph & instant Blast Radius analyzer</div>
|
|
112
|
+
<div class="search-row">
|
|
113
|
+
<input class="search-input" id="graph-file-input" placeholder="Type file path (e.g. packages/create-nexus-devflow/lib/code-graph.ts)..." />
|
|
114
|
+
<button class="search-btn" id="graph-search-btn" type="button">Analyze Impact</button>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="blast-result" id="blast-result"></div>
|
|
117
|
+
</div>
|
|
74
118
|
</section>
|
|
75
119
|
|
|
76
120
|
<section class="panel next-action" id="next-panel">
|
|
77
|
-
<div class="next-head"><span class="label">Next Action</span><button class="copy" id="next-copy" type="button">Copy command</button></div
|
|
121
|
+
<div class="next-head"><span class="label">Next Action</span><button class="copy" id="next-copy" type="button">Copy command</button></div>
|
|
122
|
+
<div class="command" id="next-command" aria-live="polite">Loading...</div>
|
|
123
|
+
<div class="muted" id="next-reason"></div>
|
|
78
124
|
</section>
|
|
79
125
|
|
|
80
|
-
<section class="stats" aria-label="Workspace summary"
|
|
126
|
+
<section class="stats" aria-label="Workspace summary">
|
|
127
|
+
<div class="stat"><div class="stat-value" id="stat-runs">-</div><div class="stat-label">Runs released</div></div>
|
|
128
|
+
<div class="stat"><div class="stat-value" id="stat-findings">-</div><div class="stat-label">Active findings</div></div>
|
|
129
|
+
<div class="stat"><div class="stat-value" id="stat-ideas">-</div><div class="stat-label">Pending ideas</div></div>
|
|
130
|
+
<div class="stat"><div class="stat-value" id="stat-mcp">-</div><div class="stat-label">MCP Tools Ready</div></div>
|
|
131
|
+
<div class="stat"><div class="stat-value" id="stat-state">-</div><div class="stat-label">Current state</div></div>
|
|
132
|
+
</section>
|
|
81
133
|
|
|
82
134
|
<section class="grid">
|
|
83
|
-
<article class="card"><div class="card-head"><span class="label">Nexus-DevFlow</span><span class="pill" id="update-pill">checking</span></div><div class="facts"><div class="fact"><span>Installed / latest</span><span id="installed-latest">-</span></div><div class="fact"><span>Health</span><span id="system-health">-</span></div><div class="fact"><span>Architecture</span><span>3-Pillars +
|
|
135
|
+
<article class="card"><div class="card-head"><span class="label">Nexus-DevFlow</span><span class="pill" id="update-pill">checking</span></div><div class="facts"><div class="fact"><span>Installed / latest</span><span id="installed-latest">-</span></div><div class="fact"><span>Health</span><span id="system-health">-</span></div><div class="fact"><span>Architecture</span><span>3-Pillars + Swarm RAG</span></div></div></article>
|
|
84
136
|
<article class="card wide"><div class="card-head"><span class="label">Current Work</span><span class="pill" id="work-pill">loading</span></div><div class="value" id="work-title">Loading...</div><div class="progress"><span id="work-progress"></span></div><div class="muted" id="work-meta"></div></article>
|
|
85
|
-
<article class="card"><div class="card-head"><span class="label">Git
|
|
137
|
+
<article class="card"><div class="card-head"><span class="label">Git & Drift</span><span class="pill" id="git-pill">loading</span></div><div class="facts"><div class="fact"><span>Branch</span><span id="git-branch">-</span></div><div class="fact"><span>Working tree</span><span id="git-changed">-</span></div><div class="fact"><span>Drift Status</span><span id="git-drift">-</span></div><div class="fact"><span>Last commit</span><span id="git-commit">-</span></div></div></article>
|
|
86
138
|
<article class="card"><div class="card-head"><span class="label">Findings Ledger</span><span class="value" id="findings-count">-</span></div><div class="severity"><div class="sev"><b id="sev-p0">0</b><small>P0</small></div><div class="sev"><b id="sev-p1">0</b><small>P1</small></div><div class="sev"><b id="sev-p2">0</b><small>P2</small></div><div class="sev"><b id="sev-p3">0</b><small>P3</small></div></div><ul id="findings-list"></ul></article>
|
|
87
|
-
<article class="card"><div class="card-head"><span class="label">Completion</span><span class="pill" id="completion-pill">-</span></div><ul id="completion-list"></ul></article>
|
|
139
|
+
<article class="card"><div class="card-head"><span class="label">Completion & Gate</span><span class="pill" id="completion-pill">-</span></div><ul id="completion-list"></ul></article>
|
|
88
140
|
<article class="card"><div class="card-head"><span class="label">Warnings</span><span class="value" id="warnings-count">-</span></div><ul id="warnings-list"></ul></article>
|
|
89
141
|
</section>
|
|
90
142
|
|
|
143
|
+
<section class="card full panel"><div class="card-head"><span class="label">Model Context Protocol (MCP) Tools Hub</span><span class="value" id="mcp-count">12 Tools</span></div><div class="section-note">Typed JSON-RPC tools exposed to AI Coding Assistants</div><div class="mcp-grid" id="mcp-list"></div></section>
|
|
144
|
+
<section class="card full panel"><div class="card-head"><span class="label">Quick Commands</span><span class="muted">hover or focus for help · click to copy</span></div><div class="commands" id="command-list"></div></section>
|
|
91
145
|
<section class="grid"><article class="card full"><div class="card-head"><span class="label">Doctor · Health Check</span><span class="pill" id="doctor-pill">-</span></div><div class="record-list" id="doctor-list"></div></article></section>
|
|
92
146
|
<section class="card full panel"><div class="card-head"><span class="label">Discoveries</span><span class="value" id="discovery-count">-</span></div><div class="record-list" id="discovery-list"></div></section>
|
|
93
|
-
<section class="card full panel"><div class="card-head"><span class="label">Quick Commands</span><span class="muted">hover or focus for help · click to copy</span></div><div class="commands" id="command-list"></div></section>
|
|
94
|
-
<section class="card full panel"><div class="card-head"><span class="label">Adapter Health</span><span class="muted">configured · detected · healthy</span></div><div class="adapters" id="adapter-list"></div></section>
|
|
95
147
|
<section class="card full panel"><div class="card-head"><span class="label">Idea Inbox & Backlog</span><span class="value" id="ideas-count">-</span></div><div class="section-note">From devflow/ideas.md · start a selected item with /feature IDEA-xxx</div><div class="record-list" id="ideas-list"></div></section>
|
|
96
148
|
<section class="card full panel"><div class="card-head"><span class="label">Completed Work Archive</span><span class="value" id="history-count">-</span></div><div class="section-note">Categorized delivery history · features, fixes and rollbacks</div><div class="record-list" id="history-list"></div></section>
|
|
97
|
-
<footer><span>
|
|
149
|
+
<footer><span>Nexus-DevFlow 2.0 Enterprise Dashboard · refreshes every 2 seconds</span><span id="footer-revision">snapshot pending</span></footer>
|
|
98
150
|
</main>
|
|
99
151
|
<script>
|
|
100
152
|
const byId = (id) => document.getElementById(id);
|
|
101
153
|
const text = (id, value) => { const node = byId(id); if (node) node.textContent = value == null ? '-' : String(value); };
|
|
102
154
|
const pill = (id, state, label) => { const node = byId(id); if (!node) return; node.className = 'pill ' + (state || 'configured'); node.textContent = label || state || '-'; };
|
|
103
155
|
const list = (id, values, empty) => { const node = byId(id); if (!node) return; node.replaceChildren(); const rows = values.length ? values : [empty]; rows.forEach((value) => { const li = document.createElement('li'); li.textContent = value; if (!values.length) li.className = 'empty'; node.append(li); }); };
|
|
104
|
-
const titleCase = (value) => String(value || '').replaceAll('_',' ').replace(
|
|
105
|
-
const ICON_PATHS = { compass:'M12 2l3 7 7 3-7 3-3 7-3-7-7-3 7-3 3-7z', target:'M12 3a9 9 0 1 0 9 9M12 7a5 5 0 1 0 5 5M12 10a2 2 0 1 0 2 2', document:'M6 2h8l4 4v16H6zM14 2v5h5M9 12h6M9 16h6', list:'M8 6h12M8 12h12M8 18h12M3 6h1M3 12h1M3 18h1', code:'M8 8l-4 4 4 4M16 8l4 4-4 4M14 4l-4 16', shield:'M12 2l8 3v6c0 5-3 9-8 11-5-2-8-6-8-11V5zM8 12l3 3 5-6', report:'M5 3h14v18H5zM8 8h8M8 12h8M8 16h5', package:'M3 7l9-5 9 5v10l-9 5-9-5zM3 7l9 5 9-5M12 12v10', bulb:'M9 18h6M10 22h4M8 14c-2-1-3-3-3-5a7 7 0 0 1 14 0c0 2-1 4-3 5-1 1-1 2-1 3H9c0-1 0-2-1-3z', check:'M5 12l4 4L19 6', wrench:'M14 6a4 4 0 0 0-5 5L3 17l4 4 6-6a4 4 0 0 0 5-5l-3 1-2-2 1-3z', rollback:'M9 7H4v-5M4 7a9 9 0 1 1-1 7', search:'M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14M16 16l5 5', alert:'M12 3l10 18H2zM12 9v5M12 18h.01' };
|
|
156
|
+
const titleCase = (value) => String(value || '').replaceAll('_',' ').replace(/\\b\\w/g, (c) => c.toUpperCase());
|
|
106
157
|
const FLOW_ICON_NAMES = ['compass','target','document','list','code','shield','report','package'];
|
|
107
158
|
const EMOJI_ICONS = { compass:'🔎',target:'🎯',document:'📄',list:'🧩',code:'⚙️',shield:'🛡️',report:'📊',package:'📦',bulb:'⚡',check:'✅',wrench:'🛠️',rollback:'↩️',search:'🔍',alert:'⚠️' };
|
|
108
159
|
function iconImage(name) { const icon = document.createElement('span'); icon.className = 'icon-glyph'; icon.setAttribute('aria-hidden','true'); icon.textContent = EMOJI_ICONS[name] || '📄'; return icon; }
|
|
109
160
|
function decoratePipeline(id) { byId(id)?.querySelectorAll('.step').forEach((step,index) => { step.classList.add('flow-' + index); const icon = document.createElement('span'); icon.className = 'step-icon'; icon.setAttribute('aria-hidden','true'); icon.append(iconImage(FLOW_ICON_NAMES[index] || 'document')); const name = step.querySelector('.step-name'); step.insertBefore(icon,name || null); }); }
|
|
110
|
-
function richText(root,value) { const source = String(value || ''); let cursor = 0; const plain = (end) => { if (end > cursor) root.append(document.createTextNode(source.slice(cursor,end))); cursor = end; }; while (cursor < source.length) { if (source.startsWith('**',cursor)) { const end = source.indexOf('**',cursor + 2); if (end > cursor + 2) { const node = document.createElement('strong'); node.textContent = source.slice(cursor + 2,end); root.append(node); cursor = end + 2; continue; } } if (source[cursor] === '*') { const end = source.indexOf('*',cursor + 1); if (end > cursor + 1) { const node = document.createElement('em'); node.textContent = source.slice(cursor + 1,end); root.append(node); cursor = end + 1; continue; } } if (source.charCodeAt(cursor) === 96) { const end = source.indexOf(String.fromCharCode(96),cursor + 1); if (end > cursor + 1) { const node = document.createElement('code'); node.textContent = source.slice(cursor + 1,end); root.append(node); cursor = end + 1; continue; } }
|
|
111
|
-
function recordCard(options) { const card = document.createElement('article'); card.className = 'record-item tone-' + (options.tone || 'cyan'); const icon = document.createElement('span'); icon.className = 'record-icon'; icon.append(iconImage(options.icon || 'document')); const body = document.createElement('div'); body.className = 'record-body'; const meta = document.createElement('div'); meta.className = 'record-meta'; richText(meta,options.meta); const title = document.createElement('div'); title.className = 'record-title'; richText(title,options.title); const desc = document.createElement('div'); desc.className = 'record-desc'; richText(desc,options.description); body.append(meta,title,desc); card.append(icon,body); if (options.badge) { const badge = document.createElement('span'); badge.className = 'record-badge'; badge.textContent = options.badge; card.append(badge); }
|
|
161
|
+
function richText(root,value) { const source = String(value || ''); let cursor = 0; const plain = (end) => { if (end > cursor) root.append(document.createTextNode(source.slice(cursor,end))); cursor = end; }; while (cursor < source.length) { if (source.startsWith('**',cursor)) { const end = source.indexOf('**',cursor + 2); if (end > cursor + 2) { const node = document.createElement('strong'); node.textContent = source.slice(cursor + 2,end); root.append(node); cursor = end + 2; continue; } } if (source[cursor] === '*') { const end = source.indexOf('*',cursor + 1); if (end > cursor + 1) { const node = document.createElement('em'); node.textContent = source.slice(cursor + 1,end); root.append(node); cursor = end + 1; continue; } } if (source.charCodeAt(cursor) === 96) { const end = source.indexOf(String.fromCharCode(96),cursor + 1); if (end > cursor + 1) { const node = document.createElement('code'); node.textContent = source.slice(cursor + 1,end); root.append(node); cursor = end + 1; continue; } } const next = [source.indexOf('**',cursor + 1),source.indexOf('*',cursor + 1),source.indexOf(String.fromCharCode(96),cursor + 1)].filter((index) => index >= 0).sort((a,b) => a-b)[0] ?? source.length; plain(next > cursor ? next : cursor + 1); } }
|
|
162
|
+
function recordCard(options) { const card = document.createElement('article'); card.className = 'record-item tone-' + (options.tone || 'cyan'); const icon = document.createElement('span'); icon.className = 'record-icon'; icon.append(iconImage(options.icon || 'document')); const body = document.createElement('div'); body.className = 'record-body'; const meta = document.createElement('div'); meta.className = 'record-meta'; richText(meta,options.meta); const title = document.createElement('div'); title.className = 'record-title'; richText(title,options.title); const desc = document.createElement('div'); desc.className = 'record-desc'; richText(desc,options.description); body.append(meta,title,desc); card.append(icon,body); if (options.badge) { const badge = document.createElement('span'); badge.className = 'record-badge'; badge.textContent = options.badge; card.append(badge); } return card; }
|
|
112
163
|
function renderRecords(id,items,empty,mapper) { const root = byId(id); root.replaceChildren(); if (!items?.length) { const node = document.createElement('div'); node.className = 'empty'; node.textContent = empty; root.append(node); return; } items.forEach((item,index) => root.append(recordCard(mapper(item,index)))); }
|
|
113
|
-
function
|
|
114
|
-
function renderIdeas(items) { renderRecords('ideas-list',items,'No pending ideas',(item) => ({ icon:'bulb',tone:ideaTone(item.feasibility),meta:item.id,title:item.title,description:(item.description || '⚡') + ' · ' + (item.feasibility || '**Not scored**'),actions:['/feature ' + item.id,'/discovery ' + item.id] })); }
|
|
164
|
+
function renderIdeas(items) { renderRecords('ideas-list',items,'No pending ideas',(item) => ({ icon:'bulb',tone:'gold',meta:item.id,title:item.title,description:(item.description || '⚡') + ' · ' + (item.feasibility || 'Not scored') })); }
|
|
115
165
|
function renderHistory(items) { const map = { feature:{icon:'package',tone:'cyan'},fix:{icon:'wrench',tone:'gold'},rollback:{icon:'rollback',tone:'red'} }; renderRecords('history-list',(items || []).slice(0,10),'No completed work in history archive',(item) => { const type = String(item.type || 'other').toLowerCase(); const style = map[type] || {icon:'report',tone:'violet'}; return { ...style,meta:type + ' ' + (item.buildPlanItem || ''),title:item.title,description:'',badge:'Released' }; }); }
|
|
116
166
|
function renderDoctor(items) { renderRecords('doctor-list',items,'No doctor checks available',(item) => ({ icon:item.status === 'pass' ? 'check' : 'alert',tone:item.status === 'pass' ? 'mint' : item.status === 'warn' ? 'gold' : 'red',meta:item.status,title:item.name,description:item.message })); }
|
|
117
|
-
function renderDiscoveries(items) { renderRecords('discovery-list',items,'No discoveries recorded',(item) =>
|
|
118
|
-
let nextCopyValue = '/feature';
|
|
119
|
-
let nextCopyLabel = '/feature';
|
|
120
|
-
byId('next-copy').addEventListener('click',(event) => { event.stopImmediatePropagation(); navigator.clipboard?.writeText(nextCopyValue); const button = byId('next-copy'); button.textContent = 'Copied ' + nextCopyLabel; setTimeout(() => { button.textContent = 'Copy command ' + nextCopyLabel; },1200); },true);
|
|
121
|
-
let preferredTrack = (() => { try { return localStorage.getItem('devflow-dashboard-track'); } catch { return null; } })();
|
|
122
|
-
document.querySelectorAll('[data-track]').forEach((button) => button.addEventListener('click',() => { preferredTrack = button.dataset.track; try { localStorage.setItem('devflow-dashboard-track',preferredTrack); } catch {} },{capture:true}));
|
|
167
|
+
function renderDiscoveries(items) { renderRecords('discovery-list',items,'No discoveries recorded',(item) => ({ icon:'search',tone:'mint',meta:item.id,title:item.title,description:'',badge:'Decision: ' + (item.decision || 'Pending') })); }
|
|
123
168
|
|
|
124
169
|
function renderPipeline(id, nodes) {
|
|
125
170
|
const root = byId(id); root.replaceChildren();
|
|
@@ -153,41 +198,80 @@ const DASHBOARD_PAGE_HTML = `<!doctype html>
|
|
|
153
198
|
|
|
154
199
|
function renderCommands(commands) {
|
|
155
200
|
const root = byId('command-list'); root.replaceChildren();
|
|
156
|
-
(commands || [])
|
|
157
|
-
|
|
201
|
+
const allCommands = [...(commands || [])];
|
|
202
|
+
['nexus-devflow check-gate', 'nexus-devflow drift', 'nexus-devflow reconcile --fix', 'nexus-devflow slice --stage implement', 'nexus-devflow swarm', 'nexus-devflow studio'].forEach(c => {
|
|
203
|
+
if (!allCommands.some(item => item.command === c)) {
|
|
204
|
+
allCommands.push({ name: c.replace('nexus-devflow ', ''), command: c, family: 'companion', description: 'Run ' + c });
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
allCommands.forEach((item) => {
|
|
208
|
+
const button = document.createElement('button'); button.type = 'button'; button.className = 'cmd'; button.textContent = item.name; button.dataset.tip = item.description; wireCopy(button, () => item.command); root.append(button);
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function renderSwarm(swarm) {
|
|
213
|
+
const root = byId('swarm-roster'); if (!root) return; root.replaceChildren();
|
|
214
|
+
(swarm?.agentRoster || []).forEach(agent => {
|
|
215
|
+
const card = document.createElement('div'); card.className = 'roster-card';
|
|
216
|
+
card.innerHTML = '<strong>' + agent.avatar + ' ' + agent.name + '</strong><div class="roster-desc">' + agent.responsibility + '</div>';
|
|
217
|
+
root.append(card);
|
|
158
218
|
});
|
|
159
219
|
}
|
|
160
220
|
|
|
161
|
-
function
|
|
162
|
-
const root = byId('
|
|
163
|
-
(
|
|
221
|
+
function renderMcp(tools) {
|
|
222
|
+
const root = byId('mcp-list'); if (!root) return; root.replaceChildren();
|
|
223
|
+
(tools || []).forEach(t => {
|
|
224
|
+
const card = document.createElement('div'); card.className = 'mcp-card';
|
|
225
|
+
card.innerHTML = '<strong>⚙️ ' + t.name + '</strong><div class="mcp-desc">' + t.description + '</div>';
|
|
226
|
+
root.append(card);
|
|
227
|
+
});
|
|
164
228
|
}
|
|
165
229
|
|
|
230
|
+
byId('graph-search-btn')?.addEventListener('click', async () => {
|
|
231
|
+
const input = byId('graph-file-input'); const res = byId('blast-result');
|
|
232
|
+
if (!input || !res) return;
|
|
233
|
+
const file = input.value.trim();
|
|
234
|
+
if (!file) return;
|
|
235
|
+
res.style.display = 'block'; res.innerHTML = 'Analyzing Blast Radius...';
|
|
236
|
+
try {
|
|
237
|
+
const resp = await fetch('/api/graph?file=' + encodeURIComponent(file));
|
|
238
|
+
const data = await resp.json();
|
|
239
|
+
if (data.error) { res.innerHTML = '<span style="color:var(--red)">' + data.error + '</span>'; return; }
|
|
240
|
+
let html = '<strong>Impact Score: <span style="color:var(--gold)">' + data.impactScore + '</span> | Total Affected: ' + data.totalAffected + ' files</strong><br/><br/>';
|
|
241
|
+
if (data.directDependents?.length) {
|
|
242
|
+
html += '<strong>Direct Dependents:</strong><ul>' + data.directDependents.map(d => '<li>' + d + '</li>').join('') + '</ul>';
|
|
243
|
+
}
|
|
244
|
+
if (data.transitiveDependents?.length) {
|
|
245
|
+
html += '<br/><strong>Transitive Dependents:</strong><ul>' + data.transitiveDependents.map(t => '<li>' + t + '</li>').join('') + '</ul>';
|
|
246
|
+
}
|
|
247
|
+
res.innerHTML = html;
|
|
248
|
+
} catch (e) {
|
|
249
|
+
res.innerHTML = '<span style="color:var(--red)">Error: ' + e.message + '</span>';
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
166
253
|
function renderSnapshot(data) {
|
|
167
|
-
const status = data.status || {}; const project = status.project || {}; const devflow = status.devflow || {}; const work = status.currentWork || {}; const git = status.git || {}; const findings = status.findings || { active: [], blockers: [] }; const workflow = data.workflow || {}; const update = data.update || {}; const doctor = data.doctor || { checks: [] }; const discoveries = data.discoveries || { recent: [] }; const history = data.history || { items: [], total: 0 }; const ideas = status.ideas || { pending: [], totalPending: 0 };
|
|
168
|
-
|
|
254
|
+
const status = data.status || {}; const project = status.project || {}; const devflow = status.devflow || {}; const work = status.currentWork || {}; const git = status.git || {}; const findings = status.findings || { active: [], blockers: [] }; const workflow = data.workflow || {}; const update = data.update || {}; const doctor = data.doctor || { checks: [] }; const discoveries = data.discoveries || { recent: [] }; const history = data.history || { items: [], total: 0 }; const ideas = status.ideas || { pending: [], totalPending: 0 }; const gate = data.gatekeeper || { passed: true }; const drift = data.drift || { hasDrift: false };
|
|
255
|
+
|
|
256
|
+
text('project-name', project.name || 'Nexus-DevFlow'); text('project-path', project.root || ''); text('version-badge', 'v' + (devflow.version || '2.1.0'));
|
|
257
|
+
pill('health-badge', status.health, status.health === 'ok' ? 'Health OK' : 'Health warning');
|
|
258
|
+
pill('gate-badge', gate.passed ? 'ok' : 'blocked', gate.passed ? '✔ Gate Passed' : '✖ Gate Blocked');
|
|
259
|
+
pill('drift-badge', !drift.hasDrift ? 'ok' : 'warning', !drift.hasDrift ? '✔ In Sync' : '⚠ Drift Detected');
|
|
260
|
+
pill('track-badge', workflow.track, 'Track ' + titleCase(workflow.track || 'idle'));
|
|
261
|
+
|
|
169
262
|
text('adapter-count', (devflow.adapters || []).length + ' configured'); text('header-branch', git.branch || 'unknown'); text('generated-at', new Date(data.generatedAt).toLocaleTimeString()); text('footer-revision', 'snapshot ' + data.generatedAt);
|
|
170
|
-
const currentTrack = workflow.track || 'idle';
|
|
171
|
-
const isDeepActive = currentTrack === 'deep';
|
|
172
|
-
const isFastActive = currentTrack === 'fast';
|
|
173
|
-
const tabFast = byId('tab-fast');
|
|
174
|
-
const tabDeep = byId('tab-deep');
|
|
175
|
-
if (tabFast) tabFast.classList.toggle('is-active-track', isFastActive);
|
|
176
|
-
if (tabDeep) tabDeep.classList.toggle('is-active-track', isDeepActive);
|
|
177
263
|
renderPipeline('pipeline-fast', workflow.fast); renderPipeline('pipeline-deep', workflow.deep); decoratePipeline('pipeline-fast'); decoratePipeline('pipeline-deep');
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
text('
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
pill('
|
|
185
|
-
pill('work-pill', work.state, work.state || 'idle'); text('work-title', work.title || 'No active delivery run'); const pct = work.total > 0 ? Math.round((work.completed / work.total) * 100) : 0; byId('work-progress').style.width = pct + '%'; text('work-meta', work.state === 'active' ? work.completed + ' of ' + work.total + ' steps completed' : 'Last completed: ' + (workflow.lastCompletedRun || 'none recorded'));
|
|
186
|
-
pill('git-pill', git.clean ? 'ok' : 'warning', git.clean ? 'clean' : (git.changedFiles || 0) + ' changed'); text('git-branch', git.branch || 'unknown'); text('git-changed', git.clean ? 'clean' : (git.changedFiles || 0) + ' changed files'); text('git-upstream', git.upstream ? git.upstream + ' · ' + (git.ahead || 0) + ' ahead / ' + (git.behind || 0) + ' behind' : 'none'); text('git-commit', git.lastCommit || '-');
|
|
264
|
+
renderSwarm(data.swarm); renderMcp(data.mcpTools); text('stat-mcp', (data.mcpTools || []).length + ' Ready');
|
|
265
|
+
|
|
266
|
+
const nextCommand = data.nextAction?.command || status.nextAction?.command || '/feature'; text('next-command', nextCommand); text('next-reason', data.nextAction?.reason || 'Ready for new work.');
|
|
267
|
+
text('stat-runs', history.total || 0); text('stat-findings', (findings.active || []).length); text('stat-ideas', ideas.totalPending || 0); text('stat-state', titleCase(work.state || 'idle'));
|
|
268
|
+
pill('update-pill', update.state, update.state === 'current' ? 'up to date' : update.state); text('installed-latest', (update.installedVersion || '2.1.0') + ' / ' + (update.latestVersion || '2.1.0')); text('system-health', status.health || 'ok');
|
|
269
|
+
pill('work-pill', work.state, work.state || 'idle'); text('work-title', work.title || 'No active delivery run'); const pct = work.total > 0 ? Math.round((work.completed / work.total) * 100) : 0; byId('work-progress').style.width = pct + '%'; text('work-meta', work.state === 'active' ? work.completed + ' of ' + work.total + ' steps completed' : 'Ready');
|
|
270
|
+
pill('git-pill', git.clean ? 'ok' : 'warning', git.clean ? 'clean' : (git.changedFiles || 0) + ' changed'); text('git-branch', git.branch || 'unknown'); text('git-changed', git.clean ? 'clean' : (git.changedFiles || 0) + ' changed files'); text('git-drift', drift.clean ? 'In Sync' : 'Drift detected'); text('git-commit', git.lastCommit || '-');
|
|
187
271
|
text('findings-count', findings.total || 0); ['P0','P1','P2','P3'].forEach((severity) => text('sev-' + severity.toLowerCase(), (findings.active || []).filter((item) => item.severity === severity).length)); list('findings-list', (findings.active || []).map((item) => item.id + ' · ' + item.title), 'No active findings');
|
|
188
272
|
pill('completion-pill', status.completion?.state, status.completion?.state || 'unknown'); list('completion-list', status.completion?.blockers || [], work.state === 'idle' ? 'No active run to complete' : 'All readiness checks passed'); text('warnings-count', (status.warnings || []).length); list('warnings-list', (status.warnings || []).map((item) => item.message), 'No active warnings or drift');
|
|
189
273
|
pill('doctor-pill', doctor.failCount ? 'fail' : doctor.warnCount ? 'warning' : 'ok', doctor.passCount + '/' + doctor.totalChecks + ' pass'); renderDoctor(doctor.checks || []);
|
|
190
|
-
text('discovery-count', discoveries.total || 0); renderDiscoveries(discoveries.recent || []); renderCommands(data.commands);
|
|
274
|
+
text('discovery-count', discoveries.total || 0); renderDiscoveries(discoveries.recent || []); renderCommands(data.commands);
|
|
191
275
|
text('ideas-count', (ideas.totalPending || 0) + ' pending'); renderIdeas(ideas.pending || []); text('history-count', (history.total || 0) + ' released'); renderHistory(history.items || []);
|
|
192
276
|
}
|
|
193
277
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-page.js","sourceRoot":"","sources":["../../lib/dashboard-page.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG
|
|
1
|
+
{"version":3,"file":"dashboard-page.js","sourceRoot":"","sources":["../../lib/dashboard-page.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA0RpB,CAAC;AAET,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -5,6 +5,10 @@ import type { HistorySummary } from "./history.js";
|
|
|
5
5
|
import type { ProjectStatus } from "./status.js";
|
|
6
6
|
import type { FetchLike, PackageVersionStatus } from "./version-check.js";
|
|
7
7
|
import type { WorkflowState } from "./workflow-state.js";
|
|
8
|
+
import { type GateReport } from "./gatekeeper.js";
|
|
9
|
+
import { type GitDriftReport } from "./drift-reconciler.js";
|
|
10
|
+
import { type SwarmPlan } from "./swarm-orchestrator.js";
|
|
11
|
+
import { type McpToolDefinition } from "./mcp.js";
|
|
8
12
|
interface DashboardDoctorSummary {
|
|
9
13
|
checks: DoctorCheck[];
|
|
10
14
|
totalChecks: number;
|
|
@@ -34,6 +38,15 @@ interface DashboardSnapshot {
|
|
|
34
38
|
commands: CommandCatalogItem[];
|
|
35
39
|
adapters: AdapterDashboardItem[];
|
|
36
40
|
nextAction: DashboardNextAction;
|
|
41
|
+
gatekeeper: GateReport;
|
|
42
|
+
drift: GitDriftReport;
|
|
43
|
+
swarm: SwarmPlan;
|
|
44
|
+
graph: {
|
|
45
|
+
totalFiles: number;
|
|
46
|
+
totalEdges: number;
|
|
47
|
+
files: string[];
|
|
48
|
+
};
|
|
49
|
+
mcpTools: McpToolDefinition[];
|
|
37
50
|
}
|
|
38
51
|
interface DashboardSnapshotOptions {
|
|
39
52
|
fetchImpl?: FetchLike;
|
|
@@ -5,13 +5,18 @@ import { readHistory } from "./history.js";
|
|
|
5
5
|
import { readProjectStatus } from "./status.js";
|
|
6
6
|
import { checkPackageVersion } from "./version-check.js";
|
|
7
7
|
import { readWorkflowState } from "./workflow-state.js";
|
|
8
|
+
import { evaluateGate } from "./gatekeeper.js";
|
|
9
|
+
import { detectGitDrift } from "./drift-reconciler.js";
|
|
10
|
+
import { generateSwarmPlan } from "./swarm-orchestrator.js";
|
|
11
|
+
import { buildCodeGraph } from "./code-graph.js";
|
|
12
|
+
import { DEVFLOW_MCP_TOOLS } from "./mcp.js";
|
|
8
13
|
const slowCache = new Map();
|
|
9
14
|
async function readDashboardSnapshot(startPath = process.cwd(), options = {}) {
|
|
10
15
|
const now = options.now || Date.now;
|
|
11
16
|
const status = await readProjectStatus(startPath);
|
|
12
17
|
const projectRoot = status.project.root;
|
|
13
18
|
const workflow = await readWorkflowState(projectRoot, status.currentWork);
|
|
14
|
-
const [history, slow, update] = await Promise.all([
|
|
19
|
+
const [history, slow, update, gatekeeper, drift, swarm] = await Promise.all([
|
|
15
20
|
readHistory(projectRoot),
|
|
16
21
|
readSlowData(projectRoot, workflow.activeDiscoveryId, now, options.slowTtlMs ?? 15_000),
|
|
17
22
|
checkPackageVersion({
|
|
@@ -20,7 +25,10 @@ async function readDashboardSnapshot(startPath = process.cwd(), options = {}) {
|
|
|
20
25
|
timeoutMs: options.versionTimeoutMs,
|
|
21
26
|
cacheTtlMs: options.versionCacheTtlMs,
|
|
22
27
|
now
|
|
23
|
-
})
|
|
28
|
+
}),
|
|
29
|
+
evaluateGate(projectRoot, { strict: false }),
|
|
30
|
+
detectGitDrift(projectRoot),
|
|
31
|
+
generateSwarmPlan(projectRoot)
|
|
24
32
|
]);
|
|
25
33
|
return {
|
|
26
34
|
schemaVersion: 1,
|
|
@@ -33,7 +41,16 @@ async function readDashboardSnapshot(startPath = process.cwd(), options = {}) {
|
|
|
33
41
|
update,
|
|
34
42
|
commands: slow.commands,
|
|
35
43
|
adapters: buildAdapterItems(status.devflow.adapters, slow.doctor),
|
|
36
|
-
nextAction: selectDashboardNextAction(status, workflow)
|
|
44
|
+
nextAction: selectDashboardNextAction(status, workflow),
|
|
45
|
+
gatekeeper,
|
|
46
|
+
drift,
|
|
47
|
+
swarm,
|
|
48
|
+
graph: {
|
|
49
|
+
totalFiles: slow.graph.totalFiles,
|
|
50
|
+
totalEdges: slow.graph.totalEdges,
|
|
51
|
+
files: Object.keys(slow.graph.nodes)
|
|
52
|
+
},
|
|
53
|
+
mcpTools: DEVFLOW_MCP_TOOLS
|
|
37
54
|
};
|
|
38
55
|
}
|
|
39
56
|
async function readSlowData(projectRoot, activeDiscoveryId, now, ttlMs) {
|
|
@@ -41,12 +58,13 @@ async function readSlowData(projectRoot, activeDiscoveryId, now, ttlMs) {
|
|
|
41
58
|
if (cached && cached.expiresAt > now() && cached.activeDiscoveryId === activeDiscoveryId) {
|
|
42
59
|
return cached.value;
|
|
43
60
|
}
|
|
44
|
-
const [doctor, discoveries, commands] = await Promise.all([
|
|
61
|
+
const [doctor, discoveries, commands, graph] = await Promise.all([
|
|
45
62
|
runDoctor(projectRoot, { fix: false }),
|
|
46
63
|
readDiscoveries(projectRoot, activeDiscoveryId),
|
|
47
|
-
readCommandCatalog(projectRoot)
|
|
64
|
+
readCommandCatalog(projectRoot),
|
|
65
|
+
buildCodeGraph(projectRoot)
|
|
48
66
|
]);
|
|
49
|
-
const value = { doctor, discoveries, commands };
|
|
67
|
+
const value = { doctor, discoveries, commands, graph };
|
|
50
68
|
slowCache.set(projectRoot, { expiresAt: now() + ttlMs, activeDiscoveryId, value });
|
|
51
69
|
return value;
|
|
52
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-snapshot.js","sourceRoot":"","sources":["../../lib/dashboard-snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"dashboard-snapshot.js","sourceRoot":"","sources":["../../lib/dashboard-snapshot.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/dashboard.js
CHANGED
|
@@ -4,6 +4,8 @@ import { DASHBOARD_PAGE_HTML } from "./dashboard-page.js";
|
|
|
4
4
|
import { readDashboardSnapshot } from "./dashboard-snapshot.js";
|
|
5
5
|
import { readHistory } from "./history.js";
|
|
6
6
|
import { readProjectStatus } from "./status.js";
|
|
7
|
+
import { buildCodeGraph, calculateBlastRadius } from "./code-graph.js";
|
|
8
|
+
import { reconcileState } from "./drift-reconciler.js";
|
|
7
9
|
const DASHBOARD_HOST = "127.0.0.1";
|
|
8
10
|
async function startDashboardServer(startPath = process.cwd(), options = {}) {
|
|
9
11
|
const initialStatus = await readProjectStatus(startPath);
|
|
@@ -83,6 +85,42 @@ async function handleRequest(projectRoot, request, response, snapshotOptions) {
|
|
|
83
85
|
}
|
|
84
86
|
return;
|
|
85
87
|
}
|
|
88
|
+
if (pathname === "/api/graph") {
|
|
89
|
+
try {
|
|
90
|
+
const urlObj = new URL(request.url || "/", `http://${DASHBOARD_HOST}`);
|
|
91
|
+
const targetFile = urlObj.searchParams.get("file");
|
|
92
|
+
const graph = await buildCodeGraph(projectRoot);
|
|
93
|
+
if (targetFile && targetFile.trim().length > 0) {
|
|
94
|
+
const blast = calculateBlastRadius(graph, targetFile.trim());
|
|
95
|
+
sendResponse(response, method, 200, "application/json; charset=utf-8", `${JSON.stringify(blast)}\n`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
sendResponse(response, method, 200, "application/json; charset=utf-8", `${JSON.stringify({
|
|
99
|
+
totalFiles: graph.totalFiles,
|
|
100
|
+
totalEdges: graph.totalEdges,
|
|
101
|
+
files: Object.keys(graph.nodes)
|
|
102
|
+
})}\n`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
sendResponse(response, method, 500, "application/json; charset=utf-8", `${JSON.stringify({
|
|
107
|
+
error: error instanceof Error ? error.message : "Unable to query code graph."
|
|
108
|
+
})}\n`);
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (pathname === "/api/reconcile") {
|
|
113
|
+
try {
|
|
114
|
+
const result = await reconcileState(projectRoot, { healStage: true });
|
|
115
|
+
sendResponse(response, method, 200, "application/json; charset=utf-8", `${JSON.stringify(result)}\n`);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
sendResponse(response, method, 500, "application/json; charset=utf-8", `${JSON.stringify({
|
|
119
|
+
error: error instanceof Error ? error.message : "Unable to reconcile state."
|
|
120
|
+
})}\n`);
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
86
124
|
if (pathname === "/favicon.ico") {
|
|
87
125
|
sendResponse(response, method, 204, "text/plain; charset=utf-8", "");
|
|
88
126
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../lib/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../lib/dashboard.ts"],"names":[],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA0+BvB,CAAC;AAET,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC"}
|