@zaip-ai/cli 1.0.8 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +1 -1
  2. package/dist/services/adapters.d.ts +1 -1
  3. package/dist/services/adapters.js +1 -1
  4. package/dist/services/agent-adapters.js +2 -2
  5. package/dist/services/agent-adapters.js.map +1 -1
  6. package/dist/services/agent-adapters.test.js +5 -0
  7. package/dist/services/agent-adapters.test.js.map +1 -1
  8. package/dist/services/logger.test.js +2 -2
  9. package/dist/services/runtime-template.test.js +6 -6
  10. package/dist/services/template-manifest.d.ts.map +1 -1
  11. package/dist/services/template-manifest.js +5 -0
  12. package/dist/services/template-manifest.js.map +1 -1
  13. package/package.json +1 -1
  14. package/templates/.agents/architecture/software-architecture.md +131 -0
  15. package/templates/.agents/branding/brandbook.docx +0 -0
  16. package/templates/.agents/branding/brandbook.md +60 -0
  17. package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -1
  18. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -1
  19. package/templates/.agents/dashboard/.tmp-run-list.json +254 -0
  20. package/templates/.agents/dashboard/.zaip-managed.json +252 -136
  21. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-Z60df2r-.js → CostCalculationGuidePage-DxR_pgSV.js} +1 -1
  22. package/templates/.agents/dashboard/apps/frontend/dist/assets/DashboardHelpDialog-4jZLTWE_.js +2156 -0
  23. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-Coc6pA-1.js → PricingSettingsDialog-CKcsqb-r.js} +1 -1
  24. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BomxqCBU.css +1 -0
  25. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-DmmJD2Th.js +3 -0
  26. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BwtitWa_.js +1 -0
  27. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-N5Csr0RP.js +68 -0
  28. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DFBuc_qp.js → icons-vendor-C0fj2uU9.js} +1 -1
  29. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-C4aIB1PV.js +2 -0
  30. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-CCQOHdVI.js → react-vendor-BEsJ-FYH.js} +1 -1
  31. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-pC2_0J8x.js → traceability-B6y6Gw12.js} +1 -1
  32. package/templates/.agents/dashboard/apps/frontend/dist/index.html +5 -5
  33. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  34. package/templates/.agents/dashboard/apps/frontend/src/App.tsx +204 -32
  35. package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +11 -11
  36. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +14 -7
  37. package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +4 -2
  38. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +3 -1
  39. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +14 -11
  40. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +19 -4
  41. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +24 -2
  42. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +22 -1
  43. package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +3 -1
  44. package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +36 -26
  45. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +2 -2
  46. package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +40 -6
  47. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +39 -1
  48. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +89 -23
  49. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +219 -29
  50. package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +61 -7
  51. package/templates/.agents/dashboard/apps/frontend/src/use-app-operations-pages.ts +3 -6
  52. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +2 -2
  53. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.ts +3 -4
  54. package/templates/.agents/dashboard/apps/frontend/vite.config.ts +4 -1
  55. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  56. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +89 -19
  57. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +31 -16
  58. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.test.ts +43 -14
  59. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.tsx +5 -5
  60. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.tsx +1 -1
  61. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +67 -42
  62. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +115 -39
  63. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +188 -38
  64. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +75 -17
  65. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +147 -58
  66. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor.css +5 -2
  67. package/templates/.agents/dashboard/modules/cost-monitor/src/react/index.ts +2 -2
  68. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +2 -1
  69. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +18 -7
  70. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +95 -9
  71. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +29 -17
  72. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test.ts +0 -24
  73. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.test.ts +225 -424
  74. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +24 -15
  75. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-terminal-day.test.ts +6 -1
  76. package/templates/.agents/dashboard/modules/cost-monitor/src/server/source-size-cost-server/build-cost-monitor-projection-agents.test.ts +31 -0
  77. package/templates/.agents/dashboard/modules/cost-monitor/src/server/source-size-cost-server/build-cost-summary-projection-duration.test.ts +414 -0
  78. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  79. package/templates/.agents/dashboard/modules/operations/src/contracts.ts +26 -23
  80. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +31 -11
  81. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +3 -1
  82. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +51 -21
  83. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +47 -5
  84. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageNavigation.tsx +1 -4
  85. package/templates/.agents/dashboard/modules/operations/src/react/PeriodSummaryTable.tsx +32 -10
  86. package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +9 -3
  87. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +13 -5
  88. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +12 -4
  89. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +1 -4
  90. package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.ts +1 -2
  91. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +385 -4
  92. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +481 -61
  93. package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +14 -1
  94. package/templates/.agents/dashboard/modules/operations/src/react/export/xlsx-runtime-e2e.test.ts +248 -0
  95. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +4 -4
  96. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +6 -4
  97. package/templates/.agents/dashboard/modules/operations/src/react/operations-global-filters.test.ts +4 -1
  98. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +1 -1
  99. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +1 -1
  100. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +46 -6
  101. package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +1 -4
  102. package/templates/.agents/dashboard/modules/operations/src/react/period-summary.test.ts +82 -6
  103. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +2 -1
  104. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.ts +1 -1
  105. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.test.ts +19 -7
  106. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.ts +4 -1
  107. package/templates/.agents/dashboard/modules/operations/src/server/quick-daily-operations-projection.ts +11 -5
  108. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  109. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  110. package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
  111. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  112. package/templates/.agents/dashboard/packages/contracts/src/index.ts +1 -0
  113. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  114. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +152 -149
  115. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs.metafile.json +7333 -0
  116. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +149 -146
  117. package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
  118. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-dashboard.mjs +15 -7
  119. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +44 -13
  120. package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +5 -2
  121. package/templates/.agents/dashboard/packages/local-runtime/scripts/source-size-runtime-scripts/sqlite-read-model-fixture.mjs +397 -0
  122. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +472 -145
  123. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-unix-launchers.mjs +15 -3
  124. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +129 -31
  125. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +153 -150
  126. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +6 -2
  127. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +3 -3
  128. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +55 -16
  129. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +23 -13
  130. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +19 -4
  131. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +7 -3
  132. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +132 -9
  133. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +126 -60
  134. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.ts +16 -2
  135. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +1861 -350
  136. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +1218 -352
  137. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +119 -42
  138. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +45 -20
  139. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  140. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  141. package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +7 -5
  142. package/templates/.agents/design/.zaip-managed.json +3 -3
  143. package/templates/.agents/design/apps/catalog/package.json +1 -1
  144. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  145. package/templates/.agents/growth/estrategia-bootstrap-90-dias.md +169 -0
  146. package/templates/.agents/growth/strategy.md +27 -0
  147. package/templates/.agents/marketing/estrategia-marketing-zaip-90-dias.md +197 -0
  148. package/templates/.agents/marketing/strategy.md +29 -0
  149. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  150. package/templates/.agents/requirements/comparative-audit.md +1 -1
  151. package/templates/.agents/requirements/context-engine.md +1 -1
  152. package/templates/.agents/requirements/cost-observability.md +1 -1
  153. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  154. package/templates/.agents/requirements/data-export.md +1 -1
  155. package/templates/.agents/requirements/design-system.md +1 -1
  156. package/templates/.agents/requirements/execution-engine.md +1 -1
  157. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  158. package/templates/.agents/requirements/model-orchestration.md +1 -1
  159. package/templates/.agents/requirements/public-distribution.md +1 -1
  160. package/templates/.agents/requirements/software-architecture.md +1 -1
  161. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  162. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  163. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  164. package/templates/.agents/runtime/VERSION +1 -1
  165. package/templates/.agents/runtime/bin/zaip.mjs +30 -29
  166. package/templates/.agents/runtime/checksums.sha256 +6 -6
  167. package/templates/.agents/runtime/manifest.json +1 -1
  168. package/templates/.agents/runtime/pnpm-lock.sha256 +1 -1
  169. package/templates/.agents/runtime/provenance.json +5 -5
  170. package/templates/.agents/runtime/sbom.cdx.json +3 -3
  171. package/templates/.agents/sales/playbook.md +32 -0
  172. package/templates/.agents/sales/roteiro-comercial-zaip.md +252 -0
  173. package/templates/.agents/skills/zaip-aios/SKILL.md +1 -1
  174. package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +9 -2
  175. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-framework.md +39 -0
  176. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +1 -1
  177. package/templates/.agents/skills/zaip-skill-enforce-architecture/SKILL.md +2 -0
  178. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +6 -0
  179. package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +6 -0
  180. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +39 -82
  181. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +13 -8
  182. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +44 -14
  183. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +19 -9
  184. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +29 -5
  185. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/source-size-telemetry/model-identity-reconciliation.mjs +77 -0
  186. package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +6 -0
  187. package/templates/.agents/skills/zaip-skill-sqlite-read-model/scripts/ensure-node.mjs +28 -5
  188. package/templates/.agents/zaip-aios/INDEX.md +10 -0
  189. package/templates/.agents/zaip-aios/README.md +2 -1
  190. package/templates/.agents/zaip-aios/VERSION +1 -1
  191. package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +76 -0
  192. package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +72 -0
  193. package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +330 -0
  194. package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +52 -0
  195. package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +69 -0
  196. package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +483 -0
  197. package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +85 -0
  198. package/templates/.agents/zaip-aios/guides/25-fontes-de-precos-openai.md +18 -0
  199. package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +44 -0
  200. package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +167 -0
  201. package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +144 -0
  202. package/templates/.agents/zaip-aios/guides/assets/diagrams/lifecycles-task-spec-prd.png +0 -0
  203. package/templates/.agents/zaip-aios/guides/assets/diagrams/prd-lifecycle.png +0 -0
  204. package/templates/.agents/zaip-aios/guides/assets/diagrams/spec-lifecycle.png +0 -0
  205. package/templates/.agents/zaip-aios/guides/assets/diagrams/task-lifecycle.png +0 -0
  206. package/templates/template-manifest.json +313 -177
  207. package/templates/.agents/dashboard/apps/frontend/dist/assets/DashboardHelpDialog-Cs6dzDmW.js +0 -1505
  208. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-QE1k9yZB.css +0 -1
  209. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-_Pf5DA_A.js +0 -3
  210. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BVlz3DLZ.js +0 -1
  211. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-Cf9ctPVt.js +0 -68
  212. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8A4DcNXM.js +0 -2
@@ -1,15 +1,24 @@
1
- import { mkdir, mkdtemp, readFile, readdir, rename, utimes, writeFile } from "node:fs/promises";
1
+ import { mkdir, mkdtemp, readdir, readFile, rename, utimes, writeFile } from "node:fs/promises";
2
2
  import { join, resolve } from "node:path";
3
3
  import { DatabaseSync } from "node:sqlite";
4
4
  import { afterEach, describe, expect, it } from "vitest";
5
5
  import { createDashboardApp, projectAllTimeTopTasks } from "./server.js";
6
- import { allocateAttributedTokenActiveMs, rebuildSqliteReadModel, sourceFingerprint, SqliteReadModelFileSystem } from "./sqlite-read-model.js";
6
+ import {
7
+ allocateAttributedTokenActiveMs,
8
+ rebuildSqliteReadModel,
9
+ SqliteReadModelFileSystem,
10
+ sourceFingerprint,
11
+ } from "./sqlite-read-model.js";
7
12
 
8
13
  const roots: string[] = [];
9
14
  // Windows can deny SQLite's sidecar files below the system TEMP directory.
10
15
  // Keep disposable fixtures in the workspace-local test area instead; each
11
16
  // test still receives its own root and never touches the live read model.
12
- const sqliteTestTempRoot = join(resolve(import.meta.dirname, "../../../../../.."), ".tmp", "sqlite-read-model-tests");
17
+ const sqliteTestTempRoot = join(
18
+ resolve(import.meta.dirname, "../../../../../.."),
19
+ ".tmp",
20
+ "sqlite-read-model-tests",
21
+ );
13
22
  async function createSqliteTestRoot(): Promise<string> {
14
23
  await mkdir(sqliteTestTempRoot, { recursive: true });
15
24
  return mkdtemp(join(sqliteTestTempRoot, "fixture-"));
@@ -33,7 +42,11 @@ describe("SQLite dashboard read model", () => {
33
42
  await mkdir(join(root, ".agents", "records", "tasks", "nested"), { recursive: true });
34
43
  await mkdir(join(root, ".agents", "records", "telemetry"), { recursive: true });
35
44
  await mkdir(join(root, ".agents", "config"), { recursive: true });
36
- await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n", "utf8");
45
+ await writeFile(
46
+ join(root, ".agents", "config", "project.yaml"),
47
+ "zaip:\n enabled: true\n",
48
+ "utf8",
49
+ );
37
50
  await writeFile(included, "# included\n", "utf8");
38
51
  await writeFile(excluded, "ignored\n", "utf8");
39
52
 
@@ -56,7 +69,11 @@ describe("SQLite dashboard read model", () => {
56
69
  const task = join(root, ".agents", "records", "tasks", "task.md");
57
70
  await mkdir(join(root, ".agents", "records", "tasks"), { recursive: true });
58
71
  await mkdir(join(root, ".agents", "config"), { recursive: true });
59
- await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n", "utf8");
72
+ await writeFile(
73
+ join(root, ".agents", "config", "project.yaml"),
74
+ "zaip:\n enabled: true\n",
75
+ "utf8",
76
+ );
60
77
  await writeFile(task, "# original\n", "utf8");
61
78
  await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({ cache: "rebuilt" });
62
79
  await writeFile(task, "# changed canonically\n", "utf8");
@@ -65,7 +82,14 @@ describe("SQLite dashboard read model", () => {
65
82
  try {
66
83
  process.env.ZAIP_SQLITE_DB_PATH = join(root, ".local", "dashboard-sqlite", "next.sqlite");
67
84
  process.env.ZAIP_SQLITE_PREFER_LAST_VALID_SEED = "1";
68
- await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({ cache: "stale_seed", files: 2 });
85
+ await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({
86
+ cache: "stale_seed",
87
+ files: 2,
88
+ });
89
+ await expect(rebuildSqliteReadModel(root, { forceCanonical: true })).resolves.toMatchObject({
90
+ cache: "rebuilt",
91
+ files: 2,
92
+ });
69
93
  } finally {
70
94
  if (previousPath === undefined) delete process.env.ZAIP_SQLITE_DB_PATH;
71
95
  else process.env.ZAIP_SQLITE_DB_PATH = previousPath;
@@ -79,38 +103,76 @@ describe("SQLite dashboard read model", () => {
79
103
  roots.push(root);
80
104
  await mkdir(join(root, ".agents", "records", "tasks"), { recursive: true });
81
105
  await mkdir(join(root, ".agents", "config"), { recursive: true });
82
- await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n", "utf8");
106
+ await writeFile(
107
+ join(root, ".agents", "config", "project.yaml"),
108
+ "zaip:\n enabled: true\n",
109
+ "utf8",
110
+ );
83
111
  await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({ cache: "rebuilt" });
84
112
  const path = join(root, ".local", "dashboard-sqlite", "read-model.sqlite");
85
113
  const database = new DatabaseSync(path);
86
- database.prepare("UPDATE zaip_aios_activities SET payload_json=? WHERE payload_type='first_fold_monthly_quick_cache'").run(JSON.stringify({
87
- from_day: "2026-08-01", to_day: "2026-08-18", source_latest_day: "2026-08-30",
88
- aggregate: { days: 0, total_run_count: 0, agent_invocation_count: 0, llm_call_count: null, duration_ms: null, total_tokens: null, cost_brl: null, execution_day_count: 0 },
89
- pages: { task: [], spec: [], prd: [] }, top_tasks: [],
90
- }));
114
+ database
115
+ .prepare(
116
+ "UPDATE zaip_aios_activities SET payload_json=? WHERE payload_type='first_fold_monthly_quick_cache'",
117
+ )
118
+ .run(
119
+ JSON.stringify({
120
+ from_day: "2026-08-01",
121
+ to_day: "2026-08-18",
122
+ source_latest_day: "2026-08-30",
123
+ aggregate: {
124
+ days: 0,
125
+ total_run_count: 0,
126
+ agent_invocation_count: 0,
127
+ llm_call_count: null,
128
+ duration_ms: null,
129
+ total_tokens: null,
130
+ cost_brl: null,
131
+ execution_day_count: 0,
132
+ },
133
+ pages: { task: [], spec: [], prd: [] },
134
+ top_tasks: [],
135
+ }),
136
+ );
91
137
  database.close();
92
138
  const filesystem = new SqliteReadModelFileSystem(root);
93
139
  try {
94
- expect(filesystem.firstFoldMonthlyQuick({ from: "2026-08-01", to: "2026-08-18" })).not.toBeNull();
140
+ expect(
141
+ filesystem.firstFoldMonthlyQuick({ from: "2026-08-01", to: "2026-08-18" }),
142
+ ).not.toBeNull();
95
143
  expect(filesystem.firstFoldMonthlyQuick({ from: "2026-08-01", to: "2026-08-19" })).toBeNull();
96
- expect(filesystem.firstFoldMonthlyQuick({ from: "2026-09-01", to: "2026-09-01" })).toMatchObject({
97
- aggregate: { total_run_count: 0 }, pages: { task: [], spec: [], prd: [] },
144
+ expect(
145
+ filesystem.firstFoldMonthlyQuick({ from: "2026-09-01", to: "2026-09-01" }),
146
+ ).toMatchObject({
147
+ aggregate: { total_run_count: 0 },
148
+ pages: { task: [], spec: [], prd: [] },
98
149
  });
99
- } finally { filesystem.close(); }
150
+ } finally {
151
+ filesystem.close();
152
+ }
100
153
  });
101
154
 
102
155
  it("treats an empty snapshot as an exact empty later-month projection", async () => {
103
156
  const root = await createSqliteTestRoot();
104
157
  roots.push(root);
105
158
  await mkdir(join(root, ".agents", "config"), { recursive: true });
106
- await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n", "utf8");
159
+ await writeFile(
160
+ join(root, ".agents", "config", "project.yaml"),
161
+ "zaip:\n enabled: true\n",
162
+ "utf8",
163
+ );
107
164
  await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({ cache: "rebuilt" });
108
165
  const filesystem = new SqliteReadModelFileSystem(root);
109
166
  try {
110
- expect(filesystem.firstFoldMonthlyQuick({ from: "2099-01-01", to: "2099-01-01" })).toMatchObject({
111
- aggregate: { total_run_count: 0 }, pages: { task: [], spec: [], prd: [] },
167
+ expect(
168
+ filesystem.firstFoldMonthlyQuick({ from: "2099-01-01", to: "2099-01-01" }),
169
+ ).toMatchObject({
170
+ aggregate: { total_run_count: 0 },
171
+ pages: { task: [], spec: [], prd: [] },
112
172
  });
113
- } finally { filesystem.close(); }
173
+ } finally {
174
+ filesystem.close();
175
+ }
114
176
  });
115
177
 
116
178
  it("does not serve a schema 59 seed during the one-time SQLite cache migration", async () => {
@@ -118,16 +180,26 @@ describe("SQLite dashboard read model", () => {
118
180
  roots.push(root);
119
181
  await mkdir(join(root, ".agents", "records", "tasks"), { recursive: true });
120
182
  await mkdir(join(root, ".agents", "config"), { recursive: true });
121
- await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n", "utf8");
183
+ await writeFile(
184
+ join(root, ".agents", "config", "project.yaml"),
185
+ "zaip:\n enabled: true\n",
186
+ "utf8",
187
+ );
122
188
  await writeFile(join(root, ".agents", "records", "tasks", "task.md"), "# task\n", "utf8");
123
189
  await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({ cache: "rebuilt" });
124
190
  const cacheDirectory = join(root, ".local", "dashboard-sqlite", "cache");
125
- const current = (await readdir(cacheDirectory)).find((entry) => entry.startsWith("v60-") && entry.endsWith(".sqlite"));
191
+ const current = (await readdir(cacheDirectory)).find(
192
+ (entry) => entry.startsWith("v60-") && entry.endsWith(".sqlite"),
193
+ );
126
194
  expect(current).toBeDefined();
127
195
  const legacy = join(cacheDirectory, current!.replace("v60-", ""));
128
196
  await rename(join(cacheDirectory, current!), legacy);
129
197
  const oldSeed = new DatabaseSync(legacy);
130
- oldSeed.prepare("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'").run();
198
+ oldSeed
199
+ .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'",
201
+ )
202
+ .run();
131
203
  oldSeed.close();
132
204
  const priorPath = process.env.ZAIP_SQLITE_DB_PATH;
133
205
  const priorSeed = process.env.ZAIP_SQLITE_PREFER_LAST_VALID_SEED;
@@ -145,19 +217,41 @@ describe("SQLite dashboard read model", () => {
145
217
 
146
218
  it("rateia sobreposição e virada de dia na fato temporal aditiva", () => {
147
219
  const overlap = allocateAttributedTokenActiveMs([
148
- { activityRowId: "A", startMs: Date.parse("2026-08-10T12:00:00.000Z"), endMs: Date.parse("2026-08-10T13:00:00.000Z") },
149
- { activityRowId: "B", startMs: Date.parse("2026-08-10T12:30:00.000Z"), endMs: Date.parse("2026-08-10T13:30:00.000Z") },
220
+ {
221
+ activityRowId: "A",
222
+ startMs: Date.parse("2026-08-10T12:00:00.000Z"),
223
+ endMs: Date.parse("2026-08-10T13:00:00.000Z"),
224
+ },
225
+ {
226
+ activityRowId: "B",
227
+ startMs: Date.parse("2026-08-10T12:30:00.000Z"),
228
+ endMs: Date.parse("2026-08-10T13:30:00.000Z"),
229
+ },
150
230
  ]);
151
231
  expect(overlap.reduce((sum, fact) => sum + fact.value, 0)).toBe(5_400_000);
152
- expect(overlap.filter((fact) => fact.activityRowId === "A").reduce((sum, fact) => sum + fact.value, 0)).toBe(2_700_000);
153
- expect(overlap.filter((fact) => fact.activityRowId === "B").reduce((sum, fact) => sum + fact.value, 0)).toBe(2_700_000);
232
+ expect(
233
+ overlap
234
+ .filter((fact) => fact.activityRowId === "A")
235
+ .reduce((sum, fact) => sum + fact.value, 0),
236
+ ).toBe(2_700_000);
237
+ expect(
238
+ overlap
239
+ .filter((fact) => fact.activityRowId === "B")
240
+ .reduce((sum, fact) => sum + fact.value, 0),
241
+ ).toBe(2_700_000);
154
242
  const midnight = allocateAttributedTokenActiveMs([
155
- { activityRowId: "MID", startMs: Date.parse("2026-08-11T02:30:00.000Z"), endMs: Date.parse("2026-08-11T03:30:00.000Z") },
243
+ {
244
+ activityRowId: "MID",
245
+ startMs: Date.parse("2026-08-11T02:30:00.000Z"),
246
+ endMs: Date.parse("2026-08-11T03:30:00.000Z"),
247
+ },
156
248
  ]);
157
- expect(midnight).toEqual(expect.arrayContaining([
158
- expect.objectContaining({ day: "2026-08-10", value: 1_800_000 }),
159
- expect.objectContaining({ day: "2026-08-11", value: 1_800_000 }),
160
- ]));
249
+ expect(midnight).toEqual(
250
+ expect.arrayContaining([
251
+ expect.objectContaining({ day: "2026-08-10", value: 1_800_000 }),
252
+ expect.objectContaining({ day: "2026-08-11", value: 1_800_000 }),
253
+ ]),
254
+ );
161
255
  });
162
256
  it("projects canonical executions, conversations, changes and decisions without lifecycle aggregates", async () => {
163
257
  const root = await createSqliteTestRoot();
@@ -166,10 +260,9 @@ describe("SQLite dashboard read model", () => {
166
260
  await mkdir(join(root, ".agents", "records", "executions", "2026", "08", "EXEC-1"), {
167
261
  recursive: true,
168
262
  });
169
- await mkdir(
170
- join(root, ".agents", "records", "changes", "2026", "08", "CHG-1", "decisions"),
171
- { recursive: true },
172
- );
263
+ await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-1", "decisions"), {
264
+ recursive: true,
265
+ });
173
266
  await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n");
174
267
  await writeFile(
175
268
  join(root, ".agents", "records", "executions", "2026", "08", "EXEC-1", "execution.md"),
@@ -210,17 +303,7 @@ created_at: 2026-08-10T11:00:00.000Z
210
303
  `,
211
304
  );
212
305
  await writeFile(
213
- join(
214
- root,
215
- ".agents",
216
- "records",
217
- "changes",
218
- "2026",
219
- "08",
220
- "CHG-1",
221
- "decisions",
222
- "DEC-1.md",
223
- ),
306
+ join(root, ".agents", "records", "changes", "2026", "08", "CHG-1", "decisions", "DEC-1.md"),
224
307
  `---
225
308
  schema_version: 2
226
309
  id: DEC-1
@@ -239,7 +322,16 @@ created_at: 2026-08-10T11:01:00.000Z
239
322
  const filesystem = new SqliteReadModelFileSystem(root);
240
323
  expect(filesystem.viewPage("operations_executions", { limit: 100 })).toMatchObject({
241
324
  total_count: 1,
242
- rows: [{ execution_id: "EXEC-1", conversation_id: "CONV-1", invocation_count: 0, duration_ms: null, duration_provenance: "unavailable", lifecycle_elapsed_ms: 300_000 }],
325
+ rows: [
326
+ {
327
+ execution_id: "EXEC-1",
328
+ conversation_id: "CONV-1",
329
+ invocation_count: 0,
330
+ duration_ms: null,
331
+ duration_provenance: "unavailable",
332
+ lifecycle_elapsed_ms: 300_000,
333
+ },
334
+ ],
243
335
  });
244
336
  expect(filesystem.viewPage("operations_conversations", { limit: 100 })).toMatchObject({
245
337
  total_count: 1,
@@ -312,30 +404,84 @@ created_at: 2026-08-10T11:01:00.000Z
312
404
  const events = [...expected.keys()].flatMap((agent, index) => {
313
405
  const runId = `RUN-AGENT-${index}`;
314
406
  const started = {
315
- schema_version: 2, event_id: `${runId}:1`, run_id: runId, sequence: 1,
316
- occurred_at: "2026-08-18T12:00:00.000Z", type: "run.started", attribution_status: "attributed",
317
- phase: "execution", run_role: "subagent", run_purpose: "execution", requires_finalizer: false,
318
- execution_kind: "delivery", execution_eligibility: ["delivery"], entrypoint: "task", work_type: "new",
319
- storage_mode: "tracked_sanitized", client: "codex", agent, agent_name: agent, provider: "openai",
320
- model: "gpt-5", reasoning_effort: null, client_thread_id: runId, client_turn_id: runId,
321
- conversation_id: `CONV-${index}`, execution_id: `EXEC-${index}`, task_id: `TASK-${index}`,
322
- spec_id: null, prd_id: null, change_id: null, parent_run_id: "RUN-ROOT", continuation_of_run_id: null,
323
- retry_of_run_id: null, agent_invocation_id: `AINV-${index}`, root_agent_invocation_id: "AINV-ROOT",
324
- parent_agent_invocation_id: "AINV-ROOT", invocation_kind: "delegated", delegation_depth: 1,
407
+ schema_version: 2,
408
+ event_id: `${runId}:1`,
409
+ run_id: runId,
410
+ sequence: 1,
411
+ occurred_at: "2026-08-18T12:00:00.000Z",
412
+ type: "run.started",
413
+ attribution_status: "attributed",
414
+ phase: "execution",
415
+ run_role: "subagent",
416
+ run_purpose: "execution",
417
+ requires_finalizer: false,
418
+ execution_kind: "delivery",
419
+ execution_eligibility: ["delivery"],
420
+ entrypoint: "task",
421
+ work_type: "new",
422
+ storage_mode: "tracked_sanitized",
423
+ client: "codex",
424
+ agent,
425
+ agent_name: agent,
426
+ provider: "openai",
427
+ model: "gpt-5",
428
+ reasoning_effort: null,
429
+ client_thread_id: runId,
430
+ client_turn_id: runId,
431
+ conversation_id: `CONV-${index}`,
432
+ execution_id: `EXEC-${index}`,
433
+ task_id: `TASK-${index}`,
434
+ spec_id: null,
435
+ prd_id: null,
436
+ change_id: null,
437
+ parent_run_id: "RUN-ROOT",
438
+ continuation_of_run_id: null,
439
+ retry_of_run_id: null,
440
+ agent_invocation_id: `AINV-${index}`,
441
+ root_agent_invocation_id: "AINV-ROOT",
442
+ parent_agent_invocation_id: "AINV-ROOT",
443
+ invocation_kind: "delegated",
444
+ delegation_depth: 1,
325
445
  };
326
446
  const usage = {
327
- schema_version: 2, event_id: `${runId}:2`, run_id: runId, sequence: 2,
328
- occurred_at: "2026-08-18T12:00:01.000Z", type: "usage.recorded", phase: "execution",
329
- activity_kind: "model_usage", classification_source: "explicit",
330
- tokens: { input: 1, cached_input: 0, output: 1, reasoning: 0, total: 2, source: "provider_reported" },
331
- cost: { usd: 0.01, brl: 0.05, fx_rate: 5 }, provider: "openai", model: "gpt-5",
332
- source_segment_key: runId, model_call_id: `MCALL-${index}`, runtime: { reasoning_effort: null, service_tier: null },
333
- supersedes_event_id: null, duration_ms: null, duration_provenance: null,
447
+ schema_version: 2,
448
+ event_id: `${runId}:2`,
449
+ run_id: runId,
450
+ sequence: 2,
451
+ occurred_at: "2026-08-18T12:00:01.000Z",
452
+ type: "usage.recorded",
453
+ phase: "execution",
454
+ activity_kind: "model_usage",
455
+ classification_source: "explicit",
456
+ tokens: {
457
+ input: 1,
458
+ cached_input: 0,
459
+ output: 1,
460
+ reasoning: 0,
461
+ total: 2,
462
+ source: "provider_reported",
463
+ },
464
+ cost: { usd: 0.01, brl: 0.05, fx_rate: 5 },
465
+ provider: "openai",
466
+ model: "gpt-5",
467
+ source_segment_key: runId,
468
+ model_call_id: `MCALL-${index}`,
469
+ runtime: { reasoning_effort: null, service_tier: null },
470
+ supersedes_event_id: null,
471
+ duration_ms: null,
472
+ duration_provenance: null,
334
473
  };
335
474
  const finished = {
336
- schema_version: 2, event_id: `${runId}:3`, run_id: runId, sequence: 3,
337
- occurred_at: "2026-08-18T12:01:00.000Z", type: "run.finished", phase: "execution",
338
- status: "completed", duration_ms: 60_000, duration_provenance: "observed",
475
+ schema_version: 2,
476
+ event_id: `${runId}:3`,
477
+ run_id: runId,
478
+ sequence: 3,
479
+ occurred_at: "2026-08-18T12:01:00.000Z",
480
+ type: "run.finished",
481
+ phase: "execution",
482
+ status: "completed",
483
+ duration_ms: 60_000,
484
+ duration_provenance: "observed",
339
485
  };
340
486
  return [started, usage, finished];
341
487
  });
@@ -343,7 +489,10 @@ created_at: 2026-08-10T11:01:00.000Z
343
489
  [...expected.keys()].map((_, index) =>
344
490
  writeFile(
345
491
  join(root, ".agents", "records", "runs", "2026", "08", `RUN-AGENT-${index}.jsonl`),
346
- `${events.slice(index * 3, index * 3 + 3).map((event) => JSON.stringify(event)).join("\n")}\n`,
492
+ `${events
493
+ .slice(index * 3, index * 3 + 3)
494
+ .map((event) => JSON.stringify(event))
495
+ .join("\n")}\n`,
347
496
  ),
348
497
  ),
349
498
  );
@@ -381,25 +530,87 @@ created_at: 2026-08-10T11:01:00.000Z
381
530
  source: "fixture",
382
531
  disclaimer: "fixture",
383
532
  models: [
384
- { id: "gpt-a", provider: "openai", aliases: [], input_per_million_usd: 2, cached_input_per_million_usd: 0.2, output_per_million_usd: 8, reasoning_per_million_usd: 8, reasoning_billed_separately: false, long_context_threshold_tokens: null, long_context_input_multiplier: 1, long_context_output_multiplier: 1, source_label: "fixture-openai", source_url: "https://example.test/openai", notes: [] },
385
- { id: "claude-b", provider: "anthropic", aliases: [], input_per_million_usd: 3, cached_input_per_million_usd: 0.3, output_per_million_usd: 12, reasoning_per_million_usd: null, reasoning_billed_separately: false, long_context_threshold_tokens: null, long_context_input_multiplier: 1, long_context_output_multiplier: 1, source_label: "fixture-anthropic", source_url: "https://example.test/anthropic", notes: [] },
533
+ {
534
+ id: "gpt-a",
535
+ provider: "openai",
536
+ aliases: [],
537
+ input_per_million_usd: 2,
538
+ cached_input_per_million_usd: 0.2,
539
+ output_per_million_usd: 8,
540
+ reasoning_per_million_usd: 8,
541
+ reasoning_billed_separately: false,
542
+ long_context_threshold_tokens: null,
543
+ long_context_input_multiplier: 1,
544
+ long_context_output_multiplier: 1,
545
+ source_label: "fixture-openai",
546
+ source_url: "https://example.test/openai",
547
+ notes: [],
548
+ },
549
+ {
550
+ id: "claude-b",
551
+ provider: "anthropic",
552
+ aliases: [],
553
+ input_per_million_usd: 3,
554
+ cached_input_per_million_usd: 0.3,
555
+ output_per_million_usd: 12,
556
+ reasoning_per_million_usd: null,
557
+ reasoning_billed_separately: false,
558
+ long_context_threshold_tokens: null,
559
+ long_context_input_multiplier: 1,
560
+ long_context_output_multiplier: 1,
561
+ source_label: "fixture-anthropic",
562
+ source_url: "https://example.test/anthropic",
563
+ notes: [],
564
+ },
386
565
  ],
387
566
  }),
388
567
  );
389
568
  const started = {
390
- schema_version: 2, event_id: "RUN-MISSING:1", run_id: "RUN-MISSING", sequence: 1,
391
- occurred_at: "2026-08-05T12:00:00.000Z", type: "run.started", attribution_status: "attributed",
392
- phase: "conversation", run_role: "orchestrator", run_purpose: "orchestration", requires_finalizer: false,
393
- execution_kind: "interaction", execution_eligibility: ["interaction"], entrypoint: "conversation",
394
- work_type: "new", storage_mode: "tracked_sanitized", client: "codex", agent: "root", agent_name: "root",
395
- provider: null, model: "unknown", reasoning_effort: null, client_thread_id: "missing", client_turn_id: "missing",
396
- conversation_id: "CONV-MISSING", execution_id: null, task_id: null, spec_id: null, prd_id: null,
397
- change_id: null, parent_run_id: null, continuation_of_run_id: null, retry_of_run_id: null,
569
+ schema_version: 2,
570
+ event_id: "RUN-MISSING:1",
571
+ run_id: "RUN-MISSING",
572
+ sequence: 1,
573
+ occurred_at: "2026-08-05T12:00:00.000Z",
574
+ type: "run.started",
575
+ attribution_status: "attributed",
576
+ phase: "conversation",
577
+ run_role: "orchestrator",
578
+ run_purpose: "orchestration",
579
+ requires_finalizer: false,
580
+ execution_kind: "interaction",
581
+ execution_eligibility: ["interaction"],
582
+ entrypoint: "conversation",
583
+ work_type: "new",
584
+ storage_mode: "tracked_sanitized",
585
+ client: "codex",
586
+ agent: "root",
587
+ agent_name: "root",
588
+ provider: null,
589
+ model: "unknown",
590
+ reasoning_effort: null,
591
+ client_thread_id: "missing",
592
+ client_turn_id: "missing",
593
+ conversation_id: "CONV-MISSING",
594
+ execution_id: null,
595
+ task_id: null,
596
+ spec_id: null,
597
+ prd_id: null,
598
+ change_id: null,
599
+ parent_run_id: null,
600
+ continuation_of_run_id: null,
601
+ retry_of_run_id: null,
398
602
  };
399
603
  const finished = {
400
- schema_version: 2, event_id: "RUN-MISSING:2", run_id: "RUN-MISSING", sequence: 2,
401
- occurred_at: "2026-08-05T12:01:00.000Z", type: "run.finished", phase: "conversation",
402
- status: "completed", duration_ms: 60_000, duration_provenance: "observed",
604
+ schema_version: 2,
605
+ event_id: "RUN-MISSING:2",
606
+ run_id: "RUN-MISSING",
607
+ sequence: 2,
608
+ occurred_at: "2026-08-05T12:01:00.000Z",
609
+ type: "run.finished",
610
+ phase: "conversation",
611
+ status: "completed",
612
+ duration_ms: 60_000,
613
+ duration_provenance: "observed",
403
614
  };
404
615
  await writeFile(
405
616
  join(root, ".agents", "records", "runs", "2026", "08", "RUN-MISSING.jsonl"),
@@ -426,26 +637,40 @@ created_at: 2026-08-10T11:01:00.000Z
426
637
  await rebuildSqliteReadModel(root);
427
638
  const filesystem = new SqliteReadModelFileSystem(root);
428
639
  try {
429
- expect(await filesystem.readText(".agents/config/project.yaml")).toBe("zaip:\n enabled: true\n");
640
+ expect(await filesystem.readText(".agents/config/project.yaml")).toBe(
641
+ "zaip:\n enabled: true\n",
642
+ );
430
643
  expect(filesystem.viewPage("operations_work_list", { limit: 10 }).total_count).toBe(0);
431
- const pageCache = (filesystem as unknown as {
432
- viewPageResultCache: Map<string, Record<string, unknown>>;
433
- }).viewPageResultCache;
644
+ const pageCache = (
645
+ filesystem as unknown as {
646
+ viewPageResultCache: Map<string, Record<string, unknown>>;
647
+ }
648
+ ).viewPageResultCache;
434
649
  expect(pageCache.has('operations_work_list:{"limit":10}')).toBe(true);
435
650
  // Change canonical input only after the read-only database has opened:
436
651
  // rebuild must replace the generation rather than taking the cache path.
437
652
  await writeFile(configPath, "zaip:\n enabled: true\nproject:\n id: refreshed-fixture\n");
438
- await expect(filesystem.rebuildAndRefresh(() => rebuildSqliteReadModel(root))).resolves.toBeUndefined();
439
- expect(await filesystem.readText(".agents/config/project.yaml")).toContain("refreshed-fixture");
653
+ await expect(
654
+ filesystem.rebuildAndRefresh(() => rebuildSqliteReadModel(root)),
655
+ ).resolves.toBeUndefined();
656
+ expect(await filesystem.readText(".agents/config/project.yaml")).toContain(
657
+ "refreshed-fixture",
658
+ );
440
659
  expect(pageCache.has('operations_work_list:{"limit":10}')).toBe(false);
441
660
  // Exercise the actual public view on the same reopened instance, not
442
661
  // merely raw filesystem reads after a Windows-safe replacement.
443
- expect(() => filesystem.viewPage("cost_monitor_daily", { limit: 1, offset: 0 })).not.toThrow();
662
+ expect(() =>
663
+ filesystem.viewPage("cost_monitor_daily", { limit: 1, offset: 0 }),
664
+ ).not.toThrow();
444
665
  // A failed rebuild still reopens the existing, complete generation.
445
- await expect(filesystem.rebuildAndRefresh(async () => {
446
- throw new Error("simulated rebuild failure");
447
- })).rejects.toThrow("simulated rebuild failure");
448
- expect(await filesystem.readText(".agents/config/project.yaml")).toContain("refreshed-fixture");
666
+ await expect(
667
+ filesystem.rebuildAndRefresh(async () => {
668
+ throw new Error("simulated rebuild failure");
669
+ }),
670
+ ).rejects.toThrow("simulated rebuild failure");
671
+ expect(await filesystem.readText(".agents/config/project.yaml")).toContain(
672
+ "refreshed-fixture",
673
+ );
449
674
  } finally {
450
675
  filesystem.close();
451
676
  }
@@ -458,7 +683,7 @@ created_at: 2026-08-10T11:01:00.000Z
458
683
  await mkdir(join(root, ".agents", "config"), { recursive: true });
459
684
  await writeFile(
460
685
  join(root, ".agents", "config", "project.yaml"),
461
- "schema_version: 1\nzaip:\n enabled: true\nproject:\n id: sqlite-test\n name: sqlite-test\n timezone: UTC\nstack:\n id: zaip-aios-stack\n overrides: {}\nclients:\n codex: true\n claude: true\ntracking:\n enabled: true\n currency: BRL\n storage_mode: tracked_sanitized\n",
686
+ "schema_version: 1\nzaip:\n enabled: true\nproject:\n id: sqlite-test\n name: sqlite-test\n timezone: UTC\nstack:\n id: zaip-aios-stack\n overrides: {}\nclients:\n codex: true\n claude: true\ntracking:\n enabled: true\n currency: BRL\n storage_mode: tracked_sanitized\n",
462
687
  "utf8",
463
688
  );
464
689
  const started = {
@@ -572,11 +797,24 @@ created_at: 2026-08-10T11:01:00.000Z
572
797
  duration_unknown: 1,
573
798
  });
574
799
  expect(Object.keys(day).sort()).toEqual([
575
- "duration_known", "duration_unknown", "evidence_count", "key", "label",
576
- "prd_count", "spec_count", "task_count", "total_cost_brl", "total_cost_usd",
577
- "total_duration", "total_run_count", "total_tokens", "validation_count",
800
+ "duration_known",
801
+ "duration_unknown",
802
+ "evidence_count",
803
+ "key",
804
+ "label",
805
+ "prd_count",
806
+ "spec_count",
807
+ "task_count",
808
+ "total_cost_brl",
809
+ "total_cost_usd",
810
+ "total_duration",
811
+ "total_run_count",
812
+ "total_tokens",
813
+ "validation_count",
578
814
  ]);
579
- expect(filesystem.costMonitorFactualDurationByDay({ from: null, to: null }).get("2026-08-01")).toEqual({
815
+ expect(
816
+ filesystem.costMonitorFactualDurationByDay({ from: null, to: null }).get("2026-08-01"),
817
+ ).toEqual({
580
818
  known_sum: 0,
581
819
  eligible_runs: 1,
582
820
  known_runs: 0,
@@ -589,7 +827,9 @@ created_at: 2026-08-10T11:01:00.000Z
589
827
  roots.push(root);
590
828
  await mkdir(join(root, ".agents", "records", "runs", "2026", "08"), { recursive: true });
591
829
  await mkdir(join(root, ".agents", "config", "agents"), { recursive: true });
592
- await mkdir(join(root, ".agents", "config", "pricing", "fx", "2026", "08", "04"), { recursive: true });
830
+ await mkdir(join(root, ".agents", "config", "pricing", "fx", "2026", "08", "04"), {
831
+ recursive: true,
832
+ });
593
833
  await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n");
594
834
  await writeFile(
595
835
  join(root, ".agents", "config", "agents", "catalog.yaml"),
@@ -603,17 +843,117 @@ created_at: 2026-08-10T11:01:00.000Z
603
843
  source: "fixture",
604
844
  disclaimer: "fixture",
605
845
  models: [
606
- { id: "gpt-a", provider: "openai", aliases: [], input_per_million_usd: 2, cached_input_per_million_usd: 0.2, output_per_million_usd: 8, reasoning_per_million_usd: 8, reasoning_billed_separately: false, long_context_threshold_tokens: null, long_context_input_multiplier: 1, long_context_output_multiplier: 1, source_label: "fixture-openai", source_url: "https://example.test/openai", notes: [] },
846
+ {
847
+ id: "gpt-a",
848
+ provider: "openai",
849
+ aliases: [],
850
+ input_per_million_usd: 2,
851
+ cached_input_per_million_usd: 0.2,
852
+ output_per_million_usd: 8,
853
+ reasoning_per_million_usd: 8,
854
+ reasoning_billed_separately: false,
855
+ long_context_threshold_tokens: null,
856
+ long_context_input_multiplier: 1,
857
+ long_context_output_multiplier: 1,
858
+ source_label: "fixture-openai",
859
+ source_url: "https://example.test/openai",
860
+ notes: [],
861
+ },
607
862
  ],
608
863
  }),
609
864
  );
610
865
  await writeFile(
611
866
  join(root, ".agents", "config", "pricing", "fx", "2026", "08", "04", "usd-brl.json"),
612
- JSON.stringify({ schema_version: 1, base: "USD", quote: "BRL", rate: 5.5, as_of: "2026-08-04T00:00:00.000Z", source_label: "fixture", source_url: "https://example.test/fx" }),
867
+ JSON.stringify({
868
+ schema_version: 1,
869
+ base: "USD",
870
+ quote: "BRL",
871
+ rate: 5.5,
872
+ as_of: "2026-08-04T00:00:00.000Z",
873
+ source_label: "fixture",
874
+ source_url: "https://example.test/fx",
875
+ }),
613
876
  );
614
- const started = { schema_version: 2, event_id: "RUN-PRICED:1", run_id: "RUN-PRICED", sequence: 1, occurred_at: "2026-08-08T12:00:00.000Z", type: "run.started", attribution_status: "attributed", phase: "execution", run_role: "orchestrator", run_purpose: "execution", requires_finalizer: false, execution_kind: "delivery", execution_eligibility: ["delivery"], entrypoint: "task", work_type: "new", storage_mode: "tracked_sanitized", client: "codex", agent: "agent", agent_name: "agent", provider: "openai", model: "gpt-a", reasoning_effort: null, client_thread_id: "priced", client_turn_id: "priced", conversation_id: "CONV-PRICED", execution_id: "EXEC-PRICED", task_id: "TASK-PRICED", spec_id: null, prd_id: null, change_id: null, parent_run_id: null, continuation_of_run_id: null, retry_of_run_id: null, agent_invocation_id: "AINV-PRICED", root_agent_invocation_id: "AINV-PRICED", parent_agent_invocation_id: null, invocation_kind: "orchestrator", delegation_depth: 0 };
615
- const usage = { schema_version: 2, event_id: "RUN-PRICED:2", run_id: "RUN-PRICED", sequence: 2, occurred_at: "2026-08-08T12:00:01.000Z", type: "usage.recorded", phase: "execution", activity_kind: "model_usage", classification_source: "explicit", tokens: { input: 5, cached_input: 0, output: 0, reasoning: 0, total: 5, source: "provider_reported" }, cost: { usd: 0.5, brl: 2.5, fx_rate: 5 }, provider: "openai", model: "gpt-a", source_segment_key: "openai-gpt-a", model_call_id: "MCALL-PRICED", runtime: { reasoning_effort: null, service_tier: null }, supersedes_event_id: null, duration_ms: null, duration_provenance: null };
616
- const finished = { schema_version: 2, event_id: "RUN-PRICED:3", run_id: "RUN-PRICED", sequence: 3, occurred_at: "2026-08-08T12:01:00.000Z", type: "run.finished", phase: "execution", status: "completed", duration_ms: 60_000, duration_provenance: "observed" };
877
+ const started = {
878
+ schema_version: 2,
879
+ event_id: "RUN-PRICED:1",
880
+ run_id: "RUN-PRICED",
881
+ sequence: 1,
882
+ occurred_at: "2026-08-08T12:00:00.000Z",
883
+ type: "run.started",
884
+ attribution_status: "attributed",
885
+ phase: "execution",
886
+ run_role: "orchestrator",
887
+ run_purpose: "execution",
888
+ requires_finalizer: false,
889
+ execution_kind: "delivery",
890
+ execution_eligibility: ["delivery"],
891
+ entrypoint: "task",
892
+ work_type: "new",
893
+ storage_mode: "tracked_sanitized",
894
+ client: "codex",
895
+ agent: "agent",
896
+ agent_name: "agent",
897
+ provider: "openai",
898
+ model: "gpt-a",
899
+ reasoning_effort: null,
900
+ client_thread_id: "priced",
901
+ client_turn_id: "priced",
902
+ conversation_id: "CONV-PRICED",
903
+ execution_id: "EXEC-PRICED",
904
+ task_id: "TASK-PRICED",
905
+ spec_id: null,
906
+ prd_id: null,
907
+ change_id: null,
908
+ parent_run_id: null,
909
+ continuation_of_run_id: null,
910
+ retry_of_run_id: null,
911
+ agent_invocation_id: "AINV-PRICED",
912
+ root_agent_invocation_id: "AINV-PRICED",
913
+ parent_agent_invocation_id: null,
914
+ invocation_kind: "orchestrator",
915
+ delegation_depth: 0,
916
+ };
917
+ const usage = {
918
+ schema_version: 2,
919
+ event_id: "RUN-PRICED:2",
920
+ run_id: "RUN-PRICED",
921
+ sequence: 2,
922
+ occurred_at: "2026-08-08T12:00:01.000Z",
923
+ type: "usage.recorded",
924
+ phase: "execution",
925
+ activity_kind: "model_usage",
926
+ classification_source: "explicit",
927
+ tokens: {
928
+ input: 5,
929
+ cached_input: 0,
930
+ output: 0,
931
+ reasoning: 0,
932
+ total: 5,
933
+ source: "provider_reported",
934
+ },
935
+ cost: { usd: 0.5, brl: 2.5, fx_rate: 5 },
936
+ provider: "openai",
937
+ model: "gpt-a",
938
+ source_segment_key: "openai-gpt-a",
939
+ model_call_id: "MCALL-PRICED",
940
+ runtime: { reasoning_effort: null, service_tier: null },
941
+ supersedes_event_id: null,
942
+ duration_ms: null,
943
+ duration_provenance: null,
944
+ };
945
+ const finished = {
946
+ schema_version: 2,
947
+ event_id: "RUN-PRICED:3",
948
+ run_id: "RUN-PRICED",
949
+ sequence: 3,
950
+ occurred_at: "2026-08-08T12:01:00.000Z",
951
+ type: "run.finished",
952
+ phase: "execution",
953
+ status: "completed",
954
+ duration_ms: 60_000,
955
+ duration_provenance: "observed",
956
+ };
617
957
  await writeFile(
618
958
  join(root, ".agents", "records", "runs", "2026", "08", "RUN-PRICED.jsonl"),
619
959
  `${[started, usage, finished].map((row) => JSON.stringify(row)).join("\n")}\n`,
@@ -648,24 +988,137 @@ created_at: 2026-08-10T11:01:00.000Z
648
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",
649
989
  );
650
990
  const run = (id: string, taskId: string, tokens: number) => [
651
- { schema_version: 2, event_id: `${id}:1`, run_id: id, sequence: 1, occurred_at: "2026-08-08T12:00:00.000Z", type: "run.started", attribution_status: "attributed", phase: "execution", run_role: "orchestrator", run_purpose: "execution", requires_finalizer: false, execution_kind: "delivery", execution_eligibility: ["delivery"], entrypoint: "task", work_type: "new", storage_mode: "tracked_sanitized", client: "codex", agent: "agent", agent_name: "agent", provider: "openai", model: "gpt-a", reasoning_effort: null, client_thread_id: id, client_turn_id: id, conversation_id: `CONV-${id}`, execution_id: `EXEC-${id}`, task_id: taskId, spec_id: null, prd_id: null, change_id: null, parent_run_id: null, continuation_of_run_id: null, retry_of_run_id: null, agent_invocation_id: `AINV-${id}`, root_agent_invocation_id: `AINV-${id}`, parent_agent_invocation_id: null, invocation_kind: "orchestrator", delegation_depth: 0 },
652
- { schema_version: 2, event_id: `${id}:2`, run_id: id, sequence: 2, occurred_at: "2026-08-08T12:00:30.000Z", type: "usage.recorded", phase: "execution", activity_kind: "model_usage", classification_source: "explicit", tokens: { input: tokens, cached_input: 0, output: 0, reasoning: 0, total: tokens, source: "provider_reported" }, cost: { usd: tokens / 100, brl: tokens / 20, fx_rate: 5 }, provider: "openai", model: "gpt-a", source_segment_key: id, model_call_id: `MCALL-${id}`, runtime: { reasoning_effort: null, service_tier: null }, supersedes_event_id: null, source_started_at: "2026-08-08T12:00:00.000Z", source_finished_at: "2026-08-08T12:01:00.000Z", duration_ms: null, duration_provenance: null },
653
- { schema_version: 2, event_id: `${id}:3`, run_id: id, sequence: 3, occurred_at: "2026-08-08T12:01:00.000Z", type: "run.finished", phase: "execution", status: "completed", duration_ms: 60_000, duration_provenance: "observed" },
991
+ {
992
+ schema_version: 2,
993
+ event_id: `${id}:1`,
994
+ run_id: id,
995
+ sequence: 1,
996
+ occurred_at: "2026-08-08T12:00:00.000Z",
997
+ type: "run.started",
998
+ attribution_status: "attributed",
999
+ phase: "execution",
1000
+ run_role: "orchestrator",
1001
+ run_purpose: "execution",
1002
+ requires_finalizer: false,
1003
+ execution_kind: "delivery",
1004
+ execution_eligibility: ["delivery"],
1005
+ entrypoint: "task",
1006
+ work_type: "new",
1007
+ storage_mode: "tracked_sanitized",
1008
+ client: "codex",
1009
+ agent: "agent",
1010
+ agent_name: "agent",
1011
+ provider: "openai",
1012
+ model: "gpt-a",
1013
+ reasoning_effort: null,
1014
+ client_thread_id: id,
1015
+ client_turn_id: id,
1016
+ conversation_id: `CONV-${id}`,
1017
+ execution_id: `EXEC-${id}`,
1018
+ task_id: taskId,
1019
+ spec_id: null,
1020
+ prd_id: null,
1021
+ change_id: null,
1022
+ parent_run_id: null,
1023
+ continuation_of_run_id: null,
1024
+ retry_of_run_id: null,
1025
+ agent_invocation_id: `AINV-${id}`,
1026
+ root_agent_invocation_id: `AINV-${id}`,
1027
+ parent_agent_invocation_id: null,
1028
+ invocation_kind: "orchestrator",
1029
+ delegation_depth: 0,
1030
+ },
1031
+ {
1032
+ schema_version: 2,
1033
+ event_id: `${id}:2`,
1034
+ run_id: id,
1035
+ sequence: 2,
1036
+ occurred_at: "2026-08-08T12:00:30.000Z",
1037
+ type: "usage.recorded",
1038
+ phase: "execution",
1039
+ activity_kind: "model_usage",
1040
+ classification_source: "explicit",
1041
+ tokens: {
1042
+ input: tokens,
1043
+ cached_input: 0,
1044
+ output: 0,
1045
+ reasoning: 0,
1046
+ total: tokens,
1047
+ source: "provider_reported",
1048
+ },
1049
+ cost: { usd: tokens / 100, brl: tokens / 20, fx_rate: 5 },
1050
+ provider: "openai",
1051
+ model: "gpt-a",
1052
+ source_segment_key: id,
1053
+ model_call_id: `MCALL-${id}`,
1054
+ runtime: { reasoning_effort: null, service_tier: null },
1055
+ supersedes_event_id: null,
1056
+ source_started_at: "2026-08-08T12:00:00.000Z",
1057
+ source_finished_at: "2026-08-08T12:01:00.000Z",
1058
+ duration_ms: null,
1059
+ duration_provenance: null,
1060
+ },
1061
+ {
1062
+ schema_version: 2,
1063
+ event_id: `${id}:3`,
1064
+ run_id: id,
1065
+ sequence: 3,
1066
+ occurred_at: "2026-08-08T12:01:00.000Z",
1067
+ type: "run.finished",
1068
+ phase: "execution",
1069
+ status: "completed",
1070
+ duration_ms: 60_000,
1071
+ duration_provenance: "observed",
1072
+ },
654
1073
  ];
655
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", "RUN-CANONICAL.jsonl"), `${run("RUN-CANONICAL", "TASK-CANONICAL", 7).map((row) => JSON.stringify(row)).join("\n")}\n`);
656
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", "RUN-ORPHAN.jsonl"), `${run("RUN-ORPHAN", "TASK-ORPHAN-REFERENCE", 11).map((row) => JSON.stringify(row)).join("\n")}\n`);
1074
+ await writeFile(
1075
+ join(root, ".agents", "records", "runs", "2026", "08", "RUN-CANONICAL.jsonl"),
1076
+ `${run("RUN-CANONICAL", "TASK-CANONICAL", 7)
1077
+ .map((row) => JSON.stringify(row))
1078
+ .join("\n")}\n`,
1079
+ );
1080
+ await writeFile(
1081
+ join(root, ".agents", "records", "runs", "2026", "08", "RUN-ORPHAN.jsonl"),
1082
+ `${run("RUN-ORPHAN", "TASK-ORPHAN-REFERENCE", 11)
1083
+ .map((row) => JSON.stringify(row))
1084
+ .join("\n")}\n`,
1085
+ );
657
1086
 
658
1087
  await rebuildSqliteReadModel(root);
659
- const snapshot = new DatabaseSync(resolve(root, ".local/dashboard-sqlite/read-model.sqlite"), { readOnly: true });
660
- expect(snapshot.prepare("SELECT value FROM zaip_vw_read_model_metadata WHERE key='schema_version'").get()).toEqual({ value: "60" });
1088
+ const snapshot = new DatabaseSync(resolve(root, ".local/dashboard-sqlite/read-model.sqlite"), {
1089
+ readOnly: true,
1090
+ });
1091
+ expect(
1092
+ snapshot
1093
+ .prepare("SELECT value FROM zaip_vw_read_model_metadata WHERE key='schema_version'")
1094
+ .get(),
1095
+ ).toEqual({ value: "60" });
661
1096
  snapshot.close();
662
1097
  const filesystem = new SqliteReadModelFileSystem(root);
663
1098
  try {
664
1099
  expect(filesystem.viewPage("operations_work_kanban", { limit: 20 }).rows).toEqual([
665
1100
  expect.objectContaining({ id: "TASK-CANONICAL", title: "Titulo semantico canonico" }),
666
1101
  ]);
1102
+ // The List export is sourced from this SQLite view, so its known facts
1103
+ // must survive the public entity union rather than be left as blank XLSX
1104
+ // columns by a mapper that only receives identity fields.
1105
+ expect(filesystem.viewPage("operations_work_list", { limit: 20 }).rows).toContainEqual(
1106
+ expect.objectContaining({
1107
+ id: "TASK-CANONICAL",
1108
+ invocation_count: 1,
1109
+ total_duration: 30_000,
1110
+ total_tokens: 7,
1111
+ total_cost_brl: 0.35,
1112
+ }),
1113
+ );
667
1114
  const costTasks = filesystem.viewPage("cost_monitor_tasks", { limit: 20 }).rows;
668
- expect(costTasks).toContainEqual(expect.objectContaining({ id: "TASK-ORPHAN-REFERENCE", total_tokens: 11, total_cost_brl: 0.55 }));
1115
+ expect(costTasks).toContainEqual(
1116
+ expect.objectContaining({
1117
+ id: "TASK-ORPHAN-REFERENCE",
1118
+ total_tokens: 11,
1119
+ total_cost_brl: 0.55,
1120
+ }),
1121
+ );
669
1122
  } finally {
670
1123
  filesystem.close();
671
1124
  }
@@ -691,14 +1144,129 @@ created_at: 2026-08-10T11:01:00.000Z
691
1144
  source: "fixture",
692
1145
  disclaimer: "fixture",
693
1146
  models: [
694
- { id: "gpt-a", provider: "openai", aliases: [], input_per_million_usd: 2, cached_input_per_million_usd: 0.2, output_per_million_usd: 8, reasoning_per_million_usd: 8, reasoning_billed_separately: false, long_context_threshold_tokens: null, long_context_input_multiplier: 1, long_context_output_multiplier: 1, source_label: "fixture-openai", source_url: "https://example.test/openai", notes: [] },
695
- { id: "claude-b", provider: "anthropic", aliases: [], input_per_million_usd: 3, cached_input_per_million_usd: 0.3, output_per_million_usd: 12, reasoning_per_million_usd: null, reasoning_billed_separately: false, long_context_threshold_tokens: null, long_context_input_multiplier: 1, long_context_output_multiplier: 1, source_label: "fixture-anthropic", source_url: "https://example.test/anthropic", notes: [] },
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
+ },
696
1179
  ],
697
1180
  }),
698
1181
  );
699
- const started = { schema_version: 2, event_id: "RUN-MULTI:1", run_id: "RUN-MULTI", sequence: 1, occurred_at: "2026-08-04T12:00:00.000Z", type: "run.started", attribution_status: "attributed", phase: "execution", run_role: "orchestrator", run_purpose: "execution", requires_finalizer: false, execution_kind: "delivery", execution_eligibility: ["delivery"], entrypoint: "task", work_type: "new", storage_mode: "tracked_sanitized", client: "codex", agent: "agent", agent_name: "agent", provider: "mixed", model: "mixed", reasoning_effort: null, client_thread_id: "multi", client_turn_id: "multi", conversation_id: "CONV-MULTI", execution_id: "EXEC-MULTI", task_id: "TASK-MULTI", spec_id: null, prd_id: null, change_id: null, parent_run_id: null, continuation_of_run_id: null, retry_of_run_id: null, agent_invocation_id: "AINV-MULTI", root_agent_invocation_id: "AINV-MULTI", parent_agent_invocation_id: null, invocation_kind: "orchestrator", delegation_depth: 0 };
700
- const usage = (sequence: number, provider: string, model: string, tokens: number, brl: number) => ({ schema_version: 2, event_id: `RUN-MULTI:${sequence}`, run_id: "RUN-MULTI", sequence, occurred_at: "2026-08-04T12:00:01.000Z", type: "usage.recorded", phase: "execution", activity_kind: "model_usage", classification_source: "explicit", tokens: { input: tokens, cached_input: 0, output: 0, reasoning: 0, total: tokens, source: "provider_reported" }, cost: { usd: brl / 5, brl, fx_rate: 5 }, provider, model, source_segment_key: `${provider}-${model}`, model_call_id: `MCALL-${sequence}`, runtime: { reasoning_effort: null, service_tier: null }, supersedes_event_id: null, source_started_at: "2026-08-04T12:00:00.000Z", source_finished_at: "2026-08-04T12:01:00.000Z", duration_ms: null, duration_provenance: null });
701
- const finished = { schema_version: 2, event_id: "RUN-MULTI:5", run_id: "RUN-MULTI", sequence: 5, occurred_at: "2026-08-04T12:01:00.000Z", type: "run.finished", phase: "execution", status: "completed", duration_ms: 60_000, duration_provenance: "observed" };
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
+ };
702
1270
  const mixedNullSegment = {
703
1271
  ...usage(4, "openai", "gpt-a", 0, 0),
704
1272
  event_id: "RUN-MULTI:4",
@@ -707,7 +1275,10 @@ created_at: 2026-08-10T11:01:00.000Z
707
1275
  source_segment_key: "mixed-null",
708
1276
  model_call_id: "MCALL-MIXED-NULL",
709
1277
  };
710
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", "RUN-MULTI.jsonl"), `${[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`);
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
+ );
711
1282
  const unavailableStarted = {
712
1283
  ...started,
713
1284
  event_id: "RUN-UNAVAILABLE:1",
@@ -748,7 +1319,12 @@ created_at: 2026-08-10T11:01:00.000Z
748
1319
  );
749
1320
  // It is a canonical activity but not an Agent Invocation. Cost Monitor
750
1321
  // must not blend this population into its token/cost/session rate.
751
- const { agent_invocation_id: _invocation, root_agent_invocation_id: _rootInvocation, parent_agent_invocation_id: _parentInvocation, ...unassistedBase } = started;
1322
+ const {
1323
+ agent_invocation_id: _invocation,
1324
+ root_agent_invocation_id: _rootInvocation,
1325
+ parent_agent_invocation_id: _parentInvocation,
1326
+ ...unassistedBase
1327
+ } = started;
752
1328
  const unassistedStarted = {
753
1329
  ...unassistedBase,
754
1330
  event_id: "RUN-UNASSISTED:1",
@@ -773,27 +1349,46 @@ created_at: 2026-08-10T11:01:00.000Z
773
1349
  `${[unassistedStarted, unassistedUsage, { ...finished, event_id: "RUN-UNASSISTED:3", run_id: "RUN-UNASSISTED", sequence: 3 }].map((row) => JSON.stringify(row)).join("\n")}\n`,
774
1350
  );
775
1351
  await rebuildSqliteReadModel(root);
776
- const aggregateDatabase = new DatabaseSync(resolve(root, ".local/dashboard-sqlite/read-model.sqlite"), {
777
- readOnly: true,
778
- });
1352
+ const aggregateDatabase = new DatabaseSync(
1353
+ resolve(root, ".local/dashboard-sqlite/read-model.sqlite"),
1354
+ {
1355
+ readOnly: true,
1356
+ },
1357
+ );
779
1358
  try {
780
- const aggregates = aggregateDatabase.prepare(`SELECT
1359
+ const aggregates = aggregateDatabase
1360
+ .prepare(`SELECT
781
1361
  json_extract(payload_json, '$.dimension') AS dimension,
782
1362
  json_extract(payload_json, '$.key') AS key,
783
1363
  json_extract(payload_json, '$.schema_version') AS schema_version,
784
1364
  json_extract(payload_json, '$.total_cost_brl') AS total_cost_brl
785
1365
  FROM zaip_aios_activities
786
- WHERE payload_type = 'cost_dimension_aggregate_v1'`).all();
787
- expect(aggregates).toEqual(expect.arrayContaining([
788
- expect.objectContaining({ dimension: "provider", key: "openai", schema_version: 1, total_cost_brl: 505 }),
789
- expect.objectContaining({ dimension: "model", key: "gpt-a", schema_version: 1, total_cost_brl: 505 }),
790
- ]));
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
+ );
791
1384
  expect(aggregates.map((row) => row.key)).toEqual(expect.arrayContaining(["unavailable"]));
792
1385
  } finally {
793
1386
  aggregateDatabase.close();
794
1387
  }
795
1388
  const filesystem = new SqliteReadModelFileSystem(root);
796
- expect(filesystem.viewPage("cost_monitor_daily", { from: "2026-08-04", to: "2026-08-04" }).rows[0]).toMatchObject({ total_tokens: 1_030, total_cost_brl: 515 });
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 });
797
1392
  // The public overview view backs /api/v2/sqlite-views. It must not leak
798
1393
  // Cost Monitor retains all measurable financial activities, including
799
1394
  // historical/unassisted telemetry without an Agent Invocation id.
@@ -801,83 +1396,204 @@ created_at: 2026-08-10T11:01:00.000Z
801
1396
  expect(publicOverview.rows).toHaveLength(3);
802
1397
  expect(publicOverview.rows).toEqual(
803
1398
  expect.arrayContaining([
804
- expect.objectContaining({ period_kind: "day", total_run_count: 3, invocation_count: 3, total_tokens: 1_030, total_cost_brl: 515 }),
805
- expect.objectContaining({ period_kind: "month", total_run_count: 3, invocation_count: 3, total_tokens: 1_030, total_cost_brl: 515 }),
806
- expect.objectContaining({ period_kind: "year", total_run_count: 3, invocation_count: 3, total_tokens: 1_030, total_cost_brl: 515 }),
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
+ }),
1413
+ 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,
1419
+ }),
807
1420
  ]),
808
1421
  );
809
- const allAgentGroups = filesystem.viewPage("cost_monitor_zaip_agents", { limit: 20, offset: 0 });
1422
+ const allAgentGroups = filesystem.viewPage("cost_monitor_zaip_agents", {
1423
+ limit: 20,
1424
+ offset: 0,
1425
+ });
810
1426
  const allCostTotals = publicOverview.rows.find((row) => row.period_kind === "day");
811
1427
  if (allCostTotals === undefined) throw new Error("Expected the daily Cost Monitor overview");
812
- expect(allAgentGroups.rows.reduce((total, row) => total + Number(row.invocation_count ?? 0), 0)).toBe(allCostTotals.total_run_count);
813
- expect(allAgentGroups.rows.reduce((total, row) => total + Number(row.total_tokens ?? 0), 0)).toBe(allCostTotals?.total_tokens);
814
- expect(allAgentGroups.rows.reduce((total, row) => total + Number(row.total_cost_brl ?? 0), 0)).toBe(allCostTotals?.total_cost_brl);
815
- expect(allAgentGroups.rows.reduce((total, row) => total + Number(row.total_cost_usd ?? 0), 0)).toBe(allCostTotals.total_cost_usd);
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);
816
1440
  // Shared Cost Tempo is factual at the activity grain. It remains available
817
1441
  // in the agent-table total even where a multi-dimension invocation cannot
818
1442
  // be assigned to an individual Agent row.
819
1443
  expect(allCostTotals.cost_monitor_total_duration).toBe(120_000);
820
- expect(allAgentGroups.totals).toMatchObject({ invocation_count: allCostTotals.total_run_count, total_duration: 120_000, total_tokens: allCostTotals.total_tokens, total_cost_usd: allCostTotals.total_cost_usd, total_cost_brl: allCostTotals.total_cost_brl });
821
- for (const [providers, models] of [[ ["openai"], ["gpt-a"] ], [["anthropic"], ["claude-b"] ]] as const) {
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) {
822
1455
  const rows = filesystem.invocationCostRows({ from: null, to: null, providers, models });
823
1456
  expect(rows).toHaveLength(1);
824
1457
  // Membership is segment-based; once the invocation matches, its
825
1458
  // canonical invocation totals remain intact rather than being split.
826
1459
  expect(rows[0]).toMatchObject({ total_tokens: 30, cost_brl: 15 });
827
- expect([...filesystem.executionDurationByDay({ from: null, to: null, providers, models }).values()]).toEqual([60_000]);
828
- expect([...filesystem.canonicalRunCountByDay({ from: null, to: null, providers, models }).values()]).toEqual([1]);
829
- for (const view of ["cost_monitor_daily", "cost_monitor_monthly", "cost_monitor_annual"] as const) {
830
- const page = filesystem.viewPage(view, { provider: providers[0], model: models[0], limit: 20, offset: 0 });
831
- expect(page.rows[0]).toMatchObject({ total_run_count: 1, total_tokens: 30, total_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
+ });
832
1482
  }
833
- const agents = filesystem.viewPage("cost_monitor_zaip_agents", { provider: providers[0], model: models[0], query: "agent" });
834
- const financialRows = filesystem.costMonitorFinancialActivityRows({ from: null, to: null, providers, models });
835
- const financialTotals = financialRows.reduce<{ invocation_count: number; total_tokens: number; total_cost_brl: number }>((total, row) => ({
836
- invocation_count: total.invocation_count + 1,
837
- total_tokens: total.total_tokens + Number(row.total_tokens ?? 0),
838
- total_cost_brl: total.total_cost_brl + Number(row.cost_brl ?? 0),
839
- }), { invocation_count: 0, total_tokens: 0, total_cost_brl: 0 });
840
- expect(agents.rows[0]).toMatchObject({ key: "agent", persona: "ana", job: "quality_engineer", task_count: 1, ...financialTotals });
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({
1489
+ from: null,
1490
+ to: null,
1491
+ providers,
1492
+ models,
1493
+ });
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),
1503
+ }),
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
+ });
841
1513
  expect(agents.totals).toMatchObject(financialTotals);
842
1514
  }
843
1515
  const crossed = { from: null, to: null, providers: ["openai"], models: ["claude-b"] };
844
1516
  expect(filesystem.invocationCostRows(crossed)).toHaveLength(0);
845
1517
  expect([...filesystem.executionDurationByDay(crossed).values()]).toEqual([]);
846
1518
  expect([...filesystem.canonicalRunCountByDay(crossed).values()]).toEqual([]);
847
- expect(filesystem.viewPage("cost_monitor_agent_invocations", { provider: "openai", model: "claude-b" }).total_count).toBe(0);
848
- expect(filesystem.viewPage("cost_monitor_zaip_agents", { provider: "openai", model: "claude-b" }).total_count).toBe(0);
849
- for (const view of ["cost_monitor_daily", "cost_monitor_monthly", "cost_monitor_annual"] as const) {
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) {
850
1534
  // Lifecycle buckets can remain present independently, but the crossed
851
1535
  // pair must contribute no invocation financial or Run facts.
852
1536
  const row = filesystem.viewPage(view, { provider: "openai", model: "claude-b" }).rows[0];
853
- expect(row).toMatchObject({ total_run_count: 0, total_duration: null, total_tokens: null, total_cost_brl: null });
1537
+ expect(row).toMatchObject({
1538
+ total_run_count: 0,
1539
+ total_duration: null,
1540
+ total_tokens: null,
1541
+ total_cost_brl: null,
1542
+ });
854
1543
  }
855
- for (const view of ["cost_monitor_daily", "cost_monitor_monthly", "cost_monitor_annual"] as const) {
1544
+ for (const view of [
1545
+ "cost_monitor_daily",
1546
+ "cost_monitor_monthly",
1547
+ "cost_monitor_annual",
1548
+ ] as const) {
856
1549
  const originFiltered = filesystem.viewPage(view, { origin: "task" });
857
- expect(originFiltered.rows[0]).toMatchObject({ prd_count: null, spec_count: null, task_count: null, validation_count: null, evidence_count: null });
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
+ });
858
1557
  expect(filesystem.viewPage(view, { workType: "new" }).total_count).toBe(0);
859
1558
  }
860
- expect(filesystem.viewPage("cost_monitor_zaip_agents", { priority: "high" })).toMatchObject({ total_count: 0, rows: [] });
1559
+ expect(filesystem.viewPage("cost_monitor_zaip_agents", { priority: "high" })).toMatchObject({
1560
+ total_count: 0,
1561
+ rows: [],
1562
+ });
861
1563
  const providerGroups = filesystem.viewPage("cost_monitor_providers", { limit: 20, offset: 0 });
862
- expect(providerGroups.rows).toEqual(expect.arrayContaining([
863
- expect.objectContaining({ key: "openai", total_tokens: 1_010, total_cost_brl: 505 }),
864
- expect.objectContaining({ key: "anthropic", total_tokens: 20, total_cost_brl: 10 }),
865
- ]));
866
- expect(providerGroups.rows.map((row) => row.key)).toEqual(expect.arrayContaining(["unavailable"]));
867
- expect(filesystem.viewPage("cost_monitor_providers", { provider: "openai", model: "gpt-a" }).rows.find((row) => row.key === "openai")).toMatchObject({ total_tokens: 10, total_cost_brl: 5 });
868
- expect(filesystem.viewPage("cost_monitor_providers", { provider: "openai", model: "claude-b" })).toMatchObject({ total_count: 0, rows: [] });
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: [] });
869
1581
  // A source segment can prove its financial facts, but an invocation with
870
1582
  // multiple observed providers cannot prove a provider-specific elapsed
871
1583
  // time. It must not manufacture a "mixed" bucket for that remainder.
872
- const queriedProviderRows = filesystem.viewPage("cost_monitor_providers", { query: "openai" }).rows;
1584
+ const queriedProviderRows = filesystem.viewPage("cost_monitor_providers", {
1585
+ query: "openai",
1586
+ }).rows;
873
1587
  expect(queriedProviderRows).toEqual([
874
1588
  expect.objectContaining({ key: "openai", total_tokens: 10, total_cost_brl: 5 }),
875
1589
  ]);
876
1590
  const modelGroups = filesystem.viewPage("cost_monitor_models", { limit: 20, offset: 0 });
877
- expect(modelGroups.rows).toEqual(expect.arrayContaining([
878
- expect.objectContaining({ key: "gpt-a", total_tokens: 1_010, total_cost_brl: 505 }),
879
- expect.objectContaining({ key: "claude-b", total_tokens: 20, total_cost_brl: 10 }),
880
- ]));
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
+ );
881
1597
  // First-fold transport is aggregate-only, but its overview chart must
882
1598
  // retain the segment-backed model rows instead of falling back to the
883
1599
  // empty availability metadata.
@@ -888,7 +1604,13 @@ created_at: 2026-08-10T11:01:00.000Z
888
1604
  ]),
889
1605
  );
890
1606
  expect(modelGroups.rows.map((row) => row.key)).toEqual(expect.arrayContaining(["unavailable"]));
891
- const modelTotals = modelGroups.rows.reduce<{ invocations: number; tasks: number; duration: number; tokens: number; brl: number }>(
1607
+ const modelTotals = modelGroups.rows.reduce<{
1608
+ invocations: number;
1609
+ tasks: number;
1610
+ duration: number;
1611
+ tokens: number;
1612
+ brl: number;
1613
+ }>(
892
1614
  (total, row) => ({
893
1615
  invocations: total.invocations + Number(row.invocation_count ?? 0),
894
1616
  tasks: total.tasks + Number(row.task_count ?? 0),
@@ -898,12 +1620,30 @@ created_at: 2026-08-10T11:01:00.000Z
898
1620
  }),
899
1621
  { invocations: 0, tasks: 0, duration: 0, tokens: 0, brl: 0 },
900
1622
  );
901
- expect(modelTotals).toEqual({ invocations: 2, tasks: 3, duration: 60_000, tokens: 1030, brl: 515 });
1623
+ expect(modelTotals).toEqual({
1624
+ invocations: 2,
1625
+ tasks: 3,
1626
+ duration: 60_000,
1627
+ tokens: 1030,
1628
+ brl: 515,
1629
+ });
902
1630
  expect(filesystem.viewPage("cost_monitor_models", { query: "gpt-a" }).rows).toHaveLength(1);
903
- expect(filesystem.viewPage("cost_monitor_models", { provider: "openai", model: "gpt-a" }).rows[0]).toMatchObject({ key: "gpt-a", total_tokens: 1010, total_cost_brl: 505 });
904
- expect(filesystem.viewPage("cost_monitor_models", { provider: "openai", model: "claude-b" })).toMatchObject({ total_count: 0, rows: [] });
905
- expect(filesystem.viewPage("cost_monitor_models", { priority: "high" })).toMatchObject({ total_count: 0, rows: [] });
906
- const unavailable = { from: null, to: null, providers: ["unavailable"], models: ["unavailable"] };
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
+ };
907
1647
  const unavailableRows = filesystem.invocationCostRows(unavailable);
908
1648
  expect(unavailableRows).toHaveLength(1);
909
1649
  // Observed zero telemetry stays zero, while the missing provider/model
@@ -920,51 +1660,247 @@ created_at: 2026-08-10T11:01:00.000Z
920
1660
  });
921
1661
  expect(unavailableInvocation).toMatchObject({ total_count: 1 });
922
1662
  expect(unavailableInvocation.rows[0]).toMatchObject({ input_tokens: 0 });
923
- for (const view of ["cost_monitor_daily", "cost_monitor_monthly", "cost_monitor_annual"] as const) {
924
- const row = filesystem.viewPage(view, { provider: "unavailable", model: "unavailable" }).rows[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];
925
1670
  expect(row).toMatchObject({ total_run_count: 2, total_tokens: 1_000, total_cost_brl: 500 });
926
1671
  }
927
1672
 
928
1673
  filesystem.close();
929
- const sameModelStarted = { ...started, event_id: "RUN-SAME-MODEL:1", run_id: "RUN-SAME-MODEL", occurred_at: "2026-08-05T12:00:00.000Z", client_turn_id: "same-model", conversation_id: "CONV-SAME-MODEL", execution_id: "EXEC-SAME-MODEL", task_id: "TASK-SAME-MODEL", agent_invocation_id: "AINV-SAME-MODEL", root_agent_invocation_id: "AINV-SAME-MODEL", provider: "mixed", model: "gpt-a" };
930
- const sameModelUsage = (sequence: number, provider: string, tokens: number, brl: number) => ({ ...usage(sequence, provider, "gpt-a", tokens, brl), event_id: `RUN-SAME-MODEL:${sequence}`, run_id: "RUN-SAME-MODEL", occurred_at: "2026-08-05T12:00:01.000Z", source_started_at: "2026-08-05T12:00:00.000Z", source_finished_at: "2026-08-05T12:01:00.000Z" });
931
- const sameModelFinished = { ...finished, event_id: "RUN-SAME-MODEL:4", run_id: "RUN-SAME-MODEL", sequence: 4, occurred_at: "2026-08-05T12:01:00.000Z" };
932
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", "RUN-SAME-MODEL.jsonl"), `${[sameModelStarted, sameModelUsage(2, "openai", 3, 1.5), sameModelUsage(3, "anthropic", 4, 2), sameModelFinished].map((row) => JSON.stringify(row)).join("\n")}\n`);
933
- const durationRun = (id: string, day: string, duration: number | null, provenance: "reconciled" | "estimated") => {
934
- const start = { ...sameModelStarted, event_id: `${id}:1`, run_id: id, occurred_at: `${day}T12:00:00.000Z`, client_turn_id: id, conversation_id: `CONV-${id}`, execution_id: `EXEC-${id}`, task_id: `TASK-${id}`, agent_invocation_id: `AINV-${id}`, root_agent_invocation_id: `AINV-${id}` };
935
- const measured = { ...usage(2, "openai", "gpt-a", provenance === "estimated" ? 4_000_000 : 9, provenance === "estimated" ? 0 : 4.5), event_id: `${id}:2`, run_id: id, occurred_at: `${day}T12:00:01.000Z`, source_started_at: `${day}T12:00:00.000Z`, source_finished_at: `${day}T12:01:00.000Z`, ...(duration === null ? {} : { duration_ms: duration, duration_provenance: provenance }) };
936
- const end = { ...finished, event_id: `${id}:3`, run_id: id, sequence: 3, occurred_at: `${day}T12:01:00.000Z`, ...(provenance === "estimated" ? { duration_ms: null, duration_provenance: "unavailable" } : {}) };
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
+ };
1703
+ 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`,
1706
+ );
1707
+ const durationRun = (
1708
+ id: string,
1709
+ day: string,
1710
+ duration: number | null,
1711
+ provenance: "reconciled" | "estimated",
1712
+ ) => {
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,
1742
+ event_id: `${id}:3`,
1743
+ run_id: id,
1744
+ sequence: 3,
1745
+ occurred_at: `${day}T12:01:00.000Z`,
1746
+ ...(provenance === "estimated"
1747
+ ? { duration_ms: null, duration_provenance: "unavailable" }
1748
+ : {}),
1749
+ };
937
1750
  return [start, measured, end];
938
1751
  };
939
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", "RUN-RECONCILED-MODEL.jsonl"), `${durationRun("RUN-RECONCILED-MODEL", "2026-08-06", 45_000, "reconciled").map((row) => JSON.stringify(row)).join("\n")}\n`);
940
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", "RUN-ESTIMATED-MODEL.jsonl"), `${durationRun("RUN-ESTIMATED-MODEL", "2026-08-07", null, "estimated").map((row) => JSON.stringify(row)).join("\n")}\n`);
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
+ );
941
1764
  const sharedTaskRun = (id: string, model: string, tokens: number, brl: number) => [
942
- { ...sameModelStarted, event_id: `${id}:1`, run_id: id, occurred_at: "2026-08-08T12:00:00.000Z", client_turn_id: id, conversation_id: `CONV-${id}`, execution_id: `EXEC-${id}`, task_id: "TASK-CROSS-MODEL", agent_invocation_id: `AINV-${id}`, root_agent_invocation_id: `AINV-${id}`, provider: "openai", model },
943
- { ...usage(2, "openai", model, tokens, brl), event_id: `${id}:2`, run_id: id, occurred_at: "2026-08-08T12:00:01.000Z", source_started_at: "2026-08-08T12:00:00.000Z", source_finished_at: "2026-08-08T12:01:00.000Z" },
944
- { ...finished, event_id: `${id}:3`, run_id: id, sequence: 3, occurred_at: "2026-08-08T12:01:00.000Z" },
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",
1793
+ },
945
1794
  ];
946
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", "RUN-TASK-GPT.jsonl"), `${sharedTaskRun("RUN-TASK-GPT", "gpt-a", 5, 2.5).map((row) => JSON.stringify(row)).join("\n")}\n`);
947
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", "RUN-TASK-CLAUDE.jsonl"), `${sharedTaskRun("RUN-TASK-CLAUDE", "claude-b", 6, 3).map((row) => JSON.stringify(row)).join("\n")}\n`);
948
- const subrunStarted = { ...sameModelStarted, event_id: "RUN-PROVIDER-SUBRUN:1", run_id: "RUN-PROVIDER-SUBRUN", occurred_at: "2026-08-09T12:00:00.000Z", client_turn_id: "provider-subrun", conversation_id: "CONV-PROVIDER-SUBRUN", execution_id: "EXEC-PROVIDER-SUBRUN", task_id: "TASK-PROVIDER-SUBRUN", agent_invocation_id: "AINV-PROVIDER-SUBRUN", root_agent_invocation_id: "AINV-SAME-MODEL", parent_agent_invocation_id: "AINV-SAME-MODEL", parent_run_id: "RUN-SAME-MODEL", run_role: "subagent", invocation_kind: "delegated", delegation_depth: 1, provider: "openai", model: "gpt-a" };
949
- const subrunUsage = { ...usage(2, "openai", "gpt-a", 8, 4), event_id: "RUN-PROVIDER-SUBRUN:2", run_id: "RUN-PROVIDER-SUBRUN", occurred_at: "2026-08-09T12:00:01.000Z", source_started_at: "2026-08-09T12:00:00.000Z", source_finished_at: "2026-08-09T12:00:30.000Z" };
950
- const subrunFinished = { ...finished, event_id: "RUN-PROVIDER-SUBRUN:3", run_id: "RUN-PROVIDER-SUBRUN", sequence: 3, occurred_at: "2026-08-09T12:00:30.000Z", duration_ms: 30_000, duration_provenance: "observed" };
951
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", "RUN-PROVIDER-SUBRUN.jsonl"), `${[subrunStarted, subrunUsage, subrunFinished].map((row) => JSON.stringify(row)).join("\n")}\n`);
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",
1842
+ };
1843
+ 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`,
1846
+ );
952
1847
  await rebuildSqliteReadModel(root);
953
1848
  const sameModelFs = new SqliteReadModelFileSystem(root);
954
- const modelRow = (filter: Record<string, string>) => sameModelFs.viewPage("cost_monitor_models", { from: "2026-08-05", to: "2026-08-05", ...filter }).rows.find((row) => row.key === "gpt-a");
955
- expect(modelRow({ provider: "openai", model: "gpt-a" })).toMatchObject({ invocation_count: 1, task_count: 1, total_duration: 60_000, total_tokens: 3, total_cost_brl: 1.5 });
956
- expect(modelRow({ provider: "anthropic", model: "gpt-a" })).toMatchObject({ invocation_count: 1, task_count: 1, total_duration: 60_000, total_tokens: 4, total_cost_brl: 2 });
957
- expect(modelRow({})).toMatchObject({ invocation_count: 1, task_count: 1, total_duration: 60_000, total_tokens: 7, total_cost_brl: 3.5 });
958
- expect(sameModelFs.viewPage("cost_monitor_models", { from: "2026-08-05", to: "2026-08-05", provider: "openai", model: "claude-b" })).toMatchObject({ total_count: 0, rows: [] });
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: [] });
959
1882
  for (const day of ["2026-08-06", "2026-08-07"]) {
960
- const effective = sameModelFs.invocationCostRows({ from: day, to: day }).reduce((sum, row) => sum + Number(row.duration_ms ?? 0), 0);
961
- const modelDuration = sameModelFs.viewPage("cost_monitor_models", { from: day, to: day }).rows.reduce((sum, row) => sum + Number(row.total_duration ?? 0), 0);
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);
962
1889
  expect(modelDuration).toBe(effective);
963
1890
  }
964
1891
  for (const day of ["2026-08-06", "2026-08-07"]) {
965
1892
  const population = sameModelFs.invocationCostRows({ from: day, to: day });
966
- const providerRows = sameModelFs.viewPage("cost_monitor_providers", { from: day, to: day }).rows;
967
- const providerTotals = providerRows.reduce<{ invocations: number; tasks: number; duration: number; tokens: number; brl: number }>(
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
+ }>(
968
1904
  (total, row) => ({
969
1905
  invocations: total.invocations + Number(row.invocation_count ?? 0),
970
1906
  tasks: total.tasks + Number(row.task_count ?? 0),
@@ -976,27 +1912,87 @@ created_at: 2026-08-10T11:01:00.000Z
976
1912
  );
977
1913
  expect(providerTotals).toEqual({
978
1914
  invocations: population.length,
979
- tasks: new Set(population.map((row) => row.task_id).filter((id): id is string => typeof id === "string")).size,
1915
+ tasks: new Set(
1916
+ population.map((row) => row.task_id).filter((id): id is string => typeof id === "string"),
1917
+ ).size,
980
1918
  duration: population.reduce((sum, row) => sum + Number(row.duration_ms ?? 0), 0),
981
1919
  tokens: population.reduce((sum, row) => sum + Number(row.total_tokens ?? 0), 0),
982
1920
  brl: population.reduce((sum, row) => sum + Number(row.cost_brl ?? 0), 0),
983
1921
  });
984
1922
  }
985
- const sharedTaskRows = sameModelFs.viewPage("cost_monitor_models", { from: "2026-08-08", to: "2026-08-08" }).rows;
986
- expect(sharedTaskRows).toEqual(expect.arrayContaining([
987
- expect.objectContaining({ key: "gpt-a", invocation_count: 1, task_count: 1, total_duration: 30_000, total_tokens: 5, total_cost_brl: 2.5 }),
988
- expect.objectContaining({ key: "claude-b", invocation_count: 1, task_count: 1, total_duration: 30_000, total_tokens: 6, total_cost_brl: 3 }),
989
- ]));
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([
1929
+ 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,
1936
+ }),
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
+ );
990
1947
  expect(sharedTaskRows.map((row) => row.key)).not.toContain("mixed");
991
1948
  expect(sharedTaskRows.reduce((sum, row) => sum + Number(row.task_count ?? 0), 0)).toBe(2);
992
- const subrunPopulation = sameModelFs.invocationCostRows({ from: "2026-08-09", to: "2026-08-09", providers: ["openai"], models: ["gpt-a"] });
993
- const subrunProviderRows = sameModelFs.viewPage("cost_monitor_providers", { from: "2026-08-09", to: "2026-08-09", provider: "openai", model: "gpt-a" }).rows;
994
- const subrunProviderTotals = subrunProviderRows.reduce<{ invocations: number; tasks: number; duration: number; tokens: number; brl: number }>(
995
- (total, row) => ({ invocations: total.invocations + Number(row.invocation_count ?? 0), tasks: total.tasks + Number(row.task_count ?? 0), duration: total.duration + Number(row.total_duration ?? 0), tokens: total.tokens + Number(row.total_tokens ?? 0), brl: total.brl + Number(row.total_cost_brl ?? 0) }),
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
+ }),
996
1975
  { invocations: 0, tasks: 0, duration: 0, tokens: 0, brl: 0 },
997
1976
  );
998
- expect(subrunProviderTotals).toEqual({ invocations: subrunPopulation.length, tasks: new Set(subrunPopulation.map((row) => row.task_id).filter((id): id is string => typeof id === "string")).size, duration: subrunPopulation.reduce((sum, row) => sum + Number(row.duration_ms ?? 0), 0), tokens: subrunPopulation.reduce((sum, row) => sum + Number(row.total_tokens ?? 0), 0), brl: subrunPopulation.reduce((sum, row) => sum + Number(row.cost_brl ?? 0), 0) });
999
- expect(sameModelFs.viewPage("cost_monitor_providers", { from: "2026-08-09", to: "2026-08-09", provider: "openai", model: "claude-b" })).toMatchObject({ total_count: 0, rows: [] });
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", {
1990
+ from: "2026-08-09",
1991
+ to: "2026-08-09",
1992
+ provider: "openai",
1993
+ model: "claude-b",
1994
+ }),
1995
+ ).toMatchObject({ total_count: 0, rows: [] });
1000
1996
  sameModelFs.close();
1001
1997
  });
1002
1998
 
@@ -1007,7 +2003,7 @@ created_at: 2026-08-10T11:01:00.000Z
1007
2003
  await mkdir(join(root, ".agents", "config"), { recursive: true });
1008
2004
  await writeFile(
1009
2005
  join(root, ".agents", "config", "project.yaml"),
1010
- "schema_version: 1\nzaip:\n enabled: true\nproject:\n id: sqlite-test\n name: sqlite-test\n timezone: UTC\nstack:\n id: zaip-aios-stack\n overrides: {}\nclients:\n codex: true\n claude: true\ntracking:\n enabled: true\n currency: BRL\n storage_mode: tracked_sanitized\n",
2006
+ "schema_version: 1\nzaip:\n enabled: true\nproject:\n id: sqlite-test\n name: sqlite-test\n timezone: UTC\nstack:\n id: zaip-aios-stack\n overrides: {}\nclients:\n codex: true\n claude: true\ntracking:\n enabled: true\n currency: BRL\n storage_mode: tracked_sanitized\n",
1011
2007
  "utf8",
1012
2008
  );
1013
2009
  const started = {
@@ -1216,49 +2212,135 @@ created_at: 2026-08-10T11:01:00.000Z
1216
2212
  await mkdir(join(root, ".agents", "records", "runs", "2026", "07"), { recursive: true });
1217
2213
  await mkdir(join(root, ".agents", "config"), { recursive: true });
1218
2214
  await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n");
1219
- const run = ({ id, phase, sourceStartedAt, sourceFinishedAt, parentRunId = null }: {
1220
- id: string; phase: "conversation" | "planning" | "execution";
1221
- sourceStartedAt: string; sourceFinishedAt: string; parentRunId?: string | null;
2215
+ const run = ({
2216
+ id,
2217
+ phase,
2218
+ sourceStartedAt,
2219
+ sourceFinishedAt,
2220
+ parentRunId = null,
2221
+ }: {
2222
+ id: string;
2223
+ phase: "conversation" | "planning" | "execution";
2224
+ sourceStartedAt: string;
2225
+ sourceFinishedAt: string;
2226
+ parentRunId?: string | null;
1222
2227
  }) => {
1223
2228
  const occurredAt = sourceStartedAt;
1224
2229
  const agentInvocationId = `AINV-${id}`;
1225
2230
  return [
1226
2231
  {
1227
- schema_version: 2, event_id: `${id}:1`, run_id: id, sequence: 1, occurred_at: occurredAt,
1228
- type: "run.started", attribution_status: "attributed", phase, run_role: parentRunId === null ? "orchestrator" : "subagent",
1229
- run_purpose: "orchestration", requires_finalizer: false, execution_kind: "delivery",
1230
- execution_eligibility: ["delivery"], entrypoint: "task", work_type: "new",
1231
- storage_mode: "tracked_sanitized", client: "codex", agent: "agent", agent_name: "agent",
1232
- provider: "openai", model: "gpt-5", reasoning_effort: null, client_thread_id: `thread-${id}`,
1233
- client_turn_id: `turn-${id}`, conversation_id: `CONV-${id}`, execution_id: `EXEC-${id}`,
1234
- task_id: `TASK-${id}`, spec_id: null, prd_id: null, change_id: null, parent_run_id: parentRunId,
1235
- continuation_of_run_id: null, retry_of_run_id: null, agent_invocation_id: agentInvocationId,
2232
+ schema_version: 2,
2233
+ event_id: `${id}:1`,
2234
+ run_id: id,
2235
+ sequence: 1,
2236
+ occurred_at: occurredAt,
2237
+ type: "run.started",
2238
+ attribution_status: "attributed",
2239
+ phase,
2240
+ run_role: parentRunId === null ? "orchestrator" : "subagent",
2241
+ run_purpose: "orchestration",
2242
+ requires_finalizer: false,
2243
+ execution_kind: "delivery",
2244
+ execution_eligibility: ["delivery"],
2245
+ entrypoint: "task",
2246
+ work_type: "new",
2247
+ storage_mode: "tracked_sanitized",
2248
+ client: "codex",
2249
+ agent: "agent",
2250
+ agent_name: "agent",
2251
+ provider: "openai",
2252
+ model: "gpt-5",
2253
+ reasoning_effort: null,
2254
+ client_thread_id: `thread-${id}`,
2255
+ client_turn_id: `turn-${id}`,
2256
+ conversation_id: `CONV-${id}`,
2257
+ execution_id: `EXEC-${id}`,
2258
+ task_id: `TASK-${id}`,
2259
+ spec_id: null,
2260
+ prd_id: null,
2261
+ change_id: null,
2262
+ parent_run_id: parentRunId,
2263
+ continuation_of_run_id: null,
2264
+ retry_of_run_id: null,
2265
+ agent_invocation_id: agentInvocationId,
1236
2266
  root_agent_invocation_id: parentRunId === null ? agentInvocationId : "AINV-root",
1237
2267
  parent_agent_invocation_id: parentRunId === null ? null : "AINV-root",
1238
- invocation_kind: parentRunId === null ? "orchestrator" : "delegated", delegation_depth: parentRunId === null ? 0 : 1,
2268
+ invocation_kind: parentRunId === null ? "orchestrator" : "delegated",
2269
+ delegation_depth: parentRunId === null ? 0 : 1,
1239
2270
  },
1240
2271
  {
1241
- schema_version: 2, event_id: `${id}:2`, run_id: id, sequence: 2, occurred_at: sourceFinishedAt,
1242
- type: "usage.recorded", phase, activity_kind: "retrospective_local_remeasurement",
1243
- classification_source: "current_context", tokens: { input: 1, cached_input: 0, output: 1, reasoning: 0, total: 2, source: "provider_reported" },
1244
- cost: { usd: 1, brl: 5, fx_rate: 5 }, provider: "openai", model: "gpt-5", source_segment_key: id,
1245
- model_call_id: `MCALL-${id}`, runtime: { reasoning_effort: null, service_tier: null }, supersedes_event_id: null,
1246
- retrospective_correction: true, source_occurred_at: sourceFinishedAt, source_started_at: sourceStartedAt,
1247
- source_finished_at: sourceFinishedAt, duration_ms: null, duration_provenance: null,
2272
+ schema_version: 2,
2273
+ event_id: `${id}:2`,
2274
+ run_id: id,
2275
+ sequence: 2,
2276
+ occurred_at: sourceFinishedAt,
2277
+ type: "usage.recorded",
2278
+ phase,
2279
+ activity_kind: "retrospective_local_remeasurement",
2280
+ classification_source: "current_context",
2281
+ tokens: {
2282
+ input: 1,
2283
+ cached_input: 0,
2284
+ output: 1,
2285
+ reasoning: 0,
2286
+ total: 2,
2287
+ source: "provider_reported",
2288
+ },
2289
+ cost: { usd: 1, brl: 5, fx_rate: 5 },
2290
+ provider: "openai",
2291
+ model: "gpt-5",
2292
+ source_segment_key: id,
2293
+ model_call_id: `MCALL-${id}`,
2294
+ runtime: { reasoning_effort: null, service_tier: null },
2295
+ supersedes_event_id: null,
2296
+ retrospective_correction: true,
2297
+ source_occurred_at: sourceFinishedAt,
2298
+ source_started_at: sourceStartedAt,
2299
+ source_finished_at: sourceFinishedAt,
2300
+ duration_ms: null,
2301
+ duration_provenance: null,
1248
2302
  },
1249
2303
  {
1250
- schema_version: 2, event_id: `${id}:3`, run_id: id, sequence: 3,
1251
- occurred_at: new Date(Date.parse(occurredAt) + 60_000).toISOString(), type: "run.finished", phase,
1252
- status: "completed", duration_ms: 60_000, duration_provenance: "observed",
2304
+ schema_version: 2,
2305
+ event_id: `${id}:3`,
2306
+ run_id: id,
2307
+ sequence: 3,
2308
+ occurred_at: new Date(Date.parse(occurredAt) + 60_000).toISOString(),
2309
+ type: "run.finished",
2310
+ phase,
2311
+ status: "completed",
2312
+ duration_ms: 60_000,
2313
+ duration_provenance: "observed",
1253
2314
  },
1254
2315
  ];
1255
2316
  };
1256
2317
  for (const value of [
1257
- // 23:17–01:01 São Paulo: factual duration is split at local midnight.
1258
- { id: "RUN-planning", phase: "planning" as const, sourceStartedAt: "2026-07-23T02:17:00.000Z", sourceFinishedAt: "2026-07-23T04:01:00.000Z" },
1259
- { id: "RUN-conversation", phase: "conversation" as const, sourceStartedAt: "2026-07-23T03:00:00.000Z", sourceFinishedAt: "2026-07-23T04:01:00.000Z" },
1260
- { id: "RUN-execution", phase: "execution" as const, sourceStartedAt: "2026-07-23T03:30:00.000Z", sourceFinishedAt: "2026-07-23T04:30:00.000Z" },
1261
- { id: "RUN-subrun", phase: "execution" as const, parentRunId: "RUN-execution", sourceStartedAt: "2026-07-23T03:45:00.000Z", sourceFinishedAt: "2026-07-23T04:15:00.000Z" },
2318
+ // 23:17–01:01 São Paulo: factual duration is split at local midnight.
2319
+ {
2320
+ id: "RUN-planning",
2321
+ phase: "planning" as const,
2322
+ sourceStartedAt: "2026-07-23T02:17:00.000Z",
2323
+ sourceFinishedAt: "2026-07-23T04:01:00.000Z",
2324
+ },
2325
+ {
2326
+ id: "RUN-conversation",
2327
+ phase: "conversation" as const,
2328
+ sourceStartedAt: "2026-07-23T03:00:00.000Z",
2329
+ sourceFinishedAt: "2026-07-23T04:01:00.000Z",
2330
+ },
2331
+ {
2332
+ id: "RUN-execution",
2333
+ phase: "execution" as const,
2334
+ sourceStartedAt: "2026-07-23T03:30:00.000Z",
2335
+ sourceFinishedAt: "2026-07-23T04:30:00.000Z",
2336
+ },
2337
+ {
2338
+ id: "RUN-subrun",
2339
+ phase: "execution" as const,
2340
+ parentRunId: "RUN-execution",
2341
+ sourceStartedAt: "2026-07-23T03:45:00.000Z",
2342
+ sourceFinishedAt: "2026-07-23T04:15:00.000Z",
2343
+ },
1262
2344
  ]) {
1263
2345
  await writeFile(
1264
2346
  join(root, ".agents", "records", "runs", "2026", "07", `${value.id}.jsonl`),
@@ -1310,18 +2392,53 @@ created_at: 2026-08-10T11:01:00.000Z
1310
2392
  `${[historicalStarted, ...historicalRecords.slice(1)].map((record) => JSON.stringify(record)).join("\n")}\n`,
1311
2393
  );
1312
2394
  await rebuildSqliteReadModel(root);
1313
- const database = new DatabaseSync(resolve(root, ".local/dashboard-sqlite/read-model.sqlite"), { readOnly: true });
1314
- expect(database.prepare("SELECT duration_ms, source_duration_ms, duration_provenance FROM zaip_aios_activities WHERE run_id='RUN-planning'").get()).toEqual({ duration_ms: 4_020_000, source_duration_ms: 6_240_000, duration_provenance: "attributed_token_active" });
1315
- const daily = database.prepare("SELECT day, total_duration, invocation_count, cost_monitor_invocation_count, cost_monitor_total_duration FROM zaip_vw_daily_aggregates WHERE day IN ('2026-07-22', '2026-07-23') ORDER BY day").all();
2395
+ const database = new DatabaseSync(resolve(root, ".local/dashboard-sqlite/read-model.sqlite"), {
2396
+ readOnly: true,
2397
+ });
2398
+ expect(
2399
+ database
2400
+ .prepare(
2401
+ "SELECT duration_ms, source_duration_ms, duration_provenance FROM zaip_aios_activities WHERE run_id='RUN-planning'",
2402
+ )
2403
+ .get(),
2404
+ ).toEqual({
2405
+ duration_ms: 4_020_000,
2406
+ source_duration_ms: 6_240_000,
2407
+ duration_provenance: "attributed_token_active",
2408
+ });
2409
+ const daily = database
2410
+ .prepare(
2411
+ "SELECT day, total_duration, invocation_count, cost_monitor_invocation_count, cost_monitor_total_duration FROM zaip_vw_daily_aggregates WHERE day IN ('2026-07-22', '2026-07-23') ORDER BY day",
2412
+ )
2413
+ .all();
1316
2414
  expect(daily).toEqual([
1317
- { day: "2026-07-22", total_duration: 2_580_000, invocation_count: 1, cost_monitor_invocation_count: 1, cost_monitor_total_duration: 2_580_000 },
1318
- { day: "2026-07-23", total_duration: 5_420_000, invocation_count: 4, cost_monitor_invocation_count: 5, cost_monitor_total_duration: 5_420_000 },
2415
+ {
2416
+ day: "2026-07-22",
2417
+ total_duration: 2_580_000,
2418
+ invocation_count: 1,
2419
+ cost_monitor_invocation_count: 1,
2420
+ cost_monitor_total_duration: 2_580_000,
2421
+ },
2422
+ {
2423
+ day: "2026-07-23",
2424
+ total_duration: 5_420_000,
2425
+ invocation_count: 4,
2426
+ cost_monitor_invocation_count: 5,
2427
+ cost_monitor_total_duration: 5_420_000,
2428
+ },
1319
2429
  ]);
1320
- expect(database.prepare("SELECT COUNT(*) AS count FROM zaip_vw_daily_aggregates WHERE total_duration > 86400000").get()).toEqual({ count: 0 });
2430
+ expect(
2431
+ database
2432
+ .prepare(
2433
+ "SELECT COUNT(*) AS count FROM zaip_vw_daily_aggregates WHERE total_duration > 86400000",
2434
+ )
2435
+ .get(),
2436
+ ).toEqual({ count: 0 });
1321
2437
  database.close();
1322
2438
  const factualFilesystem = new SqliteReadModelFileSystem(root);
1323
2439
  expect(
1324
- factualFilesystem.costMonitorFinancialActivityRows({ from: "2026-07-23", to: "2026-07-23" })
2440
+ factualFilesystem
2441
+ .costMonitorFinancialActivityRows({ from: "2026-07-23", to: "2026-07-23" })
1325
2442
  .some((row) => row.run_id === "RUN-historical-financial"),
1326
2443
  ).toBe(true);
1327
2444
  const compactFinancialRow = factualFilesystem.costMonitorFinancialActivityRows({
@@ -1331,41 +2448,59 @@ created_at: 2026-08-10T11:01:00.000Z
1331
2448
  expect(compactFinancialRow).not.toHaveProperty("payload_json");
1332
2449
  expect(compactFinancialRow).toHaveProperty("total_tokens");
1333
2450
  expect(
1334
- factualFilesystem.costMonitorFinancialActivityRows({ from: "2026-07-24", to: "2026-07-24" })
2451
+ factualFilesystem
2452
+ .costMonitorFinancialActivityRows({ from: "2026-07-24", to: "2026-07-24" })
1335
2453
  .some((row) => row.run_id === "RUN-historical-financial"),
1336
2454
  ).toBe(false);
1337
2455
  expect(
1338
- factualFilesystem.viewPage("operations_agent_invocations", {
1339
- from: "2026-07-23", to: "2026-07-23", limit: 20,
1340
- }).rows.some((row) => row.run_id === "RUN-source-alias"),
2456
+ factualFilesystem
2457
+ .viewPage("operations_agent_invocations", {
2458
+ from: "2026-07-23",
2459
+ to: "2026-07-23",
2460
+ limit: 20,
2461
+ })
2462
+ .rows.some((row) => row.run_id === "RUN-source-alias"),
1341
2463
  ).toBe(true);
1342
2464
  expect(
1343
- factualFilesystem.viewPage("operations_agent_invocations", {
1344
- from: "2026-07-22", to: "2026-07-22", limit: 20,
1345
- }).rows.some((row) => row.run_id === "RUN-source-alias"),
2465
+ factualFilesystem
2466
+ .viewPage("operations_agent_invocations", {
2467
+ from: "2026-07-22",
2468
+ to: "2026-07-22",
2469
+ limit: 20,
2470
+ })
2471
+ .rows.some((row) => row.run_id === "RUN-source-alias"),
1346
2472
  ).toBe(false);
1347
2473
  // Filter dimensions stay in the SQL population: they must retain the
1348
2474
  // source-session day and never require an activity-by-activity lookup.
1349
2475
  expect(
1350
- factualFilesystem.costMonitorFinancialActivityRows({
1351
- from: "2026-07-23",
1352
- to: "2026-07-23",
1353
- phases: ["conversation"],
1354
- providers: ["openai"],
1355
- models: ["gpt-5"],
1356
- }).map((row) => row.run_id),
2476
+ factualFilesystem
2477
+ .costMonitorFinancialActivityRows({
2478
+ from: "2026-07-23",
2479
+ to: "2026-07-23",
2480
+ phases: ["conversation"],
2481
+ providers: ["openai"],
2482
+ models: ["gpt-5"],
2483
+ })
2484
+ .map((row) => row.run_id),
1357
2485
  ).toContain("RUN-historical-financial");
1358
2486
  expect(
1359
- factualFilesystem.costMonitorFinancialActivityRows({
1360
- from: "2026-07-22",
1361
- to: "2026-07-22",
1362
- phases: ["planning"],
1363
- }).map((row) => row.run_id),
2487
+ factualFilesystem
2488
+ .costMonitorFinancialActivityRows({
2489
+ from: "2026-07-22",
2490
+ to: "2026-07-22",
2491
+ phases: ["planning"],
2492
+ })
2493
+ .map((row) => row.run_id),
1364
2494
  ).toEqual(["RUN-planning"]);
1365
- for (const view of ["cost_monitor_daily", "cost_monitor_monthly", "cost_monitor_annual"] as const) {
2495
+ for (const view of [
2496
+ "cost_monitor_daily",
2497
+ "cost_monitor_monthly",
2498
+ "cost_monitor_annual",
2499
+ ] as const) {
1366
2500
  expect(
1367
- factualFilesystem.viewPage(view, { from: "2026-07-23", to: "2026-07-23", limit: 20, offset: 0 }).rows
1368
- .some((row) => Number(row.total_tokens) === 10),
2501
+ factualFilesystem
2502
+ .viewPage(view, { from: "2026-07-23", to: "2026-07-23", limit: 20, offset: 0 })
2503
+ .rows.some((row) => Number(row.total_tokens) === 10),
1369
2504
  ).toBe(true);
1370
2505
  // The API boundary supplies inclusive Sao Paulo days as ISO instants.
1371
2506
  // Do not truncate the UTC end instant into the following calendar day.
@@ -1376,20 +2511,40 @@ created_at: 2026-08-10T11:01:00.000Z
1376
2511
  offset: 0,
1377
2512
  }).rows;
1378
2513
  expect(bounded.some((row) => Number(row.total_tokens) === 10)).toBe(true);
1379
- expect(bounded.some((row) => String(row.period_key).startsWith("2026-07-24") && Number(row.total_tokens) === 10)).toBe(false);
2514
+ expect(
2515
+ bounded.some(
2516
+ (row) =>
2517
+ String(row.period_key).startsWith("2026-07-24") && Number(row.total_tokens) === 10,
2518
+ ),
2519
+ ).toBe(false);
1380
2520
  // A structural day or other source financial fact may still exist on
1381
2521
  // the 24th, but this fixture's source-day-23 aggregate must not leak.
1382
2522
  expect(
1383
- factualFilesystem.viewPage(view, { from: "2026-07-24", to: "2026-07-24", limit: 20, offset: 0 }).rows
1384
- .every((row) => row.total_tokens !== 10),
2523
+ factualFilesystem
2524
+ .viewPage(view, { from: "2026-07-24", to: "2026-07-24", limit: 20, offset: 0 })
2525
+ .rows.every((row) => row.total_tokens !== 10),
1385
2526
  ).toBe(true);
1386
2527
  }
1387
- const allFinancialRows = factualFilesystem.costMonitorFinancialActivityRows({ from: null, to: null });
1388
- const factual = factualFilesystem.costMonitorFactualDurationByDay({ from: null, to: null }, allFinancialRows);
2528
+ const allFinancialRows = factualFilesystem.costMonitorFinancialActivityRows({
2529
+ from: null,
2530
+ to: null,
2531
+ });
2532
+ const factual = factualFilesystem.costMonitorFactualDurationByDay(
2533
+ { from: null, to: null },
2534
+ allFinancialRows,
2535
+ );
1389
2536
  // The cross-midnight session is split at São Paulo midnight and each day
1390
2537
  // is the union of complete source intervals, never above one local day.
1391
- expect(factual.get("2026-07-22")).toEqual({ known_sum: 2_580_000, eligible_runs: 1, known_runs: 1 });
1392
- expect(factual.get("2026-07-23")).toEqual({ known_sum: 5_420_000, eligible_runs: 6, known_runs: 6 });
2538
+ expect(factual.get("2026-07-22")).toEqual({
2539
+ known_sum: 2_580_000,
2540
+ eligible_runs: 1,
2541
+ known_runs: 1,
2542
+ });
2543
+ expect(factual.get("2026-07-23")).toEqual({
2544
+ known_sum: 5_420_000,
2545
+ eligible_runs: 6,
2546
+ known_runs: 6,
2547
+ });
1393
2548
  factualFilesystem.close();
1394
2549
  });
1395
2550
 
@@ -1398,42 +2553,231 @@ created_at: 2026-08-10T11:01:00.000Z
1398
2553
  roots.push(root);
1399
2554
  for (const kind of ["tasks", "specs", "prds"])
1400
2555
  await mkdir(join(root, ".agents", "records", kind, "2026", "08"), { recursive: true });
1401
- await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-UNIQUE"), { recursive: true });
1402
- await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-SHARED-A"), { recursive: true });
1403
- await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-SHARED-B"), { recursive: true });
1404
- await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-PRD-ONLY"), { recursive: true });
1405
- await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-NO-MACRO"), { recursive: true });
2556
+ await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-UNIQUE"), {
2557
+ recursive: true,
2558
+ });
2559
+ await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-SHARED-A"), {
2560
+ recursive: true,
2561
+ });
2562
+ await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-SHARED-B"), {
2563
+ recursive: true,
2564
+ });
2565
+ await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-PRD-ONLY"), {
2566
+ recursive: true,
2567
+ });
2568
+ await mkdir(join(root, ".agents", "records", "changes", "2026", "08", "CHG-NO-MACRO"), {
2569
+ recursive: true,
2570
+ });
1406
2571
  await mkdir(join(root, ".agents", "records", "runs", "2026", "08"), { recursive: true });
1407
2572
  await mkdir(join(root, ".agents", "config"), { recursive: true });
1408
- await writeFile(join(root, ".agents", "config", "project.yaml"), "zaip:\n enabled: true\n", "utf8");
1409
- const item = (id: string, status = "planned") => `---\nid: ${id}\ntitle: ${id}\nstatus: ${status}\nrisk: standard\ncreated_at: 2026-08-12T12:00:00.000Z\n---\n# ${id}\n`;
1410
- for (const id of ["TASK-UNIQUE", "TASK-SHARED-A", "TASK-SHARED-B", "TASK-PRD-ONLY", "TASK-NO-MACRO"])
1411
- await writeFile(join(root, ".agents", "records", "tasks", "2026", "08", `${id}.md`), item(id), "utf8");
2573
+ await writeFile(
2574
+ join(root, ".agents", "config", "project.yaml"),
2575
+ "zaip:\n enabled: true\n",
2576
+ "utf8",
2577
+ );
2578
+ const item = (id: string, status = "planned") =>
2579
+ `---\nid: ${id}\ntitle: ${id}\nstatus: ${status}\nrisk: standard\ncreated_at: 2026-08-12T12:00:00.000Z\n---\n# ${id}\n`;
2580
+ for (const id of [
2581
+ "TASK-UNIQUE",
2582
+ "TASK-SHARED-A",
2583
+ "TASK-SHARED-B",
2584
+ "TASK-PRD-ONLY",
2585
+ "TASK-NO-MACRO",
2586
+ ])
2587
+ await writeFile(
2588
+ join(root, ".agents", "records", "tasks", "2026", "08", `${id}.md`),
2589
+ item(id),
2590
+ "utf8",
2591
+ );
1412
2592
  for (const id of ["SPEC-UNIQUE", "SPEC-SHARED"])
1413
- await writeFile(join(root, ".agents", "records", "specs", "2026", "08", `${id}.md`), item(id, "active"), "utf8");
2593
+ await writeFile(
2594
+ join(root, ".agents", "records", "specs", "2026", "08", `${id}.md`),
2595
+ item(id, "active"),
2596
+ "utf8",
2597
+ );
1414
2598
  for (const id of ["PRD-UNIQUE", "PRD-SHARED", "PRD-ONLY"])
1415
- await writeFile(join(root, ".agents", "records", "prds", "2026", "08", `${id}.md`), item(id, "active"), "utf8");
1416
- const change = (id: string, taskId: string, specId: string | null, prdId: string | null) => `---\nid: ${id}\ntitle: ${id}\nstatus: planned\nrisk: standard\nsource:\n type: ${prdId === null ? "task" : "prd"}\n ${prdId === null ? `task_id: ${taskId}` : `prd_id: ${prdId}`}\n${specId === null ? "" : ` spec_id: ${specId}\n`}task_ids:\n - ${taskId}\ncreated_at: 2026-08-12T12:00:00.000Z\n---\n# ${id}\n`;
1417
- await writeFile(join(root, ".agents", "records", "changes", "2026", "08", "CHG-UNIQUE", "change.md"), change("CHG-UNIQUE", "TASK-UNIQUE", "SPEC-UNIQUE", "PRD-UNIQUE"), "utf8");
1418
- await writeFile(join(root, ".agents", "records", "changes", "2026", "08", "CHG-SHARED-A", "change.md"), change("CHG-SHARED-A", "TASK-SHARED-A", "SPEC-SHARED", "PRD-SHARED"), "utf8");
1419
- await writeFile(join(root, ".agents", "records", "changes", "2026", "08", "CHG-SHARED-B", "change.md"), change("CHG-SHARED-B", "TASK-SHARED-B", "SPEC-SHARED", "PRD-SHARED"), "utf8");
1420
- await writeFile(join(root, ".agents", "records", "changes", "2026", "08", "CHG-PRD-ONLY", "change.md"), change("CHG-PRD-ONLY", "TASK-PRD-ONLY", null, "PRD-ONLY"), "utf8");
1421
- await writeFile(join(root, ".agents", "records", "changes", "2026", "08", "CHG-NO-MACRO", "change.md"), change("CHG-NO-MACRO", "TASK-NO-MACRO", null, null), "utf8");
1422
- const run = (id: string, specId: string | null, prdId: string | null, tokens: number, cost: number, duration: number) => [
1423
- { schema_version: 2, event_id: `${id}:1`, run_id: id, sequence: 1, occurred_at: "2026-08-12T12:00:00.000Z", type: "run.started", attribution_status: "attributed", phase: "planning", run_role: "orchestrator", run_purpose: "orchestration", requires_finalizer: false, execution_kind: "interaction", execution_eligibility: [], entrypoint: specId === null ? (prdId === null ? "conversation" : "prd") : "spec", work_type: "new", storage_mode: "tracked_sanitized", client: "codex", agent: "agent", agent_name: "agent", provider: "openai", model: "gpt-5", reasoning_effort: null, client_thread_id: id, client_turn_id: id, conversation_id: `CONV-${id}`, execution_id: null, task_id: null, spec_id: specId, prd_id: prdId, change_id: null, parent_run_id: null, continuation_of_run_id: null, retry_of_run_id: null, agent_invocation_id: `AINV-${id}`, root_agent_invocation_id: `AINV-${id}`, parent_agent_invocation_id: null, invocation_kind: "orchestrator", delegation_depth: 0 },
1424
- { schema_version: 2, event_id: `${id}:2`, run_id: id, sequence: 2, occurred_at: "2026-08-12T12:01:00.000Z", type: "usage.recorded", phase: "planning", activity_kind: "model_usage", classification_source: "explicit", tokens: { input: tokens, cached_input: 0, output: 0, reasoning: 0, total: tokens, source: "provider_reported" }, cost: { usd: cost / 5, brl: cost, fx_rate: 5 }, provider: "openai", model: "gpt-5", source_segment_key: id, model_call_id: `MCALL-${id}`, runtime: { reasoning_effort: null, service_tier: null }, supersedes_event_id: null, duration_ms: null, duration_provenance: null },
1425
- { schema_version: 2, event_id: `${id}:3`, run_id: id, sequence: 3, occurred_at: "2026-08-12T12:02:00.000Z", type: "run.finished", phase: "planning", status: "completed", duration_ms: duration, duration_provenance: "observed" },
2599
+ await writeFile(
2600
+ join(root, ".agents", "records", "prds", "2026", "08", `${id}.md`),
2601
+ item(id, "active"),
2602
+ "utf8",
2603
+ );
2604
+ const change = (id: string, taskId: string, specId: string | null, prdId: string | null) =>
2605
+ `---\nid: ${id}\ntitle: ${id}\nstatus: planned\nrisk: standard\nsource:\n type: ${prdId === null ? "task" : "prd"}\n ${prdId === null ? `task_id: ${taskId}` : `prd_id: ${prdId}`}\n${specId === null ? "" : ` spec_id: ${specId}\n`}task_ids:\n - ${taskId}\ncreated_at: 2026-08-12T12:00:00.000Z\n---\n# ${id}\n`;
2606
+ await writeFile(
2607
+ join(root, ".agents", "records", "changes", "2026", "08", "CHG-UNIQUE", "change.md"),
2608
+ change("CHG-UNIQUE", "TASK-UNIQUE", "SPEC-UNIQUE", "PRD-UNIQUE"),
2609
+ "utf8",
2610
+ );
2611
+ await writeFile(
2612
+ join(root, ".agents", "records", "changes", "2026", "08", "CHG-SHARED-A", "change.md"),
2613
+ change("CHG-SHARED-A", "TASK-SHARED-A", "SPEC-SHARED", "PRD-SHARED"),
2614
+ "utf8",
2615
+ );
2616
+ await writeFile(
2617
+ join(root, ".agents", "records", "changes", "2026", "08", "CHG-SHARED-B", "change.md"),
2618
+ change("CHG-SHARED-B", "TASK-SHARED-B", "SPEC-SHARED", "PRD-SHARED"),
2619
+ "utf8",
2620
+ );
2621
+ await writeFile(
2622
+ join(root, ".agents", "records", "changes", "2026", "08", "CHG-PRD-ONLY", "change.md"),
2623
+ change("CHG-PRD-ONLY", "TASK-PRD-ONLY", null, "PRD-ONLY"),
2624
+ "utf8",
2625
+ );
2626
+ await writeFile(
2627
+ join(root, ".agents", "records", "changes", "2026", "08", "CHG-NO-MACRO", "change.md"),
2628
+ change("CHG-NO-MACRO", "TASK-NO-MACRO", null, null),
2629
+ "utf8",
2630
+ );
2631
+ const run = (
2632
+ id: string,
2633
+ specId: string | null,
2634
+ prdId: string | null,
2635
+ tokens: number,
2636
+ cost: number,
2637
+ duration: number,
2638
+ ) => [
2639
+ {
2640
+ schema_version: 2,
2641
+ event_id: `${id}:1`,
2642
+ run_id: id,
2643
+ sequence: 1,
2644
+ occurred_at: "2026-08-12T12:00:00.000Z",
2645
+ type: "run.started",
2646
+ attribution_status: "attributed",
2647
+ phase: "planning",
2648
+ run_role: "orchestrator",
2649
+ run_purpose: "orchestration",
2650
+ requires_finalizer: false,
2651
+ execution_kind: "interaction",
2652
+ execution_eligibility: [],
2653
+ entrypoint: specId === null ? (prdId === null ? "conversation" : "prd") : "spec",
2654
+ work_type: "new",
2655
+ storage_mode: "tracked_sanitized",
2656
+ client: "codex",
2657
+ agent: "agent",
2658
+ agent_name: "agent",
2659
+ provider: "openai",
2660
+ model: "gpt-5",
2661
+ reasoning_effort: null,
2662
+ client_thread_id: id,
2663
+ client_turn_id: id,
2664
+ conversation_id: `CONV-${id}`,
2665
+ execution_id: null,
2666
+ task_id: null,
2667
+ spec_id: specId,
2668
+ prd_id: prdId,
2669
+ change_id: null,
2670
+ parent_run_id: null,
2671
+ continuation_of_run_id: null,
2672
+ retry_of_run_id: null,
2673
+ agent_invocation_id: `AINV-${id}`,
2674
+ root_agent_invocation_id: `AINV-${id}`,
2675
+ parent_agent_invocation_id: null,
2676
+ invocation_kind: "orchestrator",
2677
+ delegation_depth: 0,
2678
+ },
2679
+ {
2680
+ schema_version: 2,
2681
+ event_id: `${id}:2`,
2682
+ run_id: id,
2683
+ sequence: 2,
2684
+ occurred_at: "2026-08-12T12:01:00.000Z",
2685
+ type: "usage.recorded",
2686
+ phase: "planning",
2687
+ activity_kind: "model_usage",
2688
+ classification_source: "explicit",
2689
+ tokens: {
2690
+ input: tokens,
2691
+ cached_input: 0,
2692
+ output: 0,
2693
+ reasoning: 0,
2694
+ total: tokens,
2695
+ source: "provider_reported",
2696
+ },
2697
+ cost: { usd: cost / 5, brl: cost, fx_rate: 5 },
2698
+ provider: "openai",
2699
+ model: "gpt-5",
2700
+ source_segment_key: id,
2701
+ model_call_id: `MCALL-${id}`,
2702
+ runtime: { reasoning_effort: null, service_tier: null },
2703
+ supersedes_event_id: null,
2704
+ duration_ms: null,
2705
+ duration_provenance: null,
2706
+ },
2707
+ {
2708
+ schema_version: 2,
2709
+ event_id: `${id}:3`,
2710
+ run_id: id,
2711
+ sequence: 3,
2712
+ occurred_at: "2026-08-12T12:02:00.000Z",
2713
+ type: "run.finished",
2714
+ phase: "planning",
2715
+ status: "completed",
2716
+ duration_ms: duration,
2717
+ duration_provenance: "observed",
2718
+ },
1426
2719
  ];
1427
- for (const [id, specId, prdId, tokens, cost, duration] of [["RUN-UNIQUE", "SPEC-UNIQUE", "PRD-UNIQUE", 7, 3, 120_000], ["RUN-SHARED", "SPEC-SHARED", "PRD-SHARED", 11, 5, 60_000], ["RUN-PRD-ONLY", null, "PRD-ONLY", 13, 6, 90_000], ["RUN-NO-MACRO", null, null, 17, 8, 30_000]] as const)
1428
- await writeFile(join(root, ".agents", "records", "runs", "2026", "08", `${id}.jsonl`), `${run(id, specId, prdId, tokens, cost, duration).map((record) => JSON.stringify(record)).join("\n")}\n`, "utf8");
2720
+ for (const [id, specId, prdId, tokens, cost, duration] of [
2721
+ ["RUN-UNIQUE", "SPEC-UNIQUE", "PRD-UNIQUE", 7, 3, 120_000],
2722
+ ["RUN-SHARED", "SPEC-SHARED", "PRD-SHARED", 11, 5, 60_000],
2723
+ ["RUN-PRD-ONLY", null, "PRD-ONLY", 13, 6, 90_000],
2724
+ ["RUN-NO-MACRO", null, null, 17, 8, 30_000],
2725
+ ] as const)
2726
+ await writeFile(
2727
+ join(root, ".agents", "records", "runs", "2026", "08", `${id}.jsonl`),
2728
+ `${run(id, specId, prdId, tokens, cost, duration)
2729
+ .map((record) => JSON.stringify(record))
2730
+ .join("\n")}\n`,
2731
+ "utf8",
2732
+ );
1429
2733
  await rebuildSqliteReadModel(root);
1430
2734
  const filesystem = new SqliteReadModelFileSystem(root);
1431
2735
  const tasks = filesystem.summaryPage("task", { from: null, to: null }, 0, 10).rows;
1432
- expect(tasks).toContainEqual(expect.objectContaining({ id: "TASK-UNIQUE", invocation_count: 1, total_duration: 62_500, total_tokens: 7, total_cost_brl: 3 }));
1433
- expect(tasks).toContainEqual(expect.objectContaining({ id: "TASK-SHARED-A", invocation_count: null, total_duration: null, total_tokens: null, total_cost_brl: null }));
1434
- expect(tasks).toContainEqual(expect.objectContaining({ id: "TASK-SHARED-B", invocation_count: null, total_duration: null, total_tokens: null, total_cost_brl: null }));
1435
- expect(tasks).toContainEqual(expect.objectContaining({ id: "TASK-PRD-ONLY", invocation_count: 1, total_duration: 32_500, total_tokens: 13, total_cost_brl: 6 }));
1436
- expect(tasks).toContainEqual(expect.objectContaining({ id: "TASK-NO-MACRO", invocation_count: null, total_duration: null, total_tokens: null, total_cost_brl: null }));
2736
+ expect(tasks).toContainEqual(
2737
+ expect.objectContaining({
2738
+ id: "TASK-UNIQUE",
2739
+ invocation_count: 1,
2740
+ total_duration: 62_500,
2741
+ total_tokens: 7,
2742
+ total_cost_brl: 3,
2743
+ }),
2744
+ );
2745
+ expect(tasks).toContainEqual(
2746
+ expect.objectContaining({
2747
+ id: "TASK-SHARED-A",
2748
+ invocation_count: null,
2749
+ total_duration: null,
2750
+ total_tokens: null,
2751
+ total_cost_brl: null,
2752
+ }),
2753
+ );
2754
+ expect(tasks).toContainEqual(
2755
+ expect.objectContaining({
2756
+ id: "TASK-SHARED-B",
2757
+ invocation_count: null,
2758
+ total_duration: null,
2759
+ total_tokens: null,
2760
+ total_cost_brl: null,
2761
+ }),
2762
+ );
2763
+ expect(tasks).toContainEqual(
2764
+ expect.objectContaining({
2765
+ id: "TASK-PRD-ONLY",
2766
+ invocation_count: 1,
2767
+ total_duration: 32_500,
2768
+ total_tokens: 13,
2769
+ total_cost_brl: 6,
2770
+ }),
2771
+ );
2772
+ expect(tasks).toContainEqual(
2773
+ expect.objectContaining({
2774
+ id: "TASK-NO-MACRO",
2775
+ invocation_count: null,
2776
+ total_duration: null,
2777
+ total_tokens: null,
2778
+ total_cost_brl: null,
2779
+ }),
2780
+ );
1437
2781
  filesystem.close();
1438
2782
  });
1439
2783
 
@@ -1448,18 +2792,28 @@ created_at: 2026-08-10T11:01:00.000Z
1448
2792
  { recursive: true },
1449
2793
  );
1450
2794
  await mkdir(
1451
- join(root, ".agents", "records", "changes", "2026", "08", "CHG-ART", "artifacts", "validations"),
2795
+ join(
2796
+ root,
2797
+ ".agents",
2798
+ "records",
2799
+ "changes",
2800
+ "2026",
2801
+ "08",
2802
+ "CHG-ART",
2803
+ "artifacts",
2804
+ "validations",
2805
+ ),
1452
2806
  { recursive: true },
1453
2807
  );
1454
2808
  await mkdir(join(root, ".agents", "config"), { recursive: true });
1455
2809
  await writeFile(
1456
2810
  join(root, ".agents", "config", "project.yaml"),
1457
- "schema_version: 1\nzaip:\n enabled: true\nproject:\n id: sqlite-test\n name: sqlite-test\n timezone: UTC\nstack:\n id: zaip-aios-stack\n overrides: {}\nclients:\n codex: true\n claude: true\ntracking:\n enabled: true\n currency: BRL\n storage_mode: tracked_sanitized\n",
2811
+ "schema_version: 1\nzaip:\n enabled: true\nproject:\n id: sqlite-test\n name: sqlite-test\n timezone: UTC\nstack:\n id: zaip-aios-stack\n overrides: {}\nclients:\n codex: true\n claude: true\ntracking:\n enabled: true\n currency: BRL\n storage_mode: tracked_sanitized\n",
1458
2812
  "utf8",
1459
2813
  );
1460
2814
  await writeFile(
1461
2815
  join(root, ".agents", "config", "framework.lock.yaml"),
1462
- "lock_version: 1\nframework:\n version: 1.0.8\n distribution_sha256: null\nlayout:\n version: 3\nresolved_profile:\n id: null\n sha256: null\nmanaged_files: {}\n",
2816
+ "lock_version: 1\nframework:\n version: 1.3.0\n distribution_sha256: null\nlayout:\n version: 3\nresolved_profile:\n id: null\n sha256: null\nmanaged_files: {}\n",
1463
2817
  "utf8",
1464
2818
  );
1465
2819
  const run = (
@@ -1553,9 +2907,18 @@ created_at: 2026-08-10T11:01:00.000Z
1553
2907
  },
1554
2908
  ];
1555
2909
  for (const [id, records] of [
1556
- ["RUN-R1", run("RUN-R1", "2026-08-01", "TASK-A", 600_000, "12:00:00.000Z", "SPEC-A", "PRD-A")],
1557
- ["RUN-R2", run("RUN-R2", "2026-08-02", "TASK-B", 1_200_000, "12:00:00.000Z", "SPEC-B", "PRD-A")],
1558
- ["RUN-R3", run("RUN-R3", "2026-08-02", "TASK-B", 1_200_000, "12:10:00.000Z", "SPEC-B", "PRD-A")],
2910
+ [
2911
+ "RUN-R1",
2912
+ run("RUN-R1", "2026-08-01", "TASK-A", 600_000, "12:00:00.000Z", "SPEC-A", "PRD-A"),
2913
+ ],
2914
+ [
2915
+ "RUN-R2",
2916
+ run("RUN-R2", "2026-08-02", "TASK-B", 1_200_000, "12:00:00.000Z", "SPEC-B", "PRD-A"),
2917
+ ],
2918
+ [
2919
+ "RUN-R3",
2920
+ run("RUN-R3", "2026-08-02", "TASK-B", 1_200_000, "12:10:00.000Z", "SPEC-B", "PRD-A"),
2921
+ ],
1559
2922
  ] as const) {
1560
2923
  await writeFile(
1561
2924
  join(root, ".agents", "records", "runs", "2026", "08", `${id}.jsonl`),
@@ -1564,16 +2927,42 @@ created_at: 2026-08-10T11:01:00.000Z
1564
2927
  );
1565
2928
  }
1566
2929
  await writeFile(
1567
- join(root, ".agents", "records", "changes", "2026", "08", "CHG-ART", "artifacts", "evidence", "EVD-1.md"),
2930
+ join(
2931
+ root,
2932
+ ".agents",
2933
+ "records",
2934
+ "changes",
2935
+ "2026",
2936
+ "08",
2937
+ "CHG-ART",
2938
+ "artifacts",
2939
+ "evidence",
2940
+ "EVD-1.md",
2941
+ ),
1568
2942
  "---\nid: EVD-1\nobserved_at: 2026-08-01T12:00:00.000Z\n---\n# Evidence\n",
1569
2943
  "utf8",
1570
2944
  );
1571
2945
  await writeFile(
1572
- join(root, ".agents", "records", "changes", "2026", "08", "CHG-ART", "artifacts", "validations", "VAL-1.md"),
2946
+ join(
2947
+ root,
2948
+ ".agents",
2949
+ "records",
2950
+ "changes",
2951
+ "2026",
2952
+ "08",
2953
+ "CHG-ART",
2954
+ "artifacts",
2955
+ "validations",
2956
+ "VAL-1.md",
2957
+ ),
1573
2958
  "---\nid: VAL-1\nexecuted_at: 2026-08-02T12:00:00.000Z\n---\n# Validation\n",
1574
2959
  "utf8",
1575
2960
  );
1576
- for (const [kind, id] of [["tasks", "TASK-NO-RUN"], ["specs", "SPEC-NO-RUN"], ["prds", "PRD-NO-RUN"]] as const)
2961
+ for (const [kind, id] of [
2962
+ ["tasks", "TASK-NO-RUN"],
2963
+ ["specs", "SPEC-NO-RUN"],
2964
+ ["prds", "PRD-NO-RUN"],
2965
+ ] as const)
1577
2966
  await writeFile(
1578
2967
  join(root, ".agents", "records", kind, "2026", "08", `${id}.md`),
1579
2968
  `---\nid: ${id}\ntitle: ${id}\nstatus: draft\ncreated_at: 2026-08-03T12:00:00.000Z\n---\n# ${id}\n`,
@@ -1710,7 +3099,11 @@ created_at: 2026-08-10T11:01:00.000Z
1710
3099
  { headers: { "x-zaip-session": "test-session" } },
1711
3100
  );
1712
3101
  const nextMonth = (await nextMonthQuick.json()) as {
1713
- summary: { run_count: number; task_count: number; overview_metrics: { tokens: number | null; duration_ms: number | null } };
3102
+ summary: {
3103
+ run_count: number;
3104
+ task_count: number;
3105
+ overview_metrics: { tokens: number | null; duration_ms: number | null };
3106
+ };
1714
3107
  };
1715
3108
  expect(nextMonth.summary).toMatchObject({
1716
3109
  run_count: 0,
@@ -1808,9 +3201,21 @@ created_at: 2026-08-10T11:01:00.000Z
1808
3201
  ]);
1809
3202
  }
1810
3203
  for (const [view, key, counts] of [
1811
- ["cost_monitor_daily", "2026-08-02", { prd_count: 0, spec_count: 1, task_count: 1, validation_count: 1, evidence_count: 0 }],
1812
- ["cost_monitor_monthly", "2026-08", { prd_count: 2, spec_count: 3, task_count: 3, validation_count: 1, evidence_count: 1 }],
1813
- ["cost_monitor_annual", "2026", { prd_count: 2, spec_count: 3, task_count: 3, validation_count: 1, evidence_count: 1 }],
3204
+ [
3205
+ "cost_monitor_daily",
3206
+ "2026-08-02",
3207
+ { prd_count: 0, spec_count: 1, task_count: 1, validation_count: 1, evidence_count: 0 },
3208
+ ],
3209
+ [
3210
+ "cost_monitor_monthly",
3211
+ "2026-08",
3212
+ { prd_count: 2, spec_count: 3, task_count: 3, validation_count: 1, evidence_count: 1 },
3213
+ ],
3214
+ [
3215
+ "cost_monitor_annual",
3216
+ "2026",
3217
+ { prd_count: 2, spec_count: 3, task_count: 3, validation_count: 1, evidence_count: 1 },
3218
+ ],
1814
3219
  ] as const) {
1815
3220
  expect(filesystem.viewPage(view, { limit: 50 }).rows).toContainEqual(
1816
3221
  expect.objectContaining({ key, ...counts }),
@@ -1828,7 +3233,10 @@ created_at: 2026-08-10T11:01:00.000Z
1828
3233
  const annualCostPage = filesystem.viewPage("cost_monitor_annual", { limit: 50 });
1829
3234
  const dailyCostRows = filesystem.viewPage("cost_monitor_daily", { limit: 50 }).rows;
1830
3235
  const pagedDailyCostPage = filesystem.viewPage("cost_monitor_daily", { limit: 1 });
1831
- expect(pagedDailyCostPage).toMatchObject({ total_count: dailyCostRows.length, rows: [expect.any(Object)] });
3236
+ expect(pagedDailyCostPage).toMatchObject({
3237
+ total_count: dailyCostRows.length,
3238
+ rows: [expect.any(Object)],
3239
+ });
1832
3240
  expect(pagedDailyCostPage.totals).toMatchObject({
1833
3241
  total_tokens: dailyCostRows.reduce((sum, row) => sum + Number(row.total_tokens ?? 0), 0),
1834
3242
  total_cost_brl: dailyCostRows.reduce((sum, row) => sum + Number(row.total_cost_brl ?? 0), 0),
@@ -1841,9 +3249,17 @@ created_at: 2026-08-10T11:01:00.000Z
1841
3249
  const annualCostRow = annualCostPage.rows[0];
1842
3250
  if (annualCostRow === undefined) throw new Error("Expected the consolidated 2026 Cost row");
1843
3251
  for (const metric of [
1844
- "prd_count", "spec_count", "task_count", "validation_count", "evidence_count",
1845
- "total_run_count", "total_duration", "duration_known",
1846
- "total_tokens", "total_cost_usd", "total_cost_brl",
3252
+ "prd_count",
3253
+ "spec_count",
3254
+ "task_count",
3255
+ "validation_count",
3256
+ "evidence_count",
3257
+ "total_run_count",
3258
+ "total_duration",
3259
+ "duration_known",
3260
+ "total_tokens",
3261
+ "total_cost_usd",
3262
+ "total_cost_brl",
1847
3263
  ] as const) {
1848
3264
  const observed = dailyCostRows
1849
3265
  .map((row) => row[metric])
@@ -1883,7 +3299,14 @@ created_at: 2026-08-10T11:01:00.000Z
1883
3299
  total_cost_brl: 15,
1884
3300
  });
1885
3301
  }
1886
- expect(filesystem.viewPage("cost_monitor_tasks", { from: "2026-08-02", to: "2026-08-02", query: "TASK-B", limit: 1 }).totals).toEqual({
3302
+ expect(
3303
+ filesystem.viewPage("cost_monitor_tasks", {
3304
+ from: "2026-08-02",
3305
+ to: "2026-08-02",
3306
+ query: "TASK-B",
3307
+ limit: 1,
3308
+ }).totals,
3309
+ ).toEqual({
1887
3310
  entity_count: 1,
1888
3311
  invocation_count: 2,
1889
3312
  total_duration: 1_800_000,
@@ -1894,24 +3317,75 @@ created_at: 2026-08-10T11:01:00.000Z
1894
3317
  // The compact Cost Monitor tables share the canonical macro population
1895
3318
  // with their big numbers. A macro with no direct invocation must remain
1896
3319
  // paginable and retain unavailable financial facts as null.
1897
- expect(filesystem.viewPage("cost_monitor_specs", { query: "SPEC-NO-RUN", limit: 1 })).toMatchObject({
3320
+ expect(
3321
+ filesystem.viewPage("cost_monitor_specs", { query: "SPEC-NO-RUN", limit: 1 }),
3322
+ ).toMatchObject({
1898
3323
  total_count: 1,
1899
- totals: { entity_count: 1, invocation_count: 0, total_duration: null, total_tokens: null, total_cost_brl: null },
1900
- rows: [expect.objectContaining({ id: "SPEC-NO-RUN", title: "SPEC-NO-RUN", invocation_count: 0, total_duration: null, total_tokens: null, total_cost_brl: null })],
3324
+ totals: {
3325
+ entity_count: 1,
3326
+ invocation_count: 0,
3327
+ total_duration: null,
3328
+ total_tokens: null,
3329
+ total_cost_brl: null,
3330
+ },
3331
+ rows: [
3332
+ expect.objectContaining({
3333
+ id: "SPEC-NO-RUN",
3334
+ title: "SPEC-NO-RUN",
3335
+ invocation_count: 0,
3336
+ total_duration: null,
3337
+ total_tokens: null,
3338
+ total_cost_brl: null,
3339
+ }),
3340
+ ],
1901
3341
  });
1902
- expect(filesystem.viewPage("cost_monitor_prds", { query: "PRD-NO-RUN", limit: 1 })).toMatchObject({
3342
+ expect(
3343
+ filesystem.viewPage("cost_monitor_prds", { query: "PRD-NO-RUN", limit: 1 }),
3344
+ ).toMatchObject({
1903
3345
  total_count: 1,
1904
- totals: { entity_count: 1, invocation_count: 0, total_duration: null, total_tokens: null, total_cost_brl: null },
1905
- rows: [expect.objectContaining({ id: "PRD-NO-RUN", title: "PRD-NO-RUN", invocation_count: 0, total_duration: null, total_tokens: null, total_cost_brl: null })],
3346
+ totals: {
3347
+ entity_count: 1,
3348
+ invocation_count: 0,
3349
+ total_duration: null,
3350
+ total_tokens: null,
3351
+ total_cost_brl: null,
3352
+ },
3353
+ rows: [
3354
+ expect.objectContaining({
3355
+ id: "PRD-NO-RUN",
3356
+ title: "PRD-NO-RUN",
3357
+ invocation_count: 0,
3358
+ total_duration: null,
3359
+ total_tokens: null,
3360
+ total_cost_brl: null,
3361
+ }),
3362
+ ],
1906
3363
  });
1907
- for (const view of ["cost_monitor_tasks", "cost_monitor_specs", "cost_monitor_prds", "cost_monitor_conversations"] as const) {
1908
- const filtered = filesystem.viewPage(view, { phase: "execution", provider: "openai", model: "gpt-5", limit: 1 });
3364
+ for (const view of [
3365
+ "cost_monitor_tasks",
3366
+ "cost_monitor_specs",
3367
+ "cost_monitor_prds",
3368
+ "cost_monitor_conversations",
3369
+ ] as const) {
3370
+ const filtered = filesystem.viewPage(view, {
3371
+ phase: "execution",
3372
+ provider: "openai",
3373
+ model: "gpt-5",
3374
+ limit: 1,
3375
+ });
1909
3376
  // Dimensional membership and the subtotal share one pre-pagination
1910
3377
  // invocation population for every compact lifecycle view.
1911
3378
  expect(filtered.rows).toHaveLength(1);
1912
- expect(filtered.totals).toMatchObject({ invocation_count: 3, total_tokens: 6, total_cost_brl: 15 });
3379
+ expect(filtered.totals).toMatchObject({
3380
+ invocation_count: 3,
3381
+ total_tokens: 6,
3382
+ total_cost_brl: 15,
3383
+ });
1913
3384
  }
1914
- expect(filesystem.viewPage("cost_monitor_tasks", { workType: "new", limit: 1 })).toMatchObject({ total_count: 0, rows: [] });
3385
+ expect(filesystem.viewPage("cost_monitor_tasks", { workType: "new", limit: 1 })).toMatchObject({
3386
+ total_count: 0,
3387
+ rows: [],
3388
+ });
1915
3389
  expect(filesystem.firstFoldAllTime()).toBe(allTime);
1916
3390
  filesystem.close();
1917
3391
 
@@ -1925,26 +3399,61 @@ created_at: 2026-08-10T11:01:00.000Z
1925
3399
  );
1926
3400
  await writeFile(
1927
3401
  join(root, ".agents", "records", "runs", "2026", "08", "RUN-CANONICAL-DAY.jsonl"),
1928
- `${run("RUN-CANONICAL-DAY", "2026-08-02", "TASK-CANONICAL-DAY", 1_000, "12:30:00.000Z", "SPEC-CANONICAL-DAY").map((record) => JSON.stringify(record)).join("\n")}\n`,
3402
+ `${run(
3403
+ "RUN-CANONICAL-DAY",
3404
+ "2026-08-02",
3405
+ "TASK-CANONICAL-DAY",
3406
+ 1_000,
3407
+ "12:30:00.000Z",
3408
+ "SPEC-CANONICAL-DAY",
3409
+ )
3410
+ .map((record) => JSON.stringify(record))
3411
+ .join("\n")}\n`,
1929
3412
  "utf8",
1930
3413
  );
1931
3414
  await writeFile(
1932
3415
  join(root, ".agents", "records", "runs", "2026", "08", "RUN-CANONICAL-DAY-LATE.jsonl"),
1933
- `${run("RUN-CANONICAL-DAY-LATE", "2026-08-04", "TASK-CANONICAL-DAY-LATE", 1_000, "12:30:00.000Z", "SPEC-CANONICAL-DAY").map((record) => JSON.stringify(record)).join("\n")}\n`,
3416
+ `${run(
3417
+ "RUN-CANONICAL-DAY-LATE",
3418
+ "2026-08-04",
3419
+ "TASK-CANONICAL-DAY-LATE",
3420
+ 1_000,
3421
+ "12:30:00.000Z",
3422
+ "SPEC-CANONICAL-DAY",
3423
+ )
3424
+ .map((record) => JSON.stringify(record))
3425
+ .join("\n")}\n`,
1934
3426
  "utf8",
1935
3427
  );
1936
3428
  await rebuildSqliteReadModel(root);
1937
3429
  const canonicalDayFilesystem = new SqliteReadModelFileSystem(root);
1938
- expect(canonicalDayFilesystem.viewPage("cost_monitor_specs", {
1939
- from: "2026-08-03", to: "2026-08-03", query: "canonical title", limit: 1,
1940
- })).toMatchObject({
3430
+ expect(
3431
+ canonicalDayFilesystem.viewPage("cost_monitor_specs", {
3432
+ from: "2026-08-03",
3433
+ to: "2026-08-03",
3434
+ query: "canonical title",
3435
+ limit: 1,
3436
+ }),
3437
+ ).toMatchObject({
1941
3438
  total_count: 1,
1942
3439
  totals: { entity_count: 1, invocation_count: 0, total_tokens: null, total_cost_brl: null },
1943
- rows: [expect.objectContaining({ id: "SPEC-CANONICAL-DAY", invocation_count: 0, total_tokens: null, total_cost_brl: null })],
3440
+ rows: [
3441
+ expect.objectContaining({
3442
+ id: "SPEC-CANONICAL-DAY",
3443
+ invocation_count: 0,
3444
+ total_tokens: null,
3445
+ total_cost_brl: null,
3446
+ }),
3447
+ ],
1944
3448
  });
1945
- expect(canonicalDayFilesystem.viewPage("cost_monitor_specs", {
1946
- from: "2026-08-02", to: "2026-08-02", query: "SPEC-CANONICAL-DAY", limit: 1,
1947
- })).toMatchObject({ total_count: 0, rows: [] });
3449
+ expect(
3450
+ canonicalDayFilesystem.viewPage("cost_monitor_specs", {
3451
+ from: "2026-08-02",
3452
+ to: "2026-08-02",
3453
+ query: "SPEC-CANONICAL-DAY",
3454
+ limit: 1,
3455
+ }),
3456
+ ).toMatchObject({ total_count: 0, rows: [] });
1948
3457
  canonicalDayFilesystem.close();
1949
3458
 
1950
3459
  // A large result set keeps its subtotal for all 270 matching Tasks while
@@ -1953,7 +3462,9 @@ created_at: 2026-08-10T11:01:00.000Z
1953
3462
  const id = `RUN-PAGE-${index}`;
1954
3463
  await writeFile(
1955
3464
  join(root, ".agents", "records", "runs", "2026", "08", `${id}.jsonl`),
1956
- `${run(id, "2026-08-04", `TASK-PAGE-${index}`, 1_000).map((record) => JSON.stringify(record)).join("\n")}\n`,
3465
+ `${run(id, "2026-08-04", `TASK-PAGE-${index}`, 1_000)
3466
+ .map((record) => JSON.stringify(record))
3467
+ .join("\n")}\n`,
1957
3468
  "utf8",
1958
3469
  );
1959
3470
  }