@zaip-ai/cli 3.7.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/README.md +5 -5
  2. package/dist/commands/init.d.ts.map +1 -1
  3. package/dist/commands/init.js +6 -0
  4. package/dist/commands/init.js.map +1 -1
  5. package/dist/services/adapters.d.ts +1 -1
  6. package/dist/services/adapters.d.ts.map +1 -1
  7. package/dist/services/adapters.js +22 -4
  8. package/dist/services/adapters.js.map +1 -1
  9. package/dist/services/adapters.test.js +24 -0
  10. package/dist/services/adapters.test.js.map +1 -1
  11. package/dist/services/agent-adapters.js +1 -1
  12. package/dist/services/agent-adapters.js.map +1 -1
  13. package/dist/services/backup-gitignore.d.ts +9 -0
  14. package/dist/services/backup-gitignore.d.ts.map +1 -0
  15. package/dist/services/backup-gitignore.js +66 -0
  16. package/dist/services/backup-gitignore.js.map +1 -0
  17. package/dist/services/backup-gitignore.test.d.ts +2 -0
  18. package/dist/services/backup-gitignore.test.d.ts.map +1 -0
  19. package/dist/services/backup-gitignore.test.js +27 -0
  20. package/dist/services/backup-gitignore.test.js.map +1 -0
  21. package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
  22. package/dist/services/codex-conversation-lifecycle-hook.js +15 -7
  23. package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
  24. package/dist/services/install-agents-template.d.ts.map +1 -1
  25. package/dist/services/install-agents-template.js +43 -127
  26. package/dist/services/install-agents-template.js.map +1 -1
  27. package/dist/services/install-template-policy.d.ts.map +1 -1
  28. package/dist/services/install-template-policy.js +2 -0
  29. package/dist/services/install-template-policy.js.map +1 -1
  30. package/dist/services/legacy-records-migration.d.ts +15 -0
  31. package/dist/services/legacy-records-migration.d.ts.map +1 -0
  32. package/dist/services/legacy-records-migration.js +109 -0
  33. package/dist/services/legacy-records-migration.js.map +1 -0
  34. package/dist/services/local-state-migration.d.ts +8 -1
  35. package/dist/services/local-state-migration.d.ts.map +1 -1
  36. package/dist/services/local-state-migration.js +67 -32
  37. package/dist/services/local-state-migration.js.map +1 -1
  38. package/dist/services/logger.d.ts.map +1 -1
  39. package/dist/services/logger.js +2 -0
  40. package/dist/services/logger.js.map +1 -1
  41. package/dist/services/project-model-migration.d.ts +3 -0
  42. package/dist/services/project-model-migration.d.ts.map +1 -0
  43. package/dist/services/project-model-migration.js +163 -0
  44. package/dist/services/project-model-migration.js.map +1 -0
  45. package/dist/services/project-model-migration.test.d.ts +2 -0
  46. package/dist/services/project-model-migration.test.d.ts.map +1 -0
  47. package/dist/services/project-model-migration.test.js +62 -0
  48. package/dist/services/project-model-migration.test.js.map +1 -0
  49. package/dist/services/sqlite-bootstrap.d.ts.map +1 -1
  50. package/dist/services/sqlite-bootstrap.js +9 -1
  51. package/dist/services/sqlite-bootstrap.js.map +1 -1
  52. package/dist/services/template-manifest.d.ts.map +1 -1
  53. package/dist/services/template-manifest.js +2 -0
  54. package/dist/services/template-manifest.js.map +1 -1
  55. package/dist/services/transactional-files.d.ts +1 -0
  56. package/dist/services/transactional-files.d.ts.map +1 -1
  57. package/dist/services/transactional-files.js +3 -0
  58. package/dist/services/transactional-files.js.map +1 -1
  59. package/dist/types.d.ts +1 -0
  60. package/dist/types.d.ts.map +1 -1
  61. package/package.json +1 -1
  62. package/templates/.agents/README-ENG.md +90 -34
  63. package/templates/.agents/README.md +59 -32
  64. package/templates/.agents/config/agents/catalog.yaml +23 -23
  65. package/templates/.agents/config/agents/discovery.json +2 -2
  66. package/templates/.agents/config/clients/codex/agents/zaip-agent-analyst.toml +2 -2
  67. package/templates/.agents/config/clients/codex/agents/zaip-agent-auditor.toml +2 -2
  68. package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +2 -2
  69. package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +2 -2
  70. package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +2 -2
  71. package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +2 -2
  72. package/templates/.agents/config/clients/codex/agents/zaip-agent-data-analyst.toml +2 -2
  73. package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +2 -2
  74. package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +2 -2
  75. package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +2 -2
  76. package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +2 -2
  77. package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +2 -2
  78. package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +2 -2
  79. package/templates/.agents/config/clients/codex/agents/zaip-agent-integrator.toml +2 -2
  80. package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +2 -2
  81. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +3 -3
  82. package/templates/.agents/config/clients/codex/agents/zaip-agent-refactoring-specialist.toml +2 -2
  83. package/templates/.agents/config/clients/codex/agents/zaip-agent-reviewer.toml +2 -2
  84. package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +2 -2
  85. package/templates/.agents/config/clients/codex/agents/zaip-agent-security-auditor.toml +2 -2
  86. package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +2 -2
  87. package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +2 -2
  88. package/templates/.agents/config/clients/codex/agents/zaip-agent-writer.toml +2 -2
  89. package/templates/.agents/config/clients.yaml +1 -1
  90. package/templates/.agents/config/pricing/models.json +57 -1
  91. package/templates/.agents/config/project.yaml +21 -7
  92. package/templates/.agents/dashboard/.zaip-managed.json +195 -115
  93. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-C5NgEcVh.js → CostCalculationGuidePage-f4ZGJRg3.js} +1 -1
  94. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-BDQR0U4a.js → DashboardHelpDialog-DlN5EMmD.js} +249 -136
  95. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-CGYcJ5EB.js → PricingSettingsDialog-v9zGRTlk.js} +1 -1
  96. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BRdoeTWk.js +3 -0
  97. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-Ckxk_izu.js → TraceabilityWorkspace-B_5u4Xnp.js} +1 -1
  98. package/templates/.agents/dashboard/apps/frontend/dist/assets/{cost-monitor-BsMfGfQi.css → cost-monitor-C2AFYBu_.css} +1 -1
  99. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-D7PrDZy9.js +68 -0
  100. package/templates/.agents/dashboard/apps/frontend/dist/assets/{dashboard-localization-jvdDfNKs.js → dashboard-localization-CF7B1Hjn.js} +90 -34
  101. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-x8xxL9yW.js → icons-vendor-Cv3WBFIF.js} +1 -1
  102. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-C4rLXrz_.js +2 -0
  103. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-CNOXIJHN.js → react-vendor-mHgsmxb6.js} +1 -1
  104. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-CcpbpT1s.js → traceability-B0CPyEVq.js} +1 -1
  105. package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
  106. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  107. package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +11 -1
  108. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingBoundary.tsx +3 -2
  109. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingPanels.tsx +1 -1
  110. package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +1 -1
  111. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +9 -13
  112. package/templates/.agents/dashboard/apps/frontend/src/cost-monitor-population.test.tsx +4 -2
  113. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +9 -5
  114. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +3 -2
  115. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +2 -2
  116. package/templates/.agents/dashboard/apps/frontend/src/dashboard-identity.test.ts +3 -3
  117. package/templates/.agents/dashboard/apps/frontend/src/dashboard-identity.ts +1 -1
  118. package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.test.ts +2 -1
  119. package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +40 -3
  120. package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +12 -1
  121. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +19 -0
  122. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +1 -1
  123. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +3 -1
  124. package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +14 -23
  125. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  126. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +3 -3
  127. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +2 -3
  128. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionTable.tsx +2 -6
  129. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.period-values.test.tsx +66 -0
  130. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.tsx +29 -34
  131. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +2 -2
  132. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.embedded.test.ts +11 -0
  133. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +1 -13
  134. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.test.tsx +23 -0
  135. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.tsx +2 -1
  136. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableDisplay.ts +6 -11
  137. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +6 -6
  138. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +10 -12
  139. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-group-page-totals.ts +23 -0
  140. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-group-period-values.tsx +34 -0
  141. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-embedded.css +0 -7
  142. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-formatters.ts +4 -9
  143. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-presentation.ts +2 -3
  144. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  145. package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.tsx +2 -12
  146. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +2 -2
  147. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +1 -6
  148. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +34 -36
  149. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewCharts.tsx +12 -3
  150. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewTopPanel.tsx +12 -14
  151. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +4 -4
  152. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +23 -4
  153. package/templates/.agents/dashboard/modules/operations/src/react/OverviewCostKpi.tsx +30 -2
  154. package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +2 -13
  155. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.priority.test.ts +8 -1
  156. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +8 -16
  157. package/templates/.agents/dashboard/modules/operations/src/react/WorkColumnState.tsx +34 -0
  158. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +1 -1
  159. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +1 -1
  160. package/templates/.agents/dashboard/modules/operations/src/react/operations-average-unmeasured.test.ts +10 -0
  161. package/templates/.agents/dashboard/modules/operations/src/react/operations-content-visibility.ts +3 -0
  162. package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +4 -3
  163. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +12 -1
  164. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +1 -0
  165. package/templates/.agents/dashboard/modules/operations/src/react/operations-skeleton.css +80 -0
  166. package/templates/.agents/dashboard/modules/operations/src/react/operations.css +2 -11
  167. package/templates/.agents/dashboard/modules/operations/src/react/overview-cost-card.test.tsx +36 -0
  168. package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.test.ts +11 -0
  169. package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.ts +28 -3
  170. package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-stats.ts +44 -0
  171. package/templates/.agents/dashboard/modules/operations/src/react/work-card-label.ts +5 -0
  172. package/templates/.agents/dashboard/modules/operations/src/react/work-column-state.ts +11 -0
  173. package/templates/.agents/dashboard/modules/operations/src/react/work-item-filter.ts +13 -0
  174. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  175. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  176. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  177. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  178. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +173 -173
  179. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +120 -120
  180. package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
  181. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +173 -173
  182. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.test.ts +31 -0
  183. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +74 -1
  184. package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.test.ts +15 -15
  185. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +2 -2
  186. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +1 -1
  187. package/templates/.agents/dashboard/packages/local-runtime/src/server-identity.test.ts +1 -1
  188. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +25 -3
  189. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +51 -16
  190. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +1 -1
  191. package/templates/.agents/dashboard/packages/local-runtime/src/server-ui-security.ts +37 -0
  192. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +1 -1
  193. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +11 -33
  194. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +12 -13
  195. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.test.ts +71 -1
  196. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +141 -25
  197. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-worktree-sources.test.ts +60 -0
  198. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-rebuild-fingerprint-options.ts +13 -0
  199. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +26 -2
  200. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.test.mjs +5 -0
  201. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  202. package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.test.mjs +5 -0
  203. package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.tsx +4 -4
  204. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  205. package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -0
  206. package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +15 -23
  207. package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +1 -1
  208. package/templates/.agents/dashboard/tests/e2e/specs/performance-matrix-types.ts +15 -0
  209. package/templates/.agents/dashboard/tests/e2e/specs/performance-observability.ts +30 -0
  210. package/templates/.agents/dashboard/tests/e2e/specs/performance-work-row-identity.ts +6 -0
  211. package/templates/.agents/design/.zaip-managed.json +13 -9
  212. package/templates/.agents/design/apps/catalog/dist/assets/index-DkpQYoyC.js +72 -0
  213. package/templates/.agents/design/apps/catalog/dist/index.html +1 -1
  214. package/templates/.agents/design/apps/catalog/package.json +1 -1
  215. package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.test.tsx +8 -4
  216. package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.tsx +10 -3
  217. package/templates/.agents/design/apps/catalog/src/components/DashboardFiltersSpecimen.tsx +0 -15
  218. package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +3 -3
  219. package/templates/.agents/design/apps/catalog/src/stories/DashboardFilters.stories.tsx +0 -1
  220. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  221. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  222. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
  223. package/templates/.agents/requirements/comparative-audit.md +1 -1
  224. package/templates/.agents/requirements/context-engine.md +1 -1
  225. package/templates/.agents/requirements/cost-observability.md +1 -1
  226. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  227. package/templates/.agents/requirements/data-export.md +1 -1
  228. package/templates/.agents/requirements/design-system.md +1 -1
  229. package/templates/.agents/requirements/execution-engine.md +1 -1
  230. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  231. package/templates/.agents/requirements/model-orchestration.md +6 -6
  232. package/templates/.agents/requirements/public-distribution.md +1 -1
  233. package/templates/.agents/requirements/software-architecture.md +1 -1
  234. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  235. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  236. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  237. package/templates/.agents/rules/autonomy-decision.md +2 -2
  238. package/templates/.agents/rules/workflow.md +1 -1
  239. package/templates/.agents/runtime/VERSION +1 -1
  240. package/templates/.agents/runtime/bin/zaip.mjs +73 -64
  241. package/templates/.agents/runtime/checksums.sha256 +5 -5
  242. package/templates/.agents/runtime/manifest.json +1 -1
  243. package/templates/.agents/runtime/provenance.json +4 -4
  244. package/templates/.agents/runtime/sbom.cdx.json +1 -1
  245. package/templates/.agents/skills/zaip-skill-adapters/SKILL.md +1 -1
  246. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/SKILL.md +7 -7
  247. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.mjs +32 -7
  248. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.test.mjs +134 -1
  249. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-lease.mjs +57 -0
  250. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/scheduled-ready-queue-contract.test.mjs +9 -6
  251. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
  252. package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +2 -2
  253. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +5 -5
  254. package/templates/.agents/skills/zaip-skill-github-deploy/agents/openai.yaml +2 -2
  255. package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +5 -3
  256. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +40 -5
  257. package/templates/.agents/skills/zaip-skill-instalar-agendamento/SKILL.md +2 -2
  258. package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +6 -0
  259. package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +54 -6
  260. package/templates/.agents/zaip-aios/README.md +4 -4
  261. package/templates/.agents/zaip-aios/VERSION +1 -1
  262. package/templates/.agents/zaip-aios/guides/01-primeiros-passos.md +4 -3
  263. package/templates/.agents/zaip-aios/guides/03-tasks.md +5 -4
  264. package/templates/.agents/zaip-aios/guides/04-specs.md +4 -1
  265. package/templates/.agents/zaip-aios/guides/05-prds.md +7 -3
  266. package/templates/.agents/zaip-aios/guides/06-execucao.md +9 -4
  267. package/templates/.agents/zaip-aios/guides/09-agentes-e-squads.md +9 -5
  268. package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +10 -2
  269. package/templates/.agents/zaip-aios/guides/12-instalacao-e-upgrade.md +10 -5
  270. package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +12 -1
  271. package/templates/.agents/zaip-aios/guides/14-troubleshooting.md +3 -1
  272. package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +12 -7
  273. package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +1 -1
  274. package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +5 -1
  275. package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +19 -15
  276. package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +13 -9
  277. package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +4 -3
  278. package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +9 -7
  279. package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +40 -25
  280. package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +8 -8
  281. package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +14 -5
  282. package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +6 -0
  283. package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +129 -11
  284. package/templates/template-manifest.json +310 -218
  285. package/templates/tsconfig.base.json +22 -0
  286. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-OulA4CoX.js +0 -3
  287. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-j3aUYH5G.js +0 -68
  288. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-CqfSgtk9.js +0 -2
@@ -0,0 +1,34 @@
1
+ import type { DurationCoverage } from "../contracts.js";
2
+ import type { CostCurrency, CostLocale } from "./cost-monitor-copy.js";
3
+ import {
4
+ formatAuditableCurrency,
5
+ formatDurationCoverage,
6
+ hasKnownDuration,
7
+ } from "./cost-table-formatters.js";
8
+
9
+ export function createCostGroupPeriodValues(
10
+ currency: CostCurrency,
11
+ locale: CostLocale,
12
+ period: "daily" | "monthly" | "annual" | undefined,
13
+ ) {
14
+ const unmeasuredLabel =
15
+ locale === "pt-BR"
16
+ ? "Zero exibido por falta de medição; não é um valor observado."
17
+ : "Zero displayed because no measurement was recorded; this is not an observed value.";
18
+ const disclose = (value: string) => (
19
+ <output aria-label={`${value}. ${unmeasuredLabel}`} title={unmeasuredLabel}>
20
+ {value}
21
+ </output>
22
+ );
23
+ return {
24
+ description: period === undefined ? undefined : unmeasuredLabel,
25
+ duration: (value: DurationCoverage) =>
26
+ period !== undefined && !hasKnownDuration(value)
27
+ ? "0"
28
+ : formatDurationCoverage(value, locale),
29
+ currency: (value: number | null) =>
30
+ formatAuditableCurrency(period === undefined ? value : (value ?? 0), currency, locale),
31
+ disclose: (value: string, unmeasured: boolean) =>
32
+ period !== undefined && unmeasured ? disclose(value) : value,
33
+ };
34
+ }
@@ -9,10 +9,3 @@
9
9
  color: var(--text-primary);
10
10
  font-size: 1rem;
11
11
  }
12
- .cost-embedded-filters {
13
- margin-block: 12px;
14
- }
15
- .cost-embedded-filters summary {
16
- cursor: pointer;
17
- padding-block: 8px;
18
- }
@@ -22,11 +22,7 @@ export function formatAuditableNumber(value: number | null, locale: CostLocale):
22
22
  }
23
23
 
24
24
  export function formatFactualCount(value: number | null, locale: CostLocale): string {
25
- return value === null
26
- ? locale === "pt-BR"
27
- ? "Indisponível"
28
- : "Unavailable"
29
- : formatAuditableNumber(value, locale);
25
+ return formatAuditableNumber(value, locale);
30
26
  }
31
27
 
32
28
  export function formatAuditableCompactNumber(value: number | null, locale: CostLocale): string {
@@ -38,12 +34,12 @@ export function formatAuditableCurrency(
38
34
  currency: CostCurrency,
39
35
  locale: CostLocale,
40
36
  ): string {
41
- if (value === null) return locale === "pt-BR" ? "Indispon\u00edvel" : "Unavailable";
37
+ if (value === null) return "0";
42
38
  return formatCurrency(value, currency, locale);
43
39
  }
44
40
 
45
41
  export function formatAuditableDuration(value: number | null, locale: CostLocale): string {
46
- if (value === null) return locale === "pt-BR" ? "Indisponível" : "Unavailable";
42
+ if (value === null) return "0";
47
43
  return value === 0 ? "0" : formatDurationMs(value, locale);
48
44
  }
49
45
 
@@ -73,8 +69,7 @@ export function formatDurationCoverage(value: DurationCoverage, locale: CostLoca
73
69
  // activity in the population is unavailable. Keep completeness and the
74
70
  // unknown count as coverage metadata; hiding the known portion would turn a
75
71
  // true observation into an indistinguishable absence.
76
- if (value.known_sum <= 0 && !value.complete)
77
- return locale === "pt-BR" ? "Indisponível" : "Unavailable";
72
+ if (value.known_sum <= 0 && !value.complete) return "0";
78
73
  return value.known_sum <= 0 ? "0" : formatDurationMs(value.known_sum, locale);
79
74
  }
80
75
 
@@ -49,10 +49,9 @@ const detail = (value: string, _kind: "effort" | "speed", locale: CostLocale) =>
49
49
  export const formatMultiplierPair = (
50
50
  input: number | null,
51
51
  output: number | null,
52
- locale: CostLocale,
52
+ _locale: CostLocale,
53
53
  ) => {
54
- if (input === null || output === null)
55
- return locale === "pt-BR" ? "Indispon\u00edvel" : "Unavailable";
54
+ if (input === null || output === null) return "0";
56
55
  return `${input.toLocaleString("en-US", { maximumFractionDigits: 3 })}\u00d7 / ${output.toLocaleString("en-US", { maximumFractionDigits: 3 })}\u00d7`;
57
56
  };
58
57
  export const formatReasoningEffort = (
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaip-ai/dashboard-operations",
3
- "version": "3.7.0",
3
+ "version": "4.0.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -157,24 +157,14 @@ export function DeveloperAttributionTable({
157
157
  key: "tokens",
158
158
  label: copy.tokens,
159
159
  align: "right",
160
- render: (row) =>
161
- row.total_tokens === null
162
- ? locale === "pt-BR"
163
- ? "Indisponível"
164
- : "Unavailable"
165
- : formatCompactNumber(row.total_tokens, locale),
160
+ render: (row) => formatCompactNumber(row.total_tokens, locale),
166
161
  sortValue: (row) => row.total_tokens,
167
162
  },
168
163
  {
169
164
  key: "cost",
170
165
  label: copy.cost,
171
166
  align: "right",
172
- render: (row) =>
173
- row.total_cost_brl === null
174
- ? locale === "pt-BR"
175
- ? "Indisponível"
176
- : "Unavailable"
177
- : formatCurrency(row.total_cost_brl, "BRL", locale),
167
+ render: (row) => formatCurrency(row.total_cost_brl, "BRL", locale),
178
168
  sortValue: (row) => row.total_cost_brl,
179
169
  },
180
170
  ]}
@@ -603,8 +603,8 @@ export function formatExecutionAverageHint(
603
603
  if (totalTasks <= 0) return "0";
604
604
  if (totalDurationMs <= 0) {
605
605
  return locale === "pt-BR"
606
- ? "Médias de execução indisponíveis"
607
- : "Execution averages unavailable";
606
+ ? "Sem tempo medido para calcular médias"
607
+ : "No measured time for averages";
608
608
  }
609
609
  const averagePerTask = formatRoundedDuration(totalDurationMs / totalTasks, locale);
610
610
  // Macro aggregates can provide duration and population without individual
@@ -357,11 +357,6 @@ describe("execution average summary", () => {
357
357
  "20 min / tarefa (6 h / dia) (6 dias)",
358
358
  );
359
359
  });
360
- it("keeps the known macro average when execution days are unavailable", () => {
361
- expect(formatExecutionAverageHint(3_600_000, 3, 0, "pt-BR")).toBe("20 min / item");
362
- expect(formatExecutionAverageHint(3_600_000, 3, 0, "en-US")).toBe("20 min / item");
363
- expect(formatExecutionAverageHint(0, 3, 0, "pt-BR")).toBe("Médias de execução indisponíveis");
364
- });
365
360
  it("localizes English and shows zero for an empty population", () => {
366
361
  expect(formatExecutionAverageHint(3_600_000, 3, 1, "en-US")).toBe(
367
362
  "20 min / task (1 h / day) (1 day)",
@@ -444,7 +439,7 @@ describe("overviewMetricAverages", () => {
444
439
  "Indisponível",
445
440
  );
446
441
  expect(formatSummaryMetricValue(42, 0, (value) => String(value), "pt-BR")).toBe("42");
447
- expect(source).toContain("formatSummaryMetricValue(\n averageDuration,");
442
+ expect(source).toContain("const metricStats = overviewMetricStats(");
448
443
  expect(source).not.toContain("executionMetrics.durationMs ?? 0");
449
444
  });
450
445
  });
@@ -1,4 +1,5 @@
1
- import { formatSummaryMetricValue } from "./overview-metric-format.js";
1
+ import { formatSummaryMetricValue, unmeasuredZeroDescription } from "./overview-metric-format.js";
2
+ import { overviewMetricStats } from "./overview-metric-stats.js";
2
3
 
3
4
  export { formatSummaryMetricValue } from "./overview-metric-format.js";
4
5
 
@@ -104,6 +105,7 @@ export function OperationsOverview({
104
105
  tasks = data.tasks,
105
106
  factualCostTotal,
106
107
  factualCostFact,
108
+ costLoading = false,
107
109
  resolveRunCost,
108
110
  includeLegacyEffort: _includeLegacyEffort = false,
109
111
  }: {
@@ -141,6 +143,7 @@ export function OperationsOverview({
141
143
  factualCostTotal?: number | null | undefined;
142
144
  /** Measurement completeness for the matching Cost Monitor snapshot. */
143
145
  factualCostFact?: FactualCostFact | undefined;
146
+ costLoading?: boolean | undefined;
144
147
  resolveRunCost?: ((runId: string) => number | null) | undefined;
145
148
  includeLegacyEffort?: boolean;
146
149
  }) {
@@ -392,39 +395,23 @@ export function OperationsOverview({
392
395
  ? (overviewMetrics?.latest_task_created_at ?? null)
393
396
  : findLatestCreatedAt(tasks)
394
397
  : (selectedMacroAggregate?.latest_created_at ?? findLatestCreatedAt(selectedMacros));
395
- const metricStats = [
396
- [
397
- text.averageTime,
398
- formatSummaryMetricValue(
399
- averageDuration,
400
- selectedCount,
401
- (value) => formatDurationMs(value, locale),
402
- locale,
403
- ),
404
- ],
405
- [
406
- text.averageTokens,
407
- formatSummaryMetricValue(
408
- averageTokens,
409
- selectedCount,
410
- (value) => formatCompactNumber(value, locale),
411
- locale,
412
- ),
413
- ],
414
- [
415
- factualCostAverageLabel(
416
- overviewView === "tasks" ? factualCostFact : undefined,
417
- selectedCount,
418
- locale,
419
- ),
420
- formatSummaryMetricValue(
421
- averageCost,
422
- selectedCount,
423
- (value) => formatCurrency(value, currency, locale),
424
- locale,
425
- ),
426
- ],
427
- ] as const;
398
+ const metricStats = overviewMetricStats({
399
+ averageCost,
400
+ averageDuration,
401
+ averageTokens,
402
+ costLabel: factualCostAverageLabel(
403
+ overviewView === "tasks" ? factualCostFact : undefined,
404
+ selectedCount,
405
+ locale,
406
+ ),
407
+ count: selectedCount,
408
+ formatCost: (value) => formatCurrency(value, currency, locale),
409
+ formatDuration: (value) => formatDurationMs(value, locale),
410
+ formatTokens: (value) => formatCompactNumber(value, locale),
411
+ locale,
412
+ timeLabel: text.averageTime,
413
+ tokensLabel: text.averageTokens,
414
+ });
428
415
  const aggregateTopTasks: EntityMetric[] = (overviewMetrics?.top_tasks ?? []).map((metric) => ({
429
416
  id: metric.task_id,
430
417
  title: tasks.find((task) => task.id === metric.task_id)?.title ?? metric.task_id,
@@ -605,6 +592,12 @@ export function OperationsOverview({
605
592
  metricPopulationCount,
606
593
  (value) => formatDurationMs(value, locale),
607
594
  locale,
595
+ true,
596
+ )}
597
+ description={unmeasuredZeroDescription(
598
+ totalDurationMetric,
599
+ metricPopulationCount,
600
+ locale,
608
601
  )}
609
602
  />{" "}
610
603
  <Kpi
@@ -615,8 +608,8 @@ export function OperationsOverview({
615
608
  ? `0 / ${metricUnit} (0 / hora)`
616
609
  : `0 / ${metricUnit} (0 / hour)`
617
610
  : locale === "pt-BR"
618
- ? "Tokens por tarefa e por hora indisponíveis"
619
- : "Tokens per task and hour unavailable"
611
+ ? "Sem tokens medidos para calcular médias"
612
+ : "No measured tokens for averages"
620
613
  : locale === "pt-BR"
621
614
  ? `${formatCompactNumber(tokensPerTask, locale)} / ${metricUnit} (${formatCompactNumber(tokensPerHour, locale, 0)} / hora)`
622
615
  : `${formatCompactNumber(tokensPerTask, locale)} / ${metricUnit} (${formatCompactNumber(tokensPerHour, locale, 0)} / hour)`
@@ -635,9 +628,12 @@ export function OperationsOverview({
635
628
  metricPopulationCount,
636
629
  (value) => formatCompactNumber(value, locale),
637
630
  locale,
631
+ true,
638
632
  )}
633
+ description={unmeasuredZeroDescription(totalTokensMetric, metricPopulationCount, locale)}
639
634
  />{" "}
640
635
  <OverviewCostKpi
636
+ loading={costLoading && overviewView === "tasks"}
641
637
  fact={overviewView === "tasks" ? factualCostFact : undefined}
642
638
  unit={metricUnit}
643
639
  locale={locale}
@@ -658,6 +654,7 @@ export function OperationsOverview({
658
654
  <div className="operations-chart-grid">
659
655
  {" "}
660
656
  <OperationsOverviewCharts
657
+ costLoading={costLoading && overviewView === "tasks"}
661
658
  locale={locale}
662
659
  copy={copy}
663
660
  text={text}
@@ -685,6 +682,7 @@ export function OperationsOverview({
685
682
  }}
686
683
  />
687
684
  <OperationsOverviewTopPanel
685
+ costLoading={costLoading && overviewView === "tasks"}
688
686
  copy={{ empty: copy.emptyTop, hint: topHint, title: copy.topTitle }}
689
687
  currency={currency}
690
688
  locale={locale}
@@ -5,6 +5,7 @@ import type { OverviewClassification } from "./operations-page-contract.js";
5
5
  import type { OperationsLocale } from "./status-labels.js";
6
6
  import type { WorkStage } from "./work-board-model.js";
7
7
  export function OperationsOverviewCharts({
8
+ costLoading = false,
8
9
  locale,
9
10
  copy,
10
11
  text,
@@ -17,6 +18,7 @@ export function OperationsOverviewCharts({
17
18
  onStatusSelect,
18
19
  onClassificationSelect,
19
20
  }: {
21
+ costLoading?: boolean;
20
22
  locale: OperationsLocale;
21
23
  copy: ReturnType<typeof overviewCopy>;
22
24
  text: ReturnType<typeof overviewText>;
@@ -151,9 +153,16 @@ export function OperationsOverviewCharts({
151
153
  <PanelHeader hint={copy.averageHint} title={copy.averageTitle} />{" "}
152
154
  <div className="operations-type-summary">
153
155
  {" "}
154
- {metricStats.map(([label, value]) => (
155
- <div key={label}>
156
- <span>{label}</span> <strong>{value}</strong>{" "}
156
+ {metricStats.map(([label, value], index) => (
157
+ <div aria-busy={(costLoading && index === 2) || undefined} key={label}>
158
+ <span>{label}</span>{" "}
159
+ <strong>
160
+ {costLoading && index === 2 ? (
161
+ <i className="operations-skeleton-line" aria-hidden="true" />
162
+ ) : (
163
+ value
164
+ )}
165
+ </strong>{" "}
157
166
  </div>
158
167
  ))}{" "}
159
168
  </div>{" "}
@@ -10,13 +10,10 @@ import type { OperationsLocale } from "./status-labels.js";
10
10
  type OverviewView = "tasks" | "specs" | "prds";
11
11
 
12
12
  const duration = (value: number | null, locale: OperationsLocale) =>
13
- value === null
14
- ? locale === "pt-BR"
15
- ? "Indisponível"
16
- : "Unavailable"
17
- : formatDurationMs(value, locale);
13
+ value === null ? "0" : formatDurationMs(value, locale);
18
14
 
19
15
  export function OperationsOverviewTopPanel({
16
+ costLoading = false,
20
17
  copy,
21
18
  currency,
22
19
  locale,
@@ -28,6 +25,7 @@ export function OperationsOverviewTopPanel({
28
25
  topEntities,
29
26
  view,
30
27
  }: {
28
+ costLoading?: boolean;
31
29
  copy: { empty: string; hint: string; title: string };
32
30
  currency: "BRL" | "USD";
33
31
  locale: OperationsLocale;
@@ -108,16 +106,16 @@ export function OperationsOverviewTopPanel({
108
106
  </div>
109
107
  <div>
110
108
  <span>{text.topFiveCost}</span>
111
- <strong>
112
- {topCost === null
113
- ? duration(null, locale)
114
- : formatCurrency(topCost, currency, locale)}
109
+ <strong aria-busy={costLoading || undefined}>
110
+ {costLoading ? (
111
+ <i className="operations-skeleton-line" aria-hidden="true" />
112
+ ) : topCost === null ? (
113
+ duration(null, locale)
114
+ ) : (
115
+ formatCurrency(topCost, currency, locale)
116
+ )}
115
117
  </strong>
116
- <small>
117
- {summary.tokens === null
118
- ? text.tokensUnavailable
119
- : `${formatCompactNumber(summary.tokens, locale)} tokens`}
120
- </small>
118
+ <small>{`${formatCompactNumber(summary.tokens, locale)} tokens`}</small>
121
119
  </div>
122
120
  </div>
123
121
  </>
@@ -13,6 +13,7 @@ import {
13
13
  import { OperationsMainContent } from "./OperationsMainContent.js";
14
14
  import { OperationsViewTabs } from "./OperationsPageNavigation.js";
15
15
  import { OperationsPageLoading, OperationsPageOverview } from "./OperationsPageOverview.js";
16
+ import { shouldRenderOperationsContent } from "./operations-content-visibility.js";
16
17
  import {
17
18
  type OperationsPageProps,
18
19
  resolveOperationsPeriodControl,
@@ -77,7 +78,7 @@ export function OperationsPage({
77
78
  capabilityNavigation,
78
79
  currency,
79
80
  data,
80
- dashboardTitle = "Dashboard Zaip AIOS",
81
+ dashboardTitle = "Dashboard ZAIP AIOS",
81
82
  lastUpdatedAt = data.summary.latest_token_collected_at ?? null,
82
83
  loading,
83
84
  onLoadingChange,
@@ -110,6 +111,7 @@ export function OperationsPage({
110
111
  settings,
111
112
  factualCostTotal,
112
113
  factualCostFact,
114
+ costLoading,
113
115
  factualCostPeriods,
114
116
  resolveRunCost,
115
117
  }: OperationsPageProps) {
@@ -662,6 +664,7 @@ export function OperationsPage({
662
664
  query={query}
663
665
  factualCostTotal={factualCostTotal}
664
666
  factualCostFact={factualCostFact}
667
+ costLoading={costLoading}
665
668
  resolveRunCost={resolveRunCost}
666
669
  runs={runs}
667
670
  searchInputRef={searchInputRef}
@@ -758,6 +761,3 @@ export function OperationsPage({
758
761
  }
759
762
 
760
763
  /** Loading is never a valid zero-valued Operations projection. */
761
- export function shouldRenderOperationsContent(loading: boolean): boolean {
762
- return !loading;
763
- }
@@ -20,6 +20,7 @@ export function OperationsPageOverview({
20
20
  defaultDateRange,
21
21
  factualCostTotal,
22
22
  factualCostFact,
23
+ costLoading,
23
24
  includeLegacyEffort,
24
25
  locale,
25
26
  onOpenTask,
@@ -49,6 +50,7 @@ export function OperationsPageOverview({
49
50
  defaultDateRange: OperationDateRange;
50
51
  factualCostTotal: OverviewProps["factualCostTotal"];
51
52
  factualCostFact: OverviewProps["factualCostFact"];
53
+ costLoading: OverviewProps["costLoading"];
52
54
  includeLegacyEffort: boolean;
53
55
  locale: OperationsLocale;
54
56
  onOpenTask: OverviewProps["onOpenTask"];
@@ -77,6 +79,7 @@ export function OperationsPageOverview({
77
79
  currency={currency}
78
80
  factualCostTotal={factualCostTotal}
79
81
  factualCostFact={factualCostFact}
82
+ costLoading={costLoading}
80
83
  datePreset={datePreset}
81
84
  dateRange={dateRange}
82
85
  locale={locale}
@@ -163,13 +166,29 @@ export function OperationsPageLoading({ locale }: { locale: OperationsLocale })
163
166
  return (
164
167
  <section
165
168
  aria-busy="true"
166
- aria-live="polite"
169
+ aria-label={
170
+ locale === "pt-BR" ? "Carregando o período selecionado" : "Loading selected period"
171
+ }
167
172
  className="operations-content-skeleton"
168
173
  role="status"
169
174
  >
170
- <span>
171
- {locale === "pt-BR" ? "Carregando o período selecionado…" : "Loading selected period…"}
172
- </span>
175
+ <div className="operations-skeleton-kpis" aria-hidden="true">
176
+ {["tasks", "specs", "prds", "duration", "tokens", "cost"].map((metric) => (
177
+ <article className="operations-skeleton-block" key={metric}>
178
+ <i className="operations-skeleton-line is-short" />
179
+ <i className="operations-skeleton-line is-value" />
180
+ <i className="operations-skeleton-line" />
181
+ </article>
182
+ ))}
183
+ </div>
184
+ <div className="operations-skeleton-panels" aria-hidden="true">
185
+ {["status", "classification", "average", "top"].map((panel) => (
186
+ <article className="operations-skeleton-block" key={panel}>
187
+ <i className="operations-skeleton-line is-short" />
188
+ <i className="operations-skeleton-chart" />
189
+ </article>
190
+ ))}
191
+ </div>
173
192
  </section>
174
193
  );
175
194
  }
@@ -5,7 +5,11 @@ import {
5
5
  overviewCostRateHint,
6
6
  } from "./OperationsOverview.helpers.js";
7
7
  import type { FactualCostFact } from "./operations-page-contract.js";
8
- import { formatRoundedCurrency, formatSummaryMetricValue } from "./overview-metric-format.js";
8
+ import {
9
+ formatRoundedCurrency,
10
+ formatSummaryMetricValue,
11
+ unmeasuredZeroDescription,
12
+ } from "./overview-metric-format.js";
9
13
  import type { OperationsLocale } from "./status-labels.js";
10
14
 
11
15
  /** Compact presentation, preserving completeness and matching population semantics. */
@@ -19,6 +23,7 @@ export function OverviewCostKpi({
19
23
  perHour,
20
24
  total,
21
25
  label,
26
+ loading = false,
22
27
  }: {
23
28
  fact: FactualCostFact | undefined;
24
29
  unit: string;
@@ -29,17 +34,40 @@ export function OverviewCostKpi({
29
34
  perHour: number | null;
30
35
  total: number | null;
31
36
  label?: string | undefined;
37
+ loading?: boolean;
32
38
  }) {
39
+ if (loading)
40
+ return (
41
+ <article
42
+ aria-busy="true"
43
+ aria-label={locale === "pt-BR" ? "Carregando custo estimado" : "Loading estimated cost"}
44
+ className="operations-kpi"
45
+ role="status"
46
+ >
47
+ <span>{label ?? (locale === "pt-BR" ? "Custo Estimado" : "Estimated Cost")}</span>
48
+ <strong>
49
+ <i className="operations-skeleton-line is-value" aria-hidden="true" />
50
+ </strong>
51
+ <small>
52
+ <i className="operations-skeleton-line" aria-hidden="true" />
53
+ </small>
54
+ </article>
55
+ );
33
56
  return (
34
57
  <Kpi
35
58
  hint={overviewCostRateHint(fact, unit, locale, currency, count, perItem, perHour)}
36
- description={factualCostMetricHint(fact, unit, locale) ?? undefined}
59
+ description={
60
+ unmeasuredZeroDescription(total, count, locale) ??
61
+ factualCostMetricHint(fact, unit, locale) ??
62
+ undefined
63
+ }
37
64
  label={label ?? factualCostMetricLabel(fact, locale)}
38
65
  value={formatSummaryMetricValue(
39
66
  total,
40
67
  count,
41
68
  (value) => formatRoundedCurrency(value, currency, locale),
42
69
  locale,
70
+ true,
43
71
  )}
44
72
  />
45
73
  );
@@ -69,23 +69,12 @@ export function TaskDetailsDialog({
69
69
  label={copy.duration}
70
70
  value={formatOperationDuration(telemetry.durationMs, locale)}
71
71
  />
72
- <Detail
73
- label="Tokens"
74
- value={
75
- telemetry.tokens === null
76
- ? locale === "pt-BR"
77
- ? "Indisponível"
78
- : "Unavailable"
79
- : formatCompactNumber(telemetry.tokens, locale)
80
- }
81
- />
72
+ <Detail label="Tokens" value={formatCompactNumber(telemetry.tokens, locale)} />
82
73
  <Detail
83
74
  label={locale === "pt-BR" ? "Custo" : "Cost"}
84
75
  value={
85
76
  telemetry.costBrl === null
86
- ? locale === "pt-BR"
87
- ? "Indisponível"
88
- : "Unavailable"
77
+ ? "0"
89
78
  : new Intl.NumberFormat(locale, { style: "currency", currency: "BRL" }).format(
90
79
  telemetry.costBrl,
91
80
  )
@@ -1,7 +1,14 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { mergeManualWorkOrder, sortWorkItems } from "./UnifiedWorkBoard.js";
2
+ import { mergeManualWorkOrder, sortWorkItems, workColumnState } from "./UnifiedWorkBoard.js";
3
3
 
4
4
  describe("UnifiedWorkBoard priority path", () => {
5
+ it("does not claim an unrequested or in-flight column is empty", () => {
6
+ expect(workColumnState(0, 0, undefined)).toBe("loading");
7
+ expect(workColumnState(0, 2, { loading: false, error: null })).toBe("loading");
8
+ expect(workColumnState(0, 0, { loading: true, error: null })).toBe("loading");
9
+ expect(workColumnState(0, 0, { loading: false, error: null })).toBe("empty");
10
+ expect(workColumnState(0, 0, { loading: false, error: "falhou" })).toBe("error");
11
+ });
5
12
  const item = (id: string, rank: number | null, createdAt = "2026-08-04T10:00:00.000Z") =>
6
13
  ({ kind: "task", row: { id, manual_order: rank, updated_at: createdAt } }) as never;
7
14
 
@@ -18,6 +18,7 @@ import { TaskDetailsDialog } from "./TaskDetailsDialog.js";
18
18
  import { taskOrigin } from "./task-origin.js";
19
19
  import { useCurrentTime } from "./use-current-time.js";
20
20
  import { useInfiniteColumn } from "./use-infinite-column.js";
21
+ import { WorkColumnState } from "./WorkColumnState.js";
21
22
  import {
22
23
  isWorkItemVisible,
23
24
  type MacroWorkProgress,
@@ -30,6 +31,9 @@ import {
30
31
  workStageLabel,
31
32
  workStages,
32
33
  } from "./work-board-model.js";
34
+ import { openWorkCardLabel } from "./work-card-label.js";
35
+ import { workColumnState } from "./work-column-state.js";
36
+ import { filterWorkItems } from "./work-item-filter.js";
33
37
  import "./unified-work-board.css";
34
38
 
35
39
  type WorkItem =
@@ -323,6 +327,7 @@ function WorkColumn({
323
327
  totalItems,
324
328
  onLoadMore,
325
329
  );
330
+ const displayState = workColumnState(items.length, totalItems, state);
326
331
  return (
327
332
  <article className={`operations-column is-${stage}`}>
328
333
  <header>
@@ -371,9 +376,7 @@ function WorkColumn({
371
376
  totalsByTask={totalsByTask}
372
377
  />
373
378
  ))}
374
- {items.length === 0 && !state?.loading ? (
375
- <p className="operations-empty">{locale === "pt-BR" ? "Sem itens" : "No items"}</p>
376
- ) : null}
379
+ <WorkColumnState error={state?.error} locale={locale} state={displayState} />
377
380
  {hasMore ? (
378
381
  <div
379
382
  aria-live="polite"
@@ -543,9 +546,8 @@ function WorkCard({
543
546
  );
544
547
  }
545
548
 
546
- export function openWorkCardLabel(locale: OperationsLocale, title: string): string {
547
- return locale === "pt-BR" ? `Abrir ${title}` : `Open ${title}`;
548
- }
549
+ export { openWorkCardLabel } from "./work-card-label.js";
550
+ export { workColumnState } from "./work-column-state.js";
549
551
 
550
552
  /** Replaces only visible-column slots, preserving the global order of all other work. */
551
553
  export function mergeManualWorkOrder(
@@ -561,16 +563,6 @@ export function mergeManualWorkOrder(
561
563
  );
562
564
  }
563
565
 
564
- export function filterWorkItems(items: readonly WorkItem[], query: string): WorkItem[] {
565
- const normalized = query.trim().toLocaleLowerCase();
566
- if (!normalized) return [...items];
567
- return items.filter((item) =>
568
- [item.row.id, item.row.title, item.kind].some((value) =>
569
- value.toLocaleLowerCase().includes(normalized),
570
- ),
571
- );
572
- }
573
-
574
566
  function WorkColumnDialog({
575
567
  items,
576
568
  locale,