@zaip-ai/cli 3.8.0 → 4.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 (274) hide show
  1. package/README.md +5 -5
  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 +11 -6
  5. package/dist/services/adapters.js.map +1 -1
  6. package/dist/services/agent-adapters.js +1 -1
  7. package/dist/services/agent-adapters.js.map +1 -1
  8. package/dist/services/backup-gitignore.d.ts +9 -0
  9. package/dist/services/backup-gitignore.d.ts.map +1 -0
  10. package/dist/services/backup-gitignore.js +66 -0
  11. package/dist/services/backup-gitignore.js.map +1 -0
  12. package/dist/services/backup-gitignore.test.d.ts +2 -0
  13. package/dist/services/backup-gitignore.test.d.ts.map +1 -0
  14. package/dist/services/backup-gitignore.test.js +27 -0
  15. package/dist/services/backup-gitignore.test.js.map +1 -0
  16. package/dist/services/codex-config-template.d.ts +2 -2
  17. package/dist/services/codex-config-template.d.ts.map +1 -1
  18. package/dist/services/codex-config-template.js +4 -3
  19. package/dist/services/codex-config-template.js.map +1 -1
  20. package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
  21. package/dist/services/codex-conversation-lifecycle-hook.js +15 -7
  22. package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
  23. package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
  24. package/dist/services/codex-pre-tool-hook-template.js +10 -11
  25. package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
  26. package/dist/services/codex-pre-tool-hook-template.test.d.ts +2 -0
  27. package/dist/services/codex-pre-tool-hook-template.test.d.ts.map +1 -0
  28. package/dist/services/codex-pre-tool-hook-template.test.js +33 -0
  29. package/dist/services/codex-pre-tool-hook-template.test.js.map +1 -0
  30. package/dist/services/codex-subagent-hook-template.d.ts +1 -1
  31. package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
  32. package/dist/services/codex-subagent-hook-template.js +3 -0
  33. package/dist/services/codex-subagent-hook-template.js.map +1 -1
  34. package/dist/services/codex-windows-hook-command.d.ts +3 -0
  35. package/dist/services/codex-windows-hook-command.d.ts.map +1 -0
  36. package/dist/services/codex-windows-hook-command.js +10 -0
  37. package/dist/services/codex-windows-hook-command.js.map +1 -0
  38. package/dist/services/codex-windows-hook-command.test.d.ts +2 -0
  39. package/dist/services/codex-windows-hook-command.test.d.ts.map +1 -0
  40. package/dist/services/codex-windows-hook-command.test.js +44 -0
  41. package/dist/services/codex-windows-hook-command.test.js.map +1 -0
  42. package/dist/services/global-codex-config.d.ts.map +1 -1
  43. package/dist/services/global-codex-config.js +27 -13
  44. package/dist/services/global-codex-config.js.map +1 -1
  45. package/dist/services/global-codex-config.test.js +27 -2
  46. package/dist/services/global-codex-config.test.js.map +1 -1
  47. package/dist/services/install-agents-template.d.ts.map +1 -1
  48. package/dist/services/install-agents-template.js +43 -127
  49. package/dist/services/install-agents-template.js.map +1 -1
  50. package/dist/services/install-template-policy.d.ts.map +1 -1
  51. package/dist/services/install-template-policy.js +2 -0
  52. package/dist/services/install-template-policy.js.map +1 -1
  53. package/dist/services/legacy-records-migration.d.ts +15 -0
  54. package/dist/services/legacy-records-migration.d.ts.map +1 -0
  55. package/dist/services/legacy-records-migration.js +109 -0
  56. package/dist/services/legacy-records-migration.js.map +1 -0
  57. package/dist/services/local-state-migration.d.ts +8 -1
  58. package/dist/services/local-state-migration.d.ts.map +1 -1
  59. package/dist/services/local-state-migration.js +67 -32
  60. package/dist/services/local-state-migration.js.map +1 -1
  61. package/dist/services/logger.d.ts.map +1 -1
  62. package/dist/services/logger.js +2 -0
  63. package/dist/services/logger.js.map +1 -1
  64. package/dist/services/project-model-migration.d.ts +3 -0
  65. package/dist/services/project-model-migration.d.ts.map +1 -0
  66. package/dist/services/project-model-migration.js +163 -0
  67. package/dist/services/project-model-migration.js.map +1 -0
  68. package/dist/services/project-model-migration.test.d.ts +2 -0
  69. package/dist/services/project-model-migration.test.d.ts.map +1 -0
  70. package/dist/services/project-model-migration.test.js +62 -0
  71. package/dist/services/project-model-migration.test.js.map +1 -0
  72. package/dist/services/template-manifest.d.ts.map +1 -1
  73. package/dist/services/template-manifest.js +2 -0
  74. package/dist/services/template-manifest.js.map +1 -1
  75. package/dist/services/transactional-files.d.ts +1 -0
  76. package/dist/services/transactional-files.d.ts.map +1 -1
  77. package/dist/services/transactional-files.js +3 -0
  78. package/dist/services/transactional-files.js.map +1 -1
  79. package/dist/types.d.ts +1 -0
  80. package/dist/types.d.ts.map +1 -1
  81. package/package.json +1 -1
  82. package/templates/.agents/README-ENG.md +88 -32
  83. package/templates/.agents/README.md +57 -30
  84. package/templates/.agents/config/agents/discovery.json +1 -1
  85. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -1
  86. package/templates/.agents/config/project.yaml +21 -7
  87. package/templates/.agents/dashboard/.zaip-managed.json +184 -112
  88. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-D2PL4UOu.js → CostCalculationGuidePage-f4ZGJRg3.js} +1 -1
  89. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-CocoP9CA.js → DashboardHelpDialog-DlN5EMmD.js} +238 -124
  90. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-D255_hNf.js → PricingSettingsDialog-v9zGRTlk.js} +1 -1
  91. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BRdoeTWk.js +3 -0
  92. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-BTFSLQ69.js → TraceabilityWorkspace-B_5u4Xnp.js} +1 -1
  93. package/templates/.agents/dashboard/apps/frontend/dist/assets/{cost-monitor-BsMfGfQi.css → cost-monitor-C2AFYBu_.css} +1 -1
  94. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-D7PrDZy9.js +68 -0
  95. package/templates/.agents/dashboard/apps/frontend/dist/assets/{dashboard-localization-058lag33.js → dashboard-localization-CF7B1Hjn.js} +88 -32
  96. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DeFPiN32.js → icons-vendor-Cv3WBFIF.js} +1 -1
  97. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-C4rLXrz_.js +2 -0
  98. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-BIWcbEAc.js → react-vendor-mHgsmxb6.js} +1 -1
  99. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-fZZL0ohD.js → traceability-B0CPyEVq.js} +1 -1
  100. package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
  101. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  102. package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +11 -1
  103. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingBoundary.tsx +3 -2
  104. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingPanels.tsx +1 -1
  105. package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +1 -1
  106. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +9 -13
  107. package/templates/.agents/dashboard/apps/frontend/src/cost-monitor-population.test.tsx +4 -2
  108. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +9 -5
  109. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +3 -2
  110. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +2 -2
  111. package/templates/.agents/dashboard/apps/frontend/src/dashboard-identity.test.ts +3 -3
  112. package/templates/.agents/dashboard/apps/frontend/src/dashboard-identity.ts +1 -1
  113. package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.test.ts +2 -1
  114. package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +40 -3
  115. package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +12 -1
  116. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +19 -0
  117. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +1 -1
  118. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +3 -1
  119. package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +14 -23
  120. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  121. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +3 -3
  122. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +2 -3
  123. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionTable.tsx +2 -6
  124. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.period-values.test.tsx +66 -0
  125. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.tsx +29 -34
  126. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.embedded.test.ts +11 -0
  127. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +1 -13
  128. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.test.tsx +23 -0
  129. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.tsx +2 -1
  130. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableDisplay.ts +6 -11
  131. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +6 -6
  132. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +10 -12
  133. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-group-page-totals.ts +23 -0
  134. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-group-period-values.tsx +34 -0
  135. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-embedded.css +0 -7
  136. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-formatters.ts +4 -9
  137. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-presentation.ts +2 -3
  138. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  139. package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.tsx +2 -12
  140. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +2 -2
  141. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +1 -6
  142. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +34 -36
  143. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewCharts.tsx +12 -3
  144. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewTopPanel.tsx +12 -14
  145. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +4 -4
  146. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +23 -4
  147. package/templates/.agents/dashboard/modules/operations/src/react/OverviewCostKpi.tsx +30 -2
  148. package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +2 -13
  149. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.priority.test.ts +8 -1
  150. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +8 -16
  151. package/templates/.agents/dashboard/modules/operations/src/react/WorkColumnState.tsx +34 -0
  152. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +1 -1
  153. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +1 -1
  154. package/templates/.agents/dashboard/modules/operations/src/react/operations-average-unmeasured.test.ts +10 -0
  155. package/templates/.agents/dashboard/modules/operations/src/react/operations-content-visibility.ts +3 -0
  156. package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +4 -3
  157. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +12 -1
  158. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +1 -0
  159. package/templates/.agents/dashboard/modules/operations/src/react/operations-skeleton.css +80 -0
  160. package/templates/.agents/dashboard/modules/operations/src/react/operations.css +2 -11
  161. package/templates/.agents/dashboard/modules/operations/src/react/overview-cost-card.test.tsx +36 -0
  162. package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.test.ts +11 -0
  163. package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.ts +28 -3
  164. package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-stats.ts +44 -0
  165. package/templates/.agents/dashboard/modules/operations/src/react/work-card-label.ts +5 -0
  166. package/templates/.agents/dashboard/modules/operations/src/react/work-column-state.ts +11 -0
  167. package/templates/.agents/dashboard/modules/operations/src/react/work-item-filter.ts +13 -0
  168. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  169. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  170. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  171. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  172. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +157 -157
  173. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +153 -153
  174. package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
  175. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +159 -159
  176. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.test.ts +31 -0
  177. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +74 -1
  178. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +1 -1
  179. package/templates/.agents/dashboard/packages/local-runtime/src/server-identity.test.ts +1 -1
  180. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +25 -3
  181. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +51 -16
  182. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +1 -1
  183. package/templates/.agents/dashboard/packages/local-runtime/src/server-ui-security.ts +37 -0
  184. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +1 -1
  185. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +11 -33
  186. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +12 -13
  187. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.test.ts +71 -1
  188. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +141 -25
  189. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-worktree-sources.test.ts +60 -0
  190. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-rebuild-fingerprint-options.ts +13 -0
  191. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +26 -2
  192. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.test.mjs +5 -0
  193. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  194. package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.test.mjs +5 -0
  195. package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.tsx +4 -4
  196. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  197. package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -0
  198. package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +4 -4
  199. package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +1 -1
  200. package/templates/.agents/dashboard/tests/e2e/specs/performance-work-row-identity.ts +6 -0
  201. package/templates/.agents/design/.zaip-managed.json +13 -9
  202. package/templates/.agents/design/apps/catalog/dist/assets/index-DkpQYoyC.js +72 -0
  203. package/templates/.agents/design/apps/catalog/dist/index.html +1 -1
  204. package/templates/.agents/design/apps/catalog/package.json +1 -1
  205. package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.test.tsx +8 -4
  206. package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.tsx +10 -3
  207. package/templates/.agents/design/apps/catalog/src/components/DashboardFiltersSpecimen.tsx +0 -15
  208. package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +3 -3
  209. package/templates/.agents/design/apps/catalog/src/stories/DashboardFilters.stories.tsx +0 -1
  210. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  211. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  212. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
  213. package/templates/.agents/requirements/comparative-audit.md +1 -1
  214. package/templates/.agents/requirements/context-engine.md +1 -1
  215. package/templates/.agents/requirements/cost-observability.md +1 -1
  216. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  217. package/templates/.agents/requirements/data-export.md +1 -1
  218. package/templates/.agents/requirements/design-system.md +1 -1
  219. package/templates/.agents/requirements/execution-engine.md +1 -1
  220. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  221. package/templates/.agents/requirements/model-orchestration.md +1 -1
  222. package/templates/.agents/requirements/public-distribution.md +1 -1
  223. package/templates/.agents/requirements/software-architecture.md +1 -1
  224. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  225. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  226. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  227. package/templates/.agents/rules/autonomy-decision.md +2 -2
  228. package/templates/.agents/rules/workflow.md +1 -1
  229. package/templates/.agents/runtime/VERSION +1 -1
  230. package/templates/.agents/runtime/bin/zaip.mjs +65 -54
  231. package/templates/.agents/runtime/checksums.sha256 +5 -5
  232. package/templates/.agents/runtime/manifest.json +1 -1
  233. package/templates/.agents/runtime/provenance.json +4 -4
  234. package/templates/.agents/runtime/sbom.cdx.json +1 -1
  235. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/SKILL.md +7 -7
  236. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.mjs +32 -7
  237. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.test.mjs +134 -1
  238. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-lease.mjs +57 -0
  239. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/scheduled-ready-queue-contract.test.mjs +9 -6
  240. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
  241. package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +2 -2
  242. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +18 -6
  243. package/templates/.agents/skills/zaip-skill-instalar-agendamento/SKILL.md +2 -2
  244. package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +6 -0
  245. package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +47 -5
  246. package/templates/.agents/zaip-aios/README.md +4 -4
  247. package/templates/.agents/zaip-aios/VERSION +1 -1
  248. package/templates/.agents/zaip-aios/guides/01-primeiros-passos.md +4 -3
  249. package/templates/.agents/zaip-aios/guides/03-tasks.md +5 -4
  250. package/templates/.agents/zaip-aios/guides/04-specs.md +4 -1
  251. package/templates/.agents/zaip-aios/guides/05-prds.md +7 -3
  252. package/templates/.agents/zaip-aios/guides/06-execucao.md +9 -4
  253. package/templates/.agents/zaip-aios/guides/09-agentes-e-squads.md +9 -5
  254. package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +10 -2
  255. package/templates/.agents/zaip-aios/guides/12-instalacao-e-upgrade.md +10 -5
  256. package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +12 -1
  257. package/templates/.agents/zaip-aios/guides/14-troubleshooting.md +3 -1
  258. package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +12 -7
  259. package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +1 -1
  260. package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +4 -0
  261. package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +19 -15
  262. package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +12 -8
  263. package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +4 -3
  264. package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +9 -7
  265. package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +38 -22
  266. package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +1 -1
  267. package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +14 -5
  268. package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +6 -0
  269. package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +129 -11
  270. package/templates/template-manifest.json +270 -186
  271. package/templates/tsconfig.base.json +22 -0
  272. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-0f_x2TzJ.js +0 -3
  273. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-zhY2JoLc.js +0 -68
  274. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Dh95Yodm.js +0 -2
@@ -1,6 +1,10 @@
1
+ import { execFile } from "node:child_process";
1
2
  import { createHash } from "node:crypto";
2
3
  import { readdir, readFile, stat } from "node:fs/promises";
3
4
  import { join, relative, resolve } from "node:path";
5
+ import { promisify } from "node:util";
6
+
7
+ const execFileAsync = promisify(execFile);
4
8
 
5
9
  const textExtensions = new Set([".json", ".jsonl", ".md", ".yaml", ".yml", ".txt"]);
6
10
 
@@ -45,8 +49,141 @@ export type SqliteReadModelSourceCheckpoint = Omit<SqliteReadModelSourceCandidat
45
49
  type FingerprintOptions = {
46
50
  previous?: ReadonlyMap<string, SqliteReadModelSourceCheckpoint>;
47
51
  verifyContent?: boolean;
52
+ /** Explicit roots allow deterministic testing without a Git checkout. */
53
+ sourceRoots?: readonly string[] | undefined;
48
54
  };
49
55
 
56
+ export async function dashboardCanonicalSourceRoots(workspaceRoot: string): Promise<string[]> {
57
+ const primary = resolve(workspaceRoot);
58
+ const gitRoot = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
59
+ cwd: primary,
60
+ encoding: "utf8",
61
+ windowsHide: true,
62
+ timeout: 5_000,
63
+ }).catch(() => ({ stdout: "" }));
64
+ if (resolve(gitRoot.stdout.trim()).toLowerCase() !== primary.toLowerCase()) return [primary];
65
+ const output = await execFileAsync("git", ["worktree", "list", "--porcelain"], {
66
+ cwd: primary,
67
+ encoding: "utf8",
68
+ windowsHide: true,
69
+ timeout: 15_000,
70
+ }).catch(() => ({ stdout: "" }));
71
+ // Git supplies only worktrees registered to this repository. Ignore unrelated
72
+ // sibling folders and ordinary task workspaces; they are not Codex worktrees.
73
+ const registeredRoots = output.stdout
74
+ .split(/\r?\n/u)
75
+ .filter((line) => line.startsWith("worktree "))
76
+ .map((line) => resolve(line.slice(9).trim()));
77
+ const codexRoots = registeredRoots.filter(isCodexManagedWorktreeRoot);
78
+ // The first registered checkout is the repository's main worktree and may
79
+ // contain canonical history absent from a Codex worktree's branch.
80
+ return [...new Set([primary, ...registeredRoots.slice(0, 1), ...codexRoots])];
81
+ }
82
+
83
+ export function isCodexManagedWorktreeRoot(root: string): boolean {
84
+ // Internal Task workspaces can sit below a managed checkout but are not
85
+ // separate Codex checkouts. Avoid re-scanning that nested copy on every
86
+ // dashboard refresh.
87
+ return /[\\/]\.codex[\\/]worktrees(?:[\\/][^\\/]+){1,2}$/iu.test(root);
88
+ }
89
+
90
+ function canonicalRevision(content: string, source: string): [string, number, number] {
91
+ if (source.endsWith(".jsonl")) {
92
+ const dates = [...content.matchAll(/"occurred_at"\s*:\s*"([^"]+)"/gu)];
93
+ return [
94
+ dates.reduce((latest, match) => ((match[1] ?? "") > latest ? (match[1] ?? "") : latest), ""),
95
+ dates.length,
96
+ content.length,
97
+ ];
98
+ }
99
+ const updated = /^updated_at:\s*([^\r\n]+)/mu.exec(content)?.[1]?.trim() ?? "";
100
+ const created = /^created_at:\s*([^\r\n]+)/mu.exec(content)?.[1]?.trim() ?? "";
101
+ const revision = Number(/^revision:\s*(\d+)/mu.exec(content)?.[1] ?? 0);
102
+ return [updated || created, revision, content.length];
103
+ }
104
+
105
+ async function selectCanonicalSources(
106
+ roots: readonly string[],
107
+ ): Promise<Array<{ path: string; source: string }>> {
108
+ const locations = new Map<string, string[]>();
109
+ for (const [index, root] of roots.entries()) {
110
+ const directories =
111
+ index === 0
112
+ ? [
113
+ ".agents/config",
114
+ ...[
115
+ "tasks",
116
+ "specs",
117
+ "prds",
118
+ "runs",
119
+ "executions",
120
+ "changes",
121
+ "lifecycle/historical-developer-attribution",
122
+ ].flatMap((kind) => [`.agents/data/${kind}`, `.agents/records/${kind}`]),
123
+ ]
124
+ : [
125
+ "tasks",
126
+ "specs",
127
+ "prds",
128
+ "runs",
129
+ "executions",
130
+ "changes",
131
+ "lifecycle/historical-developer-attribution",
132
+ ].map((kind) => `.agents/records/${kind}`);
133
+ const paths = (
134
+ await Promise.all(directories.map((directory) => listFiles(resolve(root, directory))))
135
+ ).flat();
136
+ for (const path of paths) {
137
+ const source = relative(root, path).replaceAll("\\", "/");
138
+ if (
139
+ !textExtensions.has(path.slice(path.lastIndexOf(".")).toLowerCase()) ||
140
+ !isDashboardCanonicalSource(source)
141
+ )
142
+ continue;
143
+ const peers = locations.get(source) ?? [];
144
+ peers.push(path);
145
+ locations.set(source, peers);
146
+ }
147
+ }
148
+ const selected: Array<{ path: string; source: string }> = [];
149
+ const entries = [...locations.entries()];
150
+ for (let offset = 0; offset < entries.length; offset += 32) {
151
+ selected.push(
152
+ ...(await Promise.all(
153
+ entries.slice(offset, offset + 32).map(async ([source, paths]) => {
154
+ const firstPath = paths[0];
155
+ if (firstPath === undefined) throw new Error(`No canonical source for ${source}`);
156
+ if (paths.length === 1) return { source, path: firstPath };
157
+ // Worktree checkout mtimes do not represent canonical record recency.
158
+ // Compare embedded revision timestamps and prefer the first registered
159
+ // source on an exact tie, so repeated scans remain deterministic.
160
+ const revisions = await Promise.all(
161
+ paths.map(async (path) => canonicalRevision(await readFile(path, "utf8"), source)),
162
+ );
163
+ let winner = 0;
164
+ for (let index = 1; index < paths.length; index += 1) {
165
+ const left = revisions[index];
166
+ const right = revisions[winner];
167
+ if (left === undefined || right === undefined)
168
+ throw new Error(`Incomplete canonical revisions for ${source}`);
169
+ if (
170
+ left[0] > right[0] ||
171
+ (left[0] === right[0] &&
172
+ (left[1] > right[1] || (left[1] === right[1] && left[2] > right[2])))
173
+ )
174
+ winner = index;
175
+ }
176
+ const selectedPath = paths[winner];
177
+ if (selectedPath === undefined)
178
+ throw new Error(`No selected canonical source for ${source}`);
179
+ return { source, path: selectedPath };
180
+ }),
181
+ )),
182
+ );
183
+ }
184
+ return selected.sort((left, right) => left.source.localeCompare(right.source));
185
+ }
186
+
50
187
  export async function sourceFingerprint(
51
188
  workspaceRoot: string,
52
189
  options: FingerprintOptions = {},
@@ -56,29 +193,9 @@ export async function sourceFingerprint(
56
193
  hashedFiles: number;
57
194
  reusedFiles: number;
58
195
  }> {
59
- const candidates = (
60
- await Promise.all(
61
- [
62
- ".agents/config",
63
- ...[
64
- "tasks",
65
- "specs",
66
- "prds",
67
- "runs",
68
- "executions",
69
- "changes",
70
- "lifecycle/historical-developer-attribution",
71
- ].flatMap((kind) => [`.agents/data/${kind}`, `.agents/records/${kind}`]),
72
- ].map((root) => listFiles(resolve(workspaceRoot, root))),
73
- )
74
- )
75
- .flat()
76
- .filter(
77
- (path) =>
78
- textExtensions.has(path.slice(path.lastIndexOf(".")).toLowerCase()) &&
79
- isDashboardCanonicalSource(relative(workspaceRoot, path).replaceAll("\\", "/")),
80
- )
81
- .sort();
196
+ const candidates = await selectCanonicalSources(
197
+ options.sourceRoots ?? (await dashboardCanonicalSourceRoots(workspaceRoot)),
198
+ );
82
199
  const candidatesWithMetadata: SqliteReadModelSourceCandidate[] = [];
83
200
  let hashedFiles = 0;
84
201
  let reusedFiles = 0;
@@ -91,8 +208,7 @@ export async function sourceFingerprint(
91
208
  candidatesWithMetadata.push(
92
209
  ...(
93
210
  await Promise.all(
94
- candidates.slice(offset, offset + 32).map(async (candidate) => {
95
- const source = relative(workspaceRoot, candidate).replaceAll("\\", "/");
211
+ candidates.slice(offset, offset + 32).map(async ({ path: candidate, source }) => {
96
212
  try {
97
213
  for (let attempt = 0; attempt < 3; attempt += 1) {
98
214
  const metadata = await stat(candidate);
@@ -0,0 +1,60 @@
1
+ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { DatabaseSync } from "node:sqlite";
4
+ import { describe, expect, it } from "vitest";
5
+ import { rebuildSqliteReadModel } from "./sqlite-read-model.js";
6
+
7
+ const tempRoot = join(
8
+ resolve(import.meta.dirname, "../../../../../.."),
9
+ ".tmp",
10
+ "sqlite-read-model-tests",
11
+ );
12
+
13
+ describe("SQLite worktree source aggregation", () => {
14
+ it("materializes recent worktree Tasks once and refreshes when a sibling changes", async () => {
15
+ await mkdir(tempRoot, { recursive: true });
16
+ const root = await mkdtemp(join(tempRoot, "fixture-"));
17
+ const sibling = await mkdtemp(join(tempRoot, "fixture-"));
18
+ try {
19
+ await mkdir(join(root, ".agents/config"), { recursive: true });
20
+ await mkdir(join(root, ".agents/records/tasks"), { recursive: true });
21
+ await mkdir(join(sibling, ".agents/records/tasks"), { recursive: true });
22
+ await writeFile(join(root, ".agents/config/project.yaml"), "zaip:\n enabled: true\n");
23
+ const oldRecord =
24
+ "---\nid: TASK-DUPLICATE\ntitle: Old\nstatus: executing\ncreated_at: 2026-09-17T10:00:00Z\nupdated_at: 2026-09-17T10:00:00Z\n---\n";
25
+ const newRecord = oldRecord.replace("Old", "Recent").replaceAll("2026-09-17", "2026-09-23");
26
+ await writeFile(join(root, ".agents/records/tasks/TASK-DUPLICATE.md"), oldRecord);
27
+ await writeFile(join(sibling, ".agents/records/tasks/TASK-DUPLICATE.md"), newRecord);
28
+ await writeFile(
29
+ join(sibling, ".agents/records/tasks/TASK-NEW.md"),
30
+ newRecord.replaceAll("TASK-DUPLICATE", "TASK-NEW"),
31
+ );
32
+ const options = { sourceRoots: [root, sibling] };
33
+ await rebuildSqliteReadModel(root, options);
34
+ const database = new DatabaseSync(join(root, ".local/sqlite/zaip-aios-dashboard.sqlite"), {
35
+ readOnly: true,
36
+ });
37
+ try {
38
+ expect(
39
+ database.prepare("SELECT count(*) AS n FROM zaip_vw_task_summary").get(),
40
+ ).toMatchObject({ n: 2 });
41
+ expect(
42
+ database
43
+ .prepare("SELECT task_count FROM zaip_vw_daily_aggregates WHERE day=?")
44
+ .get("2026-09-23"),
45
+ ).toMatchObject({ task_count: 2 });
46
+ } finally {
47
+ database.close();
48
+ }
49
+ await writeFile(
50
+ join(sibling, ".agents/records/tasks/TASK-THIRD.md"),
51
+ newRecord.replaceAll("TASK-DUPLICATE", "TASK-THIRD"),
52
+ );
53
+ const refreshed = await rebuildSqliteReadModel(root, options);
54
+ expect(refreshed.refresh.added_sources).toBe(1);
55
+ } finally {
56
+ await rm(root, { recursive: true, force: true });
57
+ await rm(sibling, { recursive: true, force: true });
58
+ }
59
+ });
60
+ });
@@ -0,0 +1,13 @@
1
+ import { persistedSourceCheckpoint } from "./sqlite-read-model-schema.js";
2
+
3
+ export interface SqliteRebuildOptions {
4
+ forceCanonical?: boolean;
5
+ preferExisting?: boolean;
6
+ sourceRoots?: readonly string[];
7
+ }
8
+
9
+ export function rebuildFingerprintOptions(path: string, options: SqliteRebuildOptions) {
10
+ return options.forceCanonical
11
+ ? { verifyContent: true, sourceRoots: options.sourceRoots }
12
+ : { previous: persistedSourceCheckpoint(path), sourceRoots: options.sourceRoots };
13
+ }
@@ -1,5 +1,9 @@
1
+ import { execFile } from "node:child_process";
1
2
  import { createServer as createHttpServer } from "node:http";
2
3
  import { basename } from "node:path";
4
+ import { promisify } from "node:util";
5
+
6
+ const execFileAsync = promisify(execFile);
3
7
 
4
8
  const escapeHtml = (text) =>
5
9
  String(text).replace(
@@ -8,6 +12,21 @@ const escapeHtml = (text) =>
8
12
  ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[character],
9
13
  );
10
14
 
15
+ async function githubRepository(workspaceRoot) {
16
+ if (!workspaceRoot) return null;
17
+ try {
18
+ const { stdout } = await execFileAsync(
19
+ "git",
20
+ ["-C", workspaceRoot, "remote", "get-url", "origin"],
21
+ { encoding: "utf8", windowsHide: true, timeout: 1500 },
22
+ );
23
+ const match = stdout.trim().match(/github\.com(?::|\/)([^/\s]+)\/([^/\s]+?)(?:\.git)?$/i);
24
+ return match ? `${match[1]}/${match[2]}` : null;
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
29
+
11
30
  export async function createDashboardLaunchPage({
12
31
  port,
13
32
  host,
@@ -16,6 +35,10 @@ export async function createDashboardLaunchPage({
16
35
  delay,
17
36
  workspaceRoot = "",
18
37
  }) {
38
+ const repository = await githubRepository(workspaceRoot);
39
+ const repositoryBadge = repository
40
+ ? `<a class="repository-badge" href="https://github.com/${escapeHtml(repository)}" target="_blank" rel="noopener noreferrer" aria-label="Repositório GitHub ${escapeHtml(repository)}"><svg aria-hidden="true" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0a8 8 0 0 0-2.53 15.59c.4.07.55-.17.55-.39v-1.5c-2.23.49-2.7-.95-2.7-.95-.36-.93-.89-1.18-.89-1.18-.73-.5.05-.49.05-.49.8.06 1.23.82 1.23.82.71 1.22 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.9-3.64-3.95 0-.87.31-1.58.82-2.14-.08-.2-.36-1.01.08-2.11 0 0 .67-.21 2.2.82a7.67 7.67 0 0 1 4 0c1.53-1.03 2.2-.82 2.2-.82.44 1.1.16 1.91.08 2.11.51.56.82 1.27.82 2.14 0 3.06-1.87 3.75-3.65 3.95.28.24.53.71.53 1.44v2.27c0 .22.14.47.55.39A8 8 0 0 0 8 0Z"/></svg>${escapeHtml(repository)}</a>`
41
+ : "";
19
42
  let redirectUrl = null;
20
43
  let failure = null;
21
44
  let progress = {
@@ -86,17 +109,18 @@ export async function createDashboardLaunchPage({
86
109
  <head>
87
110
  <meta charset="utf-8">
88
111
  <meta name="viewport" content="width=device-width,initial-scale=1">
89
- <title>Dashboard Zaip AIOS</title>
112
+ <title>Dashboard ZAIP AIOS</title>
90
113
  <style>
91
114
  :root{color-scheme:dark;font-family:Inter,system-ui,sans-serif;background:#010610;color:#f1f5f9}
92
115
  *{box-sizing:border-box}body{margin:0;background:#010610}.launch-overlay{position:fixed;inset:0;width:100vw;height:100vh;display:grid;place-items:center;padding:clamp(18px,5vw,72px);background:radial-gradient(circle at 50% 35%,rgba(0,176,240,.11),transparent 42%),#010610}
93
116
  .progress{width:min(100%,760px);padding:clamp(24px,4vw,42px);border:1px solid rgba(125,211,252,.2);border-radius:20px;background:rgba(3,9,22,.94);box-shadow:0 24px 80px rgba(0,0,0,.45);backdrop-filter:blur(10px)}.progress strong,.progress span:not(.handoff):not(.failure){display:block}.progress strong{font-size:clamp(1.05rem,2vw,1.35rem)}.progress span{color:#b6c6db;font-size:clamp(.88rem,1.5vw,1rem);margin-top:7px}.track{position:relative;height:9px;margin-top:20px;border-radius:999px;background:#172033;overflow:hidden}.track::after{content:"";position:absolute;z-index:2;inset:0;background:linear-gradient(90deg,transparent 0%,rgba(224,242,254,.14) 35%,rgba(224,242,254,.8) 50%,rgba(224,242,254,.14) 65%,transparent 100%);transform:translateX(-100%);animation:launch-activity 1.35s ease-in-out infinite;pointer-events:none}.progress.terminal-failure .track::after{animation:none;transform:none;background:rgba(254,202,202,.2)}.progress.terminal-failure .bar{background:#f87171}.bar{position:relative;z-index:1;height:100%;width:4%;border-radius:inherit;background:linear-gradient(90deg,#38bdf8,#818cf8);transition:width .35s ease}@keyframes launch-activity{to{transform:translateX(100%)}}@media (prefers-reduced-motion:reduce){.track::after{animation:none;transform:none;background:linear-gradient(90deg,transparent 0%,rgba(224,242,254,.2) 50%,transparent 100%)}}.handoff,.failure{display:none;margin-top:16px;color:#dbeafe}.failure{color:#fecaca}
94
117
  .activity{min-height:1.3em}.steps{display:grid;gap:7px;max-height:12.5rem;overflow:auto;margin:18px 0 0;padding:0;list-style:none}.steps li{position:relative;padding-left:20px;color:#94a3b8;font-size:.82rem}.steps li::before{content:"";position:absolute;left:1px;top:.4em;width:8px;height:8px;border-radius:50%;background:#475569}.steps li[data-state="active"]{color:#dbeafe}.steps li[data-state="active"]::before{background:#38bdf8;box-shadow:0 0 0 4px rgba(56,189,248,.16)}.progress.terminal-failure .steps li[data-state="active"]::before{background:#f87171}@media (prefers-reduced-motion:reduce){.bar{transition:none}}
118
+ .launch-heading{margin-bottom:18px}.launch-heading h1{margin:0;font-size:clamp(1.2rem,2.4vw,1.55rem)}.workspace-identity{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.repository-badge{display:inline-flex;align-items:center;gap:7px;max-width:100%;padding:6px 10px;border-radius:999px;background:#f8fafc;color:#0f172a;font-size:.78rem;font-weight:700;text-decoration:none;overflow-wrap:anywhere}.repository-badge svg{width:15px;height:15px;flex:none}.repository-badge:focus-visible{outline:2px solid #7dd3fc;outline-offset:3px}
95
119
  </style>
96
120
  </head>
97
121
  <body>
98
122
  <main class="launch-overlay" aria-label="Preparando dashboard" aria-busy="true">
99
- <section class="progress" aria-live="polite" role="status"><div aria-label="Workspace" style="margin-bottom:20px;overflow-wrap:anywhere"><strong>${escapeHtml(basename(workspaceRoot))}</strong><span>${escapeHtml(workspaceRoot)}</span></div><strong id="phase">Iniciando o launcher local</strong><span id="detail">Abrindo a página de preparação.</span><span class="activity" id="activity" aria-hidden="true">Atividade em andamento.</span><div class="track" id="track" role="progressbar" aria-label="Preparação em andamento" aria-valuemin="0" aria-valuemax="100" aria-valuenow="4" aria-valuetext="Iniciando o launcher local"><div class="bar" id="bar"></div></div><ol class="steps" id="steps" aria-label="Etapas de preparação"><li data-state="active">Iniciando o launcher local</li></ol><span class="handoff" id="handoff">O dashboard está pronto. Abrindo a tela principal automaticamente…</span><span class="failure" id="failure" role="alert"></span></section>
123
+ <section class="progress" aria-live="polite" role="status"><div class="launch-heading"><h1>Dashboard ZAIP AIOS</h1></div><div aria-label="Workspace" style="margin-bottom:20px;overflow-wrap:anywhere"><div class="workspace-identity"><strong>${escapeHtml(basename(workspaceRoot))}</strong>${repositoryBadge}</div><span>${escapeHtml(workspaceRoot)}</span></div><strong id="phase">Iniciando o launcher local</strong><span id="detail">Abrindo a página de preparação.</span><span class="activity" id="activity" aria-hidden="true">Atividade em andamento.</span><div class="track" id="track" role="progressbar" aria-label="Preparação em andamento" aria-valuemin="0" aria-valuemax="100" aria-valuenow="4" aria-valuetext="Iniciando o launcher local"><div class="bar" id="bar"></div></div><ol class="steps" id="steps" aria-label="Etapas de preparação"><li data-state="active">Iniciando o launcher local</li></ol><span class="handoff" id="handoff">O dashboard está pronto. Abrindo a tela principal automaticamente…</span><span class="failure" id="failure" role="alert"></span></section>
100
124
  </main>
101
125
  <script>
102
126
  let handoffTarget=null,progressRequestInFlight=false,terminalFailure=false,lastProgressPercent=4,compilationStartedAt=null,compilationDetail="",compilationTicker=null,activeStepKey="",activeStepStartedAt=Date.now();
@@ -12,6 +12,9 @@ describe("dashboard launch page", () => {
12
12
 
13
13
  expect(page.status).toBe(200);
14
14
  const html = await page.text();
15
+ expect(html).toContain("<h1>Dashboard ZAIP AIOS</h1>");
16
+ expect(html).toContain('class="repository-badge"');
17
+ expect(html).toContain("zaip-ai/zaip-aios</a>");
15
18
  expect(html).toContain('class="launch-overlay"');
16
19
  expect(html).toContain("position:fixed;inset:0;width:100vw;height:100vh");
17
20
  expect(html).toContain("display:grid;place-items:center");
@@ -69,6 +72,8 @@ describe("dashboard launch page", () => {
69
72
  );
70
73
  await page.route("**/api/v2/health", () => new Promise(() => {}));
71
74
  await page.goto(`http://${host}:${launchPage.port}/?token=temporary`);
75
+ if (process.env.ZAIP_LAUNCH_SCREENSHOT_PATH)
76
+ await page.screenshot({ path: process.env.ZAIP_LAUNCH_SCREENSHOT_PATH });
72
77
 
73
78
  await expect
74
79
  .poll(() =>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaip-ai/dashboard-ui",
3
- "version": "3.8.0",
3
+ "version": "4.1.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -2,6 +2,7 @@ import { readFileSync } from "node:fs";
2
2
  import { describe, expect, it } from "vitest";
3
3
 
4
4
  const styles = readFileSync(new URL("ui.css", import.meta.url), "utf8");
5
+ const headerSource = readFileSync(new URL("DashboardHeader.tsx", import.meta.url), "utf8");
5
6
 
6
7
  describe("DashboardHeader", () => {
7
8
  it("optically balances the repository badge horizontal spacing", () => {
@@ -9,6 +10,10 @@ describe("DashboardHeader", () => {
9
10
  expect(rule).toContain("padding-block: 0.3rem");
10
11
  expect(rule).toContain("padding-inline: 0.6rem 0.72rem");
11
12
  });
13
+ it("labels the timestamp as telemetry rather than overall snapshot freshness", () => {
14
+ expect(headerSource).toContain('updated: "Última telemetria"');
15
+ expect(headerSource).toContain('waiting: "Sem telemetria medida"');
16
+ });
12
17
  });
13
18
 
14
19
  function cssRule(source, selector) {
@@ -38,8 +38,8 @@ export function DashboardHeader({
38
38
  refresh: "Atualizar",
39
39
  refreshing: "Atualizando…",
40
40
  settings: "Configurações",
41
- updated: "Atualizado",
42
- waiting: "Aguardando atualização",
41
+ updated: "Última telemetria",
42
+ waiting: "Sem telemetria medida",
43
43
  }
44
44
  : {
45
45
  filters: "Filters",
@@ -47,8 +47,8 @@ export function DashboardHeader({
47
47
  refresh: "Refresh",
48
48
  refreshing: "Refreshing…",
49
49
  settings: "Settings",
50
- updated: "Updated",
51
- waiting: "Waiting for refresh",
50
+ updated: "Last telemetry",
51
+ waiting: "No measured telemetry",
52
52
  };
53
53
  const updatedLabel =
54
54
  lastUpdatedAt === null
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaip-ai/dashboard-e2e",
3
- "version": "3.8.0",
3
+ "version": "4.1.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -42,6 +42,10 @@ export default defineConfig({
42
42
  // Match the Windows launcher: first paint uses the latest validated
43
43
  // immutable seed while canonical refresh work stays off the served path.
44
44
  ZAIP_SQLITE_PREFER_LAST_VALID_SEED: "1",
45
+ // Browser qualification reads a fixed Git candidate. Live host capture
46
+ // would mutate its canonical records during the clean-worktree gate.
47
+ // Source-watch/capture behavior has separate runtime tests.
48
+ ZAIP_DASHBOARD_WATCH_SOURCES: "0",
45
49
  // Keep pre-bind progress observable if the web-server health gate times out.
46
50
  ZAIP_DASHBOARD_LAUNCH_PROGRESS: "1",
47
51
  },
@@ -5,9 +5,9 @@ import {
5
5
  assertPerformanceWarnings,
6
6
  observePerformanceWarnings,
7
7
  } from "./performance-observability.js";
8
+ import { workRowIdentities } from "./performance-work-row-identity.js";
8
9
 
9
10
  type PeriodQuery = { from: string | null; to: string | null };
10
-
11
11
  const costViews = [
12
12
  ["Diário", "daily", "cost_monitor_daily"],
13
13
  ["Mensal", "monthly", "cost_monitor_monthly"],
@@ -351,7 +351,7 @@ async function assertWorkListPagination(
351
351
  const totalText = await pager.locator("output").textContent();
352
352
  const total = Number(totalText?.match(/de\s+(\d+)/)?.[1] ?? 0);
353
353
  if (total > 10) {
354
- const firstPageRows = await rowSignatures(rows);
354
+ const firstPageRows = await workRowIdentities(rows);
355
355
  const next = pager.getByRole("button", { name: "Próxima" });
356
356
  await expect(next).toBeEnabled();
357
357
  await assertNoFullscreenOverlay(page);
@@ -361,7 +361,7 @@ async function assertWorkListPagination(
361
361
  await expect(pager.locator("output")).toContainText("11–", { timeout: 10_000 });
362
362
  await expect(rows).toHaveCount(Math.min(10, total - 10), { timeout: 10_000 });
363
363
  await expect(surface).not.toHaveAttribute("aria-busy", "true", { timeout: 10_000 });
364
- expect(await rowSignatures(rows)).not.toEqual(firstPageRows);
364
+ expect(await workRowIdentities(rows)).not.toEqual(firstPageRows);
365
365
  // Filter hydration must not reset an already loaded page after navigation.
366
366
  await waitForApiQuiet(matchesSelection);
367
367
  await expect(pager.locator("output")).toContainText("11–", { timeout: 10_000 });
@@ -373,7 +373,7 @@ async function assertWorkListPagination(
373
373
  await expect(pager.locator("output")).toContainText("1–", { timeout: 10_000 });
374
374
  await expect(rows).toHaveCount(Math.min(10, total), { timeout: 10_000 });
375
375
  await expect(surface).not.toHaveAttribute("aria-busy", "true", { timeout: 10_000 });
376
- expect(await rowSignatures(rows)).toEqual(firstPageRows);
376
+ expect(await workRowIdentities(rows)).toEqual(firstPageRows);
377
377
  await assertNoFullscreenOverlay(page);
378
378
  }
379
379
  }
@@ -173,7 +173,7 @@ test("renders the modern read-only dashboard and meets accessibility gates", asy
173
173
  // Identity is loaded independently; both the initial title and the title
174
174
  // with the observed repository identify the same accessible navigation.
175
175
  await expect(
176
- page.getByRole("navigation", { name: /^Dashboard Zaip AIOS(?: .+)? menu$/ }),
176
+ page.getByRole("navigation", { name: /^Dashboard ZAIP AIOS(?: .+)? menu$/ }),
177
177
  ).toBeVisible();
178
178
  const capabilityNav = page.getByRole("navigation", { name: "Áreas do dashboard" });
179
179
  const globalControls = page.locator(".dashboard-global-controls");
@@ -0,0 +1,6 @@
1
+ import type { Locator } from "@playwright/test";
2
+
3
+ /** Live telemetry can change metrics while a paginated row keeps the same identity. */
4
+ export function workRowIdentities(rows: Locator): Promise<string[]> {
5
+ return rows.locator(".operations-work-list-identity small").allTextContents();
6
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "3.8.0",
3
+ "version": "4.1.0",
4
4
  "files": [
5
5
  {
6
6
  "path": "DESIGN.md",
@@ -42,6 +42,10 @@
42
42
  "path": "apps/catalog/dist/assets/index-D2miO4-O.js",
43
43
  "sha256": "5f8dfdc456f365253210203870f6a1f21a5f9114d64e7eafac0ffcf360fc185f"
44
44
  },
45
+ {
46
+ "path": "apps/catalog/dist/assets/index-DkpQYoyC.js",
47
+ "sha256": "527677a94c7a3d5ebd5d6b9bc81ebef5b4493535c22a4c92b7b8c20e25ac430e"
48
+ },
45
49
  {
46
50
  "path": "apps/catalog/dist/assets/index-QJsgr9Ht.js",
47
51
  "sha256": "0dd8ae107fc9742dc9da1ddff3e736521dc47729c9f33018c5ff87ef91f7b2bf"
@@ -52,7 +56,7 @@
52
56
  },
53
57
  {
54
58
  "path": "apps/catalog/dist/index.html",
55
- "sha256": "b24dd9cb3ef96cdce86f699b4aa7b0f9e09545f345fe71375bd61a7abd8e11d0"
59
+ "sha256": "626f6daaffa33be315b65a44772832748686c4e16af8b1f7449760862e7a8f88"
56
60
  },
57
61
  {
58
62
  "path": "apps/catalog/dist/logo_novo_azul.png",
@@ -268,7 +272,7 @@
268
272
  },
269
273
  {
270
274
  "path": "apps/catalog/package.json",
271
- "sha256": "1314c1c3291f961837413c6e9e3a3f774ec832e952808246a66cbc8d8abe9e08"
275
+ "sha256": "0638c2445443b4e0cb1721f44df28ddd7856af7eb028cf402abcbc7363fb2b9a"
272
276
  },
273
277
  {
274
278
  "path": "apps/catalog/public/logo_novo_azul.png",
@@ -288,15 +292,15 @@
288
292
  },
289
293
  {
290
294
  "path": "apps/catalog/src/components/CostPopulationSpecimen.test.tsx",
291
- "sha256": "2e76031ba2e94f0d4473d09c5e96e41f749fe099a13b3e4bcdd24a8455b16ac4"
295
+ "sha256": "e64951368cfdccd2821a8b8d6ac335b8d039f5a2760a88b34a408b818cf9ead7"
292
296
  },
293
297
  {
294
298
  "path": "apps/catalog/src/components/CostPopulationSpecimen.tsx",
295
- "sha256": "d92bc8d55660b020db6ba9d47037a782fbbeba9b76febf7869718064d1928170"
299
+ "sha256": "534ffa86dc4c39425c3a33c70d7e7b7718aeafcef42baa16bdb54d9831945152"
296
300
  },
297
301
  {
298
302
  "path": "apps/catalog/src/components/DashboardFiltersSpecimen.tsx",
299
- "sha256": "97824a7e2a4d7b93330dd7d688fec6e4f734a3b32ee48793d67c130462eef1e9"
303
+ "sha256": "f5d9e1d6edce82197f5e95d667ed9252dfefead9b2b1e69755129a9cb9c3fb2e"
300
304
  },
301
305
  {
302
306
  "path": "apps/catalog/src/components/EstimatedCostSpecimen.tsx",
@@ -336,7 +340,7 @@
336
340
  },
337
341
  {
338
342
  "path": "apps/catalog/src/pages/ComponentsPage.tsx",
339
- "sha256": "71174f027831a1056684d910d16cb4869011eda0a193791d5937694993ece575"
343
+ "sha256": "2a423d2153e07acbb044bf119c3118fc0d8298a9ed434c38bde1c2ffa208b491"
340
344
  },
341
345
  {
342
346
  "path": "apps/catalog/src/pages/DesignSystemPage.tsx",
@@ -348,7 +352,7 @@
348
352
  },
349
353
  {
350
354
  "path": "apps/catalog/src/stories/DashboardFilters.stories.tsx",
351
- "sha256": "6c5074199139279c905b15944f31efc8322cda0411e175a2bec25d34f54694bd"
355
+ "sha256": "020059f577525182f2461a68d84a85d8e7161452857bc01df4fad45c268c49fc"
352
356
  },
353
357
  {
354
358
  "path": "apps/catalog/src/stories/DesignSystem.stories.tsx",
@@ -392,7 +396,7 @@
392
396
  },
393
397
  {
394
398
  "path": "packages/local-runtime/package.json",
395
- "sha256": "8bec89ca56d6e114c54572d158cd2d378b49911ccfcbf1d86096a20ea30b41b5"
399
+ "sha256": "951ead4ca2c006960bd1ec087d7357543626d1d3e8710115d199bf77b4973489"
396
400
  },
397
401
  {
398
402
  "path": "packages/local-runtime/runtime.mjs",