opencastle 0.31.7 → 0.32.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 +4 -1
- package/bin/cli.mjs +15 -0
- package/dist/cli/agents.d.ts.map +1 -1
- package/dist/cli/agents.js +19 -5
- package/dist/cli/agents.js.map +1 -1
- package/dist/cli/artifacts-cli.d.ts +3 -0
- package/dist/cli/artifacts-cli.d.ts.map +1 -0
- package/dist/cli/artifacts-cli.js +36 -0
- package/dist/cli/artifacts-cli.js.map +1 -0
- package/dist/cli/baselines.d.ts.map +1 -1
- package/dist/cli/baselines.js +11 -0
- package/dist/cli/baselines.js.map +1 -1
- package/dist/cli/convoy/artifacts.d.ts +25 -0
- package/dist/cli/convoy/artifacts.d.ts.map +1 -0
- package/dist/cli/convoy/artifacts.js +129 -0
- package/dist/cli/convoy/artifacts.js.map +1 -0
- package/dist/cli/convoy/artifacts.test.d.ts +2 -0
- package/dist/cli/convoy/artifacts.test.d.ts.map +1 -0
- package/dist/cli/convoy/artifacts.test.js +169 -0
- package/dist/cli/convoy/artifacts.test.js.map +1 -0
- package/dist/cli/convoy/compaction.d.ts +23 -0
- package/dist/cli/convoy/compaction.d.ts.map +1 -0
- package/dist/cli/convoy/compaction.js +117 -0
- package/dist/cli/convoy/compaction.js.map +1 -0
- package/dist/cli/convoy/compaction.test.d.ts +2 -0
- package/dist/cli/convoy/compaction.test.d.ts.map +1 -0
- package/dist/cli/convoy/compaction.test.js +205 -0
- package/dist/cli/convoy/compaction.test.js.map +1 -0
- package/dist/cli/convoy/contracts.d.ts +22 -0
- package/dist/cli/convoy/contracts.d.ts.map +1 -0
- package/dist/cli/convoy/contracts.js +254 -0
- package/dist/cli/convoy/contracts.js.map +1 -0
- package/dist/cli/convoy/contracts.test.d.ts +2 -0
- package/dist/cli/convoy/contracts.test.d.ts.map +1 -0
- package/dist/cli/convoy/contracts.test.js +239 -0
- package/dist/cli/convoy/contracts.test.js.map +1 -0
- package/dist/cli/convoy/dag-analysis.d.ts +40 -0
- package/dist/cli/convoy/dag-analysis.d.ts.map +1 -0
- package/dist/cli/convoy/dag-analysis.js +282 -0
- package/dist/cli/convoy/dag-analysis.js.map +1 -0
- package/dist/cli/convoy/dag-analysis.test.d.ts +2 -0
- package/dist/cli/convoy/dag-analysis.test.d.ts.map +1 -0
- package/dist/cli/convoy/dag-analysis.test.js +289 -0
- package/dist/cli/convoy/dag-analysis.test.js.map +1 -0
- package/dist/cli/convoy/effort-scaling.d.ts +20 -0
- package/dist/cli/convoy/effort-scaling.d.ts.map +1 -0
- package/dist/cli/convoy/effort-scaling.js +82 -0
- package/dist/cli/convoy/effort-scaling.js.map +1 -0
- package/dist/cli/convoy/effort-scaling.test.d.ts +2 -0
- package/dist/cli/convoy/effort-scaling.test.d.ts.map +1 -0
- package/dist/cli/convoy/effort-scaling.test.js +120 -0
- package/dist/cli/convoy/effort-scaling.test.js.map +1 -0
- package/dist/cli/convoy/engine.d.ts.map +1 -1
- package/dist/cli/convoy/engine.js +280 -6
- package/dist/cli/convoy/engine.js.map +1 -1
- package/dist/cli/convoy/engine.test.js +155 -18
- package/dist/cli/convoy/engine.test.js.map +1 -1
- package/dist/cli/convoy/event-schemas.d.ts.map +1 -1
- package/dist/cli/convoy/event-schemas.js +55 -0
- package/dist/cli/convoy/event-schemas.js.map +1 -1
- package/dist/cli/convoy/isolation.d.ts +27 -0
- package/dist/cli/convoy/isolation.d.ts.map +1 -0
- package/dist/cli/convoy/isolation.js +120 -0
- package/dist/cli/convoy/isolation.js.map +1 -0
- package/dist/cli/convoy/isolation.test.d.ts +2 -0
- package/dist/cli/convoy/isolation.test.d.ts.map +1 -0
- package/dist/cli/convoy/isolation.test.js +105 -0
- package/dist/cli/convoy/isolation.test.js.map +1 -0
- package/dist/cli/convoy/review-stages.d.ts +9 -0
- package/dist/cli/convoy/review-stages.d.ts.map +1 -0
- package/dist/cli/convoy/review-stages.js +134 -0
- package/dist/cli/convoy/review-stages.js.map +1 -0
- package/dist/cli/convoy/review-stages.test.d.ts +2 -0
- package/dist/cli/convoy/review-stages.test.d.ts.map +1 -0
- package/dist/cli/convoy/review-stages.test.js +197 -0
- package/dist/cli/convoy/review-stages.test.js.map +1 -0
- package/dist/cli/convoy/skill-refinement.d.ts +39 -0
- package/dist/cli/convoy/skill-refinement.d.ts.map +1 -0
- package/dist/cli/convoy/skill-refinement.js +239 -0
- package/dist/cli/convoy/skill-refinement.js.map +1 -0
- package/dist/cli/convoy/skill-refinement.test.d.ts +2 -0
- package/dist/cli/convoy/skill-refinement.test.d.ts.map +1 -0
- package/dist/cli/convoy/skill-refinement.test.js +230 -0
- package/dist/cli/convoy/skill-refinement.test.js.map +1 -0
- package/dist/cli/convoy/spec-builder.d.ts +1 -0
- package/dist/cli/convoy/spec-builder.d.ts.map +1 -1
- package/dist/cli/convoy/spec-builder.js +11 -0
- package/dist/cli/convoy/spec-builder.js.map +1 -1
- package/dist/cli/convoy/spec-builder.test.js +54 -0
- package/dist/cli/convoy/spec-builder.test.js.map +1 -1
- package/dist/cli/convoy/store.d.ts +3 -2
- package/dist/cli/convoy/store.d.ts.map +1 -1
- package/dist/cli/convoy/store.js +20 -2
- package/dist/cli/convoy/store.js.map +1 -1
- package/dist/cli/convoy/store.test.js +15 -15
- package/dist/cli/convoy/store.test.js.map +1 -1
- package/dist/cli/convoy/tdd-gate.d.ts +15 -0
- package/dist/cli/convoy/tdd-gate.d.ts.map +1 -0
- package/dist/cli/convoy/tdd-gate.js +119 -0
- package/dist/cli/convoy/tdd-gate.js.map +1 -0
- package/dist/cli/convoy/tdd-gate.test.d.ts +2 -0
- package/dist/cli/convoy/tdd-gate.test.d.ts.map +1 -0
- package/dist/cli/convoy/tdd-gate.test.js +227 -0
- package/dist/cli/convoy/tdd-gate.test.js.map +1 -0
- package/dist/cli/convoy/types.d.ts +91 -0
- package/dist/cli/convoy/types.d.ts.map +1 -1
- package/dist/cli/convoy/types.js +8 -0
- package/dist/cli/convoy/types.js.map +1 -1
- package/dist/cli/insights.d.ts +3 -0
- package/dist/cli/insights.d.ts.map +1 -0
- package/dist/cli/insights.js +94 -0
- package/dist/cli/insights.js.map +1 -0
- package/dist/cli/lesson.d.ts.map +1 -1
- package/dist/cli/lesson.js +7 -0
- package/dist/cli/lesson.js.map +1 -1
- package/dist/cli/log.d.ts.map +1 -1
- package/dist/cli/log.js +7 -0
- package/dist/cli/log.js.map +1 -1
- package/dist/cli/package-config.d.ts +12 -0
- package/dist/cli/package-config.d.ts.map +1 -0
- package/dist/cli/package-config.js +37 -0
- package/dist/cli/package-config.js.map +1 -0
- package/dist/cli/package.d.ts +23 -0
- package/dist/cli/package.d.ts.map +1 -0
- package/dist/cli/package.js +285 -0
- package/dist/cli/package.js.map +1 -0
- package/dist/cli/package.test.d.ts +2 -0
- package/dist/cli/package.test.d.ts.map +1 -0
- package/dist/cli/package.test.js +236 -0
- package/dist/cli/package.test.js.map +1 -0
- package/dist/cli/pipeline.d.ts +6 -0
- package/dist/cli/pipeline.d.ts.map +1 -1
- package/dist/cli/pipeline.js +15 -2
- package/dist/cli/pipeline.js.map +1 -1
- package/dist/cli/run/schema.d.ts.map +1 -1
- package/dist/cli/run/schema.js +32 -0
- package/dist/cli/run/schema.js.map +1 -1
- package/dist/cli/run/schema.test.js +51 -0
- package/dist/cli/run/schema.test.js.map +1 -1
- package/dist/cli/skills.d.ts +3 -0
- package/dist/cli/skills.d.ts.map +1 -0
- package/dist/cli/skills.js +107 -0
- package/dist/cli/skills.js.map +1 -0
- package/dist/cli/types.d.ts +4 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/dashboard/scripts/etl.d.ts.map +1 -1
- package/dist/dashboard/scripts/etl.js +44 -11
- package/dist/dashboard/scripts/etl.js.map +1 -1
- package/package.json +2 -1
- package/src/cli/agents.ts +20 -5
- package/src/cli/artifacts-cli.ts +41 -0
- package/src/cli/baselines.ts +12 -0
- package/src/cli/convoy/artifacts.test.ts +201 -0
- package/src/cli/convoy/artifacts.ts +186 -0
- package/src/cli/convoy/compaction.test.ts +245 -0
- package/src/cli/convoy/compaction.ts +164 -0
- package/src/cli/convoy/contracts.test.ts +279 -0
- package/src/cli/convoy/contracts.ts +280 -0
- package/src/cli/convoy/dag-analysis.test.ts +349 -0
- package/src/cli/convoy/dag-analysis.ts +371 -0
- package/src/cli/convoy/effort-scaling.test.ts +140 -0
- package/src/cli/convoy/effort-scaling.ts +90 -0
- package/src/cli/convoy/engine.test.ts +175 -18
- package/src/cli/convoy/engine.ts +301 -7
- package/src/cli/convoy/event-schemas.ts +55 -0
- package/src/cli/convoy/isolation.test.ts +137 -0
- package/src/cli/convoy/isolation.ts +165 -0
- package/src/cli/convoy/review-stages.test.ts +235 -0
- package/src/cli/convoy/review-stages.ts +166 -0
- package/src/cli/convoy/skill-refinement.test.ts +277 -0
- package/src/cli/convoy/skill-refinement.ts +306 -0
- package/src/cli/convoy/spec-builder.test.ts +61 -0
- package/src/cli/convoy/spec-builder.ts +9 -0
- package/src/cli/convoy/store.test.ts +15 -15
- package/src/cli/convoy/store.ts +26 -4
- package/src/cli/convoy/tdd-gate.test.ts +281 -0
- package/src/cli/convoy/tdd-gate.ts +154 -0
- package/src/cli/convoy/types.ts +51 -0
- package/src/cli/insights.ts +99 -0
- package/src/cli/lesson.ts +8 -0
- package/src/cli/log.ts +8 -0
- package/src/cli/package-config.ts +48 -0
- package/src/cli/package.test.ts +276 -0
- package/src/cli/package.ts +329 -0
- package/src/cli/pipeline.ts +21 -2
- package/src/cli/run/schema.test.ts +58 -0
- package/src/cli/run/schema.ts +33 -0
- package/src/cli/skills.ts +121 -0
- package/src/cli/types.ts +4 -1
- package/src/dashboard/dist/_astro/index.D6quLrA6.css +1 -0
- package/src/dashboard/dist/data/convoy-list.json +21 -7
- package/src/dashboard/dist/data/convoys/demo-api-v2.json +3 -3
- package/src/dashboard/dist/data/convoys/demo-auth-revamp.json +5 -5
- package/src/dashboard/dist/data/convoys/demo-convoy-1.json +2 -2
- package/src/dashboard/dist/data/convoys/demo-convoy-2.json +1 -1
- package/src/dashboard/dist/data/convoys/demo-dashboard-ui.json +7 -7
- package/src/dashboard/dist/data/convoys/demo-data-pipeline.json +3 -3
- package/src/dashboard/dist/data/convoys/demo-deploy-ci.json +2 -2
- package/src/dashboard/dist/data/convoys/demo-docs-update.json +2 -2
- package/src/dashboard/dist/data/convoys/demo-perf-opt.json +4 -4
- package/src/dashboard/dist/index.html +306 -33
- package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
- package/src/dashboard/public/data/convoy-list.json +21 -7
- package/src/dashboard/public/data/convoys/demo-api-v2.json +3 -3
- package/src/dashboard/public/data/convoys/demo-auth-revamp.json +5 -5
- package/src/dashboard/public/data/convoys/demo-convoy-1.json +2 -2
- package/src/dashboard/public/data/convoys/demo-convoy-2.json +1 -1
- package/src/dashboard/public/data/convoys/demo-dashboard-ui.json +7 -7
- package/src/dashboard/public/data/convoys/demo-data-pipeline.json +3 -3
- package/src/dashboard/public/data/convoys/demo-deploy-ci.json +2 -2
- package/src/dashboard/public/data/convoys/demo-docs-update.json +2 -2
- package/src/dashboard/public/data/convoys/demo-perf-opt.json +4 -4
- package/src/dashboard/scripts/etl.test.ts +14 -0
- package/src/dashboard/scripts/etl.ts +48 -16
- package/src/dashboard/scripts/generate-demo-db.ts +18 -10
- package/src/dashboard/src/pages/index.astro +348 -45
- package/src/dashboard/src/styles/dashboard.css +56 -0
- package/src/orchestrator/prompts/assess-complexity.prompt.md +13 -0
- package/src/orchestrator/prompts/generate-convoy.prompt.md +19 -0
- package/src/dashboard/dist/_astro/index.BRDFmNzR.css +0 -1
|
@@ -39,6 +39,8 @@ try {
|
|
|
39
39
|
<ul class="dash-sidebar__list">
|
|
40
40
|
<li><a class="dash-sidebar__link dash-sidebar__link--active" href="#overall-section" data-section="overall-section" data-view="home" aria-label="Overview section">Overview</a></li>
|
|
41
41
|
<li><a class="dash-sidebar__link" href="#convoy-list-section" data-section="convoy-list-section" data-view="home" aria-label="Convoys section">Convoys</a></li>
|
|
42
|
+
<li><a class="dash-sidebar__link" href="#activity-timeline-section" data-section="activity-timeline-section" data-view="home" aria-label="Activity Timeline section">Activity</a></li>
|
|
43
|
+
<li><a class="dash-sidebar__link" href="#sessions-section" data-section="sessions-section" data-view="home" aria-label="Sessions section">Sessions</a></li>
|
|
42
44
|
<li><a class="dash-sidebar__link" href="#tasks-section" data-section="tasks-section" data-view="detail" aria-label="Tasks section">Tasks</a></li>
|
|
43
45
|
<li><a class="dash-sidebar__link" href="#pipeline-section" data-section="pipeline-section" data-view="detail" aria-label="Pipeline section">Pipeline</a></li>
|
|
44
46
|
<li><a class="dash-sidebar__link" href="#agent-section" data-section="agent-section" data-view="detail" aria-label="Agents section">Agents</a></li>
|
|
@@ -50,8 +52,8 @@ try {
|
|
|
50
52
|
<li><a class="dash-sidebar__link" href="#outputs-section" data-section="outputs-section" data-view="detail" aria-label="Outputs section">Outputs</a></li>
|
|
51
53
|
<li><a class="dash-sidebar__link" href="#execution-section" data-section="execution-section" data-view="detail" aria-label="Execution Log section">Execution Log</a></li>
|
|
52
54
|
<li><a class="dash-sidebar__link" href="#event-timeline-section" data-section="event-timeline-section" data-view="detail" aria-label="Event Log section">Event Log</a></li>
|
|
53
|
-
<li><a class="dash-sidebar__link" href="#panel-section" data-section="panel-section" data-view="detail" aria-label="Panel Reviews section">Panel Reviews</a></li>
|
|
54
55
|
<li><a class="dash-sidebar__link" href="#reviews-section" data-section="reviews-section" data-view="detail" aria-label="Fast Reviews section">Fast Reviews</a></li>
|
|
56
|
+
<li><a class="dash-sidebar__link" href="#panel-section" data-section="panel-section" data-view="detail" aria-label="Panel Reviews section">Panel Reviews</a></li>
|
|
55
57
|
</ul>
|
|
56
58
|
</nav>
|
|
57
59
|
|
|
@@ -93,9 +95,26 @@ try {
|
|
|
93
95
|
<span class="overall-kpi__label">Total Cost</span>
|
|
94
96
|
<span class="overall-kpi__value">—</span>
|
|
95
97
|
</div>
|
|
98
|
+
<div class="overall-kpi" id="overall-total-tasks">
|
|
99
|
+
<span class="overall-kpi__label">Total Tasks</span>
|
|
100
|
+
<span class="overall-kpi__value">—</span>
|
|
101
|
+
</div>
|
|
102
|
+
<div class="overall-kpi" id="overall-total-retries">
|
|
103
|
+
<span class="overall-kpi__label">Total Retries</span>
|
|
104
|
+
<span class="overall-kpi__value">—</span>
|
|
105
|
+
</div>
|
|
96
106
|
</div>
|
|
97
107
|
</section>
|
|
98
108
|
|
|
109
|
+
<!-- Activity Timeline -->
|
|
110
|
+
<section class="chart-card" id="activity-timeline-section" data-nav-section>
|
|
111
|
+
<div class="chart-card__header">
|
|
112
|
+
<h2 class="chart-card__title">Activity Timeline</h2>
|
|
113
|
+
<p class="chart-card__desc">Convoy runs over time</p>
|
|
114
|
+
</div>
|
|
115
|
+
<div class="chart-card__body" id="activity-timeline-chart"></div>
|
|
116
|
+
</section>
|
|
117
|
+
|
|
99
118
|
<!-- Convoy List Section -->
|
|
100
119
|
<section class="convoy-list-section" id="convoy-list-section">
|
|
101
120
|
<div class="convoy-list-section__header">
|
|
@@ -136,12 +155,23 @@ try {
|
|
|
136
155
|
<p class="convoy-list-empty__text">No convoys match your filters</p>
|
|
137
156
|
</div>
|
|
138
157
|
</section>
|
|
158
|
+
|
|
159
|
+
<!-- Recent Sessions -->
|
|
160
|
+
<section class="chart-card" id="sessions-section" data-nav-section>
|
|
161
|
+
<div class="chart-card__header">
|
|
162
|
+
<h2 class="chart-card__title">Recent Sessions</h2>
|
|
163
|
+
<p class="chart-card__desc">Latest agent sessions from observability log</p>
|
|
164
|
+
</div>
|
|
165
|
+
<div class="chart-card__body chart-card__body--table" id="sessions-table"></div>
|
|
166
|
+
</section>
|
|
139
167
|
</div><!-- .view-home -->
|
|
140
168
|
|
|
141
169
|
<div class="view-convoy-detail" id="view-convoy-detail" data-view-hidden>
|
|
142
170
|
<section class="convoy-detail-hero" id="convoy-detail-hero">
|
|
143
|
-
<div class="convoy-detail-
|
|
144
|
-
|
|
171
|
+
<div class="convoy-detail-hero__top">
|
|
172
|
+
<div class="convoy-detail-hero__title" id="detail-hero-title"></div>
|
|
173
|
+
<span class="convoy-detail-hero__status" id="detail-hero-status"></span>
|
|
174
|
+
</div>
|
|
145
175
|
<div class="convoy-detail-hero__meta" id="detail-hero-meta"></div>
|
|
146
176
|
</section>
|
|
147
177
|
|
|
@@ -163,7 +193,7 @@ try {
|
|
|
163
193
|
<section class="chart-card" id="pipeline-section" data-nav-section>
|
|
164
194
|
<div class="chart-card__header">
|
|
165
195
|
<h2 class="chart-card__title">Task Pipeline</h2>
|
|
166
|
-
<span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info:
|
|
196
|
+
<span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Visualizes how tasks progress through sequential execution phases." data-tooltip="Visualizes how tasks progress through sequential execution phases — from initial setup through integration, validation, and final quality gate."><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></span>
|
|
167
197
|
<p class="chart-card__desc">Task flow across execution phases</p>
|
|
168
198
|
</div>
|
|
169
199
|
<div class="chart-card__body" id="pipeline-view"></div>
|
|
@@ -275,7 +305,7 @@ try {
|
|
|
275
305
|
<div class="chart-card__header">
|
|
276
306
|
<h2 class="chart-card__title">Event Timeline</h2>
|
|
277
307
|
<span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Chronological log of everything that happened during this run." data-tooltip="Chronological log of everything that happened during this run."><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></span>
|
|
278
|
-
<p class="chart-card__desc">Convoy events in
|
|
308
|
+
<p class="chart-card__desc">Convoy events in chronological order</p>
|
|
279
309
|
</div>
|
|
280
310
|
<div class="chart-card__body">
|
|
281
311
|
<div id="event-timeline-filters" class="timeline-filters"></div>
|
|
@@ -296,16 +326,6 @@ try {
|
|
|
296
326
|
<div class="chart-card__body" id="execution-log"></div>
|
|
297
327
|
</section>
|
|
298
328
|
|
|
299
|
-
<!-- Panel Reviews -->
|
|
300
|
-
<section class="chart-card" id="panel-section" data-nav-section>
|
|
301
|
-
<div class="chart-card__header">
|
|
302
|
-
<h2 class="chart-card__title">Panel Reviews</h2>
|
|
303
|
-
<span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Quality gate verdicts from majority-vote panels." data-tooltip="Quality gate verdicts from majority-vote panels."><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></span>
|
|
304
|
-
<p class="chart-card__desc">Quality gate verdicts and fix items</p>
|
|
305
|
-
</div>
|
|
306
|
-
<div class="chart-card__body" id="panel-chart"></div>
|
|
307
|
-
</section>
|
|
308
|
-
|
|
309
329
|
<!-- Fast Reviews -->
|
|
310
330
|
<section class="chart-card" id="reviews-section" data-nav-section>
|
|
311
331
|
<div class="chart-card__header">
|
|
@@ -316,6 +336,16 @@ try {
|
|
|
316
336
|
<div class="chart-card__body chart-card__body--table" id="reviews-table"></div>
|
|
317
337
|
</section>
|
|
318
338
|
|
|
339
|
+
<!-- Panel Reviews -->
|
|
340
|
+
<section class="chart-card" id="panel-section" data-nav-section>
|
|
341
|
+
<div class="chart-card__header">
|
|
342
|
+
<h2 class="chart-card__title">Panel Reviews</h2>
|
|
343
|
+
<span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Quality gate verdicts from majority-vote panels." data-tooltip="Quality gate verdicts from majority-vote panels."><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></span>
|
|
344
|
+
<p class="chart-card__desc">Quality gate verdicts and fix items</p>
|
|
345
|
+
</div>
|
|
346
|
+
<div class="chart-card__body" id="panel-chart"></div>
|
|
347
|
+
</section>
|
|
348
|
+
|
|
319
349
|
</div><!-- .view-convoy-detail -->
|
|
320
350
|
|
|
321
351
|
|
|
@@ -361,6 +391,7 @@ try {
|
|
|
361
391
|
standard: '#a78bfa',
|
|
362
392
|
utility: '#3b82f6',
|
|
363
393
|
economy: '#64748b',
|
|
394
|
+
unknown: '#94a3b8',
|
|
364
395
|
};
|
|
365
396
|
|
|
366
397
|
const MODEL_COLORS = {
|
|
@@ -493,6 +524,8 @@ try {
|
|
|
493
524
|
}
|
|
494
525
|
renderOverallStats();
|
|
495
526
|
renderConvoyList();
|
|
527
|
+
renderActivityTimeline();
|
|
528
|
+
renderRecentSessions();
|
|
496
529
|
} catch {
|
|
497
530
|
// Non-fatal
|
|
498
531
|
}
|
|
@@ -678,6 +711,14 @@ try {
|
|
|
678
711
|
}
|
|
679
712
|
|
|
680
713
|
// ── Convoy List ─────────────────────────────────────────
|
|
714
|
+
var convoyListCurrentPage = 1;
|
|
715
|
+
var CONVOY_LIST_PAGE_SIZE = 10;
|
|
716
|
+
var convoyChainExpanded = {};
|
|
717
|
+
var executionLogPageSize = 20;
|
|
718
|
+
var executionLogCurrentPage = 1;
|
|
719
|
+
var executionLogAllSortedTasks = [];
|
|
720
|
+
var executionLogLimit = 10;
|
|
721
|
+
|
|
681
722
|
function renderConvoyList() {
|
|
682
723
|
const data = window.__DASHBOARD_DATA__;
|
|
683
724
|
const list = data?.convoyList ?? [];
|
|
@@ -698,36 +739,112 @@ try {
|
|
|
698
739
|
|
|
699
740
|
if (filtered.length === 0) {
|
|
700
741
|
wrap.innerHTML = '';
|
|
742
|
+
var existingPag = document.getElementById('convoy-list-pagination');
|
|
743
|
+
if (existingPag) existingPag.remove();
|
|
701
744
|
if (emptyEl) emptyEl.style.display = '';
|
|
702
745
|
return;
|
|
703
746
|
}
|
|
704
747
|
if (emptyEl) emptyEl.style.display = 'none';
|
|
705
748
|
|
|
706
749
|
const statusBadgeClass = (s) => {
|
|
707
|
-
const map = { done: '--done', running: '--running', failed: '--failed', 'gate-failed': '--gate-failed', pending: '--pending' };
|
|
750
|
+
const map = { done: '--done', running: '--running', failed: '--failed', 'gate-failed': '--gate-failed', gate_failed: '--gate-failed', pending: '--pending' };
|
|
708
751
|
return 'status-badge ' + (map[s] || '');
|
|
709
752
|
};
|
|
710
753
|
|
|
754
|
+
// Group convoys by pipeline_id (non-null pipeline_id forms a chain)
|
|
755
|
+
var grouped = [];
|
|
756
|
+
var pipelineMap = {};
|
|
757
|
+
for (var gi = 0; gi < filtered.length; gi++) {
|
|
758
|
+
var gc = filtered[gi];
|
|
759
|
+
if (gc.pipeline_id) {
|
|
760
|
+
if (!pipelineMap[gc.pipeline_id]) {
|
|
761
|
+
pipelineMap[gc.pipeline_id] = { pipeline_id: gc.pipeline_id, convoys: [] };
|
|
762
|
+
grouped.push(pipelineMap[gc.pipeline_id]);
|
|
763
|
+
}
|
|
764
|
+
pipelineMap[gc.pipeline_id].convoys.push(gc);
|
|
765
|
+
} else {
|
|
766
|
+
grouped.push(gc);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// Pagination on grouped top-level items
|
|
771
|
+
var totalPages = Math.ceil(grouped.length / CONVOY_LIST_PAGE_SIZE);
|
|
772
|
+
if (convoyListCurrentPage > totalPages) convoyListCurrentPage = 1;
|
|
773
|
+
var pageStart = (convoyListCurrentPage - 1) * CONVOY_LIST_PAGE_SIZE;
|
|
774
|
+
var paginated = grouped.slice(pageStart, pageStart + CONVOY_LIST_PAGE_SIZE);
|
|
775
|
+
|
|
711
776
|
let html = '<table class="convoy-list-table"><thead><tr>' +
|
|
712
777
|
'<th>Name</th><th>Status</th><th>Tasks</th><th>Created</th><th>Duration</th>' +
|
|
713
778
|
'</tr></thead><tbody>';
|
|
714
779
|
|
|
715
|
-
for (
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
780
|
+
for (var pi = 0; pi < paginated.length; pi++) {
|
|
781
|
+
var item = paginated[pi];
|
|
782
|
+
if (item.convoys) {
|
|
783
|
+
// Pipeline group row
|
|
784
|
+
var grpConvoys = item.convoys;
|
|
785
|
+
var grpPipelineId = item.pipeline_id;
|
|
786
|
+
var isExpanded = !!convoyChainExpanded[grpPipelineId];
|
|
787
|
+
var grpStatus = (function(cs) {
|
|
788
|
+
if (cs.some(function(x) { return x.status === 'failed' || x.status === 'gate_failed'; })) return 'gate_failed';
|
|
789
|
+
if (cs.some(function(x) { return x.status === 'running'; })) return 'running';
|
|
790
|
+
if (cs.every(function(x) { return x.status === 'done'; })) return 'done';
|
|
791
|
+
return cs[0] ? cs[0].status : 'pending';
|
|
792
|
+
})(grpConvoys);
|
|
793
|
+
var grpTasks = grpConvoys.reduce(function(s, x) { return s + (x.task_count || 0); }, 0);
|
|
794
|
+
var grpEarliestCreated = grpConvoys.reduce(function(a, x) { return (!a || (x.created_at && x.created_at < a)) ? x.created_at : a; }, null);
|
|
795
|
+
var grpLatestFinished = grpConvoys.reduce(function(a, x) { return (!a || (x.finished_at && x.finished_at > a)) ? x.finished_at : a; }, null);
|
|
796
|
+
var grpAllFinished = grpConvoys.every(function(x) { return !!x.finished_at; });
|
|
797
|
+
var grpDuration = grpEarliestCreated && grpAllFinished && grpLatestFinished ? formatDuration(grpEarliestCreated, grpLatestFinished) : (grpStatus === 'running' ? 'In progress' : '\u2014');
|
|
798
|
+
var grpName = grpConvoys[0].pipeline_name || grpPipelineId.replace(/-/g, ' ').replace(/\b\w/g, function(l) { return l.toUpperCase(); });
|
|
799
|
+
var toggleIcon = isExpanded ? '\u25bc' : '\u25b6';
|
|
800
|
+
html += '<tr class="convoy-chain-row task-row--clickable" data-pipeline-group-id="' + escapeHtml(grpPipelineId) + '" aria-expanded="' + isExpanded + '" role="row">' +
|
|
801
|
+
'<td><span class="convoy-chain-toggle">' + toggleIcon + '</span><strong>' + escapeHtml(grpName) + '</strong></td>' +
|
|
802
|
+
'<td><span class="' + statusBadgeClass(grpStatus) + '">' + escapeHtml(grpStatus) + '</span></td>' +
|
|
803
|
+
'<td>' + grpTasks + '</td>' +
|
|
804
|
+
'<td>' + (grpEarliestCreated ? formatTime(grpEarliestCreated) : '\u2014') + '</td>' +
|
|
805
|
+
'<td>' + grpDuration + '</td>' +
|
|
806
|
+
'</tr>';
|
|
807
|
+
if (isExpanded) {
|
|
808
|
+
for (var ci = 0; ci < grpConvoys.length; ci++) {
|
|
809
|
+
var cc = grpConvoys[ci];
|
|
810
|
+
var ccName = escapeHtml(cc.name || cc.id);
|
|
811
|
+
var ccDate = cc.created_at ? formatTime(cc.created_at) : '\u2014';
|
|
812
|
+
var ccDur = cc.started_at && cc.finished_at ? formatDuration(cc.started_at, cc.finished_at) : (cc.status === 'running' ? 'In progress' : '\u2014');
|
|
813
|
+
var ccTasks = cc.task_count != null ? cc.task_count : '\u2014';
|
|
814
|
+
html += '<tr data-convoy-id="' + escapeHtml(cc.id) + '" class="task-row--clickable convoy-chain-child">' +
|
|
815
|
+
'<td><strong>' + ccName + '</strong></td>' +
|
|
816
|
+
'<td><span class="' + statusBadgeClass(cc.status) + '">' + escapeHtml(cc.status || 'unknown') + '</span></td>' +
|
|
817
|
+
'<td>' + ccTasks + '</td>' +
|
|
818
|
+
'<td>' + ccDate + '</td>' +
|
|
819
|
+
'<td>' + ccDur + '</td>' +
|
|
820
|
+
'</tr>';
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
} else {
|
|
824
|
+
var name = escapeHtml(item.name || item.id);
|
|
825
|
+
var dateStr = item.created_at ? formatTime(item.created_at) : '\u2014';
|
|
826
|
+
var duration = item.started_at && item.finished_at ? formatDuration(item.started_at, item.finished_at) : (item.status === 'running' ? 'In progress' : '\u2014');
|
|
827
|
+
var taskCount = item.task_count != null ? item.task_count : '\u2014';
|
|
828
|
+
html += '<tr data-convoy-id="' + escapeHtml(item.id) + '" class="task-row--clickable">' +
|
|
829
|
+
'<td><strong>' + name + '</strong></td>' +
|
|
830
|
+
'<td><span class="' + statusBadgeClass(item.status) + '">' + escapeHtml(item.status || 'unknown') + '</span></td>' +
|
|
831
|
+
'<td>' + taskCount + '</td>' +
|
|
832
|
+
'<td>' + dateStr + '</td>' +
|
|
833
|
+
'<td>' + (duration || '\u2014') + '</td>' +
|
|
834
|
+
'</tr>';
|
|
835
|
+
}
|
|
727
836
|
}
|
|
728
837
|
html += '</tbody></table>';
|
|
729
838
|
wrap.innerHTML = html;
|
|
730
839
|
|
|
840
|
+
wrap.querySelectorAll('tr[data-pipeline-group-id]').forEach(row => {
|
|
841
|
+
row.addEventListener('click', () => {
|
|
842
|
+
const groupId = row.dataset.pipelineGroupId;
|
|
843
|
+
convoyChainExpanded[groupId] = !convoyChainExpanded[groupId];
|
|
844
|
+
renderConvoyList();
|
|
845
|
+
});
|
|
846
|
+
});
|
|
847
|
+
|
|
731
848
|
wrap.querySelectorAll('tr[data-convoy-id]').forEach(row => {
|
|
732
849
|
row.addEventListener('click', () => {
|
|
733
850
|
const id = row.dataset.convoyId;
|
|
@@ -735,6 +852,26 @@ try {
|
|
|
735
852
|
showConvoyDetailView(id, nameCell ? nameCell.textContent : id);
|
|
736
853
|
});
|
|
737
854
|
});
|
|
855
|
+
|
|
856
|
+
// Render pagination controls
|
|
857
|
+
var oldPag = document.getElementById('convoy-list-pagination');
|
|
858
|
+
if (oldPag) oldPag.remove();
|
|
859
|
+
if (grouped.length > CONVOY_LIST_PAGE_SIZE) {
|
|
860
|
+
var pagEl = document.createElement('div');
|
|
861
|
+
pagEl.id = 'convoy-list-pagination';
|
|
862
|
+
pagEl.className = 'convoy-list-pagination';
|
|
863
|
+
pagEl.innerHTML =
|
|
864
|
+
'<button class="dash-btn dash-btn--ghost" id="convoy-list-prev" type="button"' + (convoyListCurrentPage === 1 ? ' disabled' : '') + '>Previous</button>' +
|
|
865
|
+
'<span class="convoy-list-pagination__info">Page ' + convoyListCurrentPage + ' of ' + totalPages + '</span>' +
|
|
866
|
+
'<button class="dash-btn dash-btn--ghost" id="convoy-list-next" type="button"' + (convoyListCurrentPage === totalPages ? ' disabled' : '') + '>Next</button>';
|
|
867
|
+
wrap.after(pagEl);
|
|
868
|
+
pagEl.querySelector('#convoy-list-prev').addEventListener('click', function() {
|
|
869
|
+
if (convoyListCurrentPage > 1) { convoyListCurrentPage--; renderConvoyList(); }
|
|
870
|
+
});
|
|
871
|
+
pagEl.querySelector('#convoy-list-next').addEventListener('click', function() {
|
|
872
|
+
if (convoyListCurrentPage < totalPages) { convoyListCurrentPage++; renderConvoyList(); }
|
|
873
|
+
});
|
|
874
|
+
}
|
|
738
875
|
}
|
|
739
876
|
|
|
740
877
|
// ── Overall Stats Rendering ──────────────────────────────
|
|
@@ -757,8 +894,28 @@ try {
|
|
|
757
894
|
|
|
758
895
|
const avgSec = ds.avg_sec;
|
|
759
896
|
setKpiValue('overall-avg-duration', avgSec != null ? formatDurationSec(avgSec) : '\u2014');
|
|
760
|
-
|
|
761
|
-
|
|
897
|
+
var totalTokens = (tc && tc.total_tokens) || 0;
|
|
898
|
+
var totalCost = (tc && tc.total_cost_usd) || 0;
|
|
899
|
+
setKpiValue('overall-total-tokens', formatTokens(totalTokens));
|
|
900
|
+
setKpiValue('overall-total-cost', '$' + totalCost.toFixed(2));
|
|
901
|
+
|
|
902
|
+
// Fallback: if overall stats show 0 tokens, sum from convoy list
|
|
903
|
+
if (totalTokens === 0) {
|
|
904
|
+
var convoyListFallback = (window.__DASHBOARD_DATA__ && window.__DASHBOARD_DATA__.convoyList) || [];
|
|
905
|
+
if (convoyListFallback.length > 0) {
|
|
906
|
+
var sumTokens = convoyListFallback.reduce(function(s, c) { return s + (c.total_tokens != null ? c.total_tokens : 0); }, 0);
|
|
907
|
+
var sumCost = convoyListFallback.reduce(function(s, c) { return s + (c.total_cost_usd != null ? c.total_cost_usd : 0); }, 0);
|
|
908
|
+
if (sumTokens > 0) {
|
|
909
|
+
setKpiValue('overall-total-tokens', formatTokens(sumTokens));
|
|
910
|
+
setKpiValue('overall-total-cost', '$' + sumCost.toFixed(2));
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// Total tasks and retries
|
|
916
|
+
var tt = stats.taskTotals || {};
|
|
917
|
+
setKpiValue('overall-total-tasks', String(tt.totalTasks || 0));
|
|
918
|
+
setKpiValue('overall-total-retries', String(tt.totalRetries || 0));
|
|
762
919
|
}
|
|
763
920
|
|
|
764
921
|
function setKpiValue(id, value) {
|
|
@@ -779,7 +936,70 @@ try {
|
|
|
779
936
|
return hr + 'h ' + remMin + 'm';
|
|
780
937
|
}
|
|
781
938
|
|
|
939
|
+
function renderActivityTimeline() {
|
|
940
|
+
var el = document.getElementById('activity-timeline-chart');
|
|
941
|
+
if (!el) return;
|
|
942
|
+
var data = window.__DASHBOARD_DATA__;
|
|
943
|
+
var timeline = (data && data.overallStats && data.overallStats.activityTimeline) || [];
|
|
944
|
+
if (timeline.length === 0) {
|
|
945
|
+
el.innerHTML = emptyStateHtml('timeline', 'No activity yet', 'Convoy run activity will appear here as runs complete.');
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
var maxCount = Math.max.apply(null, timeline.map(function(d) { return d.count; }));
|
|
949
|
+
var html = '<div class="activity-timeline">';
|
|
950
|
+
for (var i = 0; i < timeline.length; i++) {
|
|
951
|
+
var d = timeline[i];
|
|
952
|
+
var pct = maxCount > 0 ? Math.round((d.count / maxCount) * 100) : 0;
|
|
953
|
+
html += '<div class="bar-row">' +
|
|
954
|
+
'<span class="bar-label">' + formatShortDate(d.date) + '</span>' +
|
|
955
|
+
'<div class="bar-track"><div class="bar-segment bar--accent" style="width:' + pct + '%"></div></div>' +
|
|
956
|
+
'<span class="bar-value">' + d.count + '</span>' +
|
|
957
|
+
'</div>';
|
|
958
|
+
}
|
|
959
|
+
html += '</div>';
|
|
960
|
+
el.innerHTML = html;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
async function renderRecentSessions() {
|
|
964
|
+
var el = document.getElementById('sessions-table');
|
|
965
|
+
if (!el) return;
|
|
966
|
+
try {
|
|
967
|
+
var allEvents = await loadNdjson(base + 'data/events.ndjson');
|
|
968
|
+
var sessions = allEvents.filter(function(e) { return e.type === 'session'; });
|
|
969
|
+
sessions.sort(function(a, b) {
|
|
970
|
+
return (b.timestamp || '').localeCompare(a.timestamp || '');
|
|
971
|
+
});
|
|
972
|
+
sessions = sessions.slice(0, 15);
|
|
973
|
+
if (sessions.length === 0) {
|
|
974
|
+
el.innerHTML = emptyStateHtml('sessions', 'No sessions recorded yet', 'Agent session data will appear here when sessions are logged via opencastle log.');
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
var thead = '<thead><tr>' +
|
|
978
|
+
'<th>Agent</th><th>Task</th><th>Outcome</th><th>Duration</th><th>Retries</th><th>Files</th><th>Time</th>' +
|
|
979
|
+
'</tr></thead>';
|
|
980
|
+
var tbody = '<tbody>';
|
|
981
|
+
for (var i = 0; i < sessions.length; i++) {
|
|
982
|
+
var s = sessions[i];
|
|
983
|
+
var outcomeClass = s.outcome === 'success' ? 'outcome-badge--success' : s.outcome === 'failed' ? 'outcome-badge--failed' : 'outcome-badge--partial';
|
|
984
|
+
tbody += '<tr>' +
|
|
985
|
+
'<td class="td-agent">' + escapeHtml(s.agent || '\u2014') + '</td>' +
|
|
986
|
+
'<td class="td-task">' + escapeHtml(s.task || '\u2014') + '</td>' +
|
|
987
|
+
'<td><span class="outcome-badge ' + outcomeClass + '">' + escapeHtml(s.outcome || '\u2014') + '</span></td>' +
|
|
988
|
+
'<td>' + (s.duration_min != null ? s.duration_min + 'm' : '\u2014') + '</td>' +
|
|
989
|
+
'<td>' + (s.retries || 0) + '</td>' +
|
|
990
|
+
'<td>' + (s.files_changed || 0) + '</td>' +
|
|
991
|
+
'<td>' + (s.timestamp ? formatTime(s.timestamp) : '\u2014') + '</td>' +
|
|
992
|
+
'</tr>';
|
|
993
|
+
}
|
|
994
|
+
tbody += '</tbody>';
|
|
995
|
+
el.innerHTML = '<table class="sessions-table">' + thead + tbody + '</table>';
|
|
996
|
+
} catch (e) {
|
|
997
|
+
el.innerHTML = emptyStateHtml('sessions', 'No sessions recorded yet', 'Agent session data will appear here when sessions are logged.');
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
782
1001
|
async function loadConvoyDetail(convoyId) {
|
|
1002
|
+
executionLogLimit = 10;
|
|
783
1003
|
if (!convoyId) {
|
|
784
1004
|
renderConvoyDetailHeader(null);
|
|
785
1005
|
['pipeline-section', 'agent-section', 'tier-section', 'model-section', 'quality-section', 'reliability-section', 'drift-section', 'outputs-section', 'execution-section', 'event-timeline-section', 'panel-section', 'reviews-section'].forEach(function(id) {
|
|
@@ -1034,6 +1254,21 @@ try {
|
|
|
1034
1254
|
|
|
1035
1255
|
function deriveTier(model) {
|
|
1036
1256
|
if (!model) return 'unknown';
|
|
1257
|
+
var TIER_MAP = {
|
|
1258
|
+
'claude-opus-4-6': 'premium',
|
|
1259
|
+
'claude-opus-4': 'premium',
|
|
1260
|
+
'claude-sonnet-4-6': 'standard',
|
|
1261
|
+
'claude-sonnet-4': 'standard',
|
|
1262
|
+
'claude-haiku-3-5': 'economy',
|
|
1263
|
+
'claude-haiku-4': 'economy',
|
|
1264
|
+
'gpt-5-mini': 'economy',
|
|
1265
|
+
'gpt-5.3-codex': 'standard',
|
|
1266
|
+
'gpt-5': 'standard',
|
|
1267
|
+
'gemini-3.1-pro': 'standard',
|
|
1268
|
+
'gemini-3.0-flash': 'economy',
|
|
1269
|
+
};
|
|
1270
|
+
if (TIER_MAP[model]) return TIER_MAP[model];
|
|
1271
|
+
// Fallback heuristics for unknown models
|
|
1037
1272
|
var m = model.toLowerCase();
|
|
1038
1273
|
if (m.includes('opus')) return 'premium';
|
|
1039
1274
|
if (m.includes('sonnet') || m.includes('pro')) return 'standard';
|
|
@@ -1186,8 +1421,9 @@ try {
|
|
|
1186
1421
|
var mechOrder = ['sub-agent', 'background', 'unknown'];
|
|
1187
1422
|
var mechs = mechOrder.filter(function(m) { return mechCounts[m]; }).map(function(m) { return { name: m, count: mechCounts[m] }; });
|
|
1188
1423
|
|
|
1189
|
-
|
|
1190
|
-
|
|
1424
|
+
var isAllUnknown = mechs.length === 0 || (mechs.length === 1 && mechs[0].name === 'unknown');
|
|
1425
|
+
if (isAllUnknown) {
|
|
1426
|
+
el.innerHTML = emptyStateHtml('mechanism', 'No delegation data', 'Delegation mechanism data is not available for this convoy.');
|
|
1191
1427
|
return;
|
|
1192
1428
|
}
|
|
1193
1429
|
|
|
@@ -1265,7 +1501,7 @@ try {
|
|
|
1265
1501
|
var models = Object.entries(modelCounts).sort(function(a, b) { return b[1] - a[1]; });
|
|
1266
1502
|
|
|
1267
1503
|
if (models.length === 0) {
|
|
1268
|
-
el.innerHTML = emptyStateHtml('models', 'No model data yet', 'Model utilization across tasks will be shown here.');
|
|
1504
|
+
el.innerHTML = emptyStateHtml('models', tasks.length > 0 ? 'Model information unavailable' : 'No model data yet', tasks.length > 0 ? 'No model information was recorded for tasks in this convoy.' : 'Model utilization across tasks will be shown here.');
|
|
1269
1505
|
return;
|
|
1270
1506
|
}
|
|
1271
1507
|
|
|
@@ -1293,7 +1529,8 @@ try {
|
|
|
1293
1529
|
return;
|
|
1294
1530
|
}
|
|
1295
1531
|
|
|
1296
|
-
var
|
|
1532
|
+
var allSorted = tasks.slice().filter(function(t) { return t.started_at; }).sort(function(a, b) { return new Date(a.started_at) - new Date(b.started_at); });
|
|
1533
|
+
var sorted = allSorted.slice(0, executionLogLimit);
|
|
1297
1534
|
|
|
1298
1535
|
if (sorted.length === 0) {
|
|
1299
1536
|
el.innerHTML = emptyStateHtml('execLog', 'No execution history yet', 'A step-by-step trace of task activity will appear here.');
|
|
@@ -1335,6 +1572,15 @@ try {
|
|
|
1335
1572
|
'</div>';
|
|
1336
1573
|
}).join('') +
|
|
1337
1574
|
'</div>';
|
|
1575
|
+
if (allSorted.length > executionLogLimit) {
|
|
1576
|
+
var remaining = allSorted.length - executionLogLimit;
|
|
1577
|
+
el.innerHTML += '<div style="text-align:center;padding:16px"><button class="dash-btn dash-btn--ghost" id="exec-log-more-btn" type="button">Show more (' + remaining + ' remaining)</button></div>';
|
|
1578
|
+
document.getElementById('exec-log-more-btn')?.addEventListener('click', function() {
|
|
1579
|
+
executionLogLimit = allSorted.length;
|
|
1580
|
+
var convoy = window.__SELECTED_CONVOY__;
|
|
1581
|
+
renderDetailExecutionLog((convoy && convoy.tasks) ? convoy.tasks : []);
|
|
1582
|
+
});
|
|
1583
|
+
}
|
|
1338
1584
|
}
|
|
1339
1585
|
|
|
1340
1586
|
// ── Convoy Detail: Panel Reviews ─────────────────────────
|
|
@@ -1346,7 +1592,7 @@ try {
|
|
|
1346
1592
|
var panelTasks = (tasks || []).filter(function(t) { return t.panel_attempts > 0; });
|
|
1347
1593
|
|
|
1348
1594
|
if (panelTasks.length === 0) {
|
|
1349
|
-
el.innerHTML = emptyStateHtml('panels', 'No panel reviews
|
|
1595
|
+
el.innerHTML = emptyStateHtml('panels', 'No panel reviews', 'This convoy completed without requiring panel reviews.');
|
|
1350
1596
|
return;
|
|
1351
1597
|
}
|
|
1352
1598
|
|
|
@@ -1382,7 +1628,7 @@ try {
|
|
|
1382
1628
|
var reviewedTasks = (tasks || []).filter(function(t) { return t.review_level != null; });
|
|
1383
1629
|
|
|
1384
1630
|
if (reviewedTasks.length === 0) {
|
|
1385
|
-
el.innerHTML = emptyStateHtml('panels', 'No fast reviews
|
|
1631
|
+
el.innerHTML = emptyStateHtml('panels', 'No fast reviews', 'This convoy completed without fast review gates.');
|
|
1386
1632
|
return;
|
|
1387
1633
|
}
|
|
1388
1634
|
|
|
@@ -1487,13 +1733,27 @@ try {
|
|
|
1487
1733
|
|
|
1488
1734
|
var dlqCount = detail.dlq_count || 0;
|
|
1489
1735
|
var dlqEntries = detail.dlq_entries || [];
|
|
1736
|
+
var tasks = detail.tasks || [];
|
|
1490
1737
|
|
|
1491
1738
|
var dlqCardEl = document.getElementById('reliability-dlq-card');
|
|
1492
1739
|
if (dlqCardEl) {
|
|
1740
|
+
var totalRetries = tasks.reduce(function(s, t) { return s + (t.retries || 0); }, 0);
|
|
1741
|
+
var doneTasks = tasks.filter(function(t) { return t.status === 'done'; }).length;
|
|
1742
|
+
var successRate = tasks.length > 0 ? Math.round((doneTasks / tasks.length) * 100) + '%' : '\u2014';
|
|
1493
1743
|
dlqCardEl.innerHTML =
|
|
1744
|
+
'<div class="task-summary-cards">' +
|
|
1494
1745
|
'<div class="task-summary-card task-summary-card--' + (dlqCount > 0 ? 'errors' : 'done') + '">' +
|
|
1495
1746
|
'<span class="task-summary-card__label">Retry Queue <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Tasks that failed too many times and need manual attention. Also known as Dead Letter Queue (DLQ)." data-tooltip="Tasks that failed too many times and need manual attention. Also known as Dead Letter Queue (DLQ).">' + INFO_ICON + '</span></span>' +
|
|
1496
1747
|
'<span class="task-summary-card__value">' + dlqCount + '</span>' +
|
|
1748
|
+
'</div>' +
|
|
1749
|
+
'<div class="task-summary-card task-summary-card--running">' +
|
|
1750
|
+
'<span class="task-summary-card__label">Total Retries <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Total number of task retries across all tasks in this convoy." data-tooltip="Total number of task retries across all tasks in this convoy.">' + INFO_ICON + '</span></span>' +
|
|
1751
|
+
'<span class="task-summary-card__value">' + totalRetries + '</span>' +
|
|
1752
|
+
'</div>' +
|
|
1753
|
+
'<div class="task-summary-card task-summary-card--done">' +
|
|
1754
|
+
'<span class="task-summary-card__label">Task Success Rate <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Percentage of tasks that completed successfully." data-tooltip="Percentage of tasks that completed successfully.">' + INFO_ICON + '</span></span>' +
|
|
1755
|
+
'<span class="task-summary-card__value">' + successRate + '</span>' +
|
|
1756
|
+
'</div>' +
|
|
1497
1757
|
'</div>';
|
|
1498
1758
|
}
|
|
1499
1759
|
|
|
@@ -1523,7 +1783,6 @@ try {
|
|
|
1523
1783
|
|
|
1524
1784
|
var errorEl = document.getElementById('reliability-error-overview');
|
|
1525
1785
|
if (errorEl) {
|
|
1526
|
-
var tasks = detail.tasks || [];
|
|
1527
1786
|
var errorCategories = [
|
|
1528
1787
|
{ key: 'failed', label: 'Failed', color: '#ef4444' },
|
|
1529
1788
|
{ key: 'gate-failed', label: 'Quality Check Failed', color: '#f59e0b' },
|
|
@@ -1605,8 +1864,8 @@ try {
|
|
|
1605
1864
|
if (!section) return;
|
|
1606
1865
|
section.style.display = '';
|
|
1607
1866
|
|
|
1608
|
-
var artifactCount = detail.artifact_count != null ? detail.artifact_count : 0;
|
|
1609
1867
|
var artifacts = detail.artifacts || [];
|
|
1868
|
+
var artifactCount = artifacts.length;
|
|
1610
1869
|
|
|
1611
1870
|
var cardsEl = document.getElementById('outputs-cards');
|
|
1612
1871
|
if (cardsEl) {
|
|
@@ -1649,7 +1908,7 @@ try {
|
|
|
1649
1908
|
}
|
|
1650
1909
|
|
|
1651
1910
|
// ── Event Timeline Section ─────────────────────────────
|
|
1652
|
-
var eventTimelinePageSize =
|
|
1911
|
+
var eventTimelinePageSize = 20;
|
|
1653
1912
|
var eventTimelineCurrentPage = 1;
|
|
1654
1913
|
var eventTimelineActiveFilter = 'all';
|
|
1655
1914
|
var eventTimelineAllEvents = [];
|
|
@@ -1686,7 +1945,10 @@ try {
|
|
|
1686
1945
|
if (!section) return;
|
|
1687
1946
|
section.style.display = '';
|
|
1688
1947
|
|
|
1689
|
-
eventTimelineAllEvents = detail.events || []
|
|
1948
|
+
eventTimelineAllEvents = (detail.events || []).slice().sort(function(a, b) {
|
|
1949
|
+
if (!a.created_at || !b.created_at) return 0;
|
|
1950
|
+
return a.created_at < b.created_at ? -1 : a.created_at > b.created_at ? 1 : 0;
|
|
1951
|
+
});
|
|
1690
1952
|
eventTimelineCurrentPage = 1;
|
|
1691
1953
|
eventTimelineActiveFilter = 'all';
|
|
1692
1954
|
|
|
@@ -1772,8 +2034,15 @@ try {
|
|
|
1772
2034
|
});
|
|
1773
2035
|
|
|
1774
2036
|
var loadMoreEl = document.getElementById('event-timeline-load-more');
|
|
2037
|
+
var loadMoreBtn = document.getElementById('event-timeline-more-btn');
|
|
1775
2038
|
if (loadMoreEl) {
|
|
1776
|
-
|
|
2039
|
+
if (visible.length < filtered.length) {
|
|
2040
|
+
loadMoreEl.style.display = '';
|
|
2041
|
+
var remaining = filtered.length - visible.length;
|
|
2042
|
+
if (loadMoreBtn) loadMoreBtn.textContent = 'Show more (' + remaining + ' remaining)';
|
|
2043
|
+
} else {
|
|
2044
|
+
loadMoreEl.style.display = 'none';
|
|
2045
|
+
}
|
|
1777
2046
|
}
|
|
1778
2047
|
}
|
|
1779
2048
|
|
|
@@ -1823,6 +2092,8 @@ try {
|
|
|
1823
2092
|
|
|
1824
2093
|
renderOverallStats();
|
|
1825
2094
|
renderConvoyList();
|
|
2095
|
+
renderActivityTimeline();
|
|
2096
|
+
renderRecentSessions();
|
|
1826
2097
|
|
|
1827
2098
|
var loadMoreBtn = document.getElementById('event-timeline-more-btn');
|
|
1828
2099
|
if (loadMoreBtn) {
|
|
@@ -1837,15 +2108,47 @@ try {
|
|
|
1837
2108
|
showHomeView();
|
|
1838
2109
|
});
|
|
1839
2110
|
|
|
1840
|
-
document.getElementById('
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
2111
|
+
document.getElementById('export-btn')?.addEventListener('click', function() {
|
|
2112
|
+
var exportData = {
|
|
2113
|
+
overallStats: window.__DASHBOARD_DATA__ && window.__DASHBOARD_DATA__.overallStats,
|
|
2114
|
+
convoyList: window.__DASHBOARD_DATA__ && window.__DASHBOARD_DATA__.convoyList,
|
|
2115
|
+
};
|
|
2116
|
+
if (window.__SELECTED_CONVOY__) {
|
|
2117
|
+
exportData.selectedConvoy = window.__SELECTED_CONVOY__;
|
|
2118
|
+
}
|
|
2119
|
+
var blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
|
|
2120
|
+
var url = URL.createObjectURL(blob);
|
|
2121
|
+
var a = document.createElement('a');
|
|
2122
|
+
a.href = url;
|
|
2123
|
+
a.download = 'opencastle-dashboard-export.json';
|
|
2124
|
+
document.body.appendChild(a);
|
|
2125
|
+
a.click();
|
|
2126
|
+
document.body.removeChild(a);
|
|
2127
|
+
URL.revokeObjectURL(url);
|
|
2128
|
+
});
|
|
2129
|
+
|
|
2130
|
+
document.getElementById('cl-filter-search')?.addEventListener('input', function() {
|
|
2131
|
+
convoyListCurrentPage = 1;
|
|
2132
|
+
renderConvoyList();
|
|
2133
|
+
});
|
|
2134
|
+
document.getElementById('cl-filter-status')?.addEventListener('change', function() {
|
|
2135
|
+
convoyListCurrentPage = 1;
|
|
2136
|
+
renderConvoyList();
|
|
2137
|
+
});
|
|
2138
|
+
document.getElementById('cl-filter-from')?.addEventListener('change', function() {
|
|
2139
|
+
convoyListCurrentPage = 1;
|
|
2140
|
+
renderConvoyList();
|
|
2141
|
+
});
|
|
2142
|
+
document.getElementById('cl-filter-to')?.addEventListener('change', function() {
|
|
2143
|
+
convoyListCurrentPage = 1;
|
|
2144
|
+
renderConvoyList();
|
|
2145
|
+
});
|
|
1844
2146
|
document.getElementById('cl-filter-reset')?.addEventListener('click', () => {
|
|
1845
2147
|
const s = document.getElementById('cl-filter-search'); if (s) s.value = '';
|
|
1846
2148
|
const st = document.getElementById('cl-filter-status'); if (st) st.value = '';
|
|
1847
2149
|
const f = document.getElementById('cl-filter-from'); if (f) f.value = '';
|
|
1848
2150
|
const t = document.getElementById('cl-filter-to'); if (t) t.value = '';
|
|
2151
|
+
convoyListCurrentPage = 1;
|
|
1849
2152
|
renderConvoyList();
|
|
1850
2153
|
});
|
|
1851
2154
|
|