opencastle 0.27.3 → 0.28.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/bin/cli.mjs +13 -5
- package/dist/cli/convoy/engine.js +2 -2
- package/dist/cli/convoy/engine.js.map +1 -1
- package/dist/cli/convoy/engine.test.js +1 -1
- package/dist/cli/convoy/engine.test.js.map +1 -1
- package/dist/cli/convoy/issues.js +3 -3
- package/dist/cli/convoy/issues.js.map +1 -1
- package/dist/cli/convoy/issues.test.js +4 -3
- package/dist/cli/convoy/issues.test.js.map +1 -1
- package/dist/cli/pipeline.d.ts +3 -0
- package/dist/cli/pipeline.d.ts.map +1 -0
- package/dist/cli/pipeline.js +305 -0
- package/dist/cli/pipeline.js.map +1 -0
- package/dist/cli/plan.d.ts +37 -0
- package/dist/cli/plan.d.ts.map +1 -1
- package/dist/cli/plan.js +321 -161
- package/dist/cli/plan.js.map +1 -1
- package/dist/cli/validate.d.ts +3 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +60 -0
- package/dist/cli/validate.js.map +1 -0
- package/package.json +5 -4
- package/src/cli/convoy/engine.test.ts +1 -1
- package/src/cli/convoy/engine.ts +2 -2
- package/src/cli/convoy/issues.test.ts +3 -2
- package/src/cli/convoy/issues.ts +3 -3
- package/src/cli/pipeline.ts +343 -0
- package/src/cli/plan.ts +357 -153
- package/src/cli/validate.ts +65 -0
- package/src/dashboard/dist/data/convoy-list.json +54 -9
- package/src/dashboard/dist/data/convoys/demo-api-v2.json +177 -0
- package/src/dashboard/dist/data/convoys/demo-auth-revamp.json +239 -0
- package/src/dashboard/dist/data/convoys/demo-dashboard-ui.json +328 -0
- package/src/dashboard/dist/data/convoys/demo-data-pipeline.json +187 -0
- package/src/dashboard/dist/data/convoys/demo-deploy-ci.json +153 -0
- package/src/dashboard/dist/data/convoys/demo-docs-update.json +154 -0
- package/src/dashboard/dist/data/convoys/demo-perf-opt.json +227 -0
- package/src/dashboard/dist/data/events.ndjson +115 -0
- package/src/dashboard/dist/data/overall-stats.json +56 -13
- package/src/dashboard/dist/data/pipelines.ndjson +5285 -0
- package/src/dashboard/dist/index.html +39 -16
- package/src/dashboard/node_modules/.vite/deps/_metadata.json +6 -6
- package/src/dashboard/public/data/convoy-list.json +54 -9
- package/src/dashboard/public/data/convoys/demo-api-v2.json +177 -0
- package/src/dashboard/public/data/convoys/demo-auth-revamp.json +239 -0
- package/src/dashboard/public/data/convoys/demo-dashboard-ui.json +328 -0
- package/src/dashboard/public/data/convoys/demo-data-pipeline.json +187 -0
- package/src/dashboard/public/data/convoys/demo-deploy-ci.json +153 -0
- package/src/dashboard/public/data/convoys/demo-docs-update.json +154 -0
- package/src/dashboard/public/data/convoys/demo-perf-opt.json +227 -0
- package/src/dashboard/public/data/events.ndjson +115 -0
- package/src/dashboard/public/data/overall-stats.json +56 -13
- package/src/dashboard/public/data/pipelines.ndjson +5285 -0
- package/src/dashboard/scripts/etl.ts +24 -3
- package/src/dashboard/scripts/generate-demo-db.ts +482 -115
- package/src/dashboard/src/pages/index.astro +46 -23
- package/src/orchestrator/prompts/fix-convoy.prompt.md +79 -0
- package/src/orchestrator/prompts/generate-convoy.prompt.md +53 -58
- package/src/orchestrator/prompts/generate-prd.prompt.md +120 -0
- package/src/orchestrator/prompts/validate-convoy.prompt.md +89 -0
- package/src/orchestrator/prompts/validate-prd.prompt.md +83 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Observability Dashboard — OpenCastle</title><meta name="description" content="Real-time observability for OpenCastle multi-agent orchestration — sessions, delegations, model tiers, and quality gates."><meta name="theme-color" content="#0a0a0f"><link rel="icon" type="image/png" sizes="192x192" href="/icon-192.png"><link rel="stylesheet" href="/_astro/index.6L3_HsPT.css"></head> <body> <script>(function(){const overallStats = {"convoyCounts":{"total":
|
|
2
|
-
const convoyList = [{"id":"demo-
|
|
1
|
+
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Observability Dashboard — OpenCastle</title><meta name="description" content="Real-time observability for OpenCastle multi-agent orchestration — sessions, delegations, model tiers, and quality gates."><meta name="theme-color" content="#0a0a0f"><link rel="icon" type="image/png" sizes="192x192" href="/icon-192.png"><link rel="stylesheet" href="/_astro/index.6L3_HsPT.css"></head> <body> <script>(function(){const overallStats = {"convoyCounts":{"total":7,"running":1,"done":5,"failed":0,"gate_failed":0},"durationStats":{"avg_sec":2950.0000052154064,"p95_sec":3720.000019669533,"max_sec":5879.9999713897705},"tokenCostTotals":{"total_tokens":226750,"total_cost_usd":22.67},"topAgents":[{"agent":"Developer","task_count":6,"total_tokens":70100},{"agent":"Reviewer","task_count":5,"total_tokens":16250},{"agent":"UI/UX Expert","task_count":3,"total_tokens":32300},{"agent":"Testing Expert","task_count":3,"total_tokens":28800},{"agent":"DevOps Expert","task_count":3,"total_tokens":6400}],"topModels":[{"model":"claude-sonnet-4-6","task_count":21,"total_tokens":177650},{"model":"claude-haiku-3-5","task_count":5,"total_tokens":17700},{"model":"claude-opus-4-6","task_count":4,"total_tokens":40700}],"dlqSummary":{"count":3,"top_failure_types":[{"type":"timeout","count":1},{"type":"review_blocked","count":1},{"type":"gate_failed","count":1}]}};
|
|
2
|
+
const convoyList = [{"id":"demo-deploy-ci","name":"CI/CD Pipeline Setup","status":"running","created_at":"2026-03-11T08:00:00.000Z","finished_at":null,"total_tokens":null,"total_cost_usd":null},{"id":"demo-docs-update","name":"Documentation Refresh","status":"done","created_at":"2026-02-28T15:00:00.000Z","finished_at":"2026-02-28T15:22:00.000Z","total_tokens":14800,"total_cost_usd":1.48},{"id":"demo-data-pipeline","name":"Analytics ETL Pipeline","status":"done","created_at":"2026-02-22T13:00:00.000Z","finished_at":"2026-02-22T13:38:00.000Z","total_tokens":28900,"total_cost_usd":2.89},{"id":"demo-perf-opt","name":"Frontend Performance Boost","status":"done","created_at":"2026-02-17T10:00:00.000Z","finished_at":"2026-02-17T11:02:00.000Z","total_tokens":37200,"total_cost_usd":3.72},{"id":"demo-api-v2","name":"REST API v2 Migration","status":"gate_failed","created_at":"2026-02-12T16:00:00.000Z","finished_at":"2026-02-12T16:28:00.000Z","total_tokens":24600,"total_cost_usd":2.46},{"id":"demo-dashboard-ui","name":"Observability Dashboard UI","status":"done","created_at":"2026-02-07T14:00:00.000Z","finished_at":"2026-02-07T15:38:00.000Z","total_tokens":78400,"total_cost_usd":7.84},{"id":"demo-auth-revamp","name":"Auth System Revamp","status":"done","created_at":"2026-02-03T09:00:00.000Z","finished_at":"2026-02-03T09:47:00.000Z","total_tokens":42850,"total_cost_usd":4.28}];
|
|
3
3
|
|
|
4
4
|
window.__DASHBOARD_DATA__ = { overallStats, convoyList }
|
|
5
5
|
})();</script> <header class="dash-header"> <div class="dash-header__inner"> <div class="dash-header__brand"> <img class="dash-header__icon" src="/icon-192.png" alt="OpenCastle" width="32" height="32"> <h1 class="dash-header__title">Observability Dashboard</h1> </div> <div class="dash-header__actions"> <div class="convoy-selector"> <label class="convoy-selector__label" for="convoy-select">Convoy</label> <select class="convoy-selector__select" id="convoy-select" aria-label="Select a convoy to view its details"> <option value="">Select convoy…</option> </select> </div> <button class="dash-btn dash-btn--ghost" id="export-btn" type="button" title="Export data as JSON" aria-label="Export dashboard data as JSON"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
|
|
6
6
|
Export
|
|
7
|
-
</button> </div> </div> </header> <div class="dash-layout"> <!-- Sidebar Navigation --> <nav class="dash-sidebar" id="dash-sidebar"> <ul class="dash-sidebar__list"> <li><a class="dash-sidebar__link dash-sidebar__link--active" href="#overall-section" data-section="overall-section" aria-label="Overview section">Overview</a></li> <li><a class="dash-sidebar__link" href="#convoy-section" data-section="convoy-section" aria-label="Convoy section">Convoy</a></li> <li><a class="dash-sidebar__link" href="#tasks-section" data-section="tasks-section" aria-label="Tasks section">Tasks</a></li> <li><a class="dash-sidebar__link" href="#quality-section" data-section="quality-section" aria-label="Quality section">Quality</a></li> <li><a class="dash-sidebar__link" href="#reliability-section" data-section="reliability-section" aria-label="Reliability section">Reliability</a></li> <li><a class="dash-sidebar__link" href="#drift-section" data-section="drift-section" aria-label="Drift section">Drift</a></li> <li><a class="dash-sidebar__link" href="#outputs-section" data-section="outputs-section" aria-label="Outputs section">Outputs</a></li> <li><a class="dash-sidebar__link" href="#event-timeline-section" data-section="event-timeline-section" aria-label="Event Log section">Event Log</a></li> </ul> </nav> <main class="dash-main"> <!-- Overall Stats Section --> <section class="overall-stats" id="overall-section" data-nav-section> <div class="overall-stats__header"> <h2 class="overall-stats__title">Overall Stats</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: How all runs behave across your project." data-tooltip="How all runs behave across your project.">ℹ️</span> </div> <div class="overall-stats__grid"> <div class="overall-kpi" id="overall-total-runs"> <span class="overall-kpi__label">Total Runs <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Number of convoy runs executed" data-tooltip="Number of convoy runs executed">ℹ️</span></span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-running"> <span class="overall-kpi__label">Running Now</span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-success-rate"> <span class="overall-kpi__label">Success Rate</span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-avg-duration"> <span class="overall-kpi__label">Avg Duration</span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-total-tokens"> <span class="overall-kpi__label">Total Tokens</span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-total-cost"> <span class="overall-kpi__label">Total Cost</span> <span class="overall-kpi__value">—</span> </div> </div> </section> <!-- Selected Convoy Header --> <section class="convoy-detail-header" id="convoy-detail-header"> <div class="convoy-detail-header__top"> <h2 class="convoy-detail-header__name" id="selected-convoy-name">No convoy selected</h2> <span class="status-badge" id="selected-convoy-status" role="status"></span> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: A convoy is a set of AI tasks working together on one goal." data-tooltip="A convoy is a set of AI tasks working together on one goal.">ℹ️</span> </div> <p class="convoy-status-explanation" id="convoy-status-explanation" role="status" aria-live="polite"></p> <div class="convoy-detail-header__meta" id="selected-convoy-meta"> <!-- Populated by JS: branch, timestamps, duration, tokens, cost --> </div> </section> <!-- Tasks Section --> <section class="chart-card" id="tasks-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Tasks</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Individual units of work in this convoy." data-tooltip="Individual units of work in this convoy.">ℹ️</span> <p class="chart-card__desc" id="tasks-section-desc">Task breakdown for the selected convoy</p> </div> <div class="chart-card__body" id="tasks-section-body"> <div id="task-summary-cards" class="task-summary-cards"></div> <div id="phase-breakdown" class="phase-breakdown"></div> <div id="task-table-wrap" class="task-table-wrap"></div> </div> </section> <!-- Quality Section --> <section class="chart-card" id="quality-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Quality / Review</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Code review results and dispute resolution." data-tooltip="Code review results and dispute resolution.">ℹ️</span> <p class="chart-card__desc">Code review results and quality gate outcomes for the selected convoy</p> </div> <div class="chart-card__body"> <div id="quality-cards" class="task-summary-cards"></div> <div id="quality-review-table"></div> </div> </section> <!-- Reliability Section --> <section class="chart-card" id="reliability-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Reliability</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Errors, retry attempts, and safety mechanisms." data-tooltip="Errors, retry attempts, and safety mechanisms.">ℹ️</span> <p class="chart-card__desc">Retry queue and error overview for the selected convoy</p> </div> <div class="chart-card__body"> <div id="reliability-dlq-card"></div> <div id="reliability-dlq-table"></div> <div style="margin-top:24px"> <h3 style="font-size:1rem;font-weight:600;color:var(--text-secondary);margin:0 0 12px">Error Overview</h3> <div id="reliability-error-overview"></div> </div> </div> </section> <!-- Drift Section --> <section class="chart-card" id="drift-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Drift</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: How far the actual work deviated from the original plan." data-tooltip="How far the actual work deviated from the original plan.">ℹ️</span> <p class="chart-card__desc">Plan adherence and deviation metrics for the selected convoy</p> </div> <div class="chart-card__body"> <div id="drift-cards" class="task-summary-cards"></div> <div id="drift-secret-banner" style="display:none"></div> </div> </section> <!-- Outputs Section --> <section class="chart-card" id="outputs-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Outputs & Artifacts</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Files, data, and summaries produced by this convoy." data-tooltip="Files, data, and summaries produced by this convoy.">ℹ️</span> <p class="chart-card__desc">Files, summaries, and structured data produced by tasks in this convoy</p> </div> <div class="chart-card__body"> <div id="outputs-cards" class="task-summary-cards"></div> <div id="artifact-table-wrap"></div> </div> </section> <!-- Event Timeline Section --> <section class="chart-card" id="event-timeline-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Event Timeline</h2> <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.">ℹ️</span> <p class="chart-card__desc">Convoy events in reverse chronological order</p> </div> <div class="chart-card__body"> <div id="event-timeline-filters" class="timeline-filters"></div> <div id="event-timeline-list"></div> <div id="event-timeline-load-more" style="display:none;text-align:center;padding:16px"> <button class="dash-btn dash-btn--ghost" id="event-timeline-more-btn" type="button">Load more</button> </div> </div> </section> <!-- Filter Bar --> <div class="filter-bar" id="filter-bar"> <div class="filter-group"> <label class="filter-label" for="filter-date-from">From</label> <input class="filter-input" type="date" id="filter-date-from"> </div> <div class="filter-group"> <label class="filter-label" for="filter-date-to">To</label> <input class="filter-input" type="date" id="filter-date-to"> </div> <div class="filter-group"> <label class="filter-label" for="filter-agent">Agent</label> <select class="filter-select" id="filter-agent"> <option value="">All agents</option> </select> </div> <div class="filter-group"> <label class="filter-label" for="filter-outcome">Outcome</label> <select class="filter-select" id="filter-outcome"> <option value="">All outcomes</option> <option value="success">Success</option> <option value="partial">Partial</option> <option value="failed">Failed</option> </select> </div> <div class="filter-group"> <label class="filter-label" for="filter-convoy">Convoy</label> <select class="filter-select" id="filter-convoy"> <option value="">All convoys</option> </select> </div> <div class="filter-group"> <label class="filter-label" for="filter-pipeline">Pipeline</label> <select class="filter-select" id="filter-pipeline"> <option value="">All</option> </select> </div> <button class="dash-btn dash-btn--ghost filter-reset" id="filter-reset" type="button">Reset</button> </div> <!-- Convoy Status Section --> <section class="chart-card convoy-status" id="convoy-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Convoy Status</h2> <p class="chart-card__desc" id="convoy-desc">Select a convoy to view details</p> </div> <div class="chart-card__body" id="convoy-body"></div> </section> <!-- Convoy Pipeline (Chaining) Section --> <section class="chart-card" id="convoy-pipeline-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Convoy Pipeline</h2> <p class="chart-card__desc" id="convoy-pipeline-desc">Pipeline convoy chain progress</p> </div> <div class="chart-card__body" id="convoy-pipeline-body"></div> </section> <!-- KPI Row --> <section class="kpi-row" id="kpi-row" data-nav-section> <div class="kpi-card" id="kpi-sessions"> <span class="kpi-card__label">Total Sessions</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-success"> <span class="kpi-card__label">Success Rate</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-delegations"> <span class="kpi-card__label">Total Delegations</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-duration"> <span class="kpi-card__label">Avg Duration</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-retries"> <span class="kpi-card__label">Total Retries</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-lessons"> <span class="kpi-card__label">Lessons Added</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> </section> <!-- Pipeline View (Steroids-inspired) --> <section class="chart-card" id="pipeline-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Task Pipeline</h2> <p class="chart-card__desc">Delegation flow across execution phases</p> </div> <div class="chart-card__body" id="pipeline-view"> <div class="loading-skeleton"></div> </div> </section> <!-- Charts Row 1 --> <div class="charts-row" id="agent-section" data-nav-section> <section class="chart-card"> <div class="chart-card__header"> <h2 class="chart-card__title">Sessions by Agent</h2> <p class="chart-card__desc">Stacked by outcome</p> </div> <div class="chart-card__body" id="agent-chart"> <div class="loading-skeleton"></div> </div> </section> <section class="chart-card" id="tier-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Tier Distribution</h2> <p class="chart-card__desc">Delegation model tiers</p> </div> <div class="chart-card__body" id="tier-chart"> <div class="loading-skeleton"></div> </div> </section> </div> <!-- Charts Row: Delegation Insights --> <div class="charts-row" id="delegation-section" data-nav-section> <section class="chart-card"> <div class="chart-card__header"> <h2 class="chart-card__title">Delegation Mechanism</h2> <p class="chart-card__desc">Sub-agent vs background split</p> </div> <div class="chart-card__body" id="mechanism-chart"> <div class="loading-skeleton"></div> </div> </section> <section class="chart-card"> <div class="chart-card__header"> <h2 class="chart-card__title">Delegation Outcomes</h2> <p class="chart-card__desc">Success rate by delegation</p> </div> <div class="chart-card__body" id="delegation-outcome-chart"> <div class="loading-skeleton"></div> </div> </section> </div> <!-- Charts Row 2 --> <div class="charts-row" id="timeline-section" data-nav-section> <section class="chart-card"> <div class="chart-card__header"> <h2 class="chart-card__title">Timeline</h2> <p class="chart-card__desc">Sessions and delegations over time</p> </div> <div class="chart-card__body" id="timeline-chart"> <div class="loading-skeleton"></div> </div> </section> <section class="chart-card" id="model-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Model Usage</h2> <p class="chart-card__desc">Sessions by model</p> </div> <div class="chart-card__body" id="model-chart"> <div class="loading-skeleton"></div> </div> </section> </div> <!-- Execution Log (Duvo-inspired) --> <section class="chart-card" id="execution-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Execution Log</h2> <p class="chart-card__desc">Recent agent activity, step by step</p> </div> <div class="chart-card__body" id="execution-log"> <div class="loading-skeleton"></div> </div> </section> <!-- Panel Results --> <section class="chart-card" id="panel-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Panel Reviews</h2> <p class="chart-card__desc">Quality gate verdicts and fix items</p> </div> <div class="chart-card__body" id="panel-chart"> <div class="loading-skeleton"></div> </div> </section> <!-- Fast Reviews --> <section class="chart-card" id="reviews-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Fast Reviews</h2> <p class="chart-card__desc">Single-reviewer quality gate results</p> </div> <div class="chart-card__body chart-card__body--table" id="reviews-table"> <div class="loading-skeleton"></div> </div> </section> <!-- Sessions Table --> <section class="chart-card" id="sessions-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Recent Sessions</h2> <p class="chart-card__desc">Last 15 sessions by timestamp</p> </div> <div class="chart-card__body chart-card__body--table" id="sessions-table"> <div class="loading-skeleton"></div> </div> </section> </main> </div> </body></html> <script>(function(){const base = "/";
|
|
7
|
+
</button> </div> </div> </header> <div class="dash-layout"> <!-- Sidebar Navigation --> <nav class="dash-sidebar" id="dash-sidebar"> <ul class="dash-sidebar__list"> <li><a class="dash-sidebar__link dash-sidebar__link--active" href="#overall-section" data-section="overall-section" aria-label="Overview section">Overview</a></li> <li><a class="dash-sidebar__link" href="#tasks-section" data-section="tasks-section" aria-label="Tasks section">Tasks</a></li> <li><a class="dash-sidebar__link" href="#quality-section" data-section="quality-section" aria-label="Quality section">Quality</a></li> <li><a class="dash-sidebar__link" href="#reliability-section" data-section="reliability-section" aria-label="Reliability section">Reliability</a></li> <li><a class="dash-sidebar__link" href="#drift-section" data-section="drift-section" aria-label="Drift section">Drift</a></li> <li><a class="dash-sidebar__link" href="#outputs-section" data-section="outputs-section" aria-label="Outputs section">Outputs</a></li> <li><a class="dash-sidebar__link" href="#event-timeline-section" data-section="event-timeline-section" aria-label="Event Log section">Event Log</a></li> <li><a class="dash-sidebar__link" href="#convoy-section" data-section="convoy-section" aria-label="Convoy section">Convoy</a></li> </ul> </nav> <main class="dash-main"> <!-- Overall Stats Section --> <section class="overall-stats" id="overall-section" data-nav-section> <div class="overall-stats__header"> <h2 class="overall-stats__title">Overall Stats</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: How all runs behave across your project." data-tooltip="How all runs behave across your project."><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"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span> </div> <div class="overall-stats__grid"> <div class="overall-kpi" id="overall-total-runs"> <span class="overall-kpi__label">Total Runs <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Number of convoy runs executed" data-tooltip="Number of convoy runs executed"><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"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span></span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-running"> <span class="overall-kpi__label">Running Now</span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-success-rate"> <span class="overall-kpi__label">Success Rate</span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-avg-duration"> <span class="overall-kpi__label">Avg Duration</span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-total-tokens"> <span class="overall-kpi__label">Total Tokens</span> <span class="overall-kpi__value">—</span> </div> <div class="overall-kpi" id="overall-total-cost"> <span class="overall-kpi__label">Total Cost</span> <span class="overall-kpi__value">—</span> </div> </div> </section> <!-- Selected Convoy Header --> <section class="convoy-detail-header" id="convoy-detail-header"> <div class="convoy-detail-header__top"> <h2 class="convoy-detail-header__name" id="selected-convoy-name">No convoy selected</h2> <span class="status-badge" id="selected-convoy-status" role="status"></span> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: A convoy is a set of AI tasks working together on one goal." data-tooltip="A convoy is a set of AI tasks working together on one goal."><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"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span> </div> <p class="convoy-status-explanation" id="convoy-status-explanation" role="status" aria-live="polite"></p> <div class="convoy-detail-header__meta" id="selected-convoy-meta"> <!-- Populated by JS: branch, timestamps, duration, tokens, cost --> </div> </section> <!-- Tasks Section --> <section class="chart-card" id="tasks-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Tasks</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Individual units of work in this convoy." data-tooltip="Individual units of work in this convoy."><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"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span> <p class="chart-card__desc" id="tasks-section-desc">Task breakdown for the selected convoy</p> </div> <div class="chart-card__body" id="tasks-section-body"> <div id="task-summary-cards" class="task-summary-cards"></div> <div id="phase-breakdown" class="phase-breakdown"></div> <div id="task-table-wrap" class="task-table-wrap"></div> </div> </section> <!-- Quality Section --> <section class="chart-card" id="quality-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Quality / Review</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Code review results and dispute resolution." data-tooltip="Code review results and dispute resolution."><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"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span> <p class="chart-card__desc">Code review results and quality gate outcomes for the selected convoy</p> </div> <div class="chart-card__body"> <div id="quality-cards" class="task-summary-cards"></div> <div id="quality-review-table"></div> </div> </section> <!-- Reliability Section --> <section class="chart-card" id="reliability-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Reliability</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Errors, retry attempts, and safety mechanisms." data-tooltip="Errors, retry attempts, and safety mechanisms."><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"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span> <p class="chart-card__desc">Retry queue and error overview for the selected convoy</p> </div> <div class="chart-card__body"> <div id="reliability-dlq-card"></div> <div id="reliability-dlq-table"></div> <div style="margin-top:24px"> <h3 style="font-size:1rem;font-weight:600;color:var(--text-secondary);margin:0 0 12px">Error Overview</h3> <div id="reliability-error-overview"></div> </div> </div> </section> <!-- Drift Section --> <section class="chart-card" id="drift-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Drift</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: How far the actual work deviated from the original plan." data-tooltip="How far the actual work deviated from the original plan."><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"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span> <p class="chart-card__desc">Plan adherence and deviation metrics for the selected convoy</p> </div> <div class="chart-card__body"> <div id="drift-cards" class="task-summary-cards"></div> <div id="drift-secret-banner" style="display:none"></div> </div> </section> <!-- Outputs Section --> <section class="chart-card" id="outputs-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Outputs & Artifacts</h2> <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Files, data, and summaries produced by this convoy." data-tooltip="Files, data, and summaries produced by this convoy."><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"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span> <p class="chart-card__desc">Files, summaries, and structured data produced by tasks in this convoy</p> </div> <div class="chart-card__body"> <div id="outputs-cards" class="task-summary-cards"></div> <div id="artifact-table-wrap"></div> </div> </section> <!-- Event Timeline Section --> <section class="chart-card" id="event-timeline-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Event Timeline</h2> <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"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg></span> <p class="chart-card__desc">Convoy events in reverse chronological order</p> </div> <div class="chart-card__body"> <div id="event-timeline-filters" class="timeline-filters"></div> <div id="event-timeline-list"></div> <div id="event-timeline-load-more" style="display:none;text-align:center;padding:16px"> <button class="dash-btn dash-btn--ghost" id="event-timeline-more-btn" type="button">Load more</button> </div> </div> </section> <!-- Filter Bar --> <div class="filter-bar" id="filter-bar"> <div class="filter-group"> <label class="filter-label" for="filter-date-from">From</label> <input class="filter-input" type="date" id="filter-date-from"> </div> <div class="filter-group"> <label class="filter-label" for="filter-date-to">To</label> <input class="filter-input" type="date" id="filter-date-to"> </div> <div class="filter-group"> <label class="filter-label" for="filter-agent">Agent</label> <select class="filter-select" id="filter-agent"> <option value="">All agents</option> </select> </div> <div class="filter-group"> <label class="filter-label" for="filter-outcome">Outcome</label> <select class="filter-select" id="filter-outcome"> <option value="">All outcomes</option> <option value="success">Success</option> <option value="partial">Partial</option> <option value="failed">Failed</option> </select> </div> <div class="filter-group"> <label class="filter-label" for="filter-convoy">Convoy</label> <select class="filter-select" id="filter-convoy"> <option value="">All convoys</option> </select> </div> <div class="filter-group"> <label class="filter-label" for="filter-pipeline">Pipeline</label> <select class="filter-select" id="filter-pipeline"> <option value="">All</option> </select> </div> <button class="dash-btn dash-btn--ghost filter-reset" id="filter-reset" type="button">Reset</button> </div> <!-- Convoy Status Section --> <section class="chart-card convoy-status" id="convoy-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Convoy Status</h2> <p class="chart-card__desc" id="convoy-desc">Select a convoy to view details</p> </div> <div class="chart-card__body" id="convoy-body"></div> </section> <!-- Convoy Pipeline (Chaining) Section --> <section class="chart-card" id="convoy-pipeline-section" data-nav-section style="display:none"> <div class="chart-card__header"> <h2 class="chart-card__title">Convoy Pipeline</h2> <p class="chart-card__desc" id="convoy-pipeline-desc">Pipeline convoy chain progress</p> </div> <div class="chart-card__body" id="convoy-pipeline-body"></div> </section> <!-- KPI Row --> <section class="kpi-row" id="kpi-row" data-nav-section> <div class="kpi-card" id="kpi-sessions"> <span class="kpi-card__label">Total Sessions</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-success"> <span class="kpi-card__label">Success Rate</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-delegations"> <span class="kpi-card__label">Total Delegations</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-duration"> <span class="kpi-card__label">Avg Duration</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-retries"> <span class="kpi-card__label">Total Retries</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> <div class="kpi-card" id="kpi-lessons"> <span class="kpi-card__label">Lessons Added</span> <span class="kpi-card__value">—</span> <span class="kpi-card__sub"></span> </div> </section> <!-- Pipeline View (Steroids-inspired) --> <section class="chart-card" id="pipeline-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Task Pipeline</h2> <p class="chart-card__desc">Delegation flow across execution phases</p> </div> <div class="chart-card__body" id="pipeline-view"> <div class="loading-skeleton"></div> </div> </section> <!-- Charts Row 1 --> <div class="charts-row" id="agent-section" data-nav-section> <section class="chart-card"> <div class="chart-card__header"> <h2 class="chart-card__title">Sessions by Agent</h2> <p class="chart-card__desc">Stacked by outcome</p> </div> <div class="chart-card__body" id="agent-chart"> <div class="loading-skeleton"></div> </div> </section> <section class="chart-card" id="tier-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Tier Distribution</h2> <p class="chart-card__desc">Delegation model tiers</p> </div> <div class="chart-card__body" id="tier-chart"> <div class="loading-skeleton"></div> </div> </section> </div> <!-- Charts Row: Delegation Insights --> <div class="charts-row" id="delegation-section" data-nav-section> <section class="chart-card"> <div class="chart-card__header"> <h2 class="chart-card__title">Delegation Mechanism</h2> <p class="chart-card__desc">Sub-agent vs background split</p> </div> <div class="chart-card__body" id="mechanism-chart"> <div class="loading-skeleton"></div> </div> </section> <section class="chart-card"> <div class="chart-card__header"> <h2 class="chart-card__title">Delegation Outcomes</h2> <p class="chart-card__desc">Success rate by delegation</p> </div> <div class="chart-card__body" id="delegation-outcome-chart"> <div class="loading-skeleton"></div> </div> </section> </div> <!-- Charts Row 2 --> <div class="charts-row" id="timeline-section" data-nav-section> <section class="chart-card"> <div class="chart-card__header"> <h2 class="chart-card__title">Timeline</h2> <p class="chart-card__desc">Sessions and delegations over time</p> </div> <div class="chart-card__body" id="timeline-chart"> <div class="loading-skeleton"></div> </div> </section> <section class="chart-card" id="model-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Model Usage</h2> <p class="chart-card__desc">Sessions by model</p> </div> <div class="chart-card__body" id="model-chart"> <div class="loading-skeleton"></div> </div> </section> </div> <!-- Execution Log (Duvo-inspired) --> <section class="chart-card" id="execution-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Execution Log</h2> <p class="chart-card__desc">Recent agent activity, step by step</p> </div> <div class="chart-card__body" id="execution-log"> <div class="loading-skeleton"></div> </div> </section> <!-- Panel Results --> <section class="chart-card" id="panel-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Panel Reviews</h2> <p class="chart-card__desc">Quality gate verdicts and fix items</p> </div> <div class="chart-card__body" id="panel-chart"> <div class="loading-skeleton"></div> </div> </section> <!-- Fast Reviews --> <section class="chart-card" id="reviews-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Fast Reviews</h2> <p class="chart-card__desc">Single-reviewer quality gate results</p> </div> <div class="chart-card__body chart-card__body--table" id="reviews-table"> <div class="loading-skeleton"></div> </div> </section> <!-- Sessions Table --> <section class="chart-card" id="sessions-section" data-nav-section> <div class="chart-card__header"> <h2 class="chart-card__title">Recent Sessions</h2> <p class="chart-card__desc">Last 15 sessions by timestamp</p> </div> <div class="chart-card__body chart-card__body--table" id="sessions-table"> <div class="loading-skeleton"></div> </div> </section> </main> </div> </body></html> <script>(function(){const base = "/";
|
|
8
8
|
|
|
9
9
|
// ── Data Loading ──────────────────────────────────────────
|
|
10
10
|
|
|
@@ -23,8 +23,21 @@ Export
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
async function loadJson(path) {
|
|
27
|
+
try {
|
|
28
|
+
const res = await fetch(path);
|
|
29
|
+
if (!res.ok) return [];
|
|
30
|
+
return await res.json();
|
|
31
|
+
} catch {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
// ── Helpers ───────────────────────────────────────────────
|
|
27
37
|
|
|
38
|
+
// ── Info Icon SVG ─────────────────────────────────────
|
|
39
|
+
const INFO_ICON = '<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>';
|
|
40
|
+
|
|
28
41
|
const TIER_COLORS = {
|
|
29
42
|
premium: '#f59e0b',
|
|
30
43
|
standard: '#a78bfa',
|
|
@@ -1608,7 +1621,7 @@ Export
|
|
|
1608
1621
|
el.innerHTML = cards.map(card =>
|
|
1609
1622
|
'<div class="task-summary-card task-summary-card--' + card.mod + '">' +
|
|
1610
1623
|
'<span class="task-summary-card__label">' + escapeHtml(card.label) +
|
|
1611
|
-
' <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: ' + escapeHtml(card.tooltip) + '" data-tooltip="' + escapeHtml(card.tooltip) + '"
|
|
1624
|
+
' <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: ' + escapeHtml(card.tooltip) + '" data-tooltip="' + escapeHtml(card.tooltip) + '">' + INFO_ICON + '</span>' +
|
|
1612
1625
|
'</span>' +
|
|
1613
1626
|
'<span class="task-summary-card__value">' + card.value + '</span>' +
|
|
1614
1627
|
'</div>'
|
|
@@ -1751,7 +1764,7 @@ Export
|
|
|
1751
1764
|
cardsEl.innerHTML = qCards.map(function(card) {
|
|
1752
1765
|
return '<div class="task-summary-card task-summary-card--' + card.mod + '">' +
|
|
1753
1766
|
'<span class="task-summary-card__label">' + escapeHtml(card.label) +
|
|
1754
|
-
' <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: ' + escapeHtml(card.tooltip) + '" data-tooltip="' + escapeHtml(card.tooltip) + '"
|
|
1767
|
+
' <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: ' + escapeHtml(card.tooltip) + '" data-tooltip="' + escapeHtml(card.tooltip) + '">' + INFO_ICON + '</span>' +
|
|
1755
1768
|
'</span>' +
|
|
1756
1769
|
'<span class="task-summary-card__value">' + card.value + '</span>' +
|
|
1757
1770
|
'</div>';
|
|
@@ -1809,7 +1822,7 @@ Export
|
|
|
1809
1822
|
if (dlqCardEl) {
|
|
1810
1823
|
dlqCardEl.innerHTML =
|
|
1811
1824
|
'<div class="task-summary-card task-summary-card--' + (dlqCount > 0 ? 'errors' : 'done') + '">' +
|
|
1812
|
-
'<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)."
|
|
1825
|
+
'<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>' +
|
|
1813
1826
|
'<span class="task-summary-card__value">' + dlqCount + '</span>' +
|
|
1814
1827
|
'</div>';
|
|
1815
1828
|
}
|
|
@@ -1889,7 +1902,7 @@ Export
|
|
|
1889
1902
|
cardsEl.innerHTML = driftCards.map(function(card) {
|
|
1890
1903
|
return '<div class="task-summary-card task-summary-card--' + card.mod + '">' +
|
|
1891
1904
|
'<span class="task-summary-card__label">' + escapeHtml(String(card.label)) +
|
|
1892
|
-
' <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: ' + escapeHtml(card.tooltip) + '" data-tooltip="' + escapeHtml(card.tooltip) + '"
|
|
1905
|
+
' <span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: ' + escapeHtml(card.tooltip) + '" data-tooltip="' + escapeHtml(card.tooltip) + '">' + INFO_ICON + '</span>' +
|
|
1893
1906
|
'</span>' +
|
|
1894
1907
|
'<span class="task-summary-card__value">' + card.value + '</span>' +
|
|
1895
1908
|
'</div>';
|
|
@@ -1930,7 +1943,7 @@ Export
|
|
|
1930
1943
|
cardsEl.innerHTML =
|
|
1931
1944
|
'<div class="task-summary-card task-summary-card--done">' +
|
|
1932
1945
|
'<span class="task-summary-card__label">Outputs Produced ' +
|
|
1933
|
-
'<span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Files, data, and summaries produced by this convoy." data-tooltip="Files, data, and summaries produced by this convoy."
|
|
1946
|
+
'<span class="tooltip-trigger" tabindex="0" role="button" aria-label="Info: Files, data, and summaries produced by this convoy." data-tooltip="Files, data, and summaries produced by this convoy.">' + INFO_ICON + '</span>' +
|
|
1934
1947
|
'</span>' +
|
|
1935
1948
|
'<span class="task-summary-card__value">' + artifactCount + '</span>' +
|
|
1936
1949
|
'</div>';
|
|
@@ -2097,6 +2110,7 @@ Export
|
|
|
2097
2110
|
async function main() {
|
|
2098
2111
|
const events = await loadNdjson(base + 'data/events.ndjson');
|
|
2099
2112
|
const pipelines = await loadNdjson(base + 'data/pipelines.ndjson');
|
|
2113
|
+
const convoys = window.__DASHBOARD_DATA__?.convoyList ?? [];
|
|
2100
2114
|
|
|
2101
2115
|
const sessions = events.filter((e) => e.type === 'session');
|
|
2102
2116
|
const delegations = events.filter((e) => e.type === 'delegation');
|
|
@@ -2177,7 +2191,7 @@ Export
|
|
|
2177
2191
|
if (refreshInterval) return;
|
|
2178
2192
|
refreshInterval = setInterval(async () => {
|
|
2179
2193
|
const freshEvents = await loadNdjson(base + 'data/events.ndjson');
|
|
2180
|
-
const freshConvoys = await
|
|
2194
|
+
const freshConvoys = await loadJson(base + 'data/convoy-list.json');
|
|
2181
2195
|
const freshPipelines = await loadNdjson(base + 'data/pipelines.ndjson');
|
|
2182
2196
|
rawSessions = freshEvents.filter((e) => e.type === 'session');
|
|
2183
2197
|
rawDelegations = freshEvents.filter((e) => e.type === 'delegation');
|
|
@@ -2233,17 +2247,26 @@ Export
|
|
|
2233
2247
|
|
|
2234
2248
|
sections.forEach((s) => observer.observe(s));
|
|
2235
2249
|
|
|
2250
|
+
// Convoy-detail sections that start hidden and need a convoy selected first
|
|
2251
|
+
const CONVOY_DETAIL_SECTIONS = ['tasks-section', 'quality-section', 'reliability-section', 'drift-section', 'outputs-section', 'event-timeline-section'];
|
|
2252
|
+
|
|
2236
2253
|
// Smooth scroll on click
|
|
2237
2254
|
links.forEach((link) => {
|
|
2238
|
-
link.addEventListener('click', (e) => {
|
|
2255
|
+
link.addEventListener('click', async (e) => {
|
|
2239
2256
|
e.preventDefault();
|
|
2240
2257
|
const sectionId = link.dataset.section;
|
|
2241
2258
|
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
const
|
|
2245
|
-
if (
|
|
2246
|
-
|
|
2259
|
+
if (CONVOY_DETAIL_SECTIONS.includes(sectionId)) {
|
|
2260
|
+
// Auto-select and load convoy detail if none selected yet
|
|
2261
|
+
const convoySelectEl = document.getElementById('convoy-select');
|
|
2262
|
+
if (convoySelectEl && !convoySelectEl.value && convoySelectEl.options.length > 1) {
|
|
2263
|
+
convoySelectEl.value = convoySelectEl.options[1].value;
|
|
2264
|
+
await loadConvoyDetail(convoySelectEl.value);
|
|
2265
|
+
}
|
|
2266
|
+
} else if (sectionId === 'convoy-section') {
|
|
2267
|
+
const convoyFilterEl = document.getElementById('filter-convoy');
|
|
2268
|
+
if (convoyFilterEl && !convoyFilterEl.value && convoyFilterEl.options.length > 1) {
|
|
2269
|
+
convoyFilterEl.value = convoyFilterEl.options[1].value;
|
|
2247
2270
|
applyFilters();
|
|
2248
2271
|
}
|
|
2249
2272
|
} else if (sectionId === 'convoy-pipeline-section') {
|
|
@@ -2255,7 +2278,7 @@ Export
|
|
|
2255
2278
|
}
|
|
2256
2279
|
|
|
2257
2280
|
const target = document.getElementById(sectionId);
|
|
2258
|
-
if (target
|
|
2281
|
+
if (target) {
|
|
2259
2282
|
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
2260
2283
|
}
|
|
2261
2284
|
});
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
"hash": "
|
|
2
|
+
"hash": "3120eea2",
|
|
3
3
|
"configHash": "30f8ea04",
|
|
4
|
-
"lockfileHash": "
|
|
5
|
-
"browserHash": "
|
|
4
|
+
"lockfileHash": "29db8675",
|
|
5
|
+
"browserHash": "392b96fc",
|
|
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": "c3358443",
|
|
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": "f6721631",
|
|
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": "337d00e2",
|
|
23
23
|
"needsInterop": true
|
|
24
24
|
}
|
|
25
25
|
},
|
|
@@ -1,20 +1,65 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
|
-
"id": "demo-
|
|
4
|
-
"name": "
|
|
3
|
+
"id": "demo-deploy-ci",
|
|
4
|
+
"name": "CI/CD Pipeline Setup",
|
|
5
5
|
"status": "running",
|
|
6
|
-
"created_at": "2026-
|
|
6
|
+
"created_at": "2026-03-11T08:00:00.000Z",
|
|
7
7
|
"finished_at": null,
|
|
8
8
|
"total_tokens": null,
|
|
9
9
|
"total_cost_usd": null
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
|
-
"id": "demo-
|
|
13
|
-
"name": "
|
|
12
|
+
"id": "demo-docs-update",
|
|
13
|
+
"name": "Documentation Refresh",
|
|
14
14
|
"status": "done",
|
|
15
|
-
"created_at": "2026-
|
|
16
|
-
"finished_at": "2026-
|
|
17
|
-
"total_tokens":
|
|
18
|
-
"total_cost_usd":
|
|
15
|
+
"created_at": "2026-02-28T15:00:00.000Z",
|
|
16
|
+
"finished_at": "2026-02-28T15:22:00.000Z",
|
|
17
|
+
"total_tokens": 14800,
|
|
18
|
+
"total_cost_usd": 1.48
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "demo-data-pipeline",
|
|
22
|
+
"name": "Analytics ETL Pipeline",
|
|
23
|
+
"status": "done",
|
|
24
|
+
"created_at": "2026-02-22T13:00:00.000Z",
|
|
25
|
+
"finished_at": "2026-02-22T13:38:00.000Z",
|
|
26
|
+
"total_tokens": 28900,
|
|
27
|
+
"total_cost_usd": 2.89
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "demo-perf-opt",
|
|
31
|
+
"name": "Frontend Performance Boost",
|
|
32
|
+
"status": "done",
|
|
33
|
+
"created_at": "2026-02-17T10:00:00.000Z",
|
|
34
|
+
"finished_at": "2026-02-17T11:02:00.000Z",
|
|
35
|
+
"total_tokens": 37200,
|
|
36
|
+
"total_cost_usd": 3.72
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "demo-api-v2",
|
|
40
|
+
"name": "REST API v2 Migration",
|
|
41
|
+
"status": "gate_failed",
|
|
42
|
+
"created_at": "2026-02-12T16:00:00.000Z",
|
|
43
|
+
"finished_at": "2026-02-12T16:28:00.000Z",
|
|
44
|
+
"total_tokens": 24600,
|
|
45
|
+
"total_cost_usd": 2.46
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "demo-dashboard-ui",
|
|
49
|
+
"name": "Observability Dashboard UI",
|
|
50
|
+
"status": "done",
|
|
51
|
+
"created_at": "2026-02-07T14:00:00.000Z",
|
|
52
|
+
"finished_at": "2026-02-07T15:38:00.000Z",
|
|
53
|
+
"total_tokens": 78400,
|
|
54
|
+
"total_cost_usd": 7.84
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "demo-auth-revamp",
|
|
58
|
+
"name": "Auth System Revamp",
|
|
59
|
+
"status": "done",
|
|
60
|
+
"created_at": "2026-02-03T09:00:00.000Z",
|
|
61
|
+
"finished_at": "2026-02-03T09:47:00.000Z",
|
|
62
|
+
"total_tokens": 42850,
|
|
63
|
+
"total_cost_usd": 4.28
|
|
19
64
|
}
|
|
20
65
|
]
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
{
|
|
2
|
+
"convoy": {
|
|
3
|
+
"id": "demo-api-v2",
|
|
4
|
+
"name": "REST API v2 Migration",
|
|
5
|
+
"status": "gate_failed",
|
|
6
|
+
"created_at": "2026-02-12T16:00:00.000Z",
|
|
7
|
+
"finished_at": "2026-02-12T16:28:00.000Z",
|
|
8
|
+
"branch": "feat/api-v2",
|
|
9
|
+
"total_tokens": 24600,
|
|
10
|
+
"total_cost_usd": 2.46
|
|
11
|
+
},
|
|
12
|
+
"taskSummary": {
|
|
13
|
+
"total": 3,
|
|
14
|
+
"done": 2,
|
|
15
|
+
"running": 0,
|
|
16
|
+
"failed": 0,
|
|
17
|
+
"review_blocked": 0,
|
|
18
|
+
"disputed": 0,
|
|
19
|
+
"reviewed": 1,
|
|
20
|
+
"panel_reviewed": 1,
|
|
21
|
+
"tasks_with_drift": 0,
|
|
22
|
+
"max_drift_score": null,
|
|
23
|
+
"drift_retried": 0
|
|
24
|
+
},
|
|
25
|
+
"quality": {
|
|
26
|
+
"reviewed_tasks": 1,
|
|
27
|
+
"review_blocked_tasks": 0,
|
|
28
|
+
"disputed_tasks": 0,
|
|
29
|
+
"panel_reviews": 1
|
|
30
|
+
},
|
|
31
|
+
"drift": {
|
|
32
|
+
"tasks_with_drift": 0,
|
|
33
|
+
"max_drift_score": null,
|
|
34
|
+
"drift_retried_tasks": 0
|
|
35
|
+
},
|
|
36
|
+
"dlq_count": 1,
|
|
37
|
+
"dlq_entries": [
|
|
38
|
+
{
|
|
39
|
+
"id": "dlq-api-1",
|
|
40
|
+
"task_id": "api-t3",
|
|
41
|
+
"agent": "Security Expert",
|
|
42
|
+
"failure_type": "gate_failed",
|
|
43
|
+
"attempts": 1,
|
|
44
|
+
"resolved": 0
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"artifact_count": 3,
|
|
48
|
+
"artifacts": [
|
|
49
|
+
{
|
|
50
|
+
"id": "artifact-demo-api-v2-docs-api-v2-contract-json",
|
|
51
|
+
"name": "docs/api-v2-contract.json",
|
|
52
|
+
"type": "json",
|
|
53
|
+
"task_id": "api-t1",
|
|
54
|
+
"created_at": "2026-03-12T22:26:01.388Z"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "artifact-demo-api-v2-reports-security-gate-failure-md",
|
|
58
|
+
"name": "reports/security-gate-failure.md",
|
|
59
|
+
"type": "summary",
|
|
60
|
+
"task_id": "api-t3",
|
|
61
|
+
"created_at": "2026-03-12T22:26:01.388Z"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "artifact-demo-api-v2-src-api-rate-limiter-ts",
|
|
65
|
+
"name": "src/api/rate-limiter.ts",
|
|
66
|
+
"type": "file",
|
|
67
|
+
"task_id": "api-t2",
|
|
68
|
+
"created_at": "2026-03-12T22:26:01.388Z"
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
"has_more_events": false,
|
|
72
|
+
"events": [
|
|
73
|
+
{
|
|
74
|
+
"type": "task_gate_failed",
|
|
75
|
+
"task_id": "api-t3",
|
|
76
|
+
"data": {
|
|
77
|
+
"reason": "SQL injection risk"
|
|
78
|
+
},
|
|
79
|
+
"created_at": "2026-02-12T16:27:00.000Z"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"type": "task_started",
|
|
83
|
+
"task_id": "api-t3",
|
|
84
|
+
"data": null,
|
|
85
|
+
"created_at": "2026-02-12T16:24:00.000Z"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"type": "task_done",
|
|
89
|
+
"task_id": "api-t2",
|
|
90
|
+
"data": null,
|
|
91
|
+
"created_at": "2026-02-12T16:23:00.000Z"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"type": "task_started",
|
|
95
|
+
"task_id": "api-t2",
|
|
96
|
+
"data": null,
|
|
97
|
+
"created_at": "2026-02-12T16:12:00.000Z"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"type": "task_done",
|
|
101
|
+
"task_id": "api-t1",
|
|
102
|
+
"data": null,
|
|
103
|
+
"created_at": "2026-02-12T16:11:00.000Z"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"type": "task_started",
|
|
107
|
+
"task_id": "api-t1",
|
|
108
|
+
"data": null,
|
|
109
|
+
"created_at": "2026-02-12T16:00:05.000Z"
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
"tasks": [
|
|
113
|
+
{
|
|
114
|
+
"id": "api-t1",
|
|
115
|
+
"phase": 1,
|
|
116
|
+
"agent": "API Designer",
|
|
117
|
+
"model": "claude-sonnet-4-6",
|
|
118
|
+
"status": "done",
|
|
119
|
+
"retries": 0,
|
|
120
|
+
"started_at": "2026-02-12T16:00:05.000Z",
|
|
121
|
+
"finished_at": "2026-02-12T16:11:00.000Z",
|
|
122
|
+
"total_tokens": 7200,
|
|
123
|
+
"cost_usd": 0.72,
|
|
124
|
+
"review_level": null,
|
|
125
|
+
"review_verdict": null,
|
|
126
|
+
"review_tokens": null,
|
|
127
|
+
"review_model": null,
|
|
128
|
+
"panel_attempts": 0,
|
|
129
|
+
"dispute_id": null,
|
|
130
|
+
"drift_score": null,
|
|
131
|
+
"drift_retried": 0,
|
|
132
|
+
"files": null
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "api-t2",
|
|
136
|
+
"phase": 2,
|
|
137
|
+
"agent": "Developer",
|
|
138
|
+
"model": "claude-sonnet-4-6",
|
|
139
|
+
"status": "done",
|
|
140
|
+
"retries": 2,
|
|
141
|
+
"started_at": "2026-02-12T16:12:00.000Z",
|
|
142
|
+
"finished_at": "2026-02-12T16:23:00.000Z",
|
|
143
|
+
"total_tokens": 11400,
|
|
144
|
+
"cost_usd": 1.14,
|
|
145
|
+
"review_level": null,
|
|
146
|
+
"review_verdict": null,
|
|
147
|
+
"review_tokens": null,
|
|
148
|
+
"review_model": null,
|
|
149
|
+
"panel_attempts": 0,
|
|
150
|
+
"dispute_id": null,
|
|
151
|
+
"drift_score": null,
|
|
152
|
+
"drift_retried": 0,
|
|
153
|
+
"files": null
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"id": "api-t3",
|
|
157
|
+
"phase": 3,
|
|
158
|
+
"agent": "Security Expert",
|
|
159
|
+
"model": "claude-sonnet-4-6",
|
|
160
|
+
"status": "gate_failed",
|
|
161
|
+
"retries": 0,
|
|
162
|
+
"started_at": "2026-02-12T16:24:00.000Z",
|
|
163
|
+
"finished_at": "2026-02-12T16:27:00.000Z",
|
|
164
|
+
"total_tokens": 6000,
|
|
165
|
+
"cost_usd": 0.6,
|
|
166
|
+
"review_level": "deep",
|
|
167
|
+
"review_verdict": "block",
|
|
168
|
+
"review_tokens": 2100,
|
|
169
|
+
"review_model": "claude-sonnet-4-6",
|
|
170
|
+
"panel_attempts": 1,
|
|
171
|
+
"dispute_id": null,
|
|
172
|
+
"drift_score": null,
|
|
173
|
+
"drift_retried": 0,
|
|
174
|
+
"files": null
|
|
175
|
+
}
|
|
176
|
+
]
|
|
177
|
+
}
|