agentfootprint 9.128.1 → 9.131.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 (603) hide show
  1. package/CAPABILITIES.md +13 -1
  2. package/dist/adapters/llm/AnthropicProvider.js +10 -111
  3. package/dist/adapters/llm/AnthropicProvider.js.map +1 -1
  4. package/dist/adapters/llm/BedrockProvider.js +11 -4
  5. package/dist/adapters/llm/BedrockProvider.js.map +1 -1
  6. package/dist/adapters/llm/InvokeModelGatewayProvider.js +167 -35
  7. package/dist/adapters/llm/InvokeModelGatewayProvider.js.map +1 -1
  8. package/dist/adapters/llm/OpenAIProvider.js +5 -0
  9. package/dist/adapters/llm/OpenAIProvider.js.map +1 -1
  10. package/dist/adapters/llm/anthropicMessagesWire.js +20 -6
  11. package/dist/adapters/llm/anthropicMessagesWire.js.map +1 -1
  12. package/dist/adapters/llm/retryAfter.js +61 -0
  13. package/dist/adapters/llm/retryAfter.js.map +1 -0
  14. package/dist/adapters/types.js.map +1 -1
  15. package/dist/artifacts/datasetResult.js +2 -2
  16. package/dist/artifacts/datasetResult.js.map +1 -1
  17. package/dist/artifacts/index.js +10 -8
  18. package/dist/artifacts/index.js.map +1 -1
  19. package/dist/artifacts/minting.js +2 -2
  20. package/dist/artifacts/minting.js.map +1 -1
  21. package/dist/core/Agent.js +229 -5
  22. package/dist/core/Agent.js.map +1 -1
  23. package/dist/core/agent/AgentBuilder.js +75 -1
  24. package/dist/core/agent/AgentBuilder.js.map +1 -1
  25. package/dist/core/agent/arguments/ask.js +356 -14
  26. package/dist/core/agent/arguments/ask.js.map +1 -1
  27. package/dist/core/agent/arguments/declare.js +260 -45
  28. package/dist/core/agent/arguments/declare.js.map +1 -1
  29. package/dist/core/agent/arguments/dispatch.js +25 -1
  30. package/dist/core/agent/arguments/dispatch.js.map +1 -1
  31. package/dist/core/agent/arguments/resolve.js +239 -6
  32. package/dist/core/agent/arguments/resolve.js.map +1 -1
  33. package/dist/core/agent/arguments/rows.js +37 -2
  34. package/dist/core/agent/arguments/rows.js.map +1 -1
  35. package/dist/core/agent/arguments/serve.js +332 -4
  36. package/dist/core/agent/arguments/serve.js.map +1 -1
  37. package/dist/core/agent/arguments/subflow.js +46 -7
  38. package/dist/core/agent/arguments/subflow.js.map +1 -1
  39. package/dist/core/agent/assessment/assess.js +45 -6
  40. package/dist/core/agent/assessment/assess.js.map +1 -1
  41. package/dist/core/agent/assessment/compose.js +3 -0
  42. package/dist/core/agent/assessment/compose.js.map +1 -1
  43. package/dist/core/agent/assessment/reasons.js +18 -0
  44. package/dist/core/agent/assessment/reasons.js.map +1 -1
  45. package/dist/core/agent/buildAgentChart.js +31 -1
  46. package/dist/core/agent/buildAgentChart.js.map +1 -1
  47. package/dist/core/agent/buildDynamicAgentChart.js +9 -0
  48. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
  49. package/dist/core/agent/coverage/answer.js +24 -7
  50. package/dist/core/agent/coverage/answer.js.map +1 -1
  51. package/dist/core/agent/coverage/period.js +110 -69
  52. package/dist/core/agent/coverage/period.js.map +1 -1
  53. package/dist/core/agent/coverage/timeLimitFacts.js +70 -0
  54. package/dist/core/agent/coverage/timeLimitFacts.js.map +1 -0
  55. package/dist/core/agent/coverage/timeLimits.js +72 -0
  56. package/dist/core/agent/coverage/timeLimits.js.map +1 -0
  57. package/dist/core/agent/evidence/evidenceIndex.js +48 -7
  58. package/dist/core/agent/evidence/evidenceIndex.js.map +1 -1
  59. package/dist/core/agent/evidence/gate.js +9 -4
  60. package/dist/core/agent/evidence/gate.js.map +1 -1
  61. package/dist/core/agent/evidence/normalize.js +1 -105
  62. package/dist/core/agent/evidence/normalize.js.map +1 -1
  63. package/dist/core/agent/findings/ledger.js +14 -0
  64. package/dist/core/agent/findings/ledger.js.map +1 -1
  65. package/dist/core/agent/findings/types.js.map +1 -1
  66. package/dist/core/agent/honesty/mounts.js +105 -4
  67. package/dist/core/agent/honesty/mounts.js.map +1 -1
  68. package/dist/core/agent/results/subflow.js +43 -11
  69. package/dist/core/agent/results/subflow.js.map +1 -1
  70. package/dist/core/agent/stages/argumentAsk.js +85 -6
  71. package/dist/core/agent/stages/argumentAsk.js.map +1 -1
  72. package/dist/core/agent/stages/callLLM.js +16 -0
  73. package/dist/core/agent/stages/callLLM.js.map +1 -1
  74. package/dist/core/agent/stages/prepareFinal.js +61 -8
  75. package/dist/core/agent/stages/prepareFinal.js.map +1 -1
  76. package/dist/core/agent/stages/route.js +64 -6
  77. package/dist/core/agent/stages/route.js.map +1 -1
  78. package/dist/core/agent/stages/seed.js +29 -6
  79. package/dist/core/agent/stages/seed.js.map +1 -1
  80. package/dist/core/agent/stages/timeLayer.js +201 -0
  81. package/dist/core/agent/stages/timeLayer.js.map +1 -0
  82. package/dist/core/agent/stages/timeLineage.js +61 -0
  83. package/dist/core/agent/stages/timeLineage.js.map +1 -0
  84. package/dist/core/agent/stages/toolCalls.js +70 -0
  85. package/dist/core/agent/stages/toolCalls.js.map +1 -1
  86. package/dist/core/inputRequest.js +132 -5
  87. package/dist/core/inputRequest.js.map +1 -1
  88. package/dist/core/messageFrom.js +5 -2
  89. package/dist/core/messageFrom.js.map +1 -1
  90. package/dist/core/runCheckpoint.js +17 -2
  91. package/dist/core/runCheckpoint.js.map +1 -1
  92. package/dist/core/slots/buildToolsSlot.js +30 -2
  93. package/dist/core/slots/buildToolsSlot.js.map +1 -1
  94. package/dist/core/time/ask.js +239 -0
  95. package/dist/core/time/ask.js.map +1 -0
  96. package/dist/core/time/axis.js +469 -0
  97. package/dist/core/time/axis.js.map +1 -0
  98. package/dist/core/time/bind.js +235 -0
  99. package/dist/core/time/bind.js.map +1 -0
  100. package/dist/core/time/check.js +261 -0
  101. package/dist/core/time/check.js.map +1 -0
  102. package/dist/core/time/checkRecord.js +97 -0
  103. package/dist/core/time/checkRecord.js.map +1 -0
  104. package/dist/core/time/clock.js +260 -0
  105. package/dist/core/time/clock.js.map +1 -0
  106. package/dist/core/time/convert.js +634 -0
  107. package/dist/core/time/convert.js.map +1 -0
  108. package/dist/core/time/drift.js +96 -0
  109. package/dist/core/time/drift.js.map +1 -0
  110. package/dist/core/time/duration.js +125 -0
  111. package/dist/core/time/duration.js.map +1 -0
  112. package/dist/core/time/forms.js +273 -0
  113. package/dist/core/time/forms.js.map +1 -0
  114. package/dist/core/time/instant.js +141 -0
  115. package/dist/core/time/instant.js.map +1 -0
  116. package/dist/core/time/periodForm.js +392 -0
  117. package/dist/core/time/periodForm.js.map +1 -0
  118. package/dist/core/time/present.js +312 -0
  119. package/dist/core/time/present.js.map +1 -0
  120. package/dist/core/time/range.js +267 -0
  121. package/dist/core/time/range.js.map +1 -0
  122. package/dist/core/time/reader.js +209 -0
  123. package/dist/core/time/reader.js.map +1 -0
  124. package/dist/core/time/readers/english.js +576 -0
  125. package/dist/core/time/readers/english.js.map +1 -0
  126. package/dist/core/time/readingAsk.js +94 -0
  127. package/dist/core/time/readingAsk.js.map +1 -0
  128. package/dist/core/time/resolve.js +694 -0
  129. package/dist/core/time/resolve.js.map +1 -0
  130. package/dist/core/time/resolveRecord.js +164 -0
  131. package/dist/core/time/resolveRecord.js.map +1 -0
  132. package/dist/core/time/rows.js +412 -0
  133. package/dist/core/time/rows.js.map +1 -0
  134. package/dist/core/time/rowsBuild.js +193 -0
  135. package/dist/core/time/rowsBuild.js.map +1 -0
  136. package/dist/core/time/textForms.js +133 -0
  137. package/dist/core/time/textForms.js.map +1 -0
  138. package/dist/core/time/windows.js +172 -0
  139. package/dist/core/time/windows.js.map +1 -0
  140. package/dist/core/time/wire.js +86 -0
  141. package/dist/core/time/wire.js.map +1 -0
  142. package/dist/core/time/zone.js +253 -0
  143. package/dist/core/time/zone.js.map +1 -0
  144. package/dist/core/tools.js.map +1 -1
  145. package/dist/esm/adapters/llm/AnthropicProvider.js +8 -109
  146. package/dist/esm/adapters/llm/AnthropicProvider.js.map +1 -1
  147. package/dist/esm/adapters/llm/BedrockProvider.js +11 -4
  148. package/dist/esm/adapters/llm/BedrockProvider.js.map +1 -1
  149. package/dist/esm/adapters/llm/InvokeModelGatewayProvider.d.ts +38 -4
  150. package/dist/esm/adapters/llm/InvokeModelGatewayProvider.js +167 -35
  151. package/dist/esm/adapters/llm/InvokeModelGatewayProvider.js.map +1 -1
  152. package/dist/esm/adapters/llm/OpenAIProvider.js +5 -0
  153. package/dist/esm/adapters/llm/OpenAIProvider.js.map +1 -1
  154. package/dist/esm/adapters/llm/anthropicMessagesWire.d.ts +6 -1
  155. package/dist/esm/adapters/llm/anthropicMessagesWire.js +20 -6
  156. package/dist/esm/adapters/llm/anthropicMessagesWire.js.map +1 -1
  157. package/dist/esm/adapters/llm/retryAfter.d.ts +27 -0
  158. package/dist/esm/adapters/llm/retryAfter.js +56 -0
  159. package/dist/esm/adapters/llm/retryAfter.js.map +1 -0
  160. package/dist/esm/adapters/types.d.ts +9 -0
  161. package/dist/esm/adapters/types.js.map +1 -1
  162. package/dist/esm/artifacts/datasetResult.js +1 -1
  163. package/dist/esm/artifacts/datasetResult.js.map +1 -1
  164. package/dist/esm/artifacts/index.d.ts +1 -1
  165. package/dist/esm/artifacts/index.js +3 -2
  166. package/dist/esm/artifacts/index.js.map +1 -1
  167. package/dist/esm/artifacts/minting.js +1 -1
  168. package/dist/esm/artifacts/minting.js.map +1 -1
  169. package/dist/esm/artifacts/types.d.ts +2 -2
  170. package/dist/esm/core/Agent.d.ts +64 -0
  171. package/dist/esm/core/Agent.js +230 -6
  172. package/dist/esm/core/Agent.js.map +1 -1
  173. package/dist/esm/core/agent/AgentBuilder.d.ts +60 -0
  174. package/dist/esm/core/agent/AgentBuilder.js +75 -1
  175. package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
  176. package/dist/esm/core/agent/arguments/ask.d.ts +88 -5
  177. package/dist/esm/core/agent/arguments/ask.js +349 -8
  178. package/dist/esm/core/agent/arguments/ask.js.map +1 -1
  179. package/dist/esm/core/agent/arguments/checks.d.ts +1 -1
  180. package/dist/esm/core/agent/arguments/declare.d.ts +76 -15
  181. package/dist/esm/core/agent/arguments/declare.js +255 -44
  182. package/dist/esm/core/agent/arguments/declare.js.map +1 -1
  183. package/dist/esm/core/agent/arguments/dispatch.js +25 -1
  184. package/dist/esm/core/agent/arguments/dispatch.js.map +1 -1
  185. package/dist/esm/core/agent/arguments/resolve.d.ts +77 -7
  186. package/dist/esm/core/agent/arguments/resolve.js +239 -8
  187. package/dist/esm/core/agent/arguments/resolve.js.map +1 -1
  188. package/dist/esm/core/agent/arguments/rows.d.ts +31 -2
  189. package/dist/esm/core/agent/arguments/rows.js +35 -1
  190. package/dist/esm/core/agent/arguments/rows.js.map +1 -1
  191. package/dist/esm/core/agent/arguments/serve.d.ts +133 -4
  192. package/dist/esm/core/agent/arguments/serve.js +328 -4
  193. package/dist/esm/core/agent/arguments/serve.js.map +1 -1
  194. package/dist/esm/core/agent/arguments/subflow.d.ts +28 -0
  195. package/dist/esm/core/agent/arguments/subflow.js +47 -8
  196. package/dist/esm/core/agent/arguments/subflow.js.map +1 -1
  197. package/dist/esm/core/agent/assessment/assess.js +45 -6
  198. package/dist/esm/core/agent/assessment/assess.js.map +1 -1
  199. package/dist/esm/core/agent/assessment/compose.js +3 -0
  200. package/dist/esm/core/agent/assessment/compose.js.map +1 -1
  201. package/dist/esm/core/agent/assessment/reasons.js +18 -0
  202. package/dist/esm/core/agent/assessment/reasons.js.map +1 -1
  203. package/dist/esm/core/agent/assessment/types.d.ts +15 -1
  204. package/dist/esm/core/agent/buildAgentChart.d.ts +41 -0
  205. package/dist/esm/core/agent/buildAgentChart.js +28 -0
  206. package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
  207. package/dist/esm/core/agent/buildDynamicAgentChart.d.ts +1 -1
  208. package/dist/esm/core/agent/buildDynamicAgentChart.js +9 -0
  209. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
  210. package/dist/esm/core/agent/coverage/answer.d.ts +20 -1
  211. package/dist/esm/core/agent/coverage/answer.js +23 -6
  212. package/dist/esm/core/agent/coverage/answer.js.map +1 -1
  213. package/dist/esm/core/agent/coverage/period.d.ts +49 -3
  214. package/dist/esm/core/agent/coverage/period.js +107 -68
  215. package/dist/esm/core/agent/coverage/period.js.map +1 -1
  216. package/dist/esm/core/agent/coverage/timeLimitFacts.d.ts +56 -0
  217. package/dist/esm/core/agent/coverage/timeLimitFacts.js +65 -0
  218. package/dist/esm/core/agent/coverage/timeLimitFacts.js.map +1 -0
  219. package/dist/esm/core/agent/coverage/timeLimits.d.ts +46 -0
  220. package/dist/esm/core/agent/coverage/timeLimits.js +67 -0
  221. package/dist/esm/core/agent/coverage/timeLimits.js.map +1 -0
  222. package/dist/esm/core/agent/evidence/evidenceIndex.d.ts +25 -2
  223. package/dist/esm/core/agent/evidence/evidenceIndex.js +47 -7
  224. package/dist/esm/core/agent/evidence/evidenceIndex.js.map +1 -1
  225. package/dist/esm/core/agent/evidence/gate.d.ts +7 -0
  226. package/dist/esm/core/agent/evidence/gate.js +9 -4
  227. package/dist/esm/core/agent/evidence/gate.js.map +1 -1
  228. package/dist/esm/core/agent/evidence/normalize.d.ts +0 -34
  229. package/dist/esm/core/agent/evidence/normalize.js +0 -103
  230. package/dist/esm/core/agent/evidence/normalize.js.map +1 -1
  231. package/dist/esm/core/agent/evidence/types.d.ts +12 -1
  232. package/dist/esm/core/agent/findings/ledger.js +14 -0
  233. package/dist/esm/core/agent/findings/ledger.js.map +1 -1
  234. package/dist/esm/core/agent/findings/types.d.ts +2 -1
  235. package/dist/esm/core/agent/findings/types.js.map +1 -1
  236. package/dist/esm/core/agent/honesty/mounts.d.ts +25 -0
  237. package/dist/esm/core/agent/honesty/mounts.js +104 -4
  238. package/dist/esm/core/agent/honesty/mounts.js.map +1 -1
  239. package/dist/esm/core/agent/results/subflow.d.ts +34 -2
  240. package/dist/esm/core/agent/results/subflow.js +43 -11
  241. package/dist/esm/core/agent/results/subflow.js.map +1 -1
  242. package/dist/esm/core/agent/stages/argumentAsk.d.ts +19 -0
  243. package/dist/esm/core/agent/stages/argumentAsk.js +85 -6
  244. package/dist/esm/core/agent/stages/argumentAsk.js.map +1 -1
  245. package/dist/esm/core/agent/stages/callLLM.d.ts +6 -0
  246. package/dist/esm/core/agent/stages/callLLM.js +16 -0
  247. package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
  248. package/dist/esm/core/agent/stages/prepareFinal.d.ts +13 -1
  249. package/dist/esm/core/agent/stages/prepareFinal.js +59 -7
  250. package/dist/esm/core/agent/stages/prepareFinal.js.map +1 -1
  251. package/dist/esm/core/agent/stages/route.d.ts +29 -1
  252. package/dist/esm/core/agent/stages/route.js +64 -7
  253. package/dist/esm/core/agent/stages/route.js.map +1 -1
  254. package/dist/esm/core/agent/stages/seed.d.ts +23 -0
  255. package/dist/esm/core/agent/stages/seed.js +29 -6
  256. package/dist/esm/core/agent/stages/seed.js.map +1 -1
  257. package/dist/esm/core/agent/stages/timeLayer.d.ts +94 -0
  258. package/dist/esm/core/agent/stages/timeLayer.js +193 -0
  259. package/dist/esm/core/agent/stages/timeLayer.js.map +1 -0
  260. package/dist/esm/core/agent/stages/timeLineage.d.ts +31 -0
  261. package/dist/esm/core/agent/stages/timeLineage.js +57 -0
  262. package/dist/esm/core/agent/stages/timeLineage.js.map +1 -0
  263. package/dist/esm/core/agent/stages/toolCalls.d.ts +32 -0
  264. package/dist/esm/core/agent/stages/toolCalls.js +70 -0
  265. package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
  266. package/dist/esm/core/agent/types.d.ts +37 -0
  267. package/dist/esm/core/inputRequest.d.ts +50 -6
  268. package/dist/esm/core/inputRequest.js +132 -5
  269. package/dist/esm/core/inputRequest.js.map +1 -1
  270. package/dist/esm/core/messageFrom.d.ts +5 -2
  271. package/dist/esm/core/messageFrom.js +5 -2
  272. package/dist/esm/core/messageFrom.js.map +1 -1
  273. package/dist/esm/core/runCheckpoint.js +17 -2
  274. package/dist/esm/core/runCheckpoint.js.map +1 -1
  275. package/dist/esm/core/slots/buildToolsSlot.d.ts +29 -0
  276. package/dist/esm/core/slots/buildToolsSlot.js +30 -2
  277. package/dist/esm/core/slots/buildToolsSlot.js.map +1 -1
  278. package/dist/esm/core/time/ask.d.ts +126 -0
  279. package/dist/esm/core/time/ask.js +230 -0
  280. package/dist/esm/core/time/ask.js.map +1 -0
  281. package/dist/esm/core/time/axis.d.ts +224 -0
  282. package/dist/esm/core/time/axis.js +462 -0
  283. package/dist/esm/core/time/axis.js.map +1 -0
  284. package/dist/esm/core/time/bind.d.ts +143 -0
  285. package/dist/esm/core/time/bind.js +227 -0
  286. package/dist/esm/core/time/bind.js.map +1 -0
  287. package/dist/esm/core/time/check.d.ts +113 -0
  288. package/dist/esm/core/time/check.js +252 -0
  289. package/dist/esm/core/time/check.js.map +1 -0
  290. package/dist/esm/core/time/checkRecord.d.ts +74 -0
  291. package/dist/esm/core/time/checkRecord.js +90 -0
  292. package/dist/esm/core/time/checkRecord.js.map +1 -0
  293. package/dist/esm/core/time/clock.d.ts +183 -0
  294. package/dist/esm/core/time/clock.js +252 -0
  295. package/dist/esm/core/time/clock.js.map +1 -0
  296. package/dist/esm/core/time/convert.d.ts +178 -0
  297. package/dist/esm/core/time/convert.js +609 -0
  298. package/dist/esm/core/time/convert.js.map +1 -0
  299. package/dist/esm/core/time/drift.d.ts +85 -0
  300. package/dist/esm/core/time/drift.js +91 -0
  301. package/dist/esm/core/time/drift.js.map +1 -0
  302. package/dist/esm/core/time/duration.d.ts +71 -0
  303. package/dist/esm/core/time/duration.js +117 -0
  304. package/dist/esm/core/time/duration.js.map +1 -0
  305. package/dist/esm/core/time/forms.d.ts +84 -0
  306. package/dist/esm/core/time/forms.js +268 -0
  307. package/dist/esm/core/time/forms.js.map +1 -0
  308. package/dist/esm/core/time/instant.d.ts +75 -0
  309. package/dist/esm/core/time/instant.js +131 -0
  310. package/dist/esm/core/time/instant.js.map +1 -0
  311. package/dist/esm/core/time/periodForm.d.ts +184 -0
  312. package/dist/esm/core/time/periodForm.js +376 -0
  313. package/dist/esm/core/time/periodForm.js.map +1 -0
  314. package/dist/esm/core/time/present.d.ts +107 -0
  315. package/dist/esm/core/time/present.js +305 -0
  316. package/dist/esm/core/time/present.js.map +1 -0
  317. package/dist/esm/core/time/range.d.ts +127 -0
  318. package/dist/esm/core/time/range.js +249 -0
  319. package/dist/esm/core/time/range.js.map +1 -0
  320. package/dist/esm/core/time/reader.d.ts +162 -0
  321. package/dist/esm/core/time/reader.js +203 -0
  322. package/dist/esm/core/time/reader.js.map +1 -0
  323. package/dist/esm/core/time/readers/english.d.ts +99 -0
  324. package/dist/esm/core/time/readers/english.js +572 -0
  325. package/dist/esm/core/time/readers/english.js.map +1 -0
  326. package/dist/esm/core/time/readingAsk.d.ts +45 -0
  327. package/dist/esm/core/time/readingAsk.js +90 -0
  328. package/dist/esm/core/time/readingAsk.js.map +1 -0
  329. package/dist/esm/core/time/resolve.d.ts +103 -0
  330. package/dist/esm/core/time/resolve.js +684 -0
  331. package/dist/esm/core/time/resolve.js.map +1 -0
  332. package/dist/esm/core/time/resolveRecord.d.ts +160 -0
  333. package/dist/esm/core/time/resolveRecord.js +158 -0
  334. package/dist/esm/core/time/resolveRecord.js.map +1 -0
  335. package/dist/esm/core/time/rows.d.ts +297 -0
  336. package/dist/esm/core/time/rows.js +397 -0
  337. package/dist/esm/core/time/rows.js.map +1 -0
  338. package/dist/esm/core/time/rowsBuild.d.ts +82 -0
  339. package/dist/esm/core/time/rowsBuild.js +185 -0
  340. package/dist/esm/core/time/rowsBuild.js.map +1 -0
  341. package/dist/esm/core/time/textForms.d.ts +53 -0
  342. package/dist/esm/core/time/textForms.js +126 -0
  343. package/dist/esm/core/time/textForms.js.map +1 -0
  344. package/dist/esm/core/time/windows.d.ts +113 -0
  345. package/dist/esm/core/time/windows.js +166 -0
  346. package/dist/esm/core/time/windows.js.map +1 -0
  347. package/dist/esm/core/time/wire.d.ts +63 -0
  348. package/dist/esm/core/time/wire.js +81 -0
  349. package/dist/esm/core/time/wire.js.map +1 -0
  350. package/dist/esm/core/time/zone.d.ts +115 -0
  351. package/dist/esm/core/time/zone.js +242 -0
  352. package/dist/esm/core/time/zone.js.map +1 -0
  353. package/dist/esm/core/tools.d.ts +26 -4
  354. package/dist/esm/core/tools.js.map +1 -1
  355. package/dist/esm/events/payloads.d.ts +16 -2
  356. package/dist/esm/index.d.ts +13 -1
  357. package/dist/esm/index.js +6 -1
  358. package/dist/esm/index.js.map +1 -1
  359. package/dist/esm/lib/answer-account/facts/howSure.js +7 -0
  360. package/dist/esm/lib/answer-account/facts/howSure.js.map +1 -1
  361. package/dist/esm/lib/answer-account/templates.d.ts +3 -0
  362. package/dist/esm/lib/answer-account/templates.js +4 -0
  363. package/dist/esm/lib/answer-account/templates.js.map +1 -1
  364. package/dist/esm/lib/mcp/elicitation.d.ts +84 -0
  365. package/dist/esm/lib/mcp/elicitation.js +181 -0
  366. package/dist/esm/lib/mcp/elicitation.js.map +1 -0
  367. package/dist/esm/lib/mcp/mcpClient.js +9 -3
  368. package/dist/esm/lib/mcp/mcpClient.js.map +1 -1
  369. package/dist/esm/lib/mcp/mcpServe.js +6 -2
  370. package/dist/esm/lib/mcp/mcpServe.js.map +1 -1
  371. package/dist/esm/lib/mcp/mockMcpClient.d.ts +9 -1
  372. package/dist/esm/lib/mcp/mockMcpClient.js +5 -3
  373. package/dist/esm/lib/mcp/mockMcpClient.js.map +1 -1
  374. package/dist/esm/lib/mcp/toolExtras.d.ts +21 -2
  375. package/dist/esm/lib/mcp/toolExtras.js +22 -0
  376. package/dist/esm/lib/mcp/toolExtras.js.map +1 -1
  377. package/dist/esm/lib/mcp/types.d.ts +8 -0
  378. package/dist/esm/lib/time-travel/receipt.d.ts +1 -1
  379. package/dist/esm/lib/time-travel/servedView.d.ts +1 -1
  380. package/dist/esm/lib/time-travel/servedView.js +9 -0
  381. package/dist/esm/lib/time-travel/servedView.js.map +1 -1
  382. package/dist/esm/locales/index.d.ts +6 -0
  383. package/dist/esm/locales/index.js +6 -0
  384. package/dist/esm/locales/index.js.map +1 -1
  385. package/dist/esm/locales/timeAsk.d.ts +29 -0
  386. package/dist/esm/locales/timeAsk.js +44 -0
  387. package/dist/esm/locales/timeAsk.js.map +1 -0
  388. package/dist/esm/recorders/core/resilienceHooks.js +1 -0
  389. package/dist/esm/recorders/core/resilienceHooks.js.map +1 -1
  390. package/dist/esm/resilience/statedWait.d.ts +22 -0
  391. package/dist/esm/resilience/statedWait.js +35 -0
  392. package/dist/esm/resilience/statedWait.js.map +1 -0
  393. package/dist/esm/resilience/withRetry.d.ts +13 -2
  394. package/dist/esm/resilience/withRetry.js +16 -1
  395. package/dist/esm/resilience/withRetry.js.map +1 -1
  396. package/dist/index.js +11 -1
  397. package/dist/index.js.map +1 -1
  398. package/dist/lib/answer-account/facts/howSure.js +7 -0
  399. package/dist/lib/answer-account/facts/howSure.js.map +1 -1
  400. package/dist/lib/answer-account/templates.js +4 -0
  401. package/dist/lib/answer-account/templates.js.map +1 -1
  402. package/dist/lib/mcp/elicitation.js +186 -0
  403. package/dist/lib/mcp/elicitation.js.map +1 -0
  404. package/dist/lib/mcp/mcpClient.js +8 -2
  405. package/dist/lib/mcp/mcpClient.js.map +1 -1
  406. package/dist/lib/mcp/mcpServe.js +5 -1
  407. package/dist/lib/mcp/mcpServe.js.map +1 -1
  408. package/dist/lib/mcp/mockMcpClient.js +4 -2
  409. package/dist/lib/mcp/mockMcpClient.js.map +1 -1
  410. package/dist/lib/mcp/toolExtras.js +25 -1
  411. package/dist/lib/mcp/toolExtras.js.map +1 -1
  412. package/dist/lib/time-travel/servedView.js +9 -0
  413. package/dist/lib/time-travel/servedView.js.map +1 -1
  414. package/dist/locales/index.js +8 -1
  415. package/dist/locales/index.js.map +1 -1
  416. package/dist/locales/timeAsk.js +47 -0
  417. package/dist/locales/timeAsk.js.map +1 -0
  418. package/dist/recorders/core/resilienceHooks.js +1 -0
  419. package/dist/recorders/core/resilienceHooks.js.map +1 -1
  420. package/dist/resilience/statedWait.js +39 -0
  421. package/dist/resilience/statedWait.js.map +1 -0
  422. package/dist/resilience/withRetry.js +16 -1
  423. package/dist/resilience/withRetry.js.map +1 -1
  424. package/dist/types/adapters/llm/AnthropicProvider.d.ts.map +1 -1
  425. package/dist/types/adapters/llm/BedrockProvider.d.ts.map +1 -1
  426. package/dist/types/adapters/llm/InvokeModelGatewayProvider.d.ts +38 -4
  427. package/dist/types/adapters/llm/InvokeModelGatewayProvider.d.ts.map +1 -1
  428. package/dist/types/adapters/llm/OpenAIProvider.d.ts.map +1 -1
  429. package/dist/types/adapters/llm/anthropicMessagesWire.d.ts +6 -1
  430. package/dist/types/adapters/llm/anthropicMessagesWire.d.ts.map +1 -1
  431. package/dist/types/adapters/llm/retryAfter.d.ts +28 -0
  432. package/dist/types/adapters/llm/retryAfter.d.ts.map +1 -0
  433. package/dist/types/adapters/types.d.ts +9 -0
  434. package/dist/types/adapters/types.d.ts.map +1 -1
  435. package/dist/types/artifacts/index.d.ts +1 -1
  436. package/dist/types/artifacts/index.d.ts.map +1 -1
  437. package/dist/types/artifacts/types.d.ts +2 -2
  438. package/dist/types/artifacts/types.d.ts.map +1 -1
  439. package/dist/types/core/Agent.d.ts +64 -0
  440. package/dist/types/core/Agent.d.ts.map +1 -1
  441. package/dist/types/core/agent/AgentBuilder.d.ts +60 -0
  442. package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
  443. package/dist/types/core/agent/arguments/ask.d.ts +88 -5
  444. package/dist/types/core/agent/arguments/ask.d.ts.map +1 -1
  445. package/dist/types/core/agent/arguments/checks.d.ts +1 -1
  446. package/dist/types/core/agent/arguments/checks.d.ts.map +1 -1
  447. package/dist/types/core/agent/arguments/declare.d.ts +76 -15
  448. package/dist/types/core/agent/arguments/declare.d.ts.map +1 -1
  449. package/dist/types/core/agent/arguments/dispatch.d.ts.map +1 -1
  450. package/dist/types/core/agent/arguments/resolve.d.ts +77 -7
  451. package/dist/types/core/agent/arguments/resolve.d.ts.map +1 -1
  452. package/dist/types/core/agent/arguments/rows.d.ts +31 -2
  453. package/dist/types/core/agent/arguments/rows.d.ts.map +1 -1
  454. package/dist/types/core/agent/arguments/serve.d.ts +133 -4
  455. package/dist/types/core/agent/arguments/serve.d.ts.map +1 -1
  456. package/dist/types/core/agent/arguments/subflow.d.ts +28 -0
  457. package/dist/types/core/agent/arguments/subflow.d.ts.map +1 -1
  458. package/dist/types/core/agent/assessment/assess.d.ts.map +1 -1
  459. package/dist/types/core/agent/assessment/compose.d.ts.map +1 -1
  460. package/dist/types/core/agent/assessment/reasons.d.ts.map +1 -1
  461. package/dist/types/core/agent/assessment/types.d.ts +15 -1
  462. package/dist/types/core/agent/assessment/types.d.ts.map +1 -1
  463. package/dist/types/core/agent/buildAgentChart.d.ts +41 -0
  464. package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
  465. package/dist/types/core/agent/buildDynamicAgentChart.d.ts +1 -1
  466. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
  467. package/dist/types/core/agent/coverage/answer.d.ts +20 -1
  468. package/dist/types/core/agent/coverage/answer.d.ts.map +1 -1
  469. package/dist/types/core/agent/coverage/period.d.ts +49 -3
  470. package/dist/types/core/agent/coverage/period.d.ts.map +1 -1
  471. package/dist/types/core/agent/coverage/timeLimitFacts.d.ts +57 -0
  472. package/dist/types/core/agent/coverage/timeLimitFacts.d.ts.map +1 -0
  473. package/dist/types/core/agent/coverage/timeLimits.d.ts +47 -0
  474. package/dist/types/core/agent/coverage/timeLimits.d.ts.map +1 -0
  475. package/dist/types/core/agent/evidence/evidenceIndex.d.ts +25 -2
  476. package/dist/types/core/agent/evidence/evidenceIndex.d.ts.map +1 -1
  477. package/dist/types/core/agent/evidence/gate.d.ts +7 -0
  478. package/dist/types/core/agent/evidence/gate.d.ts.map +1 -1
  479. package/dist/types/core/agent/evidence/normalize.d.ts +0 -34
  480. package/dist/types/core/agent/evidence/normalize.d.ts.map +1 -1
  481. package/dist/types/core/agent/evidence/types.d.ts +12 -1
  482. package/dist/types/core/agent/evidence/types.d.ts.map +1 -1
  483. package/dist/types/core/agent/findings/ledger.d.ts.map +1 -1
  484. package/dist/types/core/agent/findings/types.d.ts +2 -1
  485. package/dist/types/core/agent/findings/types.d.ts.map +1 -1
  486. package/dist/types/core/agent/honesty/mounts.d.ts +25 -0
  487. package/dist/types/core/agent/honesty/mounts.d.ts.map +1 -1
  488. package/dist/types/core/agent/results/subflow.d.ts +34 -2
  489. package/dist/types/core/agent/results/subflow.d.ts.map +1 -1
  490. package/dist/types/core/agent/stages/argumentAsk.d.ts +19 -0
  491. package/dist/types/core/agent/stages/argumentAsk.d.ts.map +1 -1
  492. package/dist/types/core/agent/stages/callLLM.d.ts +6 -0
  493. package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
  494. package/dist/types/core/agent/stages/prepareFinal.d.ts +13 -1
  495. package/dist/types/core/agent/stages/prepareFinal.d.ts.map +1 -1
  496. package/dist/types/core/agent/stages/route.d.ts +29 -1
  497. package/dist/types/core/agent/stages/route.d.ts.map +1 -1
  498. package/dist/types/core/agent/stages/seed.d.ts +23 -0
  499. package/dist/types/core/agent/stages/seed.d.ts.map +1 -1
  500. package/dist/types/core/agent/stages/timeLayer.d.ts +95 -0
  501. package/dist/types/core/agent/stages/timeLayer.d.ts.map +1 -0
  502. package/dist/types/core/agent/stages/timeLineage.d.ts +32 -0
  503. package/dist/types/core/agent/stages/timeLineage.d.ts.map +1 -0
  504. package/dist/types/core/agent/stages/toolCalls.d.ts +32 -0
  505. package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
  506. package/dist/types/core/agent/types.d.ts +37 -0
  507. package/dist/types/core/agent/types.d.ts.map +1 -1
  508. package/dist/types/core/inputRequest.d.ts +50 -6
  509. package/dist/types/core/inputRequest.d.ts.map +1 -1
  510. package/dist/types/core/messageFrom.d.ts +5 -2
  511. package/dist/types/core/messageFrom.d.ts.map +1 -1
  512. package/dist/types/core/runCheckpoint.d.ts.map +1 -1
  513. package/dist/types/core/slots/buildToolsSlot.d.ts +29 -0
  514. package/dist/types/core/slots/buildToolsSlot.d.ts.map +1 -1
  515. package/dist/types/core/time/ask.d.ts +127 -0
  516. package/dist/types/core/time/ask.d.ts.map +1 -0
  517. package/dist/types/core/time/axis.d.ts +225 -0
  518. package/dist/types/core/time/axis.d.ts.map +1 -0
  519. package/dist/types/core/time/bind.d.ts +144 -0
  520. package/dist/types/core/time/bind.d.ts.map +1 -0
  521. package/dist/types/core/time/check.d.ts +114 -0
  522. package/dist/types/core/time/check.d.ts.map +1 -0
  523. package/dist/types/core/time/checkRecord.d.ts +75 -0
  524. package/dist/types/core/time/checkRecord.d.ts.map +1 -0
  525. package/dist/types/core/time/clock.d.ts +184 -0
  526. package/dist/types/core/time/clock.d.ts.map +1 -0
  527. package/dist/types/core/time/convert.d.ts +179 -0
  528. package/dist/types/core/time/convert.d.ts.map +1 -0
  529. package/dist/types/core/time/drift.d.ts +86 -0
  530. package/dist/types/core/time/drift.d.ts.map +1 -0
  531. package/dist/types/core/time/duration.d.ts +72 -0
  532. package/dist/types/core/time/duration.d.ts.map +1 -0
  533. package/dist/types/core/time/forms.d.ts +85 -0
  534. package/dist/types/core/time/forms.d.ts.map +1 -0
  535. package/dist/types/core/time/instant.d.ts +76 -0
  536. package/dist/types/core/time/instant.d.ts.map +1 -0
  537. package/dist/types/core/time/periodForm.d.ts +185 -0
  538. package/dist/types/core/time/periodForm.d.ts.map +1 -0
  539. package/dist/types/core/time/present.d.ts +108 -0
  540. package/dist/types/core/time/present.d.ts.map +1 -0
  541. package/dist/types/core/time/range.d.ts +128 -0
  542. package/dist/types/core/time/range.d.ts.map +1 -0
  543. package/dist/types/core/time/reader.d.ts +163 -0
  544. package/dist/types/core/time/reader.d.ts.map +1 -0
  545. package/dist/types/core/time/readers/english.d.ts +100 -0
  546. package/dist/types/core/time/readers/english.d.ts.map +1 -0
  547. package/dist/types/core/time/readingAsk.d.ts +46 -0
  548. package/dist/types/core/time/readingAsk.d.ts.map +1 -0
  549. package/dist/types/core/time/resolve.d.ts +104 -0
  550. package/dist/types/core/time/resolve.d.ts.map +1 -0
  551. package/dist/types/core/time/resolveRecord.d.ts +161 -0
  552. package/dist/types/core/time/resolveRecord.d.ts.map +1 -0
  553. package/dist/types/core/time/rows.d.ts +298 -0
  554. package/dist/types/core/time/rows.d.ts.map +1 -0
  555. package/dist/types/core/time/rowsBuild.d.ts +83 -0
  556. package/dist/types/core/time/rowsBuild.d.ts.map +1 -0
  557. package/dist/types/core/time/textForms.d.ts +54 -0
  558. package/dist/types/core/time/textForms.d.ts.map +1 -0
  559. package/dist/types/core/time/windows.d.ts +114 -0
  560. package/dist/types/core/time/windows.d.ts.map +1 -0
  561. package/dist/types/core/time/wire.d.ts +64 -0
  562. package/dist/types/core/time/wire.d.ts.map +1 -0
  563. package/dist/types/core/time/zone.d.ts +116 -0
  564. package/dist/types/core/time/zone.d.ts.map +1 -0
  565. package/dist/types/core/tools.d.ts +26 -4
  566. package/dist/types/core/tools.d.ts.map +1 -1
  567. package/dist/types/events/payloads.d.ts +16 -2
  568. package/dist/types/events/payloads.d.ts.map +1 -1
  569. package/dist/types/index.d.ts +13 -1
  570. package/dist/types/index.d.ts.map +1 -1
  571. package/dist/types/lib/answer-account/facts/howSure.d.ts.map +1 -1
  572. package/dist/types/lib/answer-account/templates.d.ts +3 -0
  573. package/dist/types/lib/answer-account/templates.d.ts.map +1 -1
  574. package/dist/types/lib/mcp/elicitation.d.ts +85 -0
  575. package/dist/types/lib/mcp/elicitation.d.ts.map +1 -0
  576. package/dist/types/lib/mcp/mcpServe.d.ts.map +1 -1
  577. package/dist/types/lib/mcp/mockMcpClient.d.ts +9 -1
  578. package/dist/types/lib/mcp/mockMcpClient.d.ts.map +1 -1
  579. package/dist/types/lib/mcp/toolExtras.d.ts +21 -2
  580. package/dist/types/lib/mcp/toolExtras.d.ts.map +1 -1
  581. package/dist/types/lib/mcp/types.d.ts +8 -0
  582. package/dist/types/lib/mcp/types.d.ts.map +1 -1
  583. package/dist/types/lib/time-travel/receipt.d.ts +1 -1
  584. package/dist/types/lib/time-travel/receipt.d.ts.map +1 -1
  585. package/dist/types/lib/time-travel/servedView.d.ts +1 -1
  586. package/dist/types/lib/time-travel/servedView.d.ts.map +1 -1
  587. package/dist/types/locales/index.d.ts +6 -0
  588. package/dist/types/locales/index.d.ts.map +1 -1
  589. package/dist/types/locales/timeAsk.d.ts +30 -0
  590. package/dist/types/locales/timeAsk.d.ts.map +1 -0
  591. package/dist/types/recorders/core/resilienceHooks.d.ts.map +1 -1
  592. package/dist/types/resilience/statedWait.d.ts +23 -0
  593. package/dist/types/resilience/statedWait.d.ts.map +1 -0
  594. package/dist/types/resilience/withRetry.d.ts +13 -2
  595. package/dist/types/resilience/withRetry.d.ts.map +1 -1
  596. package/package.json +1 -1
  597. package/dist/artifacts/timeAxis.js +0 -218
  598. package/dist/artifacts/timeAxis.js.map +0 -1
  599. package/dist/esm/artifacts/timeAxis.d.ts +0 -114
  600. package/dist/esm/artifacts/timeAxis.js +0 -212
  601. package/dist/esm/artifacts/timeAxis.js.map +0 -1
  602. package/dist/types/artifacts/timeAxis.d.ts +0 -115
  603. package/dist/types/artifacts/timeAxis.d.ts.map +0 -1
@@ -0,0 +1,224 @@
1
+ /**
2
+ * core/time/axis — a dataset's TIME AXIS: the declaration, its one judge, and
3
+ * the read-side view that turns the declared column into comparable instants.
4
+ *
5
+ * Pattern: declared, never guessed; judged at mint, never repaired; values
6
+ * read through ONE view ({@link normaliseInstants}) that never
7
+ * touches the stored rows. Moved here from `artifacts/timeAxis.ts`
8
+ * (which `artifacts/index.ts` still re-exports), so the axis speaks
9
+ * the time layer's one grammar: `interval` is a `duration.ts`
10
+ * duration under {@link AXIS_UNITS}, `zone` is a `zone.ts` zone name.
11
+ * Role: core/ leaf (the time layer's one owner). Imports `instant.ts`,
12
+ * `duration.ts` and `zone.ts`. Asked by `artifacts/minting.ts` ·
13
+ * `prepareArtifact` and `artifacts/datasetResult.ts` ·
14
+ * `stageDatasetArtifacts` (the judge), and by any consumer that
15
+ * compares a dataset's times (the view).
16
+ * Emits: N/A.
17
+ *
18
+ * ## Why a producer declares it
19
+ *
20
+ * A table of rows is a time series only when one column IS time, and the
21
+ * reader of the rows cannot know that honestly: `ts` holding 1726000000 is
22
+ * epoch SECONDS to the tool that wrote it and a large integer to everything
23
+ * else; `'2026-09-14T10:00:00'` is UTC or the collector's wall clock. So the
24
+ * producer SAYS it, on the ticket (`PutArtifactInput.timeAxis`, carried on
25
+ * `ArtifactMeta.timeAxis`). A malformed declaration is REFUSED at mint
26
+ * ({@link timeAxisIssues}) — never trimmed or defaulted — and the shape is
27
+ * CLOSED: a misspelt `agg` is refused by name, never dropped.
28
+ *
29
+ * ## The view — values, not the declaration
30
+ *
31
+ * The judge never reads a value; {@link normaliseInstants} does, at read time.
32
+ * It turns the declared column into UTC `Z` instants spelled at ONE precision,
33
+ * so a lexicographic compare downstream is chronological, and it is honest
34
+ * about every value it could not place:
35
+ *
36
+ * | Value | Under | Read as |
37
+ * |-------|-------|---------|
38
+ * | a number | `epoch-s` / `epoch-ms` | that instant, exactly as written (no float rounding) |
39
+ * | ISO with `Z` or `±HH:MM` | `iso`, any zone | that instant (the lenient profile — a producer's spelling) |
40
+ * | ISO with NO offset | `iso`, no `zone` | **naive** — counted, never read as UTC; `status: 'naive-values'`, or refused under `naive: 'refuse'` |
41
+ * | ISO with no offset | `iso` + `zone` | a wall time in that zone; one instant, or — in a fall-back overlap — the row-order rule below; in a spring-forward gap, counted `dstGap` |
42
+ * | anything else | — | counted `unreadable` (`missing` when the row lacks the column) |
43
+ *
44
+ * **The fall-back rule.** In the hour the clocks go back, one wall time names
45
+ * two instants. Read in the rows' order, the values before the wall clock
46
+ * steps back take the earlier offset and those from the step on the later
47
+ * (a note `{ kind: 'dst-overlap', resolvedBy: 'row-order' }` per value). When
48
+ * the order cannot tell — a lone `01:30`, no step back, two steps back, or a
49
+ * column whose wall times are not in order anywhere — the value is counted
50
+ * `dstAmbiguous` and handled like a naive one. Nothing is picked silently.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * timeAxisIssues({ column: 'ts', unit: 'epoch-s', zone: 'UTC' }); // ['timeAxis.zone is for wall-clock ISO values; …']
55
+ * normaliseInstants([{ ts: 1726300800 }, { ts: 1726304400.5 }], { column: 'ts', unit: 'epoch-s' });
56
+ * // { status: 'instants', precision: 'millisecond',
57
+ * // points: [{ row: 0, at: '2024-09-14T08:00:00.000Z' }, { row: 1, at: '2024-09-14T09:00:00.500Z' }], … }
58
+ * normaliseInstants([{ t: '2026-09-14T10:00:00' }], { column: 't', unit: 'iso' });
59
+ * // { status: 'naive-values', count: 1, points: [], … } — never read as UTC
60
+ * ```
61
+ */
62
+ import { type InstantText } from './instant.js';
63
+ /** How the time column's values are written. */
64
+ export type TimeAxisUnit = 'iso' | 'epoch-s' | 'epoch-ms';
65
+ /** How one row summarises the interval it stands for. */
66
+ export type TimeAxisAggregate = 'avg' | 'min' | 'max' | 'sum' | 'count' | 'last';
67
+ /** The closed sets, in one place, for the judge and for its own messages. */
68
+ export declare const TIME_AXIS_UNITS: readonly TimeAxisUnit[];
69
+ export declare const TIME_AXIS_AGGREGATES: readonly TimeAxisAggregate[];
70
+ /**
71
+ * A dataset's declared time axis.
72
+ *
73
+ * @example hourly buckets, two measures summarised differently
74
+ * { column: 'hour', unit: 'iso', interval: '1h',
75
+ * aggregate: { read_iops: 'avg', peak_iops: 'max' } }
76
+ * @example raw samples every five minutes, epoch seconds
77
+ * { column: 'ts', unit: 'epoch-s', interval: '5m', aggregate: 'raw' }
78
+ */
79
+ export interface DatasetTimeAxis {
80
+ /** The column that holds time. */
81
+ readonly column: string;
82
+ /** `'iso'` — ISO-8601 strings; `'epoch-s'` / `'epoch-ms'` — numbers since
83
+ * 1970-01-01T00:00:00Z in seconds / milliseconds. */
84
+ readonly unit: TimeAxisUnit;
85
+ /** IANA zone name (`'Europe/London'`) the values are WALL-CLOCK in — never
86
+ * an abbreviation such as `'PST'` or a bare offset. `'iso'` only — an epoch
87
+ * is an instant and has no zone to declare. Absent: every ISO value must
88
+ * carry its own offset (`Z` or `±HH:MM`); a value without one is NEVER
89
+ * read as UTC — {@link normaliseInstants} counts it (`naive-values`) or,
90
+ * by the reader's choice, refuses the column. */
91
+ readonly zone?: string;
92
+ /** Width of the interval one row stands for: a positive whole number and
93
+ * one of `s m h d w` (`'30s'`, `'5m'`, `'1h'`, `'1d'`, `'1w'`) — the time
94
+ * layer's one duration grammar, any number of digits. With
95
+ * `aggregate: 'raw'` it is the sampling cadence. */
96
+ readonly interval?: string;
97
+ /**
98
+ * How each row summarises its interval. `'raw'` — every row is a sample as
99
+ * collected, nothing was reduced. One aggregate — every measure column was
100
+ * reduced the same way. A record — measure column to its own aggregate
101
+ * (`{ avg_iops: 'avg', peak_iops: 'max' }`); a column not named there is
102
+ * not a declared measure. Any aggregate other than `'raw'` requires
103
+ * `interval`, and `interval` requires `aggregate`: a summary of an interval
104
+ * nobody named, or an interval with no word for what happened in it, is
105
+ * half a declaration.
106
+ */
107
+ readonly aggregate?: 'raw' | TimeAxisAggregate | Readonly<Record<string, TimeAxisAggregate>>;
108
+ }
109
+ /**
110
+ * THE ONE JUDGE of a time-axis declaration. Returns every problem, in words a
111
+ * producer can act on; an empty list means the declaration is well-formed.
112
+ * Never throws, never repairs, never reads a value.
113
+ */
114
+ export declare function timeAxisIssues(value: unknown): string[];
115
+ /** What a consumer finds on a ticket. `malformed` exists for tickets minted
116
+ * outside this library's put (a foreign writer, an old store) — a consumer
117
+ * shows it as an error, never as an undeclared dataset. */
118
+ export type TimeAxisReading = {
119
+ readonly status: 'absent';
120
+ } | {
121
+ readonly status: 'declared';
122
+ readonly axis: DatasetTimeAxis;
123
+ } | {
124
+ readonly status: 'malformed';
125
+ readonly issues: readonly string[];
126
+ };
127
+ /** Read the declaration off a ticket (`ArtifactMeta`, or anything shaped like
128
+ * one). Absent is absent; anything present is judged. */
129
+ export declare function readTimeAxis(meta: unknown): TimeAxisReading;
130
+ /**
131
+ * The declared SUMMARY in words, for a chart title — the one wording every
132
+ * consumer shares, so two screens never describe one ticket two ways.
133
+ *
134
+ * `{ interval: '1h', aggregate: { a: 'avg', b: 'max' } }` → `'hourly avg and max'`
135
+ * `{ interval: '5m', aggregate: 'max' }` → `'5-minute max'`
136
+ * `{ interval: '5m', aggregate: 'raw' }` → `'raw samples every 5 minutes'`
137
+ * `{ aggregate: 'raw' }` → `'raw samples'`
138
+ *
139
+ * `undefined` when the declaration says nothing about summarising (column and
140
+ * unit only) — there is no summary to put in a title, and inventing "raw"
141
+ * would claim something the producer did not.
142
+ */
143
+ export declare function describeTimeAxis(axis: DatasetTimeAxis): string | undefined;
144
+ /** What {@link normaliseInstants} does with a naive value: count it (`'flag'`, the default) or refuse the column. */
145
+ export type NaiveValues = 'flag' | 'refuse';
146
+ /** Options of {@link normaliseInstants}. */
147
+ export interface NormaliseOptions {
148
+ /** A value whose clock is unknown (naive, or a fall-back wall time the row
149
+ * order cannot place): `'flag'` counts it and reads the rest; `'refuse'`
150
+ * places nothing. Never read as UTC either way. Default `'flag'`. */
151
+ readonly naive?: NaiveValues;
152
+ }
153
+ /** The one precision every point of a view is spelled at: the finest any value was written in. */
154
+ export type AxisPrecision = 'second' | 'millisecond' | 'nanosecond';
155
+ /** One placed value: the row it came from and its UTC instant. */
156
+ export interface AxisPoint {
157
+ /** The row's index in the rows as stored. */
158
+ readonly row: number;
159
+ /** The instant in UTC (`Z`), at the view's one precision — so comparing two
160
+ * spellings as text compares them in time. */
161
+ readonly at: InstantText;
162
+ }
163
+ /** A value the fall-back overlap doubled, placed by the rows' order. */
164
+ export interface AxisOverlapNote {
165
+ readonly kind: 'dst-overlap';
166
+ readonly resolvedBy: 'row-order';
167
+ readonly row: number;
168
+ /** Which of the two instants the wall time names: before the clock stepped back, or after. */
169
+ readonly which: 'earlier' | 'later';
170
+ }
171
+ /** Every value the view could not place, by reason. */
172
+ export interface AxisCounts {
173
+ /** An ISO value with no offset under an axis with no `zone`. */
174
+ readonly naive: number;
175
+ /** A wall time the fall-back doubles, where the rows' order cannot tell which. */
176
+ readonly dstAmbiguous: number;
177
+ /** A wall time the spring-forward skips — it names no instant. */
178
+ readonly dstGap: number;
179
+ /** Present, but not a value of the declared unit (or outside years 0000–9999). */
180
+ readonly unreadable: number;
181
+ /** The row lacks the column, holds `null`, or is not a record. */
182
+ readonly missing: number;
183
+ }
184
+ /**
185
+ * The read-side view of a declared time column.
186
+ *
187
+ * - `instants` — every value whose clock is known was placed.
188
+ * - `naive-values` — `count` values have no known clock (`naive` +
189
+ * `dstAmbiguous`); they are not in `points`, and nothing should compare or
190
+ * join the series with another source as if they were.
191
+ * - `refused` — the same, under `naive: 'refuse'`: nothing is placed.
192
+ *
193
+ * `points` are sorted in time (ties by row); `unreadable`, `missing` and
194
+ * `dstGap` are counted under every status.
195
+ */
196
+ export type NormalisedAxis = {
197
+ readonly status: 'instants';
198
+ readonly points: readonly AxisPoint[];
199
+ readonly precision: AxisPrecision;
200
+ readonly notes: readonly AxisOverlapNote[];
201
+ readonly counts: AxisCounts;
202
+ } | {
203
+ readonly status: 'naive-values';
204
+ readonly count: number;
205
+ readonly points: readonly AxisPoint[];
206
+ readonly precision: AxisPrecision;
207
+ readonly notes: readonly AxisOverlapNote[];
208
+ readonly counts: AxisCounts;
209
+ } | {
210
+ readonly status: 'refused';
211
+ readonly reason: 'naive-values';
212
+ readonly count: number;
213
+ readonly counts: AxisCounts;
214
+ };
215
+ /**
216
+ * THE READ-SIDE VIEW of a declared time column: every value turned into a UTC
217
+ * `Z` instant at one precision, sorted in time, with every value it could not
218
+ * place counted by reason (the module table). The rows are only read — never
219
+ * copied into, reordered or rewritten — so the stored bytes are unchanged.
220
+ *
221
+ * A malformed `axis` throws a `TypeError` naming its issues (read a ticket
222
+ * with `readTimeAxis` first; a declaration is never repaired).
223
+ */
224
+ export declare function normaliseInstants(rows: readonly unknown[], axis: DatasetTimeAxis, options?: NormaliseOptions): NormalisedAxis;
@@ -0,0 +1,462 @@
1
+ /**
2
+ * core/time/axis — a dataset's TIME AXIS: the declaration, its one judge, and
3
+ * the read-side view that turns the declared column into comparable instants.
4
+ *
5
+ * Pattern: declared, never guessed; judged at mint, never repaired; values
6
+ * read through ONE view ({@link normaliseInstants}) that never
7
+ * touches the stored rows. Moved here from `artifacts/timeAxis.ts`
8
+ * (which `artifacts/index.ts` still re-exports), so the axis speaks
9
+ * the time layer's one grammar: `interval` is a `duration.ts`
10
+ * duration under {@link AXIS_UNITS}, `zone` is a `zone.ts` zone name.
11
+ * Role: core/ leaf (the time layer's one owner). Imports `instant.ts`,
12
+ * `duration.ts` and `zone.ts`. Asked by `artifacts/minting.ts` ·
13
+ * `prepareArtifact` and `artifacts/datasetResult.ts` ·
14
+ * `stageDatasetArtifacts` (the judge), and by any consumer that
15
+ * compares a dataset's times (the view).
16
+ * Emits: N/A.
17
+ *
18
+ * ## Why a producer declares it
19
+ *
20
+ * A table of rows is a time series only when one column IS time, and the
21
+ * reader of the rows cannot know that honestly: `ts` holding 1726000000 is
22
+ * epoch SECONDS to the tool that wrote it and a large integer to everything
23
+ * else; `'2026-09-14T10:00:00'` is UTC or the collector's wall clock. So the
24
+ * producer SAYS it, on the ticket (`PutArtifactInput.timeAxis`, carried on
25
+ * `ArtifactMeta.timeAxis`). A malformed declaration is REFUSED at mint
26
+ * ({@link timeAxisIssues}) — never trimmed or defaulted — and the shape is
27
+ * CLOSED: a misspelt `agg` is refused by name, never dropped.
28
+ *
29
+ * ## The view — values, not the declaration
30
+ *
31
+ * The judge never reads a value; {@link normaliseInstants} does, at read time.
32
+ * It turns the declared column into UTC `Z` instants spelled at ONE precision,
33
+ * so a lexicographic compare downstream is chronological, and it is honest
34
+ * about every value it could not place:
35
+ *
36
+ * | Value | Under | Read as |
37
+ * |-------|-------|---------|
38
+ * | a number | `epoch-s` / `epoch-ms` | that instant, exactly as written (no float rounding) |
39
+ * | ISO with `Z` or `±HH:MM` | `iso`, any zone | that instant (the lenient profile — a producer's spelling) |
40
+ * | ISO with NO offset | `iso`, no `zone` | **naive** — counted, never read as UTC; `status: 'naive-values'`, or refused under `naive: 'refuse'` |
41
+ * | ISO with no offset | `iso` + `zone` | a wall time in that zone; one instant, or — in a fall-back overlap — the row-order rule below; in a spring-forward gap, counted `dstGap` |
42
+ * | anything else | — | counted `unreadable` (`missing` when the row lacks the column) |
43
+ *
44
+ * **The fall-back rule.** In the hour the clocks go back, one wall time names
45
+ * two instants. Read in the rows' order, the values before the wall clock
46
+ * steps back take the earlier offset and those from the step on the later
47
+ * (a note `{ kind: 'dst-overlap', resolvedBy: 'row-order' }` per value). When
48
+ * the order cannot tell — a lone `01:30`, no step back, two steps back, or a
49
+ * column whose wall times are not in order anywhere — the value is counted
50
+ * `dstAmbiguous` and handled like a naive one. Nothing is picked silently.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * timeAxisIssues({ column: 'ts', unit: 'epoch-s', zone: 'UTC' }); // ['timeAxis.zone is for wall-clock ISO values; …']
55
+ * normaliseInstants([{ ts: 1726300800 }, { ts: 1726304400.5 }], { column: 'ts', unit: 'epoch-s' });
56
+ * // { status: 'instants', precision: 'millisecond',
57
+ * // points: [{ row: 0, at: '2024-09-14T08:00:00.000Z' }, { row: 1, at: '2024-09-14T09:00:00.500Z' }], … }
58
+ * normaliseInstants([{ t: '2026-09-14T10:00:00' }], { column: 't', unit: 'iso' });
59
+ * // { status: 'naive-values', count: 1, points: [], … } — never read as UTC
60
+ * ```
61
+ */
62
+ import { AXIS_UNITS, durationParts, isDuration } from './duration.js';
63
+ import { instantOf, spellInstant } from './instant.js';
64
+ import { isZoneName, readWall } from './zone.js';
65
+ /** The closed sets, in one place, for the judge and for its own messages. */
66
+ export const TIME_AXIS_UNITS = ['iso', 'epoch-s', 'epoch-ms'];
67
+ export const TIME_AXIS_AGGREGATES = [
68
+ 'avg',
69
+ 'min',
70
+ 'max',
71
+ 'sum',
72
+ 'count',
73
+ 'last',
74
+ ];
75
+ const KEYS = new Set(['column', 'unit', 'zone', 'interval', 'aggregate']);
76
+ function isRecord(value) {
77
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
78
+ }
79
+ function isAggregate(value) {
80
+ return TIME_AXIS_AGGREGATES.includes(value);
81
+ }
82
+ /**
83
+ * THE ONE JUDGE of a time-axis declaration. Returns every problem, in words a
84
+ * producer can act on; an empty list means the declaration is well-formed.
85
+ * Never throws, never repairs, never reads a value.
86
+ */
87
+ export function timeAxisIssues(value) {
88
+ if (!isRecord(value)) {
89
+ return [`timeAxis must be an object like { column, unit }, got ${describeValue(value)}.`];
90
+ }
91
+ const issues = [];
92
+ for (const key of Object.keys(value)) {
93
+ if (!KEYS.has(key)) {
94
+ issues.push(`timeAxis has an unknown key '${key}'; the keys are column, unit, zone, interval, aggregate.`);
95
+ }
96
+ }
97
+ const { column, unit, zone, interval, aggregate } = value;
98
+ if (typeof column !== 'string' || column.trim() === '') {
99
+ issues.push(`timeAxis.column must name the time column, got ${describeValue(column)}.`);
100
+ }
101
+ if (!TIME_AXIS_UNITS.includes(unit)) {
102
+ issues.push(`timeAxis.unit must be one of ${TIME_AXIS_UNITS.join(', ')}, got ${describeValue(unit)}.`);
103
+ }
104
+ if (zone !== undefined) {
105
+ if (!isZoneName(zone)) {
106
+ issues.push(`timeAxis.zone must be an IANA zone such as 'Europe/London' (an abbreviation such as ` +
107
+ `'PST' or a bare offset is not one), got ${describeValue(zone)}.`);
108
+ }
109
+ else if (unit !== 'iso') {
110
+ issues.push(`timeAxis.zone is for wall-clock ISO values; an epoch is an instant and has no zone — ` +
111
+ `drop zone or use unit 'iso'.`);
112
+ }
113
+ }
114
+ if (interval !== undefined && !isDuration(interval, AXIS_UNITS)) {
115
+ issues.push(`timeAxis.interval must be a positive whole number and one of s m h d w ('5m', '1h', '1d'), ` +
116
+ `got ${describeValue(interval)}.`);
117
+ }
118
+ if (aggregate !== undefined && aggregate !== 'raw' && !isAggregate(aggregate)) {
119
+ if (!isRecord(aggregate)) {
120
+ issues.push(`timeAxis.aggregate must be 'raw', one of ${TIME_AXIS_AGGREGATES.join(', ')}, or a ` +
121
+ `record of measure column to one of them, got ${describeValue(aggregate)}.`);
122
+ }
123
+ else {
124
+ const entries = Object.entries(aggregate);
125
+ if (entries.length === 0) {
126
+ issues.push('timeAxis.aggregate names no measure; declare at least one, or omit it.');
127
+ }
128
+ for (const [measure, how] of entries) {
129
+ if (measure.trim() === '')
130
+ issues.push('timeAxis.aggregate has a blank measure name.');
131
+ if (measure === column) {
132
+ issues.push(`timeAxis.aggregate names the time column '${measure}' as a measure.`);
133
+ }
134
+ if (!isAggregate(how)) {
135
+ issues.push(`timeAxis.aggregate['${measure}'] must be one of ${TIME_AXIS_AGGREGATES.join(', ')}, ` +
136
+ `got ${describeValue(how)}.`);
137
+ }
138
+ }
139
+ }
140
+ }
141
+ if (aggregate !== undefined && aggregate !== 'raw' && interval === undefined) {
142
+ issues.push('timeAxis.aggregate summarises an interval, so timeAxis.interval must say how wide it is.');
143
+ }
144
+ if (interval !== undefined && aggregate === undefined) {
145
+ issues.push(`timeAxis.interval needs timeAxis.aggregate — say how each interval was summarised, or 'raw'.`);
146
+ }
147
+ return issues;
148
+ }
149
+ /** Read the declaration off a ticket (`ArtifactMeta`, or anything shaped like
150
+ * one). Absent is absent; anything present is judged. */
151
+ export function readTimeAxis(meta) {
152
+ const value = isRecord(meta) ? meta.timeAxis : undefined;
153
+ if (value === undefined)
154
+ return { status: 'absent' };
155
+ const issues = timeAxisIssues(value);
156
+ return issues.length > 0
157
+ ? { status: 'malformed', issues }
158
+ : { status: 'declared', axis: value };
159
+ }
160
+ // ── The wording ─────────────────────────────────────────────────────────────
161
+ const UNIT_WORDS = {
162
+ s: 'second',
163
+ m: 'minute',
164
+ h: 'hour',
165
+ d: 'day',
166
+ w: 'week',
167
+ };
168
+ const SINGLE = {
169
+ s: 'per-second',
170
+ m: 'per-minute',
171
+ h: 'hourly',
172
+ d: 'daily',
173
+ w: 'weekly',
174
+ };
175
+ /** `'1h'` → `'hourly'`, `'5m'` → `'5-minute'`. */
176
+ function intervalAdjective(interval) {
177
+ const parts = durationParts(interval, AXIS_UNITS);
178
+ if (parts === undefined)
179
+ return interval;
180
+ return parts.digits === '1'
181
+ ? SINGLE[parts.unit]
182
+ : `${parts.digits}-${UNIT_WORDS[parts.unit]}`;
183
+ }
184
+ /** `'5m'` → `'5 minutes'`, `'1h'` → `'hour'`. */
185
+ function intervalNoun(interval) {
186
+ const parts = durationParts(interval, AXIS_UNITS);
187
+ if (parts === undefined)
188
+ return interval;
189
+ return parts.digits === '1'
190
+ ? UNIT_WORDS[parts.unit]
191
+ : `${parts.digits} ${UNIT_WORDS[parts.unit]}s`;
192
+ }
193
+ function joinWords(words) {
194
+ if (words.length <= 1)
195
+ return words[0] ?? '';
196
+ return `${words.slice(0, -1).join(', ')} and ${words[words.length - 1]}`;
197
+ }
198
+ /**
199
+ * The declared SUMMARY in words, for a chart title — the one wording every
200
+ * consumer shares, so two screens never describe one ticket two ways.
201
+ *
202
+ * `{ interval: '1h', aggregate: { a: 'avg', b: 'max' } }` → `'hourly avg and max'`
203
+ * `{ interval: '5m', aggregate: 'max' }` → `'5-minute max'`
204
+ * `{ interval: '5m', aggregate: 'raw' }` → `'raw samples every 5 minutes'`
205
+ * `{ aggregate: 'raw' }` → `'raw samples'`
206
+ *
207
+ * `undefined` when the declaration says nothing about summarising (column and
208
+ * unit only) — there is no summary to put in a title, and inventing "raw"
209
+ * would claim something the producer did not.
210
+ */
211
+ export function describeTimeAxis(axis) {
212
+ const { aggregate, interval } = axis;
213
+ if (aggregate === undefined)
214
+ return undefined;
215
+ if (aggregate === 'raw') {
216
+ return interval === undefined ? 'raw samples' : `raw samples every ${intervalNoun(interval)}`;
217
+ }
218
+ const words = typeof aggregate === 'string' ? [aggregate] : [...new Set(Object.values(aggregate))];
219
+ const how = joinWords(words);
220
+ return interval === undefined ? how : `${intervalAdjective(interval)} ${how}`;
221
+ }
222
+ function describeValue(value) {
223
+ if (value === undefined)
224
+ return 'nothing';
225
+ try {
226
+ const text = JSON.stringify(value);
227
+ if (text === undefined)
228
+ return typeof value;
229
+ return text.length > 60 ? `${text.slice(0, 57)}...` : text;
230
+ }
231
+ catch {
232
+ return typeof value;
233
+ }
234
+ }
235
+ const NS_PER_MS = 1000000n;
236
+ /**
237
+ * An epoch number read EXACTLY as written — through its decimal spelling, so
238
+ * `1726304400.123` is 123 ms and not the double's nearest neighbour. An
239
+ * exponent spelling (`1e21`) or a fraction finer than a nanosecond is
240
+ * unreadable.
241
+ */
242
+ function epochInstant(value, unit) {
243
+ if (typeof value !== 'number' || !Number.isFinite(value))
244
+ return undefined;
245
+ const m = /^(-?)(\d+)(?:\.(\d+))?$/.exec(String(value));
246
+ if (m === null)
247
+ return undefined;
248
+ const fractionDigits = unit === 'epoch-s' ? 9 : 6; // down to one nanosecond
249
+ const fraction = m[3] ?? '';
250
+ if (fraction.length > fractionDigits)
251
+ return undefined;
252
+ const magnitude = BigInt(m[2]) * 10n ** BigInt(fractionDigits) +
253
+ BigInt(fraction.padEnd(fractionDigits, '0') || '0');
254
+ const ns = m[1] === '-' ? -magnitude : magnitude;
255
+ let ms = ns / NS_PER_MS;
256
+ if (ns < 0n && ms * NS_PER_MS !== ns)
257
+ ms -= 1n; // floor, not truncate
258
+ const whole = Number(ms);
259
+ if (!Number.isSafeInteger(whole))
260
+ return undefined;
261
+ return { ms: whole, nanos: Number(ns - ms * NS_PER_MS) };
262
+ }
263
+ const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
264
+ /**
265
+ * An ISO value with no offset, read as a UTC WALL reading only to get its
266
+ * fields — never as an instant. `undefined` when it is not a date-time (or a
267
+ * date) with no zone.
268
+ */
269
+ function naiveFields(value) {
270
+ const spelled = DATE_ONLY.test(value) ? `${value}T00:00Z` : `${value}Z`;
271
+ return instantOf(spelled, 'lenient');
272
+ }
273
+ function wallOf(fields) {
274
+ const d = new Date(fields.ms);
275
+ return {
276
+ year: d.getUTCFullYear(),
277
+ month: d.getUTCMonth() + 1,
278
+ day: d.getUTCDate(),
279
+ hour: d.getUTCHours(),
280
+ minute: d.getUTCMinutes(),
281
+ second: d.getUTCSeconds(),
282
+ millisecond: d.getUTCMilliseconds(),
283
+ };
284
+ }
285
+ function spellable(instant) {
286
+ return spellInstant(instant, 0) !== undefined;
287
+ }
288
+ function classifyIso(value, zone, walls) {
289
+ if (typeof value !== 'string')
290
+ return { kind: 'unreadable' };
291
+ const instant = instantOf(value, 'lenient');
292
+ if (instant !== undefined)
293
+ return { kind: 'instant', instant };
294
+ const fields = naiveFields(value);
295
+ if (fields === undefined)
296
+ return { kind: 'unreadable' };
297
+ if (zone === undefined)
298
+ return { kind: 'naive' };
299
+ const wall = fields.ms;
300
+ let reading = walls.get(wall);
301
+ if (reading === undefined) {
302
+ const w = wallOf(fields);
303
+ if (w.year > 9999)
304
+ return { kind: 'unreadable' };
305
+ reading = readWall(w, zone);
306
+ walls.set(wall, reading);
307
+ }
308
+ const at = (ms) => ({ ms, nanos: fields.nanos });
309
+ if (reading.kind === 'gap')
310
+ return { kind: 'gap' };
311
+ if (reading.kind === 'unique')
312
+ return { kind: 'instant', instant: at(reading.ms), wall };
313
+ return {
314
+ kind: 'overlap',
315
+ earlier: at(reading.earlier),
316
+ later: at(reading.later),
317
+ wall,
318
+ day: value.slice(0, 10),
319
+ };
320
+ }
321
+ function classifyEpoch(value, unit) {
322
+ const instant = epochInstant(value, unit);
323
+ return instant === undefined ? { kind: 'unreadable' } : { kind: 'instant', instant };
324
+ }
325
+ function classify(row, axis, walls) {
326
+ if (!isRecord(row))
327
+ return { kind: 'missing' };
328
+ const value = row[axis.column];
329
+ if (value === undefined || value === null)
330
+ return { kind: 'missing' };
331
+ const read = axis.unit === 'iso' ? classifyIso(value, axis.zone, walls) : classifyEpoch(value, axis.unit);
332
+ if (read.kind === 'instant' && !spellable(read.instant))
333
+ return { kind: 'unreadable' };
334
+ if (read.kind === 'overlap' && !(spellable(read.earlier) && spellable(read.later))) {
335
+ return { kind: 'unreadable' };
336
+ }
337
+ return read;
338
+ }
339
+ /**
340
+ * The fall-back rule over the rows' order: for each overlap day, the one
341
+ * place its wall clock steps back (a value not after the one before it)
342
+ * splits it into `earlier` then `later`. Any step back that is NOT inside one
343
+ * overlap day means the rows are not in time order, and every overlap value
344
+ * is left unplaced; so is a day with no step back or more than one.
345
+ */
346
+ function resolveOverlaps(read, nanos) {
347
+ const placed = new Map();
348
+ const walled = [];
349
+ for (let i = 0; i < read.length; i++) {
350
+ const r = read[i];
351
+ if ((r.kind === 'instant' && r.wall !== undefined) || r.kind === 'overlap')
352
+ walled.push(i);
353
+ }
354
+ const wallAt = (i) => read[i].wall;
355
+ const stepsByDay = new Map();
356
+ for (let k = 1; k < walled.length; k++) {
357
+ const prev = walled[k - 1];
358
+ const here = walled[k];
359
+ const notAfter = wallAt(here) < wallAt(prev) || (wallAt(here) === wallAt(prev) && nanos(here) <= nanos(prev));
360
+ if (!notAfter)
361
+ continue;
362
+ const a = read[prev];
363
+ const b = read[here];
364
+ if (a.kind !== 'overlap' || b.kind !== 'overlap' || a.day !== b.day)
365
+ return placed;
366
+ stepsByDay.set(a.day, [...(stepsByDay.get(a.day) ?? []), here]);
367
+ }
368
+ for (const [day, steps] of stepsByDay) {
369
+ if (steps.length !== 1)
370
+ continue;
371
+ const step = steps[0];
372
+ for (let i = 0; i < read.length; i++) {
373
+ const r = read[i];
374
+ if (r.kind === 'overlap' && r.day === day)
375
+ placed.set(i, i < step ? 'earlier' : 'later');
376
+ }
377
+ }
378
+ return placed;
379
+ }
380
+ const pad = (n, width) => String(n).padStart(width, '0');
381
+ function precisionOf(instants) {
382
+ let precision = 'second';
383
+ for (const { ms, nanos } of instants) {
384
+ if (nanos !== 0)
385
+ return 'nanosecond';
386
+ if (((ms % 1000) + 1000) % 1000 !== 0)
387
+ precision = 'millisecond';
388
+ }
389
+ return precision;
390
+ }
391
+ /** `instant` in UTC with exactly the digits `precision` names — fixed width, so text order is time order. */
392
+ function spellAt(instant, precision) {
393
+ const msPart = ((instant.ms % 1000) + 1000) % 1000;
394
+ const whole = spellInstant({ ms: instant.ms - msPart, nanos: 0 }, 0);
395
+ if (precision === 'second')
396
+ return whole;
397
+ const fraction = pad(msPart * 1_000_000 + instant.nanos, 9);
398
+ const digits = precision === 'millisecond' ? fraction.slice(0, 3) : fraction;
399
+ return `${whole.slice(0, -1)}.${digits}Z`;
400
+ }
401
+ /**
402
+ * THE READ-SIDE VIEW of a declared time column: every value turned into a UTC
403
+ * `Z` instant at one precision, sorted in time, with every value it could not
404
+ * place counted by reason (the module table). The rows are only read — never
405
+ * copied into, reordered or rewritten — so the stored bytes are unchanged.
406
+ *
407
+ * A malformed `axis` throws a `TypeError` naming its issues (read a ticket
408
+ * with `readTimeAxis` first; a declaration is never repaired).
409
+ */
410
+ export function normaliseInstants(rows, axis, options = {}) {
411
+ const issues = timeAxisIssues(axis);
412
+ if (issues.length > 0) {
413
+ throw new TypeError(`normaliseInstants: the time axis is malformed — ${issues.join(' ')}`);
414
+ }
415
+ const naive = options.naive ?? 'flag';
416
+ if (naive !== 'flag' && naive !== 'refuse') {
417
+ throw new TypeError(`normaliseInstants: naive must be 'flag' or 'refuse', got ${describeValue(naive)}.`);
418
+ }
419
+ if (!Array.isArray(rows)) {
420
+ throw new TypeError(`normaliseInstants: rows must be an array, got ${describeValue(rows)}.`);
421
+ }
422
+ const walls = new Map();
423
+ const read = rows.map((row) => classify(row, axis, walls));
424
+ const nanosOf = (i) => {
425
+ const r = read[i];
426
+ return r.kind === 'instant' ? r.instant.nanos : r.kind === 'overlap' ? r.earlier.nanos : 0;
427
+ };
428
+ const byOrder = read.some((r) => r.kind === 'overlap')
429
+ ? resolveOverlaps(read, nanosOf)
430
+ : new Map();
431
+ const counts = { naive: 0, dstAmbiguous: 0, dstGap: 0, unreadable: 0, missing: 0 };
432
+ const placed = [];
433
+ const notes = [];
434
+ read.forEach((r, row) => {
435
+ if (r.kind === 'instant')
436
+ placed.push({ row, instant: r.instant });
437
+ else if (r.kind === 'overlap') {
438
+ const which = byOrder.get(row);
439
+ if (which === undefined)
440
+ counts.dstAmbiguous++;
441
+ else {
442
+ placed.push({ row, instant: r[which] });
443
+ notes.push({ kind: 'dst-overlap', resolvedBy: 'row-order', row, which });
444
+ }
445
+ }
446
+ else if (r.kind === 'gap')
447
+ counts.dstGap++;
448
+ else
449
+ counts[r.kind]++;
450
+ });
451
+ const count = counts.naive + counts.dstAmbiguous;
452
+ if (count > 0 && naive === 'refuse') {
453
+ return { status: 'refused', reason: 'naive-values', count, counts };
454
+ }
455
+ placed.sort((a, b) => a.instant.ms - b.instant.ms || a.instant.nanos - b.instant.nanos || a.row - b.row);
456
+ const precision = precisionOf(placed.map((p) => p.instant));
457
+ const points = placed.map((p) => ({ row: p.row, at: spellAt(p.instant, precision) }));
458
+ return count > 0
459
+ ? { status: 'naive-values', count, points, precision, notes, counts }
460
+ : { status: 'instants', points, precision, notes, counts };
461
+ }
462
+ //# sourceMappingURL=axis.js.map