@zaip-ai/cli 1.3.0 → 1.3.1

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 (258) hide show
  1. package/README.md +1 -1
  2. package/dist/services/agent-adapters.js +1 -1
  3. package/dist/services/agent-adapters.js.map +1 -1
  4. package/dist/services/agent-adapters.test.js +2 -1
  5. package/dist/services/agent-adapters.test.js.map +1 -1
  6. package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
  7. package/dist/services/codex-pre-tool-hook-template.js +89 -7
  8. package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
  9. package/dist/services/codex-rules.d.ts +1 -1
  10. package/dist/services/codex-rules.d.ts.map +1 -1
  11. package/dist/services/codex-rules.js +7 -0
  12. package/dist/services/codex-rules.js.map +1 -1
  13. package/dist/services/install-agents-template.d.ts.map +1 -1
  14. package/dist/services/install-agents-template.js +1 -0
  15. package/dist/services/install-agents-template.js.map +1 -1
  16. package/dist/services/runtime-template.test.js +31 -7
  17. package/dist/services/runtime-template.test.js.map +1 -1
  18. package/dist/services/template-manifest.d.ts.map +1 -1
  19. package/dist/services/template-manifest.js +7 -3
  20. package/dist/services/template-manifest.js.map +1 -1
  21. package/package.json +1 -1
  22. package/templates/.agents/config/agents/catalog.yaml +7 -7
  23. package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +2 -2
  24. package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +2 -2
  25. package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +8 -8
  26. package/templates/.agents/dashboard/.zaip-managed.json +373 -205
  27. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-DxR_pgSV.js → CostCalculationGuidePage-ovxurkIk.js} +1 -1
  28. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-4jZLTWE_.js → DashboardHelpDialog-BgVgrfhQ.js} +240 -86
  29. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-CKcsqb-r.js → PricingSettingsDialog-vSvvOHQp.js} +1 -1
  30. package/templates/.agents/dashboard/apps/frontend/dist/assets/{ProjectSettingsPage-DmmJD2Th.js → ProjectSettingsPage-zH758vfs.js} +1 -1
  31. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-DLn-Mz2M.js +1 -0
  32. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-CaKwQP43.css → TraceabilityWorkspace-DvvavDLY.css} +1 -1
  33. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DKwP1stV.js +68 -0
  34. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-PoJA2PI1.css +1 -0
  35. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-C0fj2uU9.js → icons-vendor-B_lDDHn1.js} +1 -1
  36. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-B31GMG5O.css +1 -0
  37. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-CZQlsLV9.js +2 -0
  38. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-BEsJ-FYH.js → react-vendor-B3TJrD4O.js} +1 -1
  39. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-B6y6Gw12.js → traceability-7f1j5wx3.js} +1 -1
  40. package/templates/.agents/dashboard/apps/frontend/dist/index.html +7 -7
  41. package/templates/.agents/dashboard/apps/frontend/playwright.dom.config.ts +32 -0
  42. package/templates/.agents/dashboard/apps/frontend/src/App.tsx +132 -245
  43. package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +0 -21
  44. package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +9 -0
  45. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.dom.e2e.ts +56 -0
  46. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +18 -1
  47. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +75 -8
  48. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +25 -1
  49. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +7 -9
  50. package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +4 -4
  51. package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +1 -1
  52. package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +7 -0
  53. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +20 -8
  54. package/templates/.agents/dashboard/apps/frontend/src/sqlite-page-export.test.ts +32 -0
  55. package/templates/.agents/dashboard/apps/frontend/src/sqlite-page-export.ts +21 -0
  56. package/templates/.agents/dashboard/apps/frontend/src/styles.css +19 -0
  57. package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.test.ts +32 -0
  58. package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.ts +36 -0
  59. package/templates/.agents/dashboard/apps/frontend/src/traceability-workspace.css +6 -2
  60. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +48 -0
  61. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +31 -27
  62. package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +7 -1
  63. package/templates/.agents/dashboard/apps/frontend/src/use-app-work-list-page.test.ts +163 -0
  64. package/templates/.agents/dashboard/apps/frontend/src/use-app-work-list-page.ts +136 -0
  65. package/templates/.agents/dashboard/apps/frontend/src/use-operations-detail-export.ts +76 -0
  66. package/templates/.agents/dashboard/apps/frontend/src/work-list-load-dedup.test.ts +23 -0
  67. package/templates/.agents/dashboard/apps/frontend/src/work-list-load-dedup.ts +27 -0
  68. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +38 -14
  69. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionPanel.tsx +60 -0
  70. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionTable.tsx +191 -0
  71. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.loading.test.ts +14 -0
  72. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.run-page.test.ts +18 -0
  73. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.tsx +18 -3
  74. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +8 -2
  75. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorLoadErrors.tsx +35 -0
  76. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +47 -1
  77. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +50 -58
  78. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableLoading.test.ts +132 -0
  79. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableLoading.tsx +70 -0
  80. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +128 -138
  81. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +17 -67
  82. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-copy.ts +2 -0
  83. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-views.ts +3 -1
  84. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-page-range.ts +35 -0
  85. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +16 -4
  86. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.test.ts +37 -2
  87. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +44 -8
  88. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +6 -1
  89. package/templates/.agents/dashboard/modules/operations/src/contracts.ts +20 -3
  90. package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.test.ts +54 -0
  91. package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.tsx +247 -0
  92. package/templates/.agents/dashboard/modules/operations/src/react/OperationsMainContent.tsx +39 -13
  93. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +107 -2
  94. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.macro-metrics.test.ts +55 -0
  95. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +20 -28
  96. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +162 -165
  97. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewTopPanel.tsx +127 -0
  98. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +13 -46
  99. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +3 -0
  100. package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.test.tsx +43 -0
  101. package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.tsx +181 -0
  102. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +4 -2
  103. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +13 -0
  104. package/templates/.agents/dashboard/modules/operations/src/react/developer-identities.test.ts +18 -0
  105. package/templates/.agents/dashboard/modules/operations/src/react/developer-identities.ts +30 -0
  106. package/templates/.agents/dashboard/modules/operations/src/react/execution-metrics.ts +1 -0
  107. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +8 -0
  108. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +3 -0
  109. package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +14 -5
  110. package/templates/.agents/dashboard/modules/operations/src/react/index.ts +1 -0
  111. package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +4 -3
  112. package/templates/.agents/dashboard/modules/operations/src/react/operations-date-filters.css +1 -1
  113. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +21 -11
  114. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.css +4 -0
  115. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +8 -1
  116. package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +1 -0
  117. package/templates/.agents/dashboard/modules/operations/src/react/period-summary.ts +1 -0
  118. package/templates/.agents/dashboard/modules/operations/src/server/metric-coverage.ts +1 -0
  119. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +527 -335
  120. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +501 -309
  121. package/templates/.agents/dashboard/packages/local-runtime/gitignore.template +2 -0
  122. package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +3 -1
  123. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +3 -3
  124. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +25 -15
  125. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +527 -335
  126. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +34 -0
  127. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +15 -8
  128. package/templates/.agents/dashboard/packages/local-runtime/src/server-classification-page.test.ts +87 -0
  129. package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.test.ts +44 -0
  130. package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.ts +125 -0
  131. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +66 -0
  132. package/templates/.agents/dashboard/packages/local-runtime/src/server-request-authority.test.ts +61 -0
  133. package/templates/.agents/dashboard/packages/local-runtime/src/server-request-authority.ts +18 -0
  134. package/templates/.agents/dashboard/packages/local-runtime/src/server-run-projections.test.ts +42 -0
  135. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +97 -0
  136. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +3 -1
  137. package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.ts +91 -0
  138. package/templates/.agents/dashboard/packages/local-runtime/src/server.test-fixtures.ts +36 -0
  139. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +98 -123
  140. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +111 -135
  141. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-artifact-counts.ts +28 -0
  142. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.test.ts +63 -0
  143. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.ts +109 -0
  144. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-aggregates.ts +497 -0
  145. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-fast-page-parity.test-support.ts +65 -0
  146. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-page.test.ts +176 -0
  147. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-page.ts +119 -0
  148. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.ts +41 -0
  149. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.test.ts +16 -0
  150. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.ts +29 -0
  151. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-cache.ts +355 -0
  152. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-persistence.ts +121 -0
  153. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-timing.ts +27 -0
  154. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-projection.ts +15 -0
  155. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.test.ts +223 -0
  156. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.ts +304 -0
  157. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-cache.test-support.ts +23 -0
  158. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-first-fold-types.ts +89 -0
  159. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-fixture.ts +227 -0
  160. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider.test.ts +691 -0
  161. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +81 -0
  162. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +440 -863
  163. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +1120 -1086
  164. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-cache.ts +129 -0
  165. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-install.test.ts +26 -0
  166. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-install.ts +28 -0
  167. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-seed.test.ts +116 -0
  168. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +146 -0
  169. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.test.mjs +165 -0
  170. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-refresh.mjs +140 -0
  171. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +188 -299
  172. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +51 -70
  173. package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +5 -2
  174. package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -1
  175. package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-loading.spec.ts +142 -0
  176. package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-pagination.spec.ts +232 -0
  177. package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +743 -0
  178. package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +183 -210
  179. package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
  180. package/templates/.agents/requirements/autonomous-assurance.md +6 -6
  181. package/templates/.agents/requirements/comparative-audit.md +1 -1
  182. package/templates/.agents/requirements/context-engine.md +1 -1
  183. package/templates/.agents/requirements/cost-observability.md +1 -1
  184. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  185. package/templates/.agents/requirements/data-export.md +1 -1
  186. package/templates/.agents/requirements/design-system.md +1 -1
  187. package/templates/.agents/requirements/execution-engine.md +3 -3
  188. package/templates/.agents/requirements/kanban-dashboard.md +10 -2
  189. package/templates/.agents/requirements/model-orchestration.md +1 -1
  190. package/templates/.agents/requirements/public-distribution.md +1 -1
  191. package/templates/.agents/requirements/software-architecture.md +1 -1
  192. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  193. package/templates/.agents/requirements/work-lifecycle.md +4 -4
  194. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  195. package/templates/.agents/rules/dashboard-ui-consistency.md +14 -0
  196. package/templates/.agents/rules/frontend-lite.md +4 -4
  197. package/templates/.agents/rules/run-lifecycle-closure.md +4 -4
  198. package/templates/.agents/runtime/bin/zaip.mjs +1137 -1037
  199. package/templates/.agents/runtime/checksums.sha256 +2 -2
  200. package/templates/.agents/runtime/provenance.json +2 -2
  201. package/templates/.agents/skills/criar-pasta-obsidian/scripts/generate-obsidian-vault.test.mjs +20 -16
  202. package/templates/.agents/skills/zaip-skill-agent-catalog/SKILL.md +22 -0
  203. package/templates/.agents/skills/zaip-skill-agent-catalog/agents/openai.yaml +4 -0
  204. package/templates/.agents/skills/zaip-skill-author-skills/SKILL.md +3 -2
  205. package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +49 -0
  206. package/templates/.agents/skills/zaip-skill-author-skills/scripts/author-skill-scripts.test.mjs +27 -0
  207. package/templates/.agents/skills/zaip-skill-author-skills/scripts/run-skill-tests.mjs +37 -0
  208. package/templates/.agents/skills/zaip-skill-backend/SKILL.md +1 -0
  209. package/templates/.agents/skills/zaip-skill-change/SKILL.md +1 -1
  210. package/templates/.agents/skills/zaip-skill-change/references/observable-evidence.md +83 -0
  211. package/templates/.agents/skills/zaip-skill-dashboard-diagnostics/SKILL.md +22 -0
  212. package/templates/.agents/skills/zaip-skill-dashboard-diagnostics/agents/openai.yaml +4 -0
  213. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
  214. package/templates/.agents/skills/zaip-skill-frontend/SKILL.md +4 -3
  215. package/templates/.agents/skills/zaip-skill-frontend/agents/openai.yaml +2 -2
  216. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +10 -10
  217. package/templates/.agents/skills/zaip-skill-lifecycle-closure/SKILL.md +27 -0
  218. package/templates/.agents/skills/zaip-skill-lifecycle-closure/agents/openai.yaml +4 -0
  219. package/templates/.agents/skills/zaip-skill-prd/SKILL.md +4 -0
  220. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +72 -22
  221. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-explicit-recovery.mjs +223 -0
  222. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +42 -1
  223. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +101 -0
  224. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +53 -0
  225. package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +20 -0
  226. package/templates/.agents/skills/zaip-skill-release-qualification/agents/openai.yaml +4 -0
  227. package/templates/.agents/skills/zaip-skill-review/SKILL.md +5 -0
  228. package/templates/.agents/skills/zaip-skill-rules/SKILL.md +1 -1
  229. package/templates/.agents/skills/zaip-skill-spec/SKILL.md +4 -0
  230. package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +22 -90
  231. package/templates/.agents/zaip-aios/INDEX.md +57 -32
  232. package/templates/.agents/zaip-aios/README.md +22 -12
  233. package/templates/.agents/zaip-aios/guides/02-requirements.md +5 -0
  234. package/templates/.agents/zaip-aios/guides/06-execucao.md +13 -4
  235. package/templates/.agents/zaip-aios/guides/07-revisao-e-validacao.md +7 -0
  236. package/templates/.agents/zaip-aios/guides/10-seguranca.md +23 -0
  237. package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +6 -6
  238. package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +3 -0
  239. package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +12 -3
  240. package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +5 -5
  241. package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +23 -0
  242. package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +44 -8
  243. package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +8 -14
  244. package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +5 -0
  245. package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +6 -6
  246. package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +8 -8
  247. package/templates/.agents/zaip-aios/guides/25-fontes-de-precos-openai.md +3 -2
  248. package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +77 -10
  249. package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +8 -3
  250. package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +5 -0
  251. package/templates/template-manifest.json +555 -170
  252. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BwtitWa_.js +0 -1
  253. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-BZ5WdaMN.css +0 -1
  254. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-N5Csr0RP.js +0 -68
  255. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-C4aIB1PV.js +0 -2
  256. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DK_enB5Z.css +0 -1
  257. package/templates/.agents/dashboard/apps/frontend/src/use-idle-cost-prefetch.ts +0 -45
  258. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs.metafile.json +0 -7333
@@ -0,0 +1,27 @@
1
+ import type { OperationsPageFilters } from "./dashboard-api.js";
2
+
3
+ export type WorkListLoadIntent = "explicit" | "filter-hydration";
4
+
5
+ export function workListLoadKey(
6
+ filters: OperationsPageFilters,
7
+ period: { from: string | null; to: string | null },
8
+ ): string {
9
+ return JSON.stringify([
10
+ filters.query,
11
+ filters.status,
12
+ filters.risk,
13
+ filters.origin ?? "",
14
+ filters.kind ?? "",
15
+ period.from ?? "",
16
+ period.to ?? "",
17
+ ]);
18
+ }
19
+
20
+ /** Explicit type/reentry/page loads must remain actionable; delayed hydration is idempotent. */
21
+ export function shouldStartWorkListLoad(
22
+ intent: WorkListLoadIntent,
23
+ key: string,
24
+ knownKey: string | null,
25
+ ): boolean {
26
+ return intent === "explicit" || key !== knownKey;
27
+ }
@@ -1,9 +1,5 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import {
3
- collectWorkListPages,
4
- normalizeWorkListFilters,
5
- selectedWorkListKinds,
6
- } from "./work-list-pagination.js";
1
+ import { describe, expect, it } from "vitest";
2
+ import { normalizeWorkListFilters, selectedWorkListKinds } from "./work-list-pagination.js";
7
3
 
8
4
  describe("Trabalho (Lista) canonical pagination", () => {
9
5
  it("keeps a server-selected PRD/SPEC kind instead of refetching every kind", () => {
@@ -33,14 +29,42 @@ describe("Trabalho (Lista) canonical pagination", () => {
33
29
  expect(kanban).toEqual({ query: "kanban", status: "ready", risk: "", kind: "" });
34
30
  });
35
31
 
36
- it("continues from the returned offset until the canonical total is complete", async () => {
37
- const loadPage = vi
38
- .fn()
39
- .mockResolvedValueOnce({ total: 59, received: 50, value: "first" })
40
- .mockResolvedValueOnce({ total: 59, received: 9, value: "second" });
32
+ it("retains the active origin for the paginated List request and export", async () => {
33
+ const selected = normalizeWorkListFilters(
34
+ { query: "", status: "", risk: "", origin: "standalone", kind: "standalone-task" },
35
+ { query: "", status: "", risk: "", origin: "", kind: "" },
36
+ );
37
+ const loader = await import("node:fs/promises").then(({ readFile }) =>
38
+ readFile(new URL("./use-app-work-list-page.ts", import.meta.url), "utf8"),
39
+ );
40
+ const exportSource = await import("node:fs/promises").then(({ readFile }) =>
41
+ readFile(new URL("./use-operations-detail-export.ts", import.meta.url), "utf8"),
42
+ );
43
+
44
+ expect(selected.origin).toBe("standalone");
45
+ expect(loader).toContain(
46
+ "...(normalizedFilters.origin ? { origin: normalizedFilters.origin } : {})",
47
+ );
48
+ expect(loader).toContain("{ status: normalizedFilters.status }");
49
+ expect(exportSource).toContain("...(filters.origin ? { origin: filters.origin } : {})");
50
+ expect(exportSource).toContain("...(filters.status ? { status: filters.status } : {})");
51
+ });
52
+
53
+ it("uses one bounded SQLite page for visual List loading", async () => {
54
+ const loader = await import("node:fs/promises").then(({ readFile }) =>
55
+ readFile(new URL("./use-app-work-list-page.ts", import.meta.url), "utf8"),
56
+ );
57
+ const list = await import("node:fs/promises").then(({ readFile }) =>
58
+ readFile(
59
+ new URL("../../../modules/operations/src/react/PagedWorkList.tsx", import.meta.url),
60
+ "utf8",
61
+ ),
62
+ );
41
63
 
42
- await expect(collectWorkListPages(loadPage)).resolves.toEqual(["first", "second"]);
43
- expect(loadPage).toHaveBeenNthCalledWith(1, 0);
44
- expect(loadPage).toHaveBeenNthCalledWith(2, 50);
64
+ expect(loader).toContain('"operations_work_list"');
65
+ expect(loader).toContain("limit: 10");
66
+ expect(loader).not.toContain("collectWorkListPages");
67
+ expect(loader).not.toContain("Promise.all(");
68
+ expect(list).toContain("row.kind ?? row.entity_kind");
45
69
  });
46
70
  });
@@ -0,0 +1,60 @@
1
+ import { useEffect, useState } from "react";
2
+ import { type CostDeveloperAttributionRow, CostDeveloperAttributionTable } from "./CostTables.js";
3
+ import type { CostLocale } from "./cost-monitor-copy.js";
4
+
5
+ /** Cost-specific rendering of the factual developer aggregate endpoint. */
6
+ export function CostDeveloperAttributionPanel({
7
+ from,
8
+ to,
9
+ locale,
10
+ }: {
11
+ from?: string;
12
+ to?: string;
13
+ locale: CostLocale;
14
+ }) {
15
+ const [state, setState] = useState<{
16
+ loading: boolean;
17
+ error: string | null;
18
+ rows: readonly CostDeveloperAttributionRow[];
19
+ }>({ loading: true, error: null, rows: [] });
20
+ useEffect(() => {
21
+ const controller = new AbortController();
22
+ const params = new URLSearchParams();
23
+ if (from) params.set("from", from);
24
+ if (to) params.set("to", to);
25
+ setState((previous) => ({ ...previous, loading: true, error: null }));
26
+ fetch(`/api/v2/developers${params.size === 0 ? "" : `?${params}`}`, {
27
+ signal: controller.signal,
28
+ })
29
+ .then(async (response) => {
30
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
31
+ return response.json() as Promise<{ rows?: CostDeveloperAttributionRow[] }>;
32
+ })
33
+ .then((payload) => setState({ loading: false, error: null, rows: payload.rows ?? [] }))
34
+ .catch((error: unknown) => {
35
+ if ((error as { name?: string }).name !== "AbortError")
36
+ setState({
37
+ loading: false,
38
+ error: error instanceof Error ? error.message : "unknown",
39
+ rows: [],
40
+ });
41
+ });
42
+ return () => controller.abort();
43
+ }, [from, to]);
44
+ if (state.loading)
45
+ return (
46
+ <p className="operations-empty" role="status">
47
+ {locale === "pt-BR" ? "Carregando desenvolvedores…" : "Loading developers…"}
48
+ </p>
49
+ );
50
+ if (state.error)
51
+ return (
52
+ <p className="operations-empty" role="alert">
53
+ {locale === "pt-BR"
54
+ ? "Não foi possível carregar desenvolvedores."
55
+ : "Could not load developers."}{" "}
56
+ {state.error}
57
+ </p>
58
+ );
59
+ return <CostDeveloperAttributionTable locale={locale} rows={state.rows} />;
60
+ }
@@ -0,0 +1,191 @@
1
+ import {
2
+ DataTable,
3
+ formatCompactNumber,
4
+ formatCurrency as formatDashboardCurrency,
5
+ formatDurationMs,
6
+ } from "@zaip-ai/dashboard-ui";
7
+ import type { CostLocale } from "./cost-monitor-copy.js";
8
+
9
+ export type CostDeveloperAttributionRow = {
10
+ account_id: string;
11
+ login_snapshot: string | null;
12
+ prd_count: number;
13
+ spec_count: number;
14
+ task_count: number;
15
+ run_count: number;
16
+ test_count: number | null;
17
+ evidence_count: number | null;
18
+ total_duration_ms: number | null;
19
+ total_tokens: number | null;
20
+ total_cost_brl: number | null;
21
+ duration_covered_runs: number;
22
+ token_covered_runs: number;
23
+ brl_covered_runs: number;
24
+ };
25
+
26
+ const visuallyHiddenStyle = {
27
+ clip: "rect(0, 0, 0, 0)",
28
+ height: 1,
29
+ margin: -1,
30
+ overflow: "hidden",
31
+ position: "absolute",
32
+ whiteSpace: "nowrap",
33
+ width: 1,
34
+ } as const;
35
+
36
+ function formatCount(value: number | null, locale: CostLocale): string {
37
+ return value === null
38
+ ? "—"
39
+ : new Intl.NumberFormat(locale, { maximumFractionDigits: 0 }).format(value);
40
+ }
41
+
42
+ function formatDuration(value: number | null, locale: CostLocale): string {
43
+ if (value === null) return locale === "pt-BR" ? "Indisponível" : "Unavailable";
44
+ return value === 0 ? "0" : formatDurationMs(value, locale);
45
+ }
46
+
47
+ function formatBrlCurrency(value: number | null, locale: CostLocale): string {
48
+ return value === null ? "—" : formatDashboardCurrency(value, "BRL", locale);
49
+ }
50
+
51
+ function formatTokens(value: number | null, locale: CostLocale): string {
52
+ return value === null
53
+ ? locale === "pt-BR"
54
+ ? "Indisponível"
55
+ : "Unavailable"
56
+ : formatCompactNumber(value, locale);
57
+ }
58
+
59
+ function partialMetric(
60
+ formatted: string,
61
+ coveredRuns: number,
62
+ runCount: number,
63
+ locale: CostLocale,
64
+ ) {
65
+ if (coveredRuns >= runCount) return formatted;
66
+ const label =
67
+ locale === "pt-BR"
68
+ ? `Valor parcial: telemetria conhecida em ${coveredRuns} de ${runCount} runs.`
69
+ : `Partial value: telemetry is known for ${coveredRuns} of ${runCount} runs.`;
70
+ return (
71
+ <span title={label}>
72
+ <span aria-hidden="true">{formatted}</span>
73
+ <span style={visuallyHiddenStyle}>{`${label} ${formatted}`}</span>
74
+ </span>
75
+ );
76
+ }
77
+
78
+ /**
79
+ * Developer facts are intentionally separate from the Operations table. The
80
+ * Cost Monitor reports only structural and financial facts tied to an
81
+ * attributed developer Run.
82
+ */
83
+ export function CostDeveloperAttributionTable({
84
+ locale,
85
+ rows,
86
+ }: {
87
+ locale: CostLocale;
88
+ rows: readonly CostDeveloperAttributionRow[];
89
+ }) {
90
+ return (
91
+ <DataTable
92
+ columns={[
93
+ {
94
+ key: "developer",
95
+ label: locale === "pt-BR" ? "Desenvolvedor" : "Developer",
96
+ render: (row) => (
97
+ <>
98
+ <strong>{row.login_snapshot ?? row.account_id}</strong>
99
+ <small>#{row.account_id}</small>
100
+ </>
101
+ ),
102
+ sortValue: (row) => row.login_snapshot ?? row.account_id,
103
+ },
104
+ {
105
+ key: "prds",
106
+ label: "PRDs",
107
+ render: (row) => formatCount(row.prd_count, locale),
108
+ align: "right",
109
+ },
110
+ {
111
+ key: "specs",
112
+ label: "SPECs",
113
+ render: (row) => formatCount(row.spec_count, locale),
114
+ align: "right",
115
+ },
116
+ {
117
+ key: "tasks",
118
+ label: locale === "pt-BR" ? "Tarefas" : "Tasks",
119
+ render: (row) => formatCount(row.task_count, locale),
120
+ align: "right",
121
+ },
122
+ {
123
+ key: "runs",
124
+ label: "Runs",
125
+ render: (row) => formatCount(row.run_count, locale),
126
+ align: "right",
127
+ },
128
+ {
129
+ key: "tests",
130
+ label: locale === "pt-BR" ? "Testes" : "Tests",
131
+ render: (row) => formatCount(row.test_count, locale),
132
+ align: "right",
133
+ },
134
+ {
135
+ key: "evidences",
136
+ label: locale === "pt-BR" ? "Evidências" : "Evidence",
137
+ render: (row) => formatCount(row.evidence_count, locale),
138
+ align: "right",
139
+ },
140
+ {
141
+ key: "duration",
142
+ label: locale === "pt-BR" ? "Tempo" : "Time",
143
+ render: (row) =>
144
+ partialMetric(
145
+ formatDuration(row.total_duration_ms, locale),
146
+ row.duration_covered_runs,
147
+ row.run_count,
148
+ locale,
149
+ ),
150
+ sortValue: (row) => row.total_duration_ms,
151
+ align: "right",
152
+ },
153
+ {
154
+ key: "tokens",
155
+ label: "Tokens",
156
+ render: (row) =>
157
+ partialMetric(
158
+ formatTokens(row.total_tokens, locale),
159
+ row.token_covered_runs,
160
+ row.run_count,
161
+ locale,
162
+ ),
163
+ sortValue: (row) => row.total_tokens,
164
+ align: "right",
165
+ },
166
+ {
167
+ key: "cost",
168
+ label: locale === "pt-BR" ? "Custos" : "Costs",
169
+ render: (row) =>
170
+ partialMetric(
171
+ formatBrlCurrency(row.total_cost_brl, locale),
172
+ row.brl_covered_runs,
173
+ row.run_count,
174
+ locale,
175
+ ),
176
+ sortValue: (row) => row.total_cost_brl,
177
+ align: "right",
178
+ },
179
+ ]}
180
+ defaultSort={{ key: "cost", direction: "desc" }}
181
+ emptyMessage={locale === "pt-BR" ? "Nenhum dado disponível." : "No data available."}
182
+ locale={locale}
183
+ pageSize={10}
184
+ rowKey={(row) => row.account_id}
185
+ rows={rows}
186
+ scrollLabel={locale === "pt-BR" ? "Métricas por desenvolvedor" : "Developer metrics"}
187
+ showColumnInfo
188
+ sortable
189
+ />
190
+ );
191
+ }
@@ -0,0 +1,14 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ describe("Cost period loading lifecycle", () => {
5
+ it("clears a filtered request when the embedded snapshot becomes sufficient", () => {
6
+ const source = readFileSync(new URL("./CostFilters.tsx", import.meta.url), "utf8");
7
+
8
+ expect(source).toContain("const generation = ++generationRef.current;");
9
+ expect(source).toContain("if (!shouldFetch)");
10
+ expect(source).toContain("setPeriodLoading(false);");
11
+ expect(source).toContain("setPeriodData(null);");
12
+ expect(source).toContain("generation === generationRef.current");
13
+ });
14
+ });
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { loadCostMonitorRunPage } from "./CostFilters.js";
3
+
4
+ describe("Cost Monitor invocation page loading", () => {
5
+ it("uses a ten-row default for the remote invocation page", async () => {
6
+ const calls: string[] = [];
7
+ await loadCostMonitorRunPage({
8
+ currency: "BRL",
9
+ offset: 0,
10
+ fetcher: async (url) => {
11
+ calls.push(String(url));
12
+ return new Response(JSON.stringify({ runs: [] }), { status: 200 });
13
+ },
14
+ });
15
+
16
+ expect(new URL(calls[0]!, "http://dashboard.local").searchParams.get("limit")).toBe("10");
17
+ });
18
+ });
@@ -107,6 +107,7 @@ export async function loadCostMonitorRunPage({
107
107
  currency,
108
108
  filters,
109
109
  from,
110
+ limit = 10,
110
111
  offset,
111
112
  refresh,
112
113
  to,
@@ -116,6 +117,7 @@ export async function loadCostMonitorRunPage({
116
117
  currency: CostCurrency;
117
118
  filters?: CostFilterState;
118
119
  from?: string;
120
+ limit?: number;
119
121
  offset: number;
120
122
  refresh?: string | null;
121
123
  to?: string;
@@ -131,7 +133,7 @@ export async function loadCostMonitorRunPage({
131
133
  });
132
134
  query.set("scope", "runs");
133
135
  query.set("offset", String(Math.max(0, offset)));
134
- query.set("limit", "100");
136
+ query.set("limit", String(Math.max(1, limit)));
135
137
  const response = await fetcher(`/api/v2/cost-monitor?${query.toString()}`, {
136
138
  ...(signal === undefined ? {} : { signal }),
137
139
  });
@@ -143,7 +145,7 @@ export async function loadCostMonitorRunPage({
143
145
  return {
144
146
  page_only: true,
145
147
  runs: payload.runs,
146
- run_page: payload.run_page ?? { offset, limit: 100, total: null, has_more: false },
148
+ run_page: payload.run_page ?? { offset, limit, total: null, has_more: false },
147
149
  };
148
150
  }
149
151
 
@@ -212,6 +214,7 @@ export function useCostMonitorPeriod({
212
214
  const [periodLoading, setPeriodLoading] = useState(false);
213
215
  const [periodError, setPeriodError] = useState<string | null>(null);
214
216
  const initialDataRef = useRef(true);
217
+ const generationRef = useRef(0);
215
218
  const loadPeriodRef = useRef(loadPeriod);
216
219
  loadPeriodRef.current = loadPeriod;
217
220
  const requestedRange =
@@ -222,8 +225,16 @@ export function useCostMonitorPeriod({
222
225
  const requestedTo = requestedRange?.to;
223
226
  const shouldFetch = shouldFetchCostPeriod({ filters, period, snapshotBacked });
224
227
  useEffect(() => {
228
+ const generation = ++generationRef.current;
225
229
  if (!shouldFetch) {
226
230
  initialDataRef.current = false;
231
+ // A filtered request can be aborted immediately before this embedded
232
+ // default snapshot becomes sufficient again. There is no successor
233
+ // request in that branch to release the loading gate.
234
+ setPeriodLoading(false);
235
+ setPeriodError(null);
236
+ setPeriodData(null);
237
+ setPeriodDataBase(null);
227
238
  return;
228
239
  }
229
240
  if (initialDataRef.current && Object.values(filters).every((value) => value === "")) {
@@ -255,7 +266,11 @@ export function useCostMonitorPeriod({
255
266
  }
256
267
  })
257
268
  .finally(() => {
258
- if (!controller.signal.aborted) setPeriodLoading(false);
269
+ // An aborted predecessor must not clear a newer request. Conversely,
270
+ // an active request always releases its own loading gate, including an
271
+ // HTTP failure handled above.
272
+ if (!controller.signal.aborted && generation === generationRef.current)
273
+ setPeriodLoading(false);
259
274
  });
260
275
  return () => controller.abort();
261
276
  }, [currency, data, filters, lastUpdatedAt, requestedFrom, requestedTo, shouldFetch]);
@@ -1,5 +1,5 @@
1
1
  import { ExecutionTable } from "@zaip-ai/dashboard-operations/react";
2
- import type { ComponentProps } from "react";
2
+ import type { ComponentProps, ReactNode } from "react";
3
3
  import {
4
4
  type CompactLifecycleCostSubtotal,
5
5
  CompactLifecycleCostTable,
@@ -29,6 +29,7 @@ export function CostMonitorContent({
29
29
  currency,
30
30
  detailError,
31
31
  detailLoading,
32
+ developerPanel,
32
33
  dimensionalDetailPending,
33
34
  dimensionalRows,
34
35
  groups,
@@ -76,6 +77,7 @@ export function CostMonitorContent({
76
77
  currency: CostCurrency;
77
78
  detailError: string | null;
78
79
  detailLoading: boolean;
80
+ developerPanel: ReactNode;
79
81
  dimensionalDetailPending: boolean;
80
82
  dimensionalRows: CostRunRows;
81
83
  groups: {
@@ -152,6 +154,7 @@ export function CostMonitorContent({
152
154
  ) : null;
153
155
  return (
154
156
  <section
157
+ aria-busy={groupPageLoading || compactPageLoading || runPageLoading || undefined}
155
158
  className={`cost-content cost-content-${view} ${view === "overview" ? "cost-content-overview" : ""}`}
156
159
  >
157
160
  {detailLoading || dimensionalDetailPending ? (
@@ -178,6 +181,7 @@ export function CostMonitorContent({
178
181
  {...(useAggregateGroups ? { summaryUsage } : {})}
179
182
  />
180
183
  ) : null}
184
+ {view === "developers" ? developerPanel : null}
181
185
  {view === "agentCalls" ? (
182
186
  <>
183
187
  <CostRunsTable
@@ -191,7 +195,7 @@ export function CostMonitorContent({
191
195
  pagination: {
192
196
  ...(runPageData?.run_page ?? {
193
197
  offset: runPageOffset,
194
- limit: 100,
198
+ limit: 10,
195
199
  total: null,
196
200
  has_more: false,
197
201
  }),
@@ -284,6 +288,7 @@ export function CostMonitorContent({
284
288
  : "Providers"
285
289
  }
286
290
  locale={locale}
291
+ loading={groupPageLoading}
287
292
  rows={groups[key]}
288
293
  {...(key === "models" || key === "providers"
289
294
  ? { totals: summaryTotals }
@@ -311,6 +316,7 @@ export function CostMonitorContent({
311
316
  <CostGroupsTable
312
317
  currency={currency}
313
318
  locale={locale}
319
+ loading={groupPageLoading}
314
320
  period={view}
315
321
  rows={groups[view]}
316
322
  showDateTime={false}
@@ -0,0 +1,35 @@
1
+ import type { CostLocale } from "./cost-monitor-copy.js";
2
+
3
+ export function CostMonitorLoadErrors({
4
+ groupError,
5
+ locale,
6
+ periodError,
7
+ retryGroup,
8
+ }: {
9
+ groupError: string | null;
10
+ locale: CostLocale;
11
+ periodError: string | null;
12
+ retryGroup: () => void;
13
+ }) {
14
+ return (
15
+ <>
16
+ {periodError ? (
17
+ <p className="cost-period-error" role="status">
18
+ {locale === "pt-BR"
19
+ ? `Não foi possível carregar o período selecionado: ${periodError}`
20
+ : `Could not load the selected period: ${periodError}`}
21
+ </p>
22
+ ) : null}
23
+ {groupError ? (
24
+ <p className="cost-period-error" role="status">
25
+ {locale === "pt-BR"
26
+ ? `Não foi possível carregar esta aba: ${groupError}`
27
+ : `Could not load this tab: ${groupError}`}
28
+ <button onClick={retryGroup} type="button">
29
+ {locale === "pt-BR" ? "Tentar novamente" : "Try again"}
30
+ </button>
31
+ </p>
32
+ ) : null}
33
+ </>
34
+ );
35
+ }
@@ -111,6 +111,22 @@ describe("cost monitor navigation", () => {
111
111
  expect(page).toContain("() => () => onLoadingChange?.(false)");
112
112
  });
113
113
 
114
+ it("does not fetch group pages for a non-group Cost Monitor tab and exposes a retryable error", () => {
115
+ const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
116
+
117
+ expect(page).toContain("active: groupView !== null");
118
+ expect(page).toContain("groupPageState.retry");
119
+ });
120
+
121
+ it("requests exactly ten remote rows for the slow Cost Monitor tabs", () => {
122
+ const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
123
+
124
+ expect(page).toContain("const compactPageLimit = 10;");
125
+ expect(page).toContain("const groupPageLimit = 10;");
126
+ expect(page).toContain("limit: 10,");
127
+ expect(page).toContain("range: groupPageRange");
128
+ });
129
+
114
130
  it("labels daily pagination by its continuous result range", () => {
115
131
  expect(
116
132
  costGroupPageLabel({
@@ -267,9 +283,19 @@ describe("cost monitor navigation", () => {
267
283
  expect(runHook).toContain("query: filters.query || globalQuery");
268
284
  expect(groupHook).toContain("export type CostGroupFilters = CostFilterState");
269
285
  expect(groupHook).toContain("filters,");
270
- expect(page).toContain("groupPageState.page === null");
286
+ expect(page).toContain(
287
+ "const displayedGroupPage = groupPageState.page ?? groupPageState.stalePage",
288
+ );
271
289
  expect(page).toContain("? []");
272
290
  });
291
+
292
+ it("keeps the Agents visual page bounded when the server page loader is available", () => {
293
+ const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
294
+
295
+ expect(page).toContain('groupView === "agents" && loadGroupPage === undefined');
296
+ expect(page).toContain(": [...displayedGroupPage.rows]");
297
+ expect(page).toContain("const groupPageLimit = 10;");
298
+ });
273
299
  it("uses the Sao Paulo calendar for global daily filtering on both sides of 03:00Z", () => {
274
300
  const base = costRun("RUN-CALENDAR");
275
301
  expect(
@@ -314,6 +340,7 @@ describe("cost monitor navigation", () => {
314
340
  "daily",
315
341
  "monthly",
316
342
  "annual",
343
+ "developers",
317
344
  "overview",
318
345
  "executions",
319
346
  "agentCalls",
@@ -327,14 +354,33 @@ describe("cost monitor navigation", () => {
327
354
  ]);
328
355
  });
329
356
 
357
+ it("places the shared developer table inside the Cost Monitor content section", () => {
358
+ const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
359
+ const content = readFileSync(new URL("./CostMonitorContent.tsx", import.meta.url), "utf8");
360
+
361
+ expect(page).toMatch(
362
+ /developerPanel=\{\s*view === "developers" \? \(\s*<CostDeveloperAttributionPanel\b/,
363
+ );
364
+ expect(page).not.toMatch(/<\/CostMonitorContent>\s*\{view === "developers"/);
365
+ expect(content).toContain('{view === "developers" ? developerPanel : null}');
366
+ });
367
+
330
368
  it("prepares Agent Invocations from every server page for export", () => {
331
369
  const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
370
+ const exportSection = page.slice(
371
+ page.indexOf("const agentInvocationExportSource"),
372
+ page.indexOf("const costGroupExportSource"),
373
+ );
332
374
  expect(page).toContain('view === "agentCalls" && serverPagingEligible');
333
375
  expect(page).toContain("agentInvocationExportSource");
334
376
  expect(page).toMatch(
335
377
  /pageSource=\{\s*compactExportSource \?\? agentInvocationExportSource \?\? costGroupExportSource\s*\}/,
336
378
  );
337
379
  expect(page).toContain("if (page.runs.length === 0) return");
380
+ expect(exportSection.match(/limit: 100/g)).toHaveLength(2);
381
+ expect(exportSection).toContain("nextOffset >= page.run_page.total");
382
+ expect(exportSection).toContain("...(groupPageRange === undefined ? {} : groupPageRange)");
383
+ expect(exportSection).not.toContain("...(runPageRange === undefined ? {} : runPageRange)");
338
384
  });
339
385
 
340
386
  it("prepares every paginated period row for daily, monthly, and annual exports", () => {