@zaip-ai/cli 1.0.8 → 1.3.1

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