@zaip-ai/cli 4.5.0 → 4.7.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 (244) hide show
  1. package/README.md +2 -0
  2. package/dist/commands/init.js +1 -1
  3. package/dist/commands/init.js.map +1 -1
  4. package/dist/services/adapters.d.ts +1 -1
  5. package/dist/services/adapters.d.ts.map +1 -1
  6. package/dist/services/adapters.js +6 -6
  7. package/dist/services/adapters.js.map +1 -1
  8. package/dist/services/codex-config-overlay.d.ts.map +1 -1
  9. package/dist/services/codex-config-overlay.js +27 -10
  10. package/dist/services/codex-config-overlay.js.map +1 -1
  11. package/dist/services/codex-native-tool-authority-template.d.ts.map +1 -1
  12. package/dist/services/codex-native-tool-authority-template.js +188 -9
  13. package/dist/services/codex-native-tool-authority-template.js.map +1 -1
  14. package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
  15. package/dist/services/codex-pre-tool-hook-template.js +50 -128
  16. package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
  17. package/dist/services/codex-pre-tool-hook-template.test.js +4 -0
  18. package/dist/services/codex-pre-tool-hook-template.test.js.map +1 -1
  19. package/dist/services/codex-pre-tool-support-template.d.ts.map +1 -1
  20. package/dist/services/codex-pre-tool-support-template.js +1 -4
  21. package/dist/services/codex-pre-tool-support-template.js.map +1 -1
  22. package/dist/services/codex-stale-git-lock-template.d.ts +2 -0
  23. package/dist/services/codex-stale-git-lock-template.d.ts.map +1 -0
  24. package/dist/services/codex-stale-git-lock-template.js +64 -0
  25. package/dist/services/codex-stale-git-lock-template.js.map +1 -0
  26. package/dist/services/global-codex-config-migration.test.js +1 -4
  27. package/dist/services/global-codex-config-migration.test.js.map +1 -1
  28. package/dist/services/global-codex-config.d.ts.map +1 -1
  29. package/dist/services/global-codex-config.js +2 -1
  30. package/dist/services/global-codex-config.js.map +1 -1
  31. package/dist/services/global-codex-config.test.js +3 -1
  32. package/dist/services/global-codex-config.test.js.map +1 -1
  33. package/dist/services/hook-readiness.d.ts.map +1 -1
  34. package/dist/services/hook-readiness.js.map +1 -1
  35. package/dist/services/install-agents-template.js +2 -2
  36. package/dist/services/install-agents-template.js.map +1 -1
  37. package/dist/services/install-template-policy.d.ts.map +1 -1
  38. package/dist/services/install-template-policy.js +2 -0
  39. package/dist/services/install-template-policy.js.map +1 -1
  40. package/dist/services/logger.d.ts +1 -1
  41. package/dist/services/logger.d.ts.map +1 -1
  42. package/dist/services/logger.js +2 -1
  43. package/dist/services/logger.js.map +1 -1
  44. package/dist/services/logger.test.js +77 -0
  45. package/dist/services/logger.test.js.map +1 -1
  46. package/dist/services/runtime-template-integrity.test.d.ts +2 -0
  47. package/dist/services/runtime-template-integrity.test.d.ts.map +1 -0
  48. package/dist/services/runtime-template-integrity.test.js +26 -0
  49. package/dist/services/runtime-template-integrity.test.js.map +1 -0
  50. package/dist/services/runtime-template-test-support.d.ts +3 -0
  51. package/dist/services/runtime-template-test-support.d.ts.map +1 -0
  52. package/dist/services/runtime-template-test-support.js +32 -0
  53. package/dist/services/runtime-template-test-support.js.map +1 -0
  54. package/dist/services/runtime-template.test.js +37 -48
  55. package/dist/services/runtime-template.test.js.map +1 -1
  56. package/package.json +1 -1
  57. package/templates/.agents/README.md +8 -0
  58. package/templates/.agents/config/agents/discovery.json +1 -1
  59. package/templates/.agents/config/deploy-policy.json +5 -0
  60. package/templates/.agents/dashboard/.zaip-managed.json +235 -83
  61. package/templates/.agents/dashboard/README.md +2 -0
  62. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-f4ZGJRg3.js → CostCalculationGuidePage-OUjdwEcM.js} +1 -1
  63. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-CkQ_y8kg.js → DashboardHelpDialog-Cei1ChjE.js} +99 -10
  64. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-v9zGRTlk.js → PricingSettingsDialog-_woNCrTT.js} +1 -1
  65. package/templates/.agents/dashboard/apps/frontend/dist/assets/{ProjectSettingsPage-doIMhei7.js → ProjectSettingsPage-B2_7MVOP.js} +1 -1
  66. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-C_4ftjyB.js → TraceabilityWorkspace-C_jCsSZe.js} +1 -1
  67. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-C8zQDBT7.js +68 -0
  68. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-Cv3WBFIF.js → icons-vendor-iMPXot7Y.js} +1 -1
  69. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DZhppOIk.css +1 -0
  70. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DiCwz0sr.js +2 -0
  71. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-mHgsmxb6.js → react-vendor-721Re3Ss.js} +1 -1
  72. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-B0CPyEVq.js → traceability-BjdTkWS0.js} +1 -1
  73. package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
  74. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  75. package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +6 -34
  76. package/templates/.agents/dashboard/apps/frontend/src/ReconciliationFeedback.dom.test.ts +130 -0
  77. package/templates/.agents/dashboard/apps/frontend/src/ReconciliationFeedback.tsx +226 -0
  78. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-sqlite-view.ts +45 -0
  79. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +15 -0
  80. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +17 -46
  81. package/templates/.agents/dashboard/apps/frontend/src/reconciliation-feedback-fixtures.ts +23 -0
  82. package/templates/.agents/dashboard/apps/frontend/src/reconciliation-feedback-model.test.ts +69 -0
  83. package/templates/.agents/dashboard/apps/frontend/src/reconciliation-feedback-model.ts +59 -0
  84. package/templates/.agents/dashboard/apps/frontend/src/reconciliation-feedback.css +131 -0
  85. package/templates/.agents/dashboard/apps/frontend/src/styles.css +0 -32
  86. package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +2 -2
  87. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  88. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +2 -2
  89. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +1 -1
  90. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  91. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.macro-metrics.test.ts +7 -2
  92. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +6 -6
  93. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +1 -4
  94. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.navigation.test.ts +236 -0
  95. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +1 -24
  96. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +3 -2
  97. package/templates/.agents/dashboard/modules/operations/src/react/overview-duration-hint.ts +14 -0
  98. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  99. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  100. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  101. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  102. package/templates/.agents/dashboard/packages/local-runtime/DIAGNOSTICS.md +42 -0
  103. package/templates/.agents/dashboard/packages/local-runtime/dashboard-diagnostics.d.mts +10 -0
  104. package/templates/.agents/dashboard/packages/local-runtime/dashboard-diagnostics.mjs +101 -0
  105. package/templates/.agents/dashboard/packages/local-runtime/dashboard-diagnostics.test.mjs +58 -0
  106. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +318 -236
  107. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +285 -205
  108. package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
  109. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-dashboard-startup.mjs +233 -0
  110. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-provider-nonzero.mjs +45 -0
  111. package/templates/.agents/dashboard/packages/local-runtime/scripts/verify-dashboard-executable-startup.mjs +107 -0
  112. package/templates/.agents/dashboard/packages/local-runtime/scripts/verify-dashboard-reconciliation-executable.mjs +271 -0
  113. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +318 -236
  114. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.test.ts +78 -12
  115. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +36 -56
  116. package/templates/.agents/dashboard/packages/local-runtime/src/canonical-source-revision-cache.test.ts +125 -0
  117. package/templates/.agents/dashboard/packages/local-runtime/src/canonical-source-revision-cache.ts +168 -0
  118. package/templates/.agents/dashboard/packages/local-runtime/src/dashboard-diagnostics.test.ts +57 -0
  119. package/templates/.agents/dashboard/packages/local-runtime/src/server-agent-catalog-routes.ts +76 -0
  120. package/templates/.agents/dashboard/packages/local-runtime/src/server-dual-reads-manifest-summaries-without-losing.test.ts +5 -0
  121. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-diagnostics.test.ts +118 -0
  122. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-result.test.ts +35 -6
  123. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-route.ts +105 -0
  124. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +64 -9
  125. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +19 -27
  126. package/templates/.agents/dashboard/packages/local-runtime/src/server-telemetry-command.test.ts +111 -0
  127. package/templates/.agents/dashboard/packages/local-runtime/src/server-telemetry-refresh.test.ts +59 -0
  128. package/templates/.agents/dashboard/packages/local-runtime/src/server-telemetry-refresh.ts +44 -0
  129. package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +20 -0
  130. package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +12 -7
  131. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +48 -6
  132. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +2 -2
  133. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +126 -134
  134. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.ts +14 -2
  135. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-summary-elapsed.ts +107 -0
  136. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-dashboard-startup.test.ts +163 -0
  137. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-dashboard-startup.ts +78 -0
  138. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-header-timestamp.test.ts +31 -0
  139. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-provider-nonzero.test.ts +271 -0
  140. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-provider-visibility.ts +32 -0
  141. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-operations-duration.ts +58 -0
  142. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-provider-dimension.ts +12 -3
  143. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +41 -54
  144. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-view-page.ts +9 -58
  145. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical.ts +7 -7
  146. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +5 -5
  147. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider.test.ts +4 -4
  148. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +9 -35
  149. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +13 -9
  150. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +43 -45
  151. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +5 -9
  152. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +5 -1
  153. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-base-views.ts +9 -7
  154. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-dashboard-views.ts +10 -8
  155. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-spec-root-elapsed-view.ts +61 -0
  156. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-spec-root-elapsed.test.ts +210 -0
  157. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-startup-seed.test.ts +87 -0
  158. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-logging.mjs +6 -2
  159. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-server.mjs +7 -1
  160. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +4 -5
  161. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  162. package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.test.mjs +33 -4
  163. package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.tsx +8 -7
  164. package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +46 -3
  165. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  166. package/templates/.agents/dashboard/tests/e2e/qualify-kanban-popup.mjs +56 -0
  167. package/templates/.agents/dashboard/tests/e2e/specs/dashboard-update-label.spec.ts +49 -0
  168. package/templates/.agents/design/.zaip-managed.json +17 -5
  169. package/templates/.agents/design/apps/catalog/dist/assets/index-D3uhpycC.js +72 -0
  170. package/templates/.agents/design/apps/catalog/dist/index.html +1 -1
  171. package/templates/.agents/design/apps/catalog/package.json +1 -1
  172. package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +13 -1
  173. package/templates/.agents/design/apps/catalog/src/specimens/ReconciliationSpecimen.stories.tsx +6 -0
  174. package/templates/.agents/design/apps/catalog/src/specimens/ReconciliationSpecimen.tsx +101 -0
  175. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  176. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  177. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
  178. package/templates/.agents/requirements/comparative-audit.md +1 -1
  179. package/templates/.agents/requirements/context-engine.md +1 -1
  180. package/templates/.agents/requirements/cost-observability.md +1 -1
  181. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  182. package/templates/.agents/requirements/data-export.md +1 -1
  183. package/templates/.agents/requirements/design-system.md +1 -1
  184. package/templates/.agents/requirements/execution-engine.md +1 -1
  185. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  186. package/templates/.agents/requirements/model-orchestration.md +21 -6
  187. package/templates/.agents/requirements/public-distribution.md +4 -4
  188. package/templates/.agents/requirements/software-architecture.md +1 -1
  189. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  190. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  191. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  192. package/templates/.agents/rules/core.md +3 -1
  193. package/templates/.agents/rules/workflow.md +3 -2
  194. package/templates/.agents/runtime/VERSION +1 -1
  195. package/templates/.agents/runtime/bin/zaip.mjs +368 -199
  196. package/templates/.agents/runtime/checksums.sha256 +5 -5
  197. package/templates/.agents/runtime/manifest.json +1 -1
  198. package/templates/.agents/runtime/provenance.json +4 -4
  199. package/templates/.agents/runtime/sbom.cdx.json +1 -1
  200. package/templates/.agents/skills/zaip-skill-config/SKILL.md +25 -3
  201. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +4 -0
  202. package/templates/.agents/skills/zaip-skill-execution/references/autonomous-continuation.md +4 -0
  203. package/templates/.agents/skills/zaip-skill-execution/references/candidate-workflow.md +1 -1
  204. package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +2 -2
  205. package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +1 -0
  206. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +38 -48
  207. package/templates/.agents/skills/zaip-skill-github-deploy/agents/openai.yaml +2 -2
  208. package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +67 -99
  209. package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +33 -30
  210. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/deploy-contract.mjs +307 -0
  211. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/deploy-contract.test.mjs +337 -0
  212. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +41 -28
  213. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/guarded-commits.mjs +212 -0
  214. package/templates/.agents/skills/zaip-skill-lifecycle-closure/SKILL.md +4 -0
  215. package/templates/.agents/skills/zaip-skill-prd/SKILL.md +4 -0
  216. package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +46 -68
  217. package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +100 -44
  218. package/templates/.agents/skills/zaip-skill-send-email/SKILL.md +15 -0
  219. package/templates/.agents/skills/zaip-skill-send-email/agents/openai.yaml +4 -0
  220. package/templates/.agents/skills/zaip-skill-setup/SKILL.md +5 -2
  221. package/templates/.agents/skills/zaip-skill-spec/SKILL.md +4 -0
  222. package/templates/.agents/skills/zaip-skill-task/SKILL.md +4 -0
  223. package/templates/.agents/skills/zaip-skill-testing-strategy/SKILL.md +19 -0
  224. package/templates/.agents/skills/zaip-skill-tool-setup/SKILL.md +2 -0
  225. package/templates/.agents/skills/zaip-skill-use-connectors/SKILL.md +15 -0
  226. package/templates/.agents/skills/zaip-skill-use-connectors/agents/openai.yaml +4 -0
  227. package/templates/.agents/skills/zaip-skill-use-connectors/scripts/connector-guidance.test.mjs +29 -0
  228. package/templates/.agents/skills/zaip-skill-use-connectors/scripts/verify-connector-lock.mjs +30 -0
  229. package/templates/.agents/tools/cloud-runner.integration.test.mjs +3 -0
  230. package/templates/.agents/zaip-aios/VERSION +1 -1
  231. package/templates/.agents/zaip-aios/guides/03-tasks.md +6 -0
  232. package/templates/.agents/zaip-aios/guides/04-specs.md +6 -0
  233. package/templates/.agents/zaip-aios/guides/05-prds.md +4 -0
  234. package/templates/.agents/zaip-aios/guides/06-execucao.md +6 -0
  235. package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +6 -0
  236. package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +4 -0
  237. package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +6 -0
  238. package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +36 -4
  239. package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +15 -4
  240. package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +8 -0
  241. package/templates/template-manifest.json +354 -150
  242. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-D7PrDZy9.js +0 -68
  243. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-OBJXZOwe.css +0 -1
  244. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Rbmpz4UO.js +0 -2
@@ -0,0 +1,131 @@
1
+ .app-reconciliation-result {
2
+ position: fixed;
3
+ z-index: 80;
4
+ right: 18px;
5
+ bottom: 18px;
6
+ display: grid;
7
+ gap: 8px;
8
+ width: min(440px, calc(100vw - 36px));
9
+ max-height: calc(100dvh - 36px);
10
+ overflow: auto;
11
+ overflow-wrap: anywhere;
12
+ border: 1px solid var(--accent-border);
13
+ border-radius: 16px;
14
+ padding: 16px;
15
+ background: var(--surface-raised);
16
+ box-shadow: var(--shadow);
17
+ }
18
+
19
+ .app-reconciliation-result strong {
20
+ color: var(--text);
21
+ }
22
+ .app-reconciliation-result p {
23
+ color: var(--muted);
24
+ font-size: 0.82rem;
25
+ margin: 8px 0 0;
26
+ }
27
+ .app-reconciliation-actions {
28
+ display: flex;
29
+ flex-wrap: wrap;
30
+ gap: 8px;
31
+ }
32
+ .app-reconciliation-result button,
33
+ .app-reconciliation-dialog button {
34
+ min-height: 44px;
35
+ border: 1px solid var(--line-strong);
36
+ border-radius: 8px;
37
+ cursor: pointer;
38
+ padding: 8px 16px;
39
+ color: var(--text);
40
+ background: var(--surface-muted);
41
+ }
42
+ .app-reconciliation-actions button:first-child {
43
+ border-color: var(--accent-border);
44
+ }
45
+ .app-reconciliation-dialog {
46
+ position: fixed;
47
+ inset: 0;
48
+ display: none;
49
+ grid-template-rows: auto minmax(0, 1fr);
50
+ width: 100%;
51
+ height: 100dvh;
52
+ max-width: none;
53
+ max-height: none;
54
+ margin: 0;
55
+ padding: 0;
56
+ overflow: hidden;
57
+ border: 0;
58
+ color: var(--text);
59
+ background: var(--surface);
60
+ }
61
+ .app-reconciliation-dialog[open] {
62
+ display: grid;
63
+ }
64
+ .app-reconciliation-dialog > header {
65
+ display: flex;
66
+ align-items: center;
67
+ justify-content: space-between;
68
+ flex-wrap: wrap;
69
+ gap: 8px;
70
+ min-width: 0;
71
+ padding: 16px;
72
+ border-bottom: 1px solid var(--line);
73
+ }
74
+ .app-reconciliation-dialog h2 {
75
+ flex: 1 1 240px;
76
+ margin: 0;
77
+ font-size: 1.25rem;
78
+ overflow-wrap: anywhere;
79
+ }
80
+ .app-reconciliation-details {
81
+ min-height: 0;
82
+ min-width: 0;
83
+ padding: 16px;
84
+ overflow: auto;
85
+ overscroll-behavior: contain;
86
+ overflow-wrap: anywhere;
87
+ }
88
+ .app-reconciliation-details > p {
89
+ max-width: 75ch;
90
+ color: var(--muted);
91
+ line-height: 1.65;
92
+ }
93
+ .app-reconciliation-details section {
94
+ margin-top: 24px;
95
+ }
96
+ .app-reconciliation-details h3 {
97
+ font-size: 1rem;
98
+ }
99
+ .app-reconciliation-details ul {
100
+ display: grid;
101
+ gap: 8px;
102
+ margin: 0;
103
+ padding: 0;
104
+ list-style: none;
105
+ }
106
+ .app-reconciliation-details li {
107
+ min-width: 0;
108
+ border: 1px solid var(--line);
109
+ border-radius: 8px;
110
+ padding: 16px;
111
+ background: var(--surface-muted);
112
+ }
113
+ .app-reconciliation-details code {
114
+ font-size: 0.82rem;
115
+ white-space: normal;
116
+ }
117
+ .app-reconciliation-details li p {
118
+ color: var(--muted);
119
+ margin: 8px 0 0;
120
+ line-height: 1.5;
121
+ }
122
+ .app-reconciliation-details summary {
123
+ margin-top: 8px;
124
+ cursor: pointer;
125
+ color: var(--muted);
126
+ }
127
+ .app-reconciliation-details:focus-visible,
128
+ .app-reconciliation-details summary:focus-visible {
129
+ outline: 2px solid var(--accent);
130
+ outline-offset: -2px;
131
+ }
@@ -457,38 +457,6 @@ select:focus-visible {
457
457
  background: rgba(148, 163, 184, 0.16);
458
458
  }
459
459
 
460
- .app-reconciliation-result {
461
- position: fixed;
462
- z-index: 80;
463
- right: 18px;
464
- bottom: 18px;
465
- display: grid;
466
- gap: 8px;
467
- width: min(520px, calc(100vw - 36px));
468
- border: 1px solid rgba(56, 189, 248, 0.35);
469
- border-radius: 14px;
470
- padding: 13px 15px;
471
- background: rgba(15, 23, 42, 0.98);
472
- box-shadow: var(--shadow);
473
- }
474
-
475
- .app-reconciliation-result strong {
476
- color: #e2e8f0;
477
- }
478
- .app-reconciliation-result span,
479
- .app-reconciliation-result p {
480
- color: #cbd5e1;
481
- font-size: 0.82rem;
482
- margin: 0;
483
- }
484
- .app-reconciliation-result button {
485
- justify-self: start;
486
- border: 0;
487
- border-radius: 6px;
488
- cursor: pointer;
489
- padding: 7px 10px;
490
- }
491
-
492
460
  @media (max-width: 860px) {
493
461
  .app-skeleton-kpis {
494
462
  grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -66,7 +66,6 @@ import { useOperationsDetailExport } from "./use-operations-detail-export.js";
66
66
  import { useSnapshotNotice } from "./use-snapshot-notice.js";
67
67
  import "./loading-feedback.css";
68
68
  import "./period-transition-overlay.css";
69
-
70
69
  export function useDashboardAppModel() {
71
70
  const sessionToken = readDashboardSessionToken();
72
71
  useDashboardBrowserLease(sessionToken);
@@ -145,7 +144,8 @@ export function useDashboardAppModel() {
145
144
  >(null);
146
145
  useEffect(() => {
147
146
  void api
148
- .ready()
147
+ .captureTelemetry()
148
+ .then(() => api.ready())
149
149
  .then((ready) => setSnapshotUpdating(ready.snapshot_state === "updating"))
150
150
  .catch(() => {});
151
151
  }, [api]);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaip-ai/dashboard-cost-monitor",
3
- "version": "4.5.0",
3
+ "version": "4.7.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -340,8 +340,8 @@ describe("cost monitor navigation", () => {
340
340
  expect(page).toContain('eligible: view === "agentCalls" && serverPagingEligible');
341
341
  expect(page).toContain("setDetailLoading(false);");
342
342
  expect(page).toContain("const needsDimensionalDetail = false;");
343
- expect(page).toContain('view === "models" && useAggregateGroups ? (');
344
- expect(page).toContain("rows={groups.models}");
343
+ const content = readFileSync(new URL("./CostMonitorContent.tsx", import.meta.url), "utf8");
344
+ expect(content).toContain("rows={groups[key]}");
345
345
  });
346
346
 
347
347
  it("rejects a late A response after page request B and keeps the retry generation current", () => {
@@ -621,6 +621,7 @@ export function CostMonitorPage({
621
621
  }
622
622
  filtersActive={Object.values(filters).some(Boolean)}
623
623
  lastUpdatedAt={lastUpdatedAt}
624
+ snapshotUpdatedAt={operations?.summary.projection_updated_at ?? null}
624
625
  loading={loading || periodLoading}
625
626
  locale={locale}
626
627
  onLocaleChange={changeLocale}
@@ -708,7 +709,6 @@ export function CostMonitorPage({
708
709
  </div>
709
710
  ) : null}
710
711
  </div>{" "}
711
- {/* CostMonitorContent owns `view === "models" && useAggregateGroups ? (` and `rows={groups.models}`. */}{" "}
712
712
  <CostMonitorContent
713
713
  canonicalDurationTotal={canonicalDurationTotal}
714
714
  compactPage={compactPage ?? staleCompactPage}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaip-ai/dashboard-operations",
3
- "version": "4.5.0",
3
+ "version": "4.7.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -5,6 +5,7 @@ import {
5
5
  scopedOverviewMetric,
6
6
  selectedMacroMetricTotals,
7
7
  } from "./OperationsOverview.js";
8
+ import { overviewDurationHint } from "./overview-duration-hint.js";
8
9
 
9
10
  describe("macro overview metrics", () => {
10
11
  it("keeps narrowed SPEC/PRD totals scoped to returned entities", () => {
@@ -45,8 +46,12 @@ describe("macro overview metrics", () => {
45
46
  new URL("OperationsOverviewTopPanel.tsx", import.meta.url),
46
47
  "utf8",
47
48
  );
48
- expect(overview).toContain('"Tempo de ciclo de vida (Runs-raiz, todas as fases)."');
49
- expect(overview).toContain('"Lifecycle time (root Runs, all phases)."');
49
+ expect(overview).toContain("overviewDurationHint(");
50
+ expect(overviewDurationHint("prds", "pt-BR", "")).toBe(
51
+ "Tempo de ciclo de vida (Runs-raiz, todas as fases).",
52
+ );
53
+ expect(overviewDurationHint("prds", "en", "")).toBe("Lifecycle time (root Runs, all phases).");
54
+ expect(overviewDurationHint("specs", "pt-BR", "")).toContain("sem duplicar filhos");
50
55
  expect(topPanel).toContain(`<span>{\`#\${index + 1} \${entity.id.slice(-4)}\`}</span>`);
51
56
  expect(`${overview}\n${topPanel}`).not.toContain("operations-top-coverage");
52
57
  expect(`${overview}\n${topPanel}`).not.toContain("duração comprovada");
@@ -51,6 +51,7 @@ import type {
51
51
  OverviewStatusKind,
52
52
  OverviewStatusPage,
53
53
  } from "./operations-page-contract.js";
54
+ import { overviewDurationHint } from "./overview-duration-hint.js";
54
55
  import { type OperationsLocale, riskLabel } from "./status-labels.js";
55
56
  import { type WorkStage, workStageLabel, workStages } from "./work-board-model.js";
56
57
  import "./operations-overview.css";
@@ -480,12 +481,11 @@ export function OperationsOverview({
480
481
  (runs.length === 0 || resolveRunCost === undefined)
481
482
  ? null
482
483
  : topEntitiesSummary.costBrl;
483
- const topHint =
484
- overviewView === "tasks"
485
- ? text.topHint
486
- : locale === "pt-BR"
487
- ? "Tempo de ciclo de vida (Runs-raiz, todas as fases)."
488
- : "Lifecycle time (root Runs, all phases).";
484
+ // Macro duration is entity elapsed time. Task duration still uses its
485
+ // attributed execution population. Keep the user-facing hint coupled to
486
+ // the selected macro so a sum over different SPECs is never presented as
487
+ // a single global wall-clock interval.
488
+ const topHint = overviewDurationHint(overviewView, locale, text.topHint);
489
489
 
490
490
  const selectOverviewView = (view: OverviewView) => {
491
491
  setOverviewView(view);
@@ -343,9 +343,6 @@ export function OperationsPage({
343
343
  const exportRows = useMemo(() => {
344
344
  if (view === "daily" || view === "monthly" || view === "yearly") {
345
345
  const granularity = view === "daily" ? "day" : view === "monthly" ? "month" : "year";
346
- /* Keep the creation-only fallback contract explicit for static regression checks:
347
- aggregatePeriodSummary(
348
- summaryPopulation, */
349
346
  const periodRows =
350
347
  dailyPeriods === undefined || currency === "USD"
351
348
  ? aggregatePeriodSummary(
@@ -490,6 +487,7 @@ export function OperationsPage({
490
487
  dateRange.end !== defaultDateRange.end,
491
488
  )}
492
489
  lastUpdatedAt={lastUpdatedAt}
490
+ snapshotUpdatedAt={data.summary.projection_updated_at ?? null}
493
491
  loading={isLoading}
494
492
  locale={locale}
495
493
  onLocaleChange={onLocaleChange}
@@ -719,7 +717,6 @@ export function OperationsPage({
719
717
  />
720
718
  </div>
721
719
  </section>
722
- {/* PeriodSummaryTable delegation retains data={summaryPopulation}. */}
723
720
  <OperationsMainContent
724
721
  boardKindTotals={boardKindTotals}
725
722
  boardStates={boardStates}
@@ -0,0 +1,236 @@
1
+ import { createRequire } from "node:module";
2
+ import { fileURLToPath } from "node:url";
3
+ import type { Browser, Page } from "@playwright/test";
4
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
5
+ import type {
6
+ DashboardTaskProjection,
7
+ MacroProjection,
8
+ UsageMetricProjection,
9
+ } from "../contracts.js";
10
+
11
+ declare global {
12
+ interface Window {
13
+ __workBoardNavigationProbe: {
14
+ tasks: string[];
15
+ documents: { kind: "prd" | "spec"; id: string }[];
16
+ };
17
+ }
18
+ }
19
+
20
+ const createdAt = "2026-09-23T15:40:00.000Z";
21
+ const tasks: DashboardTaskProjection[] = ["A", "B"].map((suffix) => ({
22
+ schema_version: 2,
23
+ id: `TASK-TRACE-${suffix}`,
24
+ revision: 1,
25
+ change_id: `CHG-TRACE-${suffix}`,
26
+ title: `Task para rastreabilidade ${suffix}`,
27
+ short_name: `trace-${suffix}`,
28
+ objective: "Abrir a rastreabilidade da Task selecionada",
29
+ status: "executing",
30
+ attempt_count: 1,
31
+ risk: "standard",
32
+ priority: "medium",
33
+ owner: null,
34
+ requirement_ids: [],
35
+ acceptance_ids: [],
36
+ depends_on: [],
37
+ write_scopes: [],
38
+ created_at: createdAt,
39
+ updated_at: createdAt,
40
+ started_at: createdAt,
41
+ finished_at: null,
42
+ result: null,
43
+ artifact_path: `tasks/TASK-TRACE-${suffix}.md`,
44
+ progress: 50,
45
+ spec_id: null,
46
+ execution_started: true,
47
+ telemetry: { duration_ms: null, tokens: null, cost_brl: null },
48
+ }));
49
+
50
+ const unavailableUsage: UsageMetricProjection = {
51
+ events: 0,
52
+ tokens: { input: null, cached_input: null, output: null, reasoning: null, total: null },
53
+ cost: { usd: null, brl: null },
54
+ coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
55
+ };
56
+ const macros: MacroProjection[] = (["prd", "spec"] as const).map((kind) => ({
57
+ id: `${kind.toUpperCase()}-PLANNING`,
58
+ kind,
59
+ title: `Planejamento ${kind.toUpperCase()}`,
60
+ created_at: createdAt,
61
+ parent_id: null,
62
+ artifact_path: `${kind}/planning.md`,
63
+ lifecycle_status: "draft",
64
+ work_status: "planning",
65
+ execution_ids: [],
66
+ task_ids: [],
67
+ planned_tasks: [],
68
+ run_ids: [],
69
+ execution_count: 0,
70
+ task_count: 0,
71
+ run_count: 0,
72
+ duration_ms: null,
73
+ decisions: { human: 0, agent: 0 },
74
+ rework_run_count: 0,
75
+ quality: {
76
+ completed_tasks: 0,
77
+ task_completion_rate: 0,
78
+ terminal_runs: 0,
79
+ successful_runs: 0,
80
+ terminal_success_rate: 0,
81
+ rework_rate: 0,
82
+ },
83
+ usage: {
84
+ conversation: unavailableUsage,
85
+ planning: unavailableUsage,
86
+ execution: unavailableUsage,
87
+ total: unavailableUsage,
88
+ new_work: unavailableUsage,
89
+ rework: unavailableUsage,
90
+ },
91
+ }));
92
+
93
+ const browserRequire = createRequire(
94
+ fileURLToPath(new URL("../../../../tests/e2e/package.json", import.meta.url)),
95
+ );
96
+ const { chromium, expect: expectPlaywright } = browserRequire("@playwright/test");
97
+
98
+ describe("UnifiedWorkBoard item navigation", () => {
99
+ let browser: Browser;
100
+ let bundle: string;
101
+
102
+ beforeAll(async () => {
103
+ const esbuild = browserRequire("esbuild");
104
+ const harness = await esbuild.build({
105
+ bundle: true,
106
+ define: { "import.meta.url": '"http://localhost/"' },
107
+ format: "iife",
108
+ loader: { ".css": "text" },
109
+ logLevel: "silent",
110
+ platform: "browser",
111
+ alias: {
112
+ "@zaip-ai/dashboard-ui": fileURLToPath(
113
+ new URL("../../../../packages/ui/src/index.ts", import.meta.url),
114
+ ),
115
+ react: fileURLToPath(
116
+ new URL(
117
+ "../../../../../../node_modules/.pnpm/react@19.2.7/node_modules/react",
118
+ import.meta.url,
119
+ ),
120
+ ),
121
+ "react-dom": fileURLToPath(
122
+ new URL(
123
+ "../../../../../../node_modules/.pnpm/react-dom@19.2.7_react@19.2.7/node_modules/react-dom",
124
+ import.meta.url,
125
+ ),
126
+ ),
127
+ "lucide-react": fileURLToPath(
128
+ new URL(
129
+ "../../../../../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.7/node_modules/lucide-react",
130
+ import.meta.url,
131
+ ),
132
+ ),
133
+ },
134
+ stdin: {
135
+ contents: `
136
+ import React from "react";
137
+ import { createRoot } from "react-dom/client";
138
+ import { UnifiedWorkBoard } from "./UnifiedWorkBoard.js";
139
+ const tasks = ${JSON.stringify(tasks)};
140
+ const macros = ${JSON.stringify(macros)};
141
+ const prds = macros.filter((row) => row.kind === "prd");
142
+ const specs = macros.filter((row) => row.kind === "spec");
143
+ const probe = { tasks: [], documents: [] };
144
+ window.__workBoardNavigationProbe = probe;
145
+ Date.now = () => Date.parse("2026-09-29T11:20:00.000Z");
146
+ createRoot(document.getElementById("root")).render(
147
+ <UnifiedWorkBoard
148
+ allPrds={prds} allSpecs={specs} allTasks={tasks}
149
+ prds={prds} specs={specs} tasks={tasks}
150
+ changes={[]} runs={[]} locale="pt-BR"
151
+ onOpenTask={(id) => {
152
+ probe.tasks.push(id);
153
+ return new Promise(() => {});
154
+ }}
155
+ onOpenDocument={(kind, id) => probe.documents.push({ kind, id })}
156
+ onPriorityChange={async () => {}}
157
+ />
158
+ );
159
+ `,
160
+ loader: "tsx",
161
+ resolveDir: fileURLToPath(new URL(".", import.meta.url)),
162
+ sourcefile: "UnifiedWorkBoard.navigation-harness.tsx",
163
+ },
164
+ write: false,
165
+ });
166
+ bundle = harness.outputFiles[0].text;
167
+ browser = await chromium.launch({ headless: true });
168
+ }, 60_000);
169
+
170
+ afterAll(async () => {
171
+ await browser?.close();
172
+ }, 60_000);
173
+
174
+ it.each([
175
+ "card",
176
+ "column",
177
+ ] as const)("opens the exact Task trace directly from a %s and preserves PRD/SPEC dialogs", async (source) => {
178
+ const page = await browser.newPage();
179
+ const pageErrors: string[] = [];
180
+ page.on("pageerror", (error) => pageErrors.push(error.message));
181
+ try {
182
+ await page.setContent('<div id="root"></div>');
183
+ await page.addScriptTag({ content: bundle });
184
+
185
+ for (const [index, task] of tasks.entries()) {
186
+ await openItem(page, source, task.title, "Execução");
187
+ await expectPlaywright
188
+ .poll(() => page.evaluate(() => window.__workBoardNavigationProbe.tasks))
189
+ .toEqual(tasks.slice(0, index + 1).map((row) => row.id));
190
+ // The app owns trace loading; the board must leave no summary or column overlay.
191
+ await expectPlaywright(page.getByRole("dialog")).toHaveCount(0);
192
+ await expectPlaywright(
193
+ page.getByRole("button", { name: "Abrir rastreabilidade", exact: true }),
194
+ ).toHaveCount(0);
195
+ }
196
+
197
+ for (const macro of macros) {
198
+ const label = macro.kind.toUpperCase();
199
+ const stage =
200
+ macro.kind === "prd" ? "Definição (PRD + Requisitos)" : "Planejamento (SPEC + Change)";
201
+ await openItem(page, source, macro.title, stage);
202
+ const dialog = page.getByRole("dialog", { name: `Detalhes do ${label}`, exact: true });
203
+ await expectPlaywright(dialog).toBeVisible();
204
+ await expectPlaywright(dialog.getByRole("heading", { name: macro.title })).toBeVisible();
205
+ await expectPlaywright(dialog.getByText(macro.id, { exact: true })).toBeVisible();
206
+ await expectPlaywright(page.getByRole("dialog", { name: stage, exact: true })).toHaveCount(
207
+ 0,
208
+ );
209
+ await dialog.getByRole("button", { name: `Ler ${label} completa`, exact: true }).click();
210
+ await expectPlaywright(dialog).toHaveCount(0);
211
+ }
212
+
213
+ expect(await page.evaluate(() => window.__workBoardNavigationProbe)).toEqual({
214
+ tasks: tasks.map((row) => row.id),
215
+ documents: macros.map((row) => ({ kind: row.kind, id: row.id })),
216
+ });
217
+ expect(pageErrors).toEqual([]);
218
+ } finally {
219
+ await page.close();
220
+ }
221
+ }, 60_000);
222
+ });
223
+
224
+ async function openItem(page: Page, source: "card" | "column", title: string, stage: string) {
225
+ if (source === "card") {
226
+ await page.getByRole("button", { name: `Abrir ${title}`, exact: true }).click();
227
+ return;
228
+ }
229
+ await page.getByRole("button", { name: stage, exact: true }).click();
230
+ const dialog = page.getByRole("dialog", { name: stage, exact: true });
231
+ await expectPlaywright(dialog).toBeVisible();
232
+ await dialog
233
+ .getByRole("button")
234
+ .filter({ has: page.getByText(title, { exact: true }) })
235
+ .click();
236
+ }
@@ -14,7 +14,6 @@ import { formatRoundedDuration } from "./format-rounded-duration.js";
14
14
  import { MacroPlanningDialog } from "./MacroPlanningDialog.js";
15
15
  import { type OperationsLocale, riskLabel } from "./status-labels.js";
16
16
  import { taskTotals } from "./TaskBoard.js";
17
- import { TaskDetailsDialog } from "./TaskDetailsDialog.js";
18
17
  import { taskOrigin } from "./task-origin.js";
19
18
  import { useCurrentTime } from "./use-current-time.js";
20
19
  import { useInfiniteColumn } from "./use-infinite-column.js";
@@ -88,7 +87,6 @@ export function UnifiedWorkBoard({
88
87
  const [typeFilter, setTypeFilter] = useState<WorkTypeFilter>("all");
89
88
  const [selectedStage, setSelectedStage] = useState<WorkStage | null>(null);
90
89
  const [selectedMacro, setSelectedMacro] = useState<MacroProjection | null>(null);
91
- const [selectedTask, setSelectedTask] = useState<DashboardTaskProjection | null>(null);
92
90
  const [query, setQuery] = useState("");
93
91
  const [draggedId, setDraggedId] = useState<string | null>(null);
94
92
  const [optimisticOrder, setOptimisticOrder] = useState<readonly string[] | null>(null);
@@ -125,7 +123,7 @@ export function UnifiedWorkBoard({
125
123
  : items.filter((item) => itemStage(item, allTasks) === selectedStage);
126
124
  const openItem = (item: WorkItem) => {
127
125
  setSelectedStage(null);
128
- if (item.kind === "task") setSelectedTask(item.row);
126
+ if (item.kind === "task") void onOpenTask(item.row.id);
129
127
  else setSelectedMacro(item.row);
130
128
  };
131
129
  return (
@@ -215,31 +213,10 @@ export function UnifiedWorkBoard({
215
213
  tasks={allTasks}
216
214
  />
217
215
  ) : null}
218
- {selectedTask ? (
219
- <TaskDetailsDialog
220
- detail={{ task: selectedTask, body: "", artifact_path: selectedTask.artifact_path }}
221
- locale={locale}
222
- onClose={() => setSelectedTask(null)}
223
- onOpenTrace={(taskId) => {
224
- setSelectedTask(null);
225
- void onOpenTask(taskId);
226
- }}
227
- operations={{ decisions: [], runs }}
228
- summary
229
- summaryRunCount={exactTaskRunCount(selectedTask)}
230
- />
231
- ) : null}
232
216
  </section>
233
217
  );
234
218
  }
235
219
 
236
- function exactTaskRunCount(task: DashboardTaskProjection): number | null {
237
- const runCount = (task as DashboardTaskProjection & { run_count?: unknown }).run_count;
238
- return typeof runCount === "number" && Number.isInteger(runCount) && runCount >= 0
239
- ? runCount
240
- : null;
241
- }
242
-
243
220
  export function WorkTypeFilters({
244
221
  locale,
245
222
  onChange,
@@ -243,7 +243,8 @@ describe("overview period filter", () => {
243
243
  expect(source).toContain(
244
244
  "const summaryPopulation = periodSummaryPopulation(data, matchesSelectedDate);",
245
245
  );
246
- expect(source).toContain("aggregatePeriodSummary(\n summaryPopulation,");
247
- expect(source).toContain("data={summaryPopulation}");
246
+ expect(source).toMatch(/aggregatePeriodSummary\(\s*summaryPopulation,/);
247
+ const content = readFileSync(new URL("OperationsMainContent.tsx", import.meta.url), "utf8");
248
+ expect(content).toContain("data={summaryPopulation}");
248
249
  });
249
250
  });
@@ -0,0 +1,14 @@
1
+ export function overviewDurationHint(
2
+ view: "tasks" | "specs" | "prds",
3
+ locale: string,
4
+ taskHint: string,
5
+ ) {
6
+ if (view === "tasks") return taskHint;
7
+ if (view === "specs")
8
+ return locale === "pt-BR"
9
+ ? "Tempo decorrido observado das Runs-raiz por SPEC, sem duplicar filhos. SPECs diferentes podem compartilhar intervalos; a soma não é tempo global."
10
+ : "Observed root Run elapsed time per SPEC, without counting children twice. SPECs may share intervals; their sum is not global wall time.";
11
+ return locale === "pt-BR"
12
+ ? "Tempo de ciclo de vida (Runs-raiz, todas as fases)."
13
+ : "Lifecycle time (root Runs, all phases).";
14
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaip-ai/dashboard-traceability",
3
- "version": "4.5.0",
3
+ "version": "4.7.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaip-ai/dashboard-branding",
3
- "version": "4.5.0",
3
+ "version": "4.7.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaip-ai/dashboard-contracts",
3
- "version": "4.5.0",
3
+ "version": "4.7.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zaip-ai/dashboard-data-export",
3
- "version": "4.5.0",
3
+ "version": "4.7.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {