@zaip-ai/cli 1.0.7 → 1.0.8

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 (410) hide show
  1. package/README.md +6 -4
  2. package/dist/services/adapters.d.ts +1 -1
  3. package/dist/services/adapters.d.ts.map +1 -1
  4. package/dist/services/adapters.js +15 -5
  5. package/dist/services/adapters.js.map +1 -1
  6. package/dist/services/adapters.test.js +1 -1
  7. package/dist/services/agent-adapters.d.ts +9 -0
  8. package/dist/services/agent-adapters.d.ts.map +1 -1
  9. package/dist/services/agent-adapters.js +38 -3
  10. package/dist/services/agent-adapters.js.map +1 -1
  11. package/dist/services/agent-adapters.test.js +8 -1
  12. package/dist/services/agent-adapters.test.js.map +1 -1
  13. package/dist/services/codex-config-template.d.ts +2 -1
  14. package/dist/services/codex-config-template.d.ts.map +1 -1
  15. package/dist/services/codex-config-template.js +13 -2
  16. package/dist/services/codex-config-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 +31 -7
  20. package/dist/services/codex-rules.js.map +1 -1
  21. package/dist/services/codex-subagent-hook-template.d.ts +1 -1
  22. package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
  23. package/dist/services/codex-subagent-hook-template.js +4 -1
  24. package/dist/services/codex-subagent-hook-template.js.map +1 -1
  25. package/dist/services/doctor.d.ts.map +1 -1
  26. package/dist/services/doctor.js +3 -1
  27. package/dist/services/doctor.js.map +1 -1
  28. package/dist/services/global-codex-config.d.ts +6 -3
  29. package/dist/services/global-codex-config.d.ts.map +1 -1
  30. package/dist/services/global-codex-config.js +82 -13
  31. package/dist/services/global-codex-config.js.map +1 -1
  32. package/dist/services/global-codex-config.test.js +57 -10
  33. package/dist/services/global-codex-config.test.js.map +1 -1
  34. package/dist/services/install-agents-template.d.ts.map +1 -1
  35. package/dist/services/install-agents-template.js +15 -2
  36. package/dist/services/install-agents-template.js.map +1 -1
  37. package/dist/services/logger.js +1 -1
  38. package/dist/services/logger.js.map +1 -1
  39. package/dist/services/logger.test.js +3 -3
  40. package/dist/services/logger.test.js.map +1 -1
  41. package/dist/services/runtime-template.test.js +21 -5
  42. package/dist/services/runtime-template.test.js.map +1 -1
  43. package/dist/services/template-manifest.d.ts.map +1 -1
  44. package/dist/services/template-manifest.js +2 -0
  45. package/dist/services/template-manifest.js.map +1 -1
  46. package/package.json +1 -1
  47. package/templates/.agents/config/agents/catalog.yaml +310 -10
  48. package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +30 -0
  49. package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +5 -5
  50. package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -1
  51. package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +30 -0
  52. package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +30 -0
  53. package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +30 -0
  54. package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +8 -8
  55. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +5 -3
  56. package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +30 -0
  57. package/templates/.agents/config/project.yaml +1 -1
  58. package/templates/.agents/dashboard/.zaip-managed.json +659 -163
  59. package/templates/.agents/dashboard/DATA-DICTIONARY.md +2227 -0
  60. package/templates/.agents/dashboard/README.md +48 -97
  61. package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-Z60df2r-.js +1 -0
  62. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-Cv-JcoxP.js → DashboardHelpDialog-Cs6dzDmW.js} +294 -109
  63. package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-Coc6pA-1.js +1 -0
  64. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-QE1k9yZB.css +1 -0
  65. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-_Pf5DA_A.js +3 -0
  66. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BVlz3DLZ.js +1 -0
  67. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-CaKwQP43.css +1 -0
  68. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-BZ5WdaMN.css +1 -0
  69. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-Cf9ctPVt.js +68 -0
  70. package/templates/.agents/dashboard/apps/frontend/dist/assets/{dashboard-localization-C98LGC-Q.js → dashboard-localization-CLJ0lT9v.js} +1 -1
  71. package/templates/.agents/dashboard/apps/frontend/dist/assets/icons-vendor-DFBuc_qp.js +1 -0
  72. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8A4DcNXM.js +2 -0
  73. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DK_enB5Z.css +1 -0
  74. package/templates/.agents/dashboard/apps/frontend/dist/assets/react-vendor-CCQOHdVI.js +9 -0
  75. package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-D9-fqq9M.js +1 -0
  76. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-DFY7ZDlu.css +1 -0
  77. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-pC2_0J8x.js +1 -0
  78. package/templates/.agents/dashboard/apps/frontend/dist/index.html +9 -2
  79. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  80. package/templates/.agents/dashboard/apps/frontend/src/App.tsx +952 -595
  81. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingBoundary.tsx +48 -0
  82. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingPanels.tsx +2 -0
  83. package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +247 -0
  84. package/templates/.agents/dashboard/apps/frontend/src/AppRequestGuards.tsx +95 -0
  85. package/templates/.agents/dashboard/apps/frontend/src/AppSetupRoutes.tsx +87 -0
  86. package/templates/.agents/dashboard/apps/frontend/src/CostCalculationGuidePage.tsx +641 -0
  87. package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +159 -0
  88. package/templates/.agents/dashboard/apps/frontend/src/DashboardCapabilityNav.tsx +13 -13
  89. package/templates/.agents/dashboard/apps/frontend/src/DashboardGlobalSettings.tsx +56 -0
  90. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +257 -313
  91. package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +149 -0
  92. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +35 -0
  93. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +111 -12
  94. package/templates/.agents/dashboard/apps/frontend/src/app-preferences.ts +15 -0
  95. package/templates/.agents/dashboard/apps/frontend/src/app-session-token.ts +20 -0
  96. package/templates/.agents/dashboard/apps/frontend/src/cost-calculation-guide.css +267 -0
  97. package/templates/.agents/dashboard/apps/frontend/src/cost-calculation-guide.test.ts +69 -0
  98. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +70 -0
  99. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +111 -0
  100. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +432 -13
  101. package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.ts +1 -1
  102. package/templates/.agents/dashboard/apps/frontend/src/main.tsx +1 -0
  103. package/templates/.agents/dashboard/apps/frontend/src/operations-detail-hydration.test.ts +55 -0
  104. package/templates/.agents/dashboard/apps/frontend/src/operations-detail-hydration.ts +36 -0
  105. package/templates/.agents/dashboard/apps/frontend/src/operations-entity-page-projection.test.ts +126 -0
  106. package/templates/.agents/dashboard/apps/frontend/src/operations-entity-page-projection.ts +181 -0
  107. package/templates/.agents/dashboard/apps/frontend/src/operations-period-contract.test.ts +138 -0
  108. package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +105 -0
  109. package/templates/.agents/dashboard/apps/frontend/src/operations-period.test.ts +6 -3
  110. package/templates/.agents/dashboard/apps/frontend/src/operations-period.ts +9 -5
  111. package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +24 -0
  112. package/templates/.agents/dashboard/apps/frontend/src/period-transition-overlay.css +44 -0
  113. package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +121 -62
  114. package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +471 -2
  115. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +84 -17
  116. package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +44 -0
  117. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +196 -39
  118. package/templates/.agents/dashboard/apps/frontend/src/snapshot-notice.ts +15 -0
  119. package/templates/.agents/dashboard/apps/frontend/src/sqlite-cost-adapters.ts +26 -0
  120. package/templates/.agents/dashboard/apps/frontend/src/styles.css +14 -2
  121. package/templates/.agents/dashboard/apps/frontend/src/traceability-workspace.css +38 -2
  122. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +187 -0
  123. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +190 -0
  124. package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +121 -0
  125. package/templates/.agents/dashboard/apps/frontend/src/use-app-operations-pages.ts +398 -0
  126. package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +141 -0
  127. package/templates/.agents/dashboard/apps/frontend/src/use-idle-cost-prefetch.ts +45 -0
  128. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +46 -0
  129. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.ts +37 -0
  130. package/templates/.agents/dashboard/apps/frontend/vite.config.ts +55 -5
  131. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  132. package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +47 -6
  133. package/templates/.agents/dashboard/modules/cost-monitor/src/duration-estimate.ts +13 -0
  134. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +64 -0
  135. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +275 -0
  136. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.test.ts +100 -15
  137. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.tsx +131 -40
  138. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.tsx +137 -19
  139. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.test.ts +2 -0
  140. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.tsx +13 -10
  141. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +303 -0
  142. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +226 -6
  143. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +479 -402
  144. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostSummary.tsx +5 -13
  145. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +312 -72
  146. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +373 -321
  147. package/templates/.agents/dashboard/modules/cost-monitor/src/react/MacroCostTable.test.ts +17 -0
  148. package/templates/.agents/dashboard/modules/cost-monitor/src/react/MacroCostTable.tsx +25 -6
  149. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-copy.ts +0 -2
  150. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-helpers.ts +17 -0
  151. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-responsive.css +6 -3
  152. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-row-filters.ts +123 -0
  153. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-summary.ts +8 -3
  154. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-views.ts +32 -0
  155. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor.css +52 -14
  156. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-presentation.ts +121 -0
  157. package/templates/.agents/dashboard/modules/cost-monitor/src/react/index.ts +3 -0
  158. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.test.ts +68 -0
  159. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +32 -5
  160. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +108 -0
  161. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.test.ts +12 -0
  162. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +60 -0
  163. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +106 -0
  164. package/templates/.agents/dashboard/modules/cost-monitor/src/server/aggregate.test.ts +2 -2
  165. package/templates/.agents/dashboard/modules/cost-monitor/src/server/aggregate.ts +5 -3
  166. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-pricing-fallback.test.ts +53 -0
  167. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.basics.test.ts +34 -0
  168. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test.ts +168 -137
  169. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.ts +188 -29
  170. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.test.ts +956 -0
  171. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +775 -0
  172. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-terminal-day.test.ts +95 -0
  173. package/templates/.agents/dashboard/modules/cost-monitor/src/server/index.ts +1 -0
  174. package/templates/.agents/dashboard/modules/cost-monitor/src/server/refactor-map-xr9l.json +61 -0
  175. package/templates/.agents/dashboard/modules/cost-monitor/src/task-cost-groups.test.ts +41 -0
  176. package/templates/.agents/dashboard/modules/cost-monitor/src/task-cost-groups.ts +55 -11
  177. package/templates/.agents/dashboard/modules/operations/package.json +2 -1
  178. package/templates/.agents/dashboard/modules/operations/src/contracts.ts +182 -0
  179. package/templates/.agents/dashboard/modules/operations/src/duration-population.test.ts +63 -1
  180. package/templates/.agents/dashboard/modules/operations/src/duration-population.ts +60 -5
  181. package/templates/.agents/dashboard/modules/operations/src/react/EntityDetailsDialog.tsx +14 -3
  182. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.test.ts +44 -1
  183. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +325 -18
  184. package/templates/.agents/dashboard/modules/operations/src/react/MacroPlanningDialog.tsx +1 -0
  185. package/templates/.agents/dashboard/modules/operations/src/react/OperationDateFilters.test.ts +9 -5
  186. package/templates/.agents/dashboard/modules/operations/src/react/OperationDateFilters.tsx +2 -2
  187. package/templates/.agents/dashboard/modules/operations/src/react/OperationsMainContent.tsx +168 -0
  188. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +95 -6
  189. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +365 -14
  190. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +532 -131
  191. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +314 -358
  192. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageNavigation.tsx +68 -0
  193. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +169 -0
  194. package/templates/.agents/dashboard/modules/operations/src/react/PeriodSummaryTable.tsx +51 -8
  195. package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.test.tsx +32 -0
  196. package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.tsx +62 -6
  197. package/templates/.agents/dashboard/modules/operations/src/react/TaskBoard.test.ts +55 -0
  198. package/templates/.agents/dashboard/modules/operations/src/react/TaskBoard.tsx +27 -19
  199. package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +99 -42
  200. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.priority.test.ts +19 -0
  201. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +255 -34
  202. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +163 -8
  203. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +101 -68
  204. package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.test.ts +72 -1
  205. package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.ts +78 -16
  206. package/templates/.agents/dashboard/modules/operations/src/react/execution-metrics.ts +6 -4
  207. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +50 -1
  208. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +143 -9
  209. package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +29 -4
  210. package/templates/.agents/dashboard/modules/operations/src/react/macro-planning-dialog-content.css +49 -0
  211. package/templates/.agents/dashboard/modules/operations/src/react/macro-planning-dialog.css +93 -50
  212. package/templates/.agents/dashboard/modules/operations/src/react/manual-work-priority.test.ts +82 -0
  213. package/templates/.agents/dashboard/modules/operations/src/react/operation-date-range.test.ts +29 -2
  214. package/templates/.agents/dashboard/modules/operations/src/react/operation-date-range.ts +22 -1
  215. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +77 -4
  216. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +65 -5
  217. package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +54 -0
  218. package/templates/.agents/dashboard/modules/operations/src/react/operations-global-filters.test.ts +19 -0
  219. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +149 -12
  220. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +27 -0
  221. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +136 -0
  222. package/templates/.agents/dashboard/modules/operations/src/react/operations-period-scope.test.ts +160 -0
  223. package/templates/.agents/dashboard/modules/operations/src/react/operations-period-scope.ts +47 -0
  224. package/templates/.agents/dashboard/modules/operations/src/react/operations-query.ts +10 -0
  225. package/templates/.agents/dashboard/modules/operations/src/react/operations-responsive.css +3 -0
  226. package/templates/.agents/dashboard/modules/operations/src/react/operations-view-labels.ts +28 -0
  227. package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +24 -7
  228. package/templates/.agents/dashboard/modules/operations/src/react/operations.css +42 -0
  229. package/templates/.agents/dashboard/modules/operations/src/react/period-summary-population.test.ts +54 -0
  230. package/templates/.agents/dashboard/modules/operations/src/react/period-summary-population.ts +32 -0
  231. package/templates/.agents/dashboard/modules/operations/src/react/period-summary.test.ts +165 -6
  232. package/templates/.agents/dashboard/modules/operations/src/react/period-summary.ts +148 -6
  233. package/templates/.agents/dashboard/modules/operations/src/react/popup-localization.test.ts +1 -1
  234. package/templates/.agents/dashboard/modules/operations/src/react/unified-work-board.css +132 -0
  235. package/templates/.agents/dashboard/modules/operations/src/react/unified-work-board.css.test.ts +13 -0
  236. package/templates/.agents/dashboard/modules/operations/src/react/unified-work-board.header.test.ts +16 -0
  237. package/templates/.agents/dashboard/modules/operations/src/react/use-infinite-column.ts +11 -5
  238. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +5 -3
  239. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.ts +4 -83
  240. package/templates/.agents/dashboard/modules/operations/src/server/build-operations-projection.test.ts +291 -15
  241. package/templates/.agents/dashboard/modules/operations/src/server/build-operations-projection.ts +182 -472
  242. package/templates/.agents/dashboard/modules/operations/src/server/canonical-compat.test.ts +40 -0
  243. package/templates/.agents/dashboard/modules/operations/src/server/canonical-compat.ts +19 -6
  244. package/templates/.agents/dashboard/modules/operations/src/server/canonical-run-projection.ts +31 -6
  245. package/templates/.agents/dashboard/modules/operations/src/server/daily-duration-projection.ts +220 -0
  246. package/templates/.agents/dashboard/modules/operations/src/server/execution-duration-projection.ts +28 -0
  247. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.test.ts +27 -2
  248. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.ts +22 -13
  249. package/templates/.agents/dashboard/modules/operations/src/server/filter.test.ts +3 -3
  250. package/templates/.agents/dashboard/modules/operations/src/server/filter.ts +7 -2
  251. package/templates/.agents/dashboard/modules/operations/src/server/index.ts +3 -0
  252. package/templates/.agents/dashboard/modules/operations/src/server/macro.ts +3 -12
  253. package/templates/.agents/dashboard/modules/operations/src/server/manifest-usage.ts +65 -0
  254. package/templates/.agents/dashboard/modules/operations/src/server/operations-projection-aggregates.ts +297 -0
  255. package/templates/.agents/dashboard/modules/operations/src/server/quick-daily-operations-projection.ts +324 -0
  256. package/templates/.agents/dashboard/modules/operations/src/server/quick-operations-projection.test.ts +505 -0
  257. package/templates/.agents/dashboard/modules/operations/src/server/quick-operations-projection.ts +609 -0
  258. package/templates/.agents/dashboard/modules/operations/src/server/runs.ts +18 -19
  259. package/templates/.agents/dashboard/modules/operations/src/work-board-model.ts +76 -0
  260. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  261. package/templates/.agents/dashboard/modules/traceability/src/server/build-task-trace.ts +3 -1
  262. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  263. package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
  264. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  265. package/templates/.agents/dashboard/packages/contracts/src/index.ts +1 -0
  266. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  267. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +1756 -0
  268. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +1608 -0
  269. package/templates/.agents/dashboard/packages/local-runtime/package.json +8 -3
  270. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-dashboard.mjs +12 -0
  271. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +83 -0
  272. package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +28 -0
  273. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +262 -0
  274. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-unix-launchers.mjs +41 -0
  275. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +105 -0
  276. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +1643 -107
  277. package/templates/.agents/dashboard/packages/local-runtime/src/agent-adapter-sync.ts +30 -0
  278. package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.test.ts +3 -2
  279. package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.ts +5 -0
  280. package/templates/.agents/dashboard/packages/local-runtime/src/manifest-runs.ts +72 -33
  281. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +335 -4
  282. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +392 -1
  283. package/templates/.agents/dashboard/packages/local-runtime/src/runtime.mjs +5 -5
  284. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +71 -0
  285. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +179 -0
  286. package/templates/.agents/dashboard/packages/local-runtime/src/server-cross-layer-parity.test.ts +245 -0
  287. package/templates/.agents/dashboard/packages/local-runtime/src/server-daily-read-models-route.ts +64 -0
  288. package/templates/.agents/dashboard/packages/local-runtime/src/server-daily-read-models.test.ts +204 -0
  289. package/templates/.agents/dashboard/packages/local-runtime/src/server-daily-read-models.ts +194 -0
  290. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-pages.test.ts +163 -0
  291. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-pages.ts +354 -0
  292. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-runs-route.test.ts +74 -0
  293. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-runs-route.ts +113 -0
  294. package/templates/.agents/dashboard/packages/local-runtime/src/server-overview.test.ts +68 -0
  295. package/templates/.agents/dashboard/packages/local-runtime/src/server-period.ts +47 -0
  296. package/templates/.agents/dashboard/packages/local-runtime/src/server-projections.ts +483 -0
  297. package/templates/.agents/dashboard/packages/local-runtime/src/server-settings.test.ts +5 -2
  298. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +163 -84
  299. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +145 -0
  300. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +551 -266
  301. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +1145 -308
  302. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.test.ts +53 -0
  303. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.ts +708 -0
  304. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +2232 -0
  305. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +6151 -0
  306. package/templates/.agents/dashboard/packages/local-runtime/src/work-priority-contract.test.ts +33 -0
  307. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-history.mjs +41 -0
  308. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-processes.mjs +210 -0
  309. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +437 -190
  310. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +299 -24
  311. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  312. package/templates/.agents/dashboard/packages/windows-launcher/LauncherVerificationBehaviorTests.cs +206 -0
  313. package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +95 -8
  314. package/templates/.agents/dashboard/packages/windows-launcher/build-dashboard-launcher.ps1 +2 -2
  315. package/templates/.agents/dashboard/packages/windows-launcher/run-launcher-verification-tests.ps1 +22 -0
  316. package/templates/.agents/dashboard/read-model.dbml +2201 -0
  317. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  318. package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +1 -1
  319. package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +214 -41
  320. package/templates/.agents/dashboard/work-priority.json +34 -0
  321. package/templates/.agents/dashboard/zaip-dashboard-linux.sh +45 -0
  322. package/templates/.agents/dashboard/zaip-dashboard-mac.command +3 -0
  323. package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
  324. package/templates/.agents/design/.zaip-managed.json +3 -3
  325. package/templates/.agents/design/apps/catalog/package.json +1 -1
  326. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  327. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  328. package/templates/.agents/requirements/comparative-audit.md +1 -1
  329. package/templates/.agents/requirements/context-engine.md +1 -1
  330. package/templates/.agents/requirements/cost-observability.md +1 -1
  331. package/templates/.agents/requirements/dashboard-launch.md +24 -0
  332. package/templates/.agents/requirements/data-export.md +1 -1
  333. package/templates/.agents/requirements/design-system.md +1 -1
  334. package/templates/.agents/requirements/execution-engine.md +1 -1
  335. package/templates/.agents/requirements/kanban-dashboard.md +4 -3
  336. package/templates/.agents/requirements/model-orchestration.md +1 -1
  337. package/templates/.agents/requirements/public-distribution.md +9 -6
  338. package/templates/.agents/requirements/software-architecture.md +1 -1
  339. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  340. package/templates/.agents/requirements/work-lifecycle.md +9 -3
  341. package/templates/.agents/requirements/zaip-strategic-95.md +4 -4
  342. package/templates/.agents/rules/autonomy-decision.md +15 -0
  343. package/templates/.agents/rules/core.md +1 -1
  344. package/templates/.agents/rules/run-lifecycle-closure.md +1 -1
  345. package/templates/.agents/rules/specialist-routing.md +19 -0
  346. package/templates/.agents/rules/workflow.md +1 -1
  347. package/templates/.agents/runtime/VERSION +1 -1
  348. package/templates/.agents/runtime/bin/zaip.mjs +114 -64
  349. package/templates/.agents/runtime/checksums.sha256 +6 -4
  350. package/templates/.agents/runtime/manifest.json +3 -1
  351. package/templates/.agents/runtime/pnpm-lock.sha256 +1 -0
  352. package/templates/.agents/runtime/provenance.json +11 -0
  353. package/templates/.agents/runtime/sbom.cdx.json +1929 -39
  354. package/templates/.agents/skills/zaip-aios/SKILL.md +1 -1
  355. package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +15 -0
  356. package/templates/.agents/skills/zaip-skill-brand-governance/agents/openai.yaml +4 -0
  357. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +30 -0
  358. package/templates/.agents/skills/zaip-skill-dashboard-sqlite/SKILL.md +25 -0
  359. package/templates/.agents/skills/zaip-skill-dashboard-sqlite/agents/openai.yaml +4 -0
  360. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/SKILL.md +18 -0
  361. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/agents/openai.yaml +6 -0
  362. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.mjs +71 -0
  363. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.test.mjs +60 -0
  364. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/scheduled-ready-queue-contract.test.mjs +111 -0
  365. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +2 -2
  366. package/templates/.agents/skills/zaip-skill-frontend-launcher/references/launcher-contract.md +3 -1
  367. package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +12 -0
  368. package/templates/.agents/skills/zaip-skill-general-operations/agents/openai.yaml +4 -0
  369. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +9 -7
  370. package/templates/.agents/skills/zaip-skill-github-deploy/agents/openai.yaml +2 -2
  371. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +11 -38
  372. package/templates/.agents/skills/zaip-skill-governance-compliance/SKILL.md +12 -0
  373. package/templates/.agents/skills/zaip-skill-governance-compliance/agents/openai.yaml +4 -0
  374. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +15 -0
  375. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/agents/openai.yaml +4 -0
  376. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/references/growth-revops-framework.md +25 -0
  377. package/templates/.agents/skills/zaip-skill-instalar-agendamento/SKILL.md +17 -0
  378. package/templates/.agents/skills/zaip-skill-instalar-agendamento/agents/openai.yaml +6 -0
  379. package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +3 -3
  380. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +76 -27
  381. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +128 -24
  382. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +122 -4
  383. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +66 -19
  384. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +193 -7
  385. package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +14 -0
  386. package/templates/.agents/skills/zaip-skill-sales-methodology/agents/openai.yaml +4 -0
  387. package/templates/.agents/skills/zaip-skill-sales-methodology/references/sales-process-framework.md +77 -0
  388. package/templates/.agents/skills/zaip-skill-setup/SKILL.md +5 -0
  389. package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +96 -0
  390. package/templates/.agents/skills/zaip-skill-sqlite-read-model/agents/openai.yaml +4 -0
  391. package/templates/.agents/skills/zaip-skill-sqlite-read-model/scripts/ensure-node.mjs +18 -0
  392. package/templates/.agents/zaip-aios/INDEX.md +1 -0
  393. package/templates/.agents/zaip-aios/README.md +37 -8
  394. package/templates/.agents/zaip-aios/VERSION +1 -1
  395. package/templates/.agents/zaip-aios/guides/09-agentes-e-squads.md +43 -6
  396. package/templates/.agents/zaip-aios/guides/10-seguranca.md +21 -7
  397. package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +32 -0
  398. package/templates/template-manifest.json +945 -214
  399. package/templates/.agents/dashboard/apps/frontend/dist/assets/AgentCatalogSettingsPage-CLYIi7Vo.js +0 -1
  400. package/templates/.agents/dashboard/apps/frontend/dist/assets/AgentCatalogSettingsPage-DTDNVQGX.css +0 -1
  401. package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-CzEggcRb.js +0 -1
  402. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-05YKn6Z4.js +0 -3
  403. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-YO3yqtgV.css +0 -1
  404. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8AzCnl3a.js +0 -77
  405. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DdBYQ_8D.css +0 -1
  406. package/templates/.agents/dashboard/apps/frontend/src/AgentCatalogSettingsPage.tsx +0 -617
  407. package/templates/.agents/dashboard/apps/frontend/src/agent-catalog-settings-page.css +0 -660
  408. package/templates/.agents/dashboard/apps/frontend/src/agent-catalog-settings.test.ts +0 -249
  409. package/templates/.agents/dashboard/dashboard.config.json +0 -4
  410. package/templates/.agents/dashboard/zaip-dashboard.exe +0 -0
@@ -0,0 +1,25 @@
1
+ # Framework de Growth e RevOps
2
+
3
+ Use o framework para orientar decisões, não para substituir evidência por estimativas.
4
+
5
+ ## Diagnóstico
6
+
7
+ Defina uma árvore de métricas: objetivo de negócio, métricas de resultado, drivers, guardrails, definição, origem, proprietário e período. Defina a unidade de análise, janela temporal, população, funil, métricas e fontes. Verifique cobertura, duplicidade, atrasos de atribuição, mudanças de definição e viés de seleção antes de comparar períodos ou segmentos.
8
+
9
+ Para RevOps, registre estágios, critérios de entrada e saída, handoffs, SLA, responsável e system of record de marketing, vendas, onboarding, suporte, retenção e expansão. Uma lacuna de source of truth deve aparecer como risco operacional, não ser conciliada por suposição.
10
+
11
+ ## Experimentos
12
+
13
+ Mantenha um portfólio de experimentos com hipótese, alavanca, população elegível, controle ou comparação, métrica primária, guardrails, duração, critério de parada, decisão esperada, risco, dependências, proprietário e status. Um resultado indisponível ou inconclusivo deve permanecer inconclusivo.
14
+
15
+ ## Caso financeiro
16
+
17
+ Mostre cenários base, conservador e agressivo, com premissas, fórmula, intervalo e sensibilidade para receita incremental, custo evitado, margem, capacidade ou payback. Diferencie potencial, cenário e resultado observado; somente resultado observado pode ser declarado como realizado.
18
+
19
+ ## Aprendizado histórico
20
+
21
+ Registre hipótese, execução, resultado, decisão, contexto, limitação e reutilização recomendada. Use resultados anteriores comprovados como evidência condicionada ao contexto; não transforme um aprendizado histórico em regra universal.
22
+
23
+ ## Fronteiras
24
+
25
+ Robert orienta a priorização estratégica de crescimento e RevOps. Gabi valida dados e métodos quantitativos. Sarah governa marca e posicionamento. Lúcia executa estratégia e ativos de marketing. Nenhuma dessas atividades autoriza abordagem comercial, mudança de preço, campanha, contratação ou publicação externa.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: zaip-skill-instalar-agendamento
3
+ description: Install or update the native Codex hourly scheduler for the ready-work queue.
4
+ ---
5
+
6
+ # Instalar agendamento da fila pronta
7
+
8
+ Use esta skill somente quando a pessoa solicitar instalar, atualizar ou verificar o agendamento local da fila pronta. Ela configura o relógio; não inicia uma execução por conta própria.
9
+
10
+ 1. Confirme que o repositório é ZAIP habilitado e que a automação nativa de tarefas agendadas do Codex Desktop está chamável, com capacidade `automation_update`. Pare com `blocked` se ela não estiver disponível. Nunca use o Agendador do Windows, um arquivo, Git ou uma promessa de execução futura como substituto.
11
+ 2. Use `codex_app list_projects` para resolver o projeto Codex atual e seu checkout local real; não invente identificador, diretório ou contexto. Crie ou atualize, sem duplicar, a tarefa standalone de nome estável `ZAIP-AIOS - Fila Pronta Horária`: a cada hora, no minuto 0, em nova conversa no projeto resolvido. Ela abre uma única invocação com o prompt explícito `Ignore Automation memory and $CODEX_HOME. Start immediately by validating the repository and ready queue. First call codex_app set_thread_title without threadId, using America/Sao_Paulo local time in the exact format [YYYY-MM-DD-T-HH-mm] Tarefa Agendada; record a rename failure but continue the queue. Use $zaip-skill-executar-fila-pronta; this user-installed schedule authorizes only canonically ready/eligible items, never promotes draft or resumes blocked or failed work; respect the persisted manual order in .agents/dashboard/work-priority.json.`
12
+ 3. Antes de gravar, valide o checkout: raiz Git existente, `.agents/config/project.yaml` com `zaip.enabled: true`, runtime ZAIP disponível e caminho absoluto sem credenciais. Falhe fechado se algum requisito faltar; não registre uma tarefa parcial.
13
+ 4. Consulte `$CODEX_HOME/automations/*/automation.toml` somente em leitura, exclusivamente pelo nome estável para resolver identidade e deduplicação. É proibido criar, editar ou apagar TOML, ou usá-lo como fallback. Todas as visualizações e mutações da automação são exclusivamente por `codex_app automation_update`. Se houver mais de uma tarefa com esse nome, pare e reporte o conflito sem apagar nada. Se houver uma, inspecione seu ID, ação, agenda horária, nova conversa e diretório de trabalho e atualize-a; se não houver, crie uma. Preserve tarefas agendadas fora desse nome.
14
+ 5. Verifique após criar/atualizar que existe exatamente uma tarefa com o nome, agenda a cada hora no minuto 0, nova conversa, checkout esperado e prompt da skill executora que respeita `.agents/dashboard/work-priority.json`. Registre somente a evidência observada; não afirme que uma hora futura será executada.
15
+ 6. Explique que o agendamento pertence à máquina e ao usuário que o instalou. O repositório versiona a skill e o contrato, mas não cria um relógio em clones, nem funciona com a máquina desligada, o Codex Desktop fechado ou sem a automação nativa.
16
+
17
+ Não use esta skill para selecionar itens, burlar bloqueios, executar todos os itens `planned`, alterar prioridades do Kanban ou fazer deploy/push.
@@ -0,0 +1,6 @@
1
+ interface:
2
+ display_name: "ZAIP Instalar Agendamento"
3
+ short_description: "Instale ou atualize o agendamento horário nativo do Codex."
4
+ default_prompt: "Use $zaip-skill-instalar-agendamento para instalar ou atualizar com segurança o agendamento horário nativo do Codex Desktop, com validação imediata da fila e sua ordem manual persistida."
5
+ policy:
6
+ allow_implicit_invocation: false
@@ -5,6 +5,6 @@ description: Plan evidence-grounded marketing strategy, copy, campaigns, assets,
5
5
 
6
6
  # Planejar marketing
7
7
 
8
- 1. Delimitar público, objetivo, canal, mensagem, evidência disponível e métrica de sucesso.
9
- 2. Produzir estratégia, copy, campanha, ativos ou briefing de imagem proporcionais ao objetivo; distinguir fatos fornecidos de hipóteses.
10
- 3. Encaminhar website para Jonny, frontend de produto para Doug e regra visual central para Manu quando o escopo não for marketing.
8
+ 1. Delimitar público, objetivo, canal, mensagem, Brandbook aprovado como input somente-leitura, evidência disponível e métrica de sucesso.
9
+ 2. Produzir estratégia, copy, campanha, conteúdo, aplicação de marca ou ativo proporcionais ao objetivo; distinguir fatos fornecidos de hipóteses. Copy de marketing ambígua permanece com Lúcia.
10
+ 3. Escalar Sarah somente se uma decisão de marca estiver ausente, contraditória ou precisar ser criada; um Brandbook aprovado não redireciona a entrega para Branding. Encaminhar script voltado a vendas para Aaron, estratégia empresarial/RevOps para Robert, website para Jonny, frontend de produto para Doug e regra visual central para Manu.
@@ -3,9 +3,11 @@ import { join, resolve } from "node:path";
3
3
  import {
4
4
  aggregate,
5
5
  duplicateUsageAssignments,
6
+ duplicateUsageImpact,
6
7
  exactCompletedSegment,
7
8
  filesUnder,
8
9
  jsonLines,
10
+ isExactDuplicateUsageGroup,
9
11
  loadSegments,
10
12
  pricingFor,
11
13
  recordOccurredAt,
@@ -14,9 +16,13 @@ import {
14
16
  sameCost,
15
17
  usageStatus,
16
18
  usageView,
19
+ supersedableUsageBeforeTerminal,
17
20
  withSequence,
18
21
  } from "./reconcile-telemetry-lib.mjs";
19
- import { remeasureSelectedRuns } from "./reconcile-telemetry-remeasurement.mjs";
22
+ import {
23
+ remeasureSelectedRuns,
24
+ timingEnrichmentRunIds,
25
+ } from "./reconcile-telemetry-remeasurement.mjs";
20
26
 
21
27
  const workspace = resolve(process.cwd());
22
28
  const apply = process.argv.includes("--apply");
@@ -39,9 +45,21 @@ const selectedRunIds = new Set(
39
45
  : [],
40
46
  ),
41
47
  );
48
+ const selectedSessionFiles = process.argv
49
+ .flatMap((argument, index, values) =>
50
+ argument === "--session-file"
51
+ ? [String(values[index + 1] ?? "")]
52
+ : argument.startsWith("--session-file=")
53
+ ? [argument.slice("--session-file=".length)]
54
+ : [],
55
+ )
56
+ .filter(Boolean);
42
57
  if (remeasure && selectedRunIds.size === 0) {
43
58
  throw new Error("--remeasure requires at least one explicit --run <RUN-ID>");
44
59
  }
60
+ if (apply && deduplicate && selectedRunIds.size === 0) {
61
+ throw new Error("--apply --deduplicate requires at least one explicit --run <RUN-ID>");
62
+ }
45
63
  const applyBackfill = apply && !deduplicate && !remeasure;
46
64
 
47
65
  const runFiles = await filesUnder(join(workspace, ".agents", "records", "runs"), ".jsonl");
@@ -166,20 +184,35 @@ for (const file of runFiles) {
166
184
  if (event.source_segment_key && event.tokens?.total !== null)
167
185
  usedKeys.add(event.source_segment_key);
168
186
  const { measured, deduplicated } = usageStatus(usage);
169
- if (started) runs.push({ file, records, started, usage, measured, deduplicated });
187
+ if (started) runs.push({ file, records, started, usage, measured, deduplicated, nativeMeasured });
170
188
  }
171
189
 
172
- const allSegments = await loadSegments(workspace);
173
- const remeasurement = remeasure
174
- ? await remeasureSelectedRuns({
175
- apply,
176
- allSegments,
177
- runs,
178
- selectedRunIds,
179
- timingOnly,
180
- workspace,
181
- })
182
- : [];
190
+ const allSegments = await loadSegments(
191
+ workspace,
192
+ selectedSessionFiles.length === 0 ? null : selectedSessionFiles,
193
+ );
194
+ // Native usage can be captured before the Codex session emits task_complete.
195
+ // A normal backfill must not replace those observed tokens or costs, but it can
196
+ // append an exact, timing-only correction once that terminal boundary appears.
197
+ const timingRunIds = timingEnrichmentRunIds({
198
+ remeasure,
199
+ applyBackfill,
200
+ selectedRunIds,
201
+ runs,
202
+ });
203
+ const remeasurement =
204
+ remeasure || (applyBackfill && timingRunIds.size > 0)
205
+ ? await remeasureSelectedRuns({
206
+ apply,
207
+ allSegments,
208
+ runs,
209
+ selectedRunIds: timingRunIds,
210
+ // Automatic backfill is intentionally timing-only. Explicit remeasurement
211
+ // retains its existing token/cost correction behavior unless requested.
212
+ timingOnly: remeasure ? timingOnly : true,
213
+ workspace,
214
+ })
215
+ : [];
183
216
  const unfinished = runs.filter(
184
217
  (run) => !run.records.some((record) => recordType(record) === "run.finished"),
185
218
  );
@@ -351,7 +384,21 @@ for (const run of runs) {
351
384
  }
352
385
 
353
386
  const duplicateGroups = duplicateUsageAssignments(runs);
354
- const duplicateAssignments = duplicateGroups.flatMap((group) => group.slice(1));
387
+ const exactDuplicateGroups = duplicateGroups.filter(isExactDuplicateUsageGroup);
388
+ const aliasReviewGroups = duplicateGroups.filter((group) => !isExactDuplicateUsageGroup(group));
389
+ const selectedDuplicateGroups = selectedRunIds.size === 0
390
+ ? exactDuplicateGroups
391
+ : exactDuplicateGroups.filter((group) =>
392
+ group.some(({ run }) => selectedRunIds.has(run.started.run_id)),
393
+ );
394
+ const selectedAliasReviewGroups = selectedRunIds.size === 0
395
+ ? aliasReviewGroups
396
+ : aliasReviewGroups.filter((group) =>
397
+ group.some(({ run }) => selectedRunIds.has(run.started.run_id)),
398
+ );
399
+ const duplicateAssignments = selectedDuplicateGroups.flatMap((group) =>
400
+ group.slice(1).filter(({ run }) => selectedRunIds.size === 0 || selectedRunIds.has(run.started.run_id)),
401
+ );
355
402
  let deduplicatedEvents = 0;
356
403
  if (apply && deduplicate) {
357
404
  for (const { run, usage } of duplicateAssignments) {
@@ -600,26 +647,25 @@ const eligible = candidates.filter(
600
647
 
601
648
  if (applyBackfill) {
602
649
  for (const { run, segment, confidence } of eligible) {
650
+ // Re-read each Run under the serial apply loop: a preceding timing repair may
651
+ // have reordered or appended a correction after the initial scan.
652
+ const persistedRecords = jsonLines(await readFile(run.file, "utf8"));
653
+ const finishIndex = persistedRecords.findIndex((record) => recordType(record) === "run.finished");
654
+ const insertAt = finishIndex < 0 ? persistedRecords.length : finishIndex;
603
655
  const tokens = aggregate(segment);
604
656
  const model = segment.model ?? run.started.model ?? null;
605
657
  const cost = await pricingFor(workspace, model, tokens);
606
- const superseded = [...run.usage]
607
- .reverse()
608
- .find(
609
- (event) =>
610
- event.tokens?.total === null &&
611
- !run.usage.some((other) => other.supersedes_event_id === event.event_id),
612
- );
613
- const sequence = Math.max(...run.records.map((record) => recordSequence(record) ?? 0)) + 1;
658
+ const superseded = supersedableUsageBeforeTerminal(persistedRecords);
659
+ const sequence = Math.max(...persistedRecords.map((record) => recordSequence(record) ?? 0)) + 1;
614
660
  const event = {
615
661
  schema_version: 2,
616
662
  event_id: `${run.started.run_id}:reconcile:${String(sequence).padStart(6, "0")}`,
617
663
  run_id: run.started.run_id,
618
664
  sequence,
619
- occurred_at: run.records.find((record) => recordType(record) === "run.finished")
665
+ occurred_at: persistedRecords.find((record) => recordType(record) === "run.finished")
620
666
  ? new Date(
621
667
  Date.parse(
622
- recordOccurredAt(run.records.find((record) => recordType(record) === "run.finished")),
668
+ recordOccurredAt(persistedRecords.find((record) => recordType(record) === "run.finished")),
623
669
  ) - 1,
624
670
  ).toISOString()
625
671
  : new Date().toISOString(),
@@ -640,9 +686,7 @@ if (applyBackfill) {
640
686
  ...(segment.finished_at ? { source_finished_at: segment.finished_at } : {}),
641
687
  runtime: { reasoning_effort: segment.effort, service_tier: segment.service_tier },
642
688
  };
643
- const finishIndex = run.records.findIndex((record) => recordType(record) === "run.finished");
644
- const insertAt = finishIndex < 0 ? run.records.length : finishIndex;
645
- const updated = [...run.records.slice(0, insertAt), event, ...run.records.slice(insertAt)].map(
689
+ const updated = [...persistedRecords.slice(0, insertAt), event, ...persistedRecords.slice(insertAt)].map(
646
690
  (record, index) => withSequence(record, index + 1),
647
691
  );
648
692
  const temporary = `${run.file}.reconcile.tmp`;
@@ -722,6 +766,11 @@ console.log(
722
766
  ).length,
723
767
  duplicated_correction_segments: correctionKeys.length - new Set(correctionKeys).size,
724
768
  duplicate_segment_groups: duplicateGroups.length,
769
+ exact_source_key_groups: exactDuplicateGroups.length,
770
+ canonical_alias_review_groups: aliasReviewGroups.length,
771
+ selected_duplicate_segment_groups: selectedDuplicateGroups.length,
772
+ selected_canonical_alias_review_groups: selectedAliasReviewGroups.length,
773
+ selected_duplicate_segment_impact: duplicateUsageImpact(duplicateAssignments),
725
774
  duplicate_segment_assignments: duplicateAssignments.length,
726
775
  duplicate_segment_run_ids: duplicateGroups.map((group) =>
727
776
  group.map(({ run }) => run.started.run_id),
@@ -112,6 +112,18 @@ export function usageView(record) {
112
112
  };
113
113
  }
114
114
 
115
+ export function supersedableUsageBeforeTerminal(records) {
116
+ const finishIndex = records.findIndex((record) => recordType(record) === "run.finished");
117
+ const beforeTerminal = records.slice(0, finishIndex < 0 ? records.length : finishIndex);
118
+ const usage = beforeTerminal.map(usageView).filter(Boolean);
119
+ return [...usage]
120
+ .reverse()
121
+ .find(
122
+ (event) =>
123
+ event.tokens?.total === null && !usage.some((other) => other.supersedes_event_id === event.event_id),
124
+ ) ?? null;
125
+ }
126
+
115
127
  export function withSequence(record, sequence) {
116
128
  if (!Array.isArray(record)) return { ...record, sequence };
117
129
  const copy = [...record];
@@ -127,6 +139,10 @@ export function canonicalSegmentKey(sourceSegmentKey) {
127
139
  return (sessionsMarker < 0 ? normalized : normalized.slice(sessionsMarker + 1)).toLowerCase();
128
140
  }
129
141
 
142
+ function normalizedRawSegmentKey(sourceSegmentKey) {
143
+ return String(sourceSegmentKey).replaceAll("\\", "/").toLowerCase();
144
+ }
145
+
130
146
  export function usageStatus(usage) {
131
147
  const superseded = new Set(usage.map((event) => event.supersedes_event_id).filter(Boolean));
132
148
  const effective = usage.filter((event) => !superseded.has(event.event_id));
@@ -153,26 +169,22 @@ export function duplicateUsageAssignments(runs) {
153
169
  continue;
154
170
  }
155
171
  const baseSegmentKey = canonicalSegmentKey(usage.source_segment_key);
156
- const signature = JSON.stringify([
157
- baseSegmentKey,
158
- run.started.client_turn_id ?? null,
159
- usage.tokens.input,
160
- usage.tokens.cached_input,
161
- usage.tokens.output,
162
- usage.tokens.reasoning,
163
- usage.tokens.total,
164
- ]);
165
- groups.set(signature, [
166
- ...(groups.get(signature) ?? []),
167
- { run, usage, base_segment_key: baseSegmentKey },
172
+ groups.set(baseSegmentKey, [
173
+ ...(groups.get(baseSegmentKey) ?? []),
174
+ {
175
+ run,
176
+ usage,
177
+ base_segment_key: baseSegmentKey,
178
+ raw_segment_key: normalizedRawSegmentKey(usage.source_segment_key),
179
+ },
168
180
  ]);
169
181
  }
170
182
  }
171
183
  return [...groups.values()]
172
184
  .filter((group) => new Set(group.map(({ run }) => run.started.run_id)).size > 1)
173
185
  .map((group) =>
174
- [...group].sort(
175
- (left, right) =>
186
+ [...group].sort((left, right) =>
187
+ provenanceRank(left.usage) - provenanceRank(right.usage) ||
176
188
  String(left.run.started.occurred_at).localeCompare(
177
189
  String(right.run.started.occurred_at),
178
190
  ) || left.run.started.run_id.localeCompare(right.run.started.run_id),
@@ -180,6 +192,48 @@ export function duplicateUsageAssignments(runs) {
180
192
  );
181
193
  }
182
194
 
195
+ export function isExactDuplicateUsageGroup(group) {
196
+ return new Set(group.map(({ raw_segment_key }) => raw_segment_key)).size === 1;
197
+ }
198
+
199
+ export function duplicateUsageImpact(assignments) {
200
+ const impact = {
201
+ assignments: assignments.length,
202
+ input_tokens: 0,
203
+ output_tokens: 0,
204
+ total_tokens: 0,
205
+ cost_usd: 0,
206
+ cost_brl: 0,
207
+ duration_ms: 0,
208
+ duration_assignments: 0,
209
+ };
210
+ for (const { usage } of assignments) {
211
+ for (const [key, value] of [
212
+ ["input_tokens", usage.tokens?.input],
213
+ ["output_tokens", usage.tokens?.output],
214
+ ["total_tokens", usage.tokens?.total],
215
+ ["cost_usd", usage.cost?.usd],
216
+ ["cost_brl", usage.cost?.brl],
217
+ ]) {
218
+ if (Number.isFinite(value)) impact[key] += value;
219
+ }
220
+ const start = Date.parse(usage.source_started_at ?? "");
221
+ const finish = Date.parse(usage.source_finished_at ?? "");
222
+ if (Number.isFinite(start) && Number.isFinite(finish) && finish >= start) {
223
+ impact.duration_ms += finish - start;
224
+ impact.duration_assignments += 1;
225
+ }
226
+ }
227
+ return impact;
228
+ }
229
+
230
+ function provenanceRank(usage) {
231
+ const source = usage.classification_source ?? "";
232
+ if (source === "current_context" || source.startsWith("exact_")) return 0;
233
+ if (usage.activity_kind !== "retrospective_local_reconciliation") return 1;
234
+ return source === "legacy_inferred" ? 2 : 1;
235
+ }
236
+
183
237
  export function exactCompletedSegment(started, segments) {
184
238
  if (!started?.client_turn_id) return { segment: null, ambiguous: false };
185
239
  const runStartedAt = Date.parse(started.occurred_at ?? "");
@@ -198,7 +252,13 @@ export function exactCompletedSegment(started, segments) {
198
252
  };
199
253
  }
200
254
 
201
- export function exactRemeasurementSegment(started, sourceSegmentKey, segments) {
255
+ export function exactRemeasurementSegment(
256
+ started,
257
+ sourceSegmentKey,
258
+ segments,
259
+ sourceOccurredAt = null,
260
+ sourceTokens = null,
261
+ ) {
202
262
  const turnMatch = exactCompletedSegment(started, segments);
203
263
  if (turnMatch.segment !== null || turnMatch.ambiguous) return turnMatch;
204
264
  if (typeof sourceSegmentKey !== "string") return turnMatch;
@@ -207,9 +267,50 @@ export function exactRemeasurementSegment(started, sourceSegmentKey, segments) {
207
267
  segment.finished_at !== null &&
208
268
  canonicalSegmentKey(segment.key) === canonicalSegmentKey(sourceSegmentKey),
209
269
  );
270
+ if (matches.length === 1) return { segment: matches[0], ambiguous: false };
271
+
272
+ const sourceFinishedAt = Date.parse(sourceOccurredAt ?? "");
273
+ const sourceFile = canonicalSegmentKey(sourceSegmentKey).replace(/#\d+$/, "");
274
+ const timeMatches = Number.isFinite(sourceFinishedAt)
275
+ ? segments.filter(
276
+ (segment) =>
277
+ segment.finished_at !== null &&
278
+ Date.parse(segment.finished_at) === sourceFinishedAt &&
279
+ canonicalSegmentKey(segment.key).replace(/#\d+$/, "") === sourceFile,
280
+ )
281
+ : [];
282
+ if (timeMatches.length === 1) return { segment: timeMatches[0], ambiguous: false };
283
+
284
+ const tokenMatches =
285
+ sourceTokens !== null
286
+ ? segments.filter((segment) => {
287
+ if (canonicalSegmentKey(segment.key).replace(/#\d+$/, "") !== sourceFile) return false;
288
+ if (segment.finished_at === null || !Array.isArray(segment.usage)) return false;
289
+ const tokens = aggregate(segment);
290
+ const last = segment.usage.at(-1);
291
+ const lastTokens = last
292
+ ? {
293
+ input: last.input_tokens,
294
+ cached_input: last.cached_input_tokens,
295
+ output: last.output_tokens,
296
+ reasoning: last.reasoning_output_tokens,
297
+ total: last.total_tokens,
298
+ }
299
+ : null;
300
+ const same = (candidate) =>
301
+ candidate !== null &&
302
+ ["input", "cached_input", "output", "reasoning", "total"].every(
303
+ (key) => candidate[key] === sourceTokens[key],
304
+ );
305
+ return same(tokens) || same(lastTokens);
306
+ })
307
+ : [];
210
308
  return {
211
- segment: matches.length === 1 ? matches[0] : null,
212
- ambiguous: matches.length > 1,
309
+ segment: tokenMatches.length === 1 ? tokenMatches[0] : null,
310
+ ambiguous:
311
+ timeMatches.length > 1 ||
312
+ tokenMatches.length > 1 ||
313
+ (timeMatches.length === 0 && tokenMatches.length === 0 && matches.length > 1),
213
314
  };
214
315
  }
215
316
 
@@ -217,11 +318,10 @@ function normalized(path) {
217
318
  return resolve(path).replaceAll("\\", "/").toLowerCase();
218
319
  }
219
320
 
220
- export async function loadSegments(workspace) {
221
- const sessionFiles = await filesUnder(join(homedir(), ".codex", "sessions"), ".jsonl");
321
+ export async function loadSegments(workspace, sessionFiles = null) {
322
+ const files = sessionFiles ?? (await filesUnder(join(homedir(), ".codex", "sessions"), ".jsonl"));
222
323
  const segments = [];
223
- for (const file of sessionFiles) {
224
- const fileSegmentStart = segments.length;
324
+ for (const file of files) {
225
325
  let canonicalSessionMetaSeen = false;
226
326
  let workspaceMatches = false;
227
327
  let sessionId = null;
@@ -245,17 +345,21 @@ export async function loadSegments(workspace) {
245
345
  }
246
346
  const payload = record?.payload && typeof record.payload === "object" ? record.payload : null;
247
347
  if (record.type === "session_meta" && typeof payload?.cwd === "string") {
348
+ const nextSessionId = canonicalSessionId(payload);
349
+ const sameSession = canonicalSessionMetaSeen && nextSessionId === sessionId;
350
+ if (sameSession) {
351
+ workspaceMatches = normalized(payload.cwd) === normalized(workspace);
352
+ continue;
353
+ }
248
354
  if (canonicalSessionMetaSeen) {
249
- segments.splice(fileSegmentStart);
250
355
  current = null;
251
356
  index = 0;
252
357
  latestCumulativeUsage = null;
253
358
  latestIncrementalUsage = null;
254
- continue;
255
359
  }
256
360
  canonicalSessionMetaSeen = true;
257
361
  workspaceMatches = normalized(payload.cwd) === normalized(workspace);
258
- sessionId = canonicalSessionId(payload);
362
+ sessionId = nextSessionId;
259
363
  }
260
364
  if (!workspaceMatches) continue;
261
365
  const settings = payload?.type === "thread_settings_applied" ? payload.thread_settings : null;
@@ -8,13 +8,16 @@ import {
8
8
  canonicalSessionId,
9
9
  cumulativeSnapshotDelta,
10
10
  duplicateUsageAssignments,
11
+ duplicateUsageImpact,
11
12
  exactCompletedSegment,
12
13
  exactRemeasurementSegment,
13
14
  jsonLines,
15
+ isExactDuplicateUsageGroup,
14
16
  pricingFor,
15
17
  recordSequence,
16
18
  recordType,
17
19
  sameTokenSnapshot,
20
+ supersedableUsageBeforeTerminal,
18
21
  usageStatus,
19
22
  usageView,
20
23
  withSequence,
@@ -23,6 +26,20 @@ import {
23
26
  const roots = [];
24
27
  after(async () => Promise.all(roots.map((root) => rm(root, { recursive: true, force: true }))));
25
28
 
29
+ test("sums duplicate assignment impact without inventing duration", () => {
30
+ assert.deepEqual(duplicateUsageImpact([{ usage: { tokens: { input: 2, output: 3, total: 5 }, cost: { usd: 1, brl: 5 }, source_started_at: "2026-01-01T00:00:00Z", source_finished_at: "2026-01-01T00:00:01Z" } }]), { assignments: 1, input_tokens: 2, output_tokens: 3, total_tokens: 5, cost_usd: 1, cost_brl: 5, duration_ms: 1000, duration_assignments: 1 });
31
+ });
32
+
33
+ test("never supersedes usage recorded after run.finished", () => {
34
+ const records = [
35
+ { type: "run.started", sequence: 1 },
36
+ { type: "usage.recorded", sequence: 2, event_id: "before", tokens: { total: null } },
37
+ { type: "run.finished", sequence: 3 },
38
+ { type: "usage.recorded", sequence: 4, event_id: "after", tokens: { total: null } },
39
+ ];
40
+ assert.equal(supersedableUsageBeforeTerminal(records)?.event_id, "before");
41
+ });
42
+
26
43
  test("normalizes compact and object Run records without changing usage totals", () => {
27
44
  const compact = [
28
45
  2,
@@ -193,6 +210,70 @@ test("remeasurement falls back only to the exact persisted source segment key",
193
210
  ),
194
211
  { segment: null, ambiguous: true },
195
212
  );
213
+
214
+ const resumedTarget = {
215
+ ...target,
216
+ key: "c:/users/test/.codex/sessions/2026/07/25/child.jsonl#18",
217
+ finished_at: "2026-07-25T04:15:30.000Z",
218
+ };
219
+ assert.deepEqual(
220
+ exactRemeasurementSegment(
221
+ { client_turn_id: null, occurred_at: "2026-07-25T04:00:00.000Z" },
222
+ "sessions/2026/07/25/child.jsonl#2",
223
+ [target, resumedTarget],
224
+ "2026-07-25T04:15:30.000Z",
225
+ ),
226
+ { segment: resumedTarget, ambiguous: false },
227
+ );
228
+
229
+ const tokenTarget = {
230
+ ...resumedTarget,
231
+ finished_at: "2026-07-25T04:16:00.000Z",
232
+ usage: [
233
+ {
234
+ input_tokens: 90,
235
+ cached_input_tokens: 80,
236
+ output_tokens: 10,
237
+ reasoning_output_tokens: 2,
238
+ total_tokens: 100,
239
+ },
240
+ ],
241
+ };
242
+ assert.deepEqual(
243
+ exactRemeasurementSegment(
244
+ { client_turn_id: null, occurred_at: "2026-07-25T04:00:00.000Z" },
245
+ "sessions/2026/07/25/child.jsonl#2",
246
+ [target, tokenTarget],
247
+ "2026-07-25T04:15:59.000Z",
248
+ { input: 90, cached_input: 80, output: 10, reasoning: 2, total: 100 },
249
+ ),
250
+ { segment: tokenTarget, ambiguous: false },
251
+ );
252
+
253
+ const cumulativeSnapshotTarget = {
254
+ ...tokenTarget,
255
+ key: "c:/users/test/.codex/sessions/2026/07/25/child.jsonl#19",
256
+ usage: [
257
+ tokenTarget.usage[0],
258
+ {
259
+ input_tokens: 40,
260
+ cached_input_tokens: 30,
261
+ output_tokens: 4,
262
+ reasoning_output_tokens: 1,
263
+ total_tokens: 44,
264
+ },
265
+ ],
266
+ };
267
+ assert.deepEqual(
268
+ exactRemeasurementSegment(
269
+ { client_turn_id: null, occurred_at: "2026-07-25T04:00:00.000Z" },
270
+ "sessions/2026/07/25/child.jsonl#2",
271
+ [target, cumulativeSnapshotTarget],
272
+ null,
273
+ { input: 40, cached_input: 30, output: 4, reasoning: 1, total: 44 },
274
+ ),
275
+ { segment: cumulativeSnapshotTarget, ambiguous: false },
276
+ );
196
277
  });
197
278
 
198
279
  test("detects only exact duplicate segment assignments across Runs", () => {
@@ -237,10 +318,11 @@ test("detects only exact duplicate segment assignments across Runs", () => {
237
318
  const groups = duplicateUsageAssignments([duplicate, legitimateDelta, first]);
238
319
 
239
320
  assert.equal(groups.length, 1);
240
- assert.deepEqual(
241
- groups[0].map(({ run: item }) => item.started.run_id),
242
- ["RUN-FIRST", "RUN-DUPLICATE"],
243
- );
321
+ assert.deepEqual(groups[0].map(({ run: item }) => item.started.run_id), [
322
+ "RUN-FIRST",
323
+ "RUN-DUPLICATE",
324
+ "RUN-DELTA",
325
+ ]);
244
326
  assert.equal(groups[0][0].base_segment_key, "sessions/2026/07/17/session.jsonl#1");
245
327
  });
246
328
 
@@ -264,3 +346,39 @@ test("keeps duplicate reconciliation unavailable and protected from backfill", (
264
346
  assert.equal(status.deduplicated, true);
265
347
  assert.deepEqual(status.effective, [correction]);
266
348
  });
349
+
350
+ test("prefers later current-context assignment over earlier legacy assignment", () => {
351
+ const run = (id, occurred_at, client_turn_id, classification_source, total) => ({
352
+ started: { run_id: id, occurred_at, client_turn_id },
353
+ usage: [{ event_id: `${id}:usage`, source_segment_key: "sessions/x.jsonl#1", supersedes_event_id: null, classification_source, tokens: { input: total - 1, output: 1, total } }],
354
+ });
355
+ const [group] = duplicateUsageAssignments([
356
+ run("XCHW", "2026-07-01T00:00:00.000Z", "legacy-turn", "legacy_inferred", 9_278_701),
357
+ run("HF77", "2026-07-01T00:01:00.000Z", "exact-turn", "current_context", 577),
358
+ ]);
359
+ assert.equal(group[0].run.started.run_id, "HF77");
360
+ assert.equal(group[1].run.started.run_id, "XCHW");
361
+ });
362
+
363
+ test("keeps canonical aliases in review instead of making them apply candidates", () => {
364
+ const run = (id, source_segment_key) => ({
365
+ started: { run_id: id, occurred_at: "2026-07-01T00:00:00.000Z" },
366
+ usage: [{
367
+ event_id: `${id}:usage`,
368
+ source_segment_key,
369
+ supersedes_event_id: null,
370
+ tokens: { input: 1, output: 1, total: 2 },
371
+ }],
372
+ });
373
+ const [aliasGroup] = duplicateUsageAssignments([
374
+ run("RUN-A", "sessions/x.jsonl#1@RUN-A"),
375
+ run("RUN-B", "sessions/x.jsonl#1@RUN-B"),
376
+ ]);
377
+ const [exactGroup] = duplicateUsageAssignments([
378
+ run("RUN-C", "sessions/x.jsonl#2"),
379
+ run("RUN-D", "SESSIONS\\x.jsonl#2"),
380
+ ]);
381
+
382
+ assert.equal(isExactDuplicateUsageGroup(aliasGroup), false);
383
+ assert.equal(isExactDuplicateUsageGroup(exactGroup), true);
384
+ });