@jakkrichm/create-nexus-devflow 2.12.4 → 2.14.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 +4 -4
- package/dist/bin/create-nexus-devflow.d.ts +1 -1
- package/dist/bin/create-nexus-devflow.js +4 -3
- package/dist/bin/create-nexus-devflow.js.map +1 -1
- package/dist/lib/active-context-engine.d.ts +47 -0
- package/dist/lib/active-context-engine.js +174 -0
- package/dist/lib/active-context-engine.js.map +1 -0
- package/dist/lib/branch-context.d.ts +1 -0
- package/dist/lib/branch-context.js +1 -0
- package/dist/lib/branch-context.js.map +1 -1
- package/dist/lib/current-work.js +3 -28
- package/dist/lib/current-work.js.map +1 -1
- package/dist/lib/dashboard-engine.d.ts +54 -0
- package/dist/lib/dashboard-engine.js +109 -0
- package/dist/lib/dashboard-engine.js.map +1 -0
- package/dist/lib/dashboard-page.d.ts +8 -1
- package/dist/lib/dashboard-page.js +10 -1
- package/dist/lib/dashboard-page.js.map +1 -1
- package/dist/lib/dashboard.d.ts +2 -0
- package/dist/lib/dashboard.js +78 -1068
- package/dist/lib/dashboard.js.map +1 -1
- package/dist/lib/delivery-lifecycle-engine.d.ts +96 -0
- package/dist/lib/delivery-lifecycle-engine.js +388 -0
- package/dist/lib/delivery-lifecycle-engine.js.map +1 -0
- package/dist/lib/gatekeeper-engine.d.ts +65 -0
- package/dist/lib/gatekeeper-engine.js +155 -0
- package/dist/lib/gatekeeper-engine.js.map +1 -0
- package/dist/lib/gatekeeper.d.ts +3 -22
- package/dist/lib/gatekeeper.js +4 -67
- package/dist/lib/gatekeeper.js.map +1 -1
- package/dist/lib/history.d.ts +3 -1
- package/dist/lib/history.js +2 -1
- package/dist/lib/history.js.map +1 -1
- package/dist/lib/skill-manager.js +319 -7
- package/dist/lib/skill-manager.js.map +1 -1
- package/dist/lib/studio-view-renderer.d.ts +50 -0
- package/dist/lib/studio-view-renderer.js +773 -0
- package/dist/lib/studio-view-renderer.js.map +1 -0
- package/dist/lib/tooling/commands/link-project.d.ts +2 -0
- package/dist/lib/tooling/commands/link-project.js +22 -0
- package/dist/lib/tooling/commands/link-project.js.map +1 -0
- package/dist/lib/tooling/commands/migrate-stage-artifacts.d.ts +2 -0
- package/dist/lib/tooling/commands/migrate-stage-artifacts.js +61 -0
- package/dist/lib/tooling/commands/migrate-stage-artifacts.js.map +1 -0
- package/dist/lib/tooling/commands/render-html.d.ts +2 -0
- package/dist/lib/tooling/commands/render-html.js +78 -0
- package/dist/lib/tooling/commands/render-html.js.map +1 -0
- package/dist/lib/tooling/commands/report-html.d.ts +2 -0
- package/dist/lib/tooling/commands/report-html.js +27 -0
- package/dist/lib/tooling/commands/report-html.js.map +1 -0
- package/dist/lib/tooling/commands/scan-doc-contract.d.ts +2 -0
- package/dist/lib/tooling/commands/scan-doc-contract.js +78 -0
- package/dist/lib/tooling/commands/scan-doc-contract.js.map +1 -0
- package/dist/lib/tooling/commands/scan-security-hygiene.d.ts +2 -0
- package/dist/lib/tooling/commands/scan-security-hygiene.js +93 -0
- package/dist/lib/tooling/commands/scan-security-hygiene.js.map +1 -0
- package/dist/lib/tooling/commands/skill-descriptions.d.ts +2 -0
- package/dist/lib/tooling/commands/skill-descriptions.js +50 -0
- package/dist/lib/tooling/commands/skill-descriptions.js.map +1 -0
- package/dist/lib/tooling/commands/summarize-run-status.d.ts +2 -0
- package/dist/lib/tooling/commands/summarize-run-status.js +65 -0
- package/dist/lib/tooling/commands/summarize-run-status.js.map +1 -0
- package/dist/lib/tooling/commands/switch-artifact-language.d.ts +2 -0
- package/dist/lib/tooling/commands/switch-artifact-language.js +87 -0
- package/dist/lib/tooling/commands/switch-artifact-language.js.map +1 -0
- package/dist/lib/tooling/index.d.ts +4 -0
- package/dist/lib/tooling/index.js +23 -0
- package/dist/lib/tooling/index.js.map +1 -0
- package/dist/lib/tooling/registry.d.ts +6 -0
- package/dist/lib/tooling/registry.js +56 -0
- package/dist/lib/tooling/registry.js.map +1 -0
- package/dist/lib/tooling/types.d.ts +19 -0
- package/dist/lib/tooling/types.js +10 -0
- package/dist/lib/tooling/types.js.map +1 -0
- package/dist/lib/update.js +1 -1
- package/dist/lib/update.js.map +1 -1
- package/dist/lib/webview-studio.d.ts +5 -0
- package/dist/lib/webview-studio.js +11 -577
- package/dist/lib/webview-studio.js.map +1 -1
- package/package.json +1 -1
- package/template/AGENTS.md +1 -1
- package/template/devflow/docs/USAGE.md +145 -0
- package/template/devflow/docs/diagrams/nexus-devflow-architecture.html +14821 -0
- package/template/devflow/docs/diagrams/nexus-devflow-architecture.json +80 -0
- package/template/devflow/docs/diagrams/nexus-devflow-lifecycle.html +14860 -0
- package/template/devflow/docs/diagrams/nexus-devflow-lifecycle.json +88 -0
- package/template/devflow/docs/examples/living-spec/adr.example.md +43 -0
- package/template/devflow/docs/examples/living-spec/current-feature.example.md +113 -0
- package/template/devflow/docs/examples/living-spec/discovery.example.md +45 -0
- package/template/devflow/docs/examples/living-spec/ideas.example.md +22 -0
- package/template/devflow/docs/governance-rules.md +39 -0
- package/template/devflow/docs/manual-review-workflow-spec.md +116 -0
- package/template/devflow/docs/markdown-metadata-contract.md +140 -0
- package/template/devflow/docs/quickstart.md +119 -0
- package/template/devflow/docs/release-process.md +52 -0
- package/template/devflow/docs/skill-selection-policy.md +64 -0
- package/template/devflow/docs/workflow-surface-map.md +85 -0
|
@@ -1,585 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { evaluateGate } from "./gatekeeper.js";
|
|
3
|
-
import { detectGitDrift } from "./drift-reconciler.js";
|
|
1
|
+
import { DashboardStateEngine } from "./dashboard-engine.js";
|
|
4
2
|
import { readIdeas } from "./ideas.js";
|
|
5
|
-
|
|
6
|
-
* Escapes HTML characters safely.
|
|
7
|
-
*/
|
|
8
|
-
function escapeHtml(str) {
|
|
9
|
-
if (!str)
|
|
10
|
-
return "";
|
|
11
|
-
return String(str)
|
|
12
|
-
.replace(/&/g, "&")
|
|
13
|
-
.replace(/</g, "<")
|
|
14
|
-
.replace(/>/g, ">")
|
|
15
|
-
.replace(/"/g, """)
|
|
16
|
-
.replace(/'/g, "'");
|
|
17
|
-
}
|
|
3
|
+
import { StudioViewRenderer } from "./studio-view-renderer.js";
|
|
18
4
|
/**
|
|
19
5
|
* Renders a self-contained, interactive Webview Studio HTML page.
|
|
6
|
+
* Delegates to StudioViewRenderer.
|
|
20
7
|
*/
|
|
21
8
|
export async function renderStudioHtml(projectRoot, options = {}) {
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const driftReport = await detectGitDrift(projectRoot);
|
|
9
|
+
const engine = options.engine ?? new DashboardStateEngine(projectRoot);
|
|
10
|
+
const snapshot = await engine.getSnapshot();
|
|
25
11
|
const ideas = await readIdeas(projectRoot);
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const track = snapshot.workflow.track || (currentWork.state === "active" ? "fast" : "idle");
|
|
32
|
-
const isGatePassed = gateReport.passed;
|
|
33
|
-
const gatePillClass = isGatePassed ? "badge-pass" : "badge-blocked";
|
|
34
|
-
const gatePillText = isGatePassed ? "✔ Gate Passed" : "✖ Gate Blocked";
|
|
35
|
-
const ideasHtml = ideas.pending.length > 0
|
|
36
|
-
? ideas.pending.map((idea) => `
|
|
37
|
-
<div class="card-item idea-item">
|
|
38
|
-
<div class="item-header">
|
|
39
|
-
<span class="badge-id">${escapeHtml(idea.id)}</span>
|
|
40
|
-
<span class="item-title">${escapeHtml(idea.title || idea.rawInput.slice(0, 40))}</span>
|
|
41
|
-
</div>
|
|
42
|
-
<div class="item-tags">
|
|
43
|
-
<span class="tag tag-feasibility">${escapeHtml(idea.feasibility || "Feasible")}</span>
|
|
44
|
-
<span class="tag tag-value">${escapeHtml(idea.value || "Value: High")}</span>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
`).join("")
|
|
48
|
-
: `<div class="empty-state">No pending ideas in inbox. Use <code>nexus-devflow idea add</code></div>`;
|
|
49
|
-
const historyHtml = snapshot.history.items.length > 0
|
|
50
|
-
? snapshot.history.items.slice(0, 8).map((item) => {
|
|
51
|
-
const runId = item.buildPlanItem || item.file.replace(/\.md$/, "");
|
|
52
|
-
return `
|
|
53
|
-
<div class="card-item history-item">
|
|
54
|
-
<div class="item-header">
|
|
55
|
-
<span class="badge-id badge-history">${escapeHtml(runId)}</span>
|
|
56
|
-
<span class="item-title">${escapeHtml(item.title)}</span>
|
|
57
|
-
</div>
|
|
58
|
-
<div class="item-meta">
|
|
59
|
-
<span class="tag tag-cat">${escapeHtml(item.type)}</span>
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
`;
|
|
63
|
-
}).join("")
|
|
64
|
-
: `<div class="empty-state">No archived history records yet.</div>`;
|
|
65
|
-
const activeRuns = status.activeRuns || [];
|
|
66
|
-
let presentHtml = "";
|
|
67
|
-
let totalActiveTasks = 0;
|
|
68
|
-
let totalActiveCompleted = 0;
|
|
69
|
-
if (activeRuns.length > 0) {
|
|
70
|
-
totalActiveTasks = activeRuns.reduce((acc, r) => acc + r.totalTasks, 0);
|
|
71
|
-
totalActiveCompleted = activeRuns.reduce((acc, r) => acc + r.completedTasks, 0);
|
|
72
|
-
presentHtml = activeRuns.map((run) => {
|
|
73
|
-
const pct = run.totalTasks > 0 ? Math.round((run.completedTasks / run.totalTasks) * 100) : 0;
|
|
74
|
-
const stageBadgeClass = (run.status || "").includes("check") ? "badge-stage stage-check" : "badge-stage";
|
|
75
|
-
const findingTag = run.hasOpenFindings
|
|
76
|
-
? `<span class="tag tag-finding-warn">⚠ Open Findings</span>`
|
|
77
|
-
: `<span class="tag tag-finding-clean">✔ Clean</span>`;
|
|
78
|
-
return `
|
|
79
|
-
<div class="card-item active-item">
|
|
80
|
-
<div class="item-header">
|
|
81
|
-
<span class="badge-id">${escapeHtml(run.runId)}</span>
|
|
82
|
-
<span class="${stageBadgeClass}">${escapeHtml(run.status || "active")}</span>
|
|
83
|
-
</div>
|
|
84
|
-
<div class="item-title">${escapeHtml(run.title || "Living Spec")}</div>
|
|
85
|
-
<div class="progress-bar-container">
|
|
86
|
-
<div class="progress-bar-fill" style="width: ${pct}%;"></div>
|
|
87
|
-
</div>
|
|
88
|
-
<div class="item-meta">
|
|
89
|
-
<span>🌿 <code>${escapeHtml(run.branch || "main")}</code></span>
|
|
90
|
-
${findingTag}
|
|
91
|
-
</div>
|
|
92
|
-
<div class="item-tags">
|
|
93
|
-
<span>Progress: <strong>${pct}%</strong> (${run.completedTasks}/${run.totalTasks})</span>
|
|
94
|
-
<span>Remaining: ${run.remainingTasks}</span>
|
|
95
|
-
</div>
|
|
96
|
-
<div class="card-actions">
|
|
97
|
-
<button class="btn-card-action" onclick="dispatchCommand('/implement ${escapeHtml(run.runId)}')">▶ /implement ${escapeHtml(run.runId)}</button>
|
|
98
|
-
<button class="btn-card-action" onclick="dispatchCommand('/check ${escapeHtml(run.runId)}')">🧪 /check ${escapeHtml(run.runId)}</button>
|
|
99
|
-
<button class="btn-card-action" onclick="dispatchCommand('/complete ${escapeHtml(run.runId)}')">📦 /complete ${escapeHtml(run.runId)}</button>
|
|
100
|
-
</div>
|
|
101
|
-
</div>
|
|
102
|
-
`;
|
|
103
|
-
}).join("");
|
|
104
|
-
}
|
|
105
|
-
else if (currentWork.state === "active") {
|
|
106
|
-
totalActiveTasks = currentWork.total;
|
|
107
|
-
totalActiveCompleted = currentWork.completed;
|
|
108
|
-
const progressPercent = totalActiveTasks > 0 ? Math.round((totalActiveCompleted / totalActiveTasks) * 100) : 0;
|
|
109
|
-
const runId = currentWork.runId || "ACTIVE";
|
|
110
|
-
presentHtml = `
|
|
111
|
-
<div class="card-item active-item">
|
|
112
|
-
<div class="item-header">
|
|
113
|
-
<span class="badge-id">${escapeHtml(runId)}</span>
|
|
114
|
-
<span class="badge-stage">${escapeHtml(currentWork.status || "active")}</span>
|
|
115
|
-
</div>
|
|
116
|
-
<div class="item-title">${escapeHtml(currentWork.title || "Active Spec")}</div>
|
|
117
|
-
<div class="progress-bar-container">
|
|
118
|
-
<div class="progress-bar-fill" style="width: ${progressPercent}%;"></div>
|
|
119
|
-
</div>
|
|
120
|
-
<div class="item-meta">
|
|
121
|
-
<span>Progress: <strong>${progressPercent}%</strong> (${currentWork.completed}/${currentWork.total})</span>
|
|
122
|
-
<span>Remaining: ${currentWork.remaining}</span>
|
|
123
|
-
</div>
|
|
124
|
-
<div class="card-actions">
|
|
125
|
-
<button class="btn-card-action" onclick="dispatchCommand('/implement ${escapeHtml(runId)}')">▶ /implement ${escapeHtml(runId)}</button>
|
|
126
|
-
<button class="btn-card-action" onclick="dispatchCommand('/check ${escapeHtml(runId)}')">🧪 /check ${escapeHtml(runId)}</button>
|
|
127
|
-
<button class="btn-card-action" onclick="dispatchCommand('/complete ${escapeHtml(runId)}')">📦 /complete ${escapeHtml(runId)}</button>
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
`;
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
presentHtml = `
|
|
134
|
-
<div class="empty-state">
|
|
135
|
-
Idle workspace.<br>Run <code>/feature</code> or <code>/fix</code> to start a run.
|
|
136
|
-
</div>
|
|
137
|
-
`;
|
|
138
|
-
}
|
|
139
|
-
const presentCountLabel = activeRuns.length > 0
|
|
140
|
-
? `${activeRuns.length} Active Runs · ${totalActiveCompleted}/${totalActiveTasks} Tasks`
|
|
141
|
-
: `${totalActiveCompleted}/${totalActiveTasks} Tasks`;
|
|
142
|
-
return `<!DOCTYPE html>
|
|
143
|
-
<html lang="th" data-theme="${options.theme || "auto"}">
|
|
144
|
-
<head>
|
|
145
|
-
<meta charset="UTF-8">
|
|
146
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
147
|
-
<title>Nexus-DevFlow Studio: ${escapeHtml(projectName)}</title>
|
|
148
|
-
<style>
|
|
149
|
-
:root {
|
|
150
|
-
--bg: var(--vscode-editor-background, #070d18);
|
|
151
|
-
--bg-panel: var(--vscode-sideBar-background, rgba(15, 23, 42, 0.75));
|
|
152
|
-
--bg-card: rgba(30, 41, 59, 0.65);
|
|
153
|
-
--border: var(--vscode-panel-border, rgba(255, 255, 255, 0.08));
|
|
154
|
-
--border-accent: rgba(56, 189, 248, 0.35);
|
|
155
|
-
--fg: var(--vscode-editor-foreground, #f8fafc);
|
|
156
|
-
--fg-muted: var(--vscode-descriptionForeground, #94a3b8);
|
|
157
|
-
--accent: #38bdf8;
|
|
158
|
-
--accent-gradient: linear-gradient(135deg, #38bdf8 0%, #818cf8 100%);
|
|
159
|
-
--green: #4ade80;
|
|
160
|
-
--yellow: #facc15;
|
|
161
|
-
--red: #f87171;
|
|
162
|
-
--violet: #a78bfa;
|
|
163
|
-
--font-mono: var(--vscode-editor-font-family, 'IBM Plex Mono', 'Fira Code', Consolas, monospace);
|
|
164
|
-
--font-sans: var(--vscode-font-family, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
168
|
-
body {
|
|
169
|
-
font-family: var(--font-sans);
|
|
170
|
-
background-color: var(--bg);
|
|
171
|
-
color: var(--fg);
|
|
172
|
-
padding: 16px;
|
|
173
|
-
line-height: 1.5;
|
|
174
|
-
font-size: 13px;
|
|
175
|
-
overflow-x: hidden;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
.studio-container {
|
|
179
|
-
max-width: 1280px;
|
|
180
|
-
margin: 0 auto;
|
|
181
|
-
display: flex;
|
|
182
|
-
flex-direction: column;
|
|
183
|
-
gap: 16px;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/* Top Studio Header */
|
|
187
|
-
.studio-header {
|
|
188
|
-
background: var(--bg-panel);
|
|
189
|
-
backdrop-filter: blur(12px);
|
|
190
|
-
border: 1px solid var(--border);
|
|
191
|
-
border-radius: 12px;
|
|
192
|
-
padding: 16px 20px;
|
|
193
|
-
display: flex;
|
|
194
|
-
align-items: center;
|
|
195
|
-
justify-content: space-between;
|
|
196
|
-
flex-wrap: wrap;
|
|
197
|
-
gap: 12px;
|
|
198
|
-
}
|
|
199
|
-
.header-left {
|
|
200
|
-
display: flex;
|
|
201
|
-
align-items: center;
|
|
202
|
-
gap: 12px;
|
|
203
|
-
flex-wrap: wrap;
|
|
204
|
-
}
|
|
205
|
-
.project-badge {
|
|
206
|
-
font-weight: 800;
|
|
207
|
-
font-size: 16px;
|
|
208
|
-
background: var(--accent-gradient);
|
|
209
|
-
-webkit-background-clip: text;
|
|
210
|
-
-webkit-text-fill-color: transparent;
|
|
211
|
-
letter-spacing: -0.5px;
|
|
212
|
-
}
|
|
213
|
-
.branch-pill {
|
|
214
|
-
font-family: var(--font-mono);
|
|
215
|
-
font-size: 11px;
|
|
216
|
-
background: rgba(56, 189, 248, 0.12);
|
|
217
|
-
color: var(--accent);
|
|
218
|
-
padding: 3px 10px;
|
|
219
|
-
border-radius: 20px;
|
|
220
|
-
border: 1px solid var(--border-accent);
|
|
221
|
-
}
|
|
222
|
-
.multitask-pill {
|
|
223
|
-
font-family: var(--font-mono);
|
|
224
|
-
font-size: 11px;
|
|
225
|
-
background: rgba(167, 139, 250, 0.15);
|
|
226
|
-
color: var(--violet);
|
|
227
|
-
padding: 3px 10px;
|
|
228
|
-
border-radius: 20px;
|
|
229
|
-
border: 1px solid rgba(167, 139, 250, 0.3);
|
|
230
|
-
font-weight: 700;
|
|
231
|
-
}
|
|
232
|
-
.header-right {
|
|
233
|
-
display: flex;
|
|
234
|
-
align-items: center;
|
|
235
|
-
gap: 10px;
|
|
236
|
-
}
|
|
237
|
-
.badge-pass {
|
|
238
|
-
background: rgba(74, 222, 128, 0.15);
|
|
239
|
-
color: var(--green);
|
|
240
|
-
border: 1px solid rgba(74, 222, 128, 0.3);
|
|
241
|
-
padding: 4px 12px;
|
|
242
|
-
border-radius: 20px;
|
|
243
|
-
font-weight: 600;
|
|
244
|
-
font-size: 11px;
|
|
245
|
-
}
|
|
246
|
-
.badge-blocked {
|
|
247
|
-
background: rgba(248, 113, 113, 0.15);
|
|
248
|
-
color: var(--red);
|
|
249
|
-
border: 1px solid rgba(248, 113, 113, 0.3);
|
|
250
|
-
padding: 4px 12px;
|
|
251
|
-
border-radius: 20px;
|
|
252
|
-
font-weight: 600;
|
|
253
|
-
font-size: 11px;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/* Quick Action Dispatcher */
|
|
257
|
-
.action-bar {
|
|
258
|
-
background: var(--bg-panel);
|
|
259
|
-
border: 1px solid var(--border);
|
|
260
|
-
border-radius: 10px;
|
|
261
|
-
padding: 10px 16px;
|
|
262
|
-
display: flex;
|
|
263
|
-
align-items: center;
|
|
264
|
-
gap: 8px;
|
|
265
|
-
overflow-x: auto;
|
|
266
|
-
}
|
|
267
|
-
.action-label {
|
|
268
|
-
font-weight: 700;
|
|
269
|
-
color: var(--fg-muted);
|
|
270
|
-
font-size: 10px;
|
|
271
|
-
text-transform: uppercase;
|
|
272
|
-
letter-spacing: 0.08em;
|
|
273
|
-
margin-right: 4px;
|
|
274
|
-
white-space: nowrap;
|
|
275
|
-
}
|
|
276
|
-
.btn-action {
|
|
277
|
-
background: var(--bg-card);
|
|
278
|
-
border: 1px solid var(--border);
|
|
279
|
-
color: var(--fg);
|
|
280
|
-
padding: 5px 12px;
|
|
281
|
-
border-radius: 6px;
|
|
282
|
-
cursor: pointer;
|
|
283
|
-
font-family: var(--font-mono);
|
|
284
|
-
font-size: 11px;
|
|
285
|
-
transition: all 0.2s ease;
|
|
286
|
-
white-space: nowrap;
|
|
287
|
-
}
|
|
288
|
-
.btn-action:hover {
|
|
289
|
-
background: rgba(56, 189, 248, 0.15);
|
|
290
|
-
border-color: var(--accent);
|
|
291
|
-
color: var(--accent);
|
|
292
|
-
}
|
|
293
|
-
.btn-action.btn-primary {
|
|
294
|
-
background: var(--accent-gradient);
|
|
295
|
-
color: #040812;
|
|
296
|
-
font-weight: 700;
|
|
297
|
-
border: none;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/* 3-Pillars Kanban Grid */
|
|
301
|
-
.kanban-grid {
|
|
302
|
-
display: grid;
|
|
303
|
-
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
|
304
|
-
gap: 16px;
|
|
305
|
-
}
|
|
306
|
-
.kanban-col {
|
|
307
|
-
background: var(--bg-panel);
|
|
308
|
-
border: 1px solid var(--border);
|
|
309
|
-
border-radius: 12px;
|
|
310
|
-
padding: 16px;
|
|
311
|
-
display: flex;
|
|
312
|
-
flex-direction: column;
|
|
313
|
-
gap: 12px;
|
|
314
|
-
}
|
|
315
|
-
.col-header {
|
|
316
|
-
display: flex;
|
|
317
|
-
align-items: center;
|
|
318
|
-
justify-content: space-between;
|
|
319
|
-
border-bottom: 1px solid var(--border);
|
|
320
|
-
padding-bottom: 10px;
|
|
321
|
-
}
|
|
322
|
-
.col-title {
|
|
323
|
-
font-size: 13px;
|
|
324
|
-
font-weight: 700;
|
|
325
|
-
display: flex;
|
|
326
|
-
align-items: center;
|
|
327
|
-
gap: 6px;
|
|
328
|
-
}
|
|
329
|
-
.col-count {
|
|
330
|
-
font-size: 10px;
|
|
331
|
-
font-family: var(--font-mono);
|
|
332
|
-
font-weight: 600;
|
|
333
|
-
background: var(--bg-card);
|
|
334
|
-
padding: 2px 8px;
|
|
335
|
-
border-radius: 10px;
|
|
336
|
-
color: var(--fg-muted);
|
|
337
|
-
border: 1px solid var(--border);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
.col-content {
|
|
341
|
-
display: flex;
|
|
342
|
-
flex-direction: column;
|
|
343
|
-
gap: 10px;
|
|
344
|
-
max-height: 520px;
|
|
345
|
-
overflow-y: auto;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/* Card Items */
|
|
349
|
-
.card-item {
|
|
350
|
-
background: var(--bg-card);
|
|
351
|
-
border: 1px solid var(--border);
|
|
352
|
-
border-radius: 8px;
|
|
353
|
-
padding: 12px;
|
|
354
|
-
display: flex;
|
|
355
|
-
flex-direction: column;
|
|
356
|
-
gap: 6px;
|
|
357
|
-
transition: transform 0.15s ease, border-color 0.15s ease;
|
|
358
|
-
}
|
|
359
|
-
.card-item:hover {
|
|
360
|
-
border-color: var(--border-accent);
|
|
361
|
-
transform: translateY(-1px);
|
|
362
|
-
}
|
|
363
|
-
.card-item.active-item {
|
|
364
|
-
border-color: var(--border-accent);
|
|
365
|
-
box-shadow: 0 0 12px rgba(56, 189, 248, 0.12);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
.item-header {
|
|
369
|
-
display: flex;
|
|
370
|
-
align-items: flex-start;
|
|
371
|
-
justify-content: space-between;
|
|
372
|
-
gap: 8px;
|
|
373
|
-
}
|
|
374
|
-
.badge-id {
|
|
375
|
-
font-family: var(--font-mono);
|
|
376
|
-
font-size: 10px;
|
|
377
|
-
font-weight: 700;
|
|
378
|
-
background: rgba(56, 189, 248, 0.2);
|
|
379
|
-
color: var(--accent);
|
|
380
|
-
padding: 2px 6px;
|
|
381
|
-
border-radius: 4px;
|
|
382
|
-
white-space: nowrap;
|
|
383
|
-
}
|
|
384
|
-
.badge-history {
|
|
385
|
-
background: rgba(129, 140, 248, 0.2);
|
|
386
|
-
color: #818cf8;
|
|
387
|
-
}
|
|
388
|
-
.badge-stage {
|
|
389
|
-
font-family: var(--font-mono);
|
|
390
|
-
font-size: 9px;
|
|
391
|
-
font-weight: 700;
|
|
392
|
-
text-transform: uppercase;
|
|
393
|
-
padding: 1px 6px;
|
|
394
|
-
border-radius: 4px;
|
|
395
|
-
background: rgba(250, 204, 21, 0.15);
|
|
396
|
-
color: var(--yellow);
|
|
397
|
-
border: 1px solid rgba(250, 204, 21, 0.3);
|
|
398
|
-
}
|
|
399
|
-
.badge-stage.stage-check {
|
|
400
|
-
background: rgba(74, 222, 128, 0.15);
|
|
401
|
-
color: var(--green);
|
|
402
|
-
border-color: rgba(74, 222, 128, 0.3);
|
|
403
|
-
}
|
|
404
|
-
.item-title {
|
|
405
|
-
font-weight: 600;
|
|
406
|
-
font-size: 12px;
|
|
407
|
-
flex: 1;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/* Progress bar */
|
|
411
|
-
.progress-bar-container {
|
|
412
|
-
background: rgba(0, 0, 0, 0.3);
|
|
413
|
-
height: 6px;
|
|
414
|
-
border-radius: 3px;
|
|
415
|
-
overflow: hidden;
|
|
416
|
-
margin-top: 4px;
|
|
417
|
-
}
|
|
418
|
-
.progress-bar-fill {
|
|
419
|
-
background: var(--accent-gradient);
|
|
420
|
-
height: 100%;
|
|
421
|
-
transition: width 0.3s ease;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
.item-tags, .item-meta {
|
|
425
|
-
display: flex;
|
|
426
|
-
align-items: center;
|
|
427
|
-
justify-content: space-between;
|
|
428
|
-
gap: 6px;
|
|
429
|
-
font-size: 11px;
|
|
430
|
-
color: var(--fg-muted);
|
|
431
|
-
flex-wrap: wrap;
|
|
432
|
-
}
|
|
433
|
-
.tag {
|
|
434
|
-
font-size: 10px;
|
|
435
|
-
padding: 1px 6px;
|
|
436
|
-
border-radius: 4px;
|
|
437
|
-
background: rgba(255, 255, 255, 0.05);
|
|
438
|
-
border: 1px solid var(--border);
|
|
439
|
-
}
|
|
440
|
-
.tag-feasibility { color: var(--green); }
|
|
441
|
-
.tag-value { color: var(--accent); }
|
|
442
|
-
.tag-cat { color: var(--yellow); }
|
|
443
|
-
.tag-finding-clean { color: var(--green); }
|
|
444
|
-
.tag-finding-warn { color: var(--red); background: rgba(248, 113, 113, 0.15); border-color: rgba(248, 113, 113, 0.3); }
|
|
445
|
-
|
|
446
|
-
.card-actions {
|
|
447
|
-
display: flex;
|
|
448
|
-
align-items: center;
|
|
449
|
-
gap: 6px;
|
|
450
|
-
margin-top: 4px;
|
|
451
|
-
padding-top: 6px;
|
|
452
|
-
border-top: 1px dashed var(--border);
|
|
453
|
-
flex-wrap: wrap;
|
|
454
|
-
}
|
|
455
|
-
.btn-card-action {
|
|
456
|
-
background: rgba(255, 255, 255, 0.04);
|
|
457
|
-
border: 1px solid var(--border);
|
|
458
|
-
color: var(--fg);
|
|
459
|
-
padding: 2px 7px;
|
|
460
|
-
border-radius: 4px;
|
|
461
|
-
font-family: var(--font-mono);
|
|
462
|
-
font-size: 10px;
|
|
463
|
-
cursor: pointer;
|
|
464
|
-
transition: all 0.15s ease;
|
|
465
|
-
}
|
|
466
|
-
.btn-card-action:hover {
|
|
467
|
-
background: rgba(56, 189, 248, 0.15);
|
|
468
|
-
color: var(--accent);
|
|
469
|
-
border-color: var(--accent);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
.empty-state {
|
|
473
|
-
text-align: center;
|
|
474
|
-
padding: 24px;
|
|
475
|
-
color: var(--fg-muted);
|
|
476
|
-
font-size: 12px;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/* Pulse Notification */
|
|
480
|
-
.pulse-panel {
|
|
481
|
-
background: var(--bg-panel);
|
|
482
|
-
border: 1px solid var(--border);
|
|
483
|
-
border-radius: 10px;
|
|
484
|
-
padding: 12px 16px;
|
|
485
|
-
display: flex;
|
|
486
|
-
align-items: center;
|
|
487
|
-
justify-content: space-between;
|
|
488
|
-
font-size: 12px;
|
|
489
|
-
flex-wrap: wrap;
|
|
490
|
-
gap: 8px;
|
|
491
|
-
}
|
|
492
|
-
</style>
|
|
493
|
-
</head>
|
|
494
|
-
<body>
|
|
495
|
-
<div class="studio-container">
|
|
496
|
-
|
|
497
|
-
<!-- Top Header -->
|
|
498
|
-
<header class="studio-header">
|
|
499
|
-
<div class="header-left">
|
|
500
|
-
<span class="project-badge">⚡ ${escapeHtml(projectName)}</span>
|
|
501
|
-
<span class="branch-pill">🌿 ${escapeHtml(branch)}</span>
|
|
502
|
-
${activeRuns.length > 0 ? `<span class="multitask-pill">🗂️ ${activeRuns.length} Active Workspaces</span>` : ""}
|
|
503
|
-
</div>
|
|
504
|
-
<div class="header-right">
|
|
505
|
-
<span class="${gatePillClass}">${gatePillText}</span>
|
|
506
|
-
<button class="btn-action btn-primary" onclick="dispatchCommand('${escapeHtml(nextActionCmd)}')">
|
|
507
|
-
Next: ${escapeHtml(nextActionCmd)}
|
|
508
|
-
</button>
|
|
509
|
-
</div>
|
|
510
|
-
</header>
|
|
511
|
-
|
|
512
|
-
<!-- Quick Action Bar -->
|
|
513
|
-
<div class="action-bar">
|
|
514
|
-
<span class="action-label">Quick Actions:</span>
|
|
515
|
-
<button class="btn-action" onclick="dispatchCommand('/feature')">/feature</button>
|
|
516
|
-
<button class="btn-action" onclick="dispatchCommand('/implement')">/implement</button>
|
|
517
|
-
<button class="btn-action" onclick="dispatchCommand('/check')">/check</button>
|
|
518
|
-
<button class="btn-action" onclick="dispatchCommand('/complete')">/complete</button>
|
|
519
|
-
<button class="btn-action" onclick="dispatchCommand('/continuous')">/continuous</button>
|
|
520
|
-
<button class="btn-action" onclick="dispatchCommand('nexus-devflow check-gate')">check-gate</button>
|
|
521
|
-
<button class="btn-action" onclick="dispatchCommand('nexus-devflow drift')">drift</button>
|
|
522
|
-
<button class="btn-action" onclick="dispatchCommand('nexus-devflow doctor')">doctor</button>
|
|
523
|
-
</div>
|
|
524
|
-
|
|
525
|
-
<!-- 3-Pillars Kanban View -->
|
|
526
|
-
<main class="kanban-grid">
|
|
527
|
-
|
|
528
|
-
<!-- 🔮 1. Future (Ideas Inbox) -->
|
|
529
|
-
<section class="kanban-col">
|
|
530
|
-
<div class="col-header">
|
|
531
|
-
<span class="col-title">🔮 Future (Ideas Inbox)</span>
|
|
532
|
-
<span class="col-count">${ideas.pending.length}</span>
|
|
533
|
-
</div>
|
|
534
|
-
<div class="col-content">
|
|
535
|
-
${ideasHtml}
|
|
536
|
-
</div>
|
|
537
|
-
</section>
|
|
538
|
-
|
|
539
|
-
<!-- ⚡ 2. Present (Active Living Context) -->
|
|
540
|
-
<section class="kanban-col">
|
|
541
|
-
<div class="col-header">
|
|
542
|
-
<span class="col-title">⚡ Present (Active Living Spec)</span>
|
|
543
|
-
<span class="col-count">${presentCountLabel}</span>
|
|
544
|
-
</div>
|
|
545
|
-
<div class="col-content">
|
|
546
|
-
${presentHtml}
|
|
547
|
-
</div>
|
|
548
|
-
</section>
|
|
549
|
-
|
|
550
|
-
<!-- 📦 3. Past (Release History Archive) -->
|
|
551
|
-
<section class="kanban-col">
|
|
552
|
-
<div class="col-header">
|
|
553
|
-
<span class="col-title">📦 Past (History Archives)</span>
|
|
554
|
-
<span class="col-count">${snapshot.history.total} Releases</span>
|
|
555
|
-
</div>
|
|
556
|
-
<div class="col-content">
|
|
557
|
-
${historyHtml}
|
|
558
|
-
</div>
|
|
559
|
-
</section>
|
|
560
|
-
|
|
561
|
-
</main>
|
|
562
|
-
|
|
563
|
-
<!-- Bottom Pulse -->
|
|
564
|
-
<footer class="pulse-panel">
|
|
565
|
-
<div>Findings Blockers: <strong>${gateReport.findingsBlockers}</strong> | Active Findings: <strong>${status.findings.total}</strong></div>
|
|
566
|
-
<div>Git Drift: <strong>${driftReport.hasDrift ? "⚠ Drift Detected" : "✔ In Sync"}</strong> | Workspaces: <strong>${activeRuns.length || (currentWork.state === "active" ? 1 : 0)} Active</strong></div>
|
|
567
|
-
</footer>
|
|
568
|
-
|
|
569
|
-
</div>
|
|
570
|
-
|
|
571
|
-
<script>
|
|
572
|
-
function dispatchCommand(cmd) {
|
|
573
|
-
if (window.acquireVsCodeApi) {
|
|
574
|
-
const vscode = window.acquireVsCodeApi();
|
|
575
|
-
vscode.postMessage({ command: 'exec', text: cmd });
|
|
576
|
-
} else if (navigator.clipboard) {
|
|
577
|
-
navigator.clipboard.writeText(cmd);
|
|
578
|
-
alert('Copied command to clipboard: ' + cmd);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
</script>
|
|
582
|
-
</body>
|
|
583
|
-
</html>`;
|
|
12
|
+
const renderer = new StudioViewRenderer({ defaultTheme: options.theme });
|
|
13
|
+
return renderer.renderWebviewStudio(snapshot, ideas, {
|
|
14
|
+
theme: options.theme,
|
|
15
|
+
includeScripts: options.includeScripts,
|
|
16
|
+
});
|
|
584
17
|
}
|
|
18
|
+
export { StudioViewRenderer };
|
|
585
19
|
//# sourceMappingURL=webview-studio.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webview-studio.js","sourceRoot":"","sources":["../../lib/webview-studio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"webview-studio.js","sourceRoot":"","sources":["../../lib/webview-studio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAQ/D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,WAAmB,EACnB,UAA+B,EAAE;IAEjC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,oBAAoB,CAAC,WAAW,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC;IAE3C,MAAM,QAAQ,GAAG,IAAI,kBAAkB,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACzE,OAAO,QAAQ,CAAC,mBAAmB,CAAC,QAAQ,EAAE,KAAK,EAAE;QACnD,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,cAAc,EAAE,OAAO,CAAC,cAAc;KACvC,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
package/package.json
CHANGED
package/template/AGENTS.md
CHANGED
|
@@ -42,7 +42,7 @@ Unused adapter families can be removed. Codex, Antigravity, GitHub Copilot, and
|
|
|
42
42
|
|
|
43
43
|
### Universal Invocation & Agent Directives:
|
|
44
44
|
|
|
45
|
-
1. **Canonical Command Names & AI Provider Invocation**: Each workflow stage and companion tool has exactly **one Canonical Name** (e.g. `feature`, `fix`, `implement`, `check`, `complete`, `continuous`, `analyze`, `discovery`, `idea`, `grill`, `brainstorm`, `bughunter`, `devflow`, `doctor`, `overview`, `debug`, `onboard`, `adopt`, `try`, `rollback`, `ci`, `test`, `setup-tests`, `browser-tests`, `autopilot`, `prototype`, `report-html`, `brief`, `audit`, `release`, `convert-any-to-md`, `publish-devflow`). The way you invoke commands depends on your AI Provider / Tool:
|
|
45
|
+
1. **Canonical Command Names & AI Provider Invocation**: Each workflow stage and companion tool has exactly **one Canonical Name** (e.g. `feature`, `fix`, `implement`, `check`, `complete`, `continuous`, `analyze`, `discovery`, `idea`, `grill`, `brainstorm`, `bughunter`, `devflow`, `doctor`, `overview`, `debug`, `onboard`, `adopt`, `try`, `rollback`, `ci`, `test`, `setup-tests`, `browser-tests`, `autopilot`, `prototype`, `report-html`, `brief`, `audit`, `release`, `convert-any-to-md`, `publish-devflow`, `matt-pocock`). The way you invoke commands depends on your AI Provider / Tool:
|
|
46
46
|
- **Canonical Name (Plain text)**: Directly invoke or prompt the command by its standard name (e.g., `feature`, `implement`, `continuous`, `devflow`, `discovery`, `analyze`).
|
|
47
47
|
- **Slash Prefix (`/`)**: For tools supporting slash commands (Claude Code, Google Antigravity, Gemini CLI), e.g., `/feature`, `/fix`, `/implement`, `/continuous`, `/devflow`, `/discovery`, `/analyze`.
|
|
48
48
|
- **Dollar Prefix (`$`)**: For OpenAI Codex CLI or skill-invocation tools, e.g., `$feature`, `$fix`, `$continuous`, `$devflow`, `$discovery`, `$analyze`.
|