@zaip-ai/cli 2.6.0 → 3.1.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 (312) 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 +5 -2
  5. package/dist/services/adapters.js.map +1 -1
  6. package/dist/services/agent-adapters.js +12 -9
  7. package/dist/services/agent-adapters.js.map +1 -1
  8. package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
  9. package/dist/services/codex-conversation-lifecycle-hook.js +32 -21
  10. package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
  11. package/dist/services/install-agents-template.js +9 -1
  12. package/dist/services/install-agents-template.js.map +1 -1
  13. package/dist/services/runtime-template.test.js +25 -2
  14. package/dist/services/runtime-template.test.js.map +1 -1
  15. package/dist/services/transactional-files.d.ts.map +1 -1
  16. package/dist/services/transactional-files.js +59 -14
  17. package/dist/services/transactional-files.js.map +1 -1
  18. package/package.json +1 -1
  19. package/templates/.agents/README-ENG.md +75 -10
  20. package/templates/.agents/README.md +76 -10
  21. package/templates/.agents/config/agents/catalog.yaml +3 -0
  22. package/templates/.agents/config/agents/discovery.json +2 -2
  23. package/templates/.agents/config/clients/codex/agents/zaip-agent-analyst.toml +1 -1
  24. package/templates/.agents/config/clients/codex/agents/zaip-agent-auditor.toml +1 -1
  25. package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +1 -1
  26. package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +1 -1
  27. package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +1 -1
  28. package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +1 -1
  29. package/templates/.agents/config/clients/codex/agents/zaip-agent-data-analyst.toml +1 -1
  30. package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +1 -1
  31. package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +2 -2
  32. package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +1 -1
  33. package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +1 -1
  34. package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +1 -1
  35. package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +1 -1
  36. package/templates/.agents/config/clients/codex/agents/zaip-agent-integrator.toml +1 -1
  37. package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +1 -1
  38. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +13 -10
  39. package/templates/.agents/config/clients/codex/agents/zaip-agent-refactoring-specialist.toml +1 -1
  40. package/templates/.agents/config/clients/codex/agents/zaip-agent-reviewer.toml +1 -1
  41. package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +1 -1
  42. package/templates/.agents/config/clients/codex/agents/zaip-agent-security-auditor.toml +1 -1
  43. package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +1 -1
  44. package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +1 -1
  45. package/templates/.agents/config/clients/codex/agents/zaip-agent-writer.toml +1 -1
  46. package/templates/.agents/config/project.yaml +10 -1
  47. package/templates/.agents/dashboard/.zaip-managed.json +274 -138
  48. package/templates/.agents/dashboard/README.md +16 -0
  49. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-CGxeQak4.js → CostCalculationGuidePage-CEDZjl4V.js} +1 -1
  50. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-tzS7YxYB.js → DashboardHelpDialog-DIWDmvAS.js} +930 -550
  51. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-DEbCi1gP.js → PricingSettingsDialog-BBRBKaHa.js} +1 -1
  52. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-B9GWkEyN.css +1 -0
  53. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BAvLPAee.js +3 -0
  54. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-t1Om0Abw.js → TraceabilityWorkspace-C9dDhj34.js} +1 -1
  55. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-06__WZco.js +68 -0
  56. package/templates/.agents/dashboard/apps/frontend/dist/assets/dashboard-localization-CoAVMZN6.js +828 -0
  57. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DiGC-dsJ.js → icons-vendor-DEmo6Tn2.js} +1 -1
  58. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-BVzw_Wux.js +2 -0
  59. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-kPO6yNed.js → react-vendor-CadYsm83.js} +1 -1
  60. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-BzKK8kK3.js +1 -0
  61. package/templates/.agents/dashboard/apps/frontend/dist/index.html +5 -5
  62. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  63. package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +10 -5
  64. package/templates/.agents/dashboard/apps/frontend/src/AutonomySettings.tsx +82 -0
  65. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.dom.test.ts +38 -7
  66. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +164 -171
  67. package/templates/.agents/dashboard/apps/frontend/src/__tests__/app-composition-support.ts +6 -1
  68. package/templates/.agents/dashboard/apps/frontend/src/cost-monitor-population.test.tsx +149 -0
  69. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +2 -1
  70. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +19 -0
  71. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +22 -1
  72. package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.test.ts +54 -0
  73. package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.ts +20 -2
  74. package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.test.ts +37 -43
  75. package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.ts +9 -251
  76. package/templates/.agents/dashboard/apps/frontend/src/dashboard-project-overview.ts +34 -7
  77. package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.test.ts +51 -0
  78. package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.ts +3 -1
  79. package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +35 -0
  80. package/templates/.agents/dashboard/apps/frontend/src/operations-period.test.ts +19 -4
  81. package/templates/.agents/dashboard/apps/frontend/src/operations-period.ts +5 -3
  82. package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.test.ts +112 -23
  83. package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.ts +49 -12
  84. package/templates/.agents/dashboard/apps/frontend/src/project-settings-copy.ts +181 -0
  85. package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +11 -1
  86. package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +34 -51
  87. package/templates/.agents/dashboard/apps/frontend/src/project-settings-state.css +55 -0
  88. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +12 -0
  89. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +1 -1
  90. package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.ts +1 -2
  91. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +6 -0
  92. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +2 -0
  93. package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +3 -1
  94. package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-task-pagination.ts +4 -15
  95. package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +2 -2
  96. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  97. package/templates/.agents/dashboard/modules/cost-monitor/src/complete-cost-average.test.ts +73 -0
  98. package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +9 -0
  99. package/templates/.agents/dashboard/modules/cost-monitor/src/period-averages.ts +60 -0
  100. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +8 -22
  101. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +2 -3
  102. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.tsx +32 -8
  103. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-summary.ts +3 -2
  104. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +1 -42
  105. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +2 -1
  106. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.ts +3 -2
  107. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +8 -2
  108. package/templates/.agents/dashboard/modules/cost-monitor/src/server/index.ts +1 -0
  109. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  110. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview-keeps-structure-classes-mutually-exclusive.test.ts +4 -3
  111. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +66 -3
  112. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +71 -1
  113. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +36 -30
  114. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +5 -14
  115. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +3 -0
  116. package/templates/.agents/dashboard/modules/operations/src/react/OverviewCostKpi.tsx +46 -0
  117. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +28 -1
  118. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +11 -4
  119. package/templates/.agents/dashboard/modules/operations/src/react/index.ts +1 -0
  120. package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +2 -2
  121. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +28 -8
  122. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +19 -2
  123. package/templates/.agents/dashboard/modules/operations/src/react/overview-cost-card.test.tsx +89 -0
  124. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +3 -3
  125. package/templates/.agents/dashboard/modules/operations/src/work-board-model.ts +2 -1
  126. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  127. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  128. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  129. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  130. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +279 -245
  131. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +247 -215
  132. package/templates/.agents/dashboard/packages/local-runtime/package.json +2 -2
  133. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +15 -25
  134. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +279 -245
  135. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +1 -1
  136. package/templates/.agents/dashboard/packages/local-runtime/src/project-installation-summary.test.ts +142 -0
  137. package/templates/.agents/dashboard/packages/local-runtime/src/project-installation-summary.ts +190 -0
  138. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +65 -0
  139. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +67 -66
  140. package/templates/.agents/dashboard/packages/local-runtime/src/server-browser-lease.test.ts +91 -0
  141. package/templates/.agents/dashboard/packages/local-runtime/src/server-browser-lease.ts +24 -4
  142. package/templates/.agents/dashboard/packages/local-runtime/src/server-hono-security.test.ts +17 -0
  143. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-routes.ts +21 -2
  144. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.test.ts +94 -2
  145. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +62 -12
  146. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +26 -0
  147. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +4 -1
  148. package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.test.ts +97 -0
  149. package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.ts +10 -13
  150. package/templates/.agents/dashboard/packages/local-runtime/src/server-trace-routes.ts +2 -10
  151. package/templates/.agents/dashboard/packages/local-runtime/src/server-traceability-index.test.ts +84 -0
  152. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +15 -1
  153. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-calendar.ts +17 -0
  154. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cold-parse.test.ts +78 -0
  155. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-dimension-facts.test.ts +12 -1
  156. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.test.ts +94 -0
  157. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.ts +5 -5
  158. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-duration-lookup.test.ts +59 -0
  159. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-entity-label-views.test.ts +72 -0
  160. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-file-index.test.ts +69 -0
  161. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-cache.ts +3 -1
  162. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-force-canonical.test.ts +3 -1
  163. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-refresh.test.ts +2 -0
  164. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-projections.ts +9 -0
  165. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-runs.ts +4 -5
  166. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-period-averages.ts +46 -0
  167. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-provider-alias-parity.test.ts +50 -0
  168. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.test.ts +171 -0
  169. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.ts +36 -16
  170. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-filtered-dimension.ts +13 -2
  171. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +25 -7
  172. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-temporal-dimension.ts +2 -0
  173. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical-parsing.ts +7 -0
  174. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical.ts +5 -15
  175. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +34 -10
  176. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts +17 -3
  177. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-keeps-orphan-telemetry-out-kanban-without.test.ts +1 -1
  178. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +11 -0
  179. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +5 -4
  180. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.test.ts +54 -1
  181. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +7 -3
  182. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +4 -1
  183. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-risk-population.test.ts +98 -0
  184. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-base-views.ts +29 -16
  185. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-dashboard-views.ts +2 -1
  186. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-seed.test.ts +2 -0
  187. package/templates/.agents/dashboard/packages/local-runtime/src/verify-project-settings.mjs +57 -0
  188. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  189. package/templates/.agents/dashboard/scripts/qualify-observability.mjs +130 -0
  190. package/templates/.agents/dashboard/scripts/verify-autonomy-settings.mjs +175 -0
  191. package/templates/.agents/dashboard/scripts/verify-observability.mjs +254 -0
  192. package/templates/.agents/dashboard/scripts/verify-project-setup.mjs +64 -0
  193. package/templates/.agents/dashboard/tests/e2e/lease-global-setup.ts +37 -0
  194. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  195. package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +5 -3
  196. package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-period-transition.spec.ts +22 -1
  197. package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +17 -8
  198. package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +47 -6
  199. package/templates/.agents/dashboard/tests/e2e/specs/lease-lifetime.spec.ts +14 -0
  200. package/templates/.agents/dashboard/tests/observability-fixture.mjs +200 -0
  201. package/templates/.agents/design/.zaip-managed.json +84 -40
  202. package/templates/.agents/design/apps/catalog/dist/assets/index-BJV597iq.js +72 -0
  203. package/templates/.agents/design/apps/catalog/dist/assets/index-BOjCcUaU.js +72 -0
  204. package/templates/.agents/design/apps/catalog/dist/assets/index-B_WhrCZe.js +72 -0
  205. package/templates/.agents/design/apps/catalog/dist/assets/index-CqtYXZfV.js +72 -0
  206. package/templates/.agents/design/apps/catalog/dist/assets/index-D_lfqoyx.js +72 -0
  207. package/templates/.agents/design/apps/catalog/dist/assets/index-i_PO2k9R.js +9 -0
  208. package/templates/.agents/design/apps/catalog/dist/index.html +1 -1
  209. package/templates/.agents/design/apps/catalog/dist/storybook/assets/CatalogShell-Cstn1UwA.js +1 -0
  210. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{Color-6AOWCN3U-B-kAgAjB.js → Color-6AOWCN3U-Cm-yJJz_.js} +1 -1
  211. package/templates/.agents/design/apps/catalog/dist/storybook/assets/Components.stories-D1WopB2L.js +137 -0
  212. package/templates/.agents/design/apps/catalog/dist/storybook/assets/DesignSystem.stories-DQ9PJ3N3.js +1 -0
  213. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{DocsRenderer-JROSPFPF-BVN7xHtv.js → DocsRenderer-JROSPFPF-Belk4jRr.js} +4 -4
  214. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{WithTooltip-7X4HQR7L-CDHtKYkz.js → WithTooltip-7X4HQR7L-DoPvjkS1.js} +1 -1
  215. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{chunk-DRQKCCAG-D6AsDkMK.js → chunk-DRQKCCAG-B1itKXEN.js} +1 -1
  216. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{chunk-W22LQPXL-B4m5uloN.js → chunk-W22LQPXL-C-Eb5SPY.js} +1 -1
  217. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{components-CN8YyTUg.js → components-DnyKLwhj.js} +5 -5
  218. package/templates/.agents/design/apps/catalog/dist/storybook/assets/formatter-L2YTDE3Q-D0OSgxWz.js +1 -0
  219. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{iframe-9yZfIsdT.js → iframe-DcXBsFPz.js} +3 -3
  220. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{react-18-BoCSnq6H.js → react-18-CRM89QRf.js} +1 -1
  221. package/templates/.agents/design/apps/catalog/dist/storybook/assets/react-C3tkVMIp.js +1 -0
  222. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{syntaxhighlighter-YFXUGROL-Bnn_nMwJ.js → syntaxhighlighter-YFXUGROL-B03jQGTF.js} +1 -1
  223. package/templates/.agents/design/apps/catalog/dist/storybook/assets/{theming-DS_ue2sb.js → theming-4ZyufAga.js} +1 -1
  224. package/templates/.agents/design/apps/catalog/dist/storybook/iframe.html +1 -1
  225. package/templates/.agents/design/apps/catalog/dist/storybook/index.json +1 -1
  226. package/templates/.agents/design/apps/catalog/package.json +2 -2
  227. package/templates/.agents/design/apps/catalog/src/components/AutonomySpecimen.tsx +15 -0
  228. package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.test.tsx +19 -0
  229. package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.tsx +45 -0
  230. package/templates/.agents/design/apps/catalog/src/components/EstimatedCostSpecimen.tsx +48 -0
  231. package/templates/.agents/design/apps/catalog/src/components/ProjectStatusSpecimen.tsx +169 -0
  232. package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +55 -0
  233. package/templates/.agents/design/apps/catalog/src/stories/Components.stories.tsx +60 -0
  234. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  235. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  236. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
  237. package/templates/.agents/requirements/comparative-audit.md +1 -1
  238. package/templates/.agents/requirements/context-engine.md +1 -1
  239. package/templates/.agents/requirements/cost-observability.md +1 -1
  240. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  241. package/templates/.agents/requirements/data-export.md +1 -1
  242. package/templates/.agents/requirements/design-system.md +1 -1
  243. package/templates/.agents/requirements/execution-engine.md +1 -1
  244. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  245. package/templates/.agents/requirements/model-orchestration.md +1 -1
  246. package/templates/.agents/requirements/public-distribution.md +1 -1
  247. package/templates/.agents/requirements/software-architecture.md +1 -1
  248. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  249. package/templates/.agents/requirements/work-lifecycle.md +5 -5
  250. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  251. package/templates/.agents/rules/astra-diagnostic.md +3 -1
  252. package/templates/.agents/rules/autonomy-decision.md +10 -2
  253. package/templates/.agents/rules/core.md +12 -1
  254. package/templates/.agents/rules/run-lifecycle-closure.md +8 -6
  255. package/templates/.agents/rules/workflow.md +2 -2
  256. package/templates/.agents/runtime/VERSION +1 -1
  257. package/templates/.agents/runtime/bin/zaip.mjs +383 -350
  258. package/templates/.agents/runtime/checksums.sha256 +6 -6
  259. package/templates/.agents/runtime/manifest.json +1 -1
  260. package/templates/.agents/runtime/pnpm-lock.sha256 +1 -1
  261. package/templates/.agents/runtime/provenance.json +5 -5
  262. package/templates/.agents/runtime/sbom.cdx.json +3 -3
  263. package/templates/.agents/skills/zaip-skill-dev-environment/SKILL.md +2 -0
  264. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +28 -5
  265. package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +17 -3
  266. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +8 -9
  267. package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +10 -6
  268. package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +17 -12
  269. package/templates/.agents/skills/zaip-skill-move-prd/SKILL.md +2 -0
  270. package/templates/.agents/skills/zaip-skill-prd/SKILL.md +2 -0
  271. package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +21 -23
  272. package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +37 -13
  273. package/templates/.agents/skills/zaip-skill-setup/SKILL.md +2 -0
  274. package/templates/.agents/skills/zaip-skill-tool-setup/SKILL.md +2 -0
  275. package/templates/.agents/zaip-aios/INDEX.md +9 -1
  276. package/templates/.agents/zaip-aios/README.md +24 -2
  277. package/templates/.agents/zaip-aios/VERSION +1 -1
  278. package/templates/.agents/zaip-aios/guides/01-primeiros-passos.md +5 -1
  279. package/templates/.agents/zaip-aios/guides/03-tasks.md +15 -2
  280. package/templates/.agents/zaip-aios/guides/04-specs.md +13 -0
  281. package/templates/.agents/zaip-aios/guides/05-prds.md +13 -0
  282. package/templates/.agents/zaip-aios/guides/06-execucao.md +19 -4
  283. package/templates/.agents/zaip-aios/guides/07-revisao-e-validacao.md +14 -0
  284. package/templates/.agents/zaip-aios/guides/08-contexto-e-tokens.md +4 -3
  285. package/templates/.agents/zaip-aios/guides/09-agentes-e-squads.md +17 -9
  286. package/templates/.agents/zaip-aios/guides/10-seguranca.md +9 -0
  287. package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +69 -0
  288. package/templates/.agents/zaip-aios/guides/12-instalacao-e-upgrade.md +9 -4
  289. package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +7 -1
  290. package/templates/.agents/zaip-aios/guides/14-troubleshooting.md +18 -0
  291. package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +54 -3
  292. package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +10 -2
  293. package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +186 -5
  294. package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +21 -15
  295. package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +18 -2
  296. package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +14 -2
  297. package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +190 -489
  298. package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +72 -13
  299. package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +18 -0
  300. package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +18 -1
  301. package/templates/template-manifest.json +454 -274
  302. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-1L7Qw-Gq.js +0 -3
  303. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-EInWr641.css +0 -1
  304. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-B6aZfo5f.js +0 -68
  305. package/templates/.agents/dashboard/apps/frontend/dist/assets/dashboard-localization-CLJ0lT9v.js +0 -231
  306. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DgTmNHN5.js +0 -2
  307. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-DQpKX9c1.js +0 -1
  308. package/templates/.agents/design/apps/catalog/dist/storybook/assets/CatalogShell-BWY-80s4.js +0 -1
  309. package/templates/.agents/design/apps/catalog/dist/storybook/assets/Components.stories-Be2mDUQj.js +0 -27
  310. package/templates/.agents/design/apps/catalog/dist/storybook/assets/DesignSystem.stories-DRx9blDs.js +0 -1
  311. package/templates/.agents/design/apps/catalog/dist/storybook/assets/formatter-L2YTDE3Q-EwuTh8Zk.js +0 -1
  312. package/templates/.agents/design/apps/catalog/dist/storybook/assets/react-DyL61NPT.js +0 -1
@@ -7,9 +7,26 @@ import {
7
7
  parseAgentCatalog,
8
8
  parseProjectConfig,
9
9
  parseYaml,
10
+ resolveAutonomy,
10
11
  serializeYaml,
11
12
  type WorkspaceFileSystem,
12
13
  } from "@zaip-ai/core";
14
+ import {
15
+ installationProfile,
16
+ type PROJECT_INSTALLATION_TOTAL,
17
+ type ProjectStatusSummary,
18
+ readDocumentAvailability,
19
+ summarizeProjectInstallation,
20
+ summarizeProjectStatus,
21
+ } from "./project-installation-summary.js";
22
+
23
+ export {
24
+ PROJECT_INSTALLATION_AREA_REQUIREMENTS,
25
+ PROJECT_INSTALLATION_STACK_REQUIREMENTS,
26
+ PROJECT_INSTALLATION_TOTAL,
27
+ summarizeProjectInstallation,
28
+ summarizeProjectStatus,
29
+ } from "./project-installation-summary.js";
13
30
 
14
31
  const AGENT_CATALOG_PATH = ".agents/config/agents/catalog.yaml";
15
32
  const CODEX_CONFIG_PATH = ".codex/config.toml";
@@ -17,30 +34,7 @@ const FRAMEWORK_LOCK_PATH = ".agents/config/framework.lock.yaml";
17
34
  const DASHBOARD_STACK_DEPENDENCIES_PATH = ".agents/dashboard/stack-dependencies.json";
18
35
  const exec = promisify(execFile);
19
36
  export const SOFTWARE_ARCHITECTURE_PATH = ".agents/architecture/software-architecture.md";
20
- export const PROJECT_INSTALLATION_STACK_REQUIREMENTS = [
21
- "Node.js",
22
- "TypeScript",
23
- "Vite",
24
- "Astro",
25
- "Redis",
26
- "BullMQ",
27
- "Hono",
28
- "React",
29
- "Git",
30
- "Terraform",
31
- ] as const;
32
- export const PROJECT_INSTALLATION_AREA_REQUIREMENTS = [
33
- "software_architecture",
34
- "design_system",
35
- "brandbook",
36
- "marketing_strategy",
37
- "sales_playbook",
38
- "growth_strategy",
39
- ] as const;
40
- export const PROJECT_INSTALLATION_TOTAL =
41
- PROJECT_INSTALLATION_STACK_REQUIREMENTS.length + PROJECT_INSTALLATION_AREA_REQUIREMENTS.length;
42
-
43
- export type ProjectOverview = {
37
+ export type ProjectOverview = ProjectStatusSummary & {
44
38
  framework_version: string | null;
45
39
  installation: {
46
40
  completed: number;
@@ -60,6 +54,7 @@ export type ProjectOverview = {
60
54
  source: string | null;
61
55
  verification: "exact" | "constraint" | "unavailable";
62
56
  installation: "runtime" | "installed" | "missing" | "bundled";
57
+ probe?: "verified" | "missing" | "unknown";
63
58
  }>;
64
59
  areas: Array<{
65
60
  id:
@@ -71,7 +66,7 @@ export type ProjectOverview = {
71
66
  | "sales_playbook";
72
67
  label: string;
73
68
  artifact: string;
74
- available: boolean;
69
+ available: boolean | null;
75
70
  }>;
76
71
  };
77
72
 
@@ -107,19 +102,27 @@ export async function readProjectOverview(
107
102
  countDirectMarkdownFiles(filesystem, ".agents/rules"),
108
103
  countCodexHookEvents(filesystem),
109
104
  ]);
110
- const [stack_components, areas] = await Promise.all([
105
+ const [project, stack_components, areas] = await Promise.all([
106
+ readProjectSettings(filesystem),
111
107
  readVerifiedStackComponents(filesystem),
112
108
  Promise.all(
113
109
  projectOverviewArtifacts.map(async (area) => ({
114
110
  ...area,
115
- available: await hasNonEmptyFile(filesystem, area.artifact),
111
+ available: await readDocumentAvailability(filesystem, area.artifact),
116
112
  })),
117
113
  ),
118
114
  ]);
119
115
  const installation = summarizeProjectInstallation(stack_components, areas);
116
+ const status = summarizeProjectStatus(
117
+ installationProfile(project),
118
+ stack_components,
119
+ areas,
120
+ "healthy",
121
+ );
120
122
  return {
121
123
  framework_version: frameworkVersion,
122
124
  installation,
125
+ ...status,
123
126
  metrics: [
124
127
  { id: "agents", label: "Agentes", value: catalog.agents.length },
125
128
  { id: "squads", label: "Squads", value: catalog.squads.length },
@@ -132,36 +135,6 @@ export async function readProjectOverview(
132
135
  };
133
136
  }
134
137
 
135
- export function summarizeProjectInstallation(
136
- stackComponents: ProjectOverview["stack_components"],
137
- areas: ProjectOverview["areas"],
138
- ): ProjectOverview["installation"] {
139
- const completed =
140
- PROJECT_INSTALLATION_STACK_REQUIREMENTS.filter((name) =>
141
- stackComponents.some(
142
- (component) => component.name === name && isInstalledLocalRequirement(component),
143
- ),
144
- ).length +
145
- PROJECT_INSTALLATION_AREA_REQUIREMENTS.filter((id) =>
146
- areas.some((area) => area.id === id && area.available),
147
- ).length;
148
- return {
149
- completed,
150
- total: PROJECT_INSTALLATION_TOTAL,
151
- percent: (completed / PROJECT_INSTALLATION_TOTAL) * 100,
152
- state: completed === PROJECT_INSTALLATION_TOTAL ? "complete" : "incomplete",
153
- };
154
- }
155
-
156
- function isInstalledLocalRequirement(
157
- component: ProjectOverview["stack_components"][number],
158
- ): boolean {
159
- return (
160
- component.verification === "exact" &&
161
- (component.installation === "runtime" || component.installation === "installed")
162
- );
163
- }
164
-
165
138
  async function readFrameworkVersion(filesystem: WorkspaceFileSystem): Promise<string | null> {
166
139
  try {
167
140
  const lock = recordValue(parseYaml(await filesystem.readText(FRAMEWORK_LOCK_PATH)));
@@ -246,13 +219,19 @@ async function readVerifiedStackComponents(
246
219
  ];
247
220
  }
248
221
 
249
- type InstalledPackage = { name: string; version: string | null; source: string | null };
222
+ type InstalledPackage = {
223
+ name: string;
224
+ version: string | null;
225
+ source: string | null;
226
+ probe: "verified" | "missing" | "unknown";
227
+ };
250
228
  type DashboardStackDependencies = { node: string | null; packages: Map<string, string> };
251
229
 
252
230
  async function readInstalledPackageVersion(
253
231
  filesystem: WorkspaceFileSystem,
254
232
  name: string,
255
233
  ): Promise<InstalledPackage> {
234
+ let uncertain = false;
256
235
  const roots = ["node_modules"];
257
236
  if (name === "hono") roots.push(".agents/dashboard/packages/local-runtime/node_modules");
258
237
  if (name === "react") roots.push(".agents/dashboard/apps/frontend/node_modules");
@@ -267,15 +246,18 @@ async function readInstalledPackageVersion(
267
246
  version === null ||
268
247
  !/^\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(version) ||
269
248
  entrypoint === null
270
- )
249
+ ) {
250
+ uncertain = true;
271
251
  continue;
252
+ }
272
253
  await filesystem.readText(`${root}/${name}/${entrypoint}`);
273
- return { name, version, source };
274
- } catch {
275
- // A pnpm workspace can install dependencies in the owning package only.
254
+ return { name, version, source, probe: "verified" };
255
+ } catch (error) {
256
+ // Absence is known only for ENOENT; invalid JSON and denied reads are unknown.
257
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") uncertain = true;
276
258
  }
277
259
  }
278
- return { name, version: null, source: null };
260
+ return { name, version: null, source: null, probe: uncertain ? "unknown" : "missing" };
279
261
  }
280
262
 
281
263
  async function readDashboardStackDependencies(
@@ -374,6 +356,7 @@ async function executableComponent(
374
356
  source: executable === command ? `Comando do workspace: ${command}` : local,
375
357
  verification: "exact",
376
358
  installation: executable === command ? "runtime" : "installed",
359
+ probe: "verified",
377
360
  };
378
361
  } catch {
379
362
  return {
@@ -383,6 +366,7 @@ async function executableComponent(
383
366
  source: null,
384
367
  verification: "unavailable",
385
368
  installation: "missing",
369
+ probe: "unknown",
386
370
  };
387
371
  }
388
372
  }
@@ -399,6 +383,7 @@ function runtimeComponent(
399
383
  source: `Runtime do Dashboard: ${process.execPath}`,
400
384
  verification: "exact",
401
385
  installation: "runtime",
386
+ probe: "verified",
402
387
  };
403
388
  }
404
389
 
@@ -418,6 +403,7 @@ function packageComponent(
418
403
  source: installed.get(packageName)?.source ?? null,
419
404
  verification: "exact",
420
405
  installation: "installed",
406
+ probe: "verified",
421
407
  };
422
408
  if (bundled)
423
409
  return {
@@ -430,6 +416,7 @@ function packageComponent(
430
416
  : ".agents/dashboard/apps/frontend/dist",
431
417
  verification: "unavailable",
432
418
  installation: "bundled",
419
+ probe: "unknown",
433
420
  };
434
421
  return {
435
422
  name,
@@ -438,6 +425,7 @@ function packageComponent(
438
425
  source: null,
439
426
  verification: "unavailable",
440
427
  installation: "missing",
428
+ probe: installed.get(packageName)?.probe ?? "missing",
441
429
  };
442
430
  }
443
431
 
@@ -535,6 +523,7 @@ const architectureLabels: Record<string, string> = {
535
523
  };
536
524
 
537
525
  export function renderSoftwareArchitecture(config: ProjectConfig): string {
526
+ const autonomy = resolveAutonomy(config.autonomy);
538
527
  const overrides = recordValue(config.stack.overrides);
539
528
  const components = recordValue(overrides.components);
540
529
  const languages = recordValue(overrides.languages);
@@ -556,14 +545,14 @@ export function renderSoftwareArchitecture(config: ProjectConfig): string {
556
545
  "",
557
546
  ]);
558
547
  const executionDetails =
559
- config.execution?.runtime === "autonomous"
548
+ config.execution && config.execution.runtime !== "manual"
560
549
  ? [
561
- "- **Runtime:** autonomous",
550
+ `- **Runtime:** ${config.execution.runtime}`,
562
551
  `- **Provider:** ${markdownCell(config.execution.autonomous.provider)}`,
563
552
  `- **Modelo-base:** ${markdownCell(config.execution.autonomous.model)}`,
564
553
  `- **Paralelismo máximo:** ${config.execution.autonomous.max_parallelism}`,
565
554
  `- **Lease configurado:** ${config.execution.autonomous.lease_ms} ms`,
566
- `- **Limite total de invocações:** ${config.execution.autonomous.max_total_invocations ?? "Não definido"}`,
555
+ `- **Limite total de invocações:** ${config.autonomy ? "Por Task; sem teto agregado de SPEC/PRD" : (config.execution.autonomous.max_total_invocations ?? "Não definido")}`,
567
556
  ]
568
557
  : [`- **Runtime:** ${config.execution?.runtime ?? "manual (padrão implícito)"}`];
569
558
  const assuranceDetails =
@@ -602,6 +591,18 @@ export function renderSoftwareArchitecture(config: ProjectConfig): string {
602
591
  "## Execução",
603
592
  "",
604
593
  ...executionDetails,
594
+ ...(config.autonomy
595
+ ? [
596
+ "",
597
+ "### Autonomia",
598
+ "",
599
+ `- **Perfil:** ${autonomy.label}`,
600
+ `- **Execuções por Task:** ${autonomy.attempts ?? "Ilimitadas"}`,
601
+ `- **Replanejamentos por Task:** ${autonomy.replans ?? "Ilimitados"}`,
602
+ "- Sem abandono por tempo. Tasks iniciadas preservam o perfil e os contadores.",
603
+ "- Subagentes podem ter modelo/esforço diferentes do principal, com aviso explícito.",
604
+ ]
605
+ : []),
605
606
  "",
606
607
  "## Assurance",
607
608
  "",
@@ -0,0 +1,91 @@
1
+ import { Hono } from "hono";
2
+ import { afterEach, describe, expect, it, vi } from "vitest";
3
+ import { registerBrowserLeaseRoute } from "./server-browser-lease.js";
4
+
5
+ afterEach(() => {
6
+ vi.useRealTimers();
7
+ vi.restoreAllMocks();
8
+ });
9
+
10
+ async function openLease(app: Hono) {
11
+ const response = await app.request("/api/v2/browser-lease");
12
+ if (response.body === null) throw new Error("Missing SSE body");
13
+ const reader = response.body.getReader();
14
+ const chunks: string[] = [];
15
+ const drained = (async () => {
16
+ for (;;) {
17
+ const chunk = await reader.read();
18
+ if (chunk.done) return;
19
+ chunks.push(new TextDecoder().decode(chunk.value));
20
+ }
21
+ })();
22
+ await vi.advanceTimersByTimeAsync(0);
23
+ expect(response.headers.get("content-type")).toContain("text/event-stream");
24
+ expect(chunks[0]).toContain("event: lease\ndata: active");
25
+ return {
26
+ chunks,
27
+ close: async () => {
28
+ await reader.cancel();
29
+ await drained;
30
+ },
31
+ };
32
+ }
33
+
34
+ describe("browser lease lifecycle", () => {
35
+ it("keeps the real SSE body active past a five-minute idle timeout", async () => {
36
+ vi.useFakeTimers();
37
+ const exit = vi.spyOn(process, "exit").mockImplementation(() => undefined as never);
38
+ const app = new Hono();
39
+ registerBrowserLeaseRoute(app, "/api/v2", true);
40
+ const lease = await openLease(app);
41
+ try {
42
+ for (let interval = 0; interval < 31; interval++) {
43
+ const before = lease.chunks.length;
44
+ await vi.advanceTimersByTimeAsync(10_000);
45
+ expect(lease.chunks.length).toBeGreaterThan(before);
46
+ expect(lease.chunks.at(-1)).toContain(": keep-alive\n\n");
47
+ expect(exit).not.toHaveBeenCalled();
48
+ }
49
+ } finally {
50
+ await lease.close();
51
+ }
52
+ expect(vi.getTimerCount()).toBe(1);
53
+ await vi.advanceTimersByTimeAsync(11_999);
54
+ expect(exit).not.toHaveBeenCalled();
55
+ await vi.advanceTimersByTimeAsync(1);
56
+ expect(exit).toHaveBeenCalledExactlyOnceWith(0);
57
+ });
58
+
59
+ it("expires only after the last client closes and a replacement cancels expiry", async () => {
60
+ vi.useFakeTimers();
61
+ const exit = vi.spyOn(process, "exit").mockImplementation(() => undefined as never);
62
+ const app = new Hono();
63
+ registerBrowserLeaseRoute(app, "/api/v2", true);
64
+ const first = await openLease(app);
65
+ const second = await openLease(app);
66
+ await first.close();
67
+ await vi.advanceTimersByTimeAsync(13_000);
68
+ expect(exit).not.toHaveBeenCalled();
69
+ await second.close();
70
+ await vi.advanceTimersByTimeAsync(11_000);
71
+ const replacement = await openLease(app);
72
+ await vi.advanceTimersByTimeAsync(13_000);
73
+ expect(exit).not.toHaveBeenCalled();
74
+ await replacement.close();
75
+ await vi.advanceTimersByTimeAsync(12_000);
76
+ expect(exit).toHaveBeenCalledExactlyOnceWith(0);
77
+ expect(vi.getTimerCount()).toBe(0);
78
+ });
79
+
80
+ it("does not terminate an unmanaged server or retain a heartbeat after cancellation", async () => {
81
+ vi.useFakeTimers();
82
+ const exit = vi.spyOn(process, "exit").mockImplementation(() => undefined as never);
83
+ const app = new Hono();
84
+ registerBrowserLeaseRoute(app, "/api/v2");
85
+ const lease = await openLease(app);
86
+ await lease.close();
87
+ await vi.advanceTimersByTimeAsync(60_000);
88
+ expect(exit).not.toHaveBeenCalled();
89
+ expect(vi.getTimerCount()).toBe(0);
90
+ });
91
+ });
@@ -13,7 +13,7 @@ export function registerBrowserLeaseRoute(
13
13
  browserLeaseDeadline.unref();
14
14
  }
15
15
  const releaseBrowserLease = (lease: object) => {
16
- browserLeases.delete(lease);
16
+ if (!browserLeases.delete(lease)) return;
17
17
  if (!launcherOwned || browserLeases.size !== 0) return;
18
18
  if (browserLeaseDeadline !== undefined) clearTimeout(browserLeaseDeadline);
19
19
  browserLeaseDeadline = setTimeout(() => process.exit(0), 12_000);
@@ -25,9 +25,29 @@ export function registerBrowserLeaseRoute(
25
25
  browserLeaseDeadline = undefined;
26
26
  browserLeases.add(lease);
27
27
  return streamSSE(context, async (stream) => {
28
- stream.onAbort(() => releaseBrowserLease(lease));
29
- await stream.writeSSE({ event: "lease", data: "active" });
30
- await new Promise(() => {});
28
+ let heartbeat: NodeJS.Timeout | undefined;
29
+ let wake: (() => void) | undefined;
30
+ stream.onAbort(() => {
31
+ if (heartbeat !== undefined) clearTimeout(heartbeat);
32
+ wake?.();
33
+ releaseBrowserLease(lease);
34
+ });
35
+ try {
36
+ await stream.writeSSE({ event: "lease", data: "active" });
37
+ while (!stream.aborted) {
38
+ await new Promise<void>((resolve) => {
39
+ wake = resolve;
40
+ heartbeat = setTimeout(resolve, 10_000);
41
+ heartbeat.unref();
42
+ });
43
+ // SSE comments keep idle HTTP clients alive without changing the
44
+ // browser's lease event contract or accumulating overlapping writes.
45
+ if (!stream.aborted) await stream.write(": keep-alive\n\n");
46
+ }
47
+ } finally {
48
+ if (heartbeat !== undefined) clearTimeout(heartbeat);
49
+ releaseBrowserLease(lease);
50
+ }
31
51
  });
32
52
  });
33
53
  }
@@ -0,0 +1,17 @@
1
+ import { Hono } from "hono";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ describe("Dashboard HTTP query security", () => {
5
+ const app = new Hono().get("/", (context) => context.json(context.req.query()));
6
+
7
+ it("does not interpret a question mark inside a URL fragment as a query", async () => {
8
+ const response = await app.request("http://localhost/#?admin=true");
9
+ expect(response.status).toBe(200);
10
+ expect(await response.json()).toEqual({});
11
+ });
12
+
13
+ it("preserves real query parameters but excludes fragment parameters", async () => {
14
+ const response = await app.request("http://localhost/?currency=BRL#?admin=true");
15
+ expect(await response.json()).toEqual({ currency: "BRL" });
16
+ });
17
+ });
@@ -52,14 +52,14 @@ export function registerOperationsRoutes(app: Hono, dependencies: DashboardRoute
52
52
  scope !== "quick" &&
53
53
  scope !== "detail" &&
54
54
  scope !== "board" &&
55
+ scope !== "traceability" &&
55
56
  scope !== "classification"
56
57
  )
57
58
  return headOrJson(context, (await readSnapshot(context)).operations);
58
59
  const layout = await readLayout();
59
60
  const layoutMs = performance.now() - requestStartedAt;
60
61
  const { from, to } = projectionPeriodFilter(context);
61
- if (scope === "board") {
62
- const stage = boardStage(context.req.query("stage"));
62
+ if (scope === "board" || scope === "traceability") {
63
63
  const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
64
64
  const limit = Math.min(
65
65
  50,
@@ -80,6 +80,25 @@ export function registerOperationsRoutes(app: Hono, dependencies: DashboardRoute
80
80
  };
81
81
  },
82
82
  );
83
+ // Traceability is an identity index, not an executable Kanban column.
84
+ // Drafts remain discoverable without changing their canonical state.
85
+ if (scope === "traceability") {
86
+ const tasks = board.projection.tasks.toSorted(
87
+ (a, b) => b.created_at.localeCompare(a.created_at) || b.id.localeCompare(a.id),
88
+ );
89
+ return headOrJson(
90
+ context,
91
+ {
92
+ tasks: tasks.slice(offset, offset + limit),
93
+ total: tasks.length,
94
+ offset,
95
+ limit,
96
+ },
97
+ 200,
98
+ true,
99
+ );
100
+ }
101
+ const stage = boardStage(context.req.query("stage"));
83
102
  const filters = boardFilters(context);
84
103
  const pageKey = JSON.stringify({ from, to, stage, offset, limit, ...filters });
85
104
  const page = await readAggregate(`operations:board-page:${pageKey}`, async () =>
@@ -1,6 +1,21 @@
1
1
  import { EventEmitter } from "node:events";
2
- import { describe, expect, it } from "vitest";
3
- import { attachRefreshWorkerCleanup } from "./server-snapshot-refresh.js";
2
+ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { DatabaseSync } from "node:sqlite";
6
+ import { describe, expect, it, vi } from "vitest";
7
+ import {
8
+ attachRefreshWorkerCleanup,
9
+ refreshSqliteSnapshotInWorker,
10
+ validateSnapshotWorkerReceipt,
11
+ } from "./server-snapshot-refresh.js";
12
+ import { SqliteReadModelFileSystem } from "./sqlite-read-model-filesystem.js";
13
+ import {
14
+ readModelSchemaVersion,
15
+ requiredIndexes,
16
+ requiredPersistedTables,
17
+ requiredViews,
18
+ } from "./sqlite-read-model-schema.js";
4
19
 
5
20
  describe("snapshot refresh shutdown", () => {
6
21
  it("terminates an active refresh worker on runtime shutdown and removes its listener on completion", () => {
@@ -17,3 +32,80 @@ describe("snapshot refresh shutdown", () => {
17
32
  expect(calls).toEqual(["SIGTERM"]);
18
33
  });
19
34
  });
35
+
36
+ describe("snapshot worker process boundary", () => {
37
+ it.each([
38
+ "valid",
39
+ "empty",
40
+ "wrong-path",
41
+ "nonzero",
42
+ "oversized",
43
+ ] as const)("reopens only after valid receipt and successful process close: %s", async (mode) => {
44
+ const root = await mkdtemp(join(tmpdir(), "zaip-refresh-receipt-"));
45
+ const db = new DatabaseSync(":memory:");
46
+ const filesystem = new SqliteReadModelFileSystem(root, db);
47
+ const refresh = vi.spyOn(filesystem, "refresh").mockImplementation(() => undefined);
48
+ try {
49
+ const scripts = join(root, ".agents/dashboard/packages/local-runtime/scripts");
50
+ await mkdir(scripts, { recursive: true });
51
+ // This fixture tests native transport/failure handling, not DB integrity.
52
+ // The shipped rebuild script performs the real schema/integrity validation.
53
+ await writeFile(
54
+ join(scripts, "rebuild-sqlite-read-model.mjs"),
55
+ `
56
+ const receipt = {storage_mode:'sqlite_read_model',
57
+ path: ${JSON.stringify(mode)} === 'wrong-path' ? 'other.sqlite' : process.env.ZAIP_SQLITE_DB_PATH,
58
+ schema: ${JSON.stringify({ schemaVersion: readModelSchemaVersion, tableCount: requiredPersistedTables.length, viewCount: requiredViews.length, indexCount: requiredIndexes.length })}};
59
+ if (${JSON.stringify(mode)} !== 'empty') {
60
+ if (${JSON.stringify(mode)} === 'oversized') process.stdout.write(' '.repeat(64001));
61
+ const output = JSON.stringify(receipt);
62
+ process.stdout.write(output.slice(0, 20));
63
+ setTimeout(() => process.stdout.write(output.slice(20)), 5);
64
+ }
65
+ process.exitCode = ${mode === "nonzero" ? 1 : 0};
66
+ `,
67
+ );
68
+ if (mode === "valid") {
69
+ await expect(refreshSqliteSnapshotInWorker(root, filesystem)).resolves.toBeUndefined();
70
+ expect(refresh).toHaveBeenCalledTimes(1);
71
+ } else {
72
+ await expect(refreshSqliteSnapshotInWorker(root, filesystem)).rejects.toThrow();
73
+ expect(refresh).not.toHaveBeenCalled();
74
+ }
75
+ } finally {
76
+ refresh.mockRestore();
77
+ db.close();
78
+ await rm(root, { recursive: true, force: true });
79
+ }
80
+ });
81
+ });
82
+
83
+ describe("validated worker receipt", () => {
84
+ const destination = "snapshot.sqlite";
85
+ const receipt = {
86
+ storage_mode: "sqlite_read_model",
87
+ path: destination,
88
+ schema: {
89
+ schemaVersion: readModelSchemaVersion,
90
+ tableCount: requiredPersistedTables.length,
91
+ viewCount: requiredViews.length,
92
+ indexCount: requiredIndexes.length,
93
+ },
94
+ };
95
+ it("accepts the exact schema-validated destination without scanning it on the HTTP thread", () => {
96
+ // The path need not exist in this process: only the worker does the heavy check.
97
+ expect(() => validateSnapshotWorkerReceipt(JSON.stringify(receipt), destination)).not.toThrow();
98
+ });
99
+ it.each([
100
+ "",
101
+ "null",
102
+ "{}",
103
+ JSON.stringify({ ...receipt, path: "other.sqlite" }),
104
+ JSON.stringify({ ...receipt, schema: { ...receipt.schema, schemaVersion: "old" } }),
105
+ JSON.stringify({ ...receipt, schema: { ...receipt.schema, indexCount: 0 } }),
106
+ JSON.stringify({ ...receipt, schema: { ...receipt.schema, tableCount: 0 } }),
107
+ JSON.stringify({ ...receipt, schema: { ...receipt.schema, viewCount: null } }),
108
+ ])("rejects absent, stale or unrelated validation: %s", (value) => {
109
+ expect(() => validateSnapshotWorkerReceipt(value, destination)).toThrow();
110
+ });
111
+ });