@zaip-ai/cli 2.2.0 → 3.0.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/README.md +36 -13
- package/dist/services/adapters.d.ts +1 -1
- package/dist/services/adapters.d.ts.map +1 -1
- package/dist/services/adapters.js +26 -9
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/agent-adapters.js +37 -18
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/agent-discovery.d.ts +27 -0
- package/dist/services/agent-discovery.d.ts.map +1 -0
- package/dist/services/agent-discovery.js +73 -0
- package/dist/services/agent-discovery.js.map +1 -0
- package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
- package/dist/services/codex-conversation-lifecycle-hook.js +164 -24
- package/dist/services/codex-conversation-lifecycle-hook.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 +146 -72
- 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 +3 -3
- package/dist/services/codex-subagent-hook-template.d.ts +1 -1
- package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
- package/dist/services/codex-subagent-hook-template.js +117 -66
- package/dist/services/codex-subagent-hook-template.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +65 -7
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/logger.js +1 -1
- package/dist/services/logger.js.map +1 -1
- package/dist/services/logger.test.js +22 -1
- package/dist/services/logger.test.js.map +1 -1
- package/dist/services/runtime-template.test.js +153 -1
- package/dist/services/runtime-template.test.js.map +1 -1
- package/dist/services/transactional-files.d.ts.map +1 -1
- package/dist/services/transactional-files.js +59 -14
- package/dist/services/transactional-files.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/.env.example +9 -3
- package/templates/.agents/README-ENG.md +101 -15
- package/templates/.agents/README.md +102 -17
- package/templates/.agents/architecture/software-architecture.md +1 -59
- package/templates/.agents/branding/brandbook.md +3 -0
- package/templates/.agents/config/agents/catalog.yaml +25 -10
- package/templates/.agents/config/agents/discovery.json +319 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-analyst.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-auditor.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +3 -3
- package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +3 -3
- package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +12 -9
- package/templates/.agents/config/clients/codex/agents/zaip-agent-data-analyst.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +3 -3
- package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +3 -3
- package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-integrator.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +13 -10
- package/templates/.agents/config/clients/codex/agents/zaip-agent-refactoring-specialist.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-reviewer.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-security-auditor.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +3 -3
- package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +3 -3
- package/templates/.agents/config/clients/codex/agents/zaip-agent-writer.toml +1 -1
- package/templates/.agents/config/pricing/models.json +9 -5
- package/templates/.agents/config/project.yaml +22 -2
- package/templates/.agents/dashboard/.zaip-managed.json +530 -138
- package/templates/.agents/dashboard/README.md +16 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-CEDZjl4V.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-DaSllaJp.js → DashboardHelpDialog-TnrL1ZyZ.js} +967 -578
- package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-DjQpBqGU.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-B9GWkEyN.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BAvLPAee.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BQZXUnQu.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-06__WZco.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/dashboard-localization-Basaw1NR.js +824 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-TPUT2IUt.js → icons-vendor-DEmo6Tn2.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-BQe3zTvL.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-Ct48XHGL.js → react-vendor-CadYsm83.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-Bh1tDfsg.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-BzKK8kK3.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
- package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/App.tsx +3 -1264
- package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +368 -0
- package/templates/.agents/dashboard/apps/frontend/src/AutonomySettings.tsx +82 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.dom.test.ts +130 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +206 -157
- package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/__tests__/app-composition-support.ts +12 -0
- package/templates/.agents/dashboard/apps/frontend/src/cost-monitor-population.test.tsx +149 -0
- package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +9 -7
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +152 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +19 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +50 -154
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-app-shell.tsx +33 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.test.ts +54 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.ts +48 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.test.ts +37 -43
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.ts +9 -251
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-project-overview.ts +35 -2
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-retry.ts +17 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-setup-route.ts +29 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.test.ts +51 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.ts +68 -0
- package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +38 -2
- package/templates/.agents/dashboard/apps/frontend/src/operations-period.test.ts +19 -4
- package/templates/.agents/dashboard/apps/frontend/src/operations-period.ts +5 -3
- package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.test.ts +137 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.ts +66 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-copy.ts +181 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +11 -1
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +102 -51
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-state.css +55 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +14 -2
- package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.test.ts +36 -0
- package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.ts +30 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +2 -5
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +31 -20
- package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.ts +1 -2
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +6 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +2 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +9 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-task-pagination.ts +66 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-board.ts +397 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +782 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-snapshot-notice.tsx +49 -0
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/complete-cost-average.test.ts +73 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +9 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/period-averages.ts +60 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperPanelSlot.tsx +16 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.tsx +459 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +8 -22
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +27 -17
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +64 -189
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorRunDialog.tsx +20 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.tsx +32 -8
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-hides-calls-that-have-no-collected.test.ts +80 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +455 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +18 -525
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +32 -508
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-export-sources.ts +74 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-actions.ts +19 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-selectors.ts +49 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-summary.ts +3 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-formatters.ts +115 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +1 -42
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +2 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test-fixtures.ts +2 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.ts +3 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +8 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/index.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/src/contracts.ts +4 -0
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTableBadges.tsx +34 -0
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +8 -38
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview-keeps-structure-classes-mutually-exclusive.test.ts +244 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +66 -3
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +98 -276
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +105 -276
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewCharts.tsx +171 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewPanels.tsx +64 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +9 -17
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +3 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OverviewCostKpi.tsx +46 -0
- package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.test.tsx +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +28 -1
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +11 -4
- package/templates/.agents/dashboard/modules/operations/src/react/index.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/manual-work-priority.test.ts +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +8 -4
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +34 -22
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +3 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +21 -2
- package/templates/.agents/dashboard/modules/operations/src/react/overview-cost-card.test.tsx +89 -0
- package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.ts +32 -0
- package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +3 -3
- package/templates/.agents/dashboard/modules/operations/src/work-board-model.ts +2 -1
- 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/data-export/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +1625 -1613
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +1592 -1582
- package/templates/.agents/dashboard/packages/local-runtime/package.json +3 -2
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +22 -28
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +1625 -1614
- package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +25 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/project-installation-summary.test.ts +142 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/project-installation-summary.ts +190 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +118 -8
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +92 -36
- package/templates/.agents/dashboard/packages/local-runtime/src/projection-refresh-diagnostics.ts +35 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-browser-lease.test.ts +91 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-browser-lease.ts +24 -4
- package/templates/.agents/dashboard/packages/local-runtime/src/server-costs-routes.ts +168 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-dual-reads-manifest-summaries-without-losing.test.ts +344 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-hono-security.test.ts +17 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-http-contracts.ts +31 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-routes.ts +364 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-read-projections.ts +461 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +78 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-route-context.ts +13 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.test.ts +94 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +62 -12
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +44 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +22 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +22 -21
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.test.ts +97 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.ts +10 -13
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-view-allowlist.test.ts +25 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-trace-routes.ts +56 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-traceability-index.test.ts +84 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +2 -30
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +6 -23
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test-fixtures.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +2 -330
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +87 -1060
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-dimension-facts.test.ts +12 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-file-index.test.ts +69 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-cache.ts +3 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-force-canonical.test.ts +3 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-refresh.test.ts +2 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-first-fold.ts +78 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-projections.ts +570 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-runs.ts +600 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-period-averages.ts +46 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-provider-alias-parity.test.ts +50 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-agent-dimension.ts +269 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-context.ts +32 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.ts +244 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-filtered-dimension.ts +303 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-financial.ts +547 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-model-dimension.ts +360 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-provider-dimension.ts +169 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +493 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-temporal-dimension.ts +134 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-timing.ts +299 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-view-page.ts +692 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +763 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-does-not-convert-delayed-historical-finalizer.test.ts +706 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts +762 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-first-fold-types.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-keeps-orphan-telemetry-out-kanban-without.test.ts +710 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-marks-token-cost-telemetry-unavailable-when.test.ts +618 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +764 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuilds-disposable-snapshot-serves-zaip-records.test.ts +276 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +193 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.test.ts +54 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +7 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-types.ts +123 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +5 -2806
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +17 -6930
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-risk-population.test.ts +98 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-base-views.ts +390 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-dashboard-views.ts +413 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-seed.test.ts +2 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/verify-project-settings.mjs +57 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/work-priority-contract.test.ts +4 -3
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-build.mjs +195 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-lifecycle.test.mjs +2 -7
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-logging.mjs +35 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-navigation.mjs +114 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-paths.mjs +90 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +89 -418
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +22 -12
- package/templates/.agents/dashboard/packages/ui/package.json +1 -1
- package/templates/.agents/dashboard/scripts/qualify-observability.mjs +130 -0
- package/templates/.agents/dashboard/scripts/verify-autonomy-settings.mjs +175 -0
- package/templates/.agents/dashboard/scripts/verify-observability.mjs +254 -0
- package/templates/.agents/dashboard/scripts/verify-project-setup.mjs +64 -0
- package/templates/.agents/dashboard/tests/e2e/lease-global-setup.ts +37 -0
- package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +9 -4
- package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-period-transition.spec.ts +22 -1
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +17 -8
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +47 -6
- package/templates/.agents/dashboard/tests/e2e/specs/lease-lifetime.spec.ts +14 -0
- package/templates/.agents/dashboard/tests/observability-fixture.mjs +200 -0
- package/templates/.agents/design/.zaip-managed.json +86 -42
- package/templates/.agents/design/DESIGN.md +2 -186
- package/templates/.agents/design/README.md +12 -2
- package/templates/.agents/design/apps/catalog/dist/assets/index-BJV597iq.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-BOjCcUaU.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-B_WhrCZe.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-CqtYXZfV.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-D_lfqoyx.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-i_PO2k9R.js +9 -0
- package/templates/.agents/design/apps/catalog/dist/index.html +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/CatalogShell-Cstn1UwA.js +1 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{Color-6AOWCN3U-B-kAgAjB.js → Color-6AOWCN3U-Cm-yJJz_.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/Components.stories-D1WopB2L.js +137 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/DesignSystem.stories-DQ9PJ3N3.js +1 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{DocsRenderer-JROSPFPF-BVN7xHtv.js → DocsRenderer-JROSPFPF-Belk4jRr.js} +4 -4
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{WithTooltip-7X4HQR7L-CDHtKYkz.js → WithTooltip-7X4HQR7L-DoPvjkS1.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{chunk-DRQKCCAG-D6AsDkMK.js → chunk-DRQKCCAG-B1itKXEN.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{chunk-W22LQPXL-B4m5uloN.js → chunk-W22LQPXL-C-Eb5SPY.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{components-CN8YyTUg.js → components-DnyKLwhj.js} +5 -5
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/formatter-L2YTDE3Q-D0OSgxWz.js +1 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{iframe-9yZfIsdT.js → iframe-DcXBsFPz.js} +3 -3
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{react-18-BoCSnq6H.js → react-18-CRM89QRf.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/react-C3tkVMIp.js +1 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{syntaxhighlighter-YFXUGROL-Bnn_nMwJ.js → syntaxhighlighter-YFXUGROL-B03jQGTF.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{theming-DS_ue2sb.js → theming-4ZyufAga.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/iframe.html +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/index.json +1 -1
- package/templates/.agents/design/apps/catalog/package.json +2 -2
- package/templates/.agents/design/apps/catalog/src/components/AutonomySpecimen.tsx +15 -0
- package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.test.tsx +19 -0
- package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.tsx +45 -0
- package/templates/.agents/design/apps/catalog/src/components/EstimatedCostSpecimen.tsx +48 -0
- package/templates/.agents/design/apps/catalog/src/components/ProjectStatusSpecimen.tsx +169 -0
- package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +55 -0
- package/templates/.agents/design/apps/catalog/src/stories/Components.stories.tsx +60 -0
- package/templates/.agents/design/packages/local-runtime/package.json +1 -1
- package/templates/.agents/growth/strategy.md +3 -0
- package/templates/.agents/marketing/strategy.md +3 -0
- package/templates/.agents/requirements/autonomous-assurance.md +2 -1
- package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
- 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 +13 -4
- package/templates/.agents/requirements/execution-engine.md +1 -1
- package/templates/.agents/requirements/kanban-dashboard.md +1 -1
- package/templates/.agents/requirements/model-orchestration.md +1 -1
- package/templates/.agents/requirements/public-distribution.md +4 -2
- 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 +6 -6
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/architecture.md +2 -0
- package/templates/.agents/rules/astra-diagnostic.md +3 -1
- package/templates/.agents/rules/autonomy-decision.md +12 -2
- package/templates/.agents/rules/cloud-hostinger-autonomy.md +2 -0
- package/templates/.agents/rules/context.md +2 -1
- package/templates/.agents/rules/core.md +15 -4
- package/templates/.agents/rules/design-system-central-contract.md +17 -0
- package/templates/.agents/rules/evolution.md +3 -1
- package/templates/.agents/rules/frontend-lite.md +3 -1
- package/templates/.agents/rules/local-sqlite-storage.md +2 -2
- package/templates/.agents/rules/meta-mcp.md +3 -1
- package/templates/.agents/rules/model-orchestration.md +1 -1
- package/templates/.agents/rules/run-lifecycle-closure.md +11 -7
- package/templates/.agents/rules/security.md +3 -1
- package/templates/.agents/rules/specialist-routing.md +3 -1
- package/templates/.agents/rules/text-writing-utf8.md +1 -1
- package/templates/.agents/rules/workflow.md +7 -5
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +821 -516
- 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 +3 -0
- package/templates/.agents/skills/zaip-aios/SKILL.md +5 -3
- package/templates/.agents/skills/zaip-skill-adapt-stack/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-api-contracts/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-api-contracts/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-observability/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-application-observability/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-observability/references/signal-design.md +3 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/references/evidence-matrix.md +3 -0
- package/templates/.agents/skills/zaip-skill-architecture-design/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-architecture-design/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-async-jobs/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-async-jobs/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/references/data-access-paths.md +9 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/references/worker-scenario.md +5 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/scripts/worker-contract.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-author-skills/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-author-skills/references/engineering-skill-index.md +9 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +5 -3
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/author-skill-scripts.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-backend/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-backend/references/deployment-environments.md +75 -0
- package/templates/.agents/skills/zaip-skill-backend/references/supabase-migration-contract.md +23 -0
- package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-cache-strategy/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-cache-strategy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-change/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-cloud-engineering/SKILL.md +7 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/SKILL.md +37 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/agents/openai.yaml +6 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workers-static-assets.md +26 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workflow-templates.md +71 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/scripts/cloudflare-github-deploy-contract.test.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-config/SKILL.md +21 -11
- package/templates/.agents/skills/zaip-skill-config/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-container-runtime/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-container-runtime/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-context/SKILL.md +6 -1
- package/templates/.agents/skills/zaip-skill-context/references/prd-spec-task-handoff.md +10 -0
- package/templates/.agents/skills/zaip-skill-context/references/rule-selection.md +20 -0
- package/templates/.agents/skills/zaip-skill-cqrs/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/SKILL.md +18 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/references/audit-contract.md +94 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.mjs +185 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.test.mjs +101 -0
- package/templates/.agents/skills/zaip-skill-data-modeling/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-data-modeling/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/SKILL.md +20 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/references/manual-mode.md +15 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/references/promotion-example.md +5 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.mjs +145 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.test.mjs +178 -0
- package/templates/.agents/skills/zaip-skill-dependency-upgrade/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-dependency-upgrade/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/references/runtime-shapes.md +3 -0
- package/templates/.agents/skills/zaip-skill-design-system/SKILL.md +20 -9
- package/templates/.agents/skills/zaip-skill-dev-environment/SKILL.md +16 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/references/inventory-contract.md +7 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/scripts/inventory.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/references/recovery-scope.md +3 -0
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +31 -8
- package/templates/.agents/skills/zaip-skill-execution/references/correction-cycle.md +7 -0
- package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +18 -8
- package/templates/.agents/skills/zaip-skill-external-integrations/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-external-integrations/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-frontend/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-frontend-componentization/SKILL.md +44 -0
- package/templates/.agents/skills/zaip-skill-frontend-componentization/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-frontend-data-flows/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-frontend-data-flows/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/SKILL.md +36 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/cloudflare-pages.md +33 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/github.md +63 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/hostinger-vps.md +55 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/npm.md +30 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/check-skill.mjs +55 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.mjs +61 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.test.mjs +128 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-ssh.integration.test.mjs +106 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +42 -76
- package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +135 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/github-release-workflow-template.md +31 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-gate-matrix.md +24 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +44 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-notes.md +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.mjs +389 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.test.mjs +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +25 -2
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness-api.test.mjs +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.mjs +98 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.test.mjs +25 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.mjs +159 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.test.mjs +160 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.mjs +149 -12
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.test.mjs +64 -5
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/release-notes-coverage.test.mjs +126 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.mjs +78 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.test.mjs +51 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.mjs +184 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.test.mjs +109 -0
- package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/SKILL.md +18 -10
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/agents/openai.yaml +3 -4
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/aws-cli-terraform.md +62 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/guia-iniciante-hostinger-vps.md +183 -0
- package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/references/scaffold-contract.md +9 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/helpers.test.mjs +121 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/scaffold.mjs +169 -0
- package/templates/.agents/skills/zaip-skill-move-prd/SKILL.md +3 -1
- package/templates/.agents/skills/zaip-skill-move-spec/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-performance-engineering/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-performance-engineering/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-prd/SKILL.md +3 -1
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +1 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +26 -9
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +39 -13
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +1 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/SKILL.md +66 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/references/behavioral-dry-run.md +23 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +38 -1
- package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +122 -0
- package/templates/.agents/skills/zaip-skill-review/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-rules/SKILL.md +3 -3
- package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-setup/SKILL.md +21 -21
- package/templates/.agents/skills/zaip-skill-setup/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-spec/SKILL.md +3 -2
- package/templates/.agents/skills/zaip-skill-storage-uploads/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-storage-uploads/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-systematic-debugging/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-systematic-debugging/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-task/SKILL.md +16 -7
- package/templates/.agents/skills/zaip-skill-task/references/commit-policy.md +25 -0
- package/templates/.agents/skills/zaip-skill-test-data/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-test-data/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-test-data/scripts/generate.mjs +72 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/references/example-map.md +3 -0
- package/templates/.agents/skills/zaip-skill-tool-setup/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-website-readiness/SKILL.md +8 -0
- package/templates/.agents/zaip-aios/INDEX.md +9 -1
- package/templates/.agents/zaip-aios/README.md +23 -2
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/.agents/zaip-aios/guides/01-primeiros-passos.md +5 -1
- package/templates/.agents/zaip-aios/guides/03-tasks.md +15 -2
- package/templates/.agents/zaip-aios/guides/04-specs.md +13 -0
- package/templates/.agents/zaip-aios/guides/05-prds.md +13 -0
- package/templates/.agents/zaip-aios/guides/06-execucao.md +19 -4
- package/templates/.agents/zaip-aios/guides/07-revisao-e-validacao.md +14 -0
- package/templates/.agents/zaip-aios/guides/08-contexto-e-tokens.md +4 -3
- package/templates/.agents/zaip-aios/guides/09-agentes-e-squads.md +17 -9
- package/templates/.agents/zaip-aios/guides/10-seguranca.md +11 -1
- package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +69 -0
- package/templates/.agents/zaip-aios/guides/12-instalacao-e-upgrade.md +9 -4
- package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +7 -1
- package/templates/.agents/zaip-aios/guides/14-troubleshooting.md +18 -0
- package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +54 -3
- package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +10 -2
- package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +186 -5
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +26 -18
- package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +18 -2
- package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +14 -2
- package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +190 -489
- package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +61 -13
- package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +18 -0
- package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +18 -1
- package/templates/scripts/validate-cloud-hostinger-contract.mjs +34 -0
- package/templates/template-manifest.json +1229 -329
- package/templates/.agents/branding/.gitkeep +0 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-snUCQYTC.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-BPtVUGgs.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-3Awyaovx.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-GgzpZ_PY.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BCvZFMEf.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DbaLbU2q.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/dashboard-localization-CLJ0lT9v.js +0 -231
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-_MEktQNM.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-D9-fqq9M.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-BDe4_Ubl.js +0 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/CatalogShell-BWY-80s4.js +0 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/Components.stories-Be2mDUQj.js +0 -27
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/DesignSystem.stories-DRx9blDs.js +0 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/formatter-L2YTDE3Q-EwuTh8Zk.js +0 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/react-DyL61NPT.js +0 -1
- package/templates/.agents/growth/.gitkeep +0 -0
- package/templates/.agents/marketing/.gitkeep +0 -0
- package/templates/.agents/sales/.gitkeep +0 -0
|
@@ -1,27 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { serve } from "@hono/node-server";
|
|
5
5
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
6
|
-
import {
|
|
6
|
+
import { WorkspaceFileSystem, type WorkspaceLayout } from "@zaip-ai/core";
|
|
7
7
|
import { fxRateSchema, PricingRepository, pricingCatalogSchema } from "@zaip-ai/costs";
|
|
8
|
-
import {
|
|
9
|
-
buildCostSummaryProjection,
|
|
10
|
-
type CostSummarySource,
|
|
11
|
-
} from "@zaip-ai/dashboard-cost-monitor/server";
|
|
12
|
-
import type { OperationsProjection } from "@zaip-ai/dashboard-operations/contracts";
|
|
13
|
-
import {
|
|
14
|
-
buildOperationsProjection,
|
|
15
|
-
buildQuickOperationsProjection,
|
|
16
|
-
readPrdDetail,
|
|
17
|
-
readSpecDetail,
|
|
18
|
-
readTaskDetail,
|
|
19
|
-
} from "@zaip-ai/dashboard-operations/server";
|
|
20
|
-
import { buildTaskTrace } from "@zaip-ai/dashboard-traceability/server";
|
|
21
|
-
import { LifecycleManifestStore } from "@zaip-ai/lifecycle-manifests";
|
|
22
8
|
import { type Context, Hono } from "hono";
|
|
23
9
|
import { getCookie, setCookie } from "hono/cookie";
|
|
24
|
-
import
|
|
10
|
+
import { captureActiveCodexTelemetry } from "./active-codex-telemetry.js";
|
|
25
11
|
import { runAgentAdapterSync } from "./agent-adapter-sync.js";
|
|
26
12
|
import {
|
|
27
13
|
type AgentAdapterSyncResult,
|
|
@@ -34,47 +20,28 @@ import {
|
|
|
34
20
|
readProjectOverview,
|
|
35
21
|
readProjectSettings,
|
|
36
22
|
} from "./project-settings.js";
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
type BoardClassification,
|
|
40
|
-
boardFilters,
|
|
41
|
-
boardPage,
|
|
42
|
-
boardStage,
|
|
43
|
-
classificationPage,
|
|
44
|
-
} from "./server-board.js";
|
|
23
|
+
import { createProjectionRefreshDiagnostics } from "./projection-refresh-diagnostics.js";
|
|
24
|
+
import { agentPortraitFiles } from "./server-agent-assets.js";
|
|
45
25
|
import { registerBrowserLeaseRoute } from "./server-browser-lease.js";
|
|
46
|
-
import {
|
|
26
|
+
import { registerCostsRoutes } from "./server-costs-routes.js";
|
|
47
27
|
import {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
} from "./server-
|
|
53
|
-
import {
|
|
28
|
+
API_PREFIX,
|
|
29
|
+
headOrJson,
|
|
30
|
+
requireV2Layout,
|
|
31
|
+
V2WorkspaceRequiredError,
|
|
32
|
+
} from "./server-http-contracts.js";
|
|
33
|
+
import { registerOperationsRoutes } from "./server-operations-routes.js";
|
|
54
34
|
import { projectionPeriodFilter } from "./server-period.js";
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
57
|
-
buildCanonicalOperationsProjection,
|
|
58
|
-
buildCurrentCostProjection,
|
|
59
|
-
buildManifestCostRunPage,
|
|
60
|
-
buildManifestFirstCostProjection,
|
|
61
|
-
isUnfilteredCostRequest,
|
|
62
|
-
knownWorkIds,
|
|
63
|
-
normalizeWorkPriority,
|
|
64
|
-
readCurrentFxRate,
|
|
65
|
-
readWorkPriority,
|
|
66
|
-
} from "./server-projections.js";
|
|
35
|
+
import { buildFirstFoldQuickProjection, dashboardSnapshot } from "./server-read-projections.js";
|
|
67
36
|
import { isAllowedDashboardAuthority } from "./server-request-authority.js";
|
|
68
37
|
import { refreshSqliteSnapshotInWorker } from "./server-snapshot-refresh.js";
|
|
69
38
|
import { readCommittedSnapshotRevision } from "./server-snapshot-revision.js";
|
|
70
39
|
import { startSnapshotSynchronization } from "./server-snapshot-synchronization.js";
|
|
71
|
-
import { buildSqliteTaskTrace } from "./server-sqlite-task-trace.js";
|
|
72
40
|
import { writeReadModelStartup, writeStartupPhase } from "./server-startup.js";
|
|
73
|
-
import {
|
|
41
|
+
import { selectedCurrency } from "./server-summary-helpers.js";
|
|
42
|
+
import { registerTraceRoutes } from "./server-trace-routes.js";
|
|
74
43
|
import {
|
|
75
44
|
createWorkReconciliation,
|
|
76
|
-
reconciliationNeedsRefresh,
|
|
77
|
-
startHostTerminalReconciliation,
|
|
78
45
|
waitForWorkReconciliation,
|
|
79
46
|
} from "./server-work-reconciliation.js";
|
|
80
47
|
|
|
@@ -84,14 +51,9 @@ import {
|
|
|
84
51
|
dashboardIdentity,
|
|
85
52
|
dashboardWorkspaceKey,
|
|
86
53
|
ReconciliationCommandTimeoutError,
|
|
87
|
-
type ReconciliationResult,
|
|
88
54
|
reconcileOpenWork,
|
|
89
55
|
} from "./server-workspace.js";
|
|
90
|
-
import {
|
|
91
|
-
rebuildSqliteReadModel,
|
|
92
|
-
SqliteReadModelFileSystem,
|
|
93
|
-
sqliteViewMetadata,
|
|
94
|
-
} from "./sqlite-read-model.js";
|
|
56
|
+
import { rebuildSqliteReadModel, SqliteReadModelFileSystem } from "./sqlite-read-model.js";
|
|
95
57
|
|
|
96
58
|
export { manifestRun, mergeManifestRuns } from "./manifest-runs.js";
|
|
97
59
|
export { openWorkIds } from "./server-agent-assets.js";
|
|
@@ -110,15 +72,10 @@ export {
|
|
|
110
72
|
validateSqliteReadModelSchema,
|
|
111
73
|
} from "./sqlite-read-model.js";
|
|
112
74
|
|
|
113
|
-
type OverviewMacroMetrics = NonNullable<
|
|
114
|
-
NonNullable<OperationsProjection["summary"]["overview_metrics"]>["macro_metrics"]
|
|
115
|
-
>;
|
|
116
|
-
|
|
117
|
-
const API_PREFIX = "/api/v2";
|
|
118
75
|
const HOST = "127.0.0.1";
|
|
119
76
|
const RUNTIME_KIND = "zaip-dashboard-sqlite-runtime";
|
|
120
77
|
const SESSION_COOKIE = "zaip-dashboard-sqlite-session";
|
|
121
|
-
|
|
78
|
+
|
|
122
79
|
const SNAPSHOT_CACHE_TTL_MS = 5_000;
|
|
123
80
|
interface DashboardAppOptions {
|
|
124
81
|
syncAgentAdapters?: () => Promise<AgentAdapterSyncResult>;
|
|
@@ -137,10 +94,6 @@ interface DashboardAppOptions {
|
|
|
137
94
|
launcherOwned?: boolean;
|
|
138
95
|
}
|
|
139
96
|
|
|
140
|
-
class V2WorkspaceRequiredError extends Error {
|
|
141
|
-
override readonly name = "V2WorkspaceRequiredError";
|
|
142
|
-
}
|
|
143
|
-
|
|
144
97
|
function isAllowedOrigin(origin: string): boolean {
|
|
145
98
|
try {
|
|
146
99
|
const parsed = new URL(origin);
|
|
@@ -151,7 +104,6 @@ function isAllowedOrigin(origin: string): boolean {
|
|
|
151
104
|
return false;
|
|
152
105
|
}
|
|
153
106
|
}
|
|
154
|
-
|
|
155
107
|
function isSafeUiPath(pathname: string): boolean {
|
|
156
108
|
try {
|
|
157
109
|
const decoded = decodeURIComponent(pathname).replaceAll("\\", "/");
|
|
@@ -160,462 +112,29 @@ function isSafeUiPath(pathname: string): boolean {
|
|
|
160
112
|
return false;
|
|
161
113
|
}
|
|
162
114
|
}
|
|
163
|
-
|
|
164
115
|
function defaultSessionToken(): string {
|
|
165
116
|
return process.env.ZAIP_UI_TOKEN ?? randomBytes(24).toString("base64url");
|
|
166
117
|
}
|
|
167
|
-
|
|
168
118
|
function shouldBootstrapBrowserSession(context: Context): boolean {
|
|
169
119
|
if (context.req.method !== "GET" && context.req.method !== "HEAD") return false;
|
|
170
120
|
if (context.req.path !== "/" && context.req.path !== "/index.html") return false;
|
|
171
|
-
|
|
172
121
|
const origin = context.req.header("origin");
|
|
173
122
|
if (origin !== undefined && !isAllowedOrigin(origin)) return false;
|
|
174
123
|
return context.req.header("sec-fetch-site") !== "cross-site";
|
|
175
124
|
}
|
|
176
125
|
|
|
177
|
-
async function requireV2Layout(filesystem: WorkspaceFileSystem): Promise<WorkspaceLayout> {
|
|
178
|
-
const layout = await loadWorkspaceLayout(filesystem);
|
|
179
|
-
if (layout.version === 1) {
|
|
180
|
-
throw new V2WorkspaceRequiredError("Dashboard API requires a modern ZAIP-AIOS workspace");
|
|
181
|
-
}
|
|
182
|
-
return layout;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function headOrJson(
|
|
186
|
-
context: Context,
|
|
187
|
-
payload: unknown,
|
|
188
|
-
status: ContentfulStatusCode = 200,
|
|
189
|
-
cacheable = false,
|
|
190
|
-
): Response {
|
|
191
|
-
if (cacheable) {
|
|
192
|
-
const etag = `"${createHash("sha256").update(JSON.stringify(payload)).digest("base64url")}"`;
|
|
193
|
-
context.header("ETag", etag);
|
|
194
|
-
context.header("Cache-Control", "private, no-cache");
|
|
195
|
-
if (context.req.header("if-none-match") === etag) return context.body(null, 304);
|
|
196
|
-
}
|
|
197
|
-
if (context.req.method === "HEAD") return context.body(null, status);
|
|
198
|
-
return context.json(payload, status);
|
|
199
|
-
}
|
|
200
126
|
/**
|
|
201
127
|
* Keep the entity/macro details on the snapshot filesystem, while making the
|
|
202
128
|
* first-fold counters and token/cost facts come from SQL.
|
|
203
129
|
* Duration intentionally retains the shared hybrid legacy policy in the
|
|
204
130
|
* Operations module; its underlying daily rows are still SQLite-backed.
|
|
205
131
|
*/
|
|
206
|
-
async function buildFirstFoldQuickProjection(
|
|
207
|
-
filesystem: WorkspaceFileSystem,
|
|
208
|
-
layout: WorkspaceLayout,
|
|
209
|
-
filter: { from: string | null; to: string | null },
|
|
210
|
-
options: {
|
|
211
|
-
includeBoardTasks?: boolean;
|
|
212
|
-
includeExtended?: boolean;
|
|
213
|
-
includePeriods?: boolean;
|
|
214
|
-
includeTopTasks?: boolean;
|
|
215
|
-
} = {},
|
|
216
|
-
): Promise<OperationsProjection> {
|
|
217
|
-
// The comparison runtime deliberately has no lifecycle daily aggregates in
|
|
218
|
-
// its snapshot. Its immutable filesystem contains only canonical records,
|
|
219
|
-
// while the SQL views supply the first-fold facts. Never enter the legacy
|
|
220
|
-
// quick projection here: it requires lifecycle daily read models and would
|
|
221
|
-
// make an otherwise valid SQLite dashboard fail on first paint.
|
|
222
|
-
const projection =
|
|
223
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
224
|
-
? buildSqliteOperationsProjection(filesystem, layout, filter, options)
|
|
225
|
-
: await buildQuickOperationsProjection(filesystem, layout, filter, options);
|
|
226
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem)) return projection;
|
|
227
|
-
const cachedMonthlyQuick = filesystem.firstFoldMonthlyQuick(filter);
|
|
228
|
-
const aggregate =
|
|
229
|
-
filter.from === null && filter.to === null
|
|
230
|
-
? filesystem.firstFoldViewportAllTime().aggregate
|
|
231
|
-
: (cachedMonthlyQuick?.aggregate ?? filesystem.firstFoldAggregate(filter));
|
|
232
|
-
return {
|
|
233
|
-
...projection,
|
|
234
|
-
summary: {
|
|
235
|
-
...projection.summary,
|
|
236
|
-
run_count: aggregate.total_run_count,
|
|
237
|
-
overview_metrics: {
|
|
238
|
-
...projection.summary.overview_metrics,
|
|
239
|
-
duration_ms: aggregate.duration_ms,
|
|
240
|
-
tokens: aggregate.total_tokens,
|
|
241
|
-
cost_brl: aggregate.cost_brl,
|
|
242
|
-
execution_day_count: aggregate.execution_day_count,
|
|
243
|
-
data_source: "run_records",
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
132
|
|
|
249
133
|
/**
|
|
250
134
|
* SQLite's files snapshot intentionally excludes derived lifecycle manifests.
|
|
251
135
|
* Build the Operations first fold from its canonical SQL views instead of
|
|
252
136
|
* treating a missing manifest as a broken workspace.
|
|
253
137
|
*/
|
|
254
|
-
function buildSqliteOperationsProjection(
|
|
255
|
-
filesystem: SqliteReadModelFileSystem,
|
|
256
|
-
layout: WorkspaceLayout,
|
|
257
|
-
filter: { from: string | null; to: string | null },
|
|
258
|
-
options: {
|
|
259
|
-
includeBoardTasks?: boolean;
|
|
260
|
-
includeExtended?: boolean;
|
|
261
|
-
includePeriods?: boolean;
|
|
262
|
-
includeTopTasks?: boolean;
|
|
263
|
-
},
|
|
264
|
-
): OperationsProjection {
|
|
265
|
-
const cachedMonthlyQuick = filesystem.firstFoldMonthlyQuick(filter);
|
|
266
|
-
const fullAllTime =
|
|
267
|
-
filter.from === null && filter.to === null
|
|
268
|
-
? options.includeExtended === true
|
|
269
|
-
? filesystem.firstFoldAllTime()
|
|
270
|
-
: null
|
|
271
|
-
: null;
|
|
272
|
-
const allTime =
|
|
273
|
-
fullAllTime ??
|
|
274
|
-
(filter.from === null && filter.to === null ? filesystem.firstFoldViewportAllTime() : null);
|
|
275
|
-
const allTimeBoard =
|
|
276
|
-
filter.from === null && filter.to === null && options.includeBoardTasks === true
|
|
277
|
-
? filesystem.firstFoldBoardAllTime()
|
|
278
|
-
: null;
|
|
279
|
-
const page = <T extends "task" | "spec" | "prd">(kind: T) =>
|
|
280
|
-
cachedMonthlyQuick?.pages[kind] ??
|
|
281
|
-
allTimeBoard?.pages[kind] ??
|
|
282
|
-
filesystem.canonicalWorkPage(kind, filter, 0, 10_000).rows;
|
|
283
|
-
const includeEntities = allTime === null || options.includeBoardTasks === true;
|
|
284
|
-
const tasks = includeEntities ? page("task") : [];
|
|
285
|
-
const specs = includeEntities ? page("spec") : [];
|
|
286
|
-
const prds = includeEntities ? page("prd") : [];
|
|
287
|
-
const aggregate =
|
|
288
|
-
allTime?.aggregate ?? cachedMonthlyQuick?.aggregate ?? filesystem.firstFoldAggregate(filter);
|
|
289
|
-
const legacyDraftCount = allTime?.task_status_counts.draft ?? 0;
|
|
290
|
-
const taskCount =
|
|
291
|
-
allTime === null ? tasks.length : Math.max(0, allTime.aggregate.task_count - legacyDraftCount);
|
|
292
|
-
const allTimeTopTasks =
|
|
293
|
-
filter.from === null &&
|
|
294
|
-
filter.to === null &&
|
|
295
|
-
(fullAllTime !== null || options.includeTopTasks === true)
|
|
296
|
-
? (fullAllTime?.top_tasks ?? filesystem.firstFoldTopTasksAllTime())
|
|
297
|
-
: null;
|
|
298
|
-
const topTasks =
|
|
299
|
-
allTimeTopTasks === null
|
|
300
|
-
? (cachedMonthlyQuick?.top_tasks ?? filesystem.topTasks(filter)).map((task) => ({
|
|
301
|
-
task_id: task.task_id,
|
|
302
|
-
duration_ms: task.duration_ms,
|
|
303
|
-
total_tokens: task.total_tokens,
|
|
304
|
-
cost_brl: task.cost_brl,
|
|
305
|
-
run_count: task.run_count,
|
|
306
|
-
}))
|
|
307
|
-
: projectAllTimeTopTasks(allTimeTopTasks);
|
|
308
|
-
const macroMetrics =
|
|
309
|
-
fullAllTime === null
|
|
310
|
-
? ({
|
|
311
|
-
specs: periodMacroMetric(specs, "spec"),
|
|
312
|
-
prds: periodMacroMetric(prds, "prd"),
|
|
313
|
-
} satisfies OverviewMacroMetrics)
|
|
314
|
-
: (Object.fromEntries(
|
|
315
|
-
(["specs", "prds"] as const).map((kind) => {
|
|
316
|
-
const metric = fullAllTime.macro_metrics[kind];
|
|
317
|
-
return [
|
|
318
|
-
kind,
|
|
319
|
-
{
|
|
320
|
-
status_counts: metric.status_counts,
|
|
321
|
-
classification_counts: metric.classification_counts,
|
|
322
|
-
entity_count: metric.entity_count,
|
|
323
|
-
total_run_count: metric.total_run_count,
|
|
324
|
-
total_duration_ms: metric.total_duration_ms,
|
|
325
|
-
total_tokens: metric.total_tokens,
|
|
326
|
-
total_cost_usd: metric.total_cost_usd,
|
|
327
|
-
total_cost_brl: metric.total_cost_brl,
|
|
328
|
-
average_duration_ms: metric.average_duration_ms,
|
|
329
|
-
average_tokens: metric.average_tokens,
|
|
330
|
-
average_cost_usd: metric.average_cost_usd,
|
|
331
|
-
average_cost_brl: metric.average_cost_brl,
|
|
332
|
-
latest_created_at: metric.latest_created_at,
|
|
333
|
-
top_entities: metric.top_entities.map((entity) => ({
|
|
334
|
-
entity_id: entity.entity_id,
|
|
335
|
-
title: entity.title,
|
|
336
|
-
duration_ms: entity.total_duration_ms,
|
|
337
|
-
total_tokens: entity.total_tokens,
|
|
338
|
-
total_cost_usd: entity.total_cost_usd,
|
|
339
|
-
cost_brl: entity.total_cost_brl,
|
|
340
|
-
run_count: entity.total_run_count,
|
|
341
|
-
duration_share: entity.duration_share,
|
|
342
|
-
})),
|
|
343
|
-
},
|
|
344
|
-
];
|
|
345
|
-
}),
|
|
346
|
-
) as NonNullable<
|
|
347
|
-
NonNullable<OperationsProjection["summary"]["overview_metrics"]>["macro_metrics"]
|
|
348
|
-
>);
|
|
349
|
-
const statuses: Record<string, number> = Object.fromEntries(
|
|
350
|
-
Object.entries(allTime?.task_status_counts ?? {}).filter(([status]) => status !== "draft"),
|
|
351
|
-
);
|
|
352
|
-
const risks: Record<string, number> = allTime?.task_risk_counts ?? {};
|
|
353
|
-
if (allTime === null) {
|
|
354
|
-
for (const task of tasks) {
|
|
355
|
-
const status = typeof task.status === "string" ? task.status : "draft";
|
|
356
|
-
const risk = typeof task.risk === "string" ? task.risk : "standard";
|
|
357
|
-
statuses[status] = (statuses[status] ?? 0) + 1;
|
|
358
|
-
risks[risk] = (risks[risk] ?? 0) + 1;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
const latest =
|
|
362
|
-
allTime?.aggregate.latest_task_created_at ??
|
|
363
|
-
[...tasks, ...specs, ...prds]
|
|
364
|
-
.map((row) => (typeof row.occurred_at === "string" ? row.occurred_at : null))
|
|
365
|
-
.filter((value): value is string => value !== null)
|
|
366
|
-
.sort()
|
|
367
|
-
.at(-1) ??
|
|
368
|
-
null;
|
|
369
|
-
const unavailableUsage = {
|
|
370
|
-
events: 0,
|
|
371
|
-
tokens: { input: null, cached_input: null, output: null, reasoning: null, total: null },
|
|
372
|
-
cost: { usd: null, brl: null },
|
|
373
|
-
coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
|
|
374
|
-
};
|
|
375
|
-
const totalUsage = {
|
|
376
|
-
...unavailableUsage,
|
|
377
|
-
tokens: { ...unavailableUsage.tokens, total: aggregate.total_tokens },
|
|
378
|
-
cost: { ...unavailableUsage.cost, brl: aggregate.cost_brl },
|
|
379
|
-
};
|
|
380
|
-
const usage = {
|
|
381
|
-
conversation: unavailableUsage,
|
|
382
|
-
planning: unavailableUsage,
|
|
383
|
-
execution: unavailableUsage,
|
|
384
|
-
total: totalUsage,
|
|
385
|
-
new_work: unavailableUsage,
|
|
386
|
-
rework: unavailableUsage,
|
|
387
|
-
};
|
|
388
|
-
const dailyPeriods = options.includePeriods === true ? filesystem.dailyPeriods(filter) : {};
|
|
389
|
-
const hasUnknownUsage = Object.values(dailyPeriods).some(
|
|
390
|
-
(period) => period.usage.total_tokens.unknown > 0 || period.usage.cost.unknown > 0,
|
|
391
|
-
);
|
|
392
|
-
const canonicalSource = filesystem.canonicalSource();
|
|
393
|
-
const taskProjection = (row: Record<string, unknown>) => ({
|
|
394
|
-
schema_version: 2 as const,
|
|
395
|
-
id: String(row.id),
|
|
396
|
-
revision: 1,
|
|
397
|
-
change_id: typeof row.change_id === "string" ? row.change_id : "",
|
|
398
|
-
title: String(row.title ?? row.id),
|
|
399
|
-
short_name: String(row.title ?? row.id),
|
|
400
|
-
objective: "",
|
|
401
|
-
status: normalizeTaskStatus(row.status),
|
|
402
|
-
attempt_count: null,
|
|
403
|
-
risk: normalizeRisk(row.risk),
|
|
404
|
-
priority: "medium" as const,
|
|
405
|
-
owner: null,
|
|
406
|
-
requirement_ids: [],
|
|
407
|
-
acceptance_ids: [],
|
|
408
|
-
depends_on: [],
|
|
409
|
-
write_scopes: [],
|
|
410
|
-
created_at: String(row.occurred_at),
|
|
411
|
-
updated_at: String(row.occurred_at),
|
|
412
|
-
started_at: null,
|
|
413
|
-
finished_at: null,
|
|
414
|
-
result: null,
|
|
415
|
-
artifact_path: canonicalSource,
|
|
416
|
-
progress: 0,
|
|
417
|
-
spec_id: typeof row.spec_id === "string" ? row.spec_id : null,
|
|
418
|
-
origin: typeof row.origin === "string" ? row.origin : null,
|
|
419
|
-
execution_started: false,
|
|
420
|
-
telemetry: {
|
|
421
|
-
duration_ms: nullableMetric(row.total_duration),
|
|
422
|
-
tokens: nullableMetric(row.total_tokens),
|
|
423
|
-
cost_brl: nullableMetric(row.total_cost_brl),
|
|
424
|
-
},
|
|
425
|
-
});
|
|
426
|
-
const macroProjection = (row: Record<string, unknown>, kind: "prd" | "spec") => {
|
|
427
|
-
const entityUsage = {
|
|
428
|
-
...unavailableUsage,
|
|
429
|
-
tokens: { ...unavailableUsage.tokens, total: nullableMetric(row.total_tokens) },
|
|
430
|
-
cost: { ...unavailableUsage.cost, brl: nullableMetric(row.total_cost_brl) },
|
|
431
|
-
};
|
|
432
|
-
return {
|
|
433
|
-
id: String(row.id),
|
|
434
|
-
title: String(row.title ?? row.id),
|
|
435
|
-
created_at: String(row.occurred_at),
|
|
436
|
-
updated_at: String(row.occurred_at),
|
|
437
|
-
kind,
|
|
438
|
-
parent_id: null,
|
|
439
|
-
artifact_path: canonicalSource,
|
|
440
|
-
lifecycle_status: String(row.status ?? "draft"),
|
|
441
|
-
work_status: normalizeMacroStatus(row.status),
|
|
442
|
-
execution_ids: [],
|
|
443
|
-
task_ids: [],
|
|
444
|
-
planned_tasks: [],
|
|
445
|
-
canonical_run_ids: [],
|
|
446
|
-
run_ids: [],
|
|
447
|
-
root_execution_run_ids: [],
|
|
448
|
-
execution_count: 0,
|
|
449
|
-
task_count: 0,
|
|
450
|
-
run_count: nullableMetric(row.invocation_count) ?? 0,
|
|
451
|
-
duration_ms: nullableMetric(row.total_duration),
|
|
452
|
-
decisions: { human: 0, agent: 0 },
|
|
453
|
-
rework_run_count: 0,
|
|
454
|
-
quality: {
|
|
455
|
-
completed_tasks: 0,
|
|
456
|
-
task_completion_rate: 0,
|
|
457
|
-
terminal_runs: 0,
|
|
458
|
-
successful_runs: 0,
|
|
459
|
-
terminal_success_rate: 0,
|
|
460
|
-
rework_rate: 0,
|
|
461
|
-
},
|
|
462
|
-
usage: {
|
|
463
|
-
conversation: unavailableUsage,
|
|
464
|
-
planning: unavailableUsage,
|
|
465
|
-
execution: unavailableUsage,
|
|
466
|
-
total: entityUsage,
|
|
467
|
-
new_work: unavailableUsage,
|
|
468
|
-
rework: unavailableUsage,
|
|
469
|
-
},
|
|
470
|
-
};
|
|
471
|
-
};
|
|
472
|
-
return {
|
|
473
|
-
schema_version: 2,
|
|
474
|
-
layout_version: layout.version as 2 | 3,
|
|
475
|
-
readonly: true,
|
|
476
|
-
source: canonicalSource,
|
|
477
|
-
filters: filter,
|
|
478
|
-
summary: {
|
|
479
|
-
prd_count: allTime?.aggregate.prd_count ?? prds.length,
|
|
480
|
-
spec_count: allTime?.aggregate.spec_count ?? specs.length,
|
|
481
|
-
execution_count: 0,
|
|
482
|
-
task_count: taskCount,
|
|
483
|
-
run_count: aggregate.total_run_count,
|
|
484
|
-
overview_metrics: {
|
|
485
|
-
duration_ms: aggregate.duration_ms,
|
|
486
|
-
execution_day_count: aggregate.execution_day_count,
|
|
487
|
-
tokens: aggregate.total_tokens,
|
|
488
|
-
cost_brl: aggregate.cost_brl,
|
|
489
|
-
prd_count: allTime?.aggregate.prd_count ?? prds.length,
|
|
490
|
-
spec_count: allTime?.aggregate.spec_count ?? specs.length,
|
|
491
|
-
selected_counts: {
|
|
492
|
-
prds: allTime?.aggregate.prd_count ?? prds.length,
|
|
493
|
-
specs: allTime?.aggregate.spec_count ?? specs.length,
|
|
494
|
-
},
|
|
495
|
-
task_count: taskCount,
|
|
496
|
-
completed_prd_count:
|
|
497
|
-
allTime?.aggregate.completed_prd_count ??
|
|
498
|
-
prds.filter((row) => row.status === "completed").length,
|
|
499
|
-
completed_spec_count:
|
|
500
|
-
allTime?.aggregate.completed_spec_count ??
|
|
501
|
-
specs.filter((row) => row.status === "completed").length,
|
|
502
|
-
completed_task_count: allTime?.aggregate.completed_task_count ?? statuses.completed ?? 0,
|
|
503
|
-
task_status_counts: statuses,
|
|
504
|
-
task_risk_counts: risks,
|
|
505
|
-
top_tasks: topTasks,
|
|
506
|
-
...(macroMetrics === undefined ? {} : { macro_metrics: macroMetrics }),
|
|
507
|
-
latest_task_created_at: latest,
|
|
508
|
-
coverage: { duration: 1, tokens: hasUnknownUsage ? 0 : 1, cost: hasUnknownUsage ? 0 : 1 },
|
|
509
|
-
data_source: "run_records",
|
|
510
|
-
partial: true,
|
|
511
|
-
},
|
|
512
|
-
decisions: { human: 0, agent: 0 },
|
|
513
|
-
source_latest_at: latest,
|
|
514
|
-
quality: {
|
|
515
|
-
completed_tasks: statuses.completed ?? 0,
|
|
516
|
-
task_completion_rate:
|
|
517
|
-
taskCount === 0
|
|
518
|
-
? 0
|
|
519
|
-
: (allTime?.aggregate.completed_task_count ?? statuses.completed ?? 0) / taskCount,
|
|
520
|
-
terminal_runs: 0,
|
|
521
|
-
successful_runs: 0,
|
|
522
|
-
terminal_success_rate: 0,
|
|
523
|
-
rework_rate: 0,
|
|
524
|
-
},
|
|
525
|
-
reconciliation: {
|
|
526
|
-
phase_tokens_match_total: true,
|
|
527
|
-
phase_usd_match_total: true,
|
|
528
|
-
phase_brl_match_total: true,
|
|
529
|
-
origin_tokens_match_total: true,
|
|
530
|
-
},
|
|
531
|
-
usage,
|
|
532
|
-
periods: { daily: options.includePeriods === true ? dailyPeriods : {} },
|
|
533
|
-
},
|
|
534
|
-
origins: { conversation: usage, task: usage, spec: usage, prd: usage },
|
|
535
|
-
prds: prds.map((row) => macroProjection(row, "prd")),
|
|
536
|
-
specs: specs.map((row) => macroProjection(row, "spec")),
|
|
537
|
-
tasks: options.includeBoardTasks ? tasks.map(taskProjection) : [],
|
|
538
|
-
changes: [],
|
|
539
|
-
executions: [],
|
|
540
|
-
runs: [],
|
|
541
|
-
decisions: [],
|
|
542
|
-
evidences: [],
|
|
543
|
-
validations: [],
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
function nullableMetric(value: unknown): number | null {
|
|
548
|
-
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
function normalizeTaskStatus(
|
|
552
|
-
value: unknown,
|
|
553
|
-
):
|
|
554
|
-
| "draft"
|
|
555
|
-
| "planned"
|
|
556
|
-
| "executing"
|
|
557
|
-
| "verifying"
|
|
558
|
-
| "completed"
|
|
559
|
-
| "failed"
|
|
560
|
-
| "blocked"
|
|
561
|
-
| "cancelled" {
|
|
562
|
-
return [
|
|
563
|
-
"draft",
|
|
564
|
-
"planned",
|
|
565
|
-
"executing",
|
|
566
|
-
"verifying",
|
|
567
|
-
"completed",
|
|
568
|
-
"failed",
|
|
569
|
-
"blocked",
|
|
570
|
-
"cancelled",
|
|
571
|
-
].includes(String(value))
|
|
572
|
-
? (String(value) as
|
|
573
|
-
| "draft"
|
|
574
|
-
| "planned"
|
|
575
|
-
| "executing"
|
|
576
|
-
| "verifying"
|
|
577
|
-
| "completed"
|
|
578
|
-
| "failed"
|
|
579
|
-
| "blocked"
|
|
580
|
-
| "cancelled")
|
|
581
|
-
: "draft";
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
function normalizeRisk(value: unknown): "lite" | "standard" | "critical" {
|
|
585
|
-
return ["lite", "standard", "critical"].includes(String(value))
|
|
586
|
-
? (String(value) as "lite" | "standard" | "critical")
|
|
587
|
-
: "standard";
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
function normalizeMacroStatus(
|
|
591
|
-
value: unknown,
|
|
592
|
-
): "planning" | "executing" | "verifying" | "completed" | "blocked" | "failed" | "cancelled" {
|
|
593
|
-
const status = String(value);
|
|
594
|
-
if (["executing", "verifying", "completed", "blocked", "failed", "cancelled"].includes(status))
|
|
595
|
-
return status as "executing" | "verifying" | "completed" | "blocked" | "failed" | "cancelled";
|
|
596
|
-
return "planning";
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
async function firstFoldCostSource(
|
|
600
|
-
filesystem: WorkspaceFileSystem,
|
|
601
|
-
filters: Parameters<SqliteReadModelFileSystem["invocationCostRows"]>[0] = {
|
|
602
|
-
from: null,
|
|
603
|
-
to: null,
|
|
604
|
-
},
|
|
605
|
-
): Promise<CostSummarySource> {
|
|
606
|
-
if (filesystem instanceof SqliteReadModelFileSystem) {
|
|
607
|
-
return filesystem.costMonitorSummaryAggregate(filters) as CostSummarySource;
|
|
608
|
-
}
|
|
609
|
-
const daily = await new LifecycleManifestStore(filesystem).readDailyReadModels("overview");
|
|
610
|
-
if (daily === null) throw new Error("Lifecycle daily overview is not initialized");
|
|
611
|
-
return {
|
|
612
|
-
periods: {
|
|
613
|
-
daily: Object.fromEntries(
|
|
614
|
-
Object.entries(daily.days).map(([day, model]) => [day, model.overview]),
|
|
615
|
-
),
|
|
616
|
-
},
|
|
617
|
-
} satisfies CostSummarySource;
|
|
618
|
-
}
|
|
619
138
|
|
|
620
139
|
export function createDashboardApp(
|
|
621
140
|
workspaceRoot = process.env.ZAIP_WORKSPACE ?? process.cwd(),
|
|
@@ -692,6 +211,8 @@ export function createDashboardApp(
|
|
|
692
211
|
aggregateInFlight.clear();
|
|
693
212
|
};
|
|
694
213
|
let observedSnapshotRevision: string | null = null;
|
|
214
|
+
const projectionRefreshDiagnostics = createProjectionRefreshDiagnostics();
|
|
215
|
+
let activeCaptureFailure: { code: string; occurred_at: string; cause: string } | null = null;
|
|
695
216
|
let projectionRefreshInFlight: Promise<void> | null = null;
|
|
696
217
|
let projectionRefreshRequested = false;
|
|
697
218
|
const rebuildProjection = async () => {
|
|
@@ -701,15 +222,35 @@ export function createDashboardApp(
|
|
|
701
222
|
}
|
|
702
223
|
snapshotState = "updating";
|
|
703
224
|
projectionRefreshInFlight = (async () => {
|
|
225
|
+
let passes = 0;
|
|
704
226
|
do {
|
|
705
227
|
projectionRefreshRequested = false;
|
|
706
228
|
await refreshReadModel();
|
|
707
229
|
if (isSqliteSnapshot) sqliteLayout = requireV2Layout(filesystem);
|
|
708
230
|
clearSnapshotCache();
|
|
709
|
-
|
|
231
|
+
passes += 1;
|
|
232
|
+
// Publish a committed generation after a bounded catch-up pass. A
|
|
233
|
+
// busy watcher must not hold `/ready` in `updating` indefinitely.
|
|
234
|
+
} while (projectionRefreshRequested && passes < 2);
|
|
710
235
|
snapshotState = "current";
|
|
236
|
+
projectionRefreshDiagnostics.clear();
|
|
711
237
|
})().finally(() => {
|
|
712
238
|
projectionRefreshInFlight = null;
|
|
239
|
+
// Preserve a source change that arrived during the bounded catch-up.
|
|
240
|
+
// It starts after the committed generation becomes observable, rather
|
|
241
|
+
// than extending the current `updating` state without bound.
|
|
242
|
+
if (projectionRefreshRequested) {
|
|
243
|
+
projectionRefreshRequested = false;
|
|
244
|
+
// Yield a real event-loop turn with `current` exposed before starting
|
|
245
|
+
// another rebuild. `/ready` can then advertise the committed SQLite
|
|
246
|
+
// generation and open tabs can read it coherently.
|
|
247
|
+
const followUp = setTimeout(() => {
|
|
248
|
+
void rebuildProjection().catch((error: unknown) =>
|
|
249
|
+
projectionRefreshDiagnostics.record({ trigger: "source_change", error }),
|
|
250
|
+
);
|
|
251
|
+
}, 250);
|
|
252
|
+
followUp.unref();
|
|
253
|
+
}
|
|
713
254
|
});
|
|
714
255
|
return projectionRefreshInFlight;
|
|
715
256
|
};
|
|
@@ -718,6 +259,20 @@ export function createDashboardApp(
|
|
|
718
259
|
staleSeed: isSqliteSnapshot && snapshotState === "updating",
|
|
719
260
|
watchSources: isSqliteSnapshot && options.watchSources === true,
|
|
720
261
|
refresh: rebuildProjection,
|
|
262
|
+
...(isSqliteSnapshot && options.watchSources === true
|
|
263
|
+
? { captureActiveTelemetry: () => captureActiveCodexTelemetry(workspaceRoot) }
|
|
264
|
+
: {}),
|
|
265
|
+
onRefreshFailure: projectionRefreshDiagnostics.record,
|
|
266
|
+
onCaptureSuccess: () => {
|
|
267
|
+
activeCaptureFailure = null;
|
|
268
|
+
},
|
|
269
|
+
onCaptureFailure: (error) => {
|
|
270
|
+
activeCaptureFailure = {
|
|
271
|
+
code: "active_telemetry_capture_failed",
|
|
272
|
+
occurred_at: new Date().toISOString(),
|
|
273
|
+
cause: error instanceof Error ? error.name : "unknown_error",
|
|
274
|
+
};
|
|
275
|
+
},
|
|
721
276
|
});
|
|
722
277
|
const reconcileWork = createWorkReconciliation({
|
|
723
278
|
reconcile: (mode) =>
|
|
@@ -726,13 +281,9 @@ export function createDashboardApp(
|
|
|
726
281
|
}),
|
|
727
282
|
refresh: rebuildProjection,
|
|
728
283
|
});
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
process.env.ZAIP_DASHBOARD_WATCH_SOURCES !== "0"
|
|
733
|
-
) {
|
|
734
|
-
startHostTerminalReconciliation(() => reconcileWork("host-terminal"));
|
|
735
|
-
}
|
|
284
|
+
// Terminal usage is persisted by the host/CLI lifecycle boundary. The
|
|
285
|
+
// source synchronizer above projects those records, but the Dashboard must
|
|
286
|
+
// never run lifecycle reconciliation automatically on startup or a timer.
|
|
736
287
|
const readSnapshot = (context: Context) => {
|
|
737
288
|
const key = snapshotKey(context);
|
|
738
289
|
const cached = cachedSnapshots.get(key);
|
|
@@ -758,7 +309,6 @@ export function createDashboardApp(
|
|
|
758
309
|
snapshotInFlight.set(key, inFlight);
|
|
759
310
|
return inFlight;
|
|
760
311
|
};
|
|
761
|
-
|
|
762
312
|
app.use("*", async (context, next) => {
|
|
763
313
|
if (!isAllowedDashboardAuthority(context.req.url, context.req.header("host"))) {
|
|
764
314
|
return context.json({ error: "Host rejected" }, 403);
|
|
@@ -779,7 +329,6 @@ export function createDashboardApp(
|
|
|
779
329
|
}
|
|
780
330
|
return next();
|
|
781
331
|
});
|
|
782
|
-
|
|
783
332
|
app.use(`${API_PREFIX}/*`, async (context, next) => {
|
|
784
333
|
const settingsWrite =
|
|
785
334
|
context.req.method === "PUT" &&
|
|
@@ -824,7 +373,6 @@ export function createDashboardApp(
|
|
|
824
373
|
}
|
|
825
374
|
if (context.req.path === `${API_PREFIX}/health` || context.req.path === `${API_PREFIX}/ready`)
|
|
826
375
|
return next();
|
|
827
|
-
|
|
828
376
|
const origin = context.req.header("origin");
|
|
829
377
|
if (origin !== undefined && !isAllowedOrigin(origin)) {
|
|
830
378
|
return context.json({ error: "Origin rejected" }, 403);
|
|
@@ -853,7 +401,6 @@ export function createDashboardApp(
|
|
|
853
401
|
return next();
|
|
854
402
|
});
|
|
855
403
|
registerBrowserLeaseRoute(app, API_PREFIX, options.launcherOwned === true);
|
|
856
|
-
|
|
857
404
|
app.on(["GET", "HEAD"], `${API_PREFIX}/health`, async (context) => {
|
|
858
405
|
try {
|
|
859
406
|
const layout = await readLayout();
|
|
@@ -861,12 +408,15 @@ export function createDashboardApp(
|
|
|
861
408
|
kind: RUNTIME_KIND,
|
|
862
409
|
workspaceKey,
|
|
863
410
|
service: "zaip-aios-dashboard",
|
|
864
|
-
status:
|
|
411
|
+
status:
|
|
412
|
+
activeCaptureFailure === null ? projectionRefreshDiagnostics.healthStatus : "degraded",
|
|
865
413
|
api_version: 2,
|
|
866
414
|
workspace_layout: layout.version,
|
|
867
415
|
read_only: true,
|
|
868
416
|
storage: isSqliteSnapshot ? filesystem.metadata() : { storage_mode: "filesystem" },
|
|
869
417
|
snapshot_state: snapshotState,
|
|
418
|
+
projection_refresh_failure: projectionRefreshDiagnostics.failure,
|
|
419
|
+
active_capture_failure: activeCaptureFailure,
|
|
870
420
|
});
|
|
871
421
|
} catch (error) {
|
|
872
422
|
return headOrJson(
|
|
@@ -884,7 +434,6 @@ export function createDashboardApp(
|
|
|
884
434
|
);
|
|
885
435
|
}
|
|
886
436
|
});
|
|
887
|
-
|
|
888
437
|
// Launcher readiness proves a canonical projection can be read; health alone
|
|
889
438
|
// intentionally remains a lightweight process/layout probe.
|
|
890
439
|
app.on(["GET", "HEAD"], `${API_PREFIX}/ready`, async (context) => {
|
|
@@ -913,6 +462,8 @@ export function createDashboardApp(
|
|
|
913
462
|
// /ready must never start a competing projection in the background.
|
|
914
463
|
day_count: metadata.daily_aggregate_count,
|
|
915
464
|
snapshot_state: snapshotState,
|
|
465
|
+
projection_refresh_failure: projectionRefreshDiagnostics.failure,
|
|
466
|
+
active_capture_failure: activeCaptureFailure,
|
|
916
467
|
snapshot_revision: revision,
|
|
917
468
|
});
|
|
918
469
|
}
|
|
@@ -939,321 +490,21 @@ export function createDashboardApp(
|
|
|
939
490
|
);
|
|
940
491
|
}
|
|
941
492
|
});
|
|
942
|
-
|
|
943
493
|
// Header identity is intentionally separate from Operations projections.
|
|
944
494
|
// The quick first fold omits it, and resolving this small configuration/git
|
|
945
495
|
// value must not read, refresh, or otherwise materialize a snapshot.
|
|
946
496
|
app.on(["GET", "HEAD"], `${API_PREFIX}/dashboard-identity`, async (context) =>
|
|
947
497
|
headOrJson(context, await dashboardIdentity(filesystem, workspaceRoot)),
|
|
948
498
|
);
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
scope !== "detail" &&
|
|
958
|
-
scope !== "board" &&
|
|
959
|
-
scope !== "classification"
|
|
960
|
-
)
|
|
961
|
-
return headOrJson(context, (await readSnapshot(context)).operations);
|
|
962
|
-
const layout = await readLayout();
|
|
963
|
-
const layoutMs = performance.now() - requestStartedAt;
|
|
964
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
965
|
-
if (scope === "board") {
|
|
966
|
-
const stage = boardStage(context.req.query("stage"));
|
|
967
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
968
|
-
const limit = Math.min(
|
|
969
|
-
50,
|
|
970
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "10", 10) || 10),
|
|
971
|
-
);
|
|
972
|
-
const board = await readAggregate(
|
|
973
|
-
`operations:board:${from ?? ""}:${to ?? ""}`,
|
|
974
|
-
async () => {
|
|
975
|
-
const projection = await buildFirstFoldQuickProjection(
|
|
976
|
-
filesystem,
|
|
977
|
-
layout,
|
|
978
|
-
{ from, to },
|
|
979
|
-
{ includeBoardTasks: true },
|
|
980
|
-
);
|
|
981
|
-
return {
|
|
982
|
-
projection,
|
|
983
|
-
priority: await readWorkPriority(canonicalFilesystem, knownWorkIds(projection)),
|
|
984
|
-
};
|
|
985
|
-
},
|
|
986
|
-
);
|
|
987
|
-
const filters = boardFilters(context);
|
|
988
|
-
const pageKey = JSON.stringify({ from, to, stage, offset, limit, ...filters });
|
|
989
|
-
const page = await readAggregate(`operations:board-page:${pageKey}`, async () =>
|
|
990
|
-
boardPage(board.projection, stage, offset, limit, board.priority.item_ids, filters),
|
|
991
|
-
);
|
|
992
|
-
return headOrJson(context, page, 200, true);
|
|
993
|
-
}
|
|
994
|
-
if (scope === "classification") {
|
|
995
|
-
const kind = context.req.query("kind");
|
|
996
|
-
const classification = context.req.query("classification");
|
|
997
|
-
if (kind !== "task" && kind !== "spec" && kind !== "prd")
|
|
998
|
-
return headOrJson(context, { error: "A valid work kind is required" }, 400);
|
|
999
|
-
if (
|
|
1000
|
-
!["lite", "standard", "critical", "empty", "structured", "rework"].includes(
|
|
1001
|
-
classification ?? "",
|
|
1002
|
-
)
|
|
1003
|
-
)
|
|
1004
|
-
return headOrJson(context, { error: "A valid classification is required" }, 400);
|
|
1005
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
1006
|
-
const limit = Math.min(
|
|
1007
|
-
50,
|
|
1008
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "50", 10) || 50),
|
|
1009
|
-
);
|
|
1010
|
-
const projection = await readAggregate(
|
|
1011
|
-
`operations:classification:${from ?? ""}:${to ?? ""}`,
|
|
1012
|
-
() =>
|
|
1013
|
-
buildFirstFoldQuickProjection(
|
|
1014
|
-
filesystem,
|
|
1015
|
-
layout,
|
|
1016
|
-
{ from, to },
|
|
1017
|
-
{ includeBoardTasks: true },
|
|
1018
|
-
),
|
|
1019
|
-
);
|
|
1020
|
-
return headOrJson(
|
|
1021
|
-
context,
|
|
1022
|
-
classificationPage(
|
|
1023
|
-
projection,
|
|
1024
|
-
kind,
|
|
1025
|
-
classification as BoardClassification,
|
|
1026
|
-
offset,
|
|
1027
|
-
limit,
|
|
1028
|
-
),
|
|
1029
|
-
200,
|
|
1030
|
-
true,
|
|
1031
|
-
);
|
|
1032
|
-
}
|
|
1033
|
-
if (scope === "quick") {
|
|
1034
|
-
const projectionStartedAt = performance.now();
|
|
1035
|
-
const quick = await readAggregate(
|
|
1036
|
-
`operations:quick:${from ?? ""}:${to ?? ""}`,
|
|
1037
|
-
() =>
|
|
1038
|
-
buildFirstFoldQuickProjection(
|
|
1039
|
-
filesystem,
|
|
1040
|
-
layout,
|
|
1041
|
-
{ from, to },
|
|
1042
|
-
{
|
|
1043
|
-
includeTopTasks: from === null && to === null,
|
|
1044
|
-
includeExtended: from === null && to === null,
|
|
1045
|
-
},
|
|
1046
|
-
),
|
|
1047
|
-
context.req.query("fresh") === "1",
|
|
1048
|
-
);
|
|
1049
|
-
if (
|
|
1050
|
-
process.env.ZAIP_DASHBOARD_PROFILE_FIRST_FOLD === "1" &&
|
|
1051
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1052
|
-
) {
|
|
1053
|
-
const timings = filesystem.firstFoldViewportProfile();
|
|
1054
|
-
context.header(
|
|
1055
|
-
"Server-Timing",
|
|
1056
|
-
[
|
|
1057
|
-
`layout;dur=${Math.round(layoutMs * 10) / 10}`,
|
|
1058
|
-
`projection;dur=${Math.round((performance.now() - projectionStartedAt) * 10) / 10}`,
|
|
1059
|
-
...Object.entries(timings).map(([name, duration]) => `${name};dur=${duration}`),
|
|
1060
|
-
].join(", "),
|
|
1061
|
-
);
|
|
1062
|
-
}
|
|
1063
|
-
return headOrJson(context, quick, 200, true);
|
|
1064
|
-
}
|
|
1065
|
-
const projection =
|
|
1066
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1067
|
-
? await buildFirstFoldQuickProjection(
|
|
1068
|
-
filesystem,
|
|
1069
|
-
layout,
|
|
1070
|
-
{ from, to },
|
|
1071
|
-
{
|
|
1072
|
-
includeBoardTasks: scope === "detail",
|
|
1073
|
-
includeExtended: scope === "detail" || scope === "overview",
|
|
1074
|
-
includePeriods: scope === "detail" || scope === "overview",
|
|
1075
|
-
},
|
|
1076
|
-
)
|
|
1077
|
-
: await buildCanonicalOperationsProjection(
|
|
1078
|
-
filesystem,
|
|
1079
|
-
layout,
|
|
1080
|
-
{ from, to },
|
|
1081
|
-
scope === "overview",
|
|
1082
|
-
);
|
|
1083
|
-
return headOrJson(context, projection, 200, scope === "overview");
|
|
1084
|
-
} catch (error) {
|
|
1085
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1086
|
-
return headOrJson(
|
|
1087
|
-
context,
|
|
1088
|
-
{ error: error instanceof Error ? error.message : String(error) },
|
|
1089
|
-
400,
|
|
1090
|
-
);
|
|
1091
|
-
}
|
|
1092
|
-
});
|
|
1093
|
-
|
|
1094
|
-
registerOperationsRunsRoute(app, filesystem, readAggregate, headOrJson);
|
|
1095
|
-
|
|
1096
|
-
// Explicit SQL read-model API for the comparison dashboard. It never falls
|
|
1097
|
-
// back to filesystem pagination, making first-fold/entity query plans
|
|
1098
|
-
// inspectable while preserving the established Operations contracts.
|
|
1099
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/sqlite-read-models`, async (context) => {
|
|
1100
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1101
|
-
return headOrJson(context, { error: "SQLite read model is not active" }, 409);
|
|
1102
|
-
const kind = context.req.query("kind");
|
|
1103
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
1104
|
-
const limit = Math.min(
|
|
1105
|
-
200,
|
|
1106
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "20", 10) || 20),
|
|
1107
|
-
);
|
|
1108
|
-
if (kind === "overview") {
|
|
1109
|
-
const period = context.req.query("period");
|
|
1110
|
-
if (period !== "day" && period !== "month" && period !== "year")
|
|
1111
|
-
return headOrJson(context, { error: "Unsupported SQLite overview period" }, 400);
|
|
1112
|
-
return headOrJson(context, filesystem.overviewPage(period, offset, limit), 200, true);
|
|
1113
|
-
}
|
|
1114
|
-
if (kind !== "task" && kind !== "spec" && kind !== "prd")
|
|
1115
|
-
return headOrJson(context, { error: "Unsupported SQLite read model" }, 400);
|
|
1116
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1117
|
-
const filters = operationsPageFilters(context);
|
|
1118
|
-
return headOrJson(
|
|
1119
|
-
context,
|
|
1120
|
-
filesystem.summaryPage(
|
|
1121
|
-
kind,
|
|
1122
|
-
{ from, to, ...filters },
|
|
1123
|
-
offset,
|
|
1124
|
-
limit,
|
|
1125
|
-
context.req.query("cursor") ?? null,
|
|
1126
|
-
),
|
|
1127
|
-
200,
|
|
1128
|
-
true,
|
|
1129
|
-
);
|
|
1130
|
-
});
|
|
1131
|
-
|
|
1132
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/sqlite-views`, async (context) => {
|
|
1133
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1134
|
-
return headOrJson(context, { error: "SQLite read model is not active" }, 409);
|
|
1135
|
-
const view = context.req.query("view");
|
|
1136
|
-
if (view === undefined || !(view in sqliteViewMetadata))
|
|
1137
|
-
return headOrJson(context, { error: "Unsupported SQLite view" }, 400);
|
|
1138
|
-
const parsed = Number.parseInt(context.req.query("limit") ?? "", 10);
|
|
1139
|
-
const defaultLimit = view.includes("agent_invocations")
|
|
1140
|
-
? 100
|
|
1141
|
-
: view === "first_fold_top_tasks"
|
|
1142
|
-
? 5
|
|
1143
|
-
: 50;
|
|
1144
|
-
const limit = Math.min(200, Math.max(1, Number.isFinite(parsed) ? parsed : defaultLimit));
|
|
1145
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1146
|
-
const optional = (name: string) => {
|
|
1147
|
-
const value = context.req.query(name);
|
|
1148
|
-
return value === undefined ? {} : { [name]: value };
|
|
1149
|
-
};
|
|
1150
|
-
const workListKind = context.req.query("kind");
|
|
1151
|
-
if (
|
|
1152
|
-
view === "operations_work_list" &&
|
|
1153
|
-
workListKind !== undefined &&
|
|
1154
|
-
!["all", "task", "standalone-task", "prd", "spec"].includes(workListKind)
|
|
1155
|
-
)
|
|
1156
|
-
return headOrJson(context, { error: "Unsupported Operations work-list kind" }, 400);
|
|
1157
|
-
return headOrJson(
|
|
1158
|
-
context,
|
|
1159
|
-
filesystem.viewPage(view as keyof typeof sqliteViewMetadata, {
|
|
1160
|
-
from,
|
|
1161
|
-
to,
|
|
1162
|
-
...optional("query"),
|
|
1163
|
-
...optional("status"),
|
|
1164
|
-
...optional("risk"),
|
|
1165
|
-
...optional("provider"),
|
|
1166
|
-
...optional("model"),
|
|
1167
|
-
...optional("agent"),
|
|
1168
|
-
...optional("phase"),
|
|
1169
|
-
...optional("origin"),
|
|
1170
|
-
...optional("workType"),
|
|
1171
|
-
...optional("priority"),
|
|
1172
|
-
...(workListKind === undefined
|
|
1173
|
-
? {}
|
|
1174
|
-
: { kind: workListKind as "all" | "task" | "standalone-task" | "prd" | "spec" }),
|
|
1175
|
-
offset: Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0),
|
|
1176
|
-
limit,
|
|
1177
|
-
}),
|
|
1178
|
-
200,
|
|
1179
|
-
true,
|
|
1180
|
-
);
|
|
1181
|
-
});
|
|
1182
|
-
|
|
1183
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/work-priority`, async (context) => {
|
|
1184
|
-
const layout = await requireV2Layout(canonicalFilesystem);
|
|
1185
|
-
const operations = await buildOperationsProjection(canonicalFilesystem, layout, {
|
|
1186
|
-
from: null,
|
|
1187
|
-
to: null,
|
|
1188
|
-
});
|
|
1189
|
-
return headOrJson(
|
|
1190
|
-
context,
|
|
1191
|
-
await readWorkPriority(canonicalFilesystem, knownWorkIds(operations)),
|
|
1192
|
-
);
|
|
1193
|
-
});
|
|
1194
|
-
|
|
1195
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/operations/entities`, async (context) => {
|
|
1196
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
1197
|
-
const limit = Math.min(
|
|
1198
|
-
500,
|
|
1199
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "100", 10) || 100),
|
|
1200
|
-
);
|
|
1201
|
-
const kind = context.req.query("kind");
|
|
1202
|
-
if (kind !== "changes" && kind !== "decisions")
|
|
1203
|
-
return headOrJson(context, { error: "Unsupported Operations entity page" }, 400);
|
|
1204
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1205
|
-
const pageFilters = operationsPageFilters(context);
|
|
1206
|
-
const payload = await readAggregate(
|
|
1207
|
-
`operations:entities:${kind}:${from ?? ""}:${to ?? ""}:${offset}:${limit}:${pageFilters.query}:${pageFilters.status}:${pageFilters.risk}`,
|
|
1208
|
-
async () => {
|
|
1209
|
-
const layout = await readLayout();
|
|
1210
|
-
const entities = await new LifecycleManifestStore(filesystem).readEntities(
|
|
1211
|
-
kind === "changes" ? "change" : "decision",
|
|
1212
|
-
);
|
|
1213
|
-
const entityRows =
|
|
1214
|
-
kind === "changes"
|
|
1215
|
-
? changeEntityPageRows(entities, layout, from, to)
|
|
1216
|
-
: decisionEntityPageRows(entities, layout, from, to);
|
|
1217
|
-
const rows = filterLifecyclePageRows(entityRows, pageFilters);
|
|
1218
|
-
return {
|
|
1219
|
-
data_source: "lifecycle_manifest_shards",
|
|
1220
|
-
kind,
|
|
1221
|
-
offset,
|
|
1222
|
-
limit,
|
|
1223
|
-
total: rows.length,
|
|
1224
|
-
rows: rows.slice(offset, offset + limit),
|
|
1225
|
-
};
|
|
1226
|
-
},
|
|
1227
|
-
);
|
|
1228
|
-
return headOrJson(context, payload, 200, true);
|
|
1229
|
-
});
|
|
1230
|
-
|
|
1231
|
-
registerDailyReadModelRoute(app, filesystem, readAggregate, headOrJson);
|
|
1232
|
-
app.put(`${API_PREFIX}/work-priority`, async (context) => {
|
|
1233
|
-
const candidate = normalizeWorkPriority(await context.req.json());
|
|
1234
|
-
// Priority is canonical queue configuration, never snapshot content.
|
|
1235
|
-
// Keep every other settings mutation blocked in snapshot-serving mode.
|
|
1236
|
-
await canonicalFilesystem.writeTextAtomic(
|
|
1237
|
-
WORK_PRIORITY_PATH,
|
|
1238
|
-
`${JSON.stringify(candidate, null, 2)}\n`,
|
|
1239
|
-
);
|
|
1240
|
-
clearSnapshotCache();
|
|
1241
|
-
return context.json(candidate);
|
|
1242
|
-
});
|
|
1243
|
-
|
|
1244
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/snapshot`, async (context) => {
|
|
1245
|
-
try {
|
|
1246
|
-
return headOrJson(context, await readSnapshot(context));
|
|
1247
|
-
} catch (error) {
|
|
1248
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1249
|
-
return headOrJson(
|
|
1250
|
-
context,
|
|
1251
|
-
{ error: error instanceof Error ? error.message : String(error) },
|
|
1252
|
-
400,
|
|
1253
|
-
);
|
|
1254
|
-
}
|
|
499
|
+
registerOperationsRoutes(app, {
|
|
500
|
+
filesystem,
|
|
501
|
+
canonicalFilesystem,
|
|
502
|
+
isSqliteSnapshot,
|
|
503
|
+
readLayout,
|
|
504
|
+
readSnapshot,
|
|
505
|
+
readAggregate,
|
|
506
|
+
clearSnapshotCache,
|
|
1255
507
|
});
|
|
1256
|
-
|
|
1257
508
|
app.post(`${API_PREFIX}/reconcile-open-work`, async (context) => {
|
|
1258
509
|
try {
|
|
1259
510
|
await readLayout();
|
|
@@ -1286,7 +537,6 @@ export function createDashboardApp(
|
|
|
1286
537
|
return context.json({ error: error instanceof Error ? error.message : String(error) }, 400);
|
|
1287
538
|
}
|
|
1288
539
|
});
|
|
1289
|
-
|
|
1290
540
|
app.post(`${API_PREFIX}/refresh-projection`, async (context) => {
|
|
1291
541
|
try {
|
|
1292
542
|
await readLayout();
|
|
@@ -1297,151 +547,15 @@ export function createDashboardApp(
|
|
|
1297
547
|
return context.json({ error: error instanceof Error ? error.message : String(error) }, 400);
|
|
1298
548
|
}
|
|
1299
549
|
});
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
const aggregateStartedAt = performance.now();
|
|
1309
|
-
const [source, rate] = await Promise.all([
|
|
1310
|
-
firstFoldCostSource(filesystem, {
|
|
1311
|
-
from,
|
|
1312
|
-
to,
|
|
1313
|
-
providers: queryValues(context, "provider"),
|
|
1314
|
-
models: queryValues(context, "model"),
|
|
1315
|
-
agents: queryValues(context, "agent"),
|
|
1316
|
-
phases: queryValues(context, "phase"),
|
|
1317
|
-
statuses: queryValues(context, "status"),
|
|
1318
|
-
tasks: queryValues(context, "task"),
|
|
1319
|
-
specs: queryValues(context, "spec"),
|
|
1320
|
-
prds: queryValues(context, "prd"),
|
|
1321
|
-
executions: queryValues(context, "execution"),
|
|
1322
|
-
changes: queryValues(context, "change"),
|
|
1323
|
-
}),
|
|
1324
|
-
currency === "BRL" ? readCurrentFxRate(filesystem) : Promise.resolve(null),
|
|
1325
|
-
]);
|
|
1326
|
-
// First fold receives only aggregate facts. Detailed Runs and entity
|
|
1327
|
-
// arrays remain on their explicit paginated endpoints.
|
|
1328
|
-
const aggregateMs = performance.now() - aggregateStartedAt;
|
|
1329
|
-
const costOperations = {
|
|
1330
|
-
schema_version: 1,
|
|
1331
|
-
layout_version: layout.version,
|
|
1332
|
-
readonly: true,
|
|
1333
|
-
source: ".agents/records",
|
|
1334
|
-
filters: { from, to },
|
|
1335
|
-
summary: { task_count: source.task_count ?? 0 },
|
|
1336
|
-
prds: [],
|
|
1337
|
-
specs: [],
|
|
1338
|
-
runs: [],
|
|
1339
|
-
} as unknown as OperationsProjection;
|
|
1340
|
-
const projectionStartedAt = performance.now();
|
|
1341
|
-
const payload = buildCostSummaryProjection(
|
|
1342
|
-
source,
|
|
1343
|
-
costOperations,
|
|
1344
|
-
currency,
|
|
1345
|
-
rate?.rate ?? null,
|
|
1346
|
-
);
|
|
1347
|
-
context.header(
|
|
1348
|
-
"Server-Timing",
|
|
1349
|
-
`cost_sql;dur=${aggregateMs.toFixed(1)},cost_projection;dur=${(performance.now() - projectionStartedAt).toFixed(1)}`,
|
|
1350
|
-
);
|
|
1351
|
-
return headOrJson(context, payload, 200, true);
|
|
1352
|
-
}
|
|
1353
|
-
if (scope === "runs") {
|
|
1354
|
-
const layout = await readLayout();
|
|
1355
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1356
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
1357
|
-
const limit = Math.min(
|
|
1358
|
-
500,
|
|
1359
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "100", 10) || 100),
|
|
1360
|
-
);
|
|
1361
|
-
return headOrJson(
|
|
1362
|
-
context,
|
|
1363
|
-
// The paged Cost adapter reads the lifecycle summary. That canonical
|
|
1364
|
-
// artifact is intentionally not copied into SQLite; use its current
|
|
1365
|
-
// filesystem alongside the immutable SQL facts rather than failing
|
|
1366
|
-
// a filtered page with a synthetic missing-file error.
|
|
1367
|
-
await buildManifestCostRunPage(
|
|
1368
|
-
isSqliteSnapshot ? canonicalFilesystem : filesystem,
|
|
1369
|
-
layout,
|
|
1370
|
-
context,
|
|
1371
|
-
{ from, to },
|
|
1372
|
-
offset,
|
|
1373
|
-
limit,
|
|
1374
|
-
),
|
|
1375
|
-
200,
|
|
1376
|
-
true,
|
|
1377
|
-
);
|
|
1378
|
-
}
|
|
1379
|
-
if (isUnfilteredCostRequest(context))
|
|
1380
|
-
return headOrJson(context, (await readSnapshot(context)).costs);
|
|
1381
|
-
const layout = await readLayout();
|
|
1382
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1383
|
-
// Cost and Operations must start from the same manifest-corrected Run
|
|
1384
|
-
// population; financial availability is represented on each row, never
|
|
1385
|
-
// by dropping lifecycle Runs before the Cost projection.
|
|
1386
|
-
const operations = await buildCanonicalOperationsProjection(filesystem, layout, { from, to });
|
|
1387
|
-
return headOrJson(
|
|
1388
|
-
context,
|
|
1389
|
-
await buildManifestFirstCostProjection(filesystem, operations, context),
|
|
1390
|
-
);
|
|
1391
|
-
} catch (error) {
|
|
1392
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1393
|
-
return headOrJson(
|
|
1394
|
-
context,
|
|
1395
|
-
{ error: error instanceof Error ? error.message : String(error) },
|
|
1396
|
-
400,
|
|
1397
|
-
);
|
|
1398
|
-
}
|
|
550
|
+
registerCostsRoutes(app, {
|
|
551
|
+
filesystem,
|
|
552
|
+
canonicalFilesystem,
|
|
553
|
+
isSqliteSnapshot,
|
|
554
|
+
readLayout,
|
|
555
|
+
readSnapshot,
|
|
556
|
+
readAggregate,
|
|
557
|
+
clearSnapshotCache,
|
|
1399
558
|
});
|
|
1400
|
-
|
|
1401
|
-
/** Compact factual attribution view used by both Cost Monitor and Operations.
|
|
1402
|
-
* It is intentionally read-only and is available only from a coherent SQLite
|
|
1403
|
-
* generation, never by reopening mutable JSONL streams on a request. */
|
|
1404
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/developers`, async (context) => {
|
|
1405
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1406
|
-
return headOrJson(
|
|
1407
|
-
context,
|
|
1408
|
-
{ error: "Developer attribution requires the SQLite read model" },
|
|
1409
|
-
409,
|
|
1410
|
-
);
|
|
1411
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1412
|
-
return headOrJson(
|
|
1413
|
-
context,
|
|
1414
|
-
filesystem.developerCostAggregate({
|
|
1415
|
-
from,
|
|
1416
|
-
to,
|
|
1417
|
-
accountIds: queryValues(context, "account_id"),
|
|
1418
|
-
}),
|
|
1419
|
-
200,
|
|
1420
|
-
true,
|
|
1421
|
-
);
|
|
1422
|
-
});
|
|
1423
|
-
|
|
1424
|
-
/** Operations keeps its developer facts separate from Cost Monitor columns. */
|
|
1425
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/operations/developers`, async (context) => {
|
|
1426
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1427
|
-
return headOrJson(
|
|
1428
|
-
context,
|
|
1429
|
-
{ error: "Developer attribution requires the SQLite read model" },
|
|
1430
|
-
409,
|
|
1431
|
-
);
|
|
1432
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1433
|
-
return headOrJson(
|
|
1434
|
-
context,
|
|
1435
|
-
filesystem.operationsDeveloperAggregate({
|
|
1436
|
-
from,
|
|
1437
|
-
to,
|
|
1438
|
-
accountIds: queryValues(context, "account_id"),
|
|
1439
|
-
}),
|
|
1440
|
-
200,
|
|
1441
|
-
true,
|
|
1442
|
-
);
|
|
1443
|
-
});
|
|
1444
|
-
|
|
1445
559
|
app.on(["GET", "HEAD"], `${API_PREFIX}/pricing`, async (context) =>
|
|
1446
560
|
headOrJson(
|
|
1447
561
|
context,
|
|
@@ -1450,7 +564,6 @@ export function createDashboardApp(
|
|
|
1450
564
|
),
|
|
1451
565
|
),
|
|
1452
566
|
);
|
|
1453
|
-
|
|
1454
567
|
app.put(`${API_PREFIX}/pricing`, async (context) => {
|
|
1455
568
|
const catalog = pricingCatalogSchema.parse({
|
|
1456
569
|
...(await context.req.json()),
|
|
@@ -1463,19 +576,16 @@ export function createDashboardApp(
|
|
|
1463
576
|
clearSnapshotCache();
|
|
1464
577
|
return context.json(catalog);
|
|
1465
578
|
});
|
|
1466
|
-
|
|
1467
579
|
app.on(["GET", "HEAD"], `${API_PREFIX}/fx-rate`, async (context) => {
|
|
1468
580
|
const rate = await new PricingRepository(filesystem).readLatestFxRate();
|
|
1469
581
|
return headOrJson(context, rate);
|
|
1470
582
|
});
|
|
1471
|
-
|
|
1472
583
|
app.put(`${API_PREFIX}/fx-rate`, async (context) => {
|
|
1473
584
|
const input = fxRateSchema.pick({ rate: true }).parse(await context.req.json());
|
|
1474
585
|
const rate = await new PricingRepository(filesystem).writeCurrentFxRate(input.rate);
|
|
1475
586
|
clearSnapshotCache();
|
|
1476
587
|
return context.json(rate);
|
|
1477
588
|
});
|
|
1478
|
-
|
|
1479
589
|
app.on(["GET", "HEAD"], `${API_PREFIX}/agent-catalog`, async (context) => {
|
|
1480
590
|
try {
|
|
1481
591
|
return headOrJson(context, await readAgentCatalogSettings(filesystem));
|
|
@@ -1487,7 +597,6 @@ export function createDashboardApp(
|
|
|
1487
597
|
);
|
|
1488
598
|
}
|
|
1489
599
|
});
|
|
1490
|
-
|
|
1491
600
|
app.get(`${API_PREFIX}/agent-catalog-assets/:agentId`, async (context) => {
|
|
1492
601
|
const portrait = agentPortraitFiles[context.req.param("agentId")];
|
|
1493
602
|
if (portrait === undefined) return context.json({ error: "Agent portrait not found" }, 404);
|
|
@@ -1504,7 +613,6 @@ export function createDashboardApp(
|
|
|
1504
613
|
return context.json({ error: "Agent portrait could not be read" }, 500);
|
|
1505
614
|
}
|
|
1506
615
|
});
|
|
1507
|
-
|
|
1508
616
|
app.put(`${API_PREFIX}/agent-catalog`, async (context) => {
|
|
1509
617
|
const update = async () => {
|
|
1510
618
|
try {
|
|
@@ -1529,7 +637,6 @@ export function createDashboardApp(
|
|
|
1529
637
|
);
|
|
1530
638
|
return result;
|
|
1531
639
|
});
|
|
1532
|
-
|
|
1533
640
|
app.on(["GET", "HEAD"], `${API_PREFIX}/project-settings`, async (context) => {
|
|
1534
641
|
try {
|
|
1535
642
|
return headOrJson(context, await readProjectSettings(canonicalFilesystem));
|
|
@@ -1541,11 +648,9 @@ export function createDashboardApp(
|
|
|
1541
648
|
);
|
|
1542
649
|
}
|
|
1543
650
|
});
|
|
1544
|
-
|
|
1545
651
|
app.on(["GET", "HEAD"], `${API_PREFIX}/project-settings/overview`, async (context) => {
|
|
1546
652
|
return headOrJson(context, await readProjectOverview(canonicalFilesystem));
|
|
1547
653
|
});
|
|
1548
|
-
|
|
1549
654
|
app.put(`${API_PREFIX}/project-settings`, async (context) => {
|
|
1550
655
|
try {
|
|
1551
656
|
const persisted = await persistProjectSettings(canonicalFilesystem, await context.req.json());
|
|
@@ -1558,53 +663,15 @@ export function createDashboardApp(
|
|
|
1558
663
|
);
|
|
1559
664
|
}
|
|
1560
665
|
});
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
}
|
|
1570
|
-
});
|
|
1571
|
-
|
|
1572
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/prds/:id`, async (context) => {
|
|
1573
|
-
try {
|
|
1574
|
-
const layout = await readLayout();
|
|
1575
|
-
return headOrJson(context, await readPrdDetail(filesystem, layout, context.req.param("id")));
|
|
1576
|
-
} catch (error) {
|
|
1577
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1578
|
-
return headOrJson(context, { error: "PRD not found" }, 404);
|
|
1579
|
-
}
|
|
1580
|
-
});
|
|
1581
|
-
|
|
1582
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/specs/:id`, async (context) => {
|
|
1583
|
-
try {
|
|
1584
|
-
const layout = await readLayout();
|
|
1585
|
-
return headOrJson(context, await readSpecDetail(filesystem, layout, context.req.param("id")));
|
|
1586
|
-
} catch (error) {
|
|
1587
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1588
|
-
return headOrJson(context, { error: "SPEC not found" }, 404);
|
|
1589
|
-
}
|
|
666
|
+
registerTraceRoutes(app, {
|
|
667
|
+
filesystem,
|
|
668
|
+
canonicalFilesystem,
|
|
669
|
+
isSqliteSnapshot,
|
|
670
|
+
readLayout,
|
|
671
|
+
readSnapshot,
|
|
672
|
+
readAggregate,
|
|
673
|
+
clearSnapshotCache,
|
|
1590
674
|
});
|
|
1591
|
-
|
|
1592
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/tasks/:id/trace`, async (context) => {
|
|
1593
|
-
try {
|
|
1594
|
-
const layout = await readLayout();
|
|
1595
|
-
const taskId = context.req.param("id");
|
|
1596
|
-
return headOrJson(
|
|
1597
|
-
context,
|
|
1598
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1599
|
-
? buildSqliteTaskTrace(filesystem, layout, taskId)
|
|
1600
|
-
: await buildTaskTrace(filesystem, layout, taskId),
|
|
1601
|
-
);
|
|
1602
|
-
} catch (error) {
|
|
1603
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1604
|
-
return headOrJson(context, { error: "Task trace not found" }, 404);
|
|
1605
|
-
}
|
|
1606
|
-
});
|
|
1607
|
-
|
|
1608
675
|
app.onError((error, context) => {
|
|
1609
676
|
const status = error instanceof V2WorkspaceRequiredError ? 409 : 500;
|
|
1610
677
|
return headOrJson(
|
|
@@ -1613,9 +680,7 @@ export function createDashboardApp(
|
|
|
1613
680
|
status,
|
|
1614
681
|
);
|
|
1615
682
|
});
|
|
1616
|
-
|
|
1617
683
|
app.all(`${API_PREFIX}/*`, (context) => headOrJson(context, { error: "Not found" }, 404));
|
|
1618
|
-
|
|
1619
684
|
app.on(["GET", "HEAD"], "/", serveStatic({ path: `${uiRoot}/index.html` }));
|
|
1620
685
|
app.use("/*", async (context, next) => {
|
|
1621
686
|
if (!isSafeUiPath(context.req.path)) {
|
|
@@ -1628,45 +693,10 @@ export function createDashboardApp(
|
|
|
1628
693
|
return app;
|
|
1629
694
|
}
|
|
1630
695
|
|
|
1631
|
-
async function dashboardSnapshot(
|
|
1632
|
-
filesystem: WorkspaceFileSystem,
|
|
1633
|
-
workspaceRoot: string,
|
|
1634
|
-
context: Context,
|
|
1635
|
-
cachedLayout?: WorkspaceLayout,
|
|
1636
|
-
) {
|
|
1637
|
-
const layout = cachedLayout ?? (await requireV2Layout(filesystem));
|
|
1638
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1639
|
-
const currency = selectedCurrency(context);
|
|
1640
|
-
const operations =
|
|
1641
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1642
|
-
? await buildFirstFoldQuickProjection(filesystem, layout, { from, to })
|
|
1643
|
-
: await buildCanonicalOperationsProjection(filesystem, layout, { from, to });
|
|
1644
|
-
const costs =
|
|
1645
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1646
|
-
? buildCostSummaryProjection(
|
|
1647
|
-
await firstFoldCostSource(filesystem, { from, to }),
|
|
1648
|
-
operations,
|
|
1649
|
-
currency,
|
|
1650
|
-
currency === "BRL" ? ((await readCurrentFxRate(filesystem))?.rate ?? null) : null,
|
|
1651
|
-
)
|
|
1652
|
-
: await buildCurrentCostProjection(filesystem, operations, currency);
|
|
1653
|
-
return {
|
|
1654
|
-
operations,
|
|
1655
|
-
costs,
|
|
1656
|
-
dashboard: await dashboardIdentity(filesystem, workspaceRoot),
|
|
1657
|
-
projection: {
|
|
1658
|
-
source_latest_at: operations.summary.source_latest_at,
|
|
1659
|
-
served_at: new Date().toISOString(),
|
|
1660
|
-
},
|
|
1661
|
-
};
|
|
1662
|
-
}
|
|
1663
|
-
|
|
1664
696
|
const moduleStartedAt = performance.now();
|
|
1665
697
|
const sessionToken = defaultSessionToken();
|
|
1666
698
|
const runtimeWorkspaceRoot = process.env.ZAIP_WORKSPACE ?? process.cwd();
|
|
1667
|
-
|
|
1668
699
|
let defaultApp: Hono | undefined;
|
|
1669
|
-
|
|
1670
700
|
/**
|
|
1671
701
|
* Compatibility export for direct module consumers. The executable must not
|
|
1672
702
|
* construct this filesystem-backed app: `main` creates the SQLite app after
|
|
@@ -1676,14 +706,12 @@ export function defaultDashboardApp(): Hono {
|
|
|
1676
706
|
defaultApp ??= createDashboardApp(runtimeWorkspaceRoot, sessionToken);
|
|
1677
707
|
return defaultApp;
|
|
1678
708
|
}
|
|
1679
|
-
|
|
1680
709
|
export const app = new Proxy({} as Hono, {
|
|
1681
710
|
get(_target, property) {
|
|
1682
711
|
const value = Reflect.get(defaultDashboardApp(), property);
|
|
1683
712
|
return typeof value === "function" ? value.bind(defaultDashboardApp()) : value;
|
|
1684
713
|
},
|
|
1685
714
|
});
|
|
1686
|
-
|
|
1687
715
|
async function main(): Promise<void> {
|
|
1688
716
|
const port = Number.parseInt(process.env.ZAIP_SERVER_PORT ?? "4317", 10);
|
|
1689
717
|
writeStartupPhase(moduleStartedAt, "main_entered");
|
|
@@ -1706,7 +734,6 @@ async function main(): Promise<void> {
|
|
|
1706
734
|
);
|
|
1707
735
|
});
|
|
1708
736
|
}
|
|
1709
|
-
|
|
1710
737
|
if (
|
|
1711
738
|
process.argv[1]?.endsWith("server.cjs") ||
|
|
1712
739
|
process.argv[1]?.endsWith("server.js") ||
|