@zaip-ai/cli 2.2.0 → 2.6.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 (420) hide show
  1. package/dist/services/adapters.d.ts +1 -1
  2. package/dist/services/adapters.d.ts.map +1 -1
  3. package/dist/services/adapters.js +23 -9
  4. package/dist/services/adapters.js.map +1 -1
  5. package/dist/services/agent-adapters.js +25 -9
  6. package/dist/services/agent-adapters.js.map +1 -1
  7. package/dist/services/agent-discovery.d.ts +27 -0
  8. package/dist/services/agent-discovery.d.ts.map +1 -0
  9. package/dist/services/agent-discovery.js +73 -0
  10. package/dist/services/agent-discovery.js.map +1 -0
  11. package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
  12. package/dist/services/codex-conversation-lifecycle-hook.js +153 -24
  13. package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
  14. package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
  15. package/dist/services/codex-pre-tool-hook-template.js +146 -72
  16. package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
  17. package/dist/services/codex-rules.d.ts +1 -1
  18. package/dist/services/codex-rules.d.ts.map +1 -1
  19. package/dist/services/codex-rules.js +3 -3
  20. package/dist/services/codex-subagent-hook-template.d.ts +1 -1
  21. package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
  22. package/dist/services/codex-subagent-hook-template.js +117 -66
  23. package/dist/services/codex-subagent-hook-template.js.map +1 -1
  24. package/dist/services/install-agents-template.d.ts.map +1 -1
  25. package/dist/services/install-agents-template.js +56 -6
  26. package/dist/services/install-agents-template.js.map +1 -1
  27. package/dist/services/logger.js +1 -1
  28. package/dist/services/logger.js.map +1 -1
  29. package/dist/services/logger.test.js +22 -1
  30. package/dist/services/logger.test.js.map +1 -1
  31. package/dist/services/runtime-template.test.js +129 -0
  32. package/dist/services/runtime-template.test.js.map +1 -1
  33. package/package.json +1 -1
  34. package/templates/.agents/.env.example +9 -3
  35. package/templates/.agents/README-ENG.md +30 -5
  36. package/templates/.agents/README.md +30 -7
  37. package/templates/.agents/architecture/software-architecture.md +1 -59
  38. package/templates/.agents/branding/brandbook.md +3 -0
  39. package/templates/.agents/config/agents/catalog.yaml +22 -10
  40. package/templates/.agents/config/agents/discovery.json +319 -0
  41. package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +2 -2
  42. package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +2 -2
  43. package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +11 -8
  44. package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +2 -2
  45. package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +2 -2
  46. package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +2 -2
  47. package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +2 -2
  48. package/templates/.agents/config/pricing/models.json +9 -5
  49. package/templates/.agents/config/project.yaml +12 -1
  50. package/templates/.agents/dashboard/.zaip-managed.json +375 -95
  51. package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-CGxeQak4.js +1 -0
  52. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-DaSllaJp.js → DashboardHelpDialog-tzS7YxYB.js} +57 -33
  53. package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-DEbCi1gP.js +1 -0
  54. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-1L7Qw-Gq.js +3 -0
  55. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-EInWr641.css +1 -0
  56. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-t1Om0Abw.js +1 -0
  57. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-B6aZfo5f.js +68 -0
  58. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-TPUT2IUt.js → icons-vendor-DiGC-dsJ.js} +1 -1
  59. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DgTmNHN5.js +2 -0
  60. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-Ct48XHGL.js → react-vendor-kPO6yNed.js} +1 -1
  61. package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-Bh1tDfsg.js +1 -0
  62. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-DQpKX9c1.js +1 -0
  63. package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
  64. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  65. package/templates/.agents/dashboard/apps/frontend/src/App.tsx +3 -1264
  66. package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +363 -0
  67. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.dom.test.ts +99 -0
  68. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +62 -6
  69. package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +3 -1
  70. package/templates/.agents/dashboard/apps/frontend/src/__tests__/app-composition-support.ts +7 -0
  71. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +9 -7
  72. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +151 -0
  73. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +28 -153
  74. package/templates/.agents/dashboard/apps/frontend/src/dashboard-app-shell.tsx +33 -0
  75. package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.ts +30 -0
  76. package/templates/.agents/dashboard/apps/frontend/src/dashboard-project-overview.ts +7 -1
  77. package/templates/.agents/dashboard/apps/frontend/src/dashboard-retry.ts +17 -0
  78. package/templates/.agents/dashboard/apps/frontend/src/dashboard-setup-route.ts +29 -0
  79. package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.ts +66 -0
  80. package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +3 -2
  81. package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +2 -2
  82. package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.test.ts +48 -0
  83. package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.ts +29 -0
  84. package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +68 -0
  85. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +2 -2
  86. package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.test.ts +36 -0
  87. package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.ts +30 -0
  88. package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +2 -5
  89. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +30 -19
  90. package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +9 -1
  91. package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-task-pagination.ts +77 -0
  92. package/templates/.agents/dashboard/apps/frontend/src/use-app-work-board.ts +397 -0
  93. package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +782 -0
  94. package/templates/.agents/dashboard/apps/frontend/src/use-snapshot-notice.tsx +49 -0
  95. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  96. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperPanelSlot.tsx +16 -0
  97. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.tsx +459 -0
  98. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +27 -17
  99. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +62 -186
  100. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorRunDialog.tsx +20 -0
  101. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-hides-calls-that-have-no-collected.test.ts +80 -0
  102. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +455 -0
  103. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +18 -525
  104. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +32 -508
  105. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-export-sources.ts +74 -0
  106. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-actions.ts +19 -0
  107. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-selectors.ts +49 -0
  108. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-formatters.ts +115 -0
  109. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test-fixtures.ts +2 -0
  110. package/templates/.agents/dashboard/modules/operations/package.json +1 -1
  111. package/templates/.agents/dashboard/modules/operations/src/contracts.ts +4 -0
  112. package/templates/.agents/dashboard/modules/operations/src/react/EntityTableBadges.tsx +34 -0
  113. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +8 -38
  114. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview-keeps-structure-classes-mutually-exclusive.test.ts +243 -0
  115. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +27 -275
  116. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +70 -247
  117. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewCharts.tsx +171 -0
  118. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewPanels.tsx +64 -0
  119. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +4 -3
  120. package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.test.tsx +2 -1
  121. package/templates/.agents/dashboard/modules/operations/src/react/manual-work-priority.test.ts +2 -1
  122. package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +6 -2
  123. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +6 -14
  124. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +3 -1
  125. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +2 -0
  126. package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.ts +32 -0
  127. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  128. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  129. package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
  130. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  131. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  132. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +1458 -1458
  133. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +1425 -1425
  134. package/templates/.agents/dashboard/packages/local-runtime/package.json +2 -1
  135. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +7 -3
  136. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +1458 -1459
  137. package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +25 -0
  138. package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.test.ts +1 -1
  139. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +53 -8
  140. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +79 -24
  141. package/templates/.agents/dashboard/packages/local-runtime/src/projection-refresh-diagnostics.ts +35 -0
  142. package/templates/.agents/dashboard/packages/local-runtime/src/server-costs-routes.ts +168 -0
  143. package/templates/.agents/dashboard/packages/local-runtime/src/server-dual-reads-manifest-summaries-without-losing.test.ts +344 -0
  144. package/templates/.agents/dashboard/packages/local-runtime/src/server-http-contracts.ts +31 -0
  145. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-routes.ts +345 -0
  146. package/templates/.agents/dashboard/packages/local-runtime/src/server-read-projections.ts +461 -0
  147. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +78 -0
  148. package/templates/.agents/dashboard/packages/local-runtime/src/server-route-context.ts +13 -0
  149. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +18 -0
  150. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +19 -3
  151. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +22 -21
  152. package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-view-allowlist.test.ts +25 -0
  153. package/templates/.agents/dashboard/packages/local-runtime/src/server-trace-routes.ts +64 -0
  154. package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +2 -30
  155. package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +6 -23
  156. package/templates/.agents/dashboard/packages/local-runtime/src/server.test-fixtures.ts +1 -1
  157. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +2 -330
  158. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +73 -1060
  159. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-first-fold.ts +78 -0
  160. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-projections.ts +561 -0
  161. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-runs.ts +600 -0
  162. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.test.ts +1 -1
  163. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-agent-dimension.ts +269 -0
  164. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-context.ts +32 -0
  165. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.ts +244 -0
  166. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-filtered-dimension.ts +292 -0
  167. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-financial.ts +547 -0
  168. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-model-dimension.ts +360 -0
  169. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-provider-dimension.ts +169 -0
  170. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +475 -0
  171. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-temporal-dimension.ts +132 -0
  172. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-timing.ts +299 -0
  173. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-view-page.ts +692 -0
  174. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +739 -0
  175. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-does-not-convert-delayed-historical-finalizer.test.ts +706 -0
  176. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts +748 -0
  177. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-first-fold-types.ts +1 -1
  178. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-keeps-orphan-telemetry-out-kanban-without.test.ts +710 -0
  179. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-marks-token-cost-telemetry-unavailable-when.test.ts +618 -0
  180. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +755 -0
  181. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuilds-disposable-snapshot-serves-zaip-records.test.ts +276 -0
  182. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +193 -0
  183. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-types.ts +123 -0
  184. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +1 -2805
  185. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +17 -6930
  186. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-base-views.ts +385 -0
  187. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-dashboard-views.ts +412 -0
  188. package/templates/.agents/dashboard/packages/local-runtime/src/work-priority-contract.test.ts +4 -3
  189. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-build.mjs +195 -0
  190. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-lifecycle.test.mjs +2 -7
  191. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-logging.mjs +35 -0
  192. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-navigation.mjs +114 -0
  193. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-paths.mjs +90 -0
  194. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +89 -418
  195. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +22 -12
  196. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  197. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  198. package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -1
  199. package/templates/.agents/design/.zaip-managed.json +5 -5
  200. package/templates/.agents/design/DESIGN.md +2 -186
  201. package/templates/.agents/design/README.md +12 -2
  202. package/templates/.agents/design/apps/catalog/package.json +1 -1
  203. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  204. package/templates/.agents/growth/strategy.md +3 -0
  205. package/templates/.agents/marketing/strategy.md +3 -0
  206. package/templates/.agents/requirements/autonomous-assurance.md +2 -1
  207. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
  208. package/templates/.agents/requirements/comparative-audit.md +1 -1
  209. package/templates/.agents/requirements/context-engine.md +1 -1
  210. package/templates/.agents/requirements/cost-observability.md +1 -1
  211. package/templates/.agents/requirements/dashboard-launch.md +1 -1
  212. package/templates/.agents/requirements/data-export.md +1 -1
  213. package/templates/.agents/requirements/design-system.md +13 -4
  214. package/templates/.agents/requirements/execution-engine.md +1 -1
  215. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  216. package/templates/.agents/requirements/model-orchestration.md +1 -1
  217. package/templates/.agents/requirements/public-distribution.md +4 -2
  218. package/templates/.agents/requirements/software-architecture.md +1 -1
  219. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  220. package/templates/.agents/requirements/work-lifecycle.md +3 -3
  221. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  222. package/templates/.agents/rules/architecture.md +2 -0
  223. package/templates/.agents/rules/astra-diagnostic.md +1 -1
  224. package/templates/.agents/rules/autonomy-decision.md +3 -1
  225. package/templates/.agents/rules/cloud-hostinger-autonomy.md +2 -0
  226. package/templates/.agents/rules/context.md +2 -1
  227. package/templates/.agents/rules/core.md +3 -3
  228. package/templates/.agents/rules/design-system-central-contract.md +17 -0
  229. package/templates/.agents/rules/evolution.md +3 -1
  230. package/templates/.agents/rules/frontend-lite.md +3 -1
  231. package/templates/.agents/rules/local-sqlite-storage.md +2 -2
  232. package/templates/.agents/rules/meta-mcp.md +3 -1
  233. package/templates/.agents/rules/model-orchestration.md +1 -1
  234. package/templates/.agents/rules/run-lifecycle-closure.md +6 -4
  235. package/templates/.agents/rules/security.md +3 -1
  236. package/templates/.agents/rules/specialist-routing.md +3 -1
  237. package/templates/.agents/rules/text-writing-utf8.md +1 -1
  238. package/templates/.agents/rules/workflow.md +7 -5
  239. package/templates/.agents/runtime/VERSION +1 -1
  240. package/templates/.agents/runtime/bin/zaip.mjs +519 -247
  241. package/templates/.agents/runtime/checksums.sha256 +6 -6
  242. package/templates/.agents/runtime/manifest.json +1 -1
  243. package/templates/.agents/runtime/pnpm-lock.sha256 +1 -1
  244. package/templates/.agents/runtime/provenance.json +5 -5
  245. package/templates/.agents/runtime/sbom.cdx.json +1 -1
  246. package/templates/.agents/sales/playbook.md +3 -0
  247. package/templates/.agents/skills/zaip-aios/SKILL.md +5 -3
  248. package/templates/.agents/skills/zaip-skill-adapt-stack/SKILL.md +1 -0
  249. package/templates/.agents/skills/zaip-skill-api-contracts/SKILL.md +14 -0
  250. package/templates/.agents/skills/zaip-skill-api-contracts/agents/openai.yaml +4 -0
  251. package/templates/.agents/skills/zaip-skill-application-observability/SKILL.md +15 -0
  252. package/templates/.agents/skills/zaip-skill-application-observability/agents/openai.yaml +4 -0
  253. package/templates/.agents/skills/zaip-skill-application-observability/references/signal-design.md +3 -0
  254. package/templates/.agents/skills/zaip-skill-application-readiness/SKILL.md +15 -0
  255. package/templates/.agents/skills/zaip-skill-application-readiness/agents/openai.yaml +4 -0
  256. package/templates/.agents/skills/zaip-skill-application-readiness/references/evidence-matrix.md +3 -0
  257. package/templates/.agents/skills/zaip-skill-architecture-design/SKILL.md +14 -0
  258. package/templates/.agents/skills/zaip-skill-architecture-design/agents/openai.yaml +4 -0
  259. package/templates/.agents/skills/zaip-skill-async-jobs/SKILL.md +14 -0
  260. package/templates/.agents/skills/zaip-skill-async-jobs/agents/openai.yaml +4 -0
  261. package/templates/.agents/skills/zaip-skill-auth-tenancy/SKILL.md +15 -0
  262. package/templates/.agents/skills/zaip-skill-auth-tenancy/agents/openai.yaml +4 -0
  263. package/templates/.agents/skills/zaip-skill-auth-tenancy/references/data-access-paths.md +9 -0
  264. package/templates/.agents/skills/zaip-skill-auth-tenancy/references/worker-scenario.md +5 -0
  265. package/templates/.agents/skills/zaip-skill-auth-tenancy/scripts/worker-contract.test.mjs +27 -0
  266. package/templates/.agents/skills/zaip-skill-author-skills/SKILL.md +2 -0
  267. package/templates/.agents/skills/zaip-skill-author-skills/references/engineering-skill-index.md +9 -0
  268. package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +5 -3
  269. package/templates/.agents/skills/zaip-skill-author-skills/scripts/author-skill-scripts.test.mjs +27 -0
  270. package/templates/.agents/skills/zaip-skill-backend/SKILL.md +4 -0
  271. package/templates/.agents/skills/zaip-skill-backend/references/deployment-environments.md +75 -0
  272. package/templates/.agents/skills/zaip-skill-backend/references/supabase-migration-contract.md +23 -0
  273. package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +2 -0
  274. package/templates/.agents/skills/zaip-skill-cache-strategy/SKILL.md +14 -0
  275. package/templates/.agents/skills/zaip-skill-cache-strategy/agents/openai.yaml +4 -0
  276. package/templates/.agents/skills/zaip-skill-change/SKILL.md +1 -1
  277. package/templates/.agents/skills/zaip-skill-cloud-engineering/SKILL.md +7 -0
  278. package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/SKILL.md +37 -0
  279. package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/agents/openai.yaml +6 -0
  280. package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workers-static-assets.md +26 -0
  281. package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workflow-templates.md +71 -0
  282. package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/scripts/cloudflare-github-deploy-contract.test.mjs +77 -0
  283. package/templates/.agents/skills/zaip-skill-config/SKILL.md +21 -11
  284. package/templates/.agents/skills/zaip-skill-config/agents/openai.yaml +2 -2
  285. package/templates/.agents/skills/zaip-skill-container-runtime/SKILL.md +14 -0
  286. package/templates/.agents/skills/zaip-skill-container-runtime/agents/openai.yaml +4 -0
  287. package/templates/.agents/skills/zaip-skill-context/SKILL.md +6 -1
  288. package/templates/.agents/skills/zaip-skill-context/references/prd-spec-task-handoff.md +10 -0
  289. package/templates/.agents/skills/zaip-skill-context/references/rule-selection.md +20 -0
  290. package/templates/.agents/skills/zaip-skill-cqrs/SKILL.md +1 -0
  291. package/templates/.agents/skills/zaip-skill-cybersecurity/SKILL.md +18 -0
  292. package/templates/.agents/skills/zaip-skill-cybersecurity/agents/openai.yaml +4 -0
  293. package/templates/.agents/skills/zaip-skill-cybersecurity/references/audit-contract.md +94 -0
  294. package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.mjs +185 -0
  295. package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.test.mjs +101 -0
  296. package/templates/.agents/skills/zaip-skill-data-modeling/SKILL.md +14 -0
  297. package/templates/.agents/skills/zaip-skill-data-modeling/agents/openai.yaml +4 -0
  298. package/templates/.agents/skills/zaip-skill-database-migrations/SKILL.md +20 -0
  299. package/templates/.agents/skills/zaip-skill-database-migrations/agents/openai.yaml +4 -0
  300. package/templates/.agents/skills/zaip-skill-database-migrations/references/manual-mode.md +15 -0
  301. package/templates/.agents/skills/zaip-skill-database-migrations/references/promotion-example.md +5 -0
  302. package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.mjs +145 -0
  303. package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.test.mjs +178 -0
  304. package/templates/.agents/skills/zaip-skill-dependency-upgrade/SKILL.md +14 -0
  305. package/templates/.agents/skills/zaip-skill-dependency-upgrade/agents/openai.yaml +4 -0
  306. package/templates/.agents/skills/zaip-skill-deployment-pipeline/SKILL.md +15 -0
  307. package/templates/.agents/skills/zaip-skill-deployment-pipeline/agents/openai.yaml +4 -0
  308. package/templates/.agents/skills/zaip-skill-deployment-pipeline/references/runtime-shapes.md +3 -0
  309. package/templates/.agents/skills/zaip-skill-design-system/SKILL.md +20 -9
  310. package/templates/.agents/skills/zaip-skill-dev-environment/SKILL.md +14 -0
  311. package/templates/.agents/skills/zaip-skill-dev-environment/agents/openai.yaml +4 -0
  312. package/templates/.agents/skills/zaip-skill-dev-environment/references/inventory-contract.md +7 -0
  313. package/templates/.agents/skills/zaip-skill-dev-environment/scripts/inventory.mjs +77 -0
  314. package/templates/.agents/skills/zaip-skill-disaster-recovery/SKILL.md +15 -0
  315. package/templates/.agents/skills/zaip-skill-disaster-recovery/agents/openai.yaml +4 -0
  316. package/templates/.agents/skills/zaip-skill-disaster-recovery/references/recovery-scope.md +3 -0
  317. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +3 -3
  318. package/templates/.agents/skills/zaip-skill-execution/references/correction-cycle.md +7 -0
  319. package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +1 -5
  320. package/templates/.agents/skills/zaip-skill-external-integrations/SKILL.md +14 -0
  321. package/templates/.agents/skills/zaip-skill-external-integrations/agents/openai.yaml +4 -0
  322. package/templates/.agents/skills/zaip-skill-frontend/SKILL.md +4 -0
  323. package/templates/.agents/skills/zaip-skill-frontend-componentization/SKILL.md +44 -0
  324. package/templates/.agents/skills/zaip-skill-frontend-componentization/agents/openai.yaml +4 -0
  325. package/templates/.agents/skills/zaip-skill-frontend-data-flows/SKILL.md +14 -0
  326. package/templates/.agents/skills/zaip-skill-frontend-data-flows/agents/openai.yaml +4 -0
  327. package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +2 -0
  328. package/templates/.agents/skills/zaip-skill-github-actions-setup/SKILL.md +36 -0
  329. package/templates/.agents/skills/zaip-skill-github-actions-setup/agents/openai.yaml +4 -0
  330. package/templates/.agents/skills/zaip-skill-github-actions-setup/references/cloudflare-pages.md +33 -0
  331. package/templates/.agents/skills/zaip-skill-github-actions-setup/references/github.md +63 -0
  332. package/templates/.agents/skills/zaip-skill-github-actions-setup/references/hostinger-vps.md +55 -0
  333. package/templates/.agents/skills/zaip-skill-github-actions-setup/references/npm.md +30 -0
  334. package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/check-skill.mjs +55 -0
  335. package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.mjs +61 -0
  336. package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.test.mjs +128 -0
  337. package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-ssh.integration.test.mjs +106 -0
  338. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +43 -76
  339. package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +131 -0
  340. package/templates/.agents/skills/zaip-skill-github-deploy/references/github-release-workflow-template.md +31 -0
  341. package/templates/.agents/skills/zaip-skill-github-deploy/references/release-gate-matrix.md +24 -0
  342. package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +44 -0
  343. package/templates/.agents/skills/zaip-skill-github-deploy/references/release-notes.md +134 -0
  344. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.mjs +389 -0
  345. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.test.mjs +134 -0
  346. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +25 -2
  347. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness-api.test.mjs +134 -0
  348. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.mjs +98 -0
  349. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.test.mjs +25 -0
  350. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.mjs +159 -0
  351. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.test.mjs +160 -0
  352. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.mjs +149 -12
  353. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.test.mjs +64 -5
  354. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/release-notes-coverage.test.mjs +126 -0
  355. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.mjs +78 -0
  356. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.test.mjs +51 -0
  357. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.mjs +184 -0
  358. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.test.mjs +109 -0
  359. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +2 -0
  360. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/SKILL.md +18 -10
  361. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/agents/openai.yaml +3 -4
  362. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/aws-cli-terraform.md +62 -0
  363. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/guia-iniciante-hostinger-vps.md +183 -0
  364. package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +2 -0
  365. package/templates/.agents/skills/zaip-skill-module-scaffold/SKILL.md +14 -0
  366. package/templates/.agents/skills/zaip-skill-module-scaffold/agents/openai.yaml +4 -0
  367. package/templates/.agents/skills/zaip-skill-module-scaffold/references/scaffold-contract.md +9 -0
  368. package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/helpers.test.mjs +121 -0
  369. package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/scaffold.mjs +169 -0
  370. package/templates/.agents/skills/zaip-skill-move-prd/SKILL.md +1 -1
  371. package/templates/.agents/skills/zaip-skill-move-spec/SKILL.md +1 -1
  372. package/templates/.agents/skills/zaip-skill-performance-engineering/SKILL.md +14 -0
  373. package/templates/.agents/skills/zaip-skill-performance-engineering/agents/openai.yaml +4 -0
  374. package/templates/.agents/skills/zaip-skill-prd/SKILL.md +1 -1
  375. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +1 -0
  376. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +26 -9
  377. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +39 -13
  378. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +1 -0
  379. package/templates/.agents/skills/zaip-skill-refactor-landing-page/SKILL.md +66 -0
  380. package/templates/.agents/skills/zaip-skill-refactor-landing-page/agents/openai.yaml +4 -0
  381. package/templates/.agents/skills/zaip-skill-refactor-landing-page/references/behavioral-dry-run.md +23 -0
  382. package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +40 -1
  383. package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +98 -0
  384. package/templates/.agents/skills/zaip-skill-review/SKILL.md +1 -0
  385. package/templates/.agents/skills/zaip-skill-rules/SKILL.md +3 -3
  386. package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +2 -0
  387. package/templates/.agents/skills/zaip-skill-setup/SKILL.md +19 -21
  388. package/templates/.agents/skills/zaip-skill-setup/agents/openai.yaml +2 -2
  389. package/templates/.agents/skills/zaip-skill-spec/SKILL.md +3 -2
  390. package/templates/.agents/skills/zaip-skill-storage-uploads/SKILL.md +14 -0
  391. package/templates/.agents/skills/zaip-skill-storage-uploads/agents/openai.yaml +4 -0
  392. package/templates/.agents/skills/zaip-skill-systematic-debugging/SKILL.md +14 -0
  393. package/templates/.agents/skills/zaip-skill-systematic-debugging/agents/openai.yaml +4 -0
  394. package/templates/.agents/skills/zaip-skill-task/SKILL.md +16 -7
  395. package/templates/.agents/skills/zaip-skill-task/references/commit-policy.md +25 -0
  396. package/templates/.agents/skills/zaip-skill-test-data/SKILL.md +14 -0
  397. package/templates/.agents/skills/zaip-skill-test-data/agents/openai.yaml +4 -0
  398. package/templates/.agents/skills/zaip-skill-test-data/scripts/generate.mjs +72 -0
  399. package/templates/.agents/skills/zaip-skill-testing-strategy/SKILL.md +15 -0
  400. package/templates/.agents/skills/zaip-skill-testing-strategy/agents/openai.yaml +4 -0
  401. package/templates/.agents/skills/zaip-skill-testing-strategy/references/example-map.md +3 -0
  402. package/templates/.agents/skills/zaip-skill-website-readiness/SKILL.md +8 -0
  403. package/templates/.agents/zaip-aios/VERSION +1 -1
  404. package/templates/.agents/zaip-aios/guides/10-seguranca.md +2 -1
  405. package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +5 -3
  406. package/templates/scripts/validate-cloud-hostinger-contract.mjs +34 -0
  407. package/templates/template-manifest.json +955 -211
  408. package/templates/.agents/branding/.gitkeep +0 -0
  409. package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-snUCQYTC.js +0 -1
  410. package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-BPtVUGgs.js +0 -1
  411. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-3Awyaovx.js +0 -3
  412. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-GgzpZ_PY.css +0 -1
  413. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BCvZFMEf.js +0 -1
  414. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DbaLbU2q.js +0 -68
  415. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-_MEktQNM.js +0 -2
  416. package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-D9-fqq9M.js +0 -1
  417. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-BDe4_Ubl.js +0 -1
  418. package/templates/.agents/growth/.gitkeep +0 -0
  419. package/templates/.agents/marketing/.gitkeep +0 -0
  420. package/templates/.agents/sales/.gitkeep +0 -0
@@ -0,0 +1,748 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import { WorkspaceFileSystem } from "@zaip-ai/core";
3
+ import type { CostSummarySource } from "@zaip-ai/dashboard-cost-monitor/server";
4
+ import { attachAgentProductivity } from "./sqlite-agent-productivity.js";
5
+ import {
6
+ readFirstFoldAllTime,
7
+ readFirstFoldBoardAllTime,
8
+ readFirstFoldMonthlyQuick,
9
+ readFirstFoldTopTasksAllTime,
10
+ readFirstFoldViewport,
11
+ } from "./sqlite-first-fold-cache.js";
12
+ import { operationsWorkListSqlRows } from "./sqlite-operations-work-list.js";
13
+ import type { SqliteQueryContext } from "./sqlite-query-context.js";
14
+ import {
15
+ queryActivityCostRows,
16
+ queryCostMonitorFactualDurationByDay,
17
+ queryCostMonitorFinancialActivityRows,
18
+ queryDeveloperCostAggregate,
19
+ queryInvocationCostRows,
20
+ queryInvocationTotals,
21
+ queryOperationsDeveloperAggregate,
22
+ } from "./sqlite-query-financial.js";
23
+ import { queryCostMonitorSummaryAggregate } from "./sqlite-query-summary.js";
24
+ import {
25
+ queryCanonicalRunCountByDay,
26
+ queryDailyPeriods,
27
+ queryExecutionDurationByDay,
28
+ queryFirstFoldAggregate,
29
+ queryOverviewPage,
30
+ queryTopTasks,
31
+ } from "./sqlite-query-timing.js";
32
+ import { queryUncachedViewPage } from "./sqlite-query-view-page.js";
33
+ import type {
34
+ SqliteFirstFoldAllTime,
35
+ SqliteFirstFoldAllTimeBoard,
36
+ SqliteFirstFoldMonthlyQuick,
37
+ } from "./sqlite-read-model-first-fold-types.js";
38
+ import { dbRelativePath, sqliteReadModelPath } from "./sqlite-read-model-schema.js";
39
+ import {
40
+ type SqliteFirstFoldAggregate,
41
+ type SqliteFirstFoldViewport,
42
+ type SqliteSummaryKind,
43
+ type SqliteSummaryPage,
44
+ type SqliteViewName,
45
+ sqliteViewMetadata,
46
+ } from "./sqlite-read-model-types.js";
47
+ import { installLegacyViewAliases } from "./sqlite-snapshot-cache.js";
48
+ export class SqliteReadModelFileSystem extends WorkspaceFileSystem {
49
+ private readonly executionDurationCache = new Map<string, Map<string, number>>();
50
+ private dailyAggregateRowsCache: Array<Record<string, number | string | null>> | null = null;
51
+ private firstFoldAllTimeCache: SqliteFirstFoldAllTime | null = null;
52
+ private firstFoldAllTimeBoardCache: SqliteFirstFoldAllTimeBoard | null = null;
53
+ private firstFoldTopTasksAllTimeCache: SqliteFirstFoldAllTime["top_tasks"] | null = null;
54
+ private firstFoldViewportCache: SqliteFirstFoldViewport | null = null;
55
+ private firstFoldMonthlyQuickCache: SqliteFirstFoldMonthlyQuick | null | undefined = undefined;
56
+ private firstFoldViewportTimings: Record<string, number> = {};
57
+ private metadataValues: Map<string, string> | null = null;
58
+ private readonly unfilteredViewPageCache = new Map<string, Array<Record<string, unknown>>>();
59
+ private readonly technicalPayloadRowsCache = new Map<string, Array<Record<string, unknown>>>();
60
+ private readonly viewPageResultCache = new Map<string, Record<string, unknown>>();
61
+ // Summary cards and temporal Cost tables consume the same aggregate. Keep
62
+ // exact filter results inside the immutable generation so a tab switch does
63
+ // not repeat its multi-second SQL scan.
64
+ private readonly costMonitorSummaryCache = new Map<string, CostSummarySource>();
65
+
66
+ canonicalSource(): ".agents/data" | ".agents/records" {
67
+ const current = this.database
68
+ .prepare("SELECT 1 FROM files WHERE path LIKE '.agents/data/%' LIMIT 1")
69
+ .get();
70
+ return current === undefined ? ".agents/records" : ".agents/data";
71
+ }
72
+ private dailyAggregateRows(): Array<Record<string, number | string | null>> {
73
+ if (this.dailyAggregateRowsCache === null) {
74
+ this.dailyAggregateRowsCache = this.database
75
+ .prepare("SELECT * FROM daily_aggregate_cache ORDER BY day")
76
+ .all() as Array<Record<string, number | string | null>>;
77
+ }
78
+ return this.dailyAggregateRowsCache;
79
+ }
80
+
81
+ private unfilteredViewRows(view: SqliteViewName): Array<Record<string, unknown>> {
82
+ const cached = this.unfilteredViewPageCache.get(view);
83
+ if (cached !== undefined) return cached;
84
+ const order = sqliteViewMetadata[view].order;
85
+ const rows = this.database.prepare(`SELECT * FROM ${view} ORDER BY ${order}`).all() as Array<
86
+ Record<string, unknown>
87
+ >;
88
+ this.unfilteredViewPageCache.set(view, rows);
89
+ return rows;
90
+ }
91
+
92
+ private technicalPayloadRows(payloadType: string): Array<Record<string, unknown>> {
93
+ const cached = this.technicalPayloadRowsCache.get(payloadType);
94
+ if (cached !== undefined) return cached;
95
+ const rows = (
96
+ this.database
97
+ .prepare("SELECT payload_json FROM zaip_aios_activities WHERE payload_type=?")
98
+ .all(payloadType) as Array<{ payload_json: string }>
99
+ ).flatMap(({ payload_json }) => {
100
+ try {
101
+ const parsed = JSON.parse(payload_json) as unknown;
102
+ return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)
103
+ ? [parsed as Record<string, unknown>]
104
+ : [];
105
+ } catch {
106
+ return [];
107
+ }
108
+ });
109
+ this.technicalPayloadRowsCache.set(payloadType, rows);
110
+ return rows;
111
+ }
112
+ private database: DatabaseSync;
113
+ private readonly ownsDatabase: boolean;
114
+
115
+ constructor(root: string, database?: DatabaseSync) {
116
+ super(root);
117
+ this.ownsDatabase = database === undefined;
118
+ this.database = database ?? new DatabaseSync(sqliteReadModelPath(root), { readOnly: true });
119
+ // The aliases are TEMP views on this connection. The rebuilding writer
120
+ // needs them too because first-fold readers deliberately query through
121
+ // the same uncommitted transaction.
122
+ installLegacyViewAliases(this.database);
123
+ }
124
+
125
+ override async exists(path: string): Promise<boolean> {
126
+ const exact = this.database.prepare("SELECT 1 FROM files WHERE path = ? LIMIT 1").get(path);
127
+ const child = this.database
128
+ .prepare("SELECT 1 FROM files WHERE path LIKE ? LIMIT 1")
129
+ .get(`${path.replace(/\/$/, "")}/%`);
130
+ return exact !== undefined || child !== undefined;
131
+ }
132
+
133
+ override async readText(path: string): Promise<string> {
134
+ const row = this.database.prepare("SELECT content FROM files WHERE path = ?").get(path) as
135
+ | { content?: string }
136
+ | undefined;
137
+ if (row?.content === undefined)
138
+ throw Object.assign(new Error(`SQLite read model is missing ${path}`), { code: "ENOENT" });
139
+ return row.content;
140
+ }
141
+
142
+ override async readBytes(path: string): Promise<Buffer> {
143
+ return Buffer.from(await this.readText(path), "utf8");
144
+ }
145
+
146
+ override async readTextFrom(
147
+ path: string,
148
+ offset: number,
149
+ ): Promise<{ content: string; nextOffset: number }> {
150
+ const content = await this.readText(path);
151
+ const bytes = Buffer.from(content, "utf8");
152
+ return {
153
+ content: bytes.subarray(Math.min(offset, bytes.byteLength)).toString("utf8"),
154
+ nextOffset: bytes.byteLength,
155
+ };
156
+ }
157
+
158
+ override async listFiles(path: string, suffix = ""): Promise<readonly string[]> {
159
+ const prefix = `${path.replace(/\/$/, "")}/%`;
160
+ const rows = this.database
161
+ .prepare("SELECT path FROM files WHERE path LIKE ? ORDER BY path")
162
+ .all(prefix) as Array<{ path: string }>;
163
+ return rows.map((row) => row.path).filter((candidate) => candidate.endsWith(suffix));
164
+ }
165
+
166
+ override async listDirectories(path: string): Promise<readonly string[]> {
167
+ const prefix = `${path.replace(/\/$/, "")}/`;
168
+ const rows = this.database
169
+ .prepare("SELECT path FROM files WHERE path LIKE ?")
170
+ .all(`${prefix}%`) as Array<{ path: string }>;
171
+ return [
172
+ ...new Set(
173
+ rows
174
+ .map((row) => row.path.slice(prefix.length).split("/")[0])
175
+ .filter(Boolean)
176
+ .map((name) => `${path.replace(/\/$/, "")}/${name}`),
177
+ ),
178
+ ].sort();
179
+ }
180
+
181
+ close(): void {
182
+ if (this.ownsDatabase) this.database.close();
183
+ }
184
+
185
+ private reopen(): void {
186
+ this.database = new DatabaseSync(sqliteReadModelPath(this.root), { readOnly: true });
187
+ installLegacyViewAliases(this.database);
188
+ this.executionDurationCache.clear();
189
+ this.dailyAggregateRowsCache = null;
190
+ this.firstFoldAllTimeCache = null;
191
+ this.firstFoldAllTimeBoardCache = null;
192
+ this.firstFoldTopTasksAllTimeCache = null;
193
+ this.firstFoldViewportCache = null;
194
+ this.firstFoldMonthlyQuickCache = undefined;
195
+ this.firstFoldViewportTimings = {};
196
+ this.metadataValues = null;
197
+ // Public pages belong to the opened immutable SQLite generation. Never
198
+ // carry them across refresh/rebuild, even when this filesystem instance is
199
+ // reused by the launcher.
200
+ this.unfilteredViewPageCache.clear();
201
+ this.technicalPayloadRowsCache.clear();
202
+ this.costMonitorSummaryCache.clear();
203
+ this.viewPageResultCache.clear();
204
+ }
205
+
206
+ /** Reopen after an external atomic canonical read-model rebuild. */
207
+ refresh(): void {
208
+ this.database.close();
209
+ this.reopen();
210
+ }
211
+
212
+ /**
213
+ * Release the Windows read-only handle before replacing the generation.
214
+ * The prior snapshot is reopened when rebuilding fails, preserving a usable
215
+ * read model and surfacing the original rebuild error to the caller.
216
+ */
217
+ async rebuildAndRefresh(rebuild: () => Promise<unknown>): Promise<void> {
218
+ this.database.close();
219
+ try {
220
+ await rebuild();
221
+ } finally {
222
+ this.reopen();
223
+ }
224
+ // A successful refresh must leave the precise public Cost Monitor view
225
+ // usable before the server builds its response snapshot.
226
+ this.viewPage("cost_monitor_daily", { limit: 1, offset: 0 });
227
+ }
228
+
229
+ /**
230
+ * Wall-clock execution duration by Sao Paulo day. Root Runs define the
231
+ * execution envelope; child Runs are intentionally excluded because their
232
+ * time is already contained by the root. Concurrent roots are merged so the
233
+ * same clock interval is never counted twice.
234
+ */
235
+ executionDurationByDay(
236
+ filter: {
237
+ from: string | null;
238
+ to: string | null;
239
+ providers?: readonly string[];
240
+ models?: readonly string[];
241
+ agents?: readonly string[];
242
+ phases?: readonly string[];
243
+ statuses?: readonly string[];
244
+ },
245
+ taskId: string | null = null,
246
+ ): Map<string, number> {
247
+ return queryExecutionDurationByDay(this.queryContext(), filter, taskId);
248
+ }
249
+
250
+ canonicalRunCountByDay(filter: {
251
+ from: string | null;
252
+ to: string | null;
253
+ providers?: readonly string[];
254
+ models?: readonly string[];
255
+ agents?: readonly string[];
256
+ phases?: readonly string[];
257
+ statuses?: readonly string[];
258
+ }): Map<string, number> {
259
+ return queryCanonicalRunCountByDay(this.queryContext(), filter);
260
+ }
261
+
262
+ dailyPeriods(filter: { from: string | null; to: string | null }) {
263
+ return queryDailyPeriods(this.queryContext(), filter);
264
+ }
265
+
266
+ /** SQL-backed first-fold aggregate. SQLite SUM excludes unknown null facts. */
267
+ firstFoldAggregate(filter: { from: string | null; to: string | null }): SqliteFirstFoldAggregate {
268
+ return queryFirstFoldAggregate(this.queryContext(), filter);
269
+ }
270
+
271
+ /**
272
+ * Returns the materialized default-month inputs when they remain complete.
273
+ * A later month with no facts in this immutable generation is also an exact
274
+ * empty result; every month that may contain a fact continues through SQL.
275
+ */
276
+ firstFoldMonthlyQuick(filter: {
277
+ from: string | null;
278
+ to: string | null;
279
+ }): SqliteFirstFoldMonthlyQuick | null {
280
+ const read = readFirstFoldMonthlyQuick(this.database, this.firstFoldMonthlyQuickCache, filter);
281
+ this.firstFoldMonthlyQuickCache = read.cache;
282
+ return read.result;
283
+ }
284
+
285
+ firstFoldRelevantLatestDay(): string | null {
286
+ const row = this.database
287
+ .prepare(`SELECT MAX(day) AS day FROM (
288
+ SELECT occurred_day_sp AS day FROM activities
289
+ UNION ALL SELECT occurred_day_sp AS day FROM canonical_work_items
290
+ UNION ALL SELECT occurred_day_sp AS day FROM canonical_artifacts
291
+ UNION ALL SELECT occurred_day_sp AS day FROM canonical_run_index
292
+ UNION ALL SELECT occurred_day_sp AS day FROM attributed_token_active_facts
293
+ )`)
294
+ .get() as { day?: string | null };
295
+ return typeof row.day === "string" ? row.day : null;
296
+ }
297
+
298
+ firstFoldAllTime(): SqliteFirstFoldAllTime {
299
+ if (this.firstFoldAllTimeCache !== null) return this.firstFoldAllTimeCache;
300
+ this.firstFoldAllTimeCache = readFirstFoldAllTime(
301
+ this.database,
302
+ () => this.dailyAggregateRows().length,
303
+ this.firstFoldViewportAllTime(),
304
+ );
305
+ return this.firstFoldAllTimeCache;
306
+ }
307
+
308
+ firstFoldBoardAllTime(): SqliteFirstFoldAllTimeBoard {
309
+ if (this.firstFoldAllTimeBoardCache !== null) return this.firstFoldAllTimeBoardCache;
310
+ this.firstFoldAllTimeBoardCache = readFirstFoldBoardAllTime(this.database, () => {
311
+ const rows = operationsWorkListSqlRows(this.database);
312
+ return {
313
+ pages: {
314
+ task: rows.filter((row) => row.kind === "task" || row.kind === "standalone-task"),
315
+ spec: rows.filter((row) => row.kind === "spec"),
316
+ prd: rows.filter((row) => row.kind === "prd"),
317
+ },
318
+ };
319
+ });
320
+ return this.firstFoldAllTimeBoardCache;
321
+ }
322
+
323
+ firstFoldTopTasksAllTime(): SqliteFirstFoldAllTime["top_tasks"] {
324
+ if (this.firstFoldTopTasksAllTimeCache !== null) return this.firstFoldTopTasksAllTimeCache;
325
+ this.firstFoldTopTasksAllTimeCache = readFirstFoldTopTasksAllTime(this.database);
326
+ return this.firstFoldTopTasksAllTimeCache;
327
+ }
328
+
329
+ firstFoldViewportAllTime(): SqliteFirstFoldViewport {
330
+ if (this.firstFoldViewportCache !== null) return this.firstFoldViewportCache;
331
+ this.firstFoldViewportCache = readFirstFoldViewport(
332
+ this.database,
333
+ this.firstFoldViewportTimings,
334
+ );
335
+ return this.firstFoldViewportCache;
336
+ }
337
+
338
+ firstFoldViewportProfile(): Readonly<Record<string, number>> {
339
+ return this.firstFoldViewportTimings;
340
+ }
341
+
342
+ /** Top tasks from canonical activities, limited by the caller for first paint. */
343
+ topTasks(filter: { from: string | null; to: string | null }, limit = 5) {
344
+ return queryTopTasks(this.queryContext(), filter, limit);
345
+ }
346
+
347
+ canonicalTraceFiles(markers: readonly string[]): Array<{ path: string; content: string }> {
348
+ const selected = [...new Set(markers.filter(Boolean))];
349
+ if (selected.length === 0) return [];
350
+ const clauses = selected.map(() => "content LIKE ?").join(" OR ");
351
+ return this.database
352
+ .prepare(`SELECT path, content FROM files
353
+ WHERE (path LIKE '.agents/data/%' OR path LIKE '.agents/records/%') AND (${clauses}) ORDER BY path`)
354
+ .all(...selected.map((marker) => `%${marker}%`)) as Array<{
355
+ path: string;
356
+ content: string;
357
+ }>;
358
+ }
359
+
360
+ taskTraceUsage(taskId: string) {
361
+ const runs = this.database
362
+ .prepare(`SELECT run_id, run_role, phase, duration_ms FROM canonical_run_index
363
+ WHERE task_id = ?`)
364
+ .all(taskId) as Array<{
365
+ run_id: string;
366
+ run_role: string;
367
+ phase: string | null;
368
+ duration_ms: number | null;
369
+ }>;
370
+ const financial = this.database
371
+ .prepare(`SELECT run_id, total_tokens, cost_brl FROM activities WHERE task_id = ?`)
372
+ .all(taskId) as Array<{
373
+ run_id: string;
374
+ total_tokens: number | null;
375
+ cost_brl: number | null;
376
+ }>;
377
+ const knownDurationRuns = runs.filter(
378
+ (run) =>
379
+ run.run_role === "root" && run.phase === "execution" && typeof run.duration_ms === "number",
380
+ ).length;
381
+ const durationByDay = this.executionDurationByDay({ from: null, to: null }, taskId);
382
+ const duration =
383
+ durationByDay.size === 0
384
+ ? null
385
+ : [...durationByDay.values()].reduce((sum, value) => sum + value, 0);
386
+ const knownTokens = financial.filter((row) => typeof row.total_tokens === "number");
387
+ const knownCosts = financial.filter((row) => typeof row.cost_brl === "number");
388
+ const metric = (value: number | null, known: number) => ({
389
+ value,
390
+ known_runs: known,
391
+ unknown_runs: Math.max(0, runs.length - known),
392
+ coverage_ratio: runs.length === 0 ? 1 : known / runs.length,
393
+ });
394
+ return {
395
+ run_count: runs.length,
396
+ duration_ms: metric(duration, knownDurationRuns),
397
+ total_tokens: metric(
398
+ knownTokens.length === 0
399
+ ? null
400
+ : knownTokens.reduce((sum, row) => sum + Number(row.total_tokens), 0),
401
+ knownTokens.length,
402
+ ),
403
+ cost: {
404
+ ...metric(
405
+ knownCosts.length === 0
406
+ ? null
407
+ : knownCosts.reduce((sum, row) => sum + Number(row.cost_brl), 0),
408
+ knownCosts.length,
409
+ ),
410
+ currency: knownCosts.length === 0 ? null : ("BRL" as const),
411
+ },
412
+ };
413
+ }
414
+
415
+ /** Cost Monitor agent population: canonical Agent Runs filtered by São Paulo calendar day. */
416
+ invocationTotals(filter: { from: string | null; to: string | null }): {
417
+ invocation_count: number;
418
+ llm_call_count: number | null;
419
+ total_tokens: number | null;
420
+ cost_usd: number | null;
421
+ cost_brl: number | null;
422
+ } {
423
+ return queryInvocationTotals(this.queryContext(), filter);
424
+ }
425
+
426
+ invocationCostRows(filter: {
427
+ from: string | null;
428
+ to: string | null;
429
+ providers?: readonly string[];
430
+ models?: readonly string[];
431
+ agents?: readonly string[];
432
+ phases?: readonly string[];
433
+ statuses?: readonly string[];
434
+ tasks?: readonly string[];
435
+ specs?: readonly string[];
436
+ prds?: readonly string[];
437
+ executions?: readonly string[];
438
+ changes?: readonly string[];
439
+ }) {
440
+ return queryInvocationCostRows(this.queryContext(), filter);
441
+ }
442
+
443
+ /**
444
+ * Attributed active-time facts for exactly the Cost Monitor financial
445
+ * population. This deliberately reads the same activity x Sao Paulo day
446
+ * fact used by Operations: recomputing a union from raw source intervals
447
+ * made the two surfaces disagree whenever sessions overlapped.
448
+ */
449
+ costMonitorFactualDurationByDay(
450
+ filter: Parameters<SqliteReadModelFileSystem["invocationCostRows"]>[0],
451
+ financialRows: readonly Record<string, unknown>[] = this.costMonitorFinancialActivityRows(
452
+ filter,
453
+ ),
454
+ ): Map<string, { known_sum: number; eligible_runs: number; known_runs: number }> {
455
+ return queryCostMonitorFactualDurationByDay(this.queryContext(), filter, financialRows);
456
+ }
457
+
458
+ /** Complete canonical Run population for global Cost Monitor aggregates. */
459
+ activityCostRows(filter: {
460
+ from: string | null;
461
+ to: string | null;
462
+ providers?: readonly string[];
463
+ models?: readonly string[];
464
+ agents?: readonly string[];
465
+ phases?: readonly string[];
466
+ statuses?: readonly string[];
467
+ tasks?: readonly string[];
468
+ specs?: readonly string[];
469
+ prds?: readonly string[];
470
+ executions?: readonly string[];
471
+ changes?: readonly string[];
472
+ }) {
473
+ return queryActivityCostRows(this.queryContext(), filter);
474
+ }
475
+
476
+ /** Cost Monitor's historical financial population, independent of Agent-only views. */
477
+ costMonitorFinancialActivityRows(
478
+ filter: Parameters<SqliteReadModelFileSystem["activityCostRows"]>[0],
479
+ ) {
480
+ return queryCostMonitorFinancialActivityRows(this.queryContext(), filter);
481
+ }
482
+
483
+ /**
484
+ * Aggregate-only Cost Monitor source. The SQL result is bounded to one row
485
+ * per selected day plus conversation/planning/execution and total rows; no
486
+ * activity-shaped record is returned to the server or serialized to HTTP.
487
+ */
488
+ developerCostAggregate(filter: {
489
+ from: string | null;
490
+ to: string | null;
491
+ accountIds?: readonly string[];
492
+ }) {
493
+ return queryDeveloperCostAggregate(this.queryContext(), filter);
494
+ }
495
+
496
+ /**
497
+ * Operations-only developer projection. It deliberately keeps the Cost
498
+ * Monitor aggregate unchanged: status, kind and risk are derived solely
499
+ * from canonical Task records linked to the developer's observed Task ids.
500
+ */
501
+ operationsDeveloperAggregate(filter: {
502
+ from: string | null;
503
+ to: string | null;
504
+ accountIds?: readonly string[];
505
+ }) {
506
+ return queryOperationsDeveloperAggregate(this.queryContext(), filter);
507
+ }
508
+
509
+ costMonitorSummaryAggregate(
510
+ filter: Parameters<SqliteReadModelFileSystem["activityCostRows"]>[0],
511
+ ): CostSummarySource {
512
+ return queryCostMonitorSummaryAggregate(this.queryContext(), filter);
513
+ }
514
+
515
+ /** Keyset cursor or LIMIT/OFFSET pagination for materialized work summaries. */
516
+ summaryPage(
517
+ kind: SqliteSummaryKind,
518
+ filter: {
519
+ from: string | null;
520
+ to: string | null;
521
+ status?: string;
522
+ risk?: string;
523
+ query?: string;
524
+ },
525
+ offset: number,
526
+ limit: number,
527
+ cursor: string | null = null,
528
+ ): SqliteSummaryPage {
529
+ // Entity summaries retain activity-derived historical coverage. Kanban is
530
+ // deliberately stricter and lists only canonical lifecycle records.
531
+ const table = "operations_work_summary";
532
+ const from = filter.from?.slice(0, 10) ?? null;
533
+ const to = filter.to?.slice(0, 10) ?? null;
534
+ const cursorValue = parseSummaryCursor(cursor);
535
+ const clauses = [
536
+ "entity_kind = ?",
537
+ "(? IS NULL OR occurred_day_sp >= ?)",
538
+ "(? IS NULL OR occurred_day_sp <= ?)",
539
+ ];
540
+ const values: Array<string | number | null> = [kind, from, from, to, to];
541
+ if (filter.status) {
542
+ clauses.push("status = ?");
543
+ values.push(filter.status);
544
+ }
545
+ if (filter.risk) {
546
+ clauses.push("risk = ?");
547
+ values.push(filter.risk);
548
+ }
549
+ if (filter.query) {
550
+ clauses.push("(id LIKE ? OR title LIKE ?)");
551
+ values.push(`%${filter.query}%`, `%${filter.query}%`);
552
+ }
553
+ const baseWhere = clauses.join(" AND ");
554
+ const baseValues = [...values];
555
+ if (cursorValue !== null) {
556
+ clauses.push("(occurred_at < ? OR (occurred_at = ? AND id < ?))");
557
+ values.push(cursorValue[0], cursorValue[0], cursorValue[1]);
558
+ }
559
+ const where = clauses.join(" AND ");
560
+ const total = Number(
561
+ (
562
+ this.database
563
+ .prepare(`SELECT COUNT(*) AS count FROM ${table} WHERE ${baseWhere}`)
564
+ .get(...baseValues) as { count: number }
565
+ ).count,
566
+ );
567
+ const pageOffset = cursorValue === null ? offset : 0;
568
+ const rows = this.database
569
+ .prepare(
570
+ `SELECT id, title, status, risk, occurred_at, occurred_day_sp,
571
+ invocation_count, llm_call_count, total_duration, total_tokens, total_cost_usd, total_cost_brl
572
+ FROM ${table} WHERE ${where} ORDER BY occurred_at DESC, id DESC LIMIT ? OFFSET ?`,
573
+ )
574
+ .all(...values, limit, pageOffset) as Array<Record<string, unknown>>;
575
+ const last = rows.at(-1);
576
+ return {
577
+ data_source: "sqlite_read_model",
578
+ kind,
579
+ offset: pageOffset,
580
+ limit,
581
+ total,
582
+ has_more: rows.length === limit && (cursorValue !== null || pageOffset + rows.length < total),
583
+ next_cursor:
584
+ last === undefined || rows.length < limit
585
+ ? null
586
+ : encodeSummaryCursor(String(last.occurred_at), String(last.id)),
587
+ rows,
588
+ };
589
+ }
590
+
591
+ /** Canonical page for the Board: keeps telemetry-only historical rows out. */
592
+ canonicalWorkPage(
593
+ kind: SqliteSummaryKind,
594
+ filter: { from: string | null; to: string | null },
595
+ offset: number,
596
+ limit: number,
597
+ ) {
598
+ return this.viewPage("operations_work_list", {
599
+ ...filter,
600
+ kind: kind === "task" ? "all-tasks" : kind,
601
+ offset,
602
+ limit,
603
+ });
604
+ }
605
+
606
+ overviewPage(period: "day" | "month" | "year", offset: number, limit: number) {
607
+ return queryOverviewPage(this.queryContext(), period, offset, limit);
608
+ }
609
+
610
+ viewPage(
611
+ view: SqliteViewName,
612
+ input: {
613
+ from?: string | null;
614
+ to?: string | null;
615
+ query?: string;
616
+ status?: string;
617
+ risk?: string;
618
+ provider?: string;
619
+ model?: string;
620
+ agent?: string;
621
+ phase?: string;
622
+ origin?: string;
623
+ workType?: string;
624
+ priority?: string;
625
+ kind?: "all" | "all-tasks" | "task" | "standalone-task" | "prd" | "spec";
626
+ offset?: number;
627
+ limit?: number;
628
+ },
629
+ ): ReturnType<SqliteReadModelFileSystem["uncachedViewPage"]> {
630
+ const key = `${view}:${JSON.stringify(input)}`;
631
+ const cached = this.viewPageResultCache.get(key);
632
+ if (cached !== undefined)
633
+ return structuredClone(cached) as ReturnType<SqliteReadModelFileSystem["uncachedViewPage"]>;
634
+ const result = this.uncachedViewPage(view, input);
635
+ if (view === "cost_monitor_zaip_agents") attachAgentProductivity(this.database, input, result);
636
+ if (this.viewPageResultCache.size >= 256) {
637
+ const oldest = this.viewPageResultCache.keys().next().value as string | undefined;
638
+ if (oldest !== undefined) this.viewPageResultCache.delete(oldest);
639
+ }
640
+ this.viewPageResultCache.set(key, structuredClone(result) as Record<string, unknown>);
641
+ return result;
642
+ }
643
+
644
+ /** Paginated allowlisted SQL view reader. Views are never interpolated from user input. */
645
+ private uncachedViewPage(
646
+ view: SqliteViewName,
647
+ input: {
648
+ from?: string | null;
649
+ to?: string | null;
650
+ query?: string;
651
+ status?: string;
652
+ risk?: string;
653
+ provider?: string;
654
+ model?: string;
655
+ agent?: string;
656
+ phase?: string;
657
+ origin?: string;
658
+ workType?: string;
659
+ priority?: string;
660
+ kind?: "all" | "all-tasks" | "task" | "standalone-task" | "prd" | "spec";
661
+ offset?: number;
662
+ limit?: number;
663
+ },
664
+ ) {
665
+ return queryUncachedViewPage(this.queryContext(), view, input);
666
+ }
667
+
668
+ metadata(): {
669
+ storage_mode: "sqlite_read_model";
670
+ db_path: string;
671
+ source_file_count: number;
672
+ excluded_source_count: number;
673
+ daily_aggregate_count: number;
674
+ activity_count: number;
675
+ canonical_run_count: number;
676
+ agent_run_count: number;
677
+ telemetry_summary_count: number;
678
+ unassisted_activity_count: number;
679
+ } {
680
+ if (this.metadataValues === null) {
681
+ this.metadataValues = new Map(
682
+ (
683
+ this.database.prepare("SELECT key, value FROM read_model_metadata").all() as Array<{
684
+ key: string;
685
+ value: string;
686
+ }>
687
+ ).map((row) => [row.key, row.value]),
688
+ );
689
+ }
690
+ const value = (key: string) => Number(this.metadataValues?.get(key) ?? 0);
691
+ return {
692
+ storage_mode: "sqlite_read_model",
693
+ db_path: process.env.ZAIP_SQLITE_DB_PATH ? "session-specific" : dbRelativePath,
694
+ source_file_count: value("source_file_count"),
695
+ excluded_source_count: value("excluded_source_count"),
696
+ daily_aggregate_count: value("daily_aggregate_count"),
697
+ activity_count: value("activity_count"),
698
+ canonical_run_count: value("canonical_run_count"),
699
+ agent_run_count: value("agent_run_count"),
700
+ telemetry_summary_count: value("telemetry_summary_count"),
701
+ unassisted_activity_count: value("unassisted_activity_count"),
702
+ };
703
+ }
704
+
705
+ projectionUpdatedAt(): string | null {
706
+ if (this.metadataValues === null) this.metadata();
707
+ const value = this.metadataValues?.get("snapshot_updated_at") ?? null;
708
+ return value !== null && Number.isFinite(Date.parse(value)) ? value : null;
709
+ }
710
+
711
+ latestTokenCollectedAt(): string | null {
712
+ if (this.metadataValues === null) this.metadata();
713
+ const value = this.metadataValues?.get("latest_token_collected_at") ?? null;
714
+ return value !== null && Number.isFinite(Date.parse(value)) ? value : null;
715
+ }
716
+
717
+ private queryContext(): SqliteQueryContext {
718
+ return {
719
+ database: this.database,
720
+ executionDurationCache: this.executionDurationCache,
721
+ costMonitorSummaryCache: this.costMonitorSummaryCache,
722
+ executionDurationByDay: this.executionDurationByDay.bind(this),
723
+ costMonitorFinancialActivityRows: this.costMonitorFinancialActivityRows.bind(this),
724
+ costMonitorFactualDurationByDay: this.costMonitorFactualDurationByDay.bind(this),
725
+ costMonitorSummaryAggregate: this.costMonitorSummaryAggregate.bind(this),
726
+ firstFoldMonthlyQuick: this.firstFoldMonthlyQuick.bind(this),
727
+ dailyAggregateRows: this.dailyAggregateRows.bind(this),
728
+ technicalPayloadRows: this.technicalPayloadRows.bind(this),
729
+ unfilteredViewRows: this.unfilteredViewRows.bind(this),
730
+ };
731
+ }
732
+ }
733
+
734
+ function encodeSummaryCursor(occurredAt: string, id: string): string {
735
+ return encodeURIComponent(JSON.stringify([occurredAt, id]));
736
+ }
737
+
738
+ function parseSummaryCursor(cursor: string | null): [string, string] | null {
739
+ if (cursor === null) return null;
740
+ try {
741
+ const parsed = JSON.parse(decodeURIComponent(cursor));
742
+ return Array.isArray(parsed) && typeof parsed[0] === "string" && typeof parsed[1] === "string"
743
+ ? [parsed[0], parsed[1]]
744
+ : null;
745
+ } catch {
746
+ return null;
747
+ }
748
+ }