@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,8 +1,12 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import {
3
+ aggregateOperationsPageRows,
3
4
  executionEntityPageRows,
4
5
  executionLifecycleElapsedMs,
6
+ filterLifecyclePageRows,
7
+ filterOperationsMetricRows,
5
8
  lifecycleElapsedMs,
9
+ withCanonicalOperationsEntityStatuses,
6
10
  } from "./server-operations-pages.js";
7
11
 
8
12
  describe("executionEntityPageRows", () => {
@@ -120,6 +124,93 @@ describe("executionEntityPageRows", () => {
120
124
  });
121
125
  });
122
126
 
127
+ describe("Operations status filters", () => {
128
+ it("uses the latest source Run status for an aggregated Execution before filtering", () => {
129
+ const rows = aggregateOperationsPageRows(
130
+ [
131
+ metricRow("RUN-STARTED", "EXEC-1", "running", "2026-09-16T10:00:00.000Z"),
132
+ metricRow("RUN-FINISHED", "EXEC-1", "completed", "2026-09-16T10:01:00.000Z"),
133
+ ],
134
+ "executions",
135
+ );
136
+ expect(rows).toMatchObject([{ id: "EXEC-1", status: "completed" }]);
137
+ expect(
138
+ filterOperationsMetricRows(rows, { query: "", risk: "", status: "completed" }),
139
+ ).toHaveLength(1);
140
+ expect(filterOperationsMetricRows(rows, { query: "", risk: "", status: "running" })).toEqual(
141
+ [],
142
+ );
143
+ });
144
+
145
+ it("lets a canonical Execution gate override a completed Run fallback", () => {
146
+ const execution = metricRow("EXEC-1", "EXEC-1", "completed", "2026-09-16T10:00:00.000Z");
147
+ const conversation = { ...execution, id: "CONV-1", conversation_id: "CONV-1" };
148
+ const entities = [
149
+ { id: "EXEC-1", status: "blocked", data: { origin: { conversation_id: "CONV-1" } } },
150
+ ];
151
+ expect(
152
+ withCanonicalOperationsEntityStatuses([execution], entities, "executions"),
153
+ ).toMatchObject([{ status: "blocked" }]);
154
+ expect(
155
+ withCanonicalOperationsEntityStatuses([conversation], entities, "conversations"),
156
+ ).toMatchObject([{ status: "blocked" }]);
157
+ });
158
+
159
+ it("keeps an ambiguous Conversation status unavailable unless its own canonical entity exists", () => {
160
+ const conversation = {
161
+ ...metricRow("EXEC-1", "EXEC-1", "completed", "2026-09-16T10:00:00.000Z"),
162
+ id: "CONV-1",
163
+ conversation_id: "CONV-1",
164
+ };
165
+ const executions = [
166
+ { id: "EXEC-2", status: "completed", data: { origin: { conversation_id: "CONV-1" } } },
167
+ { id: "EXEC-1", status: "blocked", data: { origin: { conversation_id: "CONV-1" } } },
168
+ ];
169
+ expect(
170
+ withCanonicalOperationsEntityStatuses([conversation], executions, "conversations"),
171
+ ).toMatchObject([{ status: null }]);
172
+ expect(
173
+ withCanonicalOperationsEntityStatuses(
174
+ [conversation],
175
+ executions.toReversed(),
176
+ "conversations",
177
+ [{ id: "CONV-1", status: "blocked" }],
178
+ ),
179
+ ).toMatchObject([{ status: "blocked" }]);
180
+ });
181
+
182
+ it.each([
183
+ "planned",
184
+ "running",
185
+ "verifying",
186
+ "completed",
187
+ "blocked",
188
+ "cancelled",
189
+ "failed",
190
+ ])("matches the canonical %s status for Run, Execution and Conversation rows", (status) => {
191
+ const filters = { query: "", risk: "", status };
192
+ const run = metricRow("RUN-1", "EXEC-1", status, "2026-09-16T10:00:00.000Z");
193
+ const execution = { ...run, id: "EXEC-1" };
194
+ const conversation = { ...run, id: "CONV-1", conversation_id: "CONV-1" };
195
+ expect(filterOperationsMetricRows([run], filters)).toEqual([run]);
196
+ expect(filterOperationsMetricRows([execution], filters)).toEqual([execution]);
197
+ expect(filterOperationsMetricRows([conversation], filters)).toEqual([conversation]);
198
+ });
199
+
200
+ it.each([
201
+ "planned",
202
+ "active",
203
+ "verifying",
204
+ "delivered",
205
+ "blocked",
206
+ "cancelled",
207
+ "failed",
208
+ ])("matches the canonical %s Change status without treating it as a Run status", (status) => {
209
+ const row = { id: `CHG-${status}`, title: "Change", status, risk: "standard" };
210
+ expect(filterLifecyclePageRows([row], { query: "", risk: "standard", status })).toEqual([row]);
211
+ });
212
+ });
213
+
123
214
  describe("lifecycleElapsedMs", () => {
124
215
  it("is terminal-only and never substitutes source-observed duration", () => {
125
216
  expect(
@@ -161,3 +252,23 @@ describe("executionLifecycleElapsedMs", () => {
161
252
  expect(executionLifecycleElapsedMs([{ ...rows[0]!, status: "running" }])).toBeNull();
162
253
  });
163
254
  });
255
+
256
+ function metricRow(id: string, executionId: string, status: string, startedAt: string) {
257
+ return {
258
+ id,
259
+ started_at: startedAt,
260
+ finished_at: status === "completed" ? "2026-09-16T10:01:00.000Z" : null,
261
+ task_id: "TASK-1",
262
+ execution_id: executionId,
263
+ conversation_id: null,
264
+ run_kind: "run" as const,
265
+ phase: "execution",
266
+ parent_run_id: null,
267
+ status,
268
+ duration_ms: null,
269
+ total_tokens: null,
270
+ cost: null,
271
+ currency: null,
272
+ events: null,
273
+ };
274
+ }
@@ -1,7 +1,6 @@
1
1
  import { posix } from "node:path";
2
2
  import type { WorkspaceLayout } from "@zaip-ai/core";
3
3
  import type { CostSummarySource } from "@zaip-ai/dashboard-cost-monitor/server";
4
- import type { Context } from "hono";
5
4
  export type OperationsCompactRun = NonNullable<CostSummarySource["run_metrics"]>[number] & {
6
5
  execution_id?: string | null;
7
6
  conversation_id?: string | null;
@@ -40,6 +39,14 @@ export function aggregateOperationsPageRows(
40
39
  if (row.total_tokens !== null)
41
40
  current.total_tokens = (current.total_tokens ?? 0) + row.total_tokens;
42
41
  if (row.cost !== null) current.cost = (current.cost ?? 0) + row.cost;
42
+ const currentLatestAt = current.finished_at ?? current.started_at;
43
+ const rowLatestAt = row.finished_at ?? row.started_at;
44
+ if (rowLatestAt > currentLatestAt) {
45
+ // The entity status is a source fact from its latest observed Run.
46
+ // Filtering happens after aggregation, so keeping the first input row
47
+ // here made terminal entities match a stale active status.
48
+ current.status = row.status;
49
+ }
43
50
  if (row.started_at < current.started_at) current.started_at = row.started_at;
44
51
  if (
45
52
  current.finished_at === null ||
@@ -53,6 +60,46 @@ export function aggregateOperationsPageRows(
53
60
  );
54
61
  }
55
62
 
63
+ /** Canonical Execution state overrides a derived latest-Run fallback. */
64
+ export function withCanonicalOperationsEntityStatuses(
65
+ rows: readonly OperationsCompactRun[],
66
+ entities: readonly {
67
+ id: string;
68
+ status: string | null;
69
+ data: Record<string, unknown> | null;
70
+ }[],
71
+ kind: "executions" | "conversations",
72
+ conversations: readonly { id: string; status: string | null }[] = [],
73
+ ): OperationsCompactRun[] {
74
+ const statusById = new Map<string, string | null>();
75
+ if (kind === "conversations")
76
+ for (const conversation of conversations) statusById.set(conversation.id, conversation.status);
77
+ const fallbackConversationStatuses = new Map<string, string | null>();
78
+ for (const entity of entities) {
79
+ const conversationId =
80
+ entity.data?.origin !== null && typeof entity.data?.origin === "object"
81
+ ? (entity.data.origin as { conversation_id?: unknown }).conversation_id
82
+ : null;
83
+ const id =
84
+ kind === "executions"
85
+ ? entity.id
86
+ : typeof conversationId === "string"
87
+ ? conversationId
88
+ : null;
89
+ if (id === null || statusById.has(id)) continue;
90
+ if (kind === "executions") statusById.set(id, entity.status);
91
+ else if (!fallbackConversationStatuses.has(id))
92
+ fallbackConversationStatuses.set(id, entity.status);
93
+ else fallbackConversationStatuses.set(id, null);
94
+ }
95
+ for (const [id, status] of fallbackConversationStatuses) statusById.set(id, status);
96
+ return rows.map((row) => {
97
+ const id = kind === "executions" ? row.execution_id : row.conversation_id;
98
+ if (id === null || id === undefined || !statusById.has(id)) return row;
99
+ return { ...row, status: statusById.get(id) ?? null };
100
+ });
101
+ }
102
+
56
103
  export function executionEntityPageRows(
57
104
  entities: readonly {
58
105
  id: string;
@@ -290,65 +337,8 @@ function stringArray(value: unknown): string[] {
290
337
  : [];
291
338
  }
292
339
 
293
- interface OperationsPageFilterValues {
294
- query: string;
295
- status: string;
296
- risk: string;
297
- }
298
-
299
- export function operationsPageFilters(context: Context): OperationsPageFilterValues {
300
- return {
301
- query: (context.req.query("query") ?? "").trim().toLocaleLowerCase(),
302
- status: (context.req.query("status") ?? "").trim(),
303
- risk: (context.req.query("risk") ?? "").trim(),
304
- };
305
- }
306
-
307
- export function filterOperationsMetricRows(
308
- rows: readonly OperationsCompactRun[],
309
- filters: OperationsPageFilterValues,
310
- ): OperationsCompactRun[] {
311
- return rows.filter((row) => {
312
- if (filters.status && row.status !== filters.status) return false;
313
- if (!filters.query) return true;
314
- return [
315
- row.id,
316
- row.task_id,
317
- row.execution_id,
318
- row.conversation_id,
319
- row.parent_run_id,
320
- row.run_kind,
321
- row.phase,
322
- row.agent,
323
- ].some(
324
- (value) => typeof value === "string" && value.toLocaleLowerCase().includes(filters.query),
325
- );
326
- });
327
- }
328
-
329
- export function filterLifecyclePageRows(
330
- rows: readonly Record<string, unknown>[],
331
- filters: OperationsPageFilterValues,
332
- ): Record<string, unknown>[] {
333
- return rows.filter((row) => {
334
- if (filters.status && row.status !== filters.status) return false;
335
- if (filters.risk && row.risk !== filters.risk) return false;
336
- if (!filters.query) return true;
337
- return [
338
- row.id,
339
- row.title,
340
- row.status,
341
- row.risk,
342
- row.source,
343
- row.origin,
344
- row.scope_type,
345
- row.scope_id,
346
- ]
347
- .flatMap((value) =>
348
- typeof value === "object" && value !== null ? Object.values(value) : [value],
349
- )
350
- .some(
351
- (value) => typeof value === "string" && value.toLocaleLowerCase().includes(filters.query),
352
- );
353
- });
354
- }
340
+ export {
341
+ filterLifecyclePageRows,
342
+ filterOperationsMetricRows,
343
+ operationsPageFilters,
344
+ } from "./server-operations-page-filters.js";
@@ -8,6 +8,7 @@ import {
8
8
  aggregateOperationsPageRows,
9
9
  filterOperationsMetricRows,
10
10
  operationsPageFilters,
11
+ withCanonicalOperationsEntityStatuses,
11
12
  } from "./server-operations-pages.js";
12
13
  import { projectionPeriodFilter } from "./server-period.js";
13
14
 
@@ -32,7 +33,14 @@ export function registerOperationsRunsRoute(
32
33
  Math.max(1, Number.parseInt(context.req.query("limit") ?? "100", 10) || 100),
33
34
  );
34
35
  const { from, to } = projectionPeriodFilter(context);
35
- const kind = context.req.query("kind") ?? "runs";
36
+ const requestedKind = context.req.query("kind") ?? "runs";
37
+ if (
38
+ requestedKind !== "runs" &&
39
+ requestedKind !== "executions" &&
40
+ requestedKind !== "conversations"
41
+ )
42
+ return respond(context, { error: "Unsupported Operations Run page" }, 400, false);
43
+ const kind: "runs" | "executions" | "conversations" = requestedKind;
36
44
  const filters = operationsPageFilters(context);
37
45
  const payload = await readAggregate(
38
46
  `operations:runs:${kind}:${from ?? ""}:${to ?? ""}:${offset}:${limit}:${filters.query}:${filters.status}:${filters.risk}`,
@@ -48,9 +56,12 @@ export function registerOperationsRunsRoute(
48
56
  );
49
57
  }
50
58
  }
51
- const summary = JSON.parse(
52
- await filesystem.readText(".agents/records/lifecycle/summary.json"),
53
- ) as CostSummarySource;
59
+ const manifests = new LifecycleManifestStore(filesystem);
60
+ const [summaryText, executionEntities] = await Promise.all([
61
+ filesystem.readText(".agents/records/lifecycle/summary.json"),
62
+ manifests.readEntities("execution"),
63
+ ]);
64
+ const summary = JSON.parse(summaryText) as CostSummarySource;
54
65
  const sourceRows = (summary.run_metrics ?? []).filter(
55
66
  (run) =>
56
67
  (from === null || run.started_at >= from) &&
@@ -61,8 +72,11 @@ export function registerOperationsRunsRoute(
61
72
  run.conversation_id !== null) ||
62
73
  (kind === "executions" && run.execution_id !== null)),
63
74
  );
75
+ const aggregated = aggregateOperationsPageRows(sourceRows, kind);
64
76
  const rows = filterOperationsMetricRows(
65
- aggregateOperationsPageRows(sourceRows, kind),
77
+ kind === "runs"
78
+ ? aggregated
79
+ : withCanonicalOperationsEntityStatuses(aggregated, executionEntities, kind),
66
80
  filters,
67
81
  );
68
82
  return {
@@ -41,4 +41,23 @@ describe("periodMacroMetric", () => {
41
41
  [expectedStage]: 1,
42
42
  });
43
43
  });
44
+
45
+ it("keeps the canonical Task and rework classification for the filtered macro population", () => {
46
+ const specs = periodMacroMetric(
47
+ [
48
+ { id: "SPEC-STRUCTURED", status: "active", task_count: 2, rework_run_count: 0 },
49
+ { id: "SPEC-EMPTY", status: "blocked", task_count: 0, rework_run_count: 0 },
50
+ ],
51
+ "spec",
52
+ );
53
+ const prds = periodMacroMetric(
54
+ [{ id: "PRD-REWORK", status: "delivered", task_count: 3, rework_run_count: 1 }],
55
+ "prd",
56
+ );
57
+
58
+ expect(specs.status_counts).toEqual({ executing: 1, blocked: 1 });
59
+ expect(specs.classification_counts).toEqual({ empty: 1, structured: 1, rework: 0 });
60
+ expect(prds.status_counts).toEqual({ completed: 1 });
61
+ expect(prds.classification_counts).toEqual({ empty: 0, structured: 0, rework: 1 });
62
+ });
44
63
  });
@@ -41,7 +41,16 @@ export const periodMacroStage = (kind: MacroKind, value: unknown) => {
41
41
  if (status === "ready" || status === "planned") return "ready";
42
42
  if (status === "active") return "executing";
43
43
  if (status === "delivered") return "completed";
44
- return ["executing", "verifying", "completed", "blocked", "failed", "cancelled"].includes(status)
44
+ return [
45
+ "definition",
46
+ "planning",
47
+ "executing",
48
+ "verifying",
49
+ "completed",
50
+ "blocked",
51
+ "failed",
52
+ "cancelled",
53
+ ].includes(status)
45
54
  ? status
46
55
  : "planning";
47
56
  };
@@ -65,7 +74,7 @@ export function periodMacroMetric(
65
74
  const statusCounts: Record<string, number> = {};
66
75
  const classificationCounts: Record<string, number> = { empty: 0, structured: 0, rework: 0 };
67
76
  for (const row of rows) {
68
- const status = periodMacroStage(kind, row.status);
77
+ const status = periodMacroStage(kind, row.stage ?? row.status);
69
78
  statusCounts[status] = (statusCounts[status] ?? 0) + 1;
70
79
  const classification =
71
80
  number(row, "rework_run_count") > 0
@@ -119,15 +119,18 @@ export function buildSqliteOperationsProjection(
119
119
  run_count: task.run_count,
120
120
  }))
121
121
  : projectAllTimeTopTasks(allTimeTopTasks);
122
+ // Compact all-time responses omit entity arrays, but must retain macro aggregates.
123
+ const allTimeMacroMetrics =
124
+ allTime === null ? null : (fullAllTime?.macro_metrics ?? filesystem.firstFoldMacroMetrics());
122
125
  const macroMetrics =
123
- fullAllTime === null
126
+ allTimeMacroMetrics === null
124
127
  ? ({
125
128
  specs: periodMacroMetric(specs, "spec"),
126
129
  prds: periodMacroMetric(prds, "prd"),
127
130
  } satisfies OverviewMacroMetrics)
128
131
  : (Object.fromEntries(
129
132
  (["specs", "prds"] as const).map((kind) => {
130
- const metric = fullAllTime.macro_metrics[kind];
133
+ const metric = allTimeMacroMetrics[kind];
131
134
  return [
132
135
  kind,
133
136
  {
@@ -249,25 +252,29 @@ export function buildSqliteOperationsProjection(
249
252
  created_at: String(row.occurred_at),
250
253
  updated_at: String(row.occurred_at),
251
254
  kind,
252
- parent_id: null,
255
+ parent_id: kind === "spec" && typeof row.prd_id === "string" ? row.prd_id : null,
253
256
  artifact_path: canonicalSource,
254
257
  lifecycle_status: String(row.status ?? "draft"),
255
- work_status: normalizeMacroStatus(row.status),
258
+ work_status: normalizeMacroStatus(row.stage ?? row.status),
256
259
  execution_ids: [],
257
- task_ids: [],
260
+ task_ids:
261
+ typeof row.task_ids_json === "string" ? (JSON.parse(row.task_ids_json) as string[]) : [],
258
262
  planned_tasks: [],
259
263
  canonical_run_ids: [],
260
264
  run_ids: [],
261
265
  root_execution_run_ids: [],
262
266
  execution_count: 0,
263
- task_count: 0,
267
+ task_count: nullableMetric(row.task_count) ?? 0,
264
268
  run_count: nullableMetric(row.invocation_count) ?? 0,
265
269
  duration_ms: nullableMetric(row.total_duration),
266
270
  decisions: { human: 0, agent: 0 },
267
- rework_run_count: 0,
271
+ rework_run_count: nullableMetric(row.rework_run_count) ?? 0,
268
272
  quality: {
269
- completed_tasks: 0,
270
- task_completion_rate: 0,
273
+ completed_tasks: nullableMetric(row.completed_task_count) ?? 0,
274
+ task_completion_rate:
275
+ Number(row.task_count) > 0
276
+ ? Number(row.completed_task_count ?? 0) / Number(row.task_count)
277
+ : 0,
271
278
  terminal_runs: 0,
272
279
  successful_runs: 0,
273
280
  terminal_success_rate: 0,
@@ -308,11 +315,11 @@ export function buildSqliteOperationsProjection(
308
315
  },
309
316
  task_count: taskCount,
310
317
  completed_prd_count:
311
- allTime?.aggregate.completed_prd_count ??
312
- prds.filter((row) => row.status === "completed").length,
318
+ allTime?.aggregate.completed_prd_count ?? macroMetrics.prds.status_counts.completed ?? 0,
313
319
  completed_spec_count:
314
320
  allTime?.aggregate.completed_spec_count ??
315
- specs.filter((row) => row.status === "completed").length,
321
+ macroMetrics.specs.status_counts.completed ??
322
+ 0,
316
323
  completed_task_count: allTime?.aggregate.completed_task_count ?? statuses.completed ?? 0,
317
324
  task_status_counts: statuses,
318
325
  task_risk_counts: risks,
@@ -1,7 +1,9 @@
1
1
  import { EventEmitter } from "node:events";
2
- import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import { copyFile, mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
3
+ import { execFile } from "node:child_process";
4
+ import { promisify } from "node:util";
3
5
  import { tmpdir } from "node:os";
4
- import { join } from "node:path";
6
+ import { join, resolve } from "node:path";
5
7
  import { DatabaseSync } from "node:sqlite";
6
8
  import { describe, expect, it, vi } from "vitest";
7
9
  import {
@@ -34,6 +36,48 @@ describe("snapshot refresh shutdown", () => {
34
36
  });
35
37
 
36
38
  describe("snapshot worker process boundary", () => {
39
+ it("refreshes an installed consumer using only the portable bundle and scripts", async () => {
40
+ const runtimeRoot = resolve(import.meta.dirname, "..");
41
+ const source = resolve(runtimeRoot, "../../../..");
42
+ const parent = join(source, ".local/sqlite/tests");
43
+ await mkdir(parent, { recursive: true });
44
+ const root = await mkdtemp(join(parent, "portable-worker-"));
45
+ let filesystem: SqliteReadModelFileSystem | undefined;
46
+ try {
47
+ const installed = join(root, ".agents/dashboard/packages/local-runtime");
48
+ await mkdir(join(installed, "scripts"), { recursive: true });
49
+ await mkdir(join(root, ".agents/config"), { recursive: true });
50
+ for (const file of ["project.yaml", "framework.lock.yaml"])
51
+ await copyFile(join(source, ".agents/config", file), join(root, ".agents/config", file));
52
+ await copyFile(join(runtimeRoot, "server.mjs"), join(installed, "server.mjs"));
53
+ for (const name of ["rebuild-sqlite-read-model.mjs", "validate-sqlite-read-model.mjs"])
54
+ await copyFile(join(runtimeRoot, "scripts", name), join(installed, "scripts", name));
55
+ const rebuild = join(installed, "scripts/rebuild-sqlite-read-model.mjs");
56
+ const environment = {
57
+ ...process.env,
58
+ ZAIP_WORKSPACE: root,
59
+ ZAIP_SQLITE_DB_PATH: join(root, ".local/sqlite/zaip-aios-dashboard.sqlite"),
60
+ };
61
+ const result = await promisify(execFile)(process.execPath, [rebuild], {
62
+ cwd: root,
63
+ env: environment,
64
+ windowsHide: true,
65
+ });
66
+ expect(JSON.parse(result.stdout).schema.schemaVersion).toBe(readModelSchemaVersion);
67
+ filesystem = new SqliteReadModelFileSystem(root);
68
+ await mkdir(join(root, ".agents/records/specs"), { recursive: true });
69
+ const path = ".agents/records/specs/SPEC-PORTABLE.md";
70
+ await writeFile(
71
+ join(root, path),
72
+ "---\nid: SPEC-PORTABLE\ntitle: Portable refresh\nstatus: blocked\ncreated_at: 2026-09-16T00:00:00Z\n---\n",
73
+ );
74
+ await refreshSqliteSnapshotInWorker(root, filesystem);
75
+ expect(await filesystem.readText(path)).toContain("status: blocked");
76
+ } finally {
77
+ filesystem?.close();
78
+ await rm(root, { recursive: true, force: true });
79
+ }
80
+ }, 30000);
37
81
  it.each([
38
82
  "valid",
39
83
  "empty",
@@ -25,7 +25,13 @@ describe("snapshot source synchronization", () => {
25
25
  const onCaptureFailure = vi.fn();
26
26
  const onRefreshFailure = vi.fn();
27
27
  const onCaptureSuccess = vi.fn();
28
- const capture = vi.fn().mockRejectedValueOnce(error).mockResolvedValue(undefined);
28
+ const capture = vi.fn().mockRejectedValueOnce(error).mockResolvedValue({
29
+ captured_runs: 0,
30
+ captured_segments: 0,
31
+ manifest_state: "initialized",
32
+ skipped_reason: "no_active_runs",
33
+ last_capture_at: "2026-09-16T00:00:00.000Z",
34
+ });
29
35
  const refresh = vi.fn(async () => undefined);
30
36
  startSnapshotSynchronization({
31
37
  workspaceRoot: "C:/workspace",
@@ -42,7 +48,9 @@ describe("snapshot source synchronization", () => {
42
48
  expect(onRefreshFailure).not.toHaveBeenCalled();
43
49
  expect(refresh).toHaveBeenCalledTimes(1);
44
50
  await vi.advanceTimersByTimeAsync(60_000);
45
- expect(onCaptureSuccess).toHaveBeenCalledTimes(1);
51
+ expect(onCaptureSuccess).toHaveBeenCalledWith(
52
+ expect.objectContaining({ skipped_reason: "no_active_runs" }),
53
+ );
46
54
  expect(refresh).toHaveBeenCalledTimes(2);
47
55
  });
48
56
  it("watches current data for both creation and alteration refreshes", async () => {
@@ -1,5 +1,6 @@
1
1
  import { watch } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import type { ActiveCodexTelemetryCapture } from "./active-codex-telemetry.js";
3
4
 
4
5
  export function startSnapshotSynchronization(input: {
5
6
  workspaceRoot: string;
@@ -7,9 +8,9 @@ export function startSnapshotSynchronization(input: {
7
8
  watchSources: boolean;
8
9
  refresh: () => Promise<void>;
9
10
  /** Exact active-Codex collection, separate from projection and lifecycle repair. */
10
- captureActiveTelemetry?: () => Promise<void>;
11
+ captureActiveTelemetry?: () => Promise<ActiveCodexTelemetryCapture>;
11
12
  onCaptureFailure?: (error: unknown) => void;
12
- onCaptureSuccess?: () => void;
13
+ onCaptureSuccess?: (result: ActiveCodexTelemetryCapture) => void;
13
14
  /** Report failed asynchronous refreshes; a stale snapshot must never look healthy. */
14
15
  onRefreshFailure?: (input: { trigger: "stale_seed" | "source_change"; error: unknown }) => void;
15
16
  }): void {
@@ -42,7 +43,7 @@ export function startSnapshotSynchronization(input: {
42
43
  if (input.captureActiveTelemetry === undefined) return scheduleRefresh();
43
44
  void input
44
45
  .captureActiveTelemetry()
45
- .then(() => input.onCaptureSuccess?.())
46
+ .then((result) => input.onCaptureSuccess?.(result))
46
47
  .catch((error: unknown) => input.onCaptureFailure?.(error))
47
48
  .finally(scheduleRefresh);
48
49
  };
@@ -1,6 +1,6 @@
1
1
  import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
2
  import { tmpdir } from "node:os";
3
- import { join, resolve } from "node:path";
3
+ import { basename, join, resolve } from "node:path";
4
4
  import { WorkspaceFileSystem } from "@zaip-ai/core";
5
5
  import { describe, expect, it, vi } from "vitest";
6
6
  import {
@@ -109,12 +109,54 @@ describe("dashboard backend", () => {
109
109
  await expect(response.json()).resolves.toMatchObject({
110
110
  kind: "zaip-dashboard-sqlite-runtime",
111
111
  workspaceKey: dashboardWorkspaceKey(workspaceRoot),
112
+ workspace: workspaceRoot,
113
+ workspace_name: basename(workspaceRoot),
114
+ server_pid: process.pid,
112
115
  api_version: 2,
113
116
  read_only: true,
114
117
  status: "ok",
115
118
  workspace_layout: 3,
116
119
  });
117
120
  });
121
+ it("reports a missing canonical lifecycle manifest as degraded without hiding runtime identity", async () => {
122
+ await withSqliteReadModelFixture("missing-manifest", async ({ root, filesystem }) => {
123
+ const app = createDashboardApp(root, "test-session", undefined, { filesystem });
124
+ const health = await app.request("/api/v2/health");
125
+ expect(health.status).toBe(200);
126
+ await expect(health.json()).resolves.toMatchObject({
127
+ status: "degraded",
128
+ lifecycle_manifest_state: "missing",
129
+ workspace: root,
130
+ workspace_name: basename(root),
131
+ server_pid: process.pid,
132
+ });
133
+ const ready = await app.request("/api/v2/ready");
134
+ expect(ready.status).toBe(200);
135
+ await expect(ready.json()).resolves.toMatchObject({
136
+ status: "degraded",
137
+ lifecycle_manifest_state: "missing",
138
+ workspace: root,
139
+ });
140
+ });
141
+ });
142
+ it("rejects a parseable but invalid canonical lifecycle manifest", async () => {
143
+ await withSqliteReadModelFixture("invalid-manifest", async ({ root, filesystem }) => {
144
+ await mkdir(join(root, ".agents/records/lifecycle"), { recursive: true });
145
+ await writeFile(
146
+ join(root, ".agents/records/lifecycle/manifest.json"),
147
+ '{"schema_version":1,"offsets":[]}',
148
+ );
149
+ await writeFile(join(root, ".agents/records/lifecycle/summary.json"), '{"schema_version":1}');
150
+ const app = createDashboardApp(root, "test-session", undefined, { filesystem });
151
+ for (const path of ["/api/v2/health", "/api/v2/ready"]) {
152
+ const response = await app.request(path);
153
+ expect(await response.json()).toMatchObject({
154
+ status: "degraded",
155
+ lifecycle_manifest_state: "invalid",
156
+ });
157
+ }
158
+ });
159
+ });
118
160
  it("exposes the developer cost endpoint with an account_id filter", async () => {
119
161
  await withSqliteReadModelFixture("developer-cost", async ({ root, filesystem }) => {
120
162
  const aggregate = vi.spyOn(filesystem, "developerCostAggregate").mockReturnValue({