@zaip-ai/cli 3.2.0 → 3.4.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.
Files changed (288) hide show
  1. package/dist/services/adapters.d.ts +1 -1
  2. package/dist/services/adapters.d.ts.map +1 -1
  3. package/dist/services/adapters.js +5 -3
  4. package/dist/services/adapters.js.map +1 -1
  5. package/dist/services/agent-catalog-upgrade.d.ts +3 -0
  6. package/dist/services/agent-catalog-upgrade.d.ts.map +1 -0
  7. package/dist/services/agent-catalog-upgrade.js +35 -0
  8. package/dist/services/agent-catalog-upgrade.js.map +1 -0
  9. package/dist/services/install-agents-template.d.ts.map +1 -1
  10. package/dist/services/install-agents-template.js +22 -22
  11. package/dist/services/install-agents-template.js.map +1 -1
  12. package/dist/services/install-template-policy.d.ts +3 -0
  13. package/dist/services/install-template-policy.d.ts.map +1 -0
  14. package/dist/services/install-template-policy.js +21 -0
  15. package/dist/services/install-template-policy.js.map +1 -0
  16. package/dist/services/logger.js +24 -8
  17. package/dist/services/logger.js.map +1 -1
  18. package/dist/services/logger.test.js +33 -6
  19. package/dist/services/logger.test.js.map +1 -1
  20. package/dist/services/sqlite-bootstrap.d.ts +1 -0
  21. package/dist/services/sqlite-bootstrap.d.ts.map +1 -1
  22. package/dist/services/sqlite-bootstrap.js +10 -1
  23. package/dist/services/sqlite-bootstrap.js.map +1 -1
  24. package/package.json +2 -2
  25. package/templates/.agents/README-ENG.md +2 -1
  26. package/templates/.agents/README.md +2 -1
  27. package/templates/.agents/config/agents/catalog.yaml +1 -0
  28. package/templates/.agents/config/agents/discovery.json +2 -2
  29. package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +2 -2
  30. package/templates/.agents/dashboard/.zaip-managed.json +278 -126
  31. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-CEDZjl4V.js → CostCalculationGuidePage-C5NgEcVh.js} +1 -1
  32. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-BzaUTZDx.js → DashboardHelpDialog-CCMVnkkI.js} +4 -3
  33. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-21cCJik-.js → PricingSettingsDialog-CGYcJ5EB.js} +1 -1
  34. package/templates/.agents/dashboard/apps/frontend/dist/assets/{ProjectSettingsPage-BAvLPAee.js → ProjectSettingsPage-DVCPPV75.js} +1 -1
  35. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-wqW52uCx.js → TraceabilityWorkspace-CqK3Psfy.js} +1 -1
  36. package/templates/.agents/dashboard/apps/frontend/dist/assets/{cost-monitor-PoJA2PI1.css → cost-monitor-BsMfGfQi.css} +1 -1
  37. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-j3aUYH5G.js +68 -0
  38. package/templates/.agents/dashboard/apps/frontend/dist/assets/{dashboard-localization-BkAm8-h4.js → dashboard-localization-jvdDfNKs.js} +2 -1
  39. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DEmo6Tn2.js → icons-vendor-x8xxL9yW.js} +1 -1
  40. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Cl5EWx8R.js +2 -0
  41. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Cwylbh_N.css +1 -0
  42. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-CadYsm83.js → react-vendor-CNOXIJHN.js} +1 -1
  43. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-BzKK8kK3.js → traceability-CcpbpT1s.js} +1 -1
  44. package/templates/.agents/dashboard/apps/frontend/dist/index.html +7 -7
  45. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  46. package/templates/.agents/dashboard/apps/frontend/src/App.tsx +12 -1
  47. package/templates/.agents/dashboard/apps/frontend/src/WorkspaceStatus.test.tsx +33 -0
  48. package/templates/.agents/dashboard/apps/frontend/src/WorkspaceStatus.tsx +58 -0
  49. package/templates/.agents/dashboard/apps/frontend/src/app-work-board-options.ts +41 -0
  50. package/templates/.agents/dashboard/apps/frontend/src/dashboard-runtime-status.ts +25 -0
  51. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +1 -1
  52. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +5 -1
  53. package/templates/.agents/dashboard/apps/frontend/src/use-app-work-board.test.ts +140 -0
  54. package/templates/.agents/dashboard/apps/frontend/src/use-app-work-board.ts +28 -41
  55. package/templates/.agents/dashboard/apps/frontend/src/use-runtime-status.ts +38 -0
  56. package/templates/.agents/dashboard/apps/frontend/src/workspace-status.css +33 -0
  57. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  58. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +25 -3
  59. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +17 -19
  60. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.tsx +13 -167
  61. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.tsx +2 -9
  62. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +8 -8
  63. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +29 -52
  64. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableLoading.test.ts +1 -1
  65. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +2 -2
  66. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +4 -27
  67. package/templates/.agents/dashboard/modules/cost-monitor/src/react/MacroCostTable.test.ts +2 -2
  68. package/templates/.agents/dashboard/modules/cost-monitor/src/react/MacroCostTable.tsx +4 -3
  69. package/templates/.agents/dashboard/modules/cost-monitor/src/react/agent-model-presentation.test.ts +26 -0
  70. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-embedded.css +7 -0
  71. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-loaders.ts +173 -0
  72. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-props.ts +47 -0
  73. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-selectors.ts +1 -7
  74. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-page-range.ts +3 -9
  75. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test.ts +44 -83
  76. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.ts +11 -111
  77. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.test.ts +47 -181
  78. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +63 -91
  79. package/templates/.agents/dashboard/modules/cost-monitor/src/server/cost-monitor-unavailable.test.ts +55 -0
  80. package/templates/.agents/dashboard/modules/cost-monitor/src/server/cost-summary-duration.test.ts +189 -0
  81. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  82. package/templates/.agents/dashboard/modules/operations/src/react/OperationsEntityFilters.tsx +82 -0
  83. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +4 -1
  84. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +5 -0
  85. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +22 -31
  86. package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.test.tsx +13 -1
  87. package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.tsx +16 -3
  88. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +11 -27
  89. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +44 -193
  90. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportColumns.ts +186 -0
  91. package/templates/.agents/dashboard/modules/operations/src/react/export/excel-agent-participations.test.ts +28 -0
  92. package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +2 -1
  93. package/templates/.agents/dashboard/modules/operations/src/react/export/xlsx-runtime-e2e.test.ts +55 -31
  94. package/templates/.agents/dashboard/modules/operations/src/react/operations-export-duration.ts +13 -0
  95. package/templates/.agents/dashboard/modules/operations/src/react/operations-filter-panel.css +4 -0
  96. package/templates/.agents/dashboard/modules/operations/src/react/use-operation-filter-feedback.ts +18 -0
  97. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +11 -0
  98. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.ts +10 -2
  99. package/templates/.agents/dashboard/modules/operations/src/work-board-model.ts +1 -1
  100. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  101. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  102. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  103. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  104. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +406 -332
  105. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +352 -280
  106. package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
  107. package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +2 -1
  108. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +4 -2
  109. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +406 -332
  110. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.test.ts +95 -0
  111. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +102 -12
  112. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +75 -1
  113. package/templates/.agents/dashboard/packages/local-runtime/src/server-costs-routes.ts +10 -0
  114. package/templates/.agents/dashboard/packages/local-runtime/src/server-lifecycle-diagnostics.ts +50 -0
  115. package/templates/.agents/dashboard/packages/local-runtime/src/server-macro-population.test.ts +165 -0
  116. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-page-filters.ts +65 -0
  117. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-pages.test.ts +111 -0
  118. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-pages.ts +53 -63
  119. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-runs-route.ts +19 -5
  120. package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.test.ts +19 -0
  121. package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.ts +11 -2
  122. package/templates/.agents/dashboard/packages/local-runtime/src/server-read-projections.ts +19 -12
  123. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.test.ts +46 -2
  124. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +10 -2
  125. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +4 -3
  126. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +43 -1
  127. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +46 -11
  128. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-filter-matrix.test.ts +188 -0
  129. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-summary-details.test.ts +85 -0
  130. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-summary-details.ts +147 -0
  131. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-cache.test.ts +94 -0
  132. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-cache.ts +96 -55
  133. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-force-canonical.test.ts +58 -3
  134. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-macro-classification.test.ts +172 -0
  135. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-projections.ts +1 -1
  136. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-projection.ts +4 -1
  137. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.test.ts +7 -7
  138. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.ts +2 -1
  139. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-period-averages.ts +10 -1
  140. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-agent-dimension.ts +18 -82
  141. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-cached-cost-page.ts +169 -0
  142. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-developer.ts +205 -0
  143. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.ts +13 -4
  144. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-filtered-dimension.ts +22 -23
  145. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-financial.ts +42 -209
  146. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-model-dimension.ts +18 -4
  147. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-provider-dimension.ts +9 -2
  148. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +76 -83
  149. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-view-page.ts +25 -161
  150. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical.ts +18 -45
  151. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +15 -2
  152. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts +16 -16
  153. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-keeps-orphan-telemetry-out-kanban-without.test.ts +2 -1
  154. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider.test.ts +1 -1
  155. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +47 -22
  156. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +16 -2
  157. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +13 -1
  158. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-rebuild-result.ts +15 -0
  159. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-base-views.ts +4 -4
  160. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-dashboard-views.ts +19 -42
  161. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-macro-classification.ts +48 -0
  162. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-summary-cursor.ts +15 -0
  163. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-token-active-allocation.ts +46 -0
  164. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-work-stages.ts +60 -0
  165. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-history.mjs +5 -1
  166. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-claims.test.mjs +7 -1
  167. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +17 -2
  168. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-ownership.mjs +65 -0
  169. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-ownership.test.mjs +72 -0
  170. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-processes.mjs +32 -9
  171. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +39 -45
  172. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +5 -2
  173. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  174. package/templates/.agents/dashboard/scripts/qualify-macro-overview.mjs +50 -0
  175. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  176. package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +1 -18
  177. package/templates/.agents/dashboard/tests/e2e/specs/export-row-identity.spec.ts +20 -0
  178. package/templates/.agents/dashboard/tests/e2e/specs/export-row-identity.ts +20 -0
  179. package/templates/.agents/design/.zaip-managed.json +82 -74
  180. package/templates/.agents/design/apps/catalog/dist/assets/index-0W0Gj_Gs.css +1 -0
  181. package/templates/.agents/design/apps/catalog/dist/assets/index-32GZO95T.js +72 -0
  182. package/templates/.agents/design/apps/catalog/dist/assets/{index-D_lfqoyx.js → index-BP8IxOxt.js} +3 -3
  183. package/templates/.agents/design/apps/catalog/dist/assets/{index-BOjCcUaU.js → index-QJsgr9Ht.js} +3 -3
  184. package/templates/.agents/design/apps/catalog/dist/index.html +2 -2
  185. package/templates/.agents/design/apps/catalog/dist/storybook/assets/CatalogShell-CvaciY0C.js +1 -0
  186. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{Color-6AOWCN3U-Cm-yJJz_.js → Color-6AOWCN3U-DwBV1A1Y.js} +1 -1
  187. package/templates/.agents/design/apps/catalog/dist/storybook/assets/Components.stories-3dqK5g3e.js +142 -0
  188. package/templates/.agents/design/apps/catalog/dist/storybook/assets/DesignSystem.stories-2OCgtT0I.js +1 -0
  189. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{DocsRenderer-JROSPFPF-Belk4jRr.js → DocsRenderer-JROSPFPF-CODg0rSl.js} +4 -4
  190. package/templates/.agents/design/apps/catalog/dist/storybook/assets/Primitives-BmeKjJW4.js +1 -0
  191. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{WithTooltip-7X4HQR7L-DoPvjkS1.js → WithTooltip-7X4HQR7L-C5MI-3uZ.js} +1 -1
  192. package/templates/.agents/design/apps/catalog/dist/storybook/assets/WorkspaceStatus.stories-Tb_iQqVK.js +17 -0
  193. package/templates/.agents/design/apps/catalog/dist/storybook/assets/WorkspaceStatusSpecimen-CD54pw0-.js +1 -0
  194. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{chunk-DRQKCCAG-B1itKXEN.js → chunk-DRQKCCAG-KSn75jcy.js} +1 -1
  195. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{chunk-W22LQPXL-C-Eb5SPY.js → chunk-W22LQPXL-C4LS1Thf.js} +1 -1
  196. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{components-DnyKLwhj.js → components-DV1BRgMY.js} +5 -5
  197. package/templates/.agents/design/apps/catalog/dist/storybook/assets/formatter-L2YTDE3Q-BU_68im1.js +1 -0
  198. package/templates/.agents/design/apps/catalog/dist/storybook/assets/iframe-0W0Gj_Gs.css +1 -0
  199. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{iframe-DcXBsFPz.js → iframe-CBbPFx5G.js} +4 -4
  200. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{react-18-CRM89QRf.js → react-18-C9IPGXtb.js} +1 -1
  201. package/templates/.agents/design/apps/catalog/dist/storybook/assets/react-CEv2qkJT.js +1 -0
  202. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{syntaxhighlighter-YFXUGROL-B03jQGTF.js → syntaxhighlighter-YFXUGROL-ZgDQjyWI.js} +1 -1
  203. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{theming-4ZyufAga.js → theming-Cx9-gH6l.js} +1 -1
  204. package/templates/.agents/design/apps/catalog/dist/storybook/iframe.html +2 -2
  205. package/templates/.agents/design/apps/catalog/dist/storybook/index.json +1 -1
  206. package/templates/.agents/design/apps/catalog/dist/storybook/sb-addons/a11y-2/manager-bundle.js +3 -3
  207. package/templates/.agents/design/apps/catalog/dist/storybook/sb-addons/docs-1/manager-bundle.js +4 -4
  208. package/templates/.agents/design/apps/catalog/dist/storybook/sb-addons/storybook-core-server-presets-0/common-manager-bundle.js +60 -60
  209. package/templates/.agents/design/apps/catalog/package.json +1 -1
  210. package/templates/.agents/design/apps/catalog/src/components/DashboardFiltersSpecimen.tsx +61 -0
  211. package/templates/.agents/design/apps/catalog/src/components/Primitives.tsx +24 -0
  212. package/templates/.agents/design/apps/catalog/src/components/WorkspaceStatusSpecimen.tsx +26 -0
  213. package/templates/.agents/design/apps/catalog/src/design-contract.test.ts +27 -13
  214. package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +38 -0
  215. package/templates/.agents/design/apps/catalog/src/pages/DesignSystemPage.tsx +15 -1
  216. package/templates/.agents/design/apps/catalog/src/stories/Components.stories.tsx +18 -0
  217. package/templates/.agents/design/apps/catalog/src/stories/DashboardFilters.stories.tsx +7 -0
  218. package/templates/.agents/design/apps/catalog/src/stories/WorkspaceStatus.stories.tsx +9 -0
  219. package/templates/.agents/design/apps/catalog/src/styles/components.css +83 -2
  220. package/templates/.agents/design/apps/catalog/src/styles.css +2 -0
  221. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  222. package/templates/.agents/design/tokens.json +32 -0
  223. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  224. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
  225. package/templates/.agents/requirements/comparative-audit.md +1 -1
  226. package/templates/.agents/requirements/context-engine.md +1 -1
  227. package/templates/.agents/requirements/cost-observability.md +1 -1
  228. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  229. package/templates/.agents/requirements/data-export.md +1 -1
  230. package/templates/.agents/requirements/design-system.md +1 -1
  231. package/templates/.agents/requirements/execution-engine.md +1 -1
  232. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  233. package/templates/.agents/requirements/model-orchestration.md +1 -1
  234. package/templates/.agents/requirements/public-distribution.md +18 -4
  235. package/templates/.agents/requirements/software-architecture.md +1 -1
  236. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  237. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  238. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  239. package/templates/.agents/rules/autonomy-decision.md +1 -0
  240. package/templates/.agents/rules/workflow.md +1 -1
  241. package/templates/.agents/runtime/VERSION +1 -1
  242. package/templates/.agents/runtime/bin/zaip.mjs +28 -26
  243. package/templates/.agents/runtime/checksums.sha256 +5 -5
  244. package/templates/.agents/runtime/manifest.json +1 -1
  245. package/templates/.agents/runtime/provenance.json +4 -4
  246. package/templates/.agents/runtime/sbom.cdx.json +1 -1
  247. package/templates/.agents/skills/zaip-aios/SKILL.md +0 -1
  248. package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +1 -0
  249. package/templates/.agents/skills/zaip-skill-config/SKILL.md +1 -1
  250. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +13 -0
  251. package/templates/.agents/skills/zaip-skill-execution/references/autonomous-continuation.md +17 -0
  252. package/templates/.agents/skills/zaip-skill-execution/references/correction-cycle.md +2 -2
  253. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +4 -2
  254. package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +4 -2
  255. package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +2 -2
  256. package/templates/.agents/skills/zaip-skill-github-setup/SKILL.md +2 -2
  257. package/templates/.agents/skills/zaip-skill-move-prd/SKILL.md +4 -0
  258. package/templates/.agents/skills/zaip-skill-move-spec/SKILL.md +4 -0
  259. package/templates/.agents/skills/zaip-skill-prd/SKILL.md +3 -3
  260. package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +15 -8
  261. package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +13 -12
  262. package/templates/.agents/skills/zaip-skill-setup/SKILL.md +50 -13
  263. package/templates/.agents/skills/zaip-skill-setup/agents/openai.yaml +2 -2
  264. package/templates/.agents/skills/zaip-skill-spec/SKILL.md +2 -2
  265. package/templates/.agents/skills/zaip-skill-update-version-doc/SKILL.md +39 -0
  266. package/templates/.agents/skills/zaip-skill-update-version-doc/agents/openai.yaml +4 -0
  267. package/templates/.agents/skills/zaip-skill-update-version-doc/scripts/update-version-doc.mjs +21 -0
  268. package/templates/.agents/skills/zaip-skill-update-version-doc/scripts/update-version-doc.test.mjs +32 -0
  269. package/templates/.agents/zaip-aios/README.md +2 -1
  270. package/templates/.agents/zaip-aios/VERSION +1 -1
  271. package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +7 -3
  272. package/templates/template-manifest.json +436 -256
  273. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-06__WZco.js +0 -68
  274. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Cmlx8OYH.css +0 -1
  275. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DqZKJS8y.js +0 -2
  276. package/templates/.agents/design/apps/catalog/dist/assets/index-BEmIE7WE.css +0 -1
  277. package/templates/.agents/design/apps/catalog/dist/assets/index-BJV597iq.js +0 -72
  278. package/templates/.agents/design/apps/catalog/dist/assets/index-B_WhrCZe.js +0 -72
  279. package/templates/.agents/design/apps/catalog/dist/assets/index-CqqYWY2f.js +0 -9
  280. package/templates/.agents/design/apps/catalog/dist/assets/index-CqtYXZfV.js +0 -72
  281. package/templates/.agents/design/apps/catalog/dist/assets/index-D9pj7Jlf.js +0 -9
  282. package/templates/.agents/design/apps/catalog/dist/assets/index-i_PO2k9R.js +0 -9
  283. package/templates/.agents/design/apps/catalog/dist/storybook/assets/CatalogShell-Cstn1UwA.js +0 -1
  284. package/templates/.agents/design/apps/catalog/dist/storybook/assets/Components.stories-D1WopB2L.js +0 -137
  285. package/templates/.agents/design/apps/catalog/dist/storybook/assets/DesignSystem.stories-DQ9PJ3N3.js +0 -1
  286. package/templates/.agents/design/apps/catalog/dist/storybook/assets/formatter-L2YTDE3Q-D0OSgxWz.js +0 -1
  287. package/templates/.agents/design/apps/catalog/dist/storybook/assets/iframe-BEmIE7WE.css +0 -1
  288. package/templates/.agents/design/apps/catalog/dist/storybook/assets/react-C3tkVMIp.js +0 -1
@@ -1,13 +1,16 @@
1
1
  import { randomBytes } from "node:crypto";
2
2
  import { readFile } from "node:fs/promises";
3
- import { resolve } from "node:path";
3
+ import { basename, resolve } from "node:path";
4
4
  import { serve } from "@hono/node-server";
5
5
  import { serveStatic } from "@hono/node-server/serve-static";
6
6
  import { WorkspaceFileSystem, type WorkspaceLayout } from "@zaip-ai/core";
7
7
  import { fxRateSchema, PricingRepository, pricingCatalogSchema } from "@zaip-ai/costs";
8
8
  import { type Context, Hono } from "hono";
9
9
  import { getCookie, setCookie } from "hono/cookie";
10
- import { captureActiveCodexTelemetry } from "./active-codex-telemetry.js";
10
+ import {
11
+ type ActiveCodexTelemetryCapture,
12
+ captureActiveCodexTelemetry,
13
+ } from "./active-codex-telemetry.js";
11
14
  import { runAgentAdapterSync } from "./agent-adapter-sync.js";
12
15
  import {
13
16
  type AgentAdapterSyncResult,
@@ -30,6 +33,7 @@ import {
30
33
  requireV2Layout,
31
34
  V2WorkspaceRequiredError,
32
35
  } from "./server-http-contracts.js";
36
+ import { lifecycleManifestState } from "./server-lifecycle-diagnostics.js";
33
37
  import { registerOperationsRoutes } from "./server-operations-routes.js";
34
38
  import { projectionPeriodFilter } from "./server-period.js";
35
39
  import { buildFirstFoldQuickProjection, dashboardSnapshot } from "./server-read-projections.js";
@@ -131,9 +135,8 @@ function shouldBootstrapBrowserSession(context: Context): boolean {
131
135
  */
132
136
 
133
137
  /**
134
- * SQLite's files snapshot intentionally excludes derived lifecycle manifests.
135
- * Build the Operations first fold from its canonical SQL views instead of
136
- * treating a missing manifest as a broken workspace.
138
+ * SQLite snapshots intentionally exclude derived lifecycle manifests. Manifest
139
+ * health is therefore always read from the canonical filesystem.
137
140
  */
138
141
 
139
142
  export function createDashboardApp(
@@ -162,6 +165,8 @@ export function createDashboardApp(
162
165
  if (isSqliteSnapshot) await refreshSqliteSnapshotInWorker(workspaceRoot, filesystem);
163
166
  });
164
167
  const workspaceKey = dashboardWorkspaceKey(workspaceRoot);
168
+ const workspace = resolve(workspaceRoot);
169
+ const workspaceName = basename(workspace);
165
170
  const syncAgentAdapters = options.syncAgentAdapters ?? (() => runAgentAdapterSync(workspaceRoot));
166
171
  let catalogWriteTail = Promise.resolve();
167
172
  type DashboardSnapshot = Awaited<ReturnType<typeof dashboardSnapshot>>;
@@ -213,6 +218,7 @@ export function createDashboardApp(
213
218
  let observedSnapshotRevision: string | null = null;
214
219
  const projectionRefreshDiagnostics = createProjectionRefreshDiagnostics();
215
220
  let activeCaptureFailure: { code: string; occurred_at: string; cause: string } | null = null;
221
+ let activeCapture: ActiveCodexTelemetryCapture | null = null;
216
222
  let projectionRefreshInFlight: Promise<void> | null = null;
217
223
  let projectionRefreshRequested = false;
218
224
  const rebuildProjection = async () => {
@@ -263,7 +269,8 @@ export function createDashboardApp(
263
269
  ? { captureActiveTelemetry: () => captureActiveCodexTelemetry(workspaceRoot) }
264
270
  : {}),
265
271
  onRefreshFailure: projectionRefreshDiagnostics.record,
266
- onCaptureSuccess: () => {
272
+ onCaptureSuccess: (result) => {
273
+ activeCapture = result;
267
274
  activeCaptureFailure = null;
268
275
  },
269
276
  onCaptureFailure: (error) => {
@@ -403,20 +410,30 @@ export function createDashboardApp(
403
410
  registerBrowserLeaseRoute(app, API_PREFIX, options.launcherOwned === true);
404
411
  app.on(["GET", "HEAD"], `${API_PREFIX}/health`, async (context) => {
405
412
  try {
406
- const layout = await readLayout();
413
+ const [layout, manifestState] = await Promise.all([
414
+ readLayout(),
415
+ lifecycleManifestState(canonicalFilesystem),
416
+ ]);
407
417
  return headOrJson(context, {
408
418
  kind: RUNTIME_KIND,
409
419
  workspaceKey,
420
+ workspace,
421
+ workspace_name: workspaceName,
422
+ server_pid: process.pid,
410
423
  service: "zaip-aios-dashboard",
411
424
  status:
412
- activeCaptureFailure === null ? projectionRefreshDiagnostics.healthStatus : "degraded",
425
+ manifestState === "initialized" && activeCaptureFailure === null
426
+ ? projectionRefreshDiagnostics.healthStatus
427
+ : "degraded",
413
428
  api_version: 2,
414
429
  workspace_layout: layout.version,
430
+ lifecycle_manifest_state: manifestState,
415
431
  read_only: true,
416
432
  storage: isSqliteSnapshot ? filesystem.metadata() : { storage_mode: "filesystem" },
417
433
  snapshot_state: snapshotState,
418
434
  projection_refresh_failure: projectionRefreshDiagnostics.failure,
419
435
  active_capture_failure: activeCaptureFailure,
436
+ active_capture: activeCapture,
420
437
  });
421
438
  } catch (error) {
422
439
  return headOrJson(
@@ -424,6 +441,9 @@ export function createDashboardApp(
424
441
  {
425
442
  kind: RUNTIME_KIND,
426
443
  workspaceKey,
444
+ workspace,
445
+ workspace_name: workspaceName,
446
+ server_pid: process.pid,
427
447
  service: "zaip-aios-dashboard",
428
448
  status: "unavailable",
429
449
  api_version: 2,
@@ -438,7 +458,12 @@ export function createDashboardApp(
438
458
  // intentionally remains a lightweight process/layout probe.
439
459
  app.on(["GET", "HEAD"], `${API_PREFIX}/ready`, async (context) => {
440
460
  try {
441
- const layout = await readLayout();
461
+ const [layout, manifestState] = await Promise.all([
462
+ readLayout(),
463
+ lifecycleManifestState(canonicalFilesystem),
464
+ ]);
465
+ const readinessStatus =
466
+ manifestState === "initialized" && activeCaptureFailure === null ? "ready" : "degraded";
442
467
  if (isSqliteSnapshot) {
443
468
  const revision = readCommittedSnapshotRevision(workspaceRoot);
444
469
  if (observedSnapshotRevision !== null && observedSnapshotRevision !== revision) {
@@ -453,8 +478,12 @@ export function createDashboardApp(
453
478
  return headOrJson(context, {
454
479
  kind: RUNTIME_KIND,
455
480
  workspaceKey,
456
- status: "ready",
481
+ workspace,
482
+ workspace_name: workspaceName,
483
+ server_pid: process.pid,
484
+ status: readinessStatus,
457
485
  workspace_layout: layout.version,
486
+ lifecycle_manifest_state: manifestState,
458
487
  storage_mode: metadata.storage_mode,
459
488
  activity_count: metadata.activity_count,
460
489
  // Readiness is only an immutable-generation probe. The default
@@ -464,6 +493,7 @@ export function createDashboardApp(
464
493
  snapshot_state: snapshotState,
465
494
  projection_refresh_failure: projectionRefreshDiagnostics.failure,
466
495
  active_capture_failure: activeCaptureFailure,
496
+ active_capture: activeCapture,
467
497
  snapshot_revision: revision,
468
498
  });
469
499
  }
@@ -474,8 +504,13 @@ export function createDashboardApp(
474
504
  return headOrJson(context, {
475
505
  kind: RUNTIME_KIND,
476
506
  workspaceKey,
477
- status: "ready",
507
+ workspace,
508
+ workspace_name: workspaceName,
509
+ server_pid: process.pid,
510
+ status: readinessStatus,
511
+ lifecycle_manifest_state: manifestState,
478
512
  source_latest_at: projection.summary.source_latest_at,
513
+ active_capture: activeCapture,
479
514
  });
480
515
  } catch (error) {
481
516
  return headOrJson(
@@ -0,0 +1,188 @@
1
+ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { expect, it } from "vitest";
4
+ import { prepareMultiProviderFixture } from "./sqlite-read-model-multi-provider-fixture.js";
5
+ import { rebuildSqliteReadModel, SqliteReadModelFileSystem } from "./sqlite-read-model.js";
6
+
7
+ it.each([
8
+ "draft",
9
+ "planned",
10
+ "executing",
11
+ "verifying",
12
+ "completed",
13
+ "blocked",
14
+ "cancelled",
15
+ "failed",
16
+ ])("preserves measured time, tokens and cost across all cost groupings for canonical Task status %s", async (status) => {
17
+ const parent = resolve(import.meta.dirname, "../../../../../../.tmp/sqlite-read-model-tests");
18
+ await mkdir(parent, { recursive: true });
19
+ const root = await mkdtemp(join(parent, "cost-filter-matrix-"));
20
+ let fs: SqliteReadModelFileSystem | undefined;
21
+ try {
22
+ const { started, usage, finished } = await prepareMultiProviderFixture(root);
23
+ await mkdir(join(root, ".agents/records/tasks/2026/08"), { recursive: true });
24
+ for (const [id, priority] of [
25
+ ["TASK-MULTI", "high"],
26
+ ["TASK-LOW", "low"],
27
+ ]) {
28
+ await writeFile(
29
+ join(root, `.agents/records/tasks/2026/08/${id}.md`),
30
+ `---\nid: ${id}\ntitle: ${id}\nstatus: ${priority === "low" ? status : "completed"}\npriority: ${priority}\nrisk: standard\ncreated_at: 2026-08-04T12:00:00.000Z\n---\n`,
31
+ );
32
+ }
33
+ const events = [
34
+ {
35
+ ...started,
36
+ task_id: "TASK-LOW",
37
+ work_type: "rework",
38
+ agent_invocation_id: "AINV-LOW",
39
+ root_agent_invocation_id: "AINV-LOW",
40
+ execution_id: "EXEC-LOW",
41
+ conversation_id: "CONV-LOW",
42
+ },
43
+ usage(2, "openai", "gpt-a", 7, 3.5),
44
+ { ...finished, sequence: 3 },
45
+ ].map((event, index) => ({
46
+ ...event,
47
+ run_id: "RUN-LOW",
48
+ event_id: `RUN-LOW:${index + 1}`,
49
+ occurred_at: index === 0 ? "2026-08-04T18:00:00.000Z" : "2026-08-04T18:01:00.000Z",
50
+ ...(event.type === "usage.recorded"
51
+ ? {
52
+ source_started_at: "2026-08-04T18:00:00.000Z",
53
+ source_finished_at: "2026-08-04T18:01:00.000Z",
54
+ }
55
+ : {}),
56
+ }));
57
+ await writeFile(
58
+ join(root, ".agents/records/runs/2026/08/RUN-LOW.jsonl"),
59
+ events.map((event) => JSON.stringify(event)).join("\n") + "\n",
60
+ );
61
+ await rebuildSqliteReadModel(root);
62
+ fs = new SqliteReadModelFileSystem(root);
63
+ const summary = fs.costMonitorSummaryAggregate({ from: null, to: null });
64
+ // Summary first paint remains aggregate-only, but its controls retain
65
+ // factual filter choices from the same SQLite population.
66
+ expect(summary.run_metrics).toBeUndefined();
67
+ expect(summary.filters_available).toMatchObject({
68
+ providers: expect.arrayContaining(["anthropic", "openai"]),
69
+ agents: expect.arrayContaining(["agent"]),
70
+ models: expect.arrayContaining(["claude-b", "gpt-a"]),
71
+ statuses: expect.arrayContaining(["completed"]),
72
+ priorities: expect.arrayContaining(["high", "low"]),
73
+ risks: expect.arrayContaining(["standard"]),
74
+ phases: expect.arrayContaining(["execution"]),
75
+ origins: expect.arrayContaining(["task"]),
76
+ work_types: expect.arrayContaining(["new", "rework"]),
77
+ });
78
+ const selectedSummary = fs.costMonitorSummaryAggregate({
79
+ from: null,
80
+ to: null,
81
+ priorities: ["low"],
82
+ risks: ["standard"],
83
+ origins: ["task"],
84
+ workTypes: ["rework"],
85
+ });
86
+ expect(selectedSummary.run_metrics).toBeUndefined();
87
+ expect(selectedSummary.filters_available).toMatchObject({
88
+ priorities: ["low"],
89
+ risks: ["standard"],
90
+ origins: ["task"],
91
+ work_types: ["rework"],
92
+ providers: ["openai"],
93
+ models: ["gpt-a"],
94
+ });
95
+ for (const view of [
96
+ "cost_monitor_daily",
97
+ "cost_monitor_monthly",
98
+ "cost_monitor_annual",
99
+ "cost_monitor_tasks",
100
+ "cost_monitor_executions",
101
+ "cost_monitor_conversations",
102
+ "cost_monitor_zaip_agents",
103
+ "cost_monitor_models",
104
+ "cost_monitor_providers",
105
+ "cost_monitor_agent_invocations",
106
+ ] as const) {
107
+ for (const filter of [
108
+ { priority: "low" },
109
+ { workType: "rework" },
110
+ { priority: "low", workType: "rework" },
111
+ { priority: "low", status },
112
+ { priority: "low", risk: "standard", origin: "task", status, workType: "rework" },
113
+ ]) {
114
+ const page = fs.viewPage(view, filter);
115
+ expect(page.total_count, `${view} ${JSON.stringify(filter)}`).toBeGreaterThan(0);
116
+ const tokens = page.rows.reduce((sum, row) => sum + Number(row.total_tokens ?? 0), 0);
117
+ expect(tokens, `${view} ${JSON.stringify(filter)} tokens`).toBe(7);
118
+ for (const [metric, expected] of Object.entries({
119
+ total_duration: 60_000,
120
+ total_cost_usd: 0.7,
121
+ total_cost_brl: 3.5,
122
+ })) {
123
+ const key =
124
+ view === "cost_monitor_agent_invocations"
125
+ ? ({
126
+ total_duration: "duration_ms",
127
+ total_cost_usd: "cost_usd",
128
+ total_cost_brl: "cost_brl",
129
+ }[metric] ?? metric)
130
+ : metric;
131
+ const total = page.rows.reduce((sum, row) => sum + Number(row[key] ?? 0), 0);
132
+ expect(total, `${view} ${JSON.stringify(filter)} ${metric}`).toBeCloseTo(expected, 6);
133
+ }
134
+ expect(fs.viewPage(view, { ...filter, offset: 200 }).rows).toEqual([]);
135
+ }
136
+ expect(fs.viewPage(view, { priority: "high", workType: "rework" }).total_count, view).toBe(0);
137
+ }
138
+ if (status === "blocked") {
139
+ fs.close();
140
+ fs = undefined;
141
+ const unknown = [
142
+ {
143
+ ...started,
144
+ task_id: "TASK-LOW",
145
+ agent_invocation_id: "AINV-GAP",
146
+ root_agent_invocation_id: "AINV-GAP",
147
+ },
148
+ {
149
+ ...usage(2, "openai", "unknown-model", 5, 0),
150
+ source_started_at: undefined,
151
+ source_finished_at: undefined,
152
+ cost: { usd: null, brl: null, fx_rate: null },
153
+ },
154
+ { ...finished, sequence: 3, duration_ms: null, duration_provenance: "unavailable" },
155
+ ].map((event, index) => ({
156
+ ...event,
157
+ run_id: "RUN-GAP",
158
+ event_id: `RUN-GAP:${index + 1}`,
159
+ occurred_at: "2026-08-04T18:02:00.000Z",
160
+ }));
161
+ await writeFile(
162
+ join(root, ".agents/records/runs/2026/08/RUN-GAP.jsonl"),
163
+ unknown.map((event) => JSON.stringify(event)).join("\n") + "\n",
164
+ );
165
+ await rebuildSqliteReadModel(root);
166
+ fs = new SqliteReadModelFileSystem(root);
167
+ for (const view of [
168
+ "cost_monitor_daily",
169
+ "cost_monitor_monthly",
170
+ "cost_monitor_annual",
171
+ ] as const) {
172
+ const page = fs.viewPage(view, { priority: "low" });
173
+ expect(page.rows).toHaveLength(1);
174
+ expect(page.rows[0], view).toMatchObject({
175
+ total_tokens: 12,
176
+ total_duration: 60_000,
177
+ duration_known: 60_000,
178
+ duration_unknown: 1,
179
+ total_cost_brl: 3.5,
180
+ });
181
+ expect(page.totals, view).toMatchObject({ total_duration: 60_000, duration_unknown: 1 });
182
+ }
183
+ }
184
+ } finally {
185
+ fs?.close();
186
+ await rm(root, { recursive: true, force: true });
187
+ }
188
+ });
@@ -0,0 +1,85 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import { expect, it } from "vitest";
3
+ import { buildCostSummaryDetails } from "./sqlite-cost-summary-details.js";
4
+ import type { SqliteQueryContext } from "./sqlite-query-context.js";
5
+
6
+ it("decodes historical filter dimensions once while preserving canonical status and financial totals", () => {
7
+ const database = new DatabaseSync(":memory:");
8
+ const reads = { usage: 0, task: 0 };
9
+ const population = 1000;
10
+ try {
11
+ database.function("observe_usage", (id) => {
12
+ reads.usage += 1;
13
+ return id;
14
+ });
15
+ database.function("observe_task", (id) => {
16
+ reads.task += 1;
17
+ return id;
18
+ });
19
+ database.exec(`
20
+ CREATE TABLE runs (agent_run_id TEXT, task_id TEXT, model TEXT, provider TEXT,
21
+ total_tokens REAL, cost_usd REAL, cost_brl REAL, zaip_agent TEXT,
22
+ status TEXT, phase TEXT, prd_id TEXT, spec_id TEXT, work_key TEXT);
23
+ CREATE TABLE usage_source (id TEXT, provider TEXT, model TEXT);
24
+ CREATE TABLE task_source (id TEXT, status TEXT, priority TEXT, risk TEXT);
25
+ CREATE VIEW invocation_usage AS SELECT observe_usage(id) AS agent_invocation_id,
26
+ provider, model FROM usage_source;
27
+ CREATE VIEW canonical_work_items AS SELECT 'task' AS entity_kind,
28
+ observe_task(id) AS id, status, priority, risk FROM task_source;
29
+ CREATE TABLE cost_invocation_dimension_facts (agent_invocation_id TEXT,
30
+ model TEXT, total_tokens REAL, cost_usd REAL, cost_brl REAL);
31
+ CREATE INDEX cost_facts_invocation ON cost_invocation_dimension_facts(agent_invocation_id);
32
+ `);
33
+ const run = database.prepare(
34
+ "INSERT INTO runs VALUES (?,?,'model-a','provider-a',100,1,5,'rafa','executing','execution',NULL,NULL,'new')",
35
+ );
36
+ const usage = database.prepare("INSERT INTO usage_source VALUES (?,'provider-a','model-a')");
37
+ const task = database.prepare(
38
+ "INSERT INTO task_source VALUES (?,'completed','high','standard')",
39
+ );
40
+ const fact = database.prepare(
41
+ "INSERT INTO cost_invocation_dimension_facts VALUES (?,'model-a',80,0.8,4)",
42
+ );
43
+ for (let index = 0; index < population; index += 1) {
44
+ run.run(`run-${index}`, `task-${index}`);
45
+ usage.run(`run-${index}`);
46
+ task.run(`task-${index}`);
47
+ fact.run(`run-${index}`);
48
+ }
49
+ database.exec(
50
+ "INSERT INTO runs VALUES (NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'blocked','conversation',NULL,NULL,'rework')",
51
+ );
52
+ const details = buildCostSummaryDetails(
53
+ { database } as SqliteQueryContext,
54
+ "WITH selected AS MATERIALIZED (SELECT * FROM runs)",
55
+ [],
56
+ (value) => (typeof value === "number" ? value : 0),
57
+ (value) => (typeof value === "number" ? value : null),
58
+ );
59
+ expect(details.filters_available).toEqual({
60
+ providers: ["provider-a", "unavailable"],
61
+ models: ["model-a", "unavailable"],
62
+ agents: ["rafa"],
63
+ statuses: ["blocked", "completed"],
64
+ priorities: ["high", "none"],
65
+ risks: ["none", "standard"],
66
+ phases: ["conversation", "execution"],
67
+ origins: ["conversation", "task"],
68
+ work_types: ["new", "rework"],
69
+ });
70
+ expect(details.model_groups.find((group) => group.key === "model-a")).toMatchObject({
71
+ total_tokens: population * 80,
72
+ estimated_brl: population * 4,
73
+ });
74
+ expect(details.model_groups.find((group) => group.key === "unavailable")).toMatchObject({
75
+ total_tokens: population * 20,
76
+ estimated_brl: population,
77
+ });
78
+ // Count decoded rows, not elapsed time: an inlined view causes quadratic
79
+ // nested scans even on a fast machine and must fail this regression.
80
+ expect(reads.usage).toBe(population);
81
+ expect(reads.task).toBe(population);
82
+ } finally {
83
+ database.close();
84
+ }
85
+ });
@@ -0,0 +1,147 @@
1
+ import type { CostSummarySource } from "@zaip-ai/dashboard-cost-monitor/server";
2
+ import type { SqliteQueryContext } from "./sqlite-query-context.js";
3
+
4
+ type NumberValue = (value: unknown) => number;
5
+ type NullableValue = (value: unknown) => number | null;
6
+ type CostSummaryDetails = {
7
+ model_groups: NonNullable<CostSummarySource["model_groups"]>;
8
+ filters_available: NonNullable<CostSummarySource["filters_available"]>;
9
+ };
10
+
11
+ export function buildCostSummaryDetails(
12
+ context: SqliteQueryContext,
13
+ selected: string,
14
+ values: readonly (string | number | null)[],
15
+ number: NumberValue,
16
+ nullable: NullableValue,
17
+ ): CostSummaryDetails {
18
+ const summaryModelRows = context.database
19
+ .prepare(`${selected},
20
+ segment_totals AS (
21
+ SELECT agent_invocation_id, SUM(total_tokens) AS total_tokens,
22
+ SUM(cost_usd) AS cost_usd, SUM(cost_brl) AS cost_brl
23
+ FROM cost_invocation_dimension_facts
24
+ WHERE total_tokens IS NOT NULL OR cost_usd IS NOT NULL OR cost_brl IS NOT NULL
25
+ GROUP BY agent_invocation_id
26
+ ), components AS (
27
+ -- Agent facts can contain several observed models. Attribute their
28
+ -- financial components to the model segment, never to a mixed parent.
29
+ SELECT CASE WHEN f.model IS NULL OR trim(f.model) = '' OR lower(f.model) IN ('unavailable', 'unknown', 'mixed')
30
+ THEN 'unavailable' ELSE f.model END AS key,
31
+ SUM(f.total_tokens) AS total_tokens, SUM(f.cost_usd) AS total_cost_usd,
32
+ SUM(f.cost_brl) AS total_cost_brl
33
+ FROM selected s JOIN cost_invocation_dimension_facts f
34
+ ON f.agent_invocation_id=s.agent_run_id
35
+ WHERE s.agent_run_id IS NOT NULL
36
+ GROUP BY key
37
+ UNION ALL
38
+ -- Non-agent financial facts have no invocation segments, so their
39
+ -- observed model remains the only factual dimension.
40
+ SELECT CASE WHEN model IS NULL OR trim(model) = '' OR lower(model) IN ('unavailable', 'unknown', 'mixed')
41
+ THEN 'unavailable' ELSE model END AS key,
42
+ SUM(total_tokens), SUM(cost_usd), SUM(cost_brl)
43
+ FROM selected WHERE agent_run_id IS NULL GROUP BY key
44
+ UNION ALL
45
+ -- Preserve any consolidated invocation remainder as Sem dimensão so
46
+ -- the model chart reconciles to the same financial population.
47
+ SELECT 'unavailable' AS key,
48
+ SUM(s.total_tokens - COALESCE(st.total_tokens, 0)),
49
+ SUM(s.cost_usd - COALESCE(st.cost_usd, 0)),
50
+ SUM(s.cost_brl - COALESCE(st.cost_brl, 0))
51
+ FROM selected s LEFT JOIN segment_totals st ON st.agent_invocation_id=s.agent_run_id
52
+ WHERE s.agent_run_id IS NOT NULL
53
+ AND (s.total_tokens <> COALESCE(st.total_tokens, 0)
54
+ OR s.cost_usd <> COALESCE(st.cost_usd, 0)
55
+ OR s.cost_brl <> COALESCE(st.cost_brl, 0))
56
+ )
57
+ SELECT key, 0 AS invocation_count, NULL AS task_count,
58
+ NULL AS total_duration, 0 AS duration_unknown, 0 AS duration_known,
59
+ 0 AS source_event_count, SUM(total_tokens) AS total_tokens,
60
+ SUM(total_cost_usd) AS total_cost_usd, SUM(total_cost_brl) AS total_cost_brl
61
+ FROM components GROUP BY key ORDER BY total_cost_brl DESC, key`)
62
+ .all(...values) as Array<Record<string, unknown>>;
63
+ const model_groups = summaryModelRows.map((row) => {
64
+ const duration = nullable(row.total_duration);
65
+ const durationUnknown = number(row.duration_unknown);
66
+ const durationKnown = nullable(row.duration_known) ?? duration ?? 0;
67
+ return {
68
+ key: String(row.key ?? "unavailable"),
69
+ label: String(row.label ?? row.key ?? "unavailable"),
70
+ latest_started_at: "",
71
+ run_count: number(row.invocation_count),
72
+ task_count: nullable(row.task_count),
73
+ prd_count: 0,
74
+ spec_count: 0,
75
+ evidence_count: 0,
76
+ test_count: 0,
77
+ event_count: number(row.source_event_count),
78
+ total_tokens: nullable(row.total_tokens),
79
+ estimated_usd: nullable(row.total_cost_usd),
80
+ estimated_brl: nullable(row.total_cost_brl),
81
+ duration_ms: duration,
82
+ duration: {
83
+ known_sum: durationKnown,
84
+ unknown: durationUnknown,
85
+ complete: durationUnknown === 0,
86
+ coverage_ratio: durationUnknown === 0 ? 1 : 0,
87
+ },
88
+ coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
89
+ };
90
+ });
91
+ const availabilityRows = context.database
92
+ .prepare(`${selected},
93
+ usage AS MATERIALIZED (
94
+ SELECT agent_invocation_id, provider, model FROM invocation_usage
95
+ ), canonical_tasks AS MATERIALIZED (
96
+ SELECT id, status, priority, risk FROM canonical_work_items WHERE entity_kind='task'
97
+ ), dimensions AS (
98
+ SELECT 'providers' AS dimension, COALESCE(NULLIF(trim(u.provider), ''), 'unavailable') AS value
99
+ FROM selected s JOIN usage u ON u.agent_invocation_id=s.agent_run_id
100
+ UNION ALL
101
+ SELECT 'models', COALESCE(NULLIF(trim(u.model), ''), 'unavailable')
102
+ FROM selected s JOIN usage u ON u.agent_invocation_id=s.agent_run_id
103
+ UNION ALL
104
+ SELECT 'providers', COALESCE(NULLIF(trim(s.provider), ''), 'unavailable')
105
+ FROM selected s WHERE s.agent_run_id IS NULL
106
+ UNION ALL
107
+ SELECT 'models', COALESCE(NULLIF(trim(s.model), ''), 'unavailable')
108
+ FROM selected s WHERE s.agent_run_id IS NULL
109
+ UNION ALL
110
+ SELECT 'agents', NULLIF(trim(s.zaip_agent), '') FROM selected s
111
+ UNION ALL
112
+ SELECT 'statuses', COALESCE(NULLIF(trim(task.status), ''), NULLIF(trim(s.status), ''), 'none')
113
+ FROM selected s LEFT JOIN canonical_tasks task ON task.id=s.task_id
114
+ UNION ALL
115
+ SELECT 'priorities', COALESCE(NULLIF(trim(task.priority), ''), 'none')
116
+ FROM selected s LEFT JOIN canonical_tasks task ON task.id=s.task_id
117
+ UNION ALL
118
+ SELECT 'risks', COALESCE(NULLIF(trim(task.risk), ''), 'none')
119
+ FROM selected s LEFT JOIN canonical_tasks task ON task.id=s.task_id
120
+ UNION ALL
121
+ SELECT 'phases', NULLIF(trim(s.phase), '') FROM selected s
122
+ UNION ALL
123
+ SELECT 'origins', CASE WHEN s.prd_id IS NOT NULL THEN 'prd'
124
+ WHEN s.spec_id IS NOT NULL THEN 'spec' WHEN s.task_id IS NOT NULL THEN 'task'
125
+ ELSE 'conversation' END FROM selected s
126
+ UNION ALL
127
+ SELECT 'work_types', NULLIF(trim(s.work_key), '') FROM selected s
128
+ ) SELECT dimension, value FROM dimensions WHERE value IS NOT NULL GROUP BY dimension, value
129
+ ORDER BY dimension, value`)
130
+ .all(...values) as Array<{ dimension: string; value: string }>;
131
+ const filters_available: Required<NonNullable<CostSummarySource["filters_available"]>> = {
132
+ providers: [],
133
+ agents: [],
134
+ models: [],
135
+ statuses: [],
136
+ priorities: [],
137
+ risks: [],
138
+ phases: [],
139
+ origins: [],
140
+ work_types: [],
141
+ };
142
+ for (const row of availabilityRows) {
143
+ const dimension = row.dimension as keyof typeof filters_available;
144
+ if (dimension in filters_available) filters_available[dimension].push(row.value);
145
+ }
146
+ return { model_groups, filters_available };
147
+ }
@@ -0,0 +1,94 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import { describe, expect, it } from "vitest";
3
+ import {
4
+ hasReconciledMacroDistributions,
5
+ readFirstFoldAllTime,
6
+ } from "./sqlite-first-fold-cache.js";
7
+ import type { SqliteFirstFoldAllTime } from "./sqlite-read-model-first-fold-types.js";
8
+
9
+ function cachedFirstFold(
10
+ specs: { entityCount: number; statusCount: number; classificationCount: number },
11
+ prds: { entityCount: number; statusCount: number; classificationCount: number },
12
+ ) {
13
+ const macro = (item: {
14
+ entityCount: number;
15
+ statusCount: number;
16
+ classificationCount: number;
17
+ }) => ({
18
+ entity_count: item.entityCount,
19
+ status_counts: { executing: item.statusCount },
20
+ classification_counts: { structured: item.classificationCount },
21
+ });
22
+ return {
23
+ macro_metrics: { specs: macro(specs), prds: macro(prds) },
24
+ } as unknown as SqliteFirstFoldAllTime;
25
+ }
26
+
27
+ describe("first-fold all-time cache", () => {
28
+ it("rejects a legacy macro cache that would render zero panels beside populated cards", () => {
29
+ expect(
30
+ hasReconciledMacroDistributions(
31
+ cachedFirstFold(
32
+ { entityCount: 66, statusCount: 0, classificationCount: 0 },
33
+ { entityCount: 16, statusCount: 0, classificationCount: 0 },
34
+ ),
35
+ ),
36
+ ).toBe(false);
37
+ });
38
+
39
+ it("accepts fully reconciled SPEC and PRD panels", () => {
40
+ expect(
41
+ hasReconciledMacroDistributions(
42
+ cachedFirstFold(
43
+ { entityCount: 66, statusCount: 66, classificationCount: 66 },
44
+ { entityCount: 16, statusCount: 16, classificationCount: 16 },
45
+ ),
46
+ ),
47
+ ).toBe(true);
48
+ });
49
+
50
+ it("rejects malformed legacy count maps before summing them", () => {
51
+ const legacy = cachedFirstFold(
52
+ { entityCount: 1, statusCount: 1, classificationCount: 1 },
53
+ { entityCount: 1, statusCount: 1, classificationCount: 1 },
54
+ ) as unknown as { macro_metrics: { specs: { status_counts: unknown } } };
55
+ legacy.macro_metrics.specs.status_counts = undefined;
56
+
57
+ expect(hasReconciledMacroDistributions(legacy as unknown as SqliteFirstFoldAllTime)).toBe(
58
+ false,
59
+ );
60
+ });
61
+
62
+ it("recomputes a persisted legacy payload whose macro panels are missing", () => {
63
+ const database = new DatabaseSync(":memory:");
64
+ try {
65
+ database.exec(`
66
+ CREATE TABLE zaip_aios_activities (payload_type TEXT, payload_json TEXT, recorded_at TEXT);
67
+ INSERT INTO zaip_aios_activities VALUES ('first_fold_all_time_cache', '{"aggregate":{}}', '2026-09-15T00:00:00.000Z');
68
+ CREATE VIEW zaip_vw_first_fold_overview_all_time AS SELECT 0 AS task_count, 0 AS completed_task_count, 1 AS spec_count, 0 AS completed_spec_count, 1 AS prd_count, 0 AS completed_prd_count, 0 AS total_run_count, 0 AS agent_invocation_count, NULL AS llm_call_count, NULL AS total_duration_ms, NULL AS total_tokens, NULL AS total_cost_usd, NULL AS total_cost_brl, 0 AS execution_day_count, NULL AS latest_task_created_at, NULL AS start_day, NULL AS end_day;
69
+ CREATE VIEW zaip_vw_first_fold_task_status_all_time AS SELECT 'draft' AS status, 0 AS task_count WHERE 0;
70
+ CREATE VIEW zaip_vw_first_fold_task_risk_all_time AS SELECT 'standard' AS risk, 0 AS task_count WHERE 0;
71
+ CREATE VIEW zaip_vw_first_fold_top_tasks_all_time AS SELECT 1 AS rank WHERE 0;
72
+ CREATE VIEW zaip_vw_first_fold_task_metrics_all_time AS SELECT NULL AS average_duration_ms_per_task, NULL AS average_tokens_per_task, NULL AS average_cost_usd_per_task, NULL AS average_cost_brl_per_task, NULL AS latest_task_created_at;
73
+ CREATE VIEW zaip_vw_first_fold_spec_status_all_time AS SELECT 'executing' AS stage, 1 AS entity_count;
74
+ CREATE VIEW zaip_vw_first_fold_prd_status_all_time AS SELECT 'executing' AS stage, 1 AS entity_count;
75
+ CREATE VIEW zaip_vw_first_fold_spec_classification_all_time AS SELECT 'structured' AS classification, 1 AS entity_count;
76
+ CREATE VIEW zaip_vw_first_fold_prd_classification_all_time AS SELECT 'structured' AS classification, 1 AS entity_count;
77
+ CREATE VIEW zaip_vw_first_fold_spec_metrics_all_time AS SELECT 1 AS entity_count, 0 AS total_run_count, NULL AS total_duration_ms, NULL AS total_tokens, NULL AS total_cost_usd, NULL AS total_cost_brl, NULL AS average_duration_ms, NULL AS average_tokens, NULL AS average_cost_usd, NULL AS average_cost_brl, NULL AS latest_created_at;
78
+ CREATE VIEW zaip_vw_first_fold_prd_metrics_all_time AS SELECT 1 AS entity_count, 0 AS total_run_count, NULL AS total_duration_ms, NULL AS total_tokens, NULL AS total_cost_usd, NULL AS total_cost_brl, NULL AS average_duration_ms, NULL AS average_tokens, NULL AS average_cost_usd, NULL AS average_cost_brl, NULL AS latest_created_at;
79
+ CREATE VIEW zaip_vw_first_fold_top_specs_all_time AS SELECT 1 AS rank WHERE 0;
80
+ CREATE VIEW zaip_vw_first_fold_top_prds_all_time AS SELECT 1 AS rank WHERE 0;
81
+ `);
82
+ const rebuilt = readFirstFoldAllTime(database, () => 0);
83
+
84
+ expect(rebuilt.macro_metrics.specs).toMatchObject({
85
+ entity_count: 1,
86
+ status_counts: { executing: 1 },
87
+ classification_counts: { structured: 1 },
88
+ });
89
+ expect(rebuilt.macro_metrics.prds.entity_count).toBe(1);
90
+ } finally {
91
+ database.close();
92
+ }
93
+ });
94
+ });