@zaip-ai/cli 1.3.0 → 1.3.2

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 +3 -2
  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-BXy6nti1.js} +268 -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-CTH2wDs5.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-CuMcoUni.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 +293 -0
  156. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.ts +371 -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 +92 -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
@@ -6,15 +6,15 @@
6
6
  <meta name="color-scheme" content="dark light" />
7
7
  <link rel="icon" type="image/png" href="/icon_zaip.png" />
8
8
  <title>ZAIP-AIOS</title>
9
- <script type="module" crossorigin src="/assets/index-C4aIB1PV.js"></script>
9
+ <script type="module" crossorigin src="/assets/index-CuMcoUni.js"></script>
10
10
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-D9-fqq9M.js">
11
- <link rel="modulepreload" crossorigin href="/assets/cost-monitor-N5Csr0RP.js">
12
- <link rel="modulepreload" crossorigin href="/assets/react-vendor-BEsJ-FYH.js">
13
- <link rel="modulepreload" crossorigin href="/assets/icons-vendor-C0fj2uU9.js">
14
- <link rel="modulepreload" crossorigin href="/assets/traceability-B6y6Gw12.js">
15
- <link rel="stylesheet" crossorigin href="/assets/cost-monitor-BZ5WdaMN.css">
11
+ <link rel="modulepreload" crossorigin href="/assets/cost-monitor-DKwP1stV.js">
12
+ <link rel="modulepreload" crossorigin href="/assets/react-vendor-B3TJrD4O.js">
13
+ <link rel="modulepreload" crossorigin href="/assets/icons-vendor-B_lDDHn1.js">
14
+ <link rel="modulepreload" crossorigin href="/assets/traceability-7f1j5wx3.js">
15
+ <link rel="stylesheet" crossorigin href="/assets/cost-monitor-PoJA2PI1.css">
16
16
  <link rel="stylesheet" crossorigin href="/assets/traceability-DFY7ZDlu.css">
17
- <link rel="stylesheet" crossorigin href="/assets/index-DK_enB5Z.css">
17
+ <link rel="stylesheet" crossorigin href="/assets/index-B31GMG5O.css">
18
18
  </head>
19
19
  <body>
20
20
  <div id="root"></div>
@@ -0,0 +1,32 @@
1
+ import { defineConfig, devices } from "@playwright/test";
2
+
3
+ const workspaceRoot = decodeURIComponent(new URL("../../../..", import.meta.url).pathname).replace(
4
+ /^\/([A-Za-z]:\/)/,
5
+ "$1",
6
+ );
7
+ const serverPort = process.env.ZAIP_SERVER_PORT ?? "4517";
8
+ const baseURL = process.env.PLAYWRIGHT_BASE_URL ?? `http://127.0.0.1:${serverPort}`;
9
+
10
+ export default defineConfig({
11
+ testDir: "./src",
12
+ testMatch: "TraceabilityWorkspace.dom.e2e.ts",
13
+ timeout: 60_000,
14
+ expect: { timeout: 30_000 },
15
+ use: {
16
+ baseURL: `${baseURL}/?token=e2e-token`,
17
+ },
18
+ projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }],
19
+ webServer: {
20
+ command: "node .agents/dashboard/packages/local-runtime/dist/server.cjs",
21
+ cwd: workspaceRoot,
22
+ url: `${baseURL}/api/v2/health`,
23
+ reuseExistingServer: false,
24
+ timeout: 30_000,
25
+ env: {
26
+ ZAIP_UI_TOKEN: "e2e-token",
27
+ ZAIP_SERVER_PORT: serverPort,
28
+ ZAIP_WORKSPACE: workspaceRoot,
29
+ ZAIP_UI_ROOT: `${workspaceRoot}/.agents/dashboard/apps/frontend/dist`,
30
+ },
31
+ },
32
+ });
@@ -34,36 +34,25 @@ import type {
34
34
  OperationsPageFilters,
35
35
  PricingCatalog,
36
36
  ReconciliationResult,
37
- SqliteViewName,
38
37
  WorkBoardStage,
39
38
  } from "./dashboard-api.js";
40
39
  import { DashboardApiClient } from "./dashboard-api.js";
41
40
  import { defaultOperationsPeriod, requestPeriodForOperations } from "./operations-period.js";
42
41
  import { shouldShowSnapshotNotice, snapshotNoticeDelayMs } from "./snapshot-notice.js";
42
+ import {
43
+ appendTraceabilityTaskPage,
44
+ traceabilityTaskPageSize,
45
+ } from "./traceability-task-pagination.js";
43
46
  import { useAppCostLoaders } from "./use-app-cost-loaders.js";
44
47
  import { useAppEffects } from "./use-app-effects.js";
45
48
  import { useAppOperationsPages } from "./use-app-operations-pages.js";
46
49
  import { useAppTraceDocuments } from "./use-app-trace-documents.js";
47
- import {
48
- collectWorkListPages,
49
- normalizeWorkListFilters,
50
- selectedWorkListKinds,
51
- } from "./work-list-pagination.js";
50
+ import { useAppWorkListPage } from "./use-app-work-list-page.js";
51
+ import { useOperationsDetailExport } from "./use-operations-detail-export.js";
52
52
  import "./loading-feedback.css";
53
53
  import "./period-transition-overlay.css";
54
54
 
55
55
  type BoardStageState = { loading: boolean; error: string | null };
56
- type OperationsExportView =
57
- | "work-kanban"
58
- | "work-list"
59
- | "changes"
60
- | "decisions"
61
- | "executions"
62
- | "runs"
63
- | "conversations"
64
- | "daily"
65
- | "monthly"
66
- | "yearly";
67
56
  type OverviewStatusKind = "task" | "spec" | "prd";
68
57
  type OverviewClassification = "lite" | "standard" | "critical" | "empty" | "structured" | "rework";
69
58
  type OverviewStatusPage = {
@@ -110,82 +99,6 @@ const traceTaskSearchStages: readonly WorkBoardStage[] = [
110
99
  "definition",
111
100
  ];
112
101
 
113
- /** Mounts the Daily Cost view without requesting the historical summary blob. */
114
- function dailyCostSeed(
115
- currency: "BRL" | "USD",
116
- filters: CostMonitorProjection["filters"],
117
- ): CostMonitorProjection {
118
- const metric = {
119
- events: 0,
120
- tokens: { input: null, cached_input: null, output: null, reasoning: null, total: null },
121
- cost: { usd: null, brl: null },
122
- coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
123
- };
124
- const usage = {
125
- conversation: metric,
126
- planning: metric,
127
- execution: metric,
128
- total: metric,
129
- new_work: metric,
130
- rework: metric,
131
- };
132
- return {
133
- schema_version: 2,
134
- layout_version: 2,
135
- readonly: true,
136
- source: ".agents/records",
137
- aggregate_only: true,
138
- data_source: "run_records",
139
- legacy_effort_baseline: null,
140
- currency,
141
- pricing: { catalog_updated_at: null, fx_rate: null, conversion_applied: false },
142
- filters,
143
- overview: {
144
- task_count: 0,
145
- run_count: 0,
146
- event_count: 0,
147
- total_tokens: null,
148
- estimated_usd: null,
149
- estimated_brl: null,
150
- recorded_usd: null,
151
- recorded_brl: null,
152
- average_run_cost_usd: null,
153
- average_run_cost_brl: null,
154
- average_run_duration_ms: null,
155
- known_tokens_per_cycle: null,
156
- top_10_token_share: null,
157
- coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
158
- },
159
- filters_available: {
160
- providers: [],
161
- agents: [],
162
- models: [],
163
- statuses: [],
164
- priorities: [],
165
- risks: [],
166
- phases: [],
167
- origins: [],
168
- work_types: [],
169
- },
170
- configured_agents: [],
171
- usage,
172
- origins: { conversation: usage, task: usage, spec: usage, prd: usage },
173
- prds: [],
174
- specs: [],
175
- runs: [],
176
- groups: {
177
- conversations: [],
178
- tasks: [],
179
- providers: [],
180
- agents: [],
181
- models: [],
182
- daily: [],
183
- monthly: [],
184
- annual: [],
185
- },
186
- };
187
- }
188
-
189
102
  export {
190
103
  isAbortError,
191
104
  isCurrentDashboardRequest,
@@ -252,8 +165,8 @@ export function App() {
252
165
  const [fxRate, setFxRate] = useState<FxRate | null>(null);
253
166
  const [pathname, setPathname] = useState(window.location.pathname);
254
167
  const [operationsLoading, setOperationsLoading] = useState(true);
255
- const [operationsSurfaceLoading, setOperationsSurfaceLoading] = useState(false);
256
- const [costSurfaceLoading, setCostSurfaceLoading] = useState(false);
168
+ const [, setOperationsSurfaceLoading] = useState(false);
169
+ const [, setCostSurfaceLoading] = useState(false);
257
170
  const [periodTransitionPending, setPeriodTransitionPending] = useState(false);
258
171
  const [loadingArea, setLoadingArea] = useState<LoadingArea | null>("operations");
259
172
  const [failedArea, setFailedArea] = useState<LoadingArea | null>(null);
@@ -293,7 +206,15 @@ export function App() {
293
206
  traceLoadingTaskId,
294
207
  traceTasks,
295
208
  } = useAppTraceDocuments({ api, operations, setError, setFailedArea, setLoadingArea });
209
+ const traceTasksRef = useRef(traceTasks);
210
+ const traceTaskCursorRef = useRef({ offset: 0, stageIndex: 0 });
211
+ const traceTasksLoadingRef = useRef(false);
212
+ const [traceTasksHasMore, setTraceTasksHasMore] = useState(false);
213
+ const [traceTasksLoading, setTraceTasksLoading] = useState(false);
296
214
  const refreshVersion = useRef(0);
215
+ useEffect(() => {
216
+ traceTasksRef.current = traceTasks;
217
+ }, [traceTasks]);
297
218
  const periodTransitionVersionRef = useRef(0);
298
219
  const detailLoadInFlight = useRef(false);
299
220
  const costLoadingCount = useRef(0);
@@ -307,6 +228,7 @@ export function App() {
307
228
  const operationsPageRequestVersionRef = useRef(0);
308
229
  const boardLoadedRef = useRef<Partial<Record<WorkBoardStage, number>>>({});
309
230
  const boardInFlightRef = useRef(new Set<WorkBoardStage>());
231
+ const boardAbortControllersRef = useRef(new Map<WorkBoardStage, AbortController>());
310
232
  const overviewStatusInFlightRef = useRef(new Set<string>());
311
233
  const boardInitialPageRef = useRef(new Set<WorkBoardStage>());
312
234
  const boardFiltersRef = useRef<OperationsPageFilters>({
@@ -316,15 +238,17 @@ export function App() {
316
238
  origin: "",
317
239
  kind: "",
318
240
  });
319
- const workListFiltersRef = useRef<OperationsPageFilters>({
320
- query: "",
321
- status: "",
322
- risk: "",
323
- });
324
241
  const boardFilterKeyRef = useRef("||||");
325
242
  const boardRequestVersionRef = useRef(0);
326
243
  const quickOverviewMetricsRef =
327
244
  useRef<OperationsProjection["summary"]["overview_metrics"]>(undefined);
245
+ const {
246
+ workListPage,
247
+ workListFiltersRef,
248
+ loadWorkListFilters,
249
+ loadWorkListPage,
250
+ resetWorkListPage,
251
+ } = useAppWorkListPage({ api, operationsPeriod, operationsPeriodRef });
328
252
  // A new local SQLite generation is immutable and verified by the launcher.
329
253
  // Its server begins warming the compact first fold as soon as readiness is
330
254
  // observed, so the first paint must join that bounded cache instead of
@@ -337,6 +261,8 @@ export function App() {
337
261
  operationsDetailAbortRef.current?.abort();
338
262
  operationsDetailAbortRef.current = null;
339
263
  boardRequestVersionRef.current += 1;
264
+ for (const controller of boardAbortControllersRef.current.values()) controller.abort();
265
+ boardAbortControllersRef.current.clear();
340
266
  boardInFlightRef.current.clear();
341
267
  boardInitialPageRef.current.clear();
342
268
  boardLoadedRef.current = {};
@@ -514,13 +440,24 @@ export function App() {
514
440
  const current = operations;
515
441
  if (current === null || boardInFlightRef.current.has(stage)) return;
516
442
  boardInFlightRef.current.add(stage);
443
+ boardAbortControllersRef.current.get(stage)?.abort();
444
+ const controller = new AbortController();
445
+ boardAbortControllersRef.current.set(stage, controller);
517
446
  const requestVersion = boardRequestVersionRef.current;
518
447
  const period = requestPeriodForOperations(operationsPeriod);
519
448
  setBoardStates((previous) => ({ ...previous, [stage]: { loading: true, error: null } }));
520
449
  const loaded = boardLoadedRef.current[stage] ?? 0;
521
450
  try {
522
- const page = await api.operationsBoard(period, stage, loaded, boardFiltersRef.current);
451
+ const page = await api.operationsBoard(
452
+ period,
453
+ stage,
454
+ loaded,
455
+ boardFiltersRef.current,
456
+ controller.signal,
457
+ 10,
458
+ );
523
459
  if (
460
+ controller.signal.aborted ||
524
461
  requestVersion !== boardRequestVersionRef.current ||
525
462
  period.from !== requestPeriodForOperations(operationsPeriodRef.current).from ||
526
463
  period.to !== requestPeriodForOperations(operationsPeriodRef.current).to
@@ -540,7 +477,12 @@ export function App() {
540
477
  const next = loaded + page.prds.length + page.specs.length + page.tasks.length;
541
478
  boardLoadedRef.current = { ...boardLoadedRef.current, [stage]: next };
542
479
  } catch (cause) {
543
- if (requestVersion !== boardRequestVersionRef.current || isAbortError(cause)) return;
480
+ if (
481
+ controller.signal.aborted ||
482
+ requestVersion !== boardRequestVersionRef.current ||
483
+ isAbortError(cause)
484
+ )
485
+ return;
544
486
  setBoardStates((previous) => ({
545
487
  ...previous,
546
488
  [stage]: {
@@ -551,6 +493,8 @@ export function App() {
551
493
  } finally {
552
494
  if (requestVersion === boardRequestVersionRef.current) {
553
495
  boardInFlightRef.current.delete(stage);
496
+ if (boardAbortControllersRef.current.get(stage) === controller)
497
+ boardAbortControllersRef.current.delete(stage);
554
498
  setBoardStates((previous) =>
555
499
  previous[stage]?.error === null
556
500
  ? { ...previous, [stage]: { loading: false, error: null } }
@@ -571,6 +515,8 @@ export function App() {
571
515
  boardFilterKeyRef.current = filterKey;
572
516
  boardFiltersRef.current = normalizedFilters;
573
517
  boardRequestVersionRef.current += 1;
518
+ for (const controller of boardAbortControllersRef.current.values()) controller.abort();
519
+ boardAbortControllersRef.current.clear();
574
520
  boardInFlightRef.current.clear();
575
521
  boardInitialPageRef.current.clear();
576
522
  boardLoadedRef.current = {};
@@ -595,68 +541,6 @@ export function App() {
595
541
  },
596
542
  );
597
543
  }, []);
598
- const loadFilteredWorkList = useCallback(
599
- async (filters: OperationsPageFilters) => {
600
- const requestVersion = ++boardRequestVersionRef.current;
601
- const period = requestPeriodForOperations(operationsPeriod);
602
- const normalizedFilters = normalizeWorkListFilters(filters, workListFiltersRef.current);
603
- workListFiltersRef.current = normalizedFilters;
604
- const requestedKind = selectedWorkListKinds(normalizedFilters.kind);
605
- const loadKindStage = async (
606
- stage: WorkBoardStage,
607
- kind: "prd" | "spec" | "task" | "standalone-task",
608
- ) => {
609
- return collectWorkListPages(async (offset) => {
610
- const page = await api.operationsBoard(
611
- period,
612
- stage,
613
- offset,
614
- { ...normalizedFilters, kind },
615
- undefined,
616
- 50,
617
- );
618
- return {
619
- total: page.total,
620
- received: page.prds.length + page.specs.length + page.tasks.length,
621
- value: page,
622
- };
623
- });
624
- };
625
- try {
626
- const pages = (
627
- await Promise.all(
628
- initialWorkBoardStages.flatMap((stage) =>
629
- requestedKind.map((kind) => loadKindStage(stage, kind)),
630
- ),
631
- )
632
- ).flat();
633
- if (
634
- requestVersion !== boardRequestVersionRef.current ||
635
- period.from !== requestPeriodForOperations(operationsPeriodRef.current).from ||
636
- period.to !== requestPeriodForOperations(operationsPeriodRef.current).to
637
- )
638
- return;
639
- const unique = <T extends { id: string }>(rows: readonly T[]) => [
640
- ...new Map(rows.map((row) => [row.id, row] as const)).values(),
641
- ];
642
- setOperations((current) =>
643
- current === null
644
- ? current
645
- : {
646
- ...current,
647
- prds: unique(pages.flatMap((page) => page.prds)),
648
- specs: unique(pages.flatMap((page) => page.specs)),
649
- tasks: unique(pages.flatMap((page) => page.tasks)),
650
- },
651
- );
652
- } catch (cause) {
653
- if (requestVersion !== boardRequestVersionRef.current || isAbortError(cause)) return;
654
- setError(cause instanceof Error ? cause.message : String(cause));
655
- setFailedArea("operations");
656
- }
657
- },
658
- [api, operationsPeriod],
659
- );
660
544
  const loadOverviewStatusPage = useCallback(
661
545
  async (stage: WorkBoardStage, kind: OverviewStatusKind, offset: number) => {
662
546
  const key = overviewStatusPageKey(stage, kind);
@@ -674,7 +558,9 @@ export function App() {
674
558
  },
675
559
  }));
676
560
  try {
677
- const page = await api.operationsBoard(period, stage, offset, { kind });
561
+ const page = await api.operationsBoard(period, stage, offset, {
562
+ kind: kind === "task" ? "all-tasks" : kind,
563
+ });
678
564
  if (
679
565
  requestVersion !== boardRequestVersionRef.current ||
680
566
  period.from !== requestPeriodForOperations(operationsPeriodRef.current).from ||
@@ -795,65 +681,21 @@ export function App() {
795
681
  },
796
682
  [api, operationsPeriod],
797
683
  );
798
- const detailExportSource = useCallback(
799
- (
800
- view: OperationsExportView,
801
- filters: { query: string; status: string; risk: string; origin: string },
802
- ) => {
803
- const period = requestPeriodForOperations(operationsPeriod);
804
- if (view === "work-kanban") return undefined;
805
- const sqliteView = {
806
- "work-list": "operations_work_list",
807
- changes: "operations_changes",
808
- decisions: "operations_decisions",
809
- executions: "operations_executions",
810
- runs: "operations_agent_invocations",
811
- conversations: "operations_conversations",
812
- daily: "operations_daily",
813
- monthly: "operations_monthly",
814
- yearly: "operations_annual",
815
- } as const satisfies Partial<Record<OperationsExportView, SqliteViewName>>;
816
- const source = sqliteView[view];
817
- if (source === undefined) return undefined;
818
- const options = (offset: number) => ({
819
- offset,
820
- limit: 100,
821
- ...(filters.query ? { query: filters.query } : {}),
822
- ...(filters.status ? { status: filters.status } : {}),
823
- ...(filters.risk ? { risk: filters.risk } : {}),
824
- ...(filters.origin ? { origin: filters.origin } : {}),
825
- });
826
- return {
827
- prepare: async () => {
828
- const firstPage = await api.sqliteViewPage(source, period, options(0));
829
- return {
830
- totalRows: firstPage.total_count,
831
- pages: async function* () {
832
- let page = firstPage;
833
- while (true) {
834
- if (page.rows.length === 0) return;
835
- yield page.rows;
836
- const nextOffset = page.offset + page.rows.length;
837
- if (nextOffset >= page.total_count) return;
838
- page = await api.sqliteViewPage(source, period, options(nextOffset));
839
- }
840
- },
841
- };
842
- },
843
- };
844
- },
845
- [api, operationsPeriod],
846
- );
684
+ const detailExportSource = useOperationsDetailExport({ api, operationsPeriod });
847
685
  useEffect(() => {
848
686
  if (dashboardView !== "operations" || operations === null) return;
849
687
  let cancelled = false;
850
- const hydrateBoard = () => {
688
+ const hydrateBoard = async () => {
851
689
  if (cancelled) return;
852
- for (const stage of initialWorkBoardStages) {
853
- if (!boardInitialPageRef.current.has(stage) && !boardInFlightRef.current.has(stage)) {
854
- boardInitialPageRef.current.add(stage);
855
- void loadMoreBoard(stage);
856
- }
690
+ // A page per column preserves a fast first board without monopolising
691
+ // SQLite's single local worker with nine simultaneous aggregates.
692
+ const pending = initialWorkBoardStages.filter(
693
+ (stage) => !boardInitialPageRef.current.has(stage) && !boardInFlightRef.current.has(stage),
694
+ );
695
+ for (let offset = 0; offset < pending.length && !cancelled; offset += 3) {
696
+ const batch = pending.slice(offset, offset + 3);
697
+ for (const stage of batch) boardInitialPageRef.current.add(stage);
698
+ await Promise.all(batch.map((stage) => loadMoreBoard(stage)));
857
699
  }
858
700
  };
859
701
  // The quick projection is the complete first-fold contract. Defer the
@@ -861,8 +703,8 @@ export function App() {
861
703
  // the useful overview when SQLite must materialise the board view.
862
704
  const idle =
863
705
  typeof window.requestIdleCallback === "function"
864
- ? { kind: "idle" as const, id: window.requestIdleCallback(hydrateBoard) }
865
- : { kind: "timeout" as const, id: window.setTimeout(hydrateBoard, 0) };
706
+ ? { kind: "idle" as const, id: window.requestIdleCallback(() => void hydrateBoard()) }
707
+ : { kind: "timeout" as const, id: window.setTimeout(() => void hydrateBoard(), 0) };
866
708
  return () => {
867
709
  cancelled = true;
868
710
  if (idle.kind === "idle") window.cancelIdleCallback(idle.id);
@@ -871,7 +713,9 @@ export function App() {
871
713
  }, [dashboardView, loadMoreBoard, operations]);
872
714
 
873
715
  const refreshFromDialog = async (reconcileOpenWork: boolean) => {
874
- if (reconcileOpenWork) setReconciliationResult(null);
716
+ if (reconcileOpenWork) {
717
+ setReconciliationResult(null);
718
+ }
875
719
  setRefreshDialog(reconcileOpenWork ? "reconciling" : "refreshing");
876
720
  await refresh(false, reconcileOpenWork, !reconcileOpenWork);
877
721
  setRefreshDialog(null);
@@ -937,6 +781,53 @@ export function App() {
937
781
  void loadCostSummary();
938
782
  }, [costs?.currency, currency, loadCostSummary]);
939
783
 
784
+ const loadMoreTraceTasks = useCallback(
785
+ async (loadAll = false, reset = false): Promise<OperationsProjection["tasks"]> => {
786
+ if (traceTasksLoadingRef.current) return traceTasksRef.current;
787
+ if (reset) {
788
+ traceTaskCursorRef.current = { offset: 0, stageIndex: 0 };
789
+ traceTasksRef.current = [];
790
+ setTraceTasks([]);
791
+ setTraceTasksHasMore(true);
792
+ }
793
+ if (traceTaskCursorRef.current.stageIndex >= traceTaskSearchStages.length)
794
+ return traceTasksRef.current;
795
+
796
+ traceTasksLoadingRef.current = true;
797
+ setTraceTasksLoading(true);
798
+ try {
799
+ do {
800
+ const cursor = traceTaskCursorRef.current;
801
+ const stage = traceTaskSearchStages[cursor.stageIndex];
802
+ if (stage === undefined) break;
803
+ const page = await api.operationsBoard(
804
+ { from: null, to: null },
805
+ stage,
806
+ cursor.offset,
807
+ { kind: "all-tasks" },
808
+ undefined,
809
+ traceabilityTaskPageSize,
810
+ );
811
+ const updated = appendTraceabilityTaskPage({
812
+ cursor,
813
+ page,
814
+ tasks: traceTasksRef.current,
815
+ });
816
+ traceTasksRef.current = updated.tasks;
817
+ setTraceTasks(traceTasksRef.current);
818
+ traceTaskCursorRef.current = updated.cursor;
819
+ if (page.tasks.length > 0 && !loadAll) break;
820
+ } while (traceTaskCursorRef.current.stageIndex < traceTaskSearchStages.length);
821
+ setTraceTasksHasMore(traceTaskCursorRef.current.stageIndex < traceTaskSearchStages.length);
822
+ return traceTasksRef.current;
823
+ } finally {
824
+ traceTasksLoadingRef.current = false;
825
+ setTraceTasksLoading(false);
826
+ }
827
+ },
828
+ [api, setTraceTasks],
829
+ );
830
+
940
831
  const selectDashboardView = async (nextView: DashboardView) => {
941
832
  setDashboardView(nextView);
942
833
  window.scrollTo({ left: 0, top: 0 });
@@ -946,18 +837,13 @@ export function App() {
946
837
  costSummaryAbortRef.current?.abort();
947
838
  }
948
839
  if (nextView === "traceability") {
949
- let candidates = traceTasks.length > 0 ? traceTasks : (operations?.tasks ?? []);
840
+ let candidates = traceTasks;
950
841
  if (candidates.length === 0) {
951
842
  const requestVersion = boardRequestVersionRef.current;
952
843
  // Traceability is a global task selector, not a temporal work-board view.
953
- for (const stage of traceTaskSearchStages) {
954
- const page = await api.operationsBoard({ from: null, to: null }, stage, 0);
955
- if (requestVersion !== boardRequestVersionRef.current) return;
956
- if (page.tasks.length === 0) continue;
957
- candidates = page.tasks;
958
- setTraceTasks(page.tasks);
959
- break;
960
- }
844
+ candidates = await loadMoreTraceTasks(false, true);
845
+ if (requestVersion !== boardRequestVersionRef.current) return;
846
+ setTraceTasks(candidates);
961
847
  }
962
848
  const ordered = candidates.toSorted(
963
849
  (a, b) =>
@@ -1029,13 +915,7 @@ export function App() {
1029
915
  // prevents every tab from briefly presenting zero/empty placeholders while
1030
916
  // its coherent replacement snapshot or page is still in flight.
1031
917
  const globalLoadingPending =
1032
- periodTransitionPending ||
1033
- (currency === "USD" && costs?.currency !== currency) ||
1034
- (loadingArea !== null && loadingArea !== "costs") ||
1035
- costSurfaceLoading ||
1036
- operationsSurfaceLoading ||
1037
- entityPage.loading ||
1038
- Object.values(boardStates).some((state) => state.loading);
918
+ periodTransitionPending || (currency === "USD" && costs?.currency !== currency);
1039
919
  // The stale snapshot is useful only while the initial screen still waits
1040
920
  // for data. Once Operations has arrived, the normal dashboard is the
1041
921
  // clearest confirmation that it opened; do not leave a duplicate toast.
@@ -1123,6 +1003,7 @@ export function App() {
1123
1003
  onCurrencyChange: setCurrency,
1124
1004
  onLoadingChange: setCostSurfaceLoading,
1125
1005
  onLocaleChange: changeDashboardLocale,
1006
+ onLoadMoreTraceTasks: loadMoreTraceTasks,
1126
1007
  onOpenTrace: (taskId) => void openTrace(taskId),
1127
1008
  onRefresh: () => setRefreshDialog("choose"),
1128
1009
  onRetry: retryLastLoad,
@@ -1136,6 +1017,8 @@ export function App() {
1136
1017
  selectedTraceTaskId,
1137
1018
  trace,
1138
1019
  traceLoadingTaskId,
1020
+ traceTasksHasMore,
1021
+ traceTasksLoading,
1139
1022
  traceTasks,
1140
1023
  })}
1141
1024
  capabilityNavigation={capabilityNavigation}
@@ -1174,6 +1057,7 @@ export function App() {
1174
1057
  void loadOperationsLifecyclePage(view);
1175
1058
  else void loadOperationsDetails();
1176
1059
  }}
1060
+ onLoadMacroMetrics={() => void loadOperationsDetails()}
1177
1061
  onEntityPageChange={(offset) => {
1178
1062
  if (entityPageKind === "changes" || entityPageKind === "decisions")
1179
1063
  void loadOperationsLifecyclePage(entityPageKind, offset);
@@ -1181,7 +1065,10 @@ export function App() {
1181
1065
  }}
1182
1066
  onEntityFiltersChange={loadFilteredOperationsPage}
1183
1067
  onBoardFiltersChange={loadFilteredBoard}
1184
- onWorkListFiltersChange={loadFilteredWorkList}
1068
+ onWorkListFiltersChange={loadWorkListFilters}
1069
+ onWorkListPageChange={(offset) =>
1070
+ void loadWorkListPage(workListFiltersRef.current, offset)
1071
+ }
1185
1072
  onBoardTypeChange={(kind) =>
1186
1073
  loadFilteredBoard({
1187
1074
  ...boardFiltersRef.current,
@@ -1189,12 +1076,13 @@ export function App() {
1189
1076
  })
1190
1077
  }
1191
1078
  onWorkListTypeChange={(kind) =>
1192
- void loadFilteredWorkList({
1079
+ void loadWorkListPage({
1193
1080
  ...workListFiltersRef.current,
1194
1081
  kind: kind === "all" ? "" : kind,
1195
1082
  })
1196
1083
  }
1197
1084
  onLoadMoreBoard={(stage) => void loadMoreBoard(stage)}
1085
+ workListPage={workListPage}
1198
1086
  statusPage={(stage, kind) => overviewStatusPages[overviewStatusPageKey(stage, kind)]}
1199
1087
  onLoadStatusPage={(stage, kind, offset) =>
1200
1088
  void loadOverviewStatusPage(stage, kind, offset)
@@ -1223,8 +1111,11 @@ export function App() {
1223
1111
  operationsDetailAbortRef.current = null;
1224
1112
  operationsPageAbortRef.current?.abort();
1225
1113
  operationsPageAbortRef.current = null;
1114
+ resetWorkListPage();
1226
1115
  ++operationsPageRequestVersionRef.current;
1227
1116
  boardRequestVersionRef.current += 1;
1117
+ for (const controller of boardAbortControllersRef.current.values()) controller.abort();
1118
+ boardAbortControllersRef.current.clear();
1228
1119
  boardInFlightRef.current.clear();
1229
1120
  boardInitialPageRef.current.clear();
1230
1121
  boardLoadedRef.current = {};
@@ -1264,8 +1155,6 @@ export function App() {
1264
1155
  closeDocument={closeDocument}
1265
1156
  costLocale={costLocale}
1266
1157
  documentDetail={documentDetail}
1267
- error={error}
1268
- failedArea={failedArea}
1269
1158
  helpOpen={helpOpen}
1270
1159
  loadingArea={dashboardView === "cost-monitor" && costs === null ? null : loadingArea}
1271
1160
  operations={renderedOperations}
@@ -1277,7 +1166,6 @@ export function App() {
1277
1166
  traceLoadingTaskId={traceLoadingTaskId}
1278
1167
  onCloseHelp={() => setHelpOpen(false)}
1279
1168
  onCloseTrace={() => setTrace(null)}
1280
- onDismissError={() => setError(null)}
1281
1169
  onDismissReconciliation={() => setReconciliationResult(null)}
1282
1170
  onOpenDocument={(kind, id) => void openDocument(kind, id)}
1283
1171
  onOpenTrace={(taskId) => void openTrace(taskId)}
@@ -1285,7 +1173,6 @@ export function App() {
1285
1173
  onOpenTraceMacro={openTraceMacro}
1286
1174
  onRefreshCancel={() => setRefreshDialog(null)}
1287
1175
  onRefreshFromDialog={(reconcileOpenWork) => void refreshFromDialog(reconcileOpenWork)}
1288
- onRetry={retryLastLoad}
1289
1176
  setTraceLink={(value) => setTraceLink(value)}
1290
1177
  />
1291
1178
  </PeriodTransitionShell>