@zaip-ai/cli 1.0.8 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/services/adapters.d.ts +1 -1
- package/dist/services/adapters.js +1 -1
- package/dist/services/agent-adapters.js +3 -3
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/agent-adapters.test.js +7 -1
- package/dist/services/agent-adapters.test.js.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.js +89 -7
- package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
- package/dist/services/codex-rules.d.ts +1 -1
- package/dist/services/codex-rules.d.ts.map +1 -1
- package/dist/services/codex-rules.js +7 -0
- package/dist/services/codex-rules.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +1 -0
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/logger.test.js +2 -2
- package/dist/services/runtime-template.test.js +31 -7
- package/dist/services/runtime-template.test.js.map +1 -1
- package/dist/services/template-manifest.d.ts.map +1 -1
- package/dist/services/template-manifest.js +12 -3
- package/dist/services/template-manifest.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/architecture/software-architecture.md +131 -0
- package/templates/.agents/branding/brandbook.docx +0 -0
- package/templates/.agents/branding/brandbook.md +60 -0
- package/templates/.agents/config/agents/catalog.yaml +7 -7
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +8 -8
- package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -1
- package/templates/.agents/dashboard/.tmp-run-list.json +254 -0
- package/templates/.agents/dashboard/.zaip-managed.json +457 -173
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-Z60df2r-.js → CostCalculationGuidePage-ovxurkIk.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/DashboardHelpDialog-BgVgrfhQ.js +2310 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-Coc6pA-1.js → PricingSettingsDialog-vSvvOHQp.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BomxqCBU.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-zH758vfs.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-DLn-Mz2M.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-CaKwQP43.css → TraceabilityWorkspace-DvvavDLY.css} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DKwP1stV.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-PoJA2PI1.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DFBuc_qp.js → icons-vendor-B_lDDHn1.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-B31GMG5O.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-CZQlsLV9.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-CCQOHdVI.js → react-vendor-B3TJrD4O.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-pC2_0J8x.js → traceability-7f1j5wx3.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +7 -7
- package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
- package/templates/.agents/dashboard/apps/frontend/playwright.dom.config.ts +32 -0
- package/templates/.agents/dashboard/apps/frontend/src/App.tsx +199 -140
- package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +0 -21
- package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +20 -11
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +14 -7
- package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +4 -2
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.dom.e2e.ts +56 -0
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +21 -2
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +89 -19
- package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +19 -4
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +49 -3
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +29 -10
- package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +4 -4
- package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +4 -2
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +36 -26
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +47 -6
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +59 -9
- package/templates/.agents/dashboard/apps/frontend/src/sqlite-page-export.test.ts +32 -0
- package/templates/.agents/dashboard/apps/frontend/src/sqlite-page-export.ts +21 -0
- package/templates/.agents/dashboard/apps/frontend/src/styles.css +19 -0
- package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.test.ts +32 -0
- package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.ts +36 -0
- package/templates/.agents/dashboard/apps/frontend/src/traceability-workspace.css +6 -2
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +137 -23
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +229 -35
- package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +61 -7
- package/templates/.agents/dashboard/apps/frontend/src/use-app-operations-pages.ts +3 -6
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +7 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-list-page.test.ts +163 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-list-page.ts +136 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-operations-detail-export.ts +76 -0
- package/templates/.agents/dashboard/apps/frontend/src/work-list-load-dedup.test.ts +23 -0
- package/templates/.agents/dashboard/apps/frontend/src/work-list-load-dedup.ts +27 -0
- package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +39 -15
- package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.ts +3 -4
- package/templates/.agents/dashboard/apps/frontend/vite.config.ts +4 -1
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +89 -19
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +31 -16
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.test.ts +43 -14
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.tsx +5 -5
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionPanel.tsx +60 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionTable.tsx +191 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.loading.test.ts +14 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.run-page.test.ts +18 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.tsx +18 -3
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.tsx +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +75 -44
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorLoadErrors.tsx +35 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +162 -40
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +221 -79
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableLoading.test.ts +132 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableLoading.tsx +70 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +203 -155
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +164 -125
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-copy.ts +2 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-views.ts +3 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor.css +5 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-page-range.ts +35 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/index.ts +2 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +2 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +32 -9
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.test.ts +37 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +131 -9
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +34 -17
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test.ts +0 -24
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.test.ts +225 -424
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +24 -15
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-terminal-day.test.ts +6 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/source-size-cost-server/build-cost-monitor-projection-agents.test.ts +31 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/source-size-cost-server/build-cost-summary-projection-duration.test.ts +414 -0
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/src/contracts.ts +46 -26
- package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.test.ts +54 -0
- package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.tsx +247 -0
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +31 -11
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsMainContent.tsx +39 -13
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +107 -2
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.macro-metrics.test.ts +55 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +23 -29
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +211 -184
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewTopPanel.tsx +127 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +60 -51
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageNavigation.tsx +1 -4
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +3 -0
- package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.test.tsx +43 -0
- package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.tsx +181 -0
- package/templates/.agents/dashboard/modules/operations/src/react/PeriodSummaryTable.tsx +32 -10
- package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +9 -3
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +13 -5
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +16 -6
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +14 -4
- package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.ts +1 -2
- package/templates/.agents/dashboard/modules/operations/src/react/developer-identities.test.ts +18 -0
- package/templates/.agents/dashboard/modules/operations/src/react/developer-identities.ts +30 -0
- package/templates/.agents/dashboard/modules/operations/src/react/execution-metrics.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +393 -4
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +484 -61
- package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +23 -1
- package/templates/.agents/dashboard/modules/operations/src/react/export/xlsx-runtime-e2e.test.ts +248 -0
- package/templates/.agents/dashboard/modules/operations/src/react/index.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +4 -4
- package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +6 -4
- package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +4 -3
- package/templates/.agents/dashboard/modules/operations/src/react/operations-date-filters.css +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-global-filters.test.ts +4 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +22 -12
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.css +4 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +53 -6
- package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +2 -4
- package/templates/.agents/dashboard/modules/operations/src/react/period-summary.test.ts +82 -6
- package/templates/.agents/dashboard/modules/operations/src/react/period-summary.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.ts +1 -1
- package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.test.ts +19 -7
- package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.ts +4 -1
- package/templates/.agents/dashboard/modules/operations/src/server/metric-coverage.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/server/quick-daily-operations-projection.ts +11 -5
- package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
- package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
- package/templates/.agents/dashboard/packages/contracts/src/index.ts +1 -0
- package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +533 -338
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +506 -311
- package/templates/.agents/dashboard/packages/local-runtime/gitignore.template +2 -0
- package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-dashboard.mjs +15 -7
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +44 -13
- package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +8 -3
- package/templates/.agents/dashboard/packages/local-runtime/scripts/source-size-runtime-scripts/sqlite-read-model-fixture.mjs +397 -0
- package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +472 -145
- package/templates/.agents/dashboard/packages/local-runtime/scripts/test-unix-launchers.mjs +15 -3
- package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +141 -33
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +533 -338
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +6 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +3 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +89 -16
- package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +33 -16
- package/templates/.agents/dashboard/packages/local-runtime/src/server-classification-page.test.ts +87 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.test.ts +44 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.ts +125 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +66 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-request-authority.test.ts +61 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-request-authority.ts +18 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-run-projections.test.ts +42 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +97 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +22 -5
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.ts +91 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +7 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test-fixtures.ts +36 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +230 -132
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +224 -182
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-artifact-counts.ts +28 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.test.ts +63 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.ts +109 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-aggregates.ts +497 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-fast-page-parity.test-support.ts +65 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-page.test.ts +176 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-page.ts +119 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.ts +41 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.test.ts +16 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.ts +29 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-cache.ts +355 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-persistence.ts +121 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-timing.ts +27 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.ts +16 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-projection.ts +15 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.test.ts +223 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.ts +304 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-cache.test-support.ts +23 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-first-fold-types.ts +89 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-fixture.ts +227 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider.test.ts +691 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +81 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +1655 -567
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +2168 -1268
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-cache.ts +129 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-install.test.ts +26 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-install.ts +28 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-seed.test.ts +116 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +146 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.test.mjs +165 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-refresh.mjs +140 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +255 -289
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +94 -88
- package/templates/.agents/dashboard/packages/ui/package.json +1 -1
- package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +5 -2
- package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -1
- package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-loading.spec.ts +142 -0
- package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-pagination.spec.ts +232 -0
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +743 -0
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +189 -214
- package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
- package/templates/.agents/design/.zaip-managed.json +3 -3
- package/templates/.agents/design/apps/catalog/package.json +1 -1
- package/templates/.agents/design/packages/local-runtime/package.json +1 -1
- package/templates/.agents/growth/estrategia-bootstrap-90-dias.md +169 -0
- package/templates/.agents/growth/strategy.md +27 -0
- package/templates/.agents/marketing/estrategia-marketing-zaip-90-dias.md +197 -0
- package/templates/.agents/marketing/strategy.md +29 -0
- package/templates/.agents/requirements/autonomous-assurance.md +6 -6
- package/templates/.agents/requirements/comparative-audit.md +1 -1
- package/templates/.agents/requirements/context-engine.md +1 -1
- package/templates/.agents/requirements/cost-observability.md +1 -1
- package/templates/.agents/requirements/dashboard-launch.md +1 -1
- package/templates/.agents/requirements/data-export.md +1 -1
- package/templates/.agents/requirements/design-system.md +1 -1
- package/templates/.agents/requirements/execution-engine.md +3 -3
- package/templates/.agents/requirements/kanban-dashboard.md +10 -2
- package/templates/.agents/requirements/model-orchestration.md +1 -1
- package/templates/.agents/requirements/public-distribution.md +1 -1
- package/templates/.agents/requirements/software-architecture.md +1 -1
- package/templates/.agents/requirements/strategic-improvements.md +1 -1
- package/templates/.agents/requirements/work-lifecycle.md +4 -4
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/dashboard-ui-consistency.md +14 -0
- package/templates/.agents/rules/frontend-lite.md +4 -4
- package/templates/.agents/rules/run-lifecycle-closure.md +4 -4
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +1142 -1041
- package/templates/.agents/runtime/checksums.sha256 +6 -6
- package/templates/.agents/runtime/manifest.json +1 -1
- package/templates/.agents/runtime/pnpm-lock.sha256 +1 -1
- package/templates/.agents/runtime/provenance.json +5 -5
- package/templates/.agents/runtime/sbom.cdx.json +3 -3
- package/templates/.agents/sales/playbook.md +32 -0
- package/templates/.agents/sales/roteiro-comercial-zaip.md +252 -0
- package/templates/.agents/skills/criar-pasta-obsidian/scripts/generate-obsidian-vault.test.mjs +20 -16
- package/templates/.agents/skills/zaip-aios/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-agent-catalog/SKILL.md +22 -0
- package/templates/.agents/skills/zaip-skill-agent-catalog/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-author-skills/SKILL.md +3 -2
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +49 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/author-skill-scripts.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/run-skill-tests.mjs +37 -0
- package/templates/.agents/skills/zaip-skill-backend/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +9 -2
- package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-framework.md +39 -0
- package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +1 -1
- package/templates/.agents/skills/zaip-skill-change/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-change/references/observable-evidence.md +83 -0
- package/templates/.agents/skills/zaip-skill-dashboard-diagnostics/SKILL.md +22 -0
- package/templates/.agents/skills/zaip-skill-dashboard-diagnostics/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-enforce-architecture/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-frontend/SKILL.md +4 -3
- package/templates/.agents/skills/zaip-skill-frontend/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +10 -10
- package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +6 -0
- package/templates/.agents/skills/zaip-skill-lifecycle-closure/SKILL.md +27 -0
- package/templates/.agents/skills/zaip-skill-lifecycle-closure/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +6 -0
- package/templates/.agents/skills/zaip-skill-prd/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +111 -104
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-explicit-recovery.mjs +223 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +55 -9
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +145 -14
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +19 -9
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +82 -5
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/source-size-telemetry/model-identity-reconciliation.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +20 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-review/SKILL.md +5 -0
- package/templates/.agents/skills/zaip-skill-rules/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +6 -0
- package/templates/.agents/skills/zaip-skill-spec/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +22 -90
- package/templates/.agents/skills/zaip-skill-sqlite-read-model/scripts/ensure-node.mjs +28 -5
- package/templates/.agents/zaip-aios/INDEX.md +57 -22
- package/templates/.agents/zaip-aios/README.md +24 -13
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/.agents/zaip-aios/guides/02-requirements.md +5 -0
- package/templates/.agents/zaip-aios/guides/06-execucao.md +13 -4
- package/templates/.agents/zaip-aios/guides/07-revisao-e-validacao.md +7 -0
- package/templates/.agents/zaip-aios/guides/10-seguranca.md +23 -0
- package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +6 -6
- package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +3 -0
- package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +12 -3
- package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +5 -5
- package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +76 -0
- package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +95 -0
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +366 -0
- package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +46 -0
- package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +74 -0
- package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +483 -0
- package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +85 -0
- package/templates/.agents/zaip-aios/guides/25-fontes-de-precos-openai.md +19 -0
- package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +111 -0
- package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +172 -0
- package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +149 -0
- package/templates/.agents/zaip-aios/guides/assets/diagrams/lifecycles-task-spec-prd.png +0 -0
- package/templates/.agents/zaip-aios/guides/assets/diagrams/prd-lifecycle.png +0 -0
- package/templates/.agents/zaip-aios/guides/assets/diagrams/spec-lifecycle.png +0 -0
- package/templates/.agents/zaip-aios/guides/assets/diagrams/task-lifecycle.png +0 -0
- package/templates/template-manifest.json +756 -235
- package/templates/.agents/dashboard/apps/frontend/dist/assets/DashboardHelpDialog-Cs6dzDmW.js +0 -1505
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-QE1k9yZB.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-_Pf5DA_A.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BVlz3DLZ.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-BZ5WdaMN.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-Cf9ctPVt.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8A4DcNXM.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DK_enB5Z.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-idle-cost-prefetch.ts +0 -45
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createHash, randomBytes } from "node:crypto";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
4
|
import { serve } from "@hono/node-server";
|
|
6
5
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
7
6
|
import { loadWorkspaceLayout, WorkspaceFileSystem, type WorkspaceLayout } from "@zaip-ai/core";
|
|
@@ -18,17 +17,8 @@ import {
|
|
|
18
17
|
readSpecDetail,
|
|
19
18
|
readTaskDetail,
|
|
20
19
|
} from "@zaip-ai/dashboard-operations/server";
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
buildTraceStageRecords,
|
|
24
|
-
classifyTraceDocument,
|
|
25
|
-
timestampsFromContent,
|
|
26
|
-
} from "@zaip-ai/dashboard-traceability/server";
|
|
27
|
-
import type {
|
|
28
|
-
TaskTrace,
|
|
29
|
-
TraceDocument,
|
|
30
|
-
} from "../../../modules/traceability/src/contracts.js";
|
|
31
|
-
import { type CompactRunMetric, LifecycleManifestStore } from "@zaip-ai/lifecycle-manifests";
|
|
20
|
+
import { buildTaskTrace } from "@zaip-ai/dashboard-traceability/server";
|
|
21
|
+
import { LifecycleManifestStore } from "@zaip-ai/lifecycle-manifests";
|
|
32
22
|
import { type Context, Hono } from "hono";
|
|
33
23
|
import { getCookie, setCookie } from "hono/cookie";
|
|
34
24
|
import type { ContentfulStatusCode } from "hono/utils/http-status";
|
|
@@ -39,7 +29,11 @@ import {
|
|
|
39
29
|
persistAgentCatalogUpdate,
|
|
40
30
|
readAgentCatalogSettings,
|
|
41
31
|
} from "./agent-catalog-settings.js";
|
|
42
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
persistProjectSettings,
|
|
34
|
+
readProjectOverview,
|
|
35
|
+
readProjectSettings,
|
|
36
|
+
} from "./project-settings.js";
|
|
43
37
|
import {
|
|
44
38
|
type BoardClassification,
|
|
45
39
|
boardFilters,
|
|
@@ -56,21 +50,28 @@ import {
|
|
|
56
50
|
} from "./server-operations-pages.js";
|
|
57
51
|
import { registerOperationsRunsRoute } from "./server-operations-runs-route.js";
|
|
58
52
|
import { projectionPeriodFilter } from "./server-period.js";
|
|
53
|
+
import { periodMacroMetric, projectAllTimeTopTasks } from "./server-period-macro-metric.js";
|
|
59
54
|
import {
|
|
60
55
|
buildCanonicalOperationsProjection,
|
|
61
56
|
buildCurrentCostProjection,
|
|
62
57
|
buildManifestCostRunPage,
|
|
63
58
|
buildManifestFirstCostProjection,
|
|
64
|
-
filterCostRunRows,
|
|
65
59
|
isUnfilteredCostRequest,
|
|
66
60
|
knownWorkIds,
|
|
67
61
|
normalizeWorkPriority,
|
|
68
|
-
pageCostRunRows,
|
|
69
62
|
readCurrentFxRate,
|
|
70
63
|
readWorkPriority,
|
|
71
64
|
} from "./server-projections.js";
|
|
65
|
+
import { isAllowedDashboardAuthority } from "./server-request-authority.js";
|
|
66
|
+
import { refreshSqliteSnapshotInWorker } from "./server-snapshot-refresh.js";
|
|
67
|
+
import { buildSqliteTaskTrace } from "./server-sqlite-task-trace.js";
|
|
72
68
|
import { queryValues, selectedCurrency } from "./server-summary-helpers.js";
|
|
73
|
-
import {
|
|
69
|
+
import {
|
|
70
|
+
dashboardIdentity,
|
|
71
|
+
dashboardWorkspaceKey,
|
|
72
|
+
type ReconciliationResult,
|
|
73
|
+
reconcileOpenWork,
|
|
74
|
+
} from "./server-workspace.js";
|
|
74
75
|
import {
|
|
75
76
|
rebuildSqliteReadModel,
|
|
76
77
|
SqliteReadModelFileSystem,
|
|
@@ -79,6 +80,7 @@ import {
|
|
|
79
80
|
|
|
80
81
|
export { manifestRun, mergeManifestRuns } from "./manifest-runs.js";
|
|
81
82
|
export { projectionPeriodFilter } from "./server-period.js";
|
|
83
|
+
export { projectAllTimeTopTasks } from "./server-period-macro-metric.js";
|
|
82
84
|
export {
|
|
83
85
|
dashboardWorkspaceKey,
|
|
84
86
|
githubRepositoryFromRemote,
|
|
@@ -92,28 +94,14 @@ export {
|
|
|
92
94
|
validateSqliteReadModelSchema,
|
|
93
95
|
} from "./sqlite-read-model.js";
|
|
94
96
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
total_duration_ms: number | null;
|
|
98
|
-
total_tokens: number | null;
|
|
99
|
-
total_cost_usd: number | null;
|
|
100
|
-
total_cost_brl: number | null;
|
|
101
|
-
total_run_count: number;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
export function projectAllTimeTopTasks(
|
|
105
|
-
tasks: readonly AllTimeTopTaskFact[],
|
|
106
|
-
): NonNullable<NonNullable<OperationsProjection["summary"]["overview_metrics"]>["top_tasks"]> {
|
|
107
|
-
return tasks.map((task) => ({
|
|
108
|
-
task_id: task.task_id,
|
|
109
|
-
duration_ms: task.total_duration_ms,
|
|
110
|
-
total_tokens: task.total_tokens,
|
|
111
|
-
total_cost_usd: task.total_cost_usd,
|
|
112
|
-
cost_brl: task.total_cost_brl,
|
|
113
|
-
run_count: task.total_run_count,
|
|
114
|
-
}));
|
|
97
|
+
export function reconciliationNeedsRefresh(result: ReconciliationResult): boolean {
|
|
98
|
+
return result.reconciled_ids.length > 0 || result.blocked.length > 0;
|
|
115
99
|
}
|
|
116
100
|
|
|
101
|
+
type OverviewMacroMetrics = NonNullable<
|
|
102
|
+
NonNullable<OperationsProjection["summary"]["overview_metrics"]>["macro_metrics"]
|
|
103
|
+
>;
|
|
104
|
+
|
|
117
105
|
const API_PREFIX = "/api/v2";
|
|
118
106
|
const HOST = "127.0.0.1";
|
|
119
107
|
const RUNTIME_KIND = "zaip-dashboard-sqlite-runtime";
|
|
@@ -170,6 +158,8 @@ interface DashboardAppOptions {
|
|
|
170
158
|
reconcileOpenWork?: typeof reconcileOpenWork;
|
|
171
159
|
refreshReadModel?: () => Promise<void>;
|
|
172
160
|
snapshotState?: "current" | "updating";
|
|
161
|
+
/** Test seam: health and reconciliation only require the asserted V2 layout. */
|
|
162
|
+
layout?: WorkspaceLayout;
|
|
173
163
|
}
|
|
174
164
|
|
|
175
165
|
class V2WorkspaceRequiredError extends Error {
|
|
@@ -232,7 +222,6 @@ function headOrJson(
|
|
|
232
222
|
if (context.req.method === "HEAD") return context.body(null, status);
|
|
233
223
|
return context.json(payload, status);
|
|
234
224
|
}
|
|
235
|
-
|
|
236
225
|
/**
|
|
237
226
|
* Keep the entity/macro details on the snapshot filesystem, while making the
|
|
238
227
|
* first-fold counters and token/cost facts come from SQL.
|
|
@@ -264,7 +253,7 @@ async function buildFirstFoldQuickProjection(
|
|
|
264
253
|
const aggregate =
|
|
265
254
|
filter.from === null && filter.to === null
|
|
266
255
|
? filesystem.firstFoldViewportAllTime().aggregate
|
|
267
|
-
: cachedMonthlyQuick?.aggregate ?? filesystem.firstFoldAggregate(filter);
|
|
256
|
+
: (cachedMonthlyQuick?.aggregate ?? filesystem.firstFoldAggregate(filter));
|
|
268
257
|
return {
|
|
269
258
|
...projection,
|
|
270
259
|
summary: {
|
|
@@ -308,16 +297,26 @@ function buildSqliteOperationsProjection(
|
|
|
308
297
|
const allTime =
|
|
309
298
|
fullAllTime ??
|
|
310
299
|
(filter.from === null && filter.to === null ? filesystem.firstFoldViewportAllTime() : null);
|
|
300
|
+
const allTimeBoard =
|
|
301
|
+
filter.from === null && filter.to === null && options.includeBoardTasks === true
|
|
302
|
+
? filesystem.firstFoldBoardAllTime()
|
|
303
|
+
: null;
|
|
311
304
|
const page = <T extends "task" | "spec" | "prd">(kind: T) =>
|
|
312
|
-
cachedMonthlyQuick?.pages[kind] ??
|
|
305
|
+
cachedMonthlyQuick?.pages[kind] ??
|
|
306
|
+
allTimeBoard?.pages[kind] ??
|
|
307
|
+
filesystem.canonicalWorkPage(kind, filter, 0, 10_000).rows;
|
|
313
308
|
const includeEntities = allTime === null || options.includeBoardTasks === true;
|
|
314
309
|
const tasks = includeEntities ? page("task") : [];
|
|
315
310
|
const specs = includeEntities ? page("spec") : [];
|
|
316
311
|
const prds = includeEntities ? page("prd") : [];
|
|
317
|
-
const aggregate =
|
|
318
|
-
|
|
312
|
+
const aggregate =
|
|
313
|
+
allTime?.aggregate ?? cachedMonthlyQuick?.aggregate ?? filesystem.firstFoldAggregate(filter);
|
|
314
|
+
const legacyDraftCount = allTime?.task_status_counts.draft ?? 0;
|
|
315
|
+
const taskCount =
|
|
316
|
+
allTime === null ? tasks.length : Math.max(0, allTime.aggregate.task_count - legacyDraftCount);
|
|
319
317
|
const allTimeTopTasks =
|
|
320
|
-
filter.from === null &&
|
|
318
|
+
filter.from === null &&
|
|
319
|
+
filter.to === null &&
|
|
321
320
|
(fullAllTime !== null || options.includeTopTasks === true)
|
|
322
321
|
? (fullAllTime?.top_tasks ?? filesystem.firstFoldTopTasksAllTime())
|
|
323
322
|
: null;
|
|
@@ -333,8 +332,11 @@ function buildSqliteOperationsProjection(
|
|
|
333
332
|
: projectAllTimeTopTasks(allTimeTopTasks);
|
|
334
333
|
const macroMetrics =
|
|
335
334
|
fullAllTime === null
|
|
336
|
-
?
|
|
337
|
-
|
|
335
|
+
? ({
|
|
336
|
+
specs: periodMacroMetric(specs, "spec"),
|
|
337
|
+
prds: periodMacroMetric(prds, "prd"),
|
|
338
|
+
} satisfies OverviewMacroMetrics)
|
|
339
|
+
: (Object.fromEntries(
|
|
338
340
|
(["specs", "prds"] as const).map((kind) => {
|
|
339
341
|
const metric = fullAllTime.macro_metrics[kind];
|
|
340
342
|
return [
|
|
@@ -368,8 +370,10 @@ function buildSqliteOperationsProjection(
|
|
|
368
370
|
}),
|
|
369
371
|
) as NonNullable<
|
|
370
372
|
NonNullable<OperationsProjection["summary"]["overview_metrics"]>["macro_metrics"]
|
|
371
|
-
|
|
372
|
-
const statuses: Record<string, number> =
|
|
373
|
+
>);
|
|
374
|
+
const statuses: Record<string, number> = Object.fromEntries(
|
|
375
|
+
Object.entries(allTime?.task_status_counts ?? {}).filter(([status]) => status !== "draft"),
|
|
376
|
+
);
|
|
373
377
|
const risks: Record<string, number> = allTime?.task_risk_counts ?? {};
|
|
374
378
|
if (allTime === null) {
|
|
375
379
|
for (const task of tasks) {
|
|
@@ -414,7 +418,7 @@ function buildSqliteOperationsProjection(
|
|
|
414
418
|
schema_version: 2 as const,
|
|
415
419
|
id: String(row.id),
|
|
416
420
|
revision: 1,
|
|
417
|
-
change_id: "",
|
|
421
|
+
change_id: typeof row.change_id === "string" ? row.change_id : "",
|
|
418
422
|
title: String(row.title ?? row.id),
|
|
419
423
|
short_name: String(row.title ?? row.id),
|
|
420
424
|
objective: "",
|
|
@@ -434,7 +438,8 @@ function buildSqliteOperationsProjection(
|
|
|
434
438
|
result: null,
|
|
435
439
|
artifact_path: ".agents/records",
|
|
436
440
|
progress: 0,
|
|
437
|
-
spec_id: null,
|
|
441
|
+
spec_id: typeof row.spec_id === "string" ? row.spec_id : null,
|
|
442
|
+
origin: typeof row.origin === "string" ? row.origin : null,
|
|
438
443
|
execution_started: false,
|
|
439
444
|
telemetry: {
|
|
440
445
|
duration_ms: nullableMetric(row.total_duration),
|
|
@@ -535,8 +540,7 @@ function buildSqliteOperationsProjection(
|
|
|
535
540
|
task_completion_rate:
|
|
536
541
|
taskCount === 0
|
|
537
542
|
? 0
|
|
538
|
-
: (allTime?.aggregate.completed_task_count ?? statuses.completed ?? 0) /
|
|
539
|
-
taskCount,
|
|
543
|
+
: (allTime?.aggregate.completed_task_count ?? statuses.completed ?? 0) / taskCount,
|
|
540
544
|
terminal_runs: 0,
|
|
541
545
|
successful_runs: 0,
|
|
542
546
|
terminal_success_rate: 0,
|
|
@@ -549,9 +553,6 @@ function buildSqliteOperationsProjection(
|
|
|
549
553
|
origin_tokens_match_total: true,
|
|
550
554
|
},
|
|
551
555
|
usage,
|
|
552
|
-
// The period tabs are part of the first-fold contract too. Supplying an
|
|
553
|
-
// empty object for the all-time fast path made Daily, Monthly and Annual
|
|
554
|
-
// look empty even though the SQLite daily aggregate already existed.
|
|
555
556
|
periods: { daily: options.includePeriods === true ? dailyPeriods : {} },
|
|
556
557
|
},
|
|
557
558
|
origins: { conversation: usage, task: usage, spec: usage, prd: usage },
|
|
@@ -640,90 +641,6 @@ async function firstFoldCostSource(
|
|
|
640
641
|
} satisfies CostSummarySource;
|
|
641
642
|
}
|
|
642
643
|
|
|
643
|
-
function buildSqliteTaskTrace(
|
|
644
|
-
filesystem: SqliteReadModelFileSystem,
|
|
645
|
-
layout: WorkspaceLayout,
|
|
646
|
-
taskId: string,
|
|
647
|
-
): TaskTrace {
|
|
648
|
-
const initial = filesystem.canonicalTraceFiles([taskId]);
|
|
649
|
-
const taskFile = initial.find(
|
|
650
|
-
(row) => row.path.includes("/.agents/records/tasks/") || row.path.includes(".agents/records/tasks/"),
|
|
651
|
-
);
|
|
652
|
-
if (taskFile === undefined) throw new Error(`Canonical Task ${taskId} was not found`);
|
|
653
|
-
const scalar = (key: string): string | null => {
|
|
654
|
-
const frontMatter = /^---\r?\n([\s\S]*?)\r?\n---/.exec(taskFile.content)?.[1] ?? "";
|
|
655
|
-
const value = new RegExp(`^${key}:\\s*(.+?)\\s*$`, "m").exec(frontMatter)?.[1]?.trim();
|
|
656
|
-
if (value === undefined || value === "null") return null;
|
|
657
|
-
return value.replace(/^['"]|['"]$/g, "");
|
|
658
|
-
};
|
|
659
|
-
const relatedId = (key: string, prefix: string): string | null =>
|
|
660
|
-
scalar(key) ?? new RegExp(`\\b${prefix}[A-Z0-9-]+`).exec(taskFile.content)?.[0] ?? null;
|
|
661
|
-
const changeId = relatedId("change_id", "CHG-") ?? taskId;
|
|
662
|
-
const specId = relatedId("spec_id", "SPEC-");
|
|
663
|
-
const prdId = relatedId("prd_id", "PRD-");
|
|
664
|
-
const markers = [taskId, changeId, specId, prdId].filter(
|
|
665
|
-
(value): value is string => value !== null,
|
|
666
|
-
);
|
|
667
|
-
const documents = filesystem
|
|
668
|
-
.canonicalTraceFiles(markers)
|
|
669
|
-
.filter(
|
|
670
|
-
(row) =>
|
|
671
|
-
/\.(?:md|json|jsonl|txt|log)$/i.test(row.path) && row.content.length <= 250_000,
|
|
672
|
-
)
|
|
673
|
-
.map((row) => {
|
|
674
|
-
const classification = classifyTraceDocument(row.path);
|
|
675
|
-
const timestamps = timestampsFromContent(row.content);
|
|
676
|
-
return {
|
|
677
|
-
id: createHash("sha256").update(row.path).digest("hex").slice(0, 16),
|
|
678
|
-
path: row.path,
|
|
679
|
-
title:
|
|
680
|
-
row.content.match(/^#\s+(.+)$/m)?.[1]?.trim() ??
|
|
681
|
-
row.path.split("/").at(-1) ??
|
|
682
|
-
row.path,
|
|
683
|
-
...classification,
|
|
684
|
-
content: row.content,
|
|
685
|
-
...timestamps,
|
|
686
|
-
} satisfies TraceDocument;
|
|
687
|
-
});
|
|
688
|
-
const stages = buildTraceStageRecords(documents);
|
|
689
|
-
const coveredStages = new Set(documents.map((document) => document.stage));
|
|
690
|
-
const risk = scalar("risk");
|
|
691
|
-
const status = scalar("status");
|
|
692
|
-
return {
|
|
693
|
-
schema_version: 2,
|
|
694
|
-
layout_version: layout.version as 2 | 3,
|
|
695
|
-
readonly: true,
|
|
696
|
-
source: ".agents/records",
|
|
697
|
-
task_id: taskId,
|
|
698
|
-
task_title: scalar("title") ?? taskFile.content.match(/^#\s+(.+)$/m)?.[1]?.trim() ?? taskId,
|
|
699
|
-
task_risk: risk === "lite" || risk === "standard" || risk === "critical" ? risk : null,
|
|
700
|
-
task_created_at: scalar("created_at"),
|
|
701
|
-
task_progress:
|
|
702
|
-
status === "completed"
|
|
703
|
-
? 100
|
|
704
|
-
: status === "verifying"
|
|
705
|
-
? 80
|
|
706
|
-
: status === "executing"
|
|
707
|
-
? 50
|
|
708
|
-
: status === "blocked" || status === "failed" || status === "cancelled"
|
|
709
|
-
? 0
|
|
710
|
-
: 10,
|
|
711
|
-
spec_id: specId,
|
|
712
|
-
prd_id: prdId,
|
|
713
|
-
change_id: changeId,
|
|
714
|
-
usage: filesystem.taskTraceUsage(taskId),
|
|
715
|
-
documents,
|
|
716
|
-
stages,
|
|
717
|
-
coverage: {
|
|
718
|
-
stages_with_documents: coveredStages.size,
|
|
719
|
-
stages_with_timestamps: stages.filter((stage) => stage.status === "recorded").length,
|
|
720
|
-
total_stages: 6,
|
|
721
|
-
evidence_count: documents.filter((document) => document.kind === "evidence").length,
|
|
722
|
-
test_count: documents.filter((document) => document.kind === "test").length,
|
|
723
|
-
},
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
|
|
727
644
|
export function createDashboardApp(
|
|
728
645
|
workspaceRoot = process.env.ZAIP_WORKSPACE ?? process.cwd(),
|
|
729
646
|
sessionToken = defaultSessionToken(),
|
|
@@ -737,15 +654,17 @@ export function createDashboardApp(
|
|
|
737
654
|
// its V2 layout repeatedly costs hundreds of milliseconds per navigation;
|
|
738
655
|
// canonical filesystems remain deliberately uncached.
|
|
739
656
|
const sqliteLayout = isSqliteSnapshot ? requireV2Layout(filesystem) : null;
|
|
740
|
-
const readLayout = () =>
|
|
657
|
+
const readLayout = async () =>
|
|
658
|
+
options.layout ?? sqliteLayout ?? (await requireV2Layout(filesystem));
|
|
741
659
|
const snapshotReadOnly = options.snapshotReadOnly ?? isSqliteSnapshot;
|
|
742
660
|
const snapshotState = options.snapshotState ?? "current";
|
|
743
661
|
const canonicalFilesystem = options.canonicalFilesystem ?? new WorkspaceFileSystem(workspaceRoot);
|
|
744
662
|
const reconcileOpen = options.reconcileOpenWork ?? reconcileOpenWork;
|
|
745
|
-
const refreshReadModel =
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
663
|
+
const refreshReadModel =
|
|
664
|
+
options.refreshReadModel ??
|
|
665
|
+
(async () => {
|
|
666
|
+
if (isSqliteSnapshot) await refreshSqliteSnapshotInWorker(workspaceRoot, filesystem);
|
|
667
|
+
});
|
|
749
668
|
const workspaceKey = dashboardWorkspaceKey(workspaceRoot);
|
|
750
669
|
const syncAgentAdapters = options.syncAgentAdapters ?? (() => runAgentAdapterSync(workspaceRoot));
|
|
751
670
|
let catalogWriteTail = Promise.resolve();
|
|
@@ -764,7 +683,8 @@ export function createDashboardApp(
|
|
|
764
683
|
// so retain their expensive board projection until an explicit refresh
|
|
765
684
|
// clears this map rather than expiring it on the short snapshot TTL.
|
|
766
685
|
if (
|
|
767
|
-
!fresh &&
|
|
686
|
+
!fresh &&
|
|
687
|
+
cached !== undefined &&
|
|
768
688
|
(key.startsWith("operations:board:") || Date.now() - cached.cachedAt < SNAPSHOT_CACHE_TTL_MS)
|
|
769
689
|
)
|
|
770
690
|
return cached.payload as T;
|
|
@@ -794,6 +714,16 @@ export function createDashboardApp(
|
|
|
794
714
|
aggregatePayloads.clear();
|
|
795
715
|
aggregateInFlight.clear();
|
|
796
716
|
};
|
|
717
|
+
let projectionRefreshInFlight: Promise<void> | null = null;
|
|
718
|
+
const rebuildProjection = async () => {
|
|
719
|
+
if (projectionRefreshInFlight !== null) return projectionRefreshInFlight;
|
|
720
|
+
projectionRefreshInFlight = refreshReadModel()
|
|
721
|
+
.then(() => clearSnapshotCache())
|
|
722
|
+
.finally(() => {
|
|
723
|
+
projectionRefreshInFlight = null;
|
|
724
|
+
});
|
|
725
|
+
return projectionRefreshInFlight;
|
|
726
|
+
};
|
|
797
727
|
const readSnapshot = (context: Context) => {
|
|
798
728
|
const key = snapshotKey(context);
|
|
799
729
|
const cached = cachedSnapshots.get(key);
|
|
@@ -807,7 +737,8 @@ export function createDashboardApp(
|
|
|
807
737
|
return pending;
|
|
808
738
|
}
|
|
809
739
|
context.header("X-ZAIP-Snapshot-Cache", "miss");
|
|
810
|
-
const inFlight = readLayout()
|
|
740
|
+
const inFlight = readLayout()
|
|
741
|
+
.then((layout) => dashboardSnapshot(filesystem, workspaceRoot, context, layout))
|
|
811
742
|
.then((snapshot) => {
|
|
812
743
|
cachedSnapshots.set(key, { snapshot, cachedAt: Date.now() });
|
|
813
744
|
return snapshot;
|
|
@@ -820,6 +751,9 @@ export function createDashboardApp(
|
|
|
820
751
|
};
|
|
821
752
|
|
|
822
753
|
app.use("*", async (context, next) => {
|
|
754
|
+
if (!isAllowedDashboardAuthority(context.req.url, context.req.header("host"))) {
|
|
755
|
+
return context.json({ error: "Host rejected" }, 403);
|
|
756
|
+
}
|
|
823
757
|
context.header("Cache-Control", "no-store");
|
|
824
758
|
context.header("X-Content-Type-Options", "nosniff");
|
|
825
759
|
context.header("Referrer-Policy", "no-referrer");
|
|
@@ -850,13 +784,15 @@ export function createDashboardApp(
|
|
|
850
784
|
// CLI. It does not mutate the disposable SQLite read model, so it remains
|
|
851
785
|
// available while the dashboard serves a read-only snapshot.
|
|
852
786
|
const reconcileWrite =
|
|
853
|
-
context.req.method === "POST" &&
|
|
854
|
-
|
|
787
|
+
context.req.method === "POST" && context.req.path === `${API_PREFIX}/reconcile-open-work`;
|
|
788
|
+
const projectionRefreshWrite =
|
|
789
|
+
context.req.method === "POST" && context.req.path === `${API_PREFIX}/refresh-projection`;
|
|
855
790
|
if (
|
|
856
791
|
context.req.method !== "GET" &&
|
|
857
792
|
context.req.method !== "HEAD" &&
|
|
858
793
|
!settingsWrite &&
|
|
859
|
-
!reconcileWrite
|
|
794
|
+
!reconcileWrite &&
|
|
795
|
+
!projectionRefreshWrite
|
|
860
796
|
) {
|
|
861
797
|
context.header(
|
|
862
798
|
"Allow",
|
|
@@ -868,7 +804,9 @@ export function createDashboardApp(
|
|
|
868
804
|
? "GET, HEAD, PUT"
|
|
869
805
|
: context.req.path === `${API_PREFIX}/reconcile-open-work`
|
|
870
806
|
? "POST"
|
|
871
|
-
:
|
|
807
|
+
: context.req.path === `${API_PREFIX}/refresh-projection`
|
|
808
|
+
? "POST"
|
|
809
|
+
: "GET, HEAD",
|
|
872
810
|
);
|
|
873
811
|
return context.json({ error: "Dashboard API is read-only" }, 405);
|
|
874
812
|
}
|
|
@@ -976,7 +914,13 @@ export function createDashboardApp(
|
|
|
976
914
|
try {
|
|
977
915
|
const requestStartedAt = performance.now();
|
|
978
916
|
const scope = context.req.query("scope");
|
|
979
|
-
if (
|
|
917
|
+
if (
|
|
918
|
+
scope !== "overview" &&
|
|
919
|
+
scope !== "quick" &&
|
|
920
|
+
scope !== "detail" &&
|
|
921
|
+
scope !== "board" &&
|
|
922
|
+
scope !== "classification"
|
|
923
|
+
)
|
|
980
924
|
return headOrJson(context, (await readSnapshot(context)).operations);
|
|
981
925
|
const layout = await readLayout();
|
|
982
926
|
const layoutMs = performance.now() - requestStartedAt;
|
|
@@ -988,52 +932,81 @@ export function createDashboardApp(
|
|
|
988
932
|
50,
|
|
989
933
|
Math.max(1, Number.parseInt(context.req.query("limit") ?? "10", 10) || 10),
|
|
990
934
|
);
|
|
991
|
-
const board = await readAggregate(
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
935
|
+
const board = await readAggregate(
|
|
936
|
+
`operations:board:${from ?? ""}:${to ?? ""}`,
|
|
937
|
+
async () => {
|
|
938
|
+
const projection = await buildFirstFoldQuickProjection(
|
|
939
|
+
filesystem,
|
|
940
|
+
layout,
|
|
941
|
+
{ from, to },
|
|
942
|
+
{ includeBoardTasks: true },
|
|
943
|
+
);
|
|
944
|
+
return {
|
|
945
|
+
projection,
|
|
946
|
+
priority: await readWorkPriority(canonicalFilesystem, knownWorkIds(projection)),
|
|
947
|
+
};
|
|
948
|
+
},
|
|
949
|
+
);
|
|
1003
950
|
const filters = boardFilters(context);
|
|
1004
951
|
const pageKey = JSON.stringify({ from, to, stage, offset, limit, ...filters });
|
|
1005
952
|
const page = await readAggregate(`operations:board-page:${pageKey}`, async () =>
|
|
1006
953
|
boardPage(board.projection, stage, offset, limit, board.priority.item_ids, filters),
|
|
1007
954
|
);
|
|
1008
|
-
return headOrJson(
|
|
1009
|
-
context,
|
|
1010
|
-
page,
|
|
1011
|
-
200,
|
|
1012
|
-
true,
|
|
1013
|
-
);
|
|
955
|
+
return headOrJson(context, page, 200, true);
|
|
1014
956
|
}
|
|
1015
957
|
if (scope === "classification") {
|
|
1016
958
|
const kind = context.req.query("kind");
|
|
1017
959
|
const classification = context.req.query("classification");
|
|
1018
960
|
if (kind !== "task" && kind !== "spec" && kind !== "prd")
|
|
1019
961
|
return headOrJson(context, { error: "A valid work kind is required" }, 400);
|
|
1020
|
-
if (
|
|
962
|
+
if (
|
|
963
|
+
!["lite", "standard", "critical", "empty", "structured", "rework"].includes(
|
|
964
|
+
classification ?? "",
|
|
965
|
+
)
|
|
966
|
+
)
|
|
1021
967
|
return headOrJson(context, { error: "A valid classification is required" }, 400);
|
|
1022
968
|
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
1023
|
-
const limit = Math.min(
|
|
1024
|
-
|
|
1025
|
-
|
|
969
|
+
const limit = Math.min(
|
|
970
|
+
50,
|
|
971
|
+
Math.max(1, Number.parseInt(context.req.query("limit") ?? "50", 10) || 50),
|
|
972
|
+
);
|
|
973
|
+
const projection = await readAggregate(
|
|
974
|
+
`operations:classification:${from ?? ""}:${to ?? ""}`,
|
|
975
|
+
() =>
|
|
976
|
+
buildFirstFoldQuickProjection(
|
|
977
|
+
filesystem,
|
|
978
|
+
layout,
|
|
979
|
+
{ from, to },
|
|
980
|
+
{ includeBoardTasks: true },
|
|
981
|
+
),
|
|
982
|
+
);
|
|
983
|
+
return headOrJson(
|
|
984
|
+
context,
|
|
985
|
+
classificationPage(
|
|
986
|
+
projection,
|
|
987
|
+
kind,
|
|
988
|
+
classification as BoardClassification,
|
|
989
|
+
offset,
|
|
990
|
+
limit,
|
|
991
|
+
),
|
|
992
|
+
200,
|
|
993
|
+
true,
|
|
1026
994
|
);
|
|
1027
|
-
return headOrJson(context, classificationPage(projection, kind, classification as BoardClassification, offset, limit), 200, true);
|
|
1028
995
|
}
|
|
1029
996
|
if (scope === "quick") {
|
|
1030
997
|
const projectionStartedAt = performance.now();
|
|
1031
998
|
const quick = await readAggregate(
|
|
1032
999
|
`operations:quick:${from ?? ""}:${to ?? ""}`,
|
|
1033
1000
|
() =>
|
|
1034
|
-
buildFirstFoldQuickProjection(
|
|
1035
|
-
|
|
1036
|
-
|
|
1001
|
+
buildFirstFoldQuickProjection(
|
|
1002
|
+
filesystem,
|
|
1003
|
+
layout,
|
|
1004
|
+
{ from, to },
|
|
1005
|
+
{
|
|
1006
|
+
includeTopTasks: from === null && to === null,
|
|
1007
|
+
includeExtended: from === null && to === null,
|
|
1008
|
+
},
|
|
1009
|
+
),
|
|
1037
1010
|
context.req.query("fresh") === "1",
|
|
1038
1011
|
);
|
|
1039
1012
|
if (
|
|
@@ -1046,8 +1019,7 @@ export function createDashboardApp(
|
|
|
1046
1019
|
[
|
|
1047
1020
|
`layout;dur=${Math.round(layoutMs * 10) / 10}`,
|
|
1048
1021
|
`projection;dur=${Math.round((performance.now() - projectionStartedAt) * 10) / 10}`,
|
|
1049
|
-
...Object.entries(timings)
|
|
1050
|
-
.map(([name, duration]) => `${name};dur=${duration}`)
|
|
1022
|
+
...Object.entries(timings).map(([name, duration]) => `${name};dur=${duration}`),
|
|
1051
1023
|
].join(", "),
|
|
1052
1024
|
);
|
|
1053
1025
|
}
|
|
@@ -1138,6 +1110,13 @@ export function createDashboardApp(
|
|
|
1138
1110
|
const value = context.req.query(name);
|
|
1139
1111
|
return value === undefined ? {} : { [name]: value };
|
|
1140
1112
|
};
|
|
1113
|
+
const workListKind = context.req.query("kind");
|
|
1114
|
+
if (
|
|
1115
|
+
view === "operations_work_list" &&
|
|
1116
|
+
workListKind !== undefined &&
|
|
1117
|
+
!["all", "task", "standalone-task", "prd", "spec"].includes(workListKind)
|
|
1118
|
+
)
|
|
1119
|
+
return headOrJson(context, { error: "Unsupported Operations work-list kind" }, 400);
|
|
1141
1120
|
return headOrJson(
|
|
1142
1121
|
context,
|
|
1143
1122
|
filesystem.viewPage(view as keyof typeof sqliteViewMetadata, {
|
|
@@ -1153,6 +1132,9 @@ export function createDashboardApp(
|
|
|
1153
1132
|
...optional("origin"),
|
|
1154
1133
|
...optional("workType"),
|
|
1155
1134
|
...optional("priority"),
|
|
1135
|
+
...(workListKind === undefined
|
|
1136
|
+
? {}
|
|
1137
|
+
: { kind: workListKind as "all" | "task" | "standalone-task" | "prd" | "spec" }),
|
|
1156
1138
|
offset: Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0),
|
|
1157
1139
|
limit,
|
|
1158
1140
|
}),
|
|
@@ -1239,14 +1221,19 @@ export function createDashboardApp(
|
|
|
1239
1221
|
try {
|
|
1240
1222
|
await readLayout();
|
|
1241
1223
|
// The served snapshot is immutable by design. Reconciliation must use
|
|
1242
|
-
// canonical records,
|
|
1243
|
-
// before the response exposes fresh projections.
|
|
1224
|
+
// canonical records. When those records changed, atomically rebuild and
|
|
1225
|
+
// reopen the snapshot before the response exposes fresh projections.
|
|
1244
1226
|
const reconciledIds = await reconcileOpen(canonicalFilesystem, workspaceRoot);
|
|
1245
|
-
|
|
1246
|
-
|
|
1227
|
+
// A clean reconciliation is the normal startup path. It changed no
|
|
1228
|
+
// canonical data, so rebuilding the immutable SQLite snapshot only adds
|
|
1229
|
+
// seconds of redundant work before the dashboard can settle.
|
|
1230
|
+
if (reconciliationNeedsRefresh(reconciledIds)) {
|
|
1231
|
+
await rebuildProjection();
|
|
1232
|
+
}
|
|
1247
1233
|
return context.json({
|
|
1248
1234
|
...(await readSnapshot(context)),
|
|
1249
1235
|
reconciliation: reconciledIds,
|
|
1236
|
+
projection_refresh_completed: reconciliationNeedsRefresh(reconciledIds),
|
|
1250
1237
|
});
|
|
1251
1238
|
} catch (error) {
|
|
1252
1239
|
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
@@ -1254,6 +1241,17 @@ export function createDashboardApp(
|
|
|
1254
1241
|
}
|
|
1255
1242
|
});
|
|
1256
1243
|
|
|
1244
|
+
app.post(`${API_PREFIX}/refresh-projection`, async (context) => {
|
|
1245
|
+
try {
|
|
1246
|
+
await readLayout();
|
|
1247
|
+
await rebuildProjection();
|
|
1248
|
+
return context.json(await readSnapshot(context));
|
|
1249
|
+
} catch (error) {
|
|
1250
|
+
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1251
|
+
return context.json({ error: error instanceof Error ? error.message : String(error) }, 400);
|
|
1252
|
+
}
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1257
1255
|
app.on(["GET", "HEAD"], `${API_PREFIX}/cost-monitor`, async (context) => {
|
|
1258
1256
|
try {
|
|
1259
1257
|
const scope = context.req.query("scope") ?? "summary";
|
|
@@ -1343,6 +1341,50 @@ export function createDashboardApp(
|
|
|
1343
1341
|
}
|
|
1344
1342
|
});
|
|
1345
1343
|
|
|
1344
|
+
/** Compact factual attribution view used by both Cost Monitor and Operations.
|
|
1345
|
+
* It is intentionally read-only and is available only from a coherent SQLite
|
|
1346
|
+
* generation, never by reopening mutable JSONL streams on a request. */
|
|
1347
|
+
app.on(["GET", "HEAD"], `${API_PREFIX}/developers`, async (context) => {
|
|
1348
|
+
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1349
|
+
return headOrJson(
|
|
1350
|
+
context,
|
|
1351
|
+
{ error: "Developer attribution requires the SQLite read model" },
|
|
1352
|
+
409,
|
|
1353
|
+
);
|
|
1354
|
+
const { from, to } = projectionPeriodFilter(context);
|
|
1355
|
+
return headOrJson(
|
|
1356
|
+
context,
|
|
1357
|
+
filesystem.developerCostAggregate({
|
|
1358
|
+
from,
|
|
1359
|
+
to,
|
|
1360
|
+
accountIds: queryValues(context, "account_id"),
|
|
1361
|
+
}),
|
|
1362
|
+
200,
|
|
1363
|
+
true,
|
|
1364
|
+
);
|
|
1365
|
+
});
|
|
1366
|
+
|
|
1367
|
+
/** Operations keeps its developer facts separate from Cost Monitor columns. */
|
|
1368
|
+
app.on(["GET", "HEAD"], `${API_PREFIX}/operations/developers`, async (context) => {
|
|
1369
|
+
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1370
|
+
return headOrJson(
|
|
1371
|
+
context,
|
|
1372
|
+
{ error: "Developer attribution requires the SQLite read model" },
|
|
1373
|
+
409,
|
|
1374
|
+
);
|
|
1375
|
+
const { from, to } = projectionPeriodFilter(context);
|
|
1376
|
+
return headOrJson(
|
|
1377
|
+
context,
|
|
1378
|
+
filesystem.operationsDeveloperAggregate({
|
|
1379
|
+
from,
|
|
1380
|
+
to,
|
|
1381
|
+
accountIds: queryValues(context, "account_id"),
|
|
1382
|
+
}),
|
|
1383
|
+
200,
|
|
1384
|
+
true,
|
|
1385
|
+
);
|
|
1386
|
+
});
|
|
1387
|
+
|
|
1346
1388
|
app.on(["GET", "HEAD"], `${API_PREFIX}/pricing`, async (context) =>
|
|
1347
1389
|
headOrJson(
|
|
1348
1390
|
context,
|
|
@@ -1535,7 +1577,7 @@ async function dashboardSnapshot(
|
|
|
1535
1577
|
context: Context,
|
|
1536
1578
|
cachedLayout?: WorkspaceLayout,
|
|
1537
1579
|
) {
|
|
1538
|
-
const layout = cachedLayout ?? await requireV2Layout(filesystem);
|
|
1580
|
+
const layout = cachedLayout ?? (await requireV2Layout(filesystem));
|
|
1539
1581
|
const { from, to } = projectionPeriodFilter(context);
|
|
1540
1582
|
const currency = selectedCurrency(context);
|
|
1541
1583
|
const operations =
|