@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
@@ -24,13 +24,44 @@ function persisted<T>(database: DatabaseSync, payloadType: string): T | null {
24
24
  }
25
25
  }
26
26
 
27
+ /** Reject legacy first-fold payloads that have card totals but no matching macro panels. */
28
+ export function hasReconciledMacroDistributions(value: SqliteFirstFoldAllTime): boolean {
29
+ return (["specs", "prds"] as const).every((kind) => {
30
+ const metric = value.macro_metrics?.[kind];
31
+ if (
32
+ metric === null ||
33
+ metric === undefined ||
34
+ !Number.isSafeInteger(metric.entity_count) ||
35
+ metric.entity_count < 0 ||
36
+ !isCountMap(metric.status_counts) ||
37
+ !isCountMap(metric.classification_counts)
38
+ )
39
+ return false;
40
+ const sum = (counts: Record<string, number>) =>
41
+ Object.values(counts).reduce((total, count) => total + count, 0);
42
+ return (
43
+ sum(metric.status_counts) === metric.entity_count &&
44
+ sum(metric.classification_counts) === metric.entity_count
45
+ );
46
+ });
47
+ }
48
+
49
+ function isCountMap(value: unknown): value is Record<string, number> {
50
+ return (
51
+ value !== null &&
52
+ typeof value === "object" &&
53
+ !Array.isArray(value) &&
54
+ Object.values(value).every((count) => Number.isSafeInteger(count) && count >= 0)
55
+ );
56
+ }
57
+
27
58
  export function readFirstFoldAllTime(
28
59
  database: DatabaseSync,
29
60
  dailyAggregateCount: () => number,
30
61
  viewport?: SqliteFirstFoldViewport,
31
62
  ): SqliteFirstFoldAllTime {
32
63
  const cached = persisted<SqliteFirstFoldAllTime>(database, "first_fold_all_time_cache");
33
- if (cached !== null) return cached;
64
+ if (cached !== null && hasReconciledMacroDistributions(cached)) return cached;
34
65
  const timed = <T>(phase: string, action: () => T) => measureFirstFoldQuery(phase, action);
35
66
  const row =
36
67
  viewport === undefined
@@ -58,59 +89,7 @@ export function readFirstFoldAllTime(
58
89
  .prepare("SELECT * FROM zaip_vw_first_fold_top_tasks_all_time ORDER BY rank")
59
90
  .all() as SqliteFirstFoldAllTime["top_tasks"],
60
91
  );
61
- const readMacroMetrics = (kind: "spec" | "prd") => {
62
- const statuses = timed(
63
- `first_fold_${kind}_status`,
64
- () =>
65
- database
66
- .prepare(`SELECT stage, entity_count FROM zaip_vw_first_fold_${kind}_status_all_time`)
67
- .all() as Array<{ stage: string; entity_count: number }>,
68
- );
69
- const classifications = timed(
70
- `first_fold_${kind}_classification`,
71
- () =>
72
- database
73
- .prepare(
74
- `SELECT classification, entity_count FROM zaip_vw_first_fold_${kind}_classification_all_time`,
75
- )
76
- .all() as Array<{ classification: string; entity_count: number }>,
77
- );
78
- const macro = timed(
79
- `first_fold_${kind}_metrics`,
80
- () =>
81
- database
82
- .prepare(`SELECT * FROM zaip_vw_first_fold_${kind}_metrics_all_time`)
83
- .get() as Record<string, unknown>,
84
- );
85
- const topEntities = timed(
86
- `first_fold_${kind}_top_entities`,
87
- () =>
88
- database
89
- .prepare(`SELECT * FROM zaip_vw_first_fold_top_${kind}s_all_time ORDER BY rank`)
90
- .all() as SqliteFirstFoldAllTime["macro_metrics"]["specs"]["top_entities"],
91
- );
92
- return {
93
- status_counts: Object.fromEntries(
94
- statuses.map((status) => [status.stage, Number(status.entity_count)]),
95
- ),
96
- classification_counts: Object.fromEntries(
97
- classifications.map((item) => [item.classification, Number(item.entity_count)]),
98
- ),
99
- entity_count: number(macro.entity_count),
100
- total_run_count: number(macro.total_run_count),
101
- total_duration_ms: nullableNumber(macro.total_duration_ms),
102
- total_tokens: nullableNumber(macro.total_tokens),
103
- total_cost_usd: nullableNumber(macro.total_cost_usd),
104
- total_cost_brl: nullableNumber(macro.total_cost_brl),
105
- average_duration_ms: nullableNumber(macro.average_duration_ms),
106
- average_tokens: nullableNumber(macro.average_tokens),
107
- average_cost_usd: nullableNumber(macro.average_cost_usd),
108
- average_cost_brl: nullableNumber(macro.average_cost_brl),
109
- latest_created_at:
110
- typeof macro.latest_created_at === "string" ? macro.latest_created_at : null,
111
- top_entities: topEntities,
112
- };
113
- };
92
+
114
93
  return {
115
94
  aggregate: viewport?.aggregate ?? {
116
95
  days:
@@ -180,7 +159,7 @@ export function readFirstFoldAllTime(
180
159
  };
181
160
  })(),
182
161
  top_tasks: topTasks,
183
- macro_metrics: { specs: readMacroMetrics("spec"), prds: readMacroMetrics("prd") },
162
+ macro_metrics: readFirstFoldMacroMetrics(database),
184
163
  };
185
164
  }
186
165
 
@@ -355,3 +334,65 @@ export function readFirstFoldMonthlyQuick(
355
334
  },
356
335
  };
357
336
  }
337
+
338
+ export function readFirstFoldMacroMetrics(
339
+ database: DatabaseSync,
340
+ ): SqliteFirstFoldAllTime["macro_metrics"] {
341
+ const cached = persisted<SqliteFirstFoldAllTime>(database, "first_fold_all_time_cache");
342
+ if (cached !== null && hasReconciledMacroDistributions(cached)) return cached.macro_metrics;
343
+ const timed = <T>(phase: string, action: () => T) => measureFirstFoldQuery(phase, action);
344
+ const readMacroMetrics = (kind: "spec" | "prd") => {
345
+ const statuses = timed(
346
+ `first_fold_${kind}_status`,
347
+ () =>
348
+ database
349
+ .prepare(`SELECT stage, entity_count FROM zaip_vw_first_fold_${kind}_status_all_time`)
350
+ .all() as Array<{ stage: string; entity_count: number }>,
351
+ );
352
+ const classifications = timed(
353
+ `first_fold_${kind}_classification`,
354
+ () =>
355
+ database
356
+ .prepare(
357
+ `SELECT classification, entity_count FROM zaip_vw_first_fold_${kind}_classification_all_time`,
358
+ )
359
+ .all() as Array<{ classification: string; entity_count: number }>,
360
+ );
361
+ const macro = timed(
362
+ `first_fold_${kind}_metrics`,
363
+ () =>
364
+ database
365
+ .prepare(`SELECT * FROM zaip_vw_first_fold_${kind}_metrics_all_time`)
366
+ .get() as Record<string, unknown>,
367
+ );
368
+ const topEntities = timed(
369
+ `first_fold_${kind}_top_entities`,
370
+ () =>
371
+ database
372
+ .prepare(`SELECT * FROM zaip_vw_first_fold_top_${kind}s_all_time ORDER BY rank`)
373
+ .all() as SqliteFirstFoldAllTime["macro_metrics"]["specs"]["top_entities"],
374
+ );
375
+ return {
376
+ status_counts: Object.fromEntries(
377
+ statuses.map((status) => [status.stage, Number(status.entity_count)]),
378
+ ),
379
+ classification_counts: Object.fromEntries(
380
+ classifications.map((item) => [item.classification, Number(item.entity_count)]),
381
+ ),
382
+ entity_count: number(macro.entity_count),
383
+ total_run_count: number(macro.total_run_count),
384
+ total_duration_ms: nullableNumber(macro.total_duration_ms),
385
+ total_tokens: nullableNumber(macro.total_tokens),
386
+ total_cost_usd: nullableNumber(macro.total_cost_usd),
387
+ total_cost_brl: nullableNumber(macro.total_cost_brl),
388
+ average_duration_ms: nullableNumber(macro.average_duration_ms),
389
+ average_tokens: nullableNumber(macro.average_tokens),
390
+ average_cost_usd: nullableNumber(macro.average_cost_usd),
391
+ average_cost_brl: nullableNumber(macro.average_cost_brl),
392
+ latest_created_at:
393
+ typeof macro.latest_created_at === "string" ? macro.latest_created_at : null,
394
+ top_entities: topEntities,
395
+ };
396
+ };
397
+ return { specs: readMacroMetrics("spec"), prds: readMacroMetrics("prd") };
398
+ }
@@ -2,7 +2,9 @@ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
2
  import { join, resolve } from "node:path";
3
3
  import { DatabaseSync } from "node:sqlite";
4
4
  import { afterEach, describe, expect, it, vi } from "vitest";
5
- import { rebuildSqliteReadModel } from "./sqlite-read-model.js";
5
+ import { buildSqliteOperationsProjection } from "./server-read-projections.js";
6
+ import { rebuildSqliteReadModel, SqliteReadModelFileSystem } from "./sqlite-read-model.js";
7
+ import { readModelSchemaVersion } from "./sqlite-read-model-schema.js";
6
8
 
7
9
  const roots: string[] = [];
8
10
 
@@ -22,6 +24,37 @@ afterEach(async () => {
22
24
  });
23
25
 
24
26
  describe("forceCanonical SQLite refresh", () => {
27
+ it("keeps filtered completed cards consistent with legacy delivered macro statuses", async () => {
28
+ const root = await fixture();
29
+ for (const kind of ["spec", "prd"]) {
30
+ const directory = join(root, `.agents/records/${kind}s/2026/08`);
31
+ await mkdir(directory, { recursive: true });
32
+ await writeFile(
33
+ join(directory, `${kind.toUpperCase()}-DELIVERED.md`),
34
+ `---\nid: ${kind.toUpperCase()}-DELIVERED\ntitle: Delivered macro\nstatus: delivered\ncreated_at: 2026-08-03T12:00:00.000Z\n---\n`,
35
+ );
36
+ }
37
+ await rebuildSqliteReadModel(root);
38
+ const filesystem = new SqliteReadModelFileSystem(root);
39
+ try {
40
+ const projection = buildSqliteOperationsProjection(
41
+ filesystem,
42
+ { version: 3 } as Parameters<typeof buildSqliteOperationsProjection>[1],
43
+ { from: "2026-08-01", to: "2026-08-31" },
44
+ {},
45
+ );
46
+ expect(projection.summary.overview_metrics).toMatchObject({
47
+ completed_spec_count: 1,
48
+ completed_prd_count: 1,
49
+ macro_metrics: {
50
+ specs: { status_counts: { completed: 1 } },
51
+ prds: { status_counts: { completed: 1 } },
52
+ },
53
+ });
54
+ } finally {
55
+ filesystem.close();
56
+ }
57
+ });
25
58
  it("bypasses a healthy generation and verifies canonical sources again", async () => {
26
59
  const root = await fixture();
27
60
  vi.spyOn(Date, "now").mockReturnValue(Date.now() + 5_000);
@@ -37,14 +70,20 @@ describe("forceCanonical SQLite refresh", () => {
37
70
  });
38
71
  });
39
72
 
40
- it("rebuilds a generation whose persisted schema marker is incompatible", async () => {
73
+ it("upgrades an old physical projection when the canonical sources are unchanged", async () => {
41
74
  const root = await fixture();
42
75
  const initial = await rebuildSqliteReadModel(root);
43
76
  const database = new DatabaseSync(initial.path);
44
77
  try {
78
+ // Simulate the pre-80 cache that predates macro classification fields.
79
+ // The source fingerprint remains valid, so only the schema contract can
80
+ // cause the next ordinary refresh to rebuild this disposable projection.
81
+ database.exec(
82
+ "DROP TABLE operations_work_projection; CREATE TABLE operations_work_projection (id TEXT);",
83
+ );
45
84
  database
46
85
  .prepare(
47
- "UPDATE zaip_aios_activities SET payload_json=json_set(payload_json, '$.value', 'invalid') WHERE payload_type='metadata' AND activity_key='metadata:schema_version'",
86
+ "UPDATE zaip_aios_activities SET payload_json=json_set(payload_json, '$.value', '79') WHERE payload_type='metadata' AND activity_key='metadata:schema_version'",
48
87
  )
49
88
  .run();
50
89
  } finally {
@@ -54,5 +93,21 @@ describe("forceCanonical SQLite refresh", () => {
54
93
  cache: "rebuilt",
55
94
  path: initial.path,
56
95
  });
96
+ const upgraded = new DatabaseSync(initial.path, { readOnly: true });
97
+ try {
98
+ expect(upgraded.prepare("PRAGMA table_info(operations_work_projection)").all()).toEqual(
99
+ expect.arrayContaining([
100
+ expect.objectContaining({ name: "task_count" }),
101
+ expect.objectContaining({ name: "rework_run_count" }),
102
+ ]),
103
+ );
104
+ expect(
105
+ upgraded
106
+ .prepare("SELECT value FROM zaip_vw_read_model_metadata WHERE key='schema_version'")
107
+ .get(),
108
+ ).toEqual({ value: readModelSchemaVersion });
109
+ } finally {
110
+ upgraded.close();
111
+ }
57
112
  });
58
113
  });
@@ -0,0 +1,172 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import { afterEach, describe, expect, it } from "vitest";
3
+ import { dashboardViewSql } from "./sqlite-schema-dashboard-views.js";
4
+
5
+ describe("vw_macro_classification", () => {
6
+ const databases: DatabaseSync[] = [];
7
+ afterEach(() => {
8
+ databases.splice(0).forEach((database) => {
9
+ database.close();
10
+ });
11
+ });
12
+
13
+ function database() {
14
+ const db = new DatabaseSync(":memory:");
15
+ databases.push(db);
16
+ db.exec(`
17
+ CREATE TABLE canonical_work_items (
18
+ entity_kind TEXT, id TEXT, status TEXT, spec_id TEXT, change_id TEXT, prd_id TEXT
19
+ );
20
+ CREATE TABLE canonical_changes (
21
+ id TEXT, source_type TEXT, source_id TEXT, source_spec_id TEXT,
22
+ source_prd_id TEXT, task_ids_json TEXT
23
+ );
24
+ CREATE TABLE activities (
25
+ spec_id TEXT, prd_id TEXT, task_id TEXT, work_type TEXT, run_role TEXT
26
+ );
27
+ CREATE TABLE work_items (entity_kind TEXT, id TEXT);
28
+ `);
29
+ db.exec(dashboardViewSql);
30
+ return db;
31
+ }
32
+
33
+ it("preserves direct, JSON, duplicate, fallback, completion, and rework classification", () => {
34
+ const db = database();
35
+ db.exec(`
36
+ INSERT INTO work_items VALUES
37
+ ('spec','SPEC-DIRECT'),('prd','PRD-DIRECT'),('spec','SPEC-JSON'),('prd','PRD-JSON'),
38
+ ('spec','SPEC-BOTH'),('prd','PRD-BOTH'),('spec','SPEC-OWN'),('spec','SPEC-HISTORY'),
39
+ ('prd','PRD-HISTORY'),('spec','SPEC-DRAFT'),('prd','PRD-DRAFT'),('spec','SPEC-COMP'),
40
+ ('prd','PRD-COMP'),('spec','SPEC-REWORK'),('prd','PRD-REWORK');
41
+ INSERT INTO canonical_work_items (entity_kind,id,status,spec_id,change_id) VALUES
42
+ ('task','TASK-DIRECT','active',NULL,'CHANGE-DIRECT'),
43
+ ('task','TASK-JSON','active',NULL,NULL),
44
+ ('task','TASK-BOTH','active',NULL,'CHANGE-BOTH'),
45
+ ('task','TASK-OWN','active','SPEC-OWN',NULL),
46
+ ('task','TASK-DRAFT','draft',NULL,'CHANGE-DRAFT'),
47
+ ('task','TASK-COMP','completed',NULL,'CHANGE-COMP');
48
+ INSERT INTO canonical_changes VALUES
49
+ ('CHANGE-DIRECT','spec','SPEC-DIRECT',NULL,'PRD-DIRECT','[]'),
50
+ ('CHANGE-JSON','spec','SPEC-JSON',NULL,'PRD-JSON','["TASK-JSON"]'),
51
+ ('CHANGE-BOTH','spec','SPEC-BOTH',NULL,'PRD-BOTH','["TASK-BOTH"]'),
52
+ ('CHANGE-DRAFT','spec','SPEC-DRAFT',NULL,'PRD-DRAFT','["TASK-DRAFT"]'),
53
+ ('CHANGE-COMP','spec','SPEC-COMP',NULL,'PRD-COMP','[]');
54
+ INSERT INTO activities VALUES
55
+ ('SPEC-HISTORY','PRD-HISTORY','TASK-HISTORY','delivery','root'),
56
+ ('SPEC-DRAFT','PRD-DRAFT','TASK-DRAFT','delivery','root'),
57
+ ('SPEC-REWORK','PRD-REWORK','TASK-REWORK','rework','root'),
58
+ ('SPEC-REWORK','PRD-REWORK','TASK-CHILD','rework','child');
59
+ `);
60
+ const rows = db
61
+ .prepare(`SELECT entity_kind, entity_id, task_count, rework_run_count, completed_task_count
62
+ FROM vw_macro_classification ORDER BY entity_kind, entity_id`)
63
+ .all();
64
+ expect(rows).toEqual([
65
+ {
66
+ entity_kind: "prd",
67
+ entity_id: "PRD-BOTH",
68
+ task_count: 1,
69
+ rework_run_count: 0,
70
+ completed_task_count: 0,
71
+ },
72
+ {
73
+ entity_kind: "prd",
74
+ entity_id: "PRD-COMP",
75
+ task_count: 1,
76
+ rework_run_count: 0,
77
+ completed_task_count: 1,
78
+ },
79
+ {
80
+ entity_kind: "prd",
81
+ entity_id: "PRD-DIRECT",
82
+ task_count: 1,
83
+ rework_run_count: 0,
84
+ completed_task_count: 0,
85
+ },
86
+ {
87
+ entity_kind: "prd",
88
+ entity_id: "PRD-DRAFT",
89
+ task_count: 0,
90
+ rework_run_count: 0,
91
+ completed_task_count: 0,
92
+ },
93
+ {
94
+ entity_kind: "prd",
95
+ entity_id: "PRD-HISTORY",
96
+ task_count: 1,
97
+ rework_run_count: 0,
98
+ completed_task_count: 0,
99
+ },
100
+ {
101
+ entity_kind: "prd",
102
+ entity_id: "PRD-JSON",
103
+ task_count: 1,
104
+ rework_run_count: 0,
105
+ completed_task_count: 0,
106
+ },
107
+ {
108
+ entity_kind: "prd",
109
+ entity_id: "PRD-REWORK",
110
+ task_count: 2,
111
+ rework_run_count: 1,
112
+ completed_task_count: 0,
113
+ },
114
+ {
115
+ entity_kind: "spec",
116
+ entity_id: "SPEC-BOTH",
117
+ task_count: 1,
118
+ rework_run_count: 0,
119
+ completed_task_count: 0,
120
+ },
121
+ {
122
+ entity_kind: "spec",
123
+ entity_id: "SPEC-COMP",
124
+ task_count: 1,
125
+ rework_run_count: 0,
126
+ completed_task_count: 1,
127
+ },
128
+ {
129
+ entity_kind: "spec",
130
+ entity_id: "SPEC-DIRECT",
131
+ task_count: 1,
132
+ rework_run_count: 0,
133
+ completed_task_count: 0,
134
+ },
135
+ {
136
+ entity_kind: "spec",
137
+ entity_id: "SPEC-DRAFT",
138
+ task_count: 0,
139
+ rework_run_count: 0,
140
+ completed_task_count: 0,
141
+ },
142
+ {
143
+ entity_kind: "spec",
144
+ entity_id: "SPEC-HISTORY",
145
+ task_count: 1,
146
+ rework_run_count: 0,
147
+ completed_task_count: 0,
148
+ },
149
+ {
150
+ entity_kind: "spec",
151
+ entity_id: "SPEC-JSON",
152
+ task_count: 1,
153
+ rework_run_count: 0,
154
+ completed_task_count: 0,
155
+ },
156
+ {
157
+ entity_kind: "spec",
158
+ entity_id: "SPEC-OWN",
159
+ task_count: 1,
160
+ rework_run_count: 0,
161
+ completed_task_count: 0,
162
+ },
163
+ {
164
+ entity_kind: "spec",
165
+ entity_id: "SPEC-REWORK",
166
+ task_count: 2,
167
+ rework_run_count: 1,
168
+ completed_task_count: 0,
169
+ },
170
+ ]);
171
+ });
172
+ });
@@ -380,7 +380,7 @@ export function materializeDashboardProjections(input: ProjectionInput) {
380
380
  );
381
381
  persistPayload(
382
382
  "work_item",
383
- "SELECT entity_kind || ':' || id AS row_key, json_object('entity_kind', entity_kind, 'id', id, 'title', title, 'status', status, 'stage', stage, 'risk', risk, 'spec_id', spec_id, 'change_id', change_id, 'creation_run_id', creation_run_id, 'completed_run_id', completed_run_id, 'occurred_at', occurred_at, 'occurred_day_sp', occurred_day_sp) AS payload_json FROM canonical_work_items",
383
+ "SELECT entity_kind || ':' || id AS row_key, json_object('entity_kind', entity_kind, 'id', id, 'title', title, 'status', status, 'stage', stage, 'risk', risk, 'priority', priority, 'spec_id', spec_id, 'prd_id', prd_id, 'change_id', change_id, 'creation_run_id', creation_run_id, 'completed_run_id', completed_run_id, 'occurred_at', occurred_at, 'occurred_day_sp', occurred_day_sp) AS payload_json FROM canonical_work_items",
384
384
  );
385
385
  persistPayload(
386
386
  "execution",
@@ -15,13 +15,16 @@ export function materializeOperationsWorkProjection(database: DatabaseSync): voi
15
15
  FROM work_items canonical
16
16
  LEFT JOIN fallback_changes fallback ON fallback.task_id=canonical.id AND fallback.preference=1
17
17
  )
18
- SELECT summary.*, canonical.stage, canonical.spec_id,
18
+ SELECT summary.*, canonical.stage, canonical.prd_id,
19
+ COALESCE(canonical.spec_id, change.source_spec_id, CASE WHEN change.source_type='spec' THEN change.source_id END) AS spec_id,
19
20
  canonical.resolved_change_id AS change_id, change.source_type AS origin,
20
21
  CASE WHEN canonical.entity_kind='task' THEN CASE WHEN canonical.spec_id IS NOT NULL OR COALESCE(change.source_type IN ('spec','prd'), 0) THEN 'task' ELSE 'standalone-task' END ELSE canonical.entity_kind END AS kind
21
22
  FROM zaip_vw_operations_work_kanban summary
22
23
  JOIN resolved canonical ON canonical.entity_kind=summary.entity_kind AND canonical.id=summary.id
23
24
  LEFT JOIN changes change ON change.id=canonical.resolved_change_id`;
24
25
  database.exec(`
26
+ -- Schema compatibility is checked before incremental refresh. Preserve
27
+ -- this table and its indexes; only replace the projected rows here.
25
28
  CREATE TABLE IF NOT EXISTS operations_work_projection AS ${select} LIMIT 0;
26
29
  DELETE FROM operations_work_projection;
27
30
  INSERT INTO operations_work_projection ${select};
@@ -10,10 +10,10 @@ import {
10
10
  function page(input: Parameters<typeof operationsWorkListSql>[0]) {
11
11
  const database = new DatabaseSync(":memory:");
12
12
  database.exec(`
13
- CREATE TABLE canonical_work_items (entity_kind TEXT, id TEXT, stage TEXT, risk TEXT, spec_id TEXT, change_id TEXT, occurred_day_sp TEXT);
14
- CREATE TABLE canonical_changes (id TEXT, source_type TEXT, task_ids_json TEXT, created_at TEXT);
13
+ CREATE TABLE canonical_work_items (entity_kind TEXT, id TEXT, stage TEXT, risk TEXT, spec_id TEXT, change_id TEXT, occurred_day_sp TEXT, prd_id TEXT);
14
+ CREATE TABLE canonical_changes (id TEXT, source_type TEXT, task_ids_json TEXT, created_at TEXT, source_spec_id TEXT, source_id TEXT);
15
15
  CREATE TABLE operations_work_kanban (entity_kind TEXT, id TEXT, title TEXT, status TEXT, risk TEXT, occurred_at TEXT, occurred_day_sp TEXT);
16
- INSERT INTO canonical_work_items VALUES
16
+ INSERT INTO canonical_work_items (entity_kind,id,stage,risk,spec_id,change_id,occurred_day_sp) VALUES
17
17
  ('task','TASK-PRD','executing','standard','SPEC-1','CHG-PRD','2026-08-01'),
18
18
  ('task','TASK-SPEC','ready','standard','SPEC-1',NULL,'2026-08-02'),
19
19
  ('task','TASK-STANDALONE','executing','standard',NULL,NULL,'2026-08-03'),
@@ -21,7 +21,7 @@ function page(input: Parameters<typeof operationsWorkListSql>[0]) {
21
21
  ('prd','PRD-1','definition','standard',NULL,NULL,'2026-08-04'),
22
22
  ('spec','SPEC-1','planning','standard',NULL,NULL,'2026-08-05');
23
23
  INSERT INTO operations_work_kanban SELECT entity_kind,id,id,'active',risk,occurred_day_sp || 'T00:00:00Z',occurred_day_sp FROM canonical_work_items;
24
- INSERT INTO canonical_changes VALUES
24
+ INSERT INTO canonical_changes (id,source_type,task_ids_json,created_at) VALUES
25
25
  ('CHG-PRD','prd','["TASK-PRD"]','2026-08-04T00:00:00Z'),
26
26
  ('CHG-SPEC','spec','["TASK-ORIGIN-SPEC"]','2026-08-04T00:00:00Z'),
27
27
  ('CHG-NEWER','spec','["TASK-PRD"]','2026-08-05T00:00:00Z');
@@ -234,10 +234,10 @@ describe("operations work list SQL", () => {
234
234
  it("keeps the legacy view fallback when no physical projection exists", () => {
235
235
  const database = new DatabaseSync(":memory:");
236
236
  database.exec(`
237
- CREATE TABLE canonical_work_items (entity_kind TEXT, id TEXT, stage TEXT, risk TEXT, spec_id TEXT, change_id TEXT, occurred_day_sp TEXT);
238
- CREATE TABLE canonical_changes (id TEXT, source_type TEXT, task_ids_json TEXT, created_at TEXT);
237
+ CREATE TABLE canonical_work_items (entity_kind TEXT, id TEXT, stage TEXT, risk TEXT, spec_id TEXT, change_id TEXT, occurred_day_sp TEXT, prd_id TEXT);
238
+ CREATE TABLE canonical_changes (id TEXT, source_type TEXT, task_ids_json TEXT, created_at TEXT, source_spec_id TEXT, source_id TEXT);
239
239
  CREATE TABLE operations_work_kanban (entity_kind TEXT, id TEXT, title TEXT, status TEXT, risk TEXT, occurred_at TEXT, occurred_day_sp TEXT);
240
- INSERT INTO canonical_work_items VALUES ('task', 'TASK-LEGACY', 'ready', 'standard', NULL, NULL, '2026-08-01');
240
+ INSERT INTO canonical_work_items (entity_kind,id,stage,risk,spec_id,change_id,occurred_day_sp) VALUES ('task', 'TASK-LEGACY', 'ready', 'standard', NULL, NULL, '2026-08-01');
241
241
  INSERT INTO operations_work_kanban VALUES ('task', 'TASK-LEGACY', 'Legacy task', 'active', 'standard', '2026-08-01T00:00:00Z', '2026-08-01');
242
242
  `);
243
243
  expect(operationsWorkListSqlPage(database, { limit: 10 })).toMatchObject({
@@ -172,7 +172,8 @@ export function operationsWorkListSql(input: OperationsWorkListQuery) {
172
172
  source,
173
173
  where: clauses.length === 0 ? "" : ` WHERE ${clauses.join(" AND ")}`,
174
174
  values,
175
- select: `SELECT work.*, canonical.stage, canonical.spec_id,
175
+ select: `SELECT work.*, canonical.stage, canonical.prd_id,
176
+ COALESCE(canonical.spec_id, (SELECT COALESCE(change.source_spec_id, CASE WHEN change.source_type='spec' THEN change.source_id END) FROM canonical_changes change WHERE change.id=${changeId})) AS spec_id,
176
177
  ${changeId} AS change_id, ${changeOrigin} AS origin,
177
178
  CASE WHEN canonical.entity_kind='task' THEN CASE WHEN ${linkedTask} THEN 'task' ELSE 'standalone-task' END ELSE canonical.entity_kind END AS kind`,
178
179
  };
@@ -20,7 +20,16 @@ export function sqlitePeriodTotals(rows: readonly Record<string, unknown>[]) {
20
20
  totals[key] = values.length === 0 ? null : values.reduce((sum, value) => sum + value, 0);
21
21
  }
22
22
  totals.duration_known = totals.total_duration ?? 0;
23
- totals.duration_unknown = rows.filter((row) => typeof row.total_duration !== "number").length;
23
+ totals.duration_unknown = rows.reduce(
24
+ (sum, row) =>
25
+ sum +
26
+ (typeof row.duration_unknown === "number"
27
+ ? row.duration_unknown
28
+ : typeof row.total_duration !== "number"
29
+ ? 1
30
+ : 0),
31
+ 0,
32
+ );
24
33
  return totals;
25
34
  }
26
35
 
@@ -6,83 +6,6 @@ export function readAgentDimension(
6
6
  input: SqliteViewInput,
7
7
  _filteredCostGroup: "agent",
8
8
  ) {
9
- const clauses = ["i.zaip_agent IS NOT NULL"];
10
- const values: Array<string | number> = [];
11
- if (input.from) {
12
- clauses.push(
13
- "date(COALESCE(i.source_started_at, i.source_occurred_at, i.occurred_at), '-3 hours') >= ?",
14
- );
15
- values.push(input.from.slice(0, 10));
16
- }
17
- if (input.to) {
18
- clauses.push(
19
- "date(COALESCE(i.source_started_at, i.source_occurred_at, i.occurred_at), '-3 hours') <= ?",
20
- );
21
- values.push(input.to.slice(0, 10));
22
- }
23
- if (input.agent) {
24
- clauses.push("i.zaip_agent = ?");
25
- values.push(input.agent);
26
- }
27
- if (input.phase) {
28
- clauses.push("i.phase = ?");
29
- values.push(input.phase);
30
- }
31
- if (input.status) {
32
- clauses.push("i.status = ?");
33
- values.push(input.status);
34
- }
35
- // This read model does not materialize canonical Task priority. Keep
36
- // the filtered view safe and avoid substituting a different field.
37
- if (input.priority) clauses.push("0");
38
- if (input.risk) {
39
- clauses.push("t.risk = ?");
40
- values.push(input.risk);
41
- }
42
- if (input.origin) {
43
- const origin =
44
- input.origin === "prd"
45
- ? "i.prd_id IS NOT NULL"
46
- : input.origin === "spec"
47
- ? "i.prd_id IS NULL AND i.spec_id IS NOT NULL"
48
- : input.origin === "task"
49
- ? "i.prd_id IS NULL AND i.spec_id IS NULL AND i.task_id IS NOT NULL"
50
- : "i.prd_id IS NULL AND i.spec_id IS NULL AND i.task_id IS NULL";
51
- clauses.push(origin);
52
- }
53
- // SQLite invocation facts do not contain canonical work_type. A work-type
54
- // filter must therefore return no rows rather than inventing attribution.
55
- if (input.workType) clauses.push("0");
56
- const segment: string[] = [];
57
- if (input.provider) {
58
- if (input.provider === "unavailable")
59
- clauses.push(
60
- "NOT EXISTS (SELECT 1 FROM invocation_usage known_provider WHERE known_provider.agent_invocation_id=i.agent_invocation_id AND known_provider.provider IS NOT NULL AND known_provider.provider <> 'unavailable')",
61
- );
62
- else {
63
- segment.push("f.provider = ?");
64
- values.push(input.provider);
65
- }
66
- }
67
- if (input.model) {
68
- if (input.model === "unavailable")
69
- clauses.push(
70
- "NOT EXISTS (SELECT 1 FROM invocation_usage known_model WHERE known_model.agent_invocation_id=i.agent_invocation_id AND known_model.model IS NOT NULL AND known_model.model <> 'unavailable')",
71
- );
72
- else {
73
- segment.push("f.model = ?");
74
- values.push(input.model);
75
- }
76
- }
77
- if (segment.length > 0)
78
- clauses.push(
79
- `EXISTS (SELECT 1 FROM invocation_usage f WHERE f.agent_invocation_id=i.agent_invocation_id AND ${segment.join(" AND ")})`,
80
- );
81
- if (input.query) {
82
- const query = `%${input.query}%`;
83
- clauses.push("(i.zaip_agent LIKE ? OR i.zaip_agent_persona LIKE ? OR i.zaip_agent_job LIKE ?)");
84
- values.push(query, query, query);
85
- }
86
9
  // This is deliberately the same financial fact population as the Cost
87
10
  // Monitor summary, grouped by the factual activity.zaip_agent. It is
88
11
  // not an invocation-only approximation.
@@ -111,10 +34,17 @@ export function readAgentDimension(
111
34
  activityValues.push(input.phase);
112
35
  }
113
36
  if (input.status) {
114
- activityClauses.push("a.status = ?");
37
+ activityClauses.push("COALESCE(activity_task.status, a.status) = ?");
115
38
  activityValues.push(input.status);
116
39
  }
117
- if (input.priority || input.workType) activityClauses.push("0");
40
+ if (input.priority) {
41
+ activityClauses.push("activity_task.priority = ?");
42
+ activityValues.push(input.priority);
43
+ }
44
+ if (input.workType) {
45
+ activityClauses.push("a.work_type = ?");
46
+ activityValues.push(input.workType);
47
+ }
118
48
  if (input.risk) {
119
49
  activityClauses.push("activity_task.risk = ?");
120
50
  activityValues.push(input.risk);
@@ -155,7 +85,6 @@ export function readAgentDimension(
155
85
  );
156
86
  activityValues.push(query, query, query);
157
87
  }
158
- const _where = clauses.join(" AND ");
159
88
  const invocationClauses = ["i.zaip_agent IS NOT NULL"];
160
89
  const invocationValues: Array<string | number> = [];
161
90
  const invocationSourceDay =
@@ -183,10 +112,17 @@ export function readAgentDimension(
183
112
  invocationValues.push(input.phase);
184
113
  }
185
114
  if (input.status) {
186
- invocationClauses.push("i.status = ?");
115
+ invocationClauses.push("COALESCE(invocation_task.status, i.status) = ?");
187
116
  invocationValues.push(input.status);
188
117
  }
189
- if (input.priority || input.workType) invocationClauses.push("0");
118
+ if (input.priority) {
119
+ invocationClauses.push("invocation_task.priority = ?");
120
+ invocationValues.push(input.priority);
121
+ }
122
+ if (input.workType) {
123
+ invocationClauses.push("i.work_type = ?");
124
+ invocationValues.push(input.workType);
125
+ }
190
126
  if (input.risk) {
191
127
  invocationClauses.push("invocation_task.risk = ?");
192
128
  invocationValues.push(input.risk);