@zaip-ai/cli 2.2.0 → 3.0.0

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