@zaip-ai/cli 1.0.8 → 1.3.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 (212) hide show
  1. package/README.md +1 -1
  2. package/dist/services/adapters.d.ts +1 -1
  3. package/dist/services/adapters.js +1 -1
  4. package/dist/services/agent-adapters.js +2 -2
  5. package/dist/services/agent-adapters.js.map +1 -1
  6. package/dist/services/agent-adapters.test.js +5 -0
  7. package/dist/services/agent-adapters.test.js.map +1 -1
  8. package/dist/services/logger.test.js +2 -2
  9. package/dist/services/runtime-template.test.js +6 -6
  10. package/dist/services/template-manifest.d.ts.map +1 -1
  11. package/dist/services/template-manifest.js +5 -0
  12. package/dist/services/template-manifest.js.map +1 -1
  13. package/package.json +1 -1
  14. package/templates/.agents/architecture/software-architecture.md +131 -0
  15. package/templates/.agents/branding/brandbook.docx +0 -0
  16. package/templates/.agents/branding/brandbook.md +60 -0
  17. package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -1
  18. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -1
  19. package/templates/.agents/dashboard/.tmp-run-list.json +254 -0
  20. package/templates/.agents/dashboard/.zaip-managed.json +252 -136
  21. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-Z60df2r-.js → CostCalculationGuidePage-DxR_pgSV.js} +1 -1
  22. package/templates/.agents/dashboard/apps/frontend/dist/assets/DashboardHelpDialog-4jZLTWE_.js +2156 -0
  23. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-Coc6pA-1.js → PricingSettingsDialog-CKcsqb-r.js} +1 -1
  24. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BomxqCBU.css +1 -0
  25. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-DmmJD2Th.js +3 -0
  26. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BwtitWa_.js +1 -0
  27. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-N5Csr0RP.js +68 -0
  28. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DFBuc_qp.js → icons-vendor-C0fj2uU9.js} +1 -1
  29. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-C4aIB1PV.js +2 -0
  30. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-CCQOHdVI.js → react-vendor-BEsJ-FYH.js} +1 -1
  31. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-pC2_0J8x.js → traceability-B6y6Gw12.js} +1 -1
  32. package/templates/.agents/dashboard/apps/frontend/dist/index.html +5 -5
  33. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  34. package/templates/.agents/dashboard/apps/frontend/src/App.tsx +204 -32
  35. package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +11 -11
  36. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +14 -7
  37. package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +4 -2
  38. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +3 -1
  39. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +14 -11
  40. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +19 -4
  41. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +24 -2
  42. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +22 -1
  43. package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +3 -1
  44. package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +36 -26
  45. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +2 -2
  46. package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +40 -6
  47. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +39 -1
  48. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +89 -23
  49. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +219 -29
  50. package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +61 -7
  51. package/templates/.agents/dashboard/apps/frontend/src/use-app-operations-pages.ts +3 -6
  52. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +2 -2
  53. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.ts +3 -4
  54. package/templates/.agents/dashboard/apps/frontend/vite.config.ts +4 -1
  55. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  56. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +89 -19
  57. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +31 -16
  58. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.test.ts +43 -14
  59. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.tsx +5 -5
  60. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.tsx +1 -1
  61. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +67 -42
  62. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +115 -39
  63. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +188 -38
  64. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +75 -17
  65. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +147 -58
  66. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor.css +5 -2
  67. package/templates/.agents/dashboard/modules/cost-monitor/src/react/index.ts +2 -2
  68. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +2 -1
  69. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +18 -7
  70. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +95 -9
  71. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +29 -17
  72. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test.ts +0 -24
  73. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.test.ts +225 -424
  74. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +24 -15
  75. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-terminal-day.test.ts +6 -1
  76. package/templates/.agents/dashboard/modules/cost-monitor/src/server/source-size-cost-server/build-cost-monitor-projection-agents.test.ts +31 -0
  77. package/templates/.agents/dashboard/modules/cost-monitor/src/server/source-size-cost-server/build-cost-summary-projection-duration.test.ts +414 -0
  78. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  79. package/templates/.agents/dashboard/modules/operations/src/contracts.ts +26 -23
  80. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +31 -11
  81. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +3 -1
  82. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +51 -21
  83. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +47 -5
  84. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageNavigation.tsx +1 -4
  85. package/templates/.agents/dashboard/modules/operations/src/react/PeriodSummaryTable.tsx +32 -10
  86. package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +9 -3
  87. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +13 -5
  88. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +12 -4
  89. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +1 -4
  90. package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.ts +1 -2
  91. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +385 -4
  92. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +481 -61
  93. package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +14 -1
  94. package/templates/.agents/dashboard/modules/operations/src/react/export/xlsx-runtime-e2e.test.ts +248 -0
  95. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +4 -4
  96. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +6 -4
  97. package/templates/.agents/dashboard/modules/operations/src/react/operations-global-filters.test.ts +4 -1
  98. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +1 -1
  99. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +1 -1
  100. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +46 -6
  101. package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +1 -4
  102. package/templates/.agents/dashboard/modules/operations/src/react/period-summary.test.ts +82 -6
  103. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +2 -1
  104. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.ts +1 -1
  105. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.test.ts +19 -7
  106. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.ts +4 -1
  107. package/templates/.agents/dashboard/modules/operations/src/server/quick-daily-operations-projection.ts +11 -5
  108. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  109. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  110. package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
  111. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  112. package/templates/.agents/dashboard/packages/contracts/src/index.ts +1 -0
  113. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  114. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +152 -149
  115. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs.metafile.json +7333 -0
  116. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +149 -146
  117. package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
  118. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-dashboard.mjs +15 -7
  119. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +44 -13
  120. package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +5 -2
  121. package/templates/.agents/dashboard/packages/local-runtime/scripts/source-size-runtime-scripts/sqlite-read-model-fixture.mjs +397 -0
  122. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +472 -145
  123. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-unix-launchers.mjs +15 -3
  124. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +129 -31
  125. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +153 -150
  126. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +6 -2
  127. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +3 -3
  128. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +55 -16
  129. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +23 -13
  130. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +19 -4
  131. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +7 -3
  132. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +132 -9
  133. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +126 -60
  134. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.ts +16 -2
  135. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +1861 -350
  136. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +1218 -352
  137. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +119 -42
  138. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +45 -20
  139. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  140. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  141. package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +7 -5
  142. package/templates/.agents/design/.zaip-managed.json +3 -3
  143. package/templates/.agents/design/apps/catalog/package.json +1 -1
  144. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  145. package/templates/.agents/growth/estrategia-bootstrap-90-dias.md +169 -0
  146. package/templates/.agents/growth/strategy.md +27 -0
  147. package/templates/.agents/marketing/estrategia-marketing-zaip-90-dias.md +197 -0
  148. package/templates/.agents/marketing/strategy.md +29 -0
  149. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  150. package/templates/.agents/requirements/comparative-audit.md +1 -1
  151. package/templates/.agents/requirements/context-engine.md +1 -1
  152. package/templates/.agents/requirements/cost-observability.md +1 -1
  153. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  154. package/templates/.agents/requirements/data-export.md +1 -1
  155. package/templates/.agents/requirements/design-system.md +1 -1
  156. package/templates/.agents/requirements/execution-engine.md +1 -1
  157. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  158. package/templates/.agents/requirements/model-orchestration.md +1 -1
  159. package/templates/.agents/requirements/public-distribution.md +1 -1
  160. package/templates/.agents/requirements/software-architecture.md +1 -1
  161. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  162. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  163. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  164. package/templates/.agents/runtime/VERSION +1 -1
  165. package/templates/.agents/runtime/bin/zaip.mjs +30 -29
  166. package/templates/.agents/runtime/checksums.sha256 +6 -6
  167. package/templates/.agents/runtime/manifest.json +1 -1
  168. package/templates/.agents/runtime/pnpm-lock.sha256 +1 -1
  169. package/templates/.agents/runtime/provenance.json +5 -5
  170. package/templates/.agents/runtime/sbom.cdx.json +3 -3
  171. package/templates/.agents/sales/playbook.md +32 -0
  172. package/templates/.agents/sales/roteiro-comercial-zaip.md +252 -0
  173. package/templates/.agents/skills/zaip-aios/SKILL.md +1 -1
  174. package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +9 -2
  175. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-framework.md +39 -0
  176. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +1 -1
  177. package/templates/.agents/skills/zaip-skill-enforce-architecture/SKILL.md +2 -0
  178. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +6 -0
  179. package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +6 -0
  180. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +39 -82
  181. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +13 -8
  182. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +44 -14
  183. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +19 -9
  184. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +29 -5
  185. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/source-size-telemetry/model-identity-reconciliation.mjs +77 -0
  186. package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +6 -0
  187. package/templates/.agents/skills/zaip-skill-sqlite-read-model/scripts/ensure-node.mjs +28 -5
  188. package/templates/.agents/zaip-aios/INDEX.md +10 -0
  189. package/templates/.agents/zaip-aios/README.md +2 -1
  190. package/templates/.agents/zaip-aios/VERSION +1 -1
  191. package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +76 -0
  192. package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +72 -0
  193. package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +330 -0
  194. package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +52 -0
  195. package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +69 -0
  196. package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +483 -0
  197. package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +85 -0
  198. package/templates/.agents/zaip-aios/guides/25-fontes-de-precos-openai.md +18 -0
  199. package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +44 -0
  200. package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +167 -0
  201. package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +144 -0
  202. package/templates/.agents/zaip-aios/guides/assets/diagrams/lifecycles-task-spec-prd.png +0 -0
  203. package/templates/.agents/zaip-aios/guides/assets/diagrams/prd-lifecycle.png +0 -0
  204. package/templates/.agents/zaip-aios/guides/assets/diagrams/spec-lifecycle.png +0 -0
  205. package/templates/.agents/zaip-aios/guides/assets/diagrams/task-lifecycle.png +0 -0
  206. package/templates/template-manifest.json +313 -177
  207. package/templates/.agents/dashboard/apps/frontend/dist/assets/DashboardHelpDialog-Cs6dzDmW.js +0 -1505
  208. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-QE1k9yZB.css +0 -1
  209. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-_Pf5DA_A.js +0 -3
  210. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BVlz3DLZ.js +0 -1
  211. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-Cf9ctPVt.js +0 -68
  212. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8A4DcNXM.js +0 -2
@@ -73,7 +73,13 @@ export interface OperationsBoardPage {
73
73
  stage: WorkBoardStage;
74
74
  offset: number;
75
75
  total: number;
76
- totals_by_kind: { all: number; task: number; prd: number; spec: number };
76
+ totals_by_kind: {
77
+ all: number;
78
+ task: number;
79
+ "standalone-task": number;
80
+ prd: number;
81
+ spec: number;
82
+ };
77
83
  prds: MacroProjection[];
78
84
  specs: MacroProjection[];
79
85
  tasks: DashboardTaskProjection[];
@@ -423,6 +429,21 @@ export class DashboardApiClient {
423
429
  );
424
430
  }
425
431
 
432
+ refreshProjection(
433
+ currency: "BRL" | "USD" = "BRL",
434
+ period?: { from: string | null; to: string | null },
435
+ ): Promise<{
436
+ operations: OperationsProjection;
437
+ costs: CostMonitorProjection;
438
+ dashboard?: { title: string; repository_name: string };
439
+ projection: { source_latest_at: string | null; served_at: string };
440
+ }> {
441
+ return this.post(
442
+ withPeriod(`${dashboardApiPaths.refreshProjection}?currency=${currency}`, period),
443
+ reconciliationRequestTimeoutMs,
444
+ );
445
+ }
446
+
426
447
  task(taskId: string): Promise<TaskDetailProjection> {
427
448
  return this.get(dashboardApiPaths.task(taskId));
428
449
  }
@@ -7,7 +7,9 @@ describe("overview status page loading", () => {
7
7
  it("requests a dedicated stage and kind page instead of reusing the mixed board page", () => {
8
8
  expect(source).toContain("const loadOverviewStatusPage");
9
9
  expect(source).toContain("api.operationsBoard(period, stage, offset, { kind })");
10
- expect(source).toContain("kind === \"task\" ? page.tasks : kind === \"spec\" ? page.specs : page.prds");
10
+ expect(source).toContain(
11
+ 'kind === "task" ? page.tasks : kind === "spec" ? page.specs : page.prds',
12
+ );
11
13
  });
12
14
 
13
15
  it("keeps a dedicated collection paginated by the loaded typed rows", () => {
@@ -20,33 +20,34 @@
20
20
 
21
21
  .project-settings-state-card {
22
22
  display: grid;
23
+ gap: 12px;
23
24
  justify-items: center;
24
- max-width: 580px;
25
+ max-width: 420px;
25
26
  border: 1px solid #dbe4ef;
26
27
  border-radius: 24px;
27
- padding: clamp(32px, 6vw, 56px);
28
+ padding: clamp(32px, 6vw, 48px);
28
29
  background: #fff;
29
30
  box-shadow: 0 18px 48px rgba(15, 23, 42, 0.08);
30
31
  text-align: center;
31
32
  }
32
33
 
33
34
  .project-settings-loader {
34
- width: 42px;
35
- height: 42px;
36
- margin-bottom: 20px;
37
- border: 4px solid rgba(0, 176, 240, 0.18);
35
+ width: 32px;
36
+ height: 32px;
37
+ border: 3px solid rgba(0, 176, 240, 0.18);
38
38
  border-top-color: #00b0f0;
39
39
  border-radius: 50%;
40
40
  animation: project-settings-spin 0.8s linear infinite;
41
41
  }
42
42
 
43
43
  .project-settings-state-card h1 {
44
- max-width: 16ch;
44
+ max-width: 18ch;
45
+ font-size: clamp(1.75rem, 5vw, 2.25rem);
45
46
  }
46
47
 
47
48
  .project-settings-state-card button {
48
49
  width: auto;
49
- margin-top: 26px;
50
+ margin-top: 12px;
50
51
  }
51
52
 
52
53
  .project-settings-header {
@@ -59,7 +60,7 @@
59
60
 
60
61
  .project-settings-header p,
61
62
  .project-settings-state p {
62
- margin: 0 0 8px;
63
+ margin: 0;
63
64
  color: #006b91;
64
65
  font-size: 0.75rem;
65
66
  font-weight: 700;
@@ -406,15 +407,18 @@
406
407
 
407
408
  .project-stack-versions > div {
408
409
  display: grid;
409
- grid-template-columns: minmax(0, 1fr);
410
+ grid-template-columns: repeat(2, minmax(0, 1fr));
410
411
  gap: 8px;
411
412
  }
412
413
 
413
414
  .project-stack-versions article {
414
415
  display: grid;
415
- grid-template-columns: minmax(150px, 1.1fr) minmax(92px, 0.55fr) auto minmax(0, 1fr);
416
- gap: 12px;
417
- align-items: center;
416
+ grid-template-columns: minmax(0, 1fr) auto;
417
+ grid-template-areas:
418
+ "identity badge"
419
+ "source source";
420
+ gap: 7px 12px;
421
+ align-items: start;
418
422
  min-width: 0;
419
423
  border: 1px solid #dbe4ef;
420
424
  border-radius: 12px;
@@ -422,13 +426,22 @@
422
426
  background: #f8fafc;
423
427
  }
424
428
 
425
- .project-stack-versions article strong {
429
+ .project-stack-version-identity {
430
+ display: flex;
431
+ grid-area: identity;
432
+ align-items: baseline;
433
+ gap: 8px;
434
+ min-width: 0;
435
+ }
436
+
437
+ .project-stack-version-identity strong {
426
438
  min-width: 0;
427
439
  color: #334155;
428
440
  font-size: 0.8rem;
429
441
  }
430
442
 
431
- .project-stack-versions article code {
443
+ .project-stack-version-identity code {
444
+ flex: none;
432
445
  min-width: 0;
433
446
  color: #0f172a;
434
447
  font-size: 0.8rem;
@@ -436,6 +449,7 @@
436
449
  }
437
450
 
438
451
  .project-stack-versions article small {
452
+ grid-area: source;
439
453
  min-width: 0;
440
454
  color: #64748b;
441
455
  font-size: 0.68rem;
@@ -444,6 +458,7 @@
444
458
  }
445
459
 
446
460
  .project-stack-versions article span {
461
+ grid-area: badge;
447
462
  width: fit-content;
448
463
  border-radius: 999px;
449
464
  padding: 3px 6px;
@@ -726,29 +741,24 @@
726
741
 
727
742
  .project-stack-versions article {
728
743
  grid-template-areas:
729
- "name badge"
730
- "version source";
744
+ "identity badge"
745
+ "source source";
731
746
  grid-template-columns: minmax(0, 1fr) auto;
732
747
  gap: 6px 10px;
733
748
  align-items: start;
734
749
  padding: 10px 12px;
735
750
  }
736
751
 
737
- .project-stack-versions article strong {
738
- grid-area: name;
739
- }
740
-
741
- .project-stack-versions article code {
742
- grid-area: version;
752
+ .project-stack-versions > div {
753
+ grid-template-columns: 1fr;
743
754
  }
744
755
 
745
756
  .project-stack-versions article span {
746
- grid-area: badge;
757
+ align-self: start;
747
758
  }
748
759
 
749
760
  .project-stack-versions article small {
750
- grid-area: source;
751
- text-align: right;
761
+ text-align: left;
752
762
  }
753
763
 
754
764
  .project-stack-table {
@@ -34,8 +34,8 @@ const config: ProjectConfigSettings = {
34
34
 
35
35
  describe("project settings form mapping", () => {
36
36
  it("renders a canonical framework SemVer as a short major.minor label", () => {
37
- expect(shortFrameworkVersion("1.0.8")).toBe("v1.0");
38
- expect(shortFrameworkVersion("v1.0.8")).toBe("v1.0");
37
+ expect(shortFrameworkVersion("1.3.0")).toBe("v1.3");
38
+ expect(shortFrameworkVersion("v1.3.0")).toBe("v1.3");
39
39
  expect(shortFrameworkVersion("1.0")).toBeNull();
40
40
  });
41
41
 
@@ -6,25 +6,59 @@ describe("snapshot update banner semantics", () => {
6
6
  it("delays the notice, then hides it on dismiss or completed initial load", () => {
7
7
  expect(snapshotNoticeDelayMs).toBe(1_500);
8
8
  // A fast first-fold load completes before the delay and never flashes.
9
- expect(shouldShowSnapshotNotice({ snapshotUpdating: true, initialDataPending: true, dismissed: false, delayElapsed: false })).toBe(false);
9
+ expect(
10
+ shouldShowSnapshotNotice({
11
+ snapshotUpdating: true,
12
+ initialDataPending: true,
13
+ dismissed: false,
14
+ delayElapsed: false,
15
+ }),
16
+ ).toBe(false);
10
17
  // A genuinely slow initial read receives the helpful stale-snapshot notice.
11
- expect(shouldShowSnapshotNotice({ snapshotUpdating: true, initialDataPending: true, dismissed: false, delayElapsed: true })).toBe(true);
12
- expect(shouldShowSnapshotNotice({ snapshotUpdating: true, initialDataPending: true, dismissed: true, delayElapsed: true })).toBe(false);
13
- expect(shouldShowSnapshotNotice({ snapshotUpdating: true, initialDataPending: false, dismissed: false, delayElapsed: true })).toBe(false);
18
+ expect(
19
+ shouldShowSnapshotNotice({
20
+ snapshotUpdating: true,
21
+ initialDataPending: true,
22
+ dismissed: false,
23
+ delayElapsed: true,
24
+ }),
25
+ ).toBe(true);
26
+ expect(
27
+ shouldShowSnapshotNotice({
28
+ snapshotUpdating: true,
29
+ initialDataPending: true,
30
+ dismissed: true,
31
+ delayElapsed: true,
32
+ }),
33
+ ).toBe(false);
34
+ expect(
35
+ shouldShowSnapshotNotice({
36
+ snapshotUpdating: true,
37
+ initialDataPending: false,
38
+ dismissed: false,
39
+ delayElapsed: true,
40
+ }),
41
+ ).toBe(false);
14
42
  });
15
43
 
16
44
  it("presents a stale local snapshot as neutral status and reserves alert red for errors", () => {
17
45
  const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
18
46
  const boundary = readFileSync(new URL("./AppLoadingBoundary.tsx", import.meta.url), "utf8");
19
47
  const styles = readFileSync(new URL("./styles.css", import.meta.url), "utf8");
20
- const snapshot = app.slice(app.indexOf("const initialDataPending"), app.indexOf("const renderedOperations"));
48
+ const snapshot = app.slice(
49
+ app.indexOf("const initialDataPending"),
50
+ app.indexOf("const renderedOperations"),
51
+ );
52
+ const compactSnapshot = snapshot.replace(/\s+/g, " ");
21
53
  const error = app.slice(app.indexOf("{error ?"), app.indexOf("{/* Cost Monitor boundary"));
22
54
 
23
55
  expect(snapshot).toContain('className="app-notice app-snapshot-status" role="status"');
24
56
  expect(snapshot).toContain('aria-live="polite"');
25
57
  expect(snapshot).toContain("shouldShowSnapshotNotice({");
26
58
  expect(snapshot).toContain("delayElapsed: snapshotNoticeDelayElapsed,");
27
- expect(snapshot).toContain("window.setTimeout(() => setSnapshotNoticeDelayElapsed(true), snapshotNoticeDelayMs)");
59
+ expect(compactSnapshot).toMatch(
60
+ /window\.setTimeout\(\s*\(\) => setSnapshotNoticeDelayElapsed\(true\),\s*snapshotNoticeDelayMs,?\s*\)/,
61
+ );
28
62
  expect(snapshot).toContain("return () => window.clearTimeout(timeout);");
29
63
  expect(snapshot).toContain("setSnapshotNoticeDismissed(true)");
30
64
  expect(snapshot).toContain('"Fechar aviso de atualização do snapshot"');
@@ -2,6 +2,7 @@ import { readFileSync } from "node:fs";
2
2
  import { describe, expect, it } from "vitest";
3
3
  import { isCurrentDashboardRequest, mergeBoardPages, needsAtomicCostSnapshot } from "./App.js";
4
4
  import { loadAtomicCostSnapshot } from "./snapshot-coherence.js";
5
+ import { projectionRefreshDebounceMs, shouldRefreshVisibleProjection } from "./use-app-effects.js";
5
6
 
6
7
  describe("atomic Cost snapshot loading", () => {
7
8
  it("keeps Operations, Cost, and cards on one source generation while the source moves", async () => {
@@ -49,7 +50,10 @@ describe("atomic Cost snapshot loading", () => {
49
50
 
50
51
  it("opens the global overlay while the Cost page loads a selected group", () => {
51
52
  const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
52
- const globalGate = app.slice(app.indexOf("const globalLoadingPending"), app.indexOf("const renderedOperations"));
53
+ const globalGate = app.slice(
54
+ app.indexOf("const globalLoadingPending"),
55
+ app.indexOf("const renderedOperations"),
56
+ );
53
57
  expect(app).toContain("const [costSurfaceLoading, setCostSurfaceLoading] = useState(false);");
54
58
  expect(globalGate).toContain("costSurfaceLoading");
55
59
  expect(globalGate).toContain('loadingArea !== "costs"');
@@ -94,6 +98,40 @@ describe("atomic Cost snapshot loading", () => {
94
98
  expect(app).toContain('setLoadingArea("costs")');
95
99
  });
96
100
 
101
+ it("coalesces focus and visibility events into one non-reconciling projection refresh", () => {
102
+ expect(
103
+ shouldRefreshVisibleProjection({
104
+ visibilityState: "visible",
105
+ inFlight: false,
106
+ lastRefreshAt: 0,
107
+ now: projectionRefreshDebounceMs,
108
+ }),
109
+ ).toBe(true);
110
+ expect(
111
+ shouldRefreshVisibleProjection({
112
+ visibilityState: "visible",
113
+ inFlight: false,
114
+ lastRefreshAt: projectionRefreshDebounceMs,
115
+ now: projectionRefreshDebounceMs + 1,
116
+ }),
117
+ ).toBe(false);
118
+ expect(
119
+ shouldRefreshVisibleProjection({
120
+ visibilityState: "hidden",
121
+ inFlight: false,
122
+ lastRefreshAt: 0,
123
+ now: projectionRefreshDebounceMs * 2,
124
+ }),
125
+ ).toBe(false);
126
+ const effects = readFileSync(new URL("./use-app-effects.ts", import.meta.url), "utf8");
127
+ expect(effects).toContain('window.addEventListener("focus", refreshVisibleProjection)');
128
+ expect(effects).toContain(
129
+ 'document.addEventListener("visibilitychange", refreshVisibleProjection)',
130
+ );
131
+ expect(effects).not.toContain("setInterval");
132
+ expect(effects).toContain("void refresh(false, false, true)");
133
+ });
134
+
97
135
  it("removes the global Cost detail request and keeps stale request guards", () => {
98
136
  const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
99
137
  const costPage = readFileSync(
@@ -1,5 +1,5 @@
1
- import { describe, expect, it } from "vitest";
2
1
  import { CostRunsTable, matchesCostRunFilter } from "@zaip-ai/dashboard-cost-monitor/react";
2
+ import { describe, expect, it } from "vitest";
3
3
  import {
4
4
  adaptSqliteCompactLifecyclePage,
5
5
  adaptSqliteCostRun,
@@ -19,7 +19,16 @@ describe("daily Cost Monitor continuous pagination", () => {
19
19
  total_count: 35,
20
20
  has_more: true,
21
21
  rows: [{ period_key: "2026-08-17" }, { period_key: "2026-07-19" }],
22
- totals: { task_count: 916, prd_count: 13, spec_count: 59, total_run_count: 238, total_duration: 619_920_000, total_tokens: 7_300_000_000, total_cost_usd: 8_731.92, total_cost_brl: 47_589 },
22
+ totals: {
23
+ task_count: 916,
24
+ prd_count: 13,
25
+ spec_count: 59,
26
+ total_run_count: 238,
27
+ total_duration: 619_920_000,
28
+ total_tokens: 7_300_000_000,
29
+ total_cost_usd: 8_731.92,
30
+ total_cost_brl: 47_589,
31
+ },
23
32
  };
24
33
  }
25
34
  return {
@@ -27,12 +36,35 @@ describe("daily Cost Monitor continuous pagination", () => {
27
36
  limit: 30,
28
37
  total_count: 35,
29
38
  has_more: false,
30
- rows: [{ period_key: "2026-07-18", task_count: 2, total_tokens: 10 }, { period_key: "2026-07-14", task_count: 2, total_tokens: 10 }],
31
- totals: { task_count: 916, prd_count: 13, spec_count: 59, total_run_count: 238, total_duration: 619_920_000, total_tokens: 7_300_000_000, total_cost_usd: 8_731.92, total_cost_brl: 47_589 },
39
+ rows: [
40
+ { period_key: "2026-07-18", task_count: 2, total_tokens: 10 },
41
+ { period_key: "2026-07-14", task_count: 2, total_tokens: 10 },
42
+ ],
43
+ totals: {
44
+ task_count: 916,
45
+ prd_count: 13,
46
+ spec_count: 59,
47
+ total_run_count: 238,
48
+ total_duration: 619_920_000,
49
+ total_tokens: 7_300_000_000,
50
+ total_cost_usd: 8_731.92,
51
+ total_cost_brl: 47_589,
52
+ },
32
53
  };
33
54
  },
34
55
  };
35
- const filters = { query: "", provider: "", model: "", agent: "", phase: "", status: "", origin: "", workType: "", priority: "", risk: "" } as never;
56
+ const filters = {
57
+ query: "",
58
+ provider: "",
59
+ model: "",
60
+ agent: "",
61
+ phase: "",
62
+ status: "",
63
+ origin: "",
64
+ workType: "",
65
+ priority: "",
66
+ risk: "",
67
+ } as never;
36
68
  const firstPage = await loadSqliteCostGroupPage(api as never, {
37
69
  view: "daily",
38
70
  from: "2026-07-14",
@@ -51,8 +83,16 @@ describe("daily Cost Monitor continuous pagination", () => {
51
83
  });
52
84
 
53
85
  expect(calls).toEqual([
54
- { view: "cost_monitor_daily", range: { from: "2026-07-14", to: "2026-08-17" }, page: { offset: 0, limit: 30 } },
55
- { view: "cost_monitor_daily", range: { from: "2026-07-14", to: "2026-08-17" }, page: { offset: 30, limit: 30 } },
86
+ {
87
+ view: "cost_monitor_daily",
88
+ range: { from: "2026-07-14", to: "2026-08-17" },
89
+ page: { offset: 0, limit: 30 },
90
+ },
91
+ {
92
+ view: "cost_monitor_daily",
93
+ range: { from: "2026-07-14", to: "2026-08-17" },
94
+ page: { offset: 30, limit: 30 },
95
+ },
56
96
  ]);
57
97
  expect(firstPage).toMatchObject({
58
98
  offset: 0,
@@ -60,7 +100,13 @@ describe("daily Cost Monitor continuous pagination", () => {
60
100
  total_count: 35,
61
101
  has_more: true,
62
102
  rows: [{ key: "2026-08-17" }, { key: "2026-07-19" }],
63
- totals: { task_count: 916, prd_count: 13, spec_count: 59, total_tokens: 7_300_000_000, estimated_brl: 47_589 },
103
+ totals: {
104
+ task_count: 916,
105
+ prd_count: 13,
106
+ spec_count: 59,
107
+ total_tokens: 7_300_000_000,
108
+ estimated_brl: 47_589,
109
+ },
64
110
  });
65
111
  expect(secondPage).toMatchObject({
66
112
  offset: 30,
@@ -102,10 +148,12 @@ describe("adaptSqliteCostRun", () => {
102
148
  currency: "BRL",
103
149
  locale: "pt-BR",
104
150
  });
105
- const multiplier = (table.props.columns as Array<{
106
- key: string;
107
- render: (row: typeof run) => unknown;
108
- }>).find((column) => column.key === "contextMultiplier");
151
+ const multiplier = (
152
+ table.props.columns as Array<{
153
+ key: string;
154
+ render: (row: typeof run) => unknown;
155
+ }>
156
+ ).find((column) => column.key === "contextMultiplier");
109
157
  expect(multiplier?.render(run)).toBe("Indisponível");
110
158
  expect(
111
159
  matchesCostRunFilter(run, {
@@ -165,22 +213,40 @@ describe("adaptSqliteCompactLifecyclePage", () => {
165
213
  limit: 50,
166
214
  total_count: 270,
167
215
  has_more: true,
168
- totals: { entity_count: 270, invocation_count: 270, total_duration: 270_000, total_tokens: 540, total_cost_usd: 270, total_cost_brl: 1_350 },
169
- rows: Array.from({ length: 50 }, (_, index) => ({ task_id: `TASK-${index}`, invocation_count: 1, total_duration: 1_000, total_tokens: 2, total_cost_brl: 5 })),
216
+ totals: {
217
+ entity_count: 270,
218
+ invocation_count: 270,
219
+ total_duration: 270_000,
220
+ total_tokens: 540,
221
+ total_cost_usd: 270,
222
+ total_cost_brl: 1_350,
223
+ },
224
+ rows: Array.from({ length: 50 }, (_, index) => ({
225
+ task_id: `TASK-${index}`,
226
+ invocation_count: 1,
227
+ total_duration: 1_000,
228
+ total_tokens: 2,
229
+ total_cost_brl: 5,
230
+ })),
170
231
  } as const;
171
- for (const [kind, view] of [["tasks", "cost_monitor_tasks"], ["specs", "cost_monitor_specs"], ["prds", "cost_monitor_prds"], ["conversations", "cost_monitor_conversations"]] as const) {
232
+ for (const [kind, view] of [
233
+ ["tasks", "cost_monitor_tasks"],
234
+ ["specs", "cost_monitor_specs"],
235
+ ["prds", "cost_monitor_prds"],
236
+ ["conversations", "cost_monitor_conversations"],
237
+ ] as const) {
172
238
  const page = adaptSqliteCompactLifecyclePage(kind, { ...sqlitePage, view });
173
239
  expect(page.rows).toHaveLength(50);
174
240
  expect(page.offset).toBe(50);
175
241
  expect(page.subtotal).toEqual({
176
- entity_count: 270,
177
- run_count: { known_sum: 270, unknown: 0, complete: true, coverage_ratio: 1 },
178
- metrics: {
179
- duration: { known_sum: 270_000, unknown: 0, complete: true, coverage_ratio: 1 },
180
- total_tokens: { known_sum: 540, unknown: 0, complete: true, coverage_ratio: 1 },
181
- cost_brl: { known_sum: 1_350, unknown: 0, complete: true, coverage_ratio: 1 },
182
- cost_usd: { known_sum: 270, unknown: 0, complete: true, coverage_ratio: 1 },
183
- },
242
+ entity_count: 270,
243
+ run_count: { known_sum: 270, unknown: 0, complete: true, coverage_ratio: 1 },
244
+ metrics: {
245
+ duration: { known_sum: 270_000, unknown: 0, complete: true, coverage_ratio: 1 },
246
+ total_tokens: { known_sum: 540, unknown: 0, complete: true, coverage_ratio: 1 },
247
+ cost_brl: { known_sum: 1_350, unknown: 0, complete: true, coverage_ratio: 1 },
248
+ cost_usd: { known_sum: 270, unknown: 0, complete: true, coverage_ratio: 1 },
249
+ },
184
250
  });
185
251
  }
186
252
  });