shipwright-cli 2.2.2 → 2.3.1
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 +12 -11
- package/dashboard/public/index.html +224 -8
- package/dashboard/public/styles.css +1078 -4
- package/dashboard/server.ts +1100 -15
- package/dashboard/src/canvas/interactions.ts +74 -0
- package/dashboard/src/canvas/layout.ts +85 -0
- package/dashboard/src/canvas/overlays.ts +117 -0
- package/dashboard/src/canvas/particles.ts +105 -0
- package/dashboard/src/canvas/renderer.ts +191 -0
- package/dashboard/src/components/charts/bar.ts +54 -0
- package/dashboard/src/components/charts/donut.ts +25 -0
- package/dashboard/src/components/charts/pipeline-rail.ts +105 -0
- package/dashboard/src/components/charts/sparkline.ts +82 -0
- package/dashboard/src/components/header.ts +616 -0
- package/dashboard/src/components/modal.ts +413 -0
- package/dashboard/src/components/terminal.ts +144 -0
- package/dashboard/src/core/api.test.ts +362 -0
- package/dashboard/src/core/api.ts +381 -0
- package/dashboard/src/core/helpers.ts +118 -0
- package/dashboard/src/core/router.test.ts +266 -0
- package/dashboard/src/core/router.ts +190 -0
- package/dashboard/src/core/sse.ts +38 -0
- package/dashboard/src/core/state.test.ts +235 -0
- package/dashboard/src/core/state.ts +150 -0
- package/dashboard/src/core/ws.test.ts +216 -0
- package/dashboard/src/core/ws.ts +143 -0
- package/dashboard/src/design/icons.test.ts +105 -0
- package/dashboard/src/design/icons.ts +131 -0
- package/dashboard/src/design/tokens.test.ts +204 -0
- package/dashboard/src/design/tokens.ts +160 -0
- package/dashboard/src/main.ts +68 -0
- package/dashboard/src/types/api.ts +337 -0
- package/dashboard/src/views/activity.ts +185 -0
- package/dashboard/src/views/agent-cockpit.ts +236 -0
- package/dashboard/src/views/agents.ts +72 -0
- package/dashboard/src/views/fleet-map.ts +299 -0
- package/dashboard/src/views/insights.ts +298 -0
- package/dashboard/src/views/machines.ts +162 -0
- package/dashboard/src/views/metrics.ts +420 -0
- package/dashboard/src/views/overview.ts +409 -0
- package/dashboard/src/views/pipeline-theater.ts +219 -0
- package/dashboard/src/views/pipelines.ts +595 -0
- package/dashboard/src/views/team.ts +362 -0
- package/dashboard/src/views/timeline.ts +389 -0
- package/dashboard/tsconfig.json +21 -0
- package/dashboard/vitest.config.ts +27 -0
- package/docs/AGI-WHATS-NEXT.md +15 -15
- package/package.json +16 -2
- package/scripts/lib/helpers.sh +30 -0
- package/scripts/lib/pipeline-quality-checks.sh +1 -1
- package/scripts/lib/pipeline-stages.sh +59 -0
- package/scripts/sw +86 -167
- package/scripts/sw-activity.sh +1 -1
- package/scripts/sw-adaptive.sh +1 -1
- package/scripts/sw-adversarial.sh +1 -1
- package/scripts/sw-architecture-enforcer.sh +1 -1
- package/scripts/sw-auth.sh +14 -6
- package/scripts/sw-autonomous.sh +230 -13
- package/scripts/sw-changelog.sh +2 -2
- package/scripts/sw-checkpoint.sh +1 -1
- package/scripts/sw-ci.sh +1 -1
- package/scripts/sw-cleanup.sh +1 -1
- package/scripts/sw-code-review.sh +1 -1
- package/scripts/sw-connect.sh +1 -1
- package/scripts/sw-context.sh +1 -1
- package/scripts/sw-cost.sh +1 -1
- package/scripts/sw-daemon.sh +2 -2
- package/scripts/sw-dashboard.sh +1 -1
- package/scripts/sw-db.sh +1 -1
- package/scripts/sw-decompose.sh +1 -1
- package/scripts/sw-deps.sh +1 -1
- package/scripts/sw-developer-simulation.sh +1 -1
- package/scripts/sw-discovery.sh +1 -1
- package/scripts/sw-doc-fleet.sh +1 -1
- package/scripts/sw-docs-agent.sh +1 -1
- package/scripts/sw-docs.sh +1 -1
- package/scripts/sw-doctor.sh +8 -1
- package/scripts/sw-dora.sh +1 -1
- package/scripts/sw-durable.sh +1 -1
- package/scripts/sw-e2e-orchestrator.sh +1 -1
- package/scripts/sw-eventbus.sh +1 -1
- package/scripts/sw-feedback.sh +1 -1
- package/scripts/sw-fix.sh +6 -5
- package/scripts/sw-fleet-discover.sh +1 -1
- package/scripts/sw-fleet-viz.sh +1 -1
- package/scripts/sw-fleet.sh +1 -1
- package/scripts/sw-github-app.sh +5 -2
- package/scripts/sw-github-checks.sh +1 -1
- package/scripts/sw-github-deploy.sh +1 -1
- package/scripts/sw-github-graphql.sh +1 -1
- package/scripts/sw-guild.sh +1 -1
- package/scripts/sw-heartbeat.sh +1 -1
- package/scripts/sw-hygiene.sh +1 -1
- package/scripts/sw-incident.sh +1 -1
- package/scripts/sw-init.sh +112 -9
- package/scripts/sw-instrument.sh +6 -1
- package/scripts/sw-intelligence.sh +5 -1
- package/scripts/sw-jira.sh +1 -1
- package/scripts/sw-launchd.sh +1 -1
- package/scripts/sw-linear.sh +20 -9
- package/scripts/sw-logs.sh +1 -1
- package/scripts/sw-loop.sh +2 -1
- package/scripts/sw-memory.sh +10 -1
- package/scripts/sw-mission-control.sh +1 -1
- package/scripts/sw-model-router.sh +4 -1
- package/scripts/sw-otel.sh +1 -1
- package/scripts/sw-oversight.sh +1 -1
- package/scripts/sw-pipeline-composer.sh +3 -1
- package/scripts/sw-pipeline-vitals.sh +4 -6
- package/scripts/sw-pipeline.sh +4 -1
- package/scripts/sw-pm.sh +5 -2
- package/scripts/sw-pr-lifecycle.sh +1 -1
- package/scripts/sw-predictive.sh +4 -1
- package/scripts/sw-prep.sh +3 -2
- package/scripts/sw-ps.sh +1 -1
- package/scripts/sw-public-dashboard.sh +10 -4
- package/scripts/sw-quality.sh +1 -1
- package/scripts/sw-reaper.sh +1 -1
- package/scripts/sw-recruit.sh +16 -0
- package/scripts/sw-regression.sh +2 -1
- package/scripts/sw-release-manager.sh +1 -1
- package/scripts/sw-release.sh +7 -5
- package/scripts/sw-remote.sh +1 -1
- package/scripts/sw-replay.sh +1 -1
- package/scripts/sw-retro.sh +4 -1
- package/scripts/sw-scale.sh +4 -1
- package/scripts/sw-security-audit.sh +1 -1
- package/scripts/sw-self-optimize.sh +113 -1
- package/scripts/sw-session.sh +1 -1
- package/scripts/sw-setup.sh +1 -1
- package/scripts/sw-standup.sh +2 -1
- package/scripts/sw-status.sh +1 -1
- package/scripts/sw-strategic.sh +2 -1
- package/scripts/sw-stream.sh +1 -1
- package/scripts/sw-swarm.sh +6 -1
- package/scripts/sw-team-stages.sh +1 -1
- package/scripts/sw-templates.sh +1 -1
- package/scripts/sw-testgen.sh +3 -2
- package/scripts/sw-tmux-pipeline.sh +2 -1
- package/scripts/sw-tmux.sh +1 -1
- package/scripts/sw-trace.sh +1 -1
- package/scripts/sw-tracker-jira.sh +1 -0
- package/scripts/sw-tracker-linear.sh +1 -0
- package/scripts/sw-tracker.sh +1 -1
- package/scripts/sw-triage.sh +198 -11
- package/scripts/sw-upgrade.sh +1 -1
- package/scripts/sw-ux.sh +1 -1
- package/scripts/sw-webhook.sh +1 -1
- package/scripts/sw-widgets.sh +2 -2
- package/scripts/sw-worktree.sh +1 -1
- package/dashboard/public/app.js +0 -4422
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// SVG Pipeline Stage Visualization
|
|
2
|
+
|
|
3
|
+
import { STAGES, STAGE_SHORT, STAGE_HEX } from "../../design/tokens";
|
|
4
|
+
import { escapeHtml } from "../../core/helpers";
|
|
5
|
+
import type { PipelineInfo } from "../../types/api";
|
|
6
|
+
|
|
7
|
+
export function renderPipelineSVG(pipeline: PipelineInfo): string {
|
|
8
|
+
const stagesDone = pipeline.stagesDone || [];
|
|
9
|
+
const currentStage = pipeline.stage || "";
|
|
10
|
+
const failed = pipeline.status === "failed";
|
|
11
|
+
|
|
12
|
+
const nodeSpacing = 80;
|
|
13
|
+
const nodeR = 14;
|
|
14
|
+
const svgWidth = STAGES.length * nodeSpacing + 40;
|
|
15
|
+
const svgHeight = 72;
|
|
16
|
+
const yCenter = 28;
|
|
17
|
+
const yLabel = 60;
|
|
18
|
+
|
|
19
|
+
let svg = `<svg class="pipeline-svg" viewBox="0 0 ${svgWidth} ${svgHeight}" width="100%" height="${svgHeight}" xmlns="http://www.w3.org/2000/svg">`;
|
|
20
|
+
|
|
21
|
+
// Connecting lines
|
|
22
|
+
for (let i = 0; i < STAGES.length - 1; i++) {
|
|
23
|
+
const x1 = 20 + i * nodeSpacing + nodeR;
|
|
24
|
+
const x2 = 20 + (i + 1) * nodeSpacing - nodeR;
|
|
25
|
+
const isDone = stagesDone.indexOf(STAGES[i]) !== -1;
|
|
26
|
+
const lineColor = isDone ? "#4ade80" : "#1a3a6a";
|
|
27
|
+
const dashAttr = isDone ? "" : ' stroke-dasharray="4,3"';
|
|
28
|
+
svg += `<line x1="${x1}" y1="${yCenter}" x2="${x2}" y2="${yCenter}" stroke="${lineColor}" stroke-width="2"${dashAttr}/>`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Stage nodes
|
|
32
|
+
for (let i = 0; i < STAGES.length; i++) {
|
|
33
|
+
const s = STAGES[i];
|
|
34
|
+
const cx = 20 + i * nodeSpacing;
|
|
35
|
+
const isDone = stagesDone.indexOf(s) !== -1;
|
|
36
|
+
const isActive = s === currentStage;
|
|
37
|
+
const isFailed = failed && isActive;
|
|
38
|
+
|
|
39
|
+
let fillColor = "#0d1f3c";
|
|
40
|
+
let strokeColor = "#1a3a6a";
|
|
41
|
+
let textColor = "#5a6d8a";
|
|
42
|
+
let extra = "";
|
|
43
|
+
|
|
44
|
+
if (isDone) {
|
|
45
|
+
fillColor = "#4ade80";
|
|
46
|
+
strokeColor = "#4ade80";
|
|
47
|
+
textColor = "#060a14";
|
|
48
|
+
} else if (isFailed) {
|
|
49
|
+
fillColor = "#f43f5e";
|
|
50
|
+
strokeColor = "#f43f5e";
|
|
51
|
+
textColor = "#fff";
|
|
52
|
+
} else if (isActive) {
|
|
53
|
+
fillColor = "#00d4ff";
|
|
54
|
+
strokeColor = "#00d4ff";
|
|
55
|
+
textColor = "#060a14";
|
|
56
|
+
extra = ' class="stage-node-active"';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (isActive && !isFailed) {
|
|
60
|
+
svg +=
|
|
61
|
+
`<circle cx="${cx}" cy="${yCenter}" r="${nodeR + 4}" fill="none" stroke="${strokeColor}" stroke-width="1" opacity="0.3"${extra}>` +
|
|
62
|
+
`<animate attributeName="r" values="${nodeR + 2};${nodeR + 6};${nodeR + 2}" dur="2s" repeatCount="indefinite"/>` +
|
|
63
|
+
`<animate attributeName="opacity" values="0.3;0.1;0.3" dur="2s" repeatCount="indefinite"/></circle>`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
svg += `<circle cx="${cx}" cy="${yCenter}" r="${nodeR}" fill="${fillColor}" stroke="${strokeColor}" stroke-width="2"/>`;
|
|
67
|
+
svg += `<text x="${cx}" y="${yCenter + 4}" text-anchor="middle" fill="${textColor}" font-family="'JetBrains Mono', monospace" font-size="8" font-weight="600">${STAGE_SHORT[s]}</text>`;
|
|
68
|
+
svg += `<text x="${cx}" y="${yLabel}" text-anchor="middle" fill="#5a6d8a" font-family="'JetBrains Mono', monospace" font-size="7">${escapeHtml(s === "compound_quality" ? "quality" : s)}</text>`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
svg += "</svg>";
|
|
72
|
+
return svg;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function renderDoraGrades(
|
|
76
|
+
dora:
|
|
77
|
+
| Record<string, { grade: string; value: number; unit: string }>
|
|
78
|
+
| null
|
|
79
|
+
| undefined,
|
|
80
|
+
): string {
|
|
81
|
+
if (!dora) return "";
|
|
82
|
+
|
|
83
|
+
const metrics = [
|
|
84
|
+
{ key: "deploy_freq", label: "Deploy Frequency" },
|
|
85
|
+
{ key: "lead_time", label: "Lead Time" },
|
|
86
|
+
{ key: "cfr", label: "Change Failure Rate" },
|
|
87
|
+
{ key: "mttr", label: "Mean Time to Recovery" },
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
let html = '<div class="dora-grades-row">';
|
|
91
|
+
for (const m of metrics) {
|
|
92
|
+
const d = (dora as Record<string, any>)[m.key];
|
|
93
|
+
if (!d) continue;
|
|
94
|
+
const grade = (d.grade || "N/A").toLowerCase();
|
|
95
|
+
const gradeClass = "dora-" + grade;
|
|
96
|
+
html +=
|
|
97
|
+
`<div class="dora-grade-card">` +
|
|
98
|
+
`<span class="dora-grade-label">${escapeHtml(m.label)}</span>` +
|
|
99
|
+
`<span class="dora-badge ${gradeClass}">${escapeHtml(d.grade || "N/A")}</span>` +
|
|
100
|
+
`<span class="dora-grade-value">${d.value != null ? d.value.toFixed(1) : "\u2014"} ${escapeHtml(d.unit || "")}</span>` +
|
|
101
|
+
`</div>`;
|
|
102
|
+
}
|
|
103
|
+
html += "</div>";
|
|
104
|
+
return html;
|
|
105
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// SVG Sparkline / Line Chart
|
|
2
|
+
|
|
3
|
+
export function renderSparkline(
|
|
4
|
+
points: Array<number | { value: number }>,
|
|
5
|
+
color: string,
|
|
6
|
+
width: number,
|
|
7
|
+
height: number,
|
|
8
|
+
): string {
|
|
9
|
+
if (!points || points.length < 2) return "";
|
|
10
|
+
|
|
11
|
+
let maxVal = 0;
|
|
12
|
+
let minVal = Infinity;
|
|
13
|
+
for (const p of points) {
|
|
14
|
+
const v = typeof p === "object" ? p.value || 0 : p;
|
|
15
|
+
if (v > maxVal) maxVal = v;
|
|
16
|
+
if (v < minVal) minVal = v;
|
|
17
|
+
}
|
|
18
|
+
const range = maxVal - minVal || 1;
|
|
19
|
+
const padding = 2;
|
|
20
|
+
const w = width - padding * 2;
|
|
21
|
+
const h = height - padding * 2;
|
|
22
|
+
|
|
23
|
+
const pathParts: string[] = [];
|
|
24
|
+
for (let i = 0; i < points.length; i++) {
|
|
25
|
+
const v =
|
|
26
|
+
typeof points[i] === "object"
|
|
27
|
+
? (points[i] as { value: number }).value || 0
|
|
28
|
+
: (points[i] as number);
|
|
29
|
+
const x = padding + (i / (points.length - 1)) * w;
|
|
30
|
+
const y = padding + h - ((v - minVal) / range) * h;
|
|
31
|
+
pathParts.push((i === 0 ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
`<svg class="sparkline" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">` +
|
|
36
|
+
`<path d="${pathParts.join(" ")}" fill="none" stroke="${color}" stroke-width="1.5" stroke-linecap="round"/></svg>`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function renderSVGLineChart(
|
|
41
|
+
points: Array<Record<string, number>>,
|
|
42
|
+
valueKey: string,
|
|
43
|
+
color: string,
|
|
44
|
+
width: number,
|
|
45
|
+
height: number,
|
|
46
|
+
): string {
|
|
47
|
+
if (!points || points.length < 2)
|
|
48
|
+
return '<div class="empty-state"><p>Not enough data</p></div>';
|
|
49
|
+
|
|
50
|
+
let maxVal = 0;
|
|
51
|
+
for (const p of points) {
|
|
52
|
+
const v = p[valueKey] ?? p.value ?? 0;
|
|
53
|
+
if (v > maxVal) maxVal = v;
|
|
54
|
+
}
|
|
55
|
+
if (maxVal === 0) maxVal = 1;
|
|
56
|
+
|
|
57
|
+
const padding = 20;
|
|
58
|
+
const chartW = width - padding * 2;
|
|
59
|
+
const chartH = height - padding * 2;
|
|
60
|
+
|
|
61
|
+
let svg = `<svg class="svg-line-chart" viewBox="0 0 ${width} ${height}" width="100%" height="${height}">`;
|
|
62
|
+
|
|
63
|
+
for (let g = 0; g <= 4; g++) {
|
|
64
|
+
const gy = padding + (g / 4) * chartH;
|
|
65
|
+
svg += `<line x1="${padding}" y1="${gy}" x2="${width - padding}" y2="${gy}" stroke="#1a3a6a" stroke-width="0.5"/>`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const pathParts: string[] = [];
|
|
69
|
+
for (let i = 0; i < points.length; i++) {
|
|
70
|
+
const v = points[i][valueKey] ?? points[i].value ?? 0;
|
|
71
|
+
const x = padding + (i / (points.length - 1)) * chartW;
|
|
72
|
+
const y = padding + chartH - (v / maxVal) * chartH;
|
|
73
|
+
pathParts.push((i === 0 ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const lastX = padding + chartW;
|
|
77
|
+
const firstX = padding;
|
|
78
|
+
svg += `<path d="${pathParts.join(" ")} L${lastX},${padding + chartH} L${firstX},${padding + chartH} Z" fill="${color}" opacity="0.1"/>`;
|
|
79
|
+
svg += `<path d="${pathParts.join(" ")}" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round"/>`;
|
|
80
|
+
svg += "</svg>";
|
|
81
|
+
return svg;
|
|
82
|
+
}
|