opencastle 0.33.0 → 0.33.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/package.json +1 -1
- package/src/dashboard/dist/data/convoys/demo-api-v2.json +3 -3
- package/src/dashboard/dist/data/convoys/demo-auth-revamp.json +4 -4
- package/src/dashboard/dist/data/convoys/demo-dashboard-ui.json +12 -12
- package/src/dashboard/dist/data/convoys/demo-data-pipeline.json +3 -3
- package/src/dashboard/dist/data/convoys/demo-deploy-ci.json +1 -1
- package/src/dashboard/dist/data/convoys/demo-docs-update.json +3 -3
- package/src/dashboard/dist/data/convoys/demo-perf-opt.json +10 -10
- package/src/dashboard/dist/index.html +21 -25
- package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
- package/src/dashboard/public/data/convoys/demo-api-v2.json +3 -3
- package/src/dashboard/public/data/convoys/demo-auth-revamp.json +4 -4
- package/src/dashboard/public/data/convoys/demo-dashboard-ui.json +12 -12
- package/src/dashboard/public/data/convoys/demo-data-pipeline.json +3 -3
- package/src/dashboard/public/data/convoys/demo-deploy-ci.json +1 -1
- package/src/dashboard/public/data/convoys/demo-docs-update.json +3 -3
- package/src/dashboard/public/data/convoys/demo-perf-opt.json +10 -10
- package/src/dashboard/src/pages/index.astro +21 -25
package/package.json
CHANGED
|
@@ -51,21 +51,21 @@
|
|
|
51
51
|
"name": "docs/api-v2-contract.json",
|
|
52
52
|
"type": "json",
|
|
53
53
|
"task_id": "api-t1",
|
|
54
|
-
"created_at": "2026-04-
|
|
54
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
"id": "artifact-demo-api-v2-reports-security-gate-failure-md",
|
|
58
58
|
"name": "reports/security-gate-failure.md",
|
|
59
59
|
"type": "summary",
|
|
60
60
|
"task_id": "api-t3",
|
|
61
|
-
"created_at": "2026-04-
|
|
61
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
"id": "artifact-demo-api-v2-src-api-rate-limiter-ts",
|
|
65
65
|
"name": "src/api/rate-limiter.ts",
|
|
66
66
|
"type": "file",
|
|
67
67
|
"task_id": "api-t2",
|
|
68
|
-
"created_at": "2026-04-
|
|
68
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
69
69
|
}
|
|
70
70
|
],
|
|
71
71
|
"has_more_events": false,
|
|
@@ -42,28 +42,28 @@
|
|
|
42
42
|
"name": "libs/auth/src/jwt-middleware.ts",
|
|
43
43
|
"type": "file",
|
|
44
44
|
"task_id": "auth-t2",
|
|
45
|
-
"created_at": "2026-04-
|
|
45
|
+
"created_at": "2026-04-05T06:40:02.268Z"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"id": "artifact-demo-auth-revamp-libs-auth-src-rls-policies-sql",
|
|
49
49
|
"name": "libs/auth/src/rls-policies.sql",
|
|
50
50
|
"type": "file",
|
|
51
51
|
"task_id": "auth-t3",
|
|
52
|
-
"created_at": "2026-04-
|
|
52
|
+
"created_at": "2026-04-05T06:40:02.268Z"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"id": "artifact-demo-auth-revamp-reports-auth-review-summary-md",
|
|
56
56
|
"name": "reports/auth-review-summary.md",
|
|
57
57
|
"type": "summary",
|
|
58
58
|
"task_id": "auth-t5",
|
|
59
|
-
"created_at": "2026-04-
|
|
59
|
+
"created_at": "2026-04-05T06:40:02.268Z"
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
"id": "artifact-demo-auth-revamp-tests-auth-integration-test-ts",
|
|
63
63
|
"name": "tests/auth/integration.test.ts",
|
|
64
64
|
"type": "file",
|
|
65
65
|
"task_id": "auth-t4",
|
|
66
|
-
"created_at": "2026-04-
|
|
66
|
+
"created_at": "2026-04-05T06:40:02.268Z"
|
|
67
67
|
}
|
|
68
68
|
],
|
|
69
69
|
"has_more_events": false,
|
|
@@ -46,47 +46,47 @@
|
|
|
46
46
|
],
|
|
47
47
|
"artifact_count": 6,
|
|
48
48
|
"artifacts": [
|
|
49
|
+
{
|
|
50
|
+
"id": "artifact-demo-dashboard-ui-reports-panel-review-dashboard-md",
|
|
51
|
+
"name": "reports/panel-review-dashboard.md",
|
|
52
|
+
"type": "summary",
|
|
53
|
+
"task_id": "ui-t7",
|
|
54
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
55
|
+
},
|
|
49
56
|
{
|
|
50
57
|
"id": "artifact-demo-dashboard-ui-reports-visual-regression-json",
|
|
51
58
|
"name": "reports/visual-regression.json",
|
|
52
59
|
"type": "json",
|
|
53
60
|
"task_id": "ui-t6",
|
|
54
|
-
"created_at": "2026-04-
|
|
61
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
55
62
|
},
|
|
56
63
|
{
|
|
57
64
|
"id": "artifact-demo-dashboard-ui-src-components-DonutChart-tsx",
|
|
58
65
|
"name": "src/components/DonutChart.tsx",
|
|
59
66
|
"type": "file",
|
|
60
67
|
"task_id": "ui-t3",
|
|
61
|
-
"created_at": "2026-04-
|
|
68
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
62
69
|
},
|
|
63
70
|
{
|
|
64
71
|
"id": "artifact-demo-dashboard-ui-src-components-KpiCard-tsx",
|
|
65
72
|
"name": "src/components/KpiCard.tsx",
|
|
66
73
|
"type": "file",
|
|
67
74
|
"task_id": "ui-t2",
|
|
68
|
-
"created_at": "2026-04-
|
|
75
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
69
76
|
},
|
|
70
77
|
{
|
|
71
78
|
"id": "artifact-demo-dashboard-ui-src-components-design-tokens-ts",
|
|
72
79
|
"name": "src/components/design-tokens.ts",
|
|
73
80
|
"type": "file",
|
|
74
81
|
"task_id": "ui-t1",
|
|
75
|
-
"created_at": "2026-04-
|
|
82
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
76
83
|
},
|
|
77
84
|
{
|
|
78
85
|
"id": "artifact-demo-dashboard-ui-src-styles-animations-css",
|
|
79
86
|
"name": "src/styles/animations.css",
|
|
80
87
|
"type": "file",
|
|
81
88
|
"task_id": "ui-t4",
|
|
82
|
-
"created_at": "2026-04-
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
"id": "artifact-demo-dashboard-ui-reports-panel-review-dashboard-md",
|
|
86
|
-
"name": "reports/panel-review-dashboard.md",
|
|
87
|
-
"type": "summary",
|
|
88
|
-
"task_id": "ui-t7",
|
|
89
|
-
"created_at": "2026-04-04T06:06:04.354Z"
|
|
89
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
90
90
|
}
|
|
91
91
|
],
|
|
92
92
|
"has_more_events": false,
|
|
@@ -42,21 +42,21 @@
|
|
|
42
42
|
"name": "src/etl/pipeline.ts",
|
|
43
43
|
"type": "file",
|
|
44
44
|
"task_id": "etl-t2",
|
|
45
|
-
"created_at": "2026-04-
|
|
45
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"id": "artifact-demo-data-pipeline-src-etl-schema-ts",
|
|
49
49
|
"name": "src/etl/schema.ts",
|
|
50
50
|
"type": "file",
|
|
51
51
|
"task_id": "etl-t1",
|
|
52
|
-
"created_at": "2026-04-
|
|
52
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"id": "artifact-demo-data-pipeline-tests-etl-pipeline-test-ts",
|
|
56
56
|
"name": "tests/etl/pipeline.test.ts",
|
|
57
57
|
"type": "file",
|
|
58
58
|
"task_id": "etl-t3",
|
|
59
|
-
"created_at": "2026-04-
|
|
59
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
60
60
|
}
|
|
61
61
|
],
|
|
62
62
|
"has_more_events": false,
|
|
@@ -42,21 +42,21 @@
|
|
|
42
42
|
"name": "docs/ARCHITECTURE.md",
|
|
43
43
|
"type": "file",
|
|
44
44
|
"task_id": "docs-t1",
|
|
45
|
-
"created_at": "2026-04-
|
|
45
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"id": "artifact-demo-docs-update-docs-README-md",
|
|
49
49
|
"name": "docs/README.md",
|
|
50
50
|
"type": "file",
|
|
51
51
|
"task_id": "docs-t1",
|
|
52
|
-
"created_at": "2026-04-
|
|
52
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"id": "artifact-demo-docs-update-docs-api-reference-json",
|
|
56
56
|
"name": "docs/api-reference.json",
|
|
57
57
|
"type": "json",
|
|
58
58
|
"task_id": "docs-t2",
|
|
59
|
-
"created_at": "2026-04-
|
|
59
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
60
60
|
}
|
|
61
61
|
],
|
|
62
62
|
"has_more_events": false,
|
|
@@ -42,28 +42,28 @@
|
|
|
42
42
|
"name": "reports/bundle-analysis.json",
|
|
43
43
|
"type": "json",
|
|
44
44
|
"task_id": "perf-t1",
|
|
45
|
-
"created_at": "2026-04-
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"id": "artifact-demo-perf-opt-reports-web-vitals-improvement-md",
|
|
49
|
-
"name": "reports/web-vitals-improvement.md",
|
|
50
|
-
"type": "summary",
|
|
51
|
-
"task_id": "perf-t4",
|
|
52
|
-
"created_at": "2026-04-04T06:06:04.354Z"
|
|
45
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
53
46
|
},
|
|
54
47
|
{
|
|
55
48
|
"id": "artifact-demo-perf-opt-src-charts-index-ts",
|
|
56
49
|
"name": "src/charts/index.ts",
|
|
57
50
|
"type": "file",
|
|
58
51
|
"task_id": "perf-t2",
|
|
59
|
-
"created_at": "2026-04-
|
|
52
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "artifact-demo-perf-opt-reports-web-vitals-improvement-md",
|
|
56
|
+
"name": "reports/web-vitals-improvement.md",
|
|
57
|
+
"type": "summary",
|
|
58
|
+
"task_id": "perf-t4",
|
|
59
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
"id": "artifact-demo-perf-opt-src-utils-image-loader-ts",
|
|
63
63
|
"name": "src/utils/image-loader.ts",
|
|
64
64
|
"type": "file",
|
|
65
65
|
"task_id": "perf-t3",
|
|
66
|
-
"created_at": "2026-04-
|
|
66
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
67
67
|
}
|
|
68
68
|
],
|
|
69
69
|
"has_more_events": false,
|
|
@@ -97,6 +97,7 @@ Export
|
|
|
97
97
|
// ── Active Convoy Polling ──────────────────────────────────
|
|
98
98
|
let _activePollingTimer = null;
|
|
99
99
|
let _activePollingConvoyId = null;
|
|
100
|
+
let _lastPolledConvoyStatus = null;
|
|
100
101
|
|
|
101
102
|
function startActiveConvoyPolling() {
|
|
102
103
|
if (_activePollingTimer) return; // already polling
|
|
@@ -126,6 +127,7 @@ Export
|
|
|
126
127
|
// If we haven't navigated to any convoy yet, navigate now
|
|
127
128
|
if (!_activePollingConvoyId) {
|
|
128
129
|
_activePollingConvoyId = convoy.id;
|
|
130
|
+
_lastPolledConvoyStatus = null;
|
|
129
131
|
// Refresh ETL data so convoy detail JSON exists
|
|
130
132
|
await fetch(base + 'data/refresh');
|
|
131
133
|
// Re-fetch the convoy list and stats
|
|
@@ -137,36 +139,32 @@ Export
|
|
|
137
139
|
// If we're on a convoy and a new one started (pipeline chain), follow it
|
|
138
140
|
if (_activePollingConvoyId !== convoy.id && isRunningOrPending) {
|
|
139
141
|
_activePollingConvoyId = convoy.id;
|
|
142
|
+
_lastPolledConvoyStatus = null;
|
|
140
143
|
await fetch(base + 'data/refresh');
|
|
141
144
|
await refreshDashboardData();
|
|
142
145
|
showConvoyDetailView(convoy.id, convoy.name || convoy.id);
|
|
143
146
|
}
|
|
144
147
|
|
|
145
|
-
// If we're viewing the active convoy, refresh
|
|
148
|
+
// If we're viewing the active convoy, refresh when it's running or just transitioned
|
|
146
149
|
if (_activePollingConvoyId === convoy.id) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (!isRunningOrPending) {
|
|
160
|
-
// In pipeline mode, check if all convoys in the chain are done
|
|
161
|
-
if (data.pipeline) {
|
|
162
|
-
const anyActive = data.pipeline.some(c => c.status === 'running' || c.status === 'pending');
|
|
163
|
-
if (!anyActive) {
|
|
164
|
-
stopActiveConvoyPolling();
|
|
150
|
+
const statusChanged = _lastPolledConvoyStatus !== null && _lastPolledConvoyStatus !== convoy.status;
|
|
151
|
+
_lastPolledConvoyStatus = convoy.status;
|
|
152
|
+
|
|
153
|
+
if (isRunningOrPending || statusChanged) {
|
|
154
|
+
await fetch(base + 'data/refresh');
|
|
155
|
+
await refreshDashboardData();
|
|
156
|
+
// Reload convoy detail to show latest task progress
|
|
157
|
+
await loadConvoyDetail(convoy.id);
|
|
158
|
+
|
|
159
|
+
// Update pipeline chain breadcrumb if applicable
|
|
160
|
+
if (data.pipeline && data.pipeline.length > 1) {
|
|
161
|
+
renderPipelineChain(data.pipeline, convoy.id);
|
|
165
162
|
}
|
|
166
|
-
} else {
|
|
167
|
-
stopActiveConvoyPolling();
|
|
168
163
|
}
|
|
169
164
|
}
|
|
165
|
+
|
|
166
|
+
// NOTE: In 'active' mode we intentionally keep polling even after a convoy finishes,
|
|
167
|
+
// so that subsequent convoys are detected when they start.
|
|
170
168
|
} catch {
|
|
171
169
|
// Polling errors are non-fatal — just retry next interval
|
|
172
170
|
}
|
|
@@ -1817,11 +1815,9 @@ Export
|
|
|
1817
1815
|
const target = running || latest;
|
|
1818
1816
|
if (target) {
|
|
1819
1817
|
_activePollingConvoyId = target.id;
|
|
1818
|
+
_lastPolledConvoyStatus = null;
|
|
1820
1819
|
showConvoyDetailView(target.id, target.name || target.id);
|
|
1821
|
-
|
|
1822
|
-
if (target.status === 'running' || target.status === 'pending') {
|
|
1823
|
-
startActiveConvoyPolling();
|
|
1824
|
-
}
|
|
1820
|
+
startActiveConvoyPolling();
|
|
1825
1821
|
} else {
|
|
1826
1822
|
// No convoy exists yet — show waiting state and poll
|
|
1827
1823
|
showWaitingBanner();
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
"hash": "
|
|
2
|
+
"hash": "d345d9ae",
|
|
3
3
|
"configHash": "30f8ea04",
|
|
4
|
-
"lockfileHash": "
|
|
5
|
-
"browserHash": "
|
|
4
|
+
"lockfileHash": "ea94e1c1",
|
|
5
|
+
"browserHash": "c13f12ac",
|
|
6
6
|
"optimized": {
|
|
7
7
|
"astro > cssesc": {
|
|
8
8
|
"src": "../../../../../node_modules/cssesc/cssesc.js",
|
|
9
9
|
"file": "astro___cssesc.js",
|
|
10
|
-
"fileHash": "
|
|
10
|
+
"fileHash": "1d552a66",
|
|
11
11
|
"needsInterop": true
|
|
12
12
|
},
|
|
13
13
|
"astro > aria-query": {
|
|
14
14
|
"src": "../../../../../node_modules/aria-query/lib/index.js",
|
|
15
15
|
"file": "astro___aria-query.js",
|
|
16
|
-
"fileHash": "
|
|
16
|
+
"fileHash": "6c55b8e9",
|
|
17
17
|
"needsInterop": true
|
|
18
18
|
},
|
|
19
19
|
"astro > axobject-query": {
|
|
20
20
|
"src": "../../../../../node_modules/axobject-query/lib/index.js",
|
|
21
21
|
"file": "astro___axobject-query.js",
|
|
22
|
-
"fileHash": "
|
|
22
|
+
"fileHash": "a912fe24",
|
|
23
23
|
"needsInterop": true
|
|
24
24
|
}
|
|
25
25
|
},
|
|
@@ -51,21 +51,21 @@
|
|
|
51
51
|
"name": "docs/api-v2-contract.json",
|
|
52
52
|
"type": "json",
|
|
53
53
|
"task_id": "api-t1",
|
|
54
|
-
"created_at": "2026-04-
|
|
54
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
"id": "artifact-demo-api-v2-reports-security-gate-failure-md",
|
|
58
58
|
"name": "reports/security-gate-failure.md",
|
|
59
59
|
"type": "summary",
|
|
60
60
|
"task_id": "api-t3",
|
|
61
|
-
"created_at": "2026-04-
|
|
61
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
"id": "artifact-demo-api-v2-src-api-rate-limiter-ts",
|
|
65
65
|
"name": "src/api/rate-limiter.ts",
|
|
66
66
|
"type": "file",
|
|
67
67
|
"task_id": "api-t2",
|
|
68
|
-
"created_at": "2026-04-
|
|
68
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
69
69
|
}
|
|
70
70
|
],
|
|
71
71
|
"has_more_events": false,
|
|
@@ -42,28 +42,28 @@
|
|
|
42
42
|
"name": "libs/auth/src/jwt-middleware.ts",
|
|
43
43
|
"type": "file",
|
|
44
44
|
"task_id": "auth-t2",
|
|
45
|
-
"created_at": "2026-04-
|
|
45
|
+
"created_at": "2026-04-05T06:40:02.268Z"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"id": "artifact-demo-auth-revamp-libs-auth-src-rls-policies-sql",
|
|
49
49
|
"name": "libs/auth/src/rls-policies.sql",
|
|
50
50
|
"type": "file",
|
|
51
51
|
"task_id": "auth-t3",
|
|
52
|
-
"created_at": "2026-04-
|
|
52
|
+
"created_at": "2026-04-05T06:40:02.268Z"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"id": "artifact-demo-auth-revamp-reports-auth-review-summary-md",
|
|
56
56
|
"name": "reports/auth-review-summary.md",
|
|
57
57
|
"type": "summary",
|
|
58
58
|
"task_id": "auth-t5",
|
|
59
|
-
"created_at": "2026-04-
|
|
59
|
+
"created_at": "2026-04-05T06:40:02.268Z"
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
"id": "artifact-demo-auth-revamp-tests-auth-integration-test-ts",
|
|
63
63
|
"name": "tests/auth/integration.test.ts",
|
|
64
64
|
"type": "file",
|
|
65
65
|
"task_id": "auth-t4",
|
|
66
|
-
"created_at": "2026-04-
|
|
66
|
+
"created_at": "2026-04-05T06:40:02.268Z"
|
|
67
67
|
}
|
|
68
68
|
],
|
|
69
69
|
"has_more_events": false,
|
|
@@ -46,47 +46,47 @@
|
|
|
46
46
|
],
|
|
47
47
|
"artifact_count": 6,
|
|
48
48
|
"artifacts": [
|
|
49
|
+
{
|
|
50
|
+
"id": "artifact-demo-dashboard-ui-reports-panel-review-dashboard-md",
|
|
51
|
+
"name": "reports/panel-review-dashboard.md",
|
|
52
|
+
"type": "summary",
|
|
53
|
+
"task_id": "ui-t7",
|
|
54
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
55
|
+
},
|
|
49
56
|
{
|
|
50
57
|
"id": "artifact-demo-dashboard-ui-reports-visual-regression-json",
|
|
51
58
|
"name": "reports/visual-regression.json",
|
|
52
59
|
"type": "json",
|
|
53
60
|
"task_id": "ui-t6",
|
|
54
|
-
"created_at": "2026-04-
|
|
61
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
55
62
|
},
|
|
56
63
|
{
|
|
57
64
|
"id": "artifact-demo-dashboard-ui-src-components-DonutChart-tsx",
|
|
58
65
|
"name": "src/components/DonutChart.tsx",
|
|
59
66
|
"type": "file",
|
|
60
67
|
"task_id": "ui-t3",
|
|
61
|
-
"created_at": "2026-04-
|
|
68
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
62
69
|
},
|
|
63
70
|
{
|
|
64
71
|
"id": "artifact-demo-dashboard-ui-src-components-KpiCard-tsx",
|
|
65
72
|
"name": "src/components/KpiCard.tsx",
|
|
66
73
|
"type": "file",
|
|
67
74
|
"task_id": "ui-t2",
|
|
68
|
-
"created_at": "2026-04-
|
|
75
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
69
76
|
},
|
|
70
77
|
{
|
|
71
78
|
"id": "artifact-demo-dashboard-ui-src-components-design-tokens-ts",
|
|
72
79
|
"name": "src/components/design-tokens.ts",
|
|
73
80
|
"type": "file",
|
|
74
81
|
"task_id": "ui-t1",
|
|
75
|
-
"created_at": "2026-04-
|
|
82
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
76
83
|
},
|
|
77
84
|
{
|
|
78
85
|
"id": "artifact-demo-dashboard-ui-src-styles-animations-css",
|
|
79
86
|
"name": "src/styles/animations.css",
|
|
80
87
|
"type": "file",
|
|
81
88
|
"task_id": "ui-t4",
|
|
82
|
-
"created_at": "2026-04-
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
"id": "artifact-demo-dashboard-ui-reports-panel-review-dashboard-md",
|
|
86
|
-
"name": "reports/panel-review-dashboard.md",
|
|
87
|
-
"type": "summary",
|
|
88
|
-
"task_id": "ui-t7",
|
|
89
|
-
"created_at": "2026-04-04T06:06:04.354Z"
|
|
89
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
90
90
|
}
|
|
91
91
|
],
|
|
92
92
|
"has_more_events": false,
|
|
@@ -42,21 +42,21 @@
|
|
|
42
42
|
"name": "src/etl/pipeline.ts",
|
|
43
43
|
"type": "file",
|
|
44
44
|
"task_id": "etl-t2",
|
|
45
|
-
"created_at": "2026-04-
|
|
45
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"id": "artifact-demo-data-pipeline-src-etl-schema-ts",
|
|
49
49
|
"name": "src/etl/schema.ts",
|
|
50
50
|
"type": "file",
|
|
51
51
|
"task_id": "etl-t1",
|
|
52
|
-
"created_at": "2026-04-
|
|
52
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"id": "artifact-demo-data-pipeline-tests-etl-pipeline-test-ts",
|
|
56
56
|
"name": "tests/etl/pipeline.test.ts",
|
|
57
57
|
"type": "file",
|
|
58
58
|
"task_id": "etl-t3",
|
|
59
|
-
"created_at": "2026-04-
|
|
59
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
60
60
|
}
|
|
61
61
|
],
|
|
62
62
|
"has_more_events": false,
|
|
@@ -42,21 +42,21 @@
|
|
|
42
42
|
"name": "docs/ARCHITECTURE.md",
|
|
43
43
|
"type": "file",
|
|
44
44
|
"task_id": "docs-t1",
|
|
45
|
-
"created_at": "2026-04-
|
|
45
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"id": "artifact-demo-docs-update-docs-README-md",
|
|
49
49
|
"name": "docs/README.md",
|
|
50
50
|
"type": "file",
|
|
51
51
|
"task_id": "docs-t1",
|
|
52
|
-
"created_at": "2026-04-
|
|
52
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"id": "artifact-demo-docs-update-docs-api-reference-json",
|
|
56
56
|
"name": "docs/api-reference.json",
|
|
57
57
|
"type": "json",
|
|
58
58
|
"task_id": "docs-t2",
|
|
59
|
-
"created_at": "2026-04-
|
|
59
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
60
60
|
}
|
|
61
61
|
],
|
|
62
62
|
"has_more_events": false,
|
|
@@ -42,28 +42,28 @@
|
|
|
42
42
|
"name": "reports/bundle-analysis.json",
|
|
43
43
|
"type": "json",
|
|
44
44
|
"task_id": "perf-t1",
|
|
45
|
-
"created_at": "2026-04-
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"id": "artifact-demo-perf-opt-reports-web-vitals-improvement-md",
|
|
49
|
-
"name": "reports/web-vitals-improvement.md",
|
|
50
|
-
"type": "summary",
|
|
51
|
-
"task_id": "perf-t4",
|
|
52
|
-
"created_at": "2026-04-04T06:06:04.354Z"
|
|
45
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
53
46
|
},
|
|
54
47
|
{
|
|
55
48
|
"id": "artifact-demo-perf-opt-src-charts-index-ts",
|
|
56
49
|
"name": "src/charts/index.ts",
|
|
57
50
|
"type": "file",
|
|
58
51
|
"task_id": "perf-t2",
|
|
59
|
-
"created_at": "2026-04-
|
|
52
|
+
"created_at": "2026-04-05T06:40:02.269Z"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "artifact-demo-perf-opt-reports-web-vitals-improvement-md",
|
|
56
|
+
"name": "reports/web-vitals-improvement.md",
|
|
57
|
+
"type": "summary",
|
|
58
|
+
"task_id": "perf-t4",
|
|
59
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
"id": "artifact-demo-perf-opt-src-utils-image-loader-ts",
|
|
63
63
|
"name": "src/utils/image-loader.ts",
|
|
64
64
|
"type": "file",
|
|
65
65
|
"task_id": "perf-t3",
|
|
66
|
-
"created_at": "2026-04-
|
|
66
|
+
"created_at": "2026-04-05T06:40:02.270Z"
|
|
67
67
|
}
|
|
68
68
|
],
|
|
69
69
|
"has_more_events": false,
|
|
@@ -447,6 +447,7 @@ try {
|
|
|
447
447
|
// ── Active Convoy Polling ──────────────────────────────────
|
|
448
448
|
let _activePollingTimer = null;
|
|
449
449
|
let _activePollingConvoyId = null;
|
|
450
|
+
let _lastPolledConvoyStatus = null;
|
|
450
451
|
|
|
451
452
|
function startActiveConvoyPolling() {
|
|
452
453
|
if (_activePollingTimer) return; // already polling
|
|
@@ -476,6 +477,7 @@ try {
|
|
|
476
477
|
// If we haven't navigated to any convoy yet, navigate now
|
|
477
478
|
if (!_activePollingConvoyId) {
|
|
478
479
|
_activePollingConvoyId = convoy.id;
|
|
480
|
+
_lastPolledConvoyStatus = null;
|
|
479
481
|
// Refresh ETL data so convoy detail JSON exists
|
|
480
482
|
await fetch(base + 'data/refresh');
|
|
481
483
|
// Re-fetch the convoy list and stats
|
|
@@ -487,36 +489,32 @@ try {
|
|
|
487
489
|
// If we're on a convoy and a new one started (pipeline chain), follow it
|
|
488
490
|
if (_activePollingConvoyId !== convoy.id && isRunningOrPending) {
|
|
489
491
|
_activePollingConvoyId = convoy.id;
|
|
492
|
+
_lastPolledConvoyStatus = null;
|
|
490
493
|
await fetch(base + 'data/refresh');
|
|
491
494
|
await refreshDashboardData();
|
|
492
495
|
showConvoyDetailView(convoy.id, convoy.name || convoy.id);
|
|
493
496
|
}
|
|
494
497
|
|
|
495
|
-
// If we're viewing the active convoy, refresh
|
|
498
|
+
// If we're viewing the active convoy, refresh when it's running or just transitioned
|
|
496
499
|
if (_activePollingConvoyId === convoy.id) {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
if (!isRunningOrPending) {
|
|
510
|
-
// In pipeline mode, check if all convoys in the chain are done
|
|
511
|
-
if (data.pipeline) {
|
|
512
|
-
const anyActive = data.pipeline.some(c => c.status === 'running' || c.status === 'pending');
|
|
513
|
-
if (!anyActive) {
|
|
514
|
-
stopActiveConvoyPolling();
|
|
500
|
+
const statusChanged = _lastPolledConvoyStatus !== null && _lastPolledConvoyStatus !== convoy.status;
|
|
501
|
+
_lastPolledConvoyStatus = convoy.status;
|
|
502
|
+
|
|
503
|
+
if (isRunningOrPending || statusChanged) {
|
|
504
|
+
await fetch(base + 'data/refresh');
|
|
505
|
+
await refreshDashboardData();
|
|
506
|
+
// Reload convoy detail to show latest task progress
|
|
507
|
+
await loadConvoyDetail(convoy.id);
|
|
508
|
+
|
|
509
|
+
// Update pipeline chain breadcrumb if applicable
|
|
510
|
+
if (data.pipeline && data.pipeline.length > 1) {
|
|
511
|
+
renderPipelineChain(data.pipeline, convoy.id);
|
|
515
512
|
}
|
|
516
|
-
} else {
|
|
517
|
-
stopActiveConvoyPolling();
|
|
518
513
|
}
|
|
519
514
|
}
|
|
515
|
+
|
|
516
|
+
// NOTE: In 'active' mode we intentionally keep polling even after a convoy finishes,
|
|
517
|
+
// so that subsequent convoys are detected when they start.
|
|
520
518
|
} catch {
|
|
521
519
|
// Polling errors are non-fatal — just retry next interval
|
|
522
520
|
}
|
|
@@ -2167,11 +2165,9 @@ try {
|
|
|
2167
2165
|
const target = running || latest;
|
|
2168
2166
|
if (target) {
|
|
2169
2167
|
_activePollingConvoyId = target.id;
|
|
2168
|
+
_lastPolledConvoyStatus = null;
|
|
2170
2169
|
showConvoyDetailView(target.id, target.name || target.id);
|
|
2171
|
-
|
|
2172
|
-
if (target.status === 'running' || target.status === 'pending') {
|
|
2173
|
-
startActiveConvoyPolling();
|
|
2174
|
-
}
|
|
2170
|
+
startActiveConvoyPolling();
|
|
2175
2171
|
} else {
|
|
2176
2172
|
// No convoy exists yet — show waiting state and poll
|
|
2177
2173
|
showWaitingBanner();
|