@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
@@ -32,11 +32,7 @@ import {
32
32
  type OperationDatePreset,
33
33
  type OperationDateRange,
34
34
  } from "./operation-date-range.js";
35
- import {
36
- filterStatusLabel,
37
- type OperationsView,
38
- statusesForView,
39
- } from "./operations-page-filters.js";
35
+ import type { OperationsView } from "./operations-page-filters.js";
40
36
  import { macrosWithPeriodActivity } from "./operations-period-scope.js";
41
37
  import { matchesQuery } from "./operations-query.js";
42
38
  import { viewLabels } from "./operations-view-labels.js";
@@ -49,7 +45,7 @@ import {
49
45
  } from "./period-summary.js";
50
46
  import { periodSummaryPopulation } from "./period-summary-population.js";
51
47
  import { scopeRunsToEntities } from "./run-scope.js";
52
- import { type OperationsLocale, riskLabel } from "./status-labels.js";
48
+ import { riskLabel } from "./status-labels.js";
53
49
  import {
54
50
  matchesTaskOrigin,
55
51
  type TaskOrigin,
@@ -98,7 +94,7 @@ export function OperationsPage({
98
94
  onOpenDocument,
99
95
  onOpenTask,
100
96
  onPriorityChange,
101
- onDetailDataRequest,
97
+ onLoadMacroMetrics,
102
98
  entityPage,
103
99
  onEntityPageChange,
104
100
  onEntityFiltersChange,
@@ -106,6 +102,8 @@ export function OperationsPage({
106
102
  onWorkListFiltersChange,
107
103
  onBoardTypeChange,
108
104
  onWorkListTypeChange,
105
+ onWorkListPageChange,
106
+ workListPage,
109
107
  onLoadMoreBoard,
110
108
  onLoadStatusPage,
111
109
  statusPage,
@@ -190,24 +188,6 @@ export function OperationsPage({
190
188
  showFilterLoading();
191
189
  const nextWorkListType = workListTypeOnViewChange(nextView);
192
190
  if (nextWorkListType !== null) onWorkListTypeChange?.(nextWorkListType);
193
- // Calendar reports are served by the compact canonical daily summary;
194
- // they must not hydrate entity detail merely to render month/year rolls.
195
- if (
196
- ![
197
- "work-kanban",
198
- "work-list",
199
- "daily",
200
- "monthly",
201
- "yearly",
202
- "runs",
203
- "conversations",
204
- "executions",
205
- "changes",
206
- "decisions",
207
- ].includes(nextView)
208
- ) {
209
- onDetailDataRequest?.(nextView);
210
- }
211
191
  setView(nextView);
212
192
  setStatusFilter("");
213
193
  setRiskFilter("");
@@ -250,10 +230,6 @@ export function OperationsPage({
250
230
  statusFilter,
251
231
  view,
252
232
  ]);
253
- const availableStatuses = statusesForView(data, view);
254
- const supportsStatus = !["decisions", "daily", "monthly", "yearly"].includes(view);
255
- const supportsRisk = view === "work-kanban" || view === "work-list" || view === "changes";
256
- const supportsOrigin = view === "work-kanban" || view === "work-list";
257
233
  // Only work views interpret a status option as a canonical work stage.
258
234
  // Runs, Changes and Executions use their respective persisted statuses.
259
235
  const hasEntityStageStatus =
@@ -673,8 +649,6 @@ export function OperationsPage({
673
649
  <OperationsPageLoading locale={locale} />
674
650
  ) : (
675
651
  <>
676
- {/* <OperationsOverview runs={runs} tasks={tasks} specs={specs} prds={prds} /> */}
677
- {/* <section className="dashboard-global-controls"></section> */}
678
652
  <OperationsPageOverview
679
653
  capabilityNavigation={capabilityNavigation}
680
654
  currency={currency}
@@ -701,6 +675,7 @@ export function OperationsPage({
701
675
  onLoadStatusPage={onLoadStatusPage}
702
676
  classificationPage={classificationPage}
703
677
  onLoadClassificationPage={onLoadClassificationPage}
678
+ onLoadMacroMetrics={onLoadMacroMetrics}
704
679
  updatePeriod={updatePeriod}
705
680
  />
706
681
 
@@ -732,6 +707,11 @@ export function OperationsPage({
732
707
  status: statusFilter,
733
708
  risk: riskFilter,
734
709
  origin: originFilter,
710
+ ...(view === "work-list" &&
711
+ workListPage !== undefined &&
712
+ workListPage.typeFilter !== "all"
713
+ ? { kind: workListPage.typeFilter }
714
+ : {}),
735
715
  })
736
716
  }
737
717
  view={`operations-${view}`}
@@ -757,6 +737,7 @@ export function OperationsPage({
757
737
  onEntityPageChange={onEntityPageChange}
758
738
  onLoadMoreBoard={onLoadMoreBoard}
759
739
  onWorkListTypeChange={onWorkListTypeChange}
740
+ onWorkListPageChange={onWorkListPageChange}
760
741
  onOpenDocument={onOpenDocument}
761
742
  onOpenTask={onOpenTask}
762
743
  onPriorityChange={onPriorityChange}
@@ -766,6 +747,7 @@ export function OperationsPage({
766
747
  specs={specs}
767
748
  summaryPopulation={summaryPopulation}
768
749
  tasks={tasks}
750
+ workListPage={workListPage}
769
751
  view={view}
770
752
  />
771
753
  </>
@@ -781,18 +763,3 @@ export function OperationsPage({
781
763
  export function shouldRenderOperationsContent(loading: boolean): boolean {
782
764
  return !loading;
783
765
  }
784
-
785
- function _OperationsPageLoading({ locale }: { locale: OperationsLocale }) {
786
- return (
787
- <section
788
- aria-busy="true"
789
- aria-live="polite"
790
- className="operations-content-skeleton"
791
- role="status"
792
- >
793
- <span>
794
- {locale === "pt-BR" ? "Carregando o período selecionado…" : "Loading selected period…"}
795
- </span>
796
- </section>
797
- );
798
- }
@@ -28,6 +28,7 @@ export function OperationsPageOverview({
28
28
  onLoadStatusPage,
29
29
  classificationPage,
30
30
  onLoadClassificationPage,
31
+ onLoadMacroMetrics,
31
32
  prds,
32
33
  query,
33
34
  resolveRunCost,
@@ -55,6 +56,7 @@ export function OperationsPageOverview({
55
56
  onLoadStatusPage: OverviewProps["onLoadStatusPage"];
56
57
  classificationPage: OverviewProps["classificationPage"];
57
58
  onLoadClassificationPage: OverviewProps["onLoadClassificationPage"];
59
+ onLoadMacroMetrics: OverviewProps["onLoadMacroMetrics"];
58
60
  prds: NonNullable<OverviewProps["prds"]>;
59
61
  query: string;
60
62
  resolveRunCost: OverviewProps["resolveRunCost"];
@@ -93,6 +95,7 @@ export function OperationsPageOverview({
93
95
  onLoadStatusPage={onLoadStatusPage}
94
96
  classificationPage={classificationPage}
95
97
  onLoadClassificationPage={onLoadClassificationPage}
98
+ onLoadMacroMetrics={onLoadMacroMetrics}
96
99
  prds={prds}
97
100
  runs={runs}
98
101
  resolveRunCost={resolveRunCost}
@@ -0,0 +1,43 @@
1
+ import { createElement } from "react";
2
+ import { renderToStaticMarkup } from "react-dom/server";
3
+ import { describe, expect, it } from "vitest";
4
+ import { PagedWorkList } from "./PagedWorkList.js";
5
+
6
+ describe("PagedWorkList", () => {
7
+ it("renders the factual developer column without object coercion", () => {
8
+ const markup = renderToStaticMarkup(
9
+ createElement(PagedWorkList, {
10
+ loading: false,
11
+ locale: "pt-BR",
12
+ onPageChange: () => undefined,
13
+ onTypeChange: () => undefined,
14
+ page: {
15
+ error: null,
16
+ hasMore: false,
17
+ limit: 10,
18
+ loading: false,
19
+ offset: 0,
20
+ rows: [
21
+ {
22
+ developers: [
23
+ { account_id: "199126185", login_snapshot: "zaip-ai" },
24
+ { account_id: "200", login_snapshot: null },
25
+ ],
26
+ id: "TASK-1",
27
+ kind: "task",
28
+ risk: "standard",
29
+ status: "executing",
30
+ title: "List developer identities",
31
+ },
32
+ ],
33
+ total: 1,
34
+ typeFilter: "all",
35
+ },
36
+ }),
37
+ );
38
+
39
+ expect(markup).toContain("Desenvolvedor");
40
+ expect(markup).toContain("zaip-ai (199126185); 200");
41
+ expect(markup).not.toContain("[object Object]");
42
+ });
43
+ });
@@ -0,0 +1,181 @@
1
+ import { DataTable, formatCompactNumber, formatCurrency } from "@zaip-ai/dashboard-ui";
2
+ import { formatDeveloperIdentities } from "./developer-identities.js";
3
+ import { formatRoundedDuration } from "./format-rounded-duration.js";
4
+ import type { OperationsLocale } from "./status-labels.js";
5
+ import { WorkTypeFilters } from "./UnifiedWorkBoard.js";
6
+ import type { WorkTypeFilter } from "./work-board-model.js";
7
+
8
+ export type PagedWorkListRow = Record<string, unknown>;
9
+ export type PagedWorkListPage = {
10
+ offset: number;
11
+ limit: number;
12
+ total: number | null;
13
+ hasMore: boolean;
14
+ typeFilter: WorkTypeFilter;
15
+ rows: readonly PagedWorkListRow[];
16
+ loading: boolean;
17
+ error: string | null;
18
+ };
19
+
20
+ function text(value: unknown, fallback = "—") {
21
+ return typeof value === "string" && value.length > 0 ? value : fallback;
22
+ }
23
+
24
+ function number(value: unknown): number | null {
25
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
26
+ }
27
+
28
+ function workKindLabel(value: unknown, locale: OperationsLocale) {
29
+ const kind = text(value, "");
30
+ const labels =
31
+ locale === "pt-BR"
32
+ ? { task: "Tarefas", "standalone-task": "Tarefa Avulsa", prd: "PRD", spec: "SPEC" }
33
+ : { task: "Tasks", "standalone-task": "Standalone Task", prd: "PRD", spec: "SPEC" };
34
+ return kind === "task" || kind === "standalone-task" || kind === "prd" || kind === "spec"
35
+ ? labels[kind]
36
+ : text(value);
37
+ }
38
+
39
+ /**
40
+ * Bounded list projection. It intentionally does not reuse UnifiedWorkList:
41
+ * that component requires all PRD/SPEC/Task relations in memory and therefore
42
+ * turns a visual tab into an unbounded collection request.
43
+ */
44
+ export function PagedWorkList({
45
+ loading,
46
+ locale,
47
+ onPageChange,
48
+ onTypeChange,
49
+ page,
50
+ }: {
51
+ loading: boolean;
52
+ locale: OperationsLocale;
53
+ onPageChange: (offset: number) => void;
54
+ onTypeChange: (kind: WorkTypeFilter) => void;
55
+ page: PagedWorkListPage;
56
+ }) {
57
+ return (
58
+ <section
59
+ aria-busy={loading || undefined}
60
+ className="operations-unified-work operations-work-list"
61
+ >
62
+ <WorkTypeFilters locale={locale} onChange={onTypeChange} value={page.typeFilter} />
63
+ <div className="operations-work-list-table">
64
+ <DataTable
65
+ columns={[
66
+ {
67
+ key: "item",
68
+ label: locale === "pt-BR" ? "Item" : "Item",
69
+ render: (row) => (
70
+ <span className="operations-work-list-identity">
71
+ <strong>{text(row.title, text(row.id))}</strong>
72
+ <small>{text(row.id)}</small>
73
+ </span>
74
+ ),
75
+ sortValue: (row) => text(row.title, text(row.id)),
76
+ },
77
+ {
78
+ key: "status",
79
+ label: "Status",
80
+ render: (row) => text(row.status),
81
+ sortValue: (row) => text(row.status),
82
+ },
83
+ {
84
+ key: "type",
85
+ label: locale === "pt-BR" ? "Tipo" : "Type",
86
+ render: (row) => workKindLabel(row.kind ?? row.entity_kind, locale),
87
+ sortValue: (row) => text(row.kind ?? row.entity_kind),
88
+ },
89
+ {
90
+ key: "risk",
91
+ label: locale === "pt-BR" ? "Risco" : "Risk",
92
+ render: (row) => text(row.risk),
93
+ sortValue: (row) => text(row.risk),
94
+ },
95
+ {
96
+ key: "developers",
97
+ label: locale === "pt-BR" ? "Desenvolvedor" : "Developer",
98
+ render: (row) => formatDeveloperIdentities(row.developers),
99
+ sortValue: (row) => formatDeveloperIdentities(row.developers),
100
+ },
101
+ {
102
+ key: "time",
103
+ label: locale === "pt-BR" ? "Tempo" : "Time",
104
+ render: (row) => {
105
+ const duration = number(row.total_duration);
106
+ return duration === null ? "—" : formatRoundedDuration(duration);
107
+ },
108
+ sortValue: (row) => number(row.total_duration),
109
+ align: "right",
110
+ },
111
+ {
112
+ key: "tokens",
113
+ label: "Tokens",
114
+ render: (row) => {
115
+ const tokens = number(row.total_tokens);
116
+ return tokens === null ? "—" : formatCompactNumber(tokens);
117
+ },
118
+ sortValue: (row) => number(row.total_tokens),
119
+ align: "right",
120
+ },
121
+ {
122
+ key: "cost",
123
+ label: locale === "pt-BR" ? "Custo" : "Cost",
124
+ render: (row) => {
125
+ const cost = number(row.total_cost_brl);
126
+ return cost === null ? "—" : formatCurrency(cost, "BRL");
127
+ },
128
+ sortValue: (row) => number(row.total_cost_brl),
129
+ align: "right",
130
+ },
131
+ ]}
132
+ defaultSort={{ key: "item", direction: "asc" }}
133
+ emptyMessage={
134
+ loading
135
+ ? locale === "pt-BR"
136
+ ? "Carregando itens…"
137
+ : "Loading items…"
138
+ : locale === "pt-BR"
139
+ ? "Nenhum item de trabalho encontrado."
140
+ : "No work items found."
141
+ }
142
+ locale={locale}
143
+ rowKey={(row) => text(row.id)}
144
+ rows={page.rows}
145
+ scrollLabel={
146
+ locale === "pt-BR" ? "Lista paginada de itens de trabalho." : "Paged work item list."
147
+ }
148
+ sortable
149
+ />
150
+ </div>
151
+ <nav
152
+ aria-label={locale === "pt-BR" ? "Paginação da lista de trabalho" : "Work list pagination"}
153
+ className="ui-table-pagination"
154
+ >
155
+ {page.error ? <span role="alert">{page.error}</span> : null}
156
+ {loading ? (
157
+ <span role="status">{locale === "pt-BR" ? "Atualizando…" : "Updating…"}</span>
158
+ ) : null}
159
+ <button
160
+ disabled={loading || page.offset === 0}
161
+ onClick={() => onPageChange(Math.max(0, page.offset - page.limit))}
162
+ type="button"
163
+ >
164
+ {locale === "pt-BR" ? "Anterior" : "Previous"}
165
+ </button>
166
+ <output aria-live="polite">
167
+ {page.total === null
168
+ ? "…"
169
+ : `${page.offset + (page.rows.length === 0 ? 0 : 1)}–${Math.min(page.offset + page.limit, page.total)} ${locale === "pt-BR" ? "de" : "of"} ${page.total}`}
170
+ </output>
171
+ <button
172
+ disabled={loading || !page.hasMore}
173
+ onClick={() => onPageChange(page.offset + page.limit)}
174
+ type="button"
175
+ >
176
+ {locale === "pt-BR" ? "Próxima" : "Next"}
177
+ </button>
178
+ </nav>
179
+ </section>
180
+ );
181
+ }
@@ -11,17 +11,18 @@ describe("buildWorkListRows", () => {
11
11
  expect(formatWorkListDuration(0, "cancelled", "pt-BR")).toBe("0 seg");
12
12
  });
13
13
 
14
- it("keeps the operational list to its eight standard columns", () => {
14
+ it("keeps the operational list columns including factual developers", () => {
15
15
  const source = readFileSync(
16
16
  fileURLToPath(new URL("./UnifiedWorkList.tsx", import.meta.url)),
17
17
  "utf8",
18
18
  );
19
19
  const keys = [...source.matchAll(/key: "([^"]+)"/g)].map((match) => match[1]);
20
- expect(keys.slice(0, 8)).toEqual([
20
+ expect(keys.slice(0, 9)).toEqual([
21
21
  "item",
22
22
  "status",
23
23
  "type",
24
24
  "risk",
25
+ "developers",
25
26
  "progress",
26
27
  "time",
27
28
  "tokens",
@@ -31,6 +32,7 @@ describe("buildWorkListRows", () => {
31
32
  expect(source).toContain('label: "Status"');
32
33
  expect(source).toContain('label: locale === "pt-BR" ? "Tipo" : "Type"');
33
34
  expect(source).toContain('label: locale === "pt-BR" ? "Risco" : "Risk"');
35
+ expect(source).toContain('label: locale === "pt-BR" ? "Desenvolvedor" : "Developer"');
34
36
  expect(source).toContain('label: locale === "pt-BR" ? "Progresso" : "Progress"');
35
37
  expect(source).toContain('label: locale === "pt-BR" ? "Tempo" : "Time"');
36
38
  expect(source).toContain('label: "Tokens"');
@@ -6,6 +6,7 @@ import type {
6
6
  MacroProjection,
7
7
  RunProjection,
8
8
  } from "../contracts.js";
9
+ import { formatDeveloperIdentities } from "./developer-identities.js";
9
10
  import { formatRoundedDuration } from "./format-rounded-duration.js";
10
11
  import { MacroPlanningDialog } from "./MacroPlanningDialog.js";
11
12
  import { formatDisplayedDuration, operationalDurationMs } from "./operation-duration.js";
@@ -130,6 +131,18 @@ export function UnifiedWorkList({
130
131
  ),
131
132
  sortValue: ({ risk }) => risk,
132
133
  },
134
+ {
135
+ key: "developers",
136
+ label: locale === "pt-BR" ? "Desenvolvedor" : "Developer",
137
+ render: ({ item }) =>
138
+ formatDeveloperIdentities(
139
+ (item.row as unknown as { developers?: unknown }).developers,
140
+ ),
141
+ sortValue: ({ item }) =>
142
+ formatDeveloperIdentities(
143
+ (item.row as unknown as { developers?: unknown }).developers,
144
+ ),
145
+ },
133
146
  {
134
147
  key: "progress",
135
148
  label: locale === "pt-BR" ? "Progresso" : "Progress",
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { formatDeveloperIdentities } from "./developer-identities.js";
3
+
4
+ describe("formatDeveloperIdentities", () => {
5
+ it("renders factual multiple identities without coercing objects", () => {
6
+ expect(
7
+ formatDeveloperIdentities([
8
+ { account_id: "199126185", login_snapshot: "zaip-ai" },
9
+ { account_id: "200", login_snapshot: null },
10
+ ]),
11
+ ).toBe("zaip-ai (199126185); 200");
12
+ });
13
+
14
+ it("keeps missing or malformed developer data explicit", () => {
15
+ expect(formatDeveloperIdentities(undefined)).toBe("—");
16
+ expect(formatDeveloperIdentities([{ account_id: 1, login_snapshot: "wrong" }])).toBe("—");
17
+ });
18
+ });
@@ -0,0 +1,30 @@
1
+ export type DeveloperIdentity = Readonly<{
2
+ account_id: string;
3
+ login_snapshot: string | null;
4
+ }>;
5
+
6
+ function isDeveloperIdentity(value: unknown): value is DeveloperIdentity {
7
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
8
+ const row = value as Record<string, unknown>;
9
+ return (
10
+ typeof row.account_id === "string" &&
11
+ (typeof row.login_snapshot === "string" || row.login_snapshot === null)
12
+ );
13
+ }
14
+
15
+ /**
16
+ * The projection preserves the server's factual, account-ordered identities.
17
+ * It deliberately does not fall back to task.owner, which has different semantics.
18
+ */
19
+ export function formatDeveloperIdentities(value: unknown): string {
20
+ if (!Array.isArray(value)) return "—";
21
+ const identities = value.filter(isDeveloperIdentity);
22
+ if (identities.length === 0) return "—";
23
+ return identities
24
+ .map(({ account_id, login_snapshot }) =>
25
+ login_snapshot === null || login_snapshot.length === 0
26
+ ? account_id
27
+ : `${login_snapshot} (${account_id})`,
28
+ )
29
+ .join("; ");
30
+ }
@@ -12,6 +12,7 @@ export interface ExecutionMetricRun {
12
12
  | "observed"
13
13
  | "reconciled"
14
14
  | "legacy_inferred"
15
+ | "shared_creation_allocation"
15
16
  | "estimated"
16
17
  | "unavailable"
17
18
  | undefined;
@@ -190,6 +190,7 @@ it("uses the compact work schema for Kanban and Work List", () => {
190
190
  "title",
191
191
  "status",
192
192
  "risk",
193
+ "developers",
193
194
  "occurred_at",
194
195
  "duration_hours",
195
196
  "tokens",
@@ -207,6 +208,10 @@ it("normalizes Tasks and macros into the same populated work columns", () => {
207
208
  status: "executing",
208
209
  risk: "standard",
209
210
  occurred_at: "2026-08-21T00:00:00.000Z",
211
+ developers: [
212
+ { account_id: "199126185", login_snapshot: "zaip-ai" },
213
+ { account_id: "200", login_snapshot: null },
214
+ ],
210
215
  telemetry: { duration_ms: 3_600_000, tokens: 123, cost_brl: 4.5 },
211
216
  },
212
217
  {
@@ -239,6 +244,7 @@ it("normalizes Tasks and macros into the same populated work columns", () => {
239
244
  title: "Export Task",
240
245
  status: "executing",
241
246
  risk: "standard",
247
+ developers: "zaip-ai (199126185); 200",
242
248
  occurred_at: "2026-08-21T00:00:00.000Z",
243
249
  duration_hours: 1,
244
250
  tokens: 123,
@@ -250,6 +256,7 @@ it("normalizes Tasks and macros into the same populated work columns", () => {
250
256
  title: "Export Spec",
251
257
  status: "planning",
252
258
  risk: null,
259
+ developers: "—",
253
260
  occurred_at: "2026-08-20T00:00:00.000Z",
254
261
  duration_hours: 2,
255
262
  tokens: 456,
@@ -261,6 +268,7 @@ it("normalizes Tasks and macros into the same populated work columns", () => {
261
268
  title: "Export PRD",
262
269
  status: "ready",
263
270
  risk: null,
271
+ developers: "—",
264
272
  occurred_at: "2026-08-19T00:00:00.000Z",
265
273
  duration_hours: 3,
266
274
  tokens: 789,
@@ -1,6 +1,7 @@
1
1
  import { createExportSnapshot } from "@zaip-ai/dashboard-contracts";
2
2
  import { Download } from "lucide-react";
3
3
  import { useEffect, useRef, useState } from "react";
4
+ import { formatDeveloperIdentities } from "../developer-identities.js";
4
5
  import { ExportProgressToast, ExportSuccessToast } from "./ExportProgressToast.js";
5
6
  import { ExportController, type ExportState } from "./export-session.js";
6
7
 
@@ -44,6 +45,7 @@ export const WORK_EXPORT_COLUMNS = [
44
45
  "title",
45
46
  "status",
46
47
  "risk",
48
+ "developers",
47
49
  "occurred_at",
48
50
  "duration_hours",
49
51
  "tokens",
@@ -208,6 +210,7 @@ export function exportWorkRows(
208
210
  // the canonical work stage for a Task.
209
211
  status: row.work_status ?? row.status ?? row.lifecycle_status,
210
212
  risk: row.risk ?? null,
213
+ developers: formatDeveloperIdentities(row.developers),
211
214
  occurred_at: row.occurred_at ?? row.created_at ?? row.updated_at ?? null,
212
215
  duration_hours: durationMs === null ? null : durationMs / 3_600_000,
213
216
  tokens:
@@ -36,13 +36,22 @@ describe("Excel export layout", () => {
36
36
 
37
37
  it("uses the paginated SQLite source for every Operations table, not the visible page", () => {
38
38
  expect(operationsPage).toContain("detailExportSource?.(view, {");
39
- const app = readFileSync(
40
- new URL("../../../../../apps/frontend/src/App.tsx", import.meta.url),
39
+ const exportSource = readFileSync(
40
+ new URL("../../../../../apps/frontend/src/use-operations-detail-export.ts", import.meta.url),
41
41
  "utf8",
42
42
  );
43
- expect(app).toContain('executions: "operations_executions"');
44
- expect(app).toContain("totalRows: firstPage.total_count");
45
- expect(app).toContain("if (nextOffset >= page.total_count) return");
43
+ const pagination = readFileSync(
44
+ new URL("../../../../../apps/frontend/src/sqlite-page-export.ts", import.meta.url),
45
+ "utf8",
46
+ );
47
+ expect(exportSource).toContain('executions: "operations_executions"');
48
+ expect(exportSource).toContain("totalRows: firstPage.total_count");
49
+ expect(pagination).toContain("if (!page.has_more || nextOffset >= page.total_count) return");
50
+ });
51
+
52
+ it("exports factual developer identities with the work-list rows", () => {
53
+ expect(action).toContain('"developers"');
54
+ expect(action).toContain("formatDeveloperIdentities(row.developers)");
46
55
  });
47
56
 
48
57
  it("keeps the Operations action outside the tab nav and fixed at the bar end", () => {
@@ -1,3 +1,4 @@
1
+ export * from "./DeveloperAttributionPanel.js";
1
2
  export * from "./EntityDetailsDialog.js";
2
3
  export * from "./EntityTables.js";
3
4
  export * from "./export/ExcelExportAction.js";
@@ -40,9 +40,10 @@ describe("Operations persisted aggregate display", () => {
40
40
  const overview = readFileSync(new URL("OperationsOverview.tsx", import.meta.url), "utf8");
41
41
 
42
42
  expect(overview).toContain("overviewMetrics?.duration_ms ??");
43
- expect(overview).toContain(
44
- "const totalTokensMetric = overviewMetrics?.tokens ?? allPhaseMetrics.tokens",
45
- );
43
+ expect(overview).toContain("const totalTokensMetric = scopedOverviewMetric(");
44
+ expect(overview).toContain("selectedMacroTotals?.tokens,");
45
+ expect(overview).toContain("const totalDurationMetric = scopedOverviewMetric(");
46
+ expect(overview).toContain("selectedMacroTotals?.durationMs,");
46
47
  expect(overview).toContain("const totalCostMetric =");
47
48
  expect(overview).toContain(
48
49
  "durationMs: totalDurationMetric, tokens: totalTokensMetric, costBrl: totalCostMetric",
@@ -43,7 +43,7 @@
43
43
  }
44
44
 
45
45
  .operations-toolbar-field > span {
46
- color: #64748b;
46
+ color: var(--muted);
47
47
  font-size: 0.51rem;
48
48
  font-weight: 700;
49
49
  letter-spacing: 0.08em;