@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
@@ -1,19 +1,19 @@
1
+ import { createHash } from "node:crypto";
1
2
  import { mkdir, mkdtemp, readdir, readFile, rename, utimes, writeFile } from "node:fs/promises";
2
3
  import { join, resolve } from "node:path";
3
4
  import { DatabaseSync } from "node:sqlite";
4
5
  import { afterEach, describe, expect, it } from "vitest";
5
6
  import { createDashboardApp, projectAllTimeTopTasks } from "./server.js";
7
+ import { expectFastCostPagesMatchCanonical } from "./sqlite-cost-fast-page-parity.test-support.js";
6
8
  import {
7
9
  allocateAttributedTokenActiveMs,
8
10
  rebuildSqliteReadModel,
9
11
  SqliteReadModelFileSystem,
10
12
  sourceFingerprint,
11
13
  } from "./sqlite-read-model.js";
14
+ import { expectPersistedFirstFoldCaches } from "./sqlite-read-model-cache.test-support.js";
12
15
 
13
16
  const roots: string[] = [];
14
- // Windows can deny SQLite's sidecar files below the system TEMP directory.
15
- // Keep disposable fixtures in the workspace-local test area instead; each
16
- // test still receives its own root and never touches the live read model.
17
17
  const sqliteTestTempRoot = join(
18
18
  resolve(import.meta.dirname, "../../../../../.."),
19
19
  ".tmp",
@@ -32,7 +32,6 @@ afterEach(async () => {
32
32
  ),
33
33
  );
34
34
  });
35
-
36
35
  describe("SQLite dashboard read model", () => {
37
36
  it("snapshots sorted eligible canonical sources once for fingerprinting and ingestion", async () => {
38
37
  const root = await createSqliteTestRoot();
@@ -63,6 +62,31 @@ describe("SQLite dashboard read model", () => {
63
62
  await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({ files: 2 });
64
63
  });
65
64
 
65
+ it("accepts only the canonical C3D4 historical assignment among lifecycle files", async () => {
66
+ const root = await createSqliteTestRoot();
67
+ roots.push(root);
68
+ const attributionRoot = join(
69
+ root,
70
+ ".agents",
71
+ "records",
72
+ "lifecycle",
73
+ "historical-developer-attribution",
74
+ );
75
+ await mkdir(attributionRoot, { recursive: true });
76
+ await mkdir(join(root, ".agents", "records", "lifecycle", "views"), { recursive: true });
77
+ await mkdir(join(root, ".agents", "config"), { recursive: true });
78
+ await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n");
79
+ await writeFile(join(attributionRoot, "HDA-2026-08-29-ZAIP-AI-C3D4.json"), "{}\n");
80
+ await writeFile(join(root, ".agents", "records", "lifecycle", "views", "foreign.json"), "{}\n");
81
+
82
+ const snapshot = await sourceFingerprint(root);
83
+ expect(snapshot.candidates.map((candidate) => candidate.source)).toContain(
84
+ ".agents/records/lifecycle/historical-developer-attribution/HDA-2026-08-29-ZAIP-AI-C3D4.json",
85
+ );
86
+ expect(snapshot.candidates.map((candidate) => candidate.source)).not.toContain(
87
+ ".agents/records/lifecycle/views/foreign.json",
88
+ );
89
+ });
66
90
  it("uses a current-schema seed after a canonical change", async () => {
67
91
  const root = await createSqliteTestRoot();
68
92
  roots.push(root);
@@ -175,7 +199,7 @@ describe("SQLite dashboard read model", () => {
175
199
  }
176
200
  });
177
201
 
178
- it("does not serve a schema 59 seed during the one-time SQLite cache migration", async () => {
202
+ it("does not serve a prior-schema seed during the one-time SQLite cache migration", async () => {
179
203
  const root = await createSqliteTestRoot();
180
204
  roots.push(root);
181
205
  await mkdir(join(root, ".agents", "records", "tasks"), { recursive: true });
@@ -189,15 +213,15 @@ describe("SQLite dashboard read model", () => {
189
213
  await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({ cache: "rebuilt" });
190
214
  const cacheDirectory = join(root, ".local", "dashboard-sqlite", "cache");
191
215
  const current = (await readdir(cacheDirectory)).find(
192
- (entry) => entry.startsWith("v60-") && entry.endsWith(".sqlite"),
216
+ (entry) => /^v\d+-/.test(entry) && entry.endsWith(".sqlite"),
193
217
  );
194
218
  expect(current).toBeDefined();
195
- const legacy = join(cacheDirectory, current!.replace("v60-", ""));
219
+ const legacy = join(cacheDirectory, current!.replace(/^v\d+-/, ""));
196
220
  await rename(join(cacheDirectory, current!), legacy);
197
221
  const oldSeed = new DatabaseSync(legacy);
198
222
  oldSeed
199
223
  .prepare(
200
- "UPDATE zaip_aios_activities SET payload_json=json_set(payload_json, '$.value', '59') WHERE payload_type='metadata' AND json_extract(payload_json, '$.key')='schema_version'",
224
+ "UPDATE zaip_aios_activities SET payload_json=json_set(payload_json, '$.value', '65') WHERE payload_type='metadata' AND json_extract(payload_json, '$.key')='schema_version'",
201
225
  )
202
226
  .run();
203
227
  oldSeed.close();
@@ -345,8 +369,8 @@ created_at: 2026-08-10T11:01:00.000Z
345
369
  total_count: 1,
346
370
  rows: [{ id: "DEC-1", title: "Canonical decision", scope_id: "CHG-1" }],
347
371
  });
348
- // Unfiltered Operations pagination is served from one immutable
349
- // generation-local query result, while retaining the public page contract.
372
+ // Operations pagination stays inside SQLite even with no filters: the
373
+ // browser receives only its requested page, never the whole work union.
350
374
  const workListFirst = filesystem.viewPage("operations_work_list", { limit: 1, offset: 0 });
351
375
  const workListNext = filesystem.viewPage("operations_work_list", { limit: 1, offset: 1 });
352
376
  expect(workListFirst.total_count).toBe(workListNext.total_count);
@@ -618,6 +642,7 @@ created_at: 2026-08-10T11:01:00.000Z
618
642
  );
619
643
  await rebuildSqliteReadModel(root);
620
644
  const filesystem = new SqliteReadModelFileSystem(root);
645
+ expectFastCostPagesMatchCanonical(root, filesystem);
621
646
  expect(filesystem.dailyPeriods({ from: null, to: null })["2026-08-05"]).toMatchObject({
622
647
  runs: 1,
623
648
  usage: {
@@ -981,13 +1006,41 @@ created_at: 2026-08-10T11:01:00.000Z
981
1006
  roots.push(root);
982
1007
  await mkdir(join(root, ".agents", "records", "tasks", "2026", "08"), { recursive: true });
983
1008
  await mkdir(join(root, ".agents", "records", "runs", "2026", "08"), { recursive: true });
1009
+ await mkdir(
1010
+ join(
1011
+ root,
1012
+ ".agents",
1013
+ "records",
1014
+ "changes",
1015
+ "2026",
1016
+ "08",
1017
+ "CHG-CANONICAL",
1018
+ "artifacts",
1019
+ "tests",
1020
+ ),
1021
+ { recursive: true },
1022
+ );
1023
+ await mkdir(
1024
+ join(
1025
+ root,
1026
+ ".agents",
1027
+ "records",
1028
+ "changes",
1029
+ "2026",
1030
+ "08",
1031
+ "CHG-CANONICAL",
1032
+ "artifacts",
1033
+ "evidence",
1034
+ ),
1035
+ { recursive: true },
1036
+ );
984
1037
  await mkdir(join(root, ".agents", "config"), { recursive: true });
985
1038
  await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n");
986
1039
  await writeFile(
987
1040
  join(root, ".agents", "records", "tasks", "2026", "08", "TASK-CANONICAL.md"),
988
- "---\nid: TASK-CANONICAL\ntitle: Titulo semantico canonico\nstatus: ready\nrisk: standard\ncreated_at: 2026-08-08T12:00:00.000Z\n---\n# Titulo semantico canonico\n",
1041
+ "---\nid: TASK-CANONICAL\ntitle: Titulo semantico canonico\nstatus: completed\ncompleted_run_id: RUN-CANONICAL\nrisk: standard\ncreated_at: 2026-08-08T12:00:00.000Z\n---\n# Titulo semantico canonico\n",
989
1042
  );
990
- const run = (id: string, taskId: string, tokens: number) => [
1043
+ const run = (id: string, taskId: string, tokens: number, changeId: string | null = null) => [
991
1044
  {
992
1045
  schema_version: 2,
993
1046
  event_id: `${id}:1`,
@@ -1008,6 +1061,14 @@ created_at: 2026-08-10T11:01:00.000Z
1008
1061
  client: "codex",
1009
1062
  agent: "agent",
1010
1063
  agent_name: "agent",
1064
+ developer_identity: {
1065
+ schema_version: 1,
1066
+ provider: "github",
1067
+ account_id: "42",
1068
+ login_snapshot: "dev-fixture",
1069
+ verified_at: "2026-08-08T12:00:00.000Z",
1070
+ attribution_source: "verified_local_account",
1071
+ },
1011
1072
  provider: "openai",
1012
1073
  model: "gpt-a",
1013
1074
  reasoning_effort: null,
@@ -1018,7 +1079,7 @@ created_at: 2026-08-10T11:01:00.000Z
1018
1079
  task_id: taskId,
1019
1080
  spec_id: null,
1020
1081
  prd_id: null,
1021
- change_id: null,
1082
+ change_id: changeId,
1022
1083
  parent_run_id: null,
1023
1084
  continuation_of_run_id: null,
1024
1085
  retry_of_run_id: null,
@@ -1073,7 +1134,7 @@ created_at: 2026-08-10T11:01:00.000Z
1073
1134
  ];
1074
1135
  await writeFile(
1075
1136
  join(root, ".agents", "records", "runs", "2026", "08", "RUN-CANONICAL.jsonl"),
1076
- `${run("RUN-CANONICAL", "TASK-CANONICAL", 7)
1137
+ `${run("RUN-CANONICAL", "TASK-CANONICAL", 7, "CHG-CANONICAL")
1077
1138
  .map((row) => JSON.stringify(row))
1078
1139
  .join("\n")}\n`,
1079
1140
  );
@@ -1083,6 +1144,36 @@ created_at: 2026-08-10T11:01:00.000Z
1083
1144
  .map((row) => JSON.stringify(row))
1084
1145
  .join("\n")}\n`,
1085
1146
  );
1147
+ await writeFile(
1148
+ join(
1149
+ root,
1150
+ ".agents",
1151
+ "records",
1152
+ "changes",
1153
+ "2026",
1154
+ "08",
1155
+ "CHG-CANONICAL",
1156
+ "artifacts",
1157
+ "tests",
1158
+ "TEST-CANONICAL.md",
1159
+ ),
1160
+ "---\nid: TEST-CANONICAL\nkind: test\ntask_id: TASK-CANONICAL\nchange_id: CHG-CANONICAL\nrun_id: RUN-CANONICAL\nexecuted_at: 2026-08-08T12:00:00.000Z\nstatus: passed\n---\n# Test\n",
1161
+ );
1162
+ await writeFile(
1163
+ join(
1164
+ root,
1165
+ ".agents",
1166
+ "records",
1167
+ "changes",
1168
+ "2026",
1169
+ "08",
1170
+ "CHG-CANONICAL",
1171
+ "artifacts",
1172
+ "evidence",
1173
+ "EVD-CANONICAL.md",
1174
+ ),
1175
+ "---\nid: EVD-CANONICAL\ntask_id: TASK-CANONICAL\nchange_id: CHG-CANONICAL\nrun_id: RUN-CANONICAL\nobserved_at: 2026-08-08T12:00:00.000Z\nstatus: passed\n---\n# Evidence\n",
1176
+ );
1086
1177
 
1087
1178
  await rebuildSqliteReadModel(root);
1088
1179
  const snapshot = new DatabaseSync(resolve(root, ".local/dashboard-sqlite/read-model.sqlite"), {
@@ -1092,7 +1183,7 @@ created_at: 2026-08-10T11:01:00.000Z
1092
1183
  snapshot
1093
1184
  .prepare("SELECT value FROM zaip_vw_read_model_metadata WHERE key='schema_version'")
1094
1185
  .get(),
1095
- ).toEqual({ value: "60" });
1186
+ ).toEqual({ value: "70" });
1096
1187
  snapshot.close();
1097
1188
  const filesystem = new SqliteReadModelFileSystem(root);
1098
1189
  try {
@@ -1119,881 +1210,366 @@ created_at: 2026-08-10T11:01:00.000Z
1119
1210
  total_cost_brl: 0.55,
1120
1211
  }),
1121
1212
  );
1122
- } finally {
1123
- filesystem.close();
1124
- }
1125
- });
1126
-
1127
- it("keeps a multi-provider and multi-model Run visible to both filtered financial and duration facts", async () => {
1128
- const root = await createSqliteTestRoot();
1129
- roots.push(root);
1130
- await mkdir(join(root, ".agents", "records", "runs", "2026", "08"), { recursive: true });
1131
- await mkdir(join(root, ".agents", "config"), { recursive: true });
1132
- await mkdir(join(root, ".agents", "config", "agents"), { recursive: true });
1133
- await mkdir(join(root, ".agents", "config", "pricing"), { recursive: true });
1134
- await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n");
1135
- await writeFile(
1136
- join(root, ".agents", "config", "agents", "catalog.yaml"),
1137
- "agents:\n - id: agent-catalog\n codex_name: agent\n persona: { nome: ana, cargo: quality_engineer }\n role: reviewer\n",
1138
- );
1139
- await writeFile(
1140
- join(root, ".agents", "config", "pricing", "models.json"),
1141
- JSON.stringify({
1142
- schema_version: 1,
1143
- updated_at: "2026-08-04T00:00:00.000Z",
1144
- source: "fixture",
1145
- disclaimer: "fixture",
1146
- models: [
1147
- {
1148
- id: "gpt-a",
1149
- provider: "openai",
1150
- aliases: [],
1151
- input_per_million_usd: 2,
1152
- cached_input_per_million_usd: 0.2,
1153
- output_per_million_usd: 8,
1154
- reasoning_per_million_usd: 8,
1155
- reasoning_billed_separately: false,
1156
- long_context_threshold_tokens: null,
1157
- long_context_input_multiplier: 1,
1158
- long_context_output_multiplier: 1,
1159
- source_label: "fixture-openai",
1160
- source_url: "https://example.test/openai",
1161
- notes: [],
1162
- },
1163
- {
1164
- id: "claude-b",
1165
- provider: "anthropic",
1166
- aliases: [],
1167
- input_per_million_usd: 3,
1168
- cached_input_per_million_usd: 0.3,
1169
- output_per_million_usd: 12,
1170
- reasoning_per_million_usd: null,
1171
- reasoning_billed_separately: false,
1172
- long_context_threshold_tokens: null,
1173
- long_context_input_multiplier: 1,
1174
- long_context_output_multiplier: 1,
1175
- source_label: "fixture-anthropic",
1176
- source_url: "https://example.test/anthropic",
1177
- notes: [],
1178
- },
1179
- ],
1180
- }),
1181
- );
1182
- const started = {
1183
- schema_version: 2,
1184
- event_id: "RUN-MULTI:1",
1185
- run_id: "RUN-MULTI",
1186
- sequence: 1,
1187
- occurred_at: "2026-08-04T12:00:00.000Z",
1188
- type: "run.started",
1189
- attribution_status: "attributed",
1190
- phase: "execution",
1191
- run_role: "orchestrator",
1192
- run_purpose: "execution",
1193
- requires_finalizer: false,
1194
- execution_kind: "delivery",
1195
- execution_eligibility: ["delivery"],
1196
- entrypoint: "task",
1197
- work_type: "new",
1198
- storage_mode: "tracked_sanitized",
1199
- client: "codex",
1200
- agent: "agent",
1201
- agent_name: "agent",
1202
- provider: "mixed",
1203
- model: "mixed",
1204
- reasoning_effort: null,
1205
- client_thread_id: "multi",
1206
- client_turn_id: "multi",
1207
- conversation_id: "CONV-MULTI",
1208
- execution_id: "EXEC-MULTI",
1209
- task_id: "TASK-MULTI",
1210
- spec_id: null,
1211
- prd_id: null,
1212
- change_id: null,
1213
- parent_run_id: null,
1214
- continuation_of_run_id: null,
1215
- retry_of_run_id: null,
1216
- agent_invocation_id: "AINV-MULTI",
1217
- root_agent_invocation_id: "AINV-MULTI",
1218
- parent_agent_invocation_id: null,
1219
- invocation_kind: "orchestrator",
1220
- delegation_depth: 0,
1221
- };
1222
- const usage = (
1223
- sequence: number,
1224
- provider: string,
1225
- model: string,
1226
- tokens: number,
1227
- brl: number,
1228
- ) => ({
1229
- schema_version: 2,
1230
- event_id: `RUN-MULTI:${sequence}`,
1231
- run_id: "RUN-MULTI",
1232
- sequence,
1233
- occurred_at: "2026-08-04T12:00:01.000Z",
1234
- type: "usage.recorded",
1235
- phase: "execution",
1236
- activity_kind: "model_usage",
1237
- classification_source: "explicit",
1238
- tokens: {
1239
- input: tokens,
1240
- cached_input: 0,
1241
- output: 0,
1242
- reasoning: 0,
1243
- total: tokens,
1244
- source: "provider_reported",
1245
- },
1246
- cost: { usd: brl / 5, brl, fx_rate: 5 },
1247
- provider,
1248
- model,
1249
- source_segment_key: `${provider}-${model}`,
1250
- model_call_id: `MCALL-${sequence}`,
1251
- runtime: { reasoning_effort: null, service_tier: null },
1252
- supersedes_event_id: null,
1253
- source_started_at: "2026-08-04T12:00:00.000Z",
1254
- source_finished_at: "2026-08-04T12:01:00.000Z",
1255
- duration_ms: null,
1256
- duration_provenance: null,
1257
- });
1258
- const finished = {
1259
- schema_version: 2,
1260
- event_id: "RUN-MULTI:5",
1261
- run_id: "RUN-MULTI",
1262
- sequence: 5,
1263
- occurred_at: "2026-08-04T12:01:00.000Z",
1264
- type: "run.finished",
1265
- phase: "execution",
1266
- status: "completed",
1267
- duration_ms: 60_000,
1268
- duration_provenance: "observed",
1269
- };
1270
- const mixedNullSegment = {
1271
- ...usage(4, "openai", "gpt-a", 0, 0),
1272
- event_id: "RUN-MULTI:4",
1273
- provider: null,
1274
- model: null,
1275
- source_segment_key: "mixed-null",
1276
- model_call_id: "MCALL-MIXED-NULL",
1277
- };
1278
- await writeFile(
1279
- join(root, ".agents", "records", "runs", "2026", "08", "RUN-MULTI.jsonl"),
1280
- `${[started, usage(2, "openai", "gpt-a", 10, 5), usage(3, "anthropic", "claude-b", 20, 10), mixedNullSegment, finished].map((row) => JSON.stringify(row)).join("\n")}\n`,
1281
- );
1282
- const unavailableStarted = {
1283
- ...started,
1284
- event_id: "RUN-UNAVAILABLE:1",
1285
- run_id: "RUN-UNAVAILABLE",
1286
- occurred_at: "2026-08-04T14:00:00.000Z",
1287
- client_turn_id: "unavailable",
1288
- conversation_id: "CONV-UNAVAILABLE",
1289
- execution_id: "EXEC-UNAVAILABLE",
1290
- task_id: "TASK-UNAVAILABLE",
1291
- agent_invocation_id: "AINV-UNAVAILABLE",
1292
- root_agent_invocation_id: "AINV-UNAVAILABLE",
1293
- provider: "unavailable",
1294
- model: "unavailable",
1295
- };
1296
- const unavailableFinished = {
1297
- ...finished,
1298
- event_id: "RUN-UNAVAILABLE:2",
1299
- run_id: "RUN-UNAVAILABLE",
1300
- sequence: 3,
1301
- occurred_at: "2026-08-04T14:01:00.000Z",
1302
- };
1303
- const unavailableUsage = {
1304
- ...usage(2, "openai", "gpt-a", 0, 0),
1305
- event_id: "RUN-UNAVAILABLE:usage",
1306
- run_id: "RUN-UNAVAILABLE",
1307
- sequence: 2,
1308
- occurred_at: "2026-08-04T14:00:01.000Z",
1309
- provider: null,
1310
- model: null,
1311
- source_started_at: "2026-08-04T14:00:00.000Z",
1312
- source_finished_at: "2026-08-04T14:01:00.000Z",
1313
- source_segment_key: "unknown-segment",
1314
- model_call_id: "MCALL-UNAVAILABLE",
1315
- };
1316
- await writeFile(
1317
- join(root, ".agents", "records", "runs", "2026", "08", "RUN-UNAVAILABLE.jsonl"),
1318
- `${[unavailableStarted, unavailableUsage, unavailableFinished].map((row) => JSON.stringify(row)).join("\n")}\n`,
1319
- );
1320
- // It is a canonical activity but not an Agent Invocation. Cost Monitor
1321
- // must not blend this population into its token/cost/session rate.
1322
- const {
1323
- agent_invocation_id: _invocation,
1324
- root_agent_invocation_id: _rootInvocation,
1325
- parent_agent_invocation_id: _parentInvocation,
1326
- ...unassistedBase
1327
- } = started;
1328
- const unassistedStarted = {
1329
- ...unassistedBase,
1330
- event_id: "RUN-UNASSISTED:1",
1331
- run_id: "RUN-UNASSISTED",
1332
- occurred_at: "2026-08-04T16:00:00.000Z",
1333
- client_turn_id: "unassisted",
1334
- conversation_id: "CONV-UNASSISTED",
1335
- execution_id: "EXEC-MULTI",
1336
- task_id: "TASK-MULTI",
1337
- };
1338
- const unassistedUsage = {
1339
- ...usage(2, "openai", "gpt-a", 1_000, 500),
1340
- event_id: "RUN-UNASSISTED:2",
1341
- run_id: "RUN-UNASSISTED",
1342
- occurred_at: "2026-08-04T16:00:01.000Z",
1343
- source_started_at: "2026-08-04T16:00:00.000Z",
1344
- source_finished_at: "2026-08-04T16:01:00.000Z",
1345
- source_segment_key: "unassisted-segment",
1346
- };
1347
- await writeFile(
1348
- join(root, ".agents", "records", "runs", "2026", "08", "RUN-UNASSISTED.jsonl"),
1349
- `${[unassistedStarted, unassistedUsage, { ...finished, event_id: "RUN-UNASSISTED:3", run_id: "RUN-UNASSISTED", sequence: 3 }].map((row) => JSON.stringify(row)).join("\n")}\n`,
1350
- );
1351
- await rebuildSqliteReadModel(root);
1352
- const aggregateDatabase = new DatabaseSync(
1353
- resolve(root, ".local/dashboard-sqlite/read-model.sqlite"),
1354
- {
1355
- readOnly: true,
1356
- },
1357
- );
1358
- try {
1359
- const aggregates = aggregateDatabase
1360
- .prepare(`SELECT
1361
- json_extract(payload_json, '$.dimension') AS dimension,
1362
- json_extract(payload_json, '$.key') AS key,
1363
- json_extract(payload_json, '$.schema_version') AS schema_version,
1364
- json_extract(payload_json, '$.total_cost_brl') AS total_cost_brl
1365
- FROM zaip_aios_activities
1366
- WHERE payload_type = 'cost_dimension_aggregate_v1'`)
1367
- .all();
1368
- expect(aggregates).toEqual(
1369
- expect.arrayContaining([
1370
- expect.objectContaining({
1371
- dimension: "provider",
1372
- key: "openai",
1373
- schema_version: 1,
1374
- total_cost_brl: 505,
1375
- }),
1376
- expect.objectContaining({
1377
- dimension: "model",
1378
- key: "gpt-a",
1379
- schema_version: 1,
1380
- total_cost_brl: 505,
1381
- }),
1382
- ]),
1383
- );
1384
- expect(aggregates.map((row) => row.key)).toEqual(expect.arrayContaining(["unavailable"]));
1385
- } finally {
1386
- aggregateDatabase.close();
1387
- }
1388
- const filesystem = new SqliteReadModelFileSystem(root);
1389
- expect(
1390
- filesystem.viewPage("cost_monitor_daily", { from: "2026-08-04", to: "2026-08-04" }).rows[0],
1391
- ).toMatchObject({ total_tokens: 1_030, total_cost_brl: 515 });
1392
- // The public overview view backs /api/v2/sqlite-views. It must not leak
1393
- // Cost Monitor retains all measurable financial activities, including
1394
- // historical/unassisted telemetry without an Agent Invocation id.
1395
- const publicOverview = filesystem.viewPage("cost_monitor_overview_view", {});
1396
- expect(publicOverview.rows).toHaveLength(3);
1397
- expect(publicOverview.rows).toEqual(
1398
- expect.arrayContaining([
1399
- expect.objectContaining({
1400
- period_kind: "day",
1401
- total_run_count: 3,
1402
- invocation_count: 3,
1403
- total_tokens: 1_030,
1404
- total_cost_brl: 515,
1405
- }),
1406
- expect.objectContaining({
1407
- period_kind: "month",
1408
- total_run_count: 3,
1409
- invocation_count: 3,
1410
- total_tokens: 1_030,
1411
- total_cost_brl: 515,
1412
- }),
1213
+ const developers = filesystem.developerCostAggregate({
1214
+ from: null,
1215
+ to: null,
1216
+ accountIds: ["42"],
1217
+ });
1218
+ expect(developers.rows).toEqual([
1413
1219
  expect.objectContaining({
1414
- period_kind: "year",
1415
- total_run_count: 3,
1416
- invocation_count: 3,
1417
- total_tokens: 1_030,
1418
- total_cost_brl: 515,
1220
+ account_id: "42",
1221
+ login_snapshot: "dev-fixture",
1222
+ prd_count: expect.any(Number),
1223
+ spec_count: expect.any(Number),
1224
+ task_count: 2,
1225
+ run_count: 2,
1226
+ test_count: 1,
1227
+ evidence_count: 1,
1228
+ total_duration_ms: expect.any(Number),
1229
+ completed_task_count: 1,
1230
+ total_cost_brl: 0.9,
1231
+ token_covered_runs: 2,
1232
+ usd_covered_runs: 2,
1233
+ brl_covered_runs: 2,
1234
+ qualification: "verified",
1235
+ completed_tasks: [
1236
+ expect.objectContaining({
1237
+ id: "TASK-CANONICAL",
1238
+ status: "completed",
1239
+ completed_run_id: "RUN-CANONICAL",
1240
+ delivered_by: { account_id: "42" },
1241
+ contributors: [expect.objectContaining({ account_id: "42" })],
1242
+ }),
1243
+ ],
1419
1244
  }),
1420
- ]),
1421
- );
1422
- const allAgentGroups = filesystem.viewPage("cost_monitor_zaip_agents", {
1423
- limit: 20,
1424
- offset: 0,
1425
- });
1426
- const allCostTotals = publicOverview.rows.find((row) => row.period_kind === "day");
1427
- if (allCostTotals === undefined) throw new Error("Expected the daily Cost Monitor overview");
1428
- expect(
1429
- allAgentGroups.rows.reduce((total, row) => total + Number(row.invocation_count ?? 0), 0),
1430
- ).toBe(allCostTotals.total_run_count);
1431
- expect(
1432
- allAgentGroups.rows.reduce((total, row) => total + Number(row.total_tokens ?? 0), 0),
1433
- ).toBe(allCostTotals?.total_tokens);
1434
- expect(
1435
- allAgentGroups.rows.reduce((total, row) => total + Number(row.total_cost_brl ?? 0), 0),
1436
- ).toBe(allCostTotals?.total_cost_brl);
1437
- expect(
1438
- allAgentGroups.rows.reduce((total, row) => total + Number(row.total_cost_usd ?? 0), 0),
1439
- ).toBe(allCostTotals.total_cost_usd);
1440
- // Shared Cost Tempo is factual at the activity grain. It remains available
1441
- // in the agent-table total even where a multi-dimension invocation cannot
1442
- // be assigned to an individual Agent row.
1443
- expect(allCostTotals.cost_monitor_total_duration).toBe(120_000);
1444
- expect(allAgentGroups.totals).toMatchObject({
1445
- invocation_count: allCostTotals.total_run_count,
1446
- total_duration: 120_000,
1447
- total_tokens: allCostTotals.total_tokens,
1448
- total_cost_usd: allCostTotals.total_cost_usd,
1449
- total_cost_brl: allCostTotals.total_cost_brl,
1450
- });
1451
- for (const [providers, models] of [
1452
- [["openai"], ["gpt-a"]],
1453
- [["anthropic"], ["claude-b"]],
1454
- ] as const) {
1455
- const rows = filesystem.invocationCostRows({ from: null, to: null, providers, models });
1456
- expect(rows).toHaveLength(1);
1457
- // Membership is segment-based; once the invocation matches, its
1458
- // canonical invocation totals remain intact rather than being split.
1459
- expect(rows[0]).toMatchObject({ total_tokens: 30, cost_brl: 15 });
1460
- expect([
1461
- ...filesystem.executionDurationByDay({ from: null, to: null, providers, models }).values(),
1462
- ]).toEqual([60_000]);
1463
- expect([
1464
- ...filesystem.canonicalRunCountByDay({ from: null, to: null, providers, models }).values(),
1465
- ]).toEqual([1]);
1466
- for (const view of [
1467
- "cost_monitor_daily",
1468
- "cost_monitor_monthly",
1469
- "cost_monitor_annual",
1470
- ] as const) {
1471
- const page = filesystem.viewPage(view, {
1472
- provider: providers[0],
1473
- model: models[0],
1474
- limit: 20,
1475
- offset: 0,
1476
- });
1477
- expect(page.rows[0]).toMatchObject({
1478
- total_run_count: 1,
1479
- total_tokens: 30,
1480
- total_cost_brl: 15,
1481
- });
1482
- }
1483
- const agents = filesystem.viewPage("cost_monitor_zaip_agents", {
1484
- provider: providers[0],
1485
- model: models[0],
1486
- query: "agent",
1487
- });
1488
- const financialRows = filesystem.costMonitorFinancialActivityRows({
1245
+ ]);
1246
+ expect(
1247
+ filesystem.developerCostAggregate({
1248
+ from: "2026-08-08",
1249
+ to: "2026-08-08",
1250
+ accountIds: ["42"],
1251
+ }).rows,
1252
+ ).toEqual([expect.objectContaining({ test_count: 1, evidence_count: 1 })]);
1253
+ expect(
1254
+ filesystem.dailyPeriods({ from: "2026-08-08", to: "2026-08-08" })["2026-08-08"],
1255
+ ).toMatchObject({ validations: 1, evidences: 1 });
1256
+ const operationsDevelopers = filesystem.operationsDeveloperAggregate({
1489
1257
  from: null,
1490
1258
  to: null,
1491
- providers,
1492
- models,
1259
+ accountIds: ["42"],
1493
1260
  });
1494
- const financialTotals = financialRows.reduce<{
1495
- invocation_count: number;
1496
- total_tokens: number;
1497
- total_cost_brl: number;
1498
- }>(
1499
- (total, row) => ({
1500
- invocation_count: total.invocation_count + 1,
1501
- total_tokens: total.total_tokens + Number(row.total_tokens ?? 0),
1502
- total_cost_brl: total.total_cost_brl + Number(row.cost_brl ?? 0),
1261
+ expect(operationsDevelopers.rows).toEqual([
1262
+ expect.objectContaining({
1263
+ account_id: "42",
1264
+ task_count: 2,
1265
+ completed_task_count: 1,
1266
+ status_counts: expect.objectContaining({ completed: 1 }),
1267
+ type_counts: { task: 1 },
1268
+ risk_counts: expect.any(Object),
1269
+ total_duration_ms: expect.any(Number),
1270
+ total_tokens: expect.any(Number),
1271
+ total_cost_brl: 0.9,
1503
1272
  }),
1504
- { invocation_count: 0, total_tokens: 0, total_cost_brl: 0 },
1505
- );
1506
- expect(agents.rows[0]).toMatchObject({
1507
- key: "agent",
1508
- persona: "ana",
1509
- job: "quality_engineer",
1510
- task_count: 1,
1511
- ...financialTotals,
1512
- });
1513
- expect(agents.totals).toMatchObject(financialTotals);
1514
- }
1515
- const crossed = { from: null, to: null, providers: ["openai"], models: ["claude-b"] };
1516
- expect(filesystem.invocationCostRows(crossed)).toHaveLength(0);
1517
- expect([...filesystem.executionDurationByDay(crossed).values()]).toEqual([]);
1518
- expect([...filesystem.canonicalRunCountByDay(crossed).values()]).toEqual([]);
1519
- expect(
1520
- filesystem.viewPage("cost_monitor_agent_invocations", {
1521
- provider: "openai",
1522
- model: "claude-b",
1523
- }).total_count,
1524
- ).toBe(0);
1525
- expect(
1526
- filesystem.viewPage("cost_monitor_zaip_agents", { provider: "openai", model: "claude-b" })
1527
- .total_count,
1528
- ).toBe(0);
1529
- for (const view of [
1530
- "cost_monitor_daily",
1531
- "cost_monitor_monthly",
1532
- "cost_monitor_annual",
1533
- ] as const) {
1534
- // Lifecycle buckets can remain present independently, but the crossed
1535
- // pair must contribute no invocation financial or Run facts.
1536
- const row = filesystem.viewPage(view, { provider: "openai", model: "claude-b" }).rows[0];
1537
- expect(row).toMatchObject({
1538
- total_run_count: 0,
1539
- total_duration: null,
1540
- total_tokens: null,
1541
- total_cost_brl: null,
1542
- });
1543
- }
1544
- for (const view of [
1545
- "cost_monitor_daily",
1546
- "cost_monitor_monthly",
1547
- "cost_monitor_annual",
1548
- ] as const) {
1549
- const originFiltered = filesystem.viewPage(view, { origin: "task" });
1550
- expect(originFiltered.rows[0]).toMatchObject({
1551
- prd_count: null,
1552
- spec_count: null,
1553
- task_count: null,
1554
- validation_count: null,
1555
- evidence_count: null,
1556
- });
1557
- expect(filesystem.viewPage(view, { workType: "new" }).total_count).toBe(0);
1558
- }
1559
- expect(filesystem.viewPage("cost_monitor_zaip_agents", { priority: "high" })).toMatchObject({
1560
- total_count: 0,
1561
- rows: [],
1562
- });
1563
- const providerGroups = filesystem.viewPage("cost_monitor_providers", { limit: 20, offset: 0 });
1564
- expect(providerGroups.rows).toEqual(
1565
- expect.arrayContaining([
1566
- expect.objectContaining({ key: "openai", total_tokens: 1_010, total_cost_brl: 505 }),
1567
- expect.objectContaining({ key: "anthropic", total_tokens: 20, total_cost_brl: 10 }),
1568
- ]),
1569
- );
1570
- expect(providerGroups.rows.map((row) => row.key)).toEqual(
1571
- expect.arrayContaining(["unavailable"]),
1572
- );
1573
- expect(
1574
- filesystem
1575
- .viewPage("cost_monitor_providers", { provider: "openai", model: "gpt-a" })
1576
- .rows.find((row) => row.key === "openai"),
1577
- ).toMatchObject({ total_tokens: 10, total_cost_brl: 5 });
1578
- expect(
1579
- filesystem.viewPage("cost_monitor_providers", { provider: "openai", model: "claude-b" }),
1580
- ).toMatchObject({ total_count: 0, rows: [] });
1581
- // A source segment can prove its financial facts, but an invocation with
1582
- // multiple observed providers cannot prove a provider-specific elapsed
1583
- // time. It must not manufacture a "mixed" bucket for that remainder.
1584
- const queriedProviderRows = filesystem.viewPage("cost_monitor_providers", {
1585
- query: "openai",
1586
- }).rows;
1587
- expect(queriedProviderRows).toEqual([
1588
- expect.objectContaining({ key: "openai", total_tokens: 10, total_cost_brl: 5 }),
1589
- ]);
1590
- const modelGroups = filesystem.viewPage("cost_monitor_models", { limit: 20, offset: 0 });
1591
- expect(modelGroups.rows).toEqual(
1592
- expect.arrayContaining([
1593
- expect.objectContaining({ key: "gpt-a", total_tokens: 1_010, total_cost_brl: 505 }),
1594
- expect.objectContaining({ key: "claude-b", total_tokens: 20, total_cost_brl: 10 }),
1595
- ]),
1596
- );
1597
- // First-fold transport is aggregate-only, but its overview chart must
1598
- // retain the segment-backed model rows instead of falling back to the
1599
- // empty availability metadata.
1600
- expect(filesystem.costMonitorSummaryAggregate({ from: null, to: null }).model_groups).toEqual(
1601
- expect.arrayContaining([
1602
- expect.objectContaining({ key: "gpt-a", total_tokens: 1_010, estimated_brl: 505 }),
1603
- expect.objectContaining({ key: "claude-b", total_tokens: 20, estimated_brl: 10 }),
1604
- ]),
1605
- );
1606
- expect(modelGroups.rows.map((row) => row.key)).toEqual(expect.arrayContaining(["unavailable"]));
1607
- const modelTotals = modelGroups.rows.reduce<{
1608
- invocations: number;
1609
- tasks: number;
1610
- duration: number;
1611
- tokens: number;
1612
- brl: number;
1613
- }>(
1614
- (total, row) => ({
1615
- invocations: total.invocations + Number(row.invocation_count ?? 0),
1616
- tasks: total.tasks + Number(row.task_count ?? 0),
1617
- duration: total.duration + Number(row.total_duration ?? 0),
1618
- tokens: total.tokens + Number(row.total_tokens ?? 0),
1619
- brl: total.brl + Number(row.total_cost_brl ?? 0),
1620
- }),
1621
- { invocations: 0, tasks: 0, duration: 0, tokens: 0, brl: 0 },
1622
- );
1623
- expect(modelTotals).toEqual({
1624
- invocations: 2,
1625
- tasks: 3,
1626
- duration: 60_000,
1627
- tokens: 1030,
1628
- brl: 515,
1629
- });
1630
- expect(filesystem.viewPage("cost_monitor_models", { query: "gpt-a" }).rows).toHaveLength(1);
1631
- expect(
1632
- filesystem.viewPage("cost_monitor_models", { provider: "openai", model: "gpt-a" }).rows[0],
1633
- ).toMatchObject({ key: "gpt-a", total_tokens: 1010, total_cost_brl: 505 });
1634
- expect(
1635
- filesystem.viewPage("cost_monitor_models", { provider: "openai", model: "claude-b" }),
1636
- ).toMatchObject({ total_count: 0, rows: [] });
1637
- expect(filesystem.viewPage("cost_monitor_models", { priority: "high" })).toMatchObject({
1638
- total_count: 0,
1639
- rows: [],
1640
- });
1641
- const unavailable = {
1642
- from: null,
1643
- to: null,
1644
- providers: ["unavailable"],
1645
- models: ["unavailable"],
1646
- };
1647
- const unavailableRows = filesystem.invocationCostRows(unavailable);
1648
- expect(unavailableRows).toHaveLength(1);
1649
- // Observed zero telemetry stays zero, while the missing provider/model
1650
- // attribute selects this segment rather than a literal sentinel value.
1651
- expect(unavailableRows[0]).toMatchObject({ total_tokens: 0, cost_brl: 0 });
1652
- // Execution-duration is an Operations compatibility aggregate and still
1653
- // includes the unassisted canonical Run. Cost Monitor retains its
1654
- // measurable financial activity as an unavailable historical fact.
1655
- expect([...filesystem.executionDurationByDay(unavailable).values()]).toEqual([60_000]);
1656
- expect([...filesystem.canonicalRunCountByDay(unavailable).values()]).toEqual([2]);
1657
- const unavailableInvocation = filesystem.viewPage("cost_monitor_agent_invocations", {
1658
- provider: "unavailable",
1659
- model: "unavailable",
1660
- });
1661
- expect(unavailableInvocation).toMatchObject({ total_count: 1 });
1662
- expect(unavailableInvocation.rows[0]).toMatchObject({ input_tokens: 0 });
1663
- for (const view of [
1664
- "cost_monitor_daily",
1665
- "cost_monitor_monthly",
1666
- "cost_monitor_annual",
1667
- ] as const) {
1668
- const row = filesystem.viewPage(view, { provider: "unavailable", model: "unavailable" })
1669
- .rows[0];
1670
- expect(row).toMatchObject({ total_run_count: 2, total_tokens: 1_000, total_cost_brl: 500 });
1273
+ ]);
1274
+ } finally {
1275
+ filesystem.close();
1671
1276
  }
1277
+ });
1672
1278
 
1673
- filesystem.close();
1674
- const sameModelStarted = {
1675
- ...started,
1676
- event_id: "RUN-SAME-MODEL:1",
1677
- run_id: "RUN-SAME-MODEL",
1678
- occurred_at: "2026-08-05T12:00:00.000Z",
1679
- client_turn_id: "same-model",
1680
- conversation_id: "CONV-SAME-MODEL",
1681
- execution_id: "EXEC-SAME-MODEL",
1682
- task_id: "TASK-SAME-MODEL",
1683
- agent_invocation_id: "AINV-SAME-MODEL",
1684
- root_agent_invocation_id: "AINV-SAME-MODEL",
1685
- provider: "mixed",
1686
- model: "gpt-a",
1687
- };
1688
- const sameModelUsage = (sequence: number, provider: string, tokens: number, brl: number) => ({
1689
- ...usage(sequence, provider, "gpt-a", tokens, brl),
1690
- event_id: `RUN-SAME-MODEL:${sequence}`,
1691
- run_id: "RUN-SAME-MODEL",
1692
- occurred_at: "2026-08-05T12:00:01.000Z",
1693
- source_started_at: "2026-08-05T12:00:00.000Z",
1694
- source_finished_at: "2026-08-05T12:01:00.000Z",
1695
- });
1696
- const sameModelFinished = {
1697
- ...finished,
1698
- event_id: "RUN-SAME-MODEL:4",
1699
- run_id: "RUN-SAME-MODEL",
1700
- sequence: 4,
1701
- occurred_at: "2026-08-05T12:01:00.000Z",
1702
- };
1279
+ it("qualifies factual developer deliveries without inventing missing completion or coverage", async () => {
1280
+ const root = await createSqliteTestRoot();
1281
+ roots.push(root);
1282
+ const runsRoot = join(root, ".agents", "records", "runs", "2026", "08");
1283
+ const tasksRoot = join(root, ".agents", "records", "tasks", "2026", "08");
1284
+ const assignmentsRoot = join(
1285
+ root,
1286
+ ".agents",
1287
+ "records",
1288
+ "lifecycle",
1289
+ "historical-developer-attribution",
1290
+ );
1291
+ await Promise.all([
1292
+ mkdir(runsRoot, { recursive: true }),
1293
+ mkdir(tasksRoot, { recursive: true }),
1294
+ mkdir(assignmentsRoot, { recursive: true }),
1295
+ mkdir(join(root, ".agents", "config"), { recursive: true }),
1296
+ ]);
1703
1297
  await writeFile(
1704
- join(root, ".agents", "records", "runs", "2026", "08", "RUN-SAME-MODEL.jsonl"),
1705
- `${[sameModelStarted, sameModelUsage(2, "openai", 3, 1.5), sameModelUsage(3, "anthropic", 4, 2), sameModelFinished].map((row) => JSON.stringify(row)).join("\n")}\n`,
1298
+ join(root, ".agents", "config", "project.yaml"),
1299
+ "zaip:\n enabled: true\n",
1300
+ "utf8",
1706
1301
  );
1707
- const durationRun = (
1302
+ const task = (id: string, status: string, completedRunId: string | null) =>
1303
+ `---\nid: ${id}\ntitle: ${id}\nstatus: ${status}${completedRunId === null ? "" : `\ncompleted_run_id: ${completedRunId}`}\nrisk: standard\ncreated_at: 2026-08-08T12:00:00.000Z\n---\n# ${id}\n`;
1304
+ await Promise.all([
1305
+ writeFile(
1306
+ join(tasksRoot, "TASK-DELIVERED.md"),
1307
+ task("TASK-DELIVERED", "completed", "RUN-DELIVERED"),
1308
+ ),
1309
+ writeFile(
1310
+ join(tasksRoot, "TASK-NO-COMPLETION.md"),
1311
+ task("TASK-NO-COMPLETION", "completed", null),
1312
+ ),
1313
+ writeFile(
1314
+ join(tasksRoot, "TASK-MISSING-RUN.md"),
1315
+ task("TASK-MISSING-RUN", "completed", "RUN-NOT-FOUND"),
1316
+ ),
1317
+ writeFile(
1318
+ join(tasksRoot, "TASK-NOT-COMPLETED.md"),
1319
+ task("TASK-NOT-COMPLETED", "executing", "RUN-NOT-COMPLETED"),
1320
+ ),
1321
+ writeFile(
1322
+ join(tasksRoot, "TASK-UNKNOWN-COVERAGE.md"),
1323
+ task("TASK-UNKNOWN-COVERAGE", "completed", null),
1324
+ ),
1325
+ writeFile(
1326
+ join(tasksRoot, "TASK-HISTORICAL.md"),
1327
+ task("TASK-HISTORICAL", "completed", "RUN-HISTORICAL"),
1328
+ ),
1329
+ ]);
1330
+ const stream = (
1708
1331
  id: string,
1332
+ taskId: string,
1333
+ accountId: string | null,
1709
1334
  day: string,
1710
- duration: number | null,
1711
- provenance: "reconciled" | "estimated",
1335
+ tokens: number | null,
1712
1336
  ) => {
1713
- const start = {
1714
- ...sameModelStarted,
1715
- event_id: `${id}:1`,
1716
- run_id: id,
1717
- occurred_at: `${day}T12:00:00.000Z`,
1718
- client_turn_id: id,
1719
- conversation_id: `CONV-${id}`,
1720
- execution_id: `EXEC-${id}`,
1721
- task_id: `TASK-${id}`,
1722
- agent_invocation_id: `AINV-${id}`,
1723
- root_agent_invocation_id: `AINV-${id}`,
1724
- };
1725
- const measured = {
1726
- ...usage(
1727
- 2,
1728
- "openai",
1729
- "gpt-a",
1730
- provenance === "estimated" ? 4_000_000 : 9,
1731
- provenance === "estimated" ? 0 : 4.5,
1732
- ),
1733
- event_id: `${id}:2`,
1734
- run_id: id,
1735
- occurred_at: `${day}T12:00:01.000Z`,
1736
- source_started_at: `${day}T12:00:00.000Z`,
1737
- source_finished_at: `${day}T12:01:00.000Z`,
1738
- ...(duration === null ? {} : { duration_ms: duration, duration_provenance: provenance }),
1739
- };
1740
- const end = {
1741
- ...finished,
1337
+ const identity =
1338
+ accountId === null
1339
+ ? null
1340
+ : {
1341
+ schema_version: 1,
1342
+ provider: "github",
1343
+ account_id: accountId,
1344
+ login_snapshot: `dev-${accountId}`,
1345
+ verified_at: `${day}T12:00:00.000Z`,
1346
+ attribution_source: "verified_local_account",
1347
+ };
1348
+ const records: Record<string, unknown>[] = [
1349
+ {
1350
+ schema_version: 2,
1351
+ event_id: `${id}:1`,
1352
+ run_id: id,
1353
+ sequence: 1,
1354
+ occurred_at: `${day}T12:00:00.000Z`,
1355
+ type: "run.started",
1356
+ attribution_status: "attributed",
1357
+ phase: "execution",
1358
+ run_role: "orchestrator",
1359
+ run_purpose: "execution",
1360
+ requires_finalizer: false,
1361
+ execution_kind: "delivery",
1362
+ execution_eligibility: ["delivery"],
1363
+ entrypoint: "task",
1364
+ work_type: "new",
1365
+ storage_mode: "tracked_sanitized",
1366
+ client: "codex",
1367
+ agent: "agent",
1368
+ agent_name: "agent",
1369
+ developer_identity: identity,
1370
+ provider: "openai",
1371
+ model: "gpt-a",
1372
+ reasoning_effort: null,
1373
+ client_thread_id: id,
1374
+ client_turn_id: id,
1375
+ conversation_id: `CONV-${id}`,
1376
+ execution_id: `EXEC-${id}`,
1377
+ task_id: taskId,
1378
+ spec_id: null,
1379
+ prd_id: null,
1380
+ change_id: null,
1381
+ parent_run_id: null,
1382
+ continuation_of_run_id: null,
1383
+ retry_of_run_id: null,
1384
+ agent_invocation_id: `AINV-${id}`,
1385
+ root_agent_invocation_id: `AINV-${id}`,
1386
+ parent_agent_invocation_id: null,
1387
+ invocation_kind: "orchestrator",
1388
+ delegation_depth: 0,
1389
+ },
1390
+ ];
1391
+ if (tokens !== null)
1392
+ records.push({
1393
+ schema_version: 2,
1394
+ event_id: `${id}:2`,
1395
+ run_id: id,
1396
+ sequence: 2,
1397
+ occurred_at: `${day}T12:00:30.000Z`,
1398
+ type: "usage.recorded",
1399
+ phase: "execution",
1400
+ activity_kind: "model_usage",
1401
+ classification_source: "explicit",
1402
+ tokens: {
1403
+ input: tokens,
1404
+ cached_input: 0,
1405
+ output: 0,
1406
+ reasoning: 0,
1407
+ total: tokens,
1408
+ source: "provider_reported",
1409
+ },
1410
+ cost: { usd: tokens / 100, brl: tokens / 20, fx_rate: 5 },
1411
+ provider: "openai",
1412
+ model: "gpt-a",
1413
+ source_segment_key: id,
1414
+ model_call_id: `MCALL-${id}`,
1415
+ runtime: { reasoning_effort: null, service_tier: null },
1416
+ supersedes_event_id: null,
1417
+ source_started_at: `${day}T12:00:00.000Z`,
1418
+ source_finished_at: `${day}T12:01:00.000Z`,
1419
+ duration_ms: null,
1420
+ duration_provenance: null,
1421
+ });
1422
+ records.push({
1423
+ schema_version: 2,
1742
1424
  event_id: `${id}:3`,
1743
1425
  run_id: id,
1744
- sequence: 3,
1426
+ sequence: records.length + 1,
1745
1427
  occurred_at: `${day}T12:01:00.000Z`,
1746
- ...(provenance === "estimated"
1747
- ? { duration_ms: null, duration_provenance: "unavailable" }
1748
- : {}),
1749
- };
1750
- return [start, measured, end];
1428
+ type: "run.finished",
1429
+ phase: "execution",
1430
+ status: "completed",
1431
+ duration_ms: 60_000,
1432
+ duration_provenance: "observed",
1433
+ });
1434
+ return `${records.map((record) => JSON.stringify(record)).join("\n")}\n`;
1751
1435
  };
1752
- await writeFile(
1753
- join(root, ".agents", "records", "runs", "2026", "08", "RUN-RECONCILED-MODEL.jsonl"),
1754
- `${durationRun("RUN-RECONCILED-MODEL", "2026-08-06", 45_000, "reconciled")
1755
- .map((row) => JSON.stringify(row))
1756
- .join("\n")}\n`,
1757
- );
1758
- await writeFile(
1759
- join(root, ".agents", "records", "runs", "2026", "08", "RUN-ESTIMATED-MODEL.jsonl"),
1760
- `${durationRun("RUN-ESTIMATED-MODEL", "2026-08-07", null, "estimated")
1761
- .map((row) => JSON.stringify(row))
1762
- .join("\n")}\n`,
1763
- );
1764
- const sharedTaskRun = (id: string, model: string, tokens: number, brl: number) => [
1765
- {
1766
- ...sameModelStarted,
1767
- event_id: `${id}:1`,
1768
- run_id: id,
1769
- occurred_at: "2026-08-08T12:00:00.000Z",
1770
- client_turn_id: id,
1771
- conversation_id: `CONV-${id}`,
1772
- execution_id: `EXEC-${id}`,
1773
- task_id: "TASK-CROSS-MODEL",
1774
- agent_invocation_id: `AINV-${id}`,
1775
- root_agent_invocation_id: `AINV-${id}`,
1776
- provider: "openai",
1777
- model,
1778
- },
1779
- {
1780
- ...usage(2, "openai", model, tokens, brl),
1781
- event_id: `${id}:2`,
1782
- run_id: id,
1783
- occurred_at: "2026-08-08T12:00:01.000Z",
1784
- source_started_at: "2026-08-08T12:00:00.000Z",
1785
- source_finished_at: "2026-08-08T12:01:00.000Z",
1786
- },
1787
- {
1788
- ...finished,
1789
- event_id: `${id}:3`,
1790
- run_id: id,
1791
- sequence: 3,
1792
- occurred_at: "2026-08-08T12:01:00.000Z",
1436
+ const delivered = stream("RUN-DELIVERED", "TASK-DELIVERED", "42", "2026-08-08", 10);
1437
+ const contributor = stream("RUN-CONTRIBUTOR", "TASK-DELIVERED", "99", "2026-08-08", 3);
1438
+ const noCompletion = stream("RUN-NO-COMPLETION", "TASK-NO-COMPLETION", "42", "2026-08-09", 4);
1439
+ const notCompleted = stream("RUN-NOT-COMPLETED", "TASK-NOT-COMPLETED", "42", "2026-08-09", 5);
1440
+ const unknownCoverage = stream(
1441
+ "RUN-UNKNOWN-COVERAGE",
1442
+ "TASK-UNKNOWN-COVERAGE",
1443
+ "42",
1444
+ "2026-08-09",
1445
+ null,
1446
+ );
1447
+ const historical = stream("RUN-HISTORICAL", "TASK-HISTORICAL", null, "2026-08-09", 2);
1448
+ await Promise.all([
1449
+ writeFile(join(runsRoot, "RUN-DELIVERED.jsonl"), delivered),
1450
+ writeFile(join(runsRoot, "RUN-CONTRIBUTOR.jsonl"), contributor),
1451
+ writeFile(join(runsRoot, "RUN-NO-COMPLETION.jsonl"), noCompletion),
1452
+ writeFile(join(runsRoot, "RUN-NOT-COMPLETED.jsonl"), notCompleted),
1453
+ writeFile(join(runsRoot, "RUN-UNKNOWN-COVERAGE.jsonl"), unknownCoverage),
1454
+ writeFile(join(runsRoot, "RUN-HISTORICAL.jsonl"), historical),
1455
+ ]);
1456
+ const historicalPath = ".agents/records/runs/2026/08/RUN-HISTORICAL.jsonl";
1457
+ const unsigned = {
1458
+ schema_version: 1,
1459
+ manifest_id: "HDA-FIXTURE",
1460
+ created_at: "2026-08-09T12:00:00.000Z",
1461
+ kind: "historical_developer_attribution",
1462
+ assignment: {
1463
+ schema_version: 1,
1464
+ provider: "github",
1465
+ account_id: "199126185",
1466
+ login_snapshot: "zaip-ai",
1467
+ attribution_source: "human_assigned",
1468
+ verified_at: null,
1793
1469
  },
1794
- ];
1795
- await writeFile(
1796
- join(root, ".agents", "records", "runs", "2026", "08", "RUN-TASK-GPT.jsonl"),
1797
- `${sharedTaskRun("RUN-TASK-GPT", "gpt-a", 5, 2.5)
1798
- .map((row) => JSON.stringify(row))
1799
- .join("\n")}\n`,
1800
- );
1801
- await writeFile(
1802
- join(root, ".agents", "records", "runs", "2026", "08", "RUN-TASK-CLAUDE.jsonl"),
1803
- `${sharedTaskRun("RUN-TASK-CLAUDE", "claude-b", 6, 3)
1804
- .map((row) => JSON.stringify(row))
1805
- .join("\n")}\n`,
1806
- );
1807
- const subrunStarted = {
1808
- ...sameModelStarted,
1809
- event_id: "RUN-PROVIDER-SUBRUN:1",
1810
- run_id: "RUN-PROVIDER-SUBRUN",
1811
- occurred_at: "2026-08-09T12:00:00.000Z",
1812
- client_turn_id: "provider-subrun",
1813
- conversation_id: "CONV-PROVIDER-SUBRUN",
1814
- execution_id: "EXEC-PROVIDER-SUBRUN",
1815
- task_id: "TASK-PROVIDER-SUBRUN",
1816
- agent_invocation_id: "AINV-PROVIDER-SUBRUN",
1817
- root_agent_invocation_id: "AINV-SAME-MODEL",
1818
- parent_agent_invocation_id: "AINV-SAME-MODEL",
1819
- parent_run_id: "RUN-SAME-MODEL",
1820
- run_role: "subagent",
1821
- invocation_kind: "delegated",
1822
- delegation_depth: 1,
1823
- provider: "openai",
1824
- model: "gpt-a",
1825
- };
1826
- const subrunUsage = {
1827
- ...usage(2, "openai", "gpt-a", 8, 4),
1828
- event_id: "RUN-PROVIDER-SUBRUN:2",
1829
- run_id: "RUN-PROVIDER-SUBRUN",
1830
- occurred_at: "2026-08-09T12:00:01.000Z",
1831
- source_started_at: "2026-08-09T12:00:00.000Z",
1832
- source_finished_at: "2026-08-09T12:00:30.000Z",
1833
- };
1834
- const subrunFinished = {
1835
- ...finished,
1836
- event_id: "RUN-PROVIDER-SUBRUN:3",
1837
- run_id: "RUN-PROVIDER-SUBRUN",
1838
- sequence: 3,
1839
- occurred_at: "2026-08-09T12:00:30.000Z",
1840
- duration_ms: 30_000,
1841
- duration_provenance: "observed",
1470
+ source_streams: [
1471
+ {
1472
+ run_id: "RUN-HISTORICAL",
1473
+ path: historicalPath,
1474
+ content_sha256: createHash("sha256").update(historical).digest("hex"),
1475
+ },
1476
+ ],
1842
1477
  };
1843
1478
  await writeFile(
1844
- join(root, ".agents", "records", "runs", "2026", "08", "RUN-PROVIDER-SUBRUN.jsonl"),
1845
- `${[subrunStarted, subrunUsage, subrunFinished].map((row) => JSON.stringify(row)).join("\n")}\n`,
1479
+ join(assignmentsRoot, "HDA-FIXTURE.json"),
1480
+ JSON.stringify({
1481
+ ...unsigned,
1482
+ manifest_hash: createHash("sha256").update(JSON.stringify(unsigned)).digest("hex"),
1483
+ }),
1846
1484
  );
1847
1485
  await rebuildSqliteReadModel(root);
1848
- const sameModelFs = new SqliteReadModelFileSystem(root);
1849
- const modelRow = (filter: Record<string, string>) =>
1850
- sameModelFs
1851
- .viewPage("cost_monitor_models", { from: "2026-08-05", to: "2026-08-05", ...filter })
1852
- .rows.find((row) => row.key === "gpt-a");
1853
- expect(modelRow({ provider: "openai", model: "gpt-a" })).toMatchObject({
1854
- invocation_count: 1,
1855
- task_count: 1,
1856
- total_duration: 60_000,
1857
- total_tokens: 3,
1858
- total_cost_brl: 1.5,
1859
- });
1860
- expect(modelRow({ provider: "anthropic", model: "gpt-a" })).toMatchObject({
1861
- invocation_count: 1,
1862
- task_count: 1,
1863
- total_duration: 60_000,
1864
- total_tokens: 4,
1865
- total_cost_brl: 2,
1866
- });
1867
- expect(modelRow({})).toMatchObject({
1868
- invocation_count: 1,
1869
- task_count: 1,
1870
- total_duration: 60_000,
1871
- total_tokens: 7,
1872
- total_cost_brl: 3.5,
1873
- });
1874
- expect(
1875
- sameModelFs.viewPage("cost_monitor_models", {
1876
- from: "2026-08-05",
1877
- to: "2026-08-05",
1878
- provider: "openai",
1879
- model: "claude-b",
1880
- }),
1881
- ).toMatchObject({ total_count: 0, rows: [] });
1882
- for (const day of ["2026-08-06", "2026-08-07"]) {
1883
- const effective = sameModelFs
1884
- .invocationCostRows({ from: day, to: day })
1885
- .reduce((sum, row) => sum + Number(row.duration_ms ?? 0), 0);
1886
- const modelDuration = sameModelFs
1887
- .viewPage("cost_monitor_models", { from: day, to: day })
1888
- .rows.reduce((sum, row) => sum + Number(row.total_duration ?? 0), 0);
1889
- expect(modelDuration).toBe(effective);
1890
- }
1891
- for (const day of ["2026-08-06", "2026-08-07"]) {
1892
- const population = sameModelFs.invocationCostRows({ from: day, to: day });
1893
- const providerRows = sameModelFs.viewPage("cost_monitor_providers", {
1894
- from: day,
1895
- to: day,
1896
- }).rows;
1897
- const providerTotals = providerRows.reduce<{
1898
- invocations: number;
1899
- tasks: number;
1900
- duration: number;
1901
- tokens: number;
1902
- brl: number;
1903
- }>(
1904
- (total, row) => ({
1905
- invocations: total.invocations + Number(row.invocation_count ?? 0),
1906
- tasks: total.tasks + Number(row.task_count ?? 0),
1907
- duration: total.duration + Number(row.total_duration ?? 0),
1908
- tokens: total.tokens + Number(row.total_tokens ?? 0),
1909
- brl: total.brl + Number(row.total_cost_brl ?? 0),
1910
- }),
1911
- { invocations: 0, tasks: 0, duration: 0, tokens: 0, brl: 0 },
1912
- );
1913
- expect(providerTotals).toEqual({
1914
- invocations: population.length,
1915
- tasks: new Set(
1916
- population.map((row) => row.task_id).filter((id): id is string => typeof id === "string"),
1917
- ).size,
1918
- duration: population.reduce((sum, row) => sum + Number(row.duration_ms ?? 0), 0),
1919
- tokens: population.reduce((sum, row) => sum + Number(row.total_tokens ?? 0), 0),
1920
- brl: population.reduce((sum, row) => sum + Number(row.cost_brl ?? 0), 0),
1486
+ const filesystem = new SqliteReadModelFileSystem(root);
1487
+ try {
1488
+ const all = filesystem.developerCostAggregate({ from: null, to: null });
1489
+ const deliveredBy42 = all.rows.find((row) => row.account_id === "42")!;
1490
+ expect(deliveredBy42).toMatchObject({
1491
+ qualification: "verified",
1492
+ completed_task_count: 1,
1493
+ run_count: 4,
1494
+ token_covered_runs: 3,
1495
+ usd_covered_runs: 3,
1496
+ brl_covered_runs: 3,
1921
1497
  });
1922
- }
1923
- const sharedTaskRows = sameModelFs.viewPage("cost_monitor_models", {
1924
- from: "2026-08-08",
1925
- to: "2026-08-08",
1926
- }).rows;
1927
- expect(sharedTaskRows).toEqual(
1928
- expect.arrayContaining([
1498
+ expect(deliveredBy42.completed_tasks).toEqual([
1929
1499
  expect.objectContaining({
1930
- key: "gpt-a",
1931
- invocation_count: 1,
1932
- task_count: 1,
1933
- total_duration: 30_000,
1934
- total_tokens: 5,
1935
- total_cost_brl: 2.5,
1500
+ id: "TASK-DELIVERED",
1501
+ completed_run_id: "RUN-DELIVERED",
1502
+ delivered_by: { account_id: "42" },
1503
+ contributors: expect.arrayContaining([
1504
+ expect.objectContaining({ account_id: "42" }),
1505
+ expect.objectContaining({ account_id: "99" }),
1506
+ ]),
1936
1507
  }),
1937
- expect.objectContaining({
1938
- key: "claude-b",
1939
- invocation_count: 1,
1940
- task_count: 1,
1941
- total_duration: 30_000,
1942
- total_tokens: 6,
1943
- total_cost_brl: 3,
1944
- }),
1945
- ]),
1946
- );
1947
- expect(sharedTaskRows.map((row) => row.key)).not.toContain("mixed");
1948
- expect(sharedTaskRows.reduce((sum, row) => sum + Number(row.task_count ?? 0), 0)).toBe(2);
1949
- const subrunPopulation = sameModelFs.invocationCostRows({
1950
- from: "2026-08-09",
1951
- to: "2026-08-09",
1952
- providers: ["openai"],
1953
- models: ["gpt-a"],
1954
- });
1955
- const subrunProviderRows = sameModelFs.viewPage("cost_monitor_providers", {
1956
- from: "2026-08-09",
1957
- to: "2026-08-09",
1958
- provider: "openai",
1959
- model: "gpt-a",
1960
- }).rows;
1961
- const subrunProviderTotals = subrunProviderRows.reduce<{
1962
- invocations: number;
1963
- tasks: number;
1964
- duration: number;
1965
- tokens: number;
1966
- brl: number;
1967
- }>(
1968
- (total, row) => ({
1969
- invocations: total.invocations + Number(row.invocation_count ?? 0),
1970
- tasks: total.tasks + Number(row.task_count ?? 0),
1971
- duration: total.duration + Number(row.total_duration ?? 0),
1972
- tokens: total.tokens + Number(row.total_tokens ?? 0),
1973
- brl: total.brl + Number(row.total_cost_brl ?? 0),
1974
- }),
1975
- { invocations: 0, tasks: 0, duration: 0, tokens: 0, brl: 0 },
1976
- );
1977
- expect(subrunProviderTotals).toEqual({
1978
- invocations: subrunPopulation.length,
1979
- tasks: new Set(
1980
- subrunPopulation
1981
- .map((row) => row.task_id)
1982
- .filter((id): id is string => typeof id === "string"),
1983
- ).size,
1984
- duration: subrunPopulation.reduce((sum, row) => sum + Number(row.duration_ms ?? 0), 0),
1985
- tokens: subrunPopulation.reduce((sum, row) => sum + Number(row.total_tokens ?? 0), 0),
1986
- brl: subrunPopulation.reduce((sum, row) => sum + Number(row.cost_brl ?? 0), 0),
1987
- });
1988
- expect(
1989
- sameModelFs.viewPage("cost_monitor_providers", {
1508
+ ]);
1509
+ // Operations counts completed Tasks from the same canonical Task facts
1510
+ // as its status distribution; no completed_run_id is required there.
1511
+ expect(
1512
+ filesystem
1513
+ .operationsDeveloperAggregate({ from: null, to: null })
1514
+ .rows.find((row) => row.account_id === "42"),
1515
+ ).toMatchObject({
1516
+ completed_task_count: 3,
1517
+ status_counts: expect.objectContaining({ completed: 3 }),
1518
+ });
1519
+ expect(all.rows.find((row) => row.account_id === "199126185")).toMatchObject({
1520
+ qualification: "human_assigned",
1521
+ completed_task_count: 1,
1522
+ });
1523
+ expect(
1524
+ filesystem.developerCostAggregate({
1525
+ from: "2026-08-08",
1526
+ to: "2026-08-08",
1527
+ accountIds: ["42"],
1528
+ }).rows,
1529
+ ).toHaveLength(1);
1530
+ expect(
1531
+ filesystem.developerCostAggregate({
1532
+ from: "2026-08-09",
1533
+ to: "2026-08-09",
1534
+ accountIds: ["42"],
1535
+ }).rows[0],
1536
+ ).toMatchObject({ completed_task_count: 0 });
1537
+ // The real attributed unknown Run remains linked to account 42. Its
1538
+ // coverage gap is explicit; its absent measures are never a zero.
1539
+ const unknownDay = filesystem.developerCostAggregate({
1990
1540
  from: "2026-08-09",
1991
1541
  to: "2026-08-09",
1992
- provider: "openai",
1993
- model: "claude-b",
1994
- }),
1995
- ).toMatchObject({ total_count: 0, rows: [] });
1996
- sameModelFs.close();
1542
+ accountIds: ["42"],
1543
+ }).rows[0]!;
1544
+ expect(unknownDay).toMatchObject({
1545
+ run_count: 3,
1546
+ token_covered_runs: 2,
1547
+ usd_covered_runs: 2,
1548
+ brl_covered_runs: 2,
1549
+ });
1550
+ expect(unknownDay.total_tokens).toBe(9);
1551
+ expect(
1552
+ filesystem.dailyPeriods({ from: "2026-08-09", to: "2026-08-09" })["2026-08-09"],
1553
+ ).toMatchObject({
1554
+ runs: 4,
1555
+ usage: {
1556
+ total_tokens: { known_sum: 11, unknown: 1 },
1557
+ cost: { known_sum: 0.55, unknown: 1 },
1558
+ },
1559
+ });
1560
+ } finally {
1561
+ filesystem.close();
1562
+ }
1563
+ await writeFile(join(assignmentsRoot, "HDA-FIXTURE.json"), "{corrupt");
1564
+ await rebuildSqliteReadModel(root, { forceCanonical: true });
1565
+ const corrupt = new SqliteReadModelFileSystem(root);
1566
+ try {
1567
+ expect(
1568
+ corrupt.developerCostAggregate({ from: null, to: null }).rows.map((row) => row.account_id),
1569
+ ).not.toContain("199126185");
1570
+ } finally {
1571
+ corrupt.close();
1572
+ }
1997
1573
  });
1998
1574
 
1999
1575
  it("prefers the canonical started-to-finished interval over a token estimate", async () => {
@@ -3013,6 +2589,7 @@ created_at: 2026-08-10T11:01:00.000Z
3013
2589
  }),
3014
2590
  );
3015
2591
  const allTime = filesystem.firstFoldAllTime();
2592
+ expectPersistedFirstFoldCaches(root, allTime, filesystem.firstFoldBoardAllTime());
3016
2593
  expect(allTime.aggregate).toMatchObject({
3017
2594
  start_day: "2026-08-01",
3018
2595
  end_day: "2026-08-03",