@remnic/core 9.3.690 → 9.3.691

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 (281) hide show
  1. package/dist/access-boundary.d.ts +5 -5
  2. package/dist/access-boundary.js +18 -18
  3. package/dist/access-cli.js +44 -44
  4. package/dist/access-http.d.ts +5 -5
  5. package/dist/access-http.js +24 -24
  6. package/dist/access-mcp.d.ts +5 -5
  7. package/dist/access-mcp.js +21 -21
  8. package/dist/access-operations.d.ts +5 -5
  9. package/dist/access-operations.js +20 -20
  10. package/dist/access-schema.js +3 -3
  11. package/dist/{access-service-Dujr3MTm.d.ts → access-service-CKnFdxH-.d.ts} +2 -2
  12. package/dist/access-service.d.ts +5 -5
  13. package/dist/access-service.js +17 -17
  14. package/dist/access-surface-catalog.d.ts +5 -5
  15. package/dist/action-confidence.d.ts +1 -1
  16. package/dist/active-memory-bridge.d.ts +1 -1
  17. package/dist/active-recall.d.ts +1 -1
  18. package/dist/active-recall.js +1 -1
  19. package/dist/adapters/index.js +4 -4
  20. package/dist/adapters/registry.js +2 -2
  21. package/dist/{auto-sync-NUQWSFQD.js → auto-sync-RWXT6P5M.js} +5 -5
  22. package/dist/behavior-learner.d.ts +1 -1
  23. package/dist/behavior-signals.d.ts +1 -1
  24. package/dist/bootstrap.d.ts +4 -4
  25. package/dist/briefing.d.ts +1 -1
  26. package/dist/briefing.js +5 -5
  27. package/dist/buffer-surprise-report.d.ts +1 -1
  28. package/dist/buffer.d.ts +1 -1
  29. package/dist/calibration.d.ts +1 -1
  30. package/dist/calibration.js +2 -2
  31. package/dist/capabilities.d.ts +1 -1
  32. package/dist/{catalog-CKPtJ114.d.ts → catalog-BEWLjdOr.d.ts} +1 -1
  33. package/dist/causal-behavior.d.ts +1 -1
  34. package/dist/causal-consolidation.d.ts +1 -1
  35. package/dist/causal-consolidation.js +8 -8
  36. package/dist/{chunk-GTDH3IUH.js → chunk-2D27ODNX.js} +2 -2
  37. package/dist/{chunk-3K37VPM3.js → chunk-3BRA3N5A.js} +2 -2
  38. package/dist/{chunk-RTFAZOIR.js → chunk-3VVH6ZQW.js} +2 -2
  39. package/dist/{chunk-FIVDN2SM.js → chunk-4RGWCRIJ.js} +4 -4
  40. package/dist/{chunk-AGJH5ISO.js → chunk-5KBNNUXS.js} +2 -2
  41. package/dist/{chunk-X7RLU5CR.js → chunk-66HROLW5.js} +2 -2
  42. package/dist/{chunk-NSVXK7M5.js → chunk-7UVDIWLL.js} +4 -4
  43. package/dist/{chunk-UPIBE2DK.js → chunk-ADUAF5EV.js} +2 -2
  44. package/dist/{chunk-LLONI6PY.js → chunk-AFWEUTMS.js} +2 -2
  45. package/dist/{chunk-CWE74HRG.js → chunk-D3DNGQNQ.js} +3 -3
  46. package/dist/{chunk-ZUDM75KG.js → chunk-DCWIQFNA.js} +4 -4
  47. package/dist/{chunk-NGFEWFNK.js → chunk-DQHZA7Y3.js} +1 -1
  48. package/dist/chunk-DQHZA7Y3.js.map +1 -0
  49. package/dist/{chunk-OBXTMFZQ.js → chunk-ECZPWSB5.js} +2 -2
  50. package/dist/{chunk-BFVPIKDY.js → chunk-GCOSQBQ2.js} +3 -3
  51. package/dist/{chunk-LXIEXSHU.js → chunk-IPJD7WJH.js} +2 -2
  52. package/dist/{chunk-KQAFEZQX.js → chunk-IPLYGWQF.js} +5 -5
  53. package/dist/{chunk-MDYG7VI7.js → chunk-IREVVFTM.js} +10 -1
  54. package/dist/{chunk-MDYG7VI7.js.map → chunk-IREVVFTM.js.map} +1 -1
  55. package/dist/{chunk-RKNJBZ55.js → chunk-JBPKEARU.js} +4 -4
  56. package/dist/{chunk-WROKD3XC.js → chunk-K7I24ZO2.js} +24 -24
  57. package/dist/{chunk-Z7KILAOU.js → chunk-KO6OL4I7.js} +20 -20
  58. package/dist/{chunk-SB6CQTKP.js → chunk-MCV2DD6F.js} +2 -2
  59. package/dist/{chunk-3FC6LW6T.js → chunk-MRFVMSTR.js} +2 -2
  60. package/dist/{chunk-WDXCNJSF.js → chunk-MXZWKOOR.js} +2 -2
  61. package/dist/{chunk-XKUKJIOY.js → chunk-NCRDCTEJ.js} +7 -7
  62. package/dist/{chunk-RGNEARXW.js → chunk-NUZ3N445.js} +7 -7
  63. package/dist/{chunk-CP2NZQLT.js → chunk-OOO7ZKOD.js} +6 -6
  64. package/dist/{chunk-PHZKALOE.js → chunk-QFG23CRE.js} +2 -2
  65. package/dist/{chunk-UDJLF3BO.js → chunk-QLRYXOAD.js} +2 -2
  66. package/dist/{chunk-ZU7N3S6V.js → chunk-QNG35H27.js} +2 -2
  67. package/dist/{chunk-A4HH2EWA.js → chunk-QVG4LAQO.js} +2 -2
  68. package/dist/{chunk-54PVJDO5.js → chunk-SAC5V6JT.js} +2 -2
  69. package/dist/{chunk-CE6CBRCV.js → chunk-TJ5IIQIR.js} +56 -45
  70. package/dist/chunk-TJ5IIQIR.js.map +1 -0
  71. package/dist/{chunk-OMKUJTVJ.js → chunk-TSGREOYY.js} +5 -5
  72. package/dist/{chunk-2N6UNJSX.js → chunk-U2OBZSGG.js} +2 -2
  73. package/dist/{chunk-BKAMHZYR.js → chunk-UOCLRM74.js} +2 -2
  74. package/dist/{chunk-A7UZR6RA.js → chunk-UTUYAPLY.js} +14 -1
  75. package/dist/chunk-UTUYAPLY.js.map +1 -0
  76. package/dist/{chunk-TYF3D4MS.js → chunk-UUMYB3FR.js} +2 -2
  77. package/dist/{chunk-CUNTLEJP.js → chunk-VFVG4NS2.js} +30 -9
  78. package/dist/chunk-VFVG4NS2.js.map +1 -0
  79. package/dist/{chunk-46URPRE6.js → chunk-VH2DHBHG.js} +2 -2
  80. package/dist/{chunk-UD5OKH4J.js → chunk-W4ELOUNX.js} +2 -2
  81. package/dist/{chunk-GR77Z2BM.js → chunk-WIKNVFBS.js} +2 -2
  82. package/dist/{chunk-67MMWC74.js → chunk-ZLXGFAML.js} +2 -2
  83. package/dist/{cli-BkDp6WNi.d.ts → cli-CrSW_KRq.d.ts} +3 -3
  84. package/dist/cli.d.ts +6 -6
  85. package/dist/cli.js +38 -38
  86. package/dist/compounding/engine.d.ts +1 -1
  87. package/dist/compounding/engine.js +5 -5
  88. package/dist/compounding/preference-consolidator.d.ts +1 -1
  89. package/dist/compression-optimizer.d.ts +1 -1
  90. package/dist/config.d.ts +1 -1
  91. package/dist/config.js +1 -1
  92. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  93. package/dist/connectors/codex-materialize-runner.js +5 -5
  94. package/dist/connectors/codex-materialize.d.ts +1 -1
  95. package/dist/connectors/index.d.ts +1 -1
  96. package/dist/connectors/index.js +5 -5
  97. package/dist/consolidation-provenance-check.d.ts +1 -1
  98. package/dist/consolidation-undo.d.ts +1 -1
  99. package/dist/contradiction/index.d.ts +1 -1
  100. package/dist/contradiction/index.js +4 -4
  101. package/dist/conversation-index/backend.d.ts +1 -1
  102. package/dist/conversation-index/backend.js +2 -2
  103. package/dist/conversation-index/chunker.d.ts +1 -1
  104. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  105. package/dist/conversation-index/indexer.d.ts +1 -1
  106. package/dist/conversation-index/search.d.ts +1 -1
  107. package/dist/day-summary.d.ts +1 -1
  108. package/dist/delinearize.d.ts +1 -1
  109. package/dist/direct-answer-wiring.d.ts +1 -1
  110. package/dist/direct-answer.d.ts +1 -1
  111. package/dist/embedding-fallback.d.ts +1 -1
  112. package/dist/enrichment/index.d.ts +1 -1
  113. package/dist/entity-retrieval.d.ts +1 -1
  114. package/dist/entity-retrieval.js +5 -5
  115. package/dist/entity-schema.d.ts +1 -1
  116. package/dist/event-time.d.ts +35 -0
  117. package/dist/event-time.js +325 -0
  118. package/dist/event-time.js.map +1 -0
  119. package/dist/explicit-capture.d.ts +4 -4
  120. package/dist/extraction-judge-telemetry.d.ts +1 -1
  121. package/dist/extraction-judge-training.d.ts +1 -1
  122. package/dist/extraction-judge.d.ts +1 -1
  123. package/dist/extraction-judge.js +3 -3
  124. package/dist/extraction.d.ts +1 -1
  125. package/dist/extraction.js +3 -3
  126. package/dist/fallback-llm.d.ts +1 -1
  127. package/dist/fallback-llm.js +2 -2
  128. package/dist/identity-continuity.d.ts +1 -1
  129. package/dist/importance.d.ts +1 -1
  130. package/dist/index.d.ts +9 -9
  131. package/dist/index.js +72 -72
  132. package/dist/intent.d.ts +1 -1
  133. package/dist/lcm/engine.d.ts +1 -1
  134. package/dist/lcm/index.d.ts +1 -1
  135. package/dist/lcm/tools.d.ts +1 -1
  136. package/dist/lifecycle.d.ts +1 -1
  137. package/dist/live-connectors-runner.d.ts +1 -1
  138. package/dist/local-llm.d.ts +1 -1
  139. package/dist/maintenance/memory-governance.d.ts +1 -1
  140. package/dist/maintenance/memory-governance.js +5 -5
  141. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +5 -5
  142. package/dist/maintenance/rebuild-memory-projection.js +6 -6
  143. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  144. package/dist/memory-action-policy.d.ts +1 -1
  145. package/dist/memory-cache.d.ts +1 -1
  146. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  147. package/dist/memory-projection-store.d.ts +1 -1
  148. package/dist/memory-provenance.d.ts +1 -1
  149. package/dist/memory-worth-outcomes.d.ts +1 -1
  150. package/dist/models-json.d.ts +1 -1
  151. package/dist/namespaces/migrate.d.ts +2 -2
  152. package/dist/namespaces/migrate.js +10 -10
  153. package/dist/namespaces/principal.d.ts +1 -1
  154. package/dist/namespaces/search.d.ts +1 -1
  155. package/dist/namespaces/search.js +4 -4
  156. package/dist/namespaces/storage.d.ts +2 -2
  157. package/dist/namespaces/storage.js +5 -5
  158. package/dist/native-knowledge.d.ts +1 -1
  159. package/dist/operator-toolkit.d.ts +1 -1
  160. package/dist/operator-toolkit.js +14 -14
  161. package/dist/{orchestrator-B7ixmUkP.d.ts → orchestrator-DvswGK76.d.ts} +3 -3
  162. package/dist/orchestrator.d.ts +4 -4
  163. package/dist/orchestrator.js +34 -34
  164. package/dist/patterns-cli.d.ts +1 -1
  165. package/dist/policy-runtime.d.ts +1 -1
  166. package/dist/provenance.d.ts +1 -1
  167. package/dist/qmd-recall-cache.d.ts +1 -1
  168. package/dist/qmd.d.ts +1 -1
  169. package/dist/recall-disclosure-escalation.d.ts +1 -1
  170. package/dist/recall-explain-renderer.d.ts +1 -1
  171. package/dist/recall-explain-renderer.js +3 -3
  172. package/dist/recall-planner-llm.d.ts +1 -1
  173. package/dist/recall-planner-llm.js +2 -2
  174. package/dist/recall-state.d.ts +1 -1
  175. package/dist/recall-tag-filter.d.ts +1 -1
  176. package/dist/recall-xray-cli.d.ts +1 -1
  177. package/dist/recall-xray-cli.js +4 -4
  178. package/dist/recall-xray-renderer.d.ts +1 -1
  179. package/dist/recall-xray-renderer.js +3 -3
  180. package/dist/recall-xray.d.ts +1 -1
  181. package/dist/recall-xray.js +2 -2
  182. package/dist/resolve-auth-token.d.ts +1 -1
  183. package/dist/resume-bundles.js +2 -2
  184. package/dist/retrieval-agents.d.ts +1 -1
  185. package/dist/retrieval-tiers.d.ts +1 -1
  186. package/dist/routing/engine.d.ts +1 -1
  187. package/dist/routing/store.d.ts +1 -1
  188. package/dist/search/embed-helper.d.ts +1 -1
  189. package/dist/search/factory.d.ts +1 -1
  190. package/dist/search/factory.js +3 -3
  191. package/dist/search/index.d.ts +1 -1
  192. package/dist/search/index.js +3 -3
  193. package/dist/search/lancedb-backend.d.ts +1 -1
  194. package/dist/search/meilisearch-backend.d.ts +1 -1
  195. package/dist/search/noop-backend.d.ts +1 -1
  196. package/dist/search/orama-backend.d.ts +1 -1
  197. package/dist/search/port.d.ts +1 -1
  198. package/dist/search/remote-backend.d.ts +1 -1
  199. package/dist/{semantic-consolidation-CWch5uM7.d.ts → semantic-consolidation-D5U0Mrdb.d.ts} +1 -1
  200. package/dist/semantic-consolidation.d.ts +2 -2
  201. package/dist/semantic-consolidation.js +6 -6
  202. package/dist/semantic-rule-promotion.js +5 -5
  203. package/dist/semantic-rule-verifier.d.ts +1 -1
  204. package/dist/semantic-rule-verifier.js +5 -5
  205. package/dist/session-observer-bands.d.ts +1 -1
  206. package/dist/session-observer-state.d.ts +1 -1
  207. package/dist/shared-context/manager.d.ts +1 -1
  208. package/dist/signal.d.ts +1 -1
  209. package/dist/storage.d.ts +3 -1
  210. package/dist/storage.js +4 -4
  211. package/dist/summarizer.d.ts +1 -1
  212. package/dist/summarizer.js +3 -3
  213. package/dist/summary-snapshot.d.ts +1 -1
  214. package/dist/temporal-supersession.d.ts +1 -1
  215. package/dist/temporal-supersession.js +2 -2
  216. package/dist/temporal-validity.d.ts +22 -2
  217. package/dist/temporal-validity.js +3 -1
  218. package/dist/threading.d.ts +1 -1
  219. package/dist/tier-migration.d.ts +1 -1
  220. package/dist/tier-routing.d.ts +1 -1
  221. package/dist/topics.d.ts +1 -1
  222. package/dist/transcript.d.ts +1 -1
  223. package/dist/transfer/autodetect.js +1 -1
  224. package/dist/transfer/backup.js +1 -1
  225. package/dist/transfer/capsule-export.js +2 -2
  226. package/dist/{types-Dm5xxVrr.d.ts → types-2NoBoRBM.d.ts} +38 -0
  227. package/dist/types.d.ts +1 -1
  228. package/dist/types.js +1 -1
  229. package/dist/utility-runtime.d.ts +1 -1
  230. package/dist/verified-recall.js +5 -5
  231. package/package.json +2 -2
  232. package/src/bitemporal-frontmatter.test.ts +177 -0
  233. package/src/config.ts +13 -0
  234. package/src/event-time.test.ts +514 -0
  235. package/src/event-time.ts +548 -0
  236. package/src/orchestrator.ts +27 -1
  237. package/src/storage.ts +34 -0
  238. package/src/temporal-validity.ts +34 -0
  239. package/src/types.ts +38 -0
  240. package/dist/chunk-A7UZR6RA.js.map +0 -1
  241. package/dist/chunk-CE6CBRCV.js.map +0 -1
  242. package/dist/chunk-CUNTLEJP.js.map +0 -1
  243. package/dist/chunk-NGFEWFNK.js.map +0 -1
  244. /package/dist/{auto-sync-NUQWSFQD.js.map → auto-sync-RWXT6P5M.js.map} +0 -0
  245. /package/dist/{chunk-GTDH3IUH.js.map → chunk-2D27ODNX.js.map} +0 -0
  246. /package/dist/{chunk-3K37VPM3.js.map → chunk-3BRA3N5A.js.map} +0 -0
  247. /package/dist/{chunk-RTFAZOIR.js.map → chunk-3VVH6ZQW.js.map} +0 -0
  248. /package/dist/{chunk-FIVDN2SM.js.map → chunk-4RGWCRIJ.js.map} +0 -0
  249. /package/dist/{chunk-AGJH5ISO.js.map → chunk-5KBNNUXS.js.map} +0 -0
  250. /package/dist/{chunk-X7RLU5CR.js.map → chunk-66HROLW5.js.map} +0 -0
  251. /package/dist/{chunk-NSVXK7M5.js.map → chunk-7UVDIWLL.js.map} +0 -0
  252. /package/dist/{chunk-UPIBE2DK.js.map → chunk-ADUAF5EV.js.map} +0 -0
  253. /package/dist/{chunk-LLONI6PY.js.map → chunk-AFWEUTMS.js.map} +0 -0
  254. /package/dist/{chunk-CWE74HRG.js.map → chunk-D3DNGQNQ.js.map} +0 -0
  255. /package/dist/{chunk-ZUDM75KG.js.map → chunk-DCWIQFNA.js.map} +0 -0
  256. /package/dist/{chunk-OBXTMFZQ.js.map → chunk-ECZPWSB5.js.map} +0 -0
  257. /package/dist/{chunk-BFVPIKDY.js.map → chunk-GCOSQBQ2.js.map} +0 -0
  258. /package/dist/{chunk-LXIEXSHU.js.map → chunk-IPJD7WJH.js.map} +0 -0
  259. /package/dist/{chunk-KQAFEZQX.js.map → chunk-IPLYGWQF.js.map} +0 -0
  260. /package/dist/{chunk-RKNJBZ55.js.map → chunk-JBPKEARU.js.map} +0 -0
  261. /package/dist/{chunk-WROKD3XC.js.map → chunk-K7I24ZO2.js.map} +0 -0
  262. /package/dist/{chunk-Z7KILAOU.js.map → chunk-KO6OL4I7.js.map} +0 -0
  263. /package/dist/{chunk-SB6CQTKP.js.map → chunk-MCV2DD6F.js.map} +0 -0
  264. /package/dist/{chunk-3FC6LW6T.js.map → chunk-MRFVMSTR.js.map} +0 -0
  265. /package/dist/{chunk-WDXCNJSF.js.map → chunk-MXZWKOOR.js.map} +0 -0
  266. /package/dist/{chunk-XKUKJIOY.js.map → chunk-NCRDCTEJ.js.map} +0 -0
  267. /package/dist/{chunk-RGNEARXW.js.map → chunk-NUZ3N445.js.map} +0 -0
  268. /package/dist/{chunk-CP2NZQLT.js.map → chunk-OOO7ZKOD.js.map} +0 -0
  269. /package/dist/{chunk-PHZKALOE.js.map → chunk-QFG23CRE.js.map} +0 -0
  270. /package/dist/{chunk-UDJLF3BO.js.map → chunk-QLRYXOAD.js.map} +0 -0
  271. /package/dist/{chunk-ZU7N3S6V.js.map → chunk-QNG35H27.js.map} +0 -0
  272. /package/dist/{chunk-A4HH2EWA.js.map → chunk-QVG4LAQO.js.map} +0 -0
  273. /package/dist/{chunk-54PVJDO5.js.map → chunk-SAC5V6JT.js.map} +0 -0
  274. /package/dist/{chunk-OMKUJTVJ.js.map → chunk-TSGREOYY.js.map} +0 -0
  275. /package/dist/{chunk-2N6UNJSX.js.map → chunk-U2OBZSGG.js.map} +0 -0
  276. /package/dist/{chunk-BKAMHZYR.js.map → chunk-UOCLRM74.js.map} +0 -0
  277. /package/dist/{chunk-TYF3D4MS.js.map → chunk-UUMYB3FR.js.map} +0 -0
  278. /package/dist/{chunk-46URPRE6.js.map → chunk-VH2DHBHG.js.map} +0 -0
  279. /package/dist/{chunk-UD5OKH4J.js.map → chunk-W4ELOUNX.js.map} +0 -0
  280. /package/dist/{chunk-GR77Z2BM.js.map → chunk-WIKNVFBS.js.map} +0 -0
  281. /package/dist/{chunk-67MMWC74.js.map → chunk-ZLXGFAML.js.map} +0 -0
@@ -0,0 +1,514 @@
1
+ /**
2
+ * Issue #1578 PR 1 — event-time resolver table tests.
3
+ *
4
+ * The resolver is pure: (expression, anchor) in, interval out. These tests
5
+ * pin the supported shapes (absolute, relative, since/until, yesterday/today/
6
+ * tomorrow, last/this/next period, month+year, season) and the failure modes
7
+ * (unresolvable garbage, bad anchor, Date overflow). Per the issue's PR-1
8
+ * guide: ≥25 expressions including timezone-edge anchors, leap day, year-
9
+ * boundary "last December", and unresolvable garbage.
10
+ *
11
+ * Interval semantics are `[validFrom, validUntil)` — inclusive start,
12
+ * exclusive end (AGENTS.md §23). Date-only END bounds convert to
13
+ * start-of-next-day so the end date itself is excluded.
14
+ */
15
+ import test from "node:test";
16
+ import assert from "node:assert/strict";
17
+ import { resolveEventTime } from "./event-time.js";
18
+
19
+ // Anchor fixed at 2026-06-15T12:00:00.000Z (a Monday in mid-June 2026).
20
+ const ANCHOR = "2026-06-15T12:00:00.000Z";
21
+
22
+ function dayMs(iso: string): number {
23
+ return Date.parse(iso);
24
+ }
25
+
26
+ test("absolute ISO date resolves validFrom at start-of-day UTC", () => {
27
+ const r = resolveEventTime("2026-03-01", ANCHOR);
28
+ assert.equal(r.ok, true);
29
+ assert.equal(r.validFrom, "2026-03-01T00:00:00.000Z");
30
+ assert.equal(r.validUntil, undefined);
31
+ });
32
+
33
+ test("absolute ISO datetime resolves validFrom verbatim", () => {
34
+ const r = resolveEventTime("2026-03-01T09:30:00Z", ANCHOR);
35
+ assert.equal(r.ok, true);
36
+ assert.equal(r.validFrom, "2026-03-01T09:30:00.000Z");
37
+ });
38
+
39
+ test("since <date> resolves validFrom only", () => {
40
+ const r = resolveEventTime("since 2024-01-15", ANCHOR);
41
+ assert.equal(r.ok, true);
42
+ assert.equal(r.validFrom, "2024-01-15T00:00:00.000Z");
43
+ assert.equal(r.validUntil, undefined);
44
+ });
45
+
46
+ test("until <date> resolves validUntil to start-of-NEXT-day (exclusive end)", () => {
47
+ // "until 2026-03-01" must exclude March 1 itself → exclusive bound at Mar 2.
48
+ const r = resolveEventTime("until 2026-03-01", ANCHOR);
49
+ assert.equal(r.ok, true);
50
+ assert.equal(r.validUntil, "2026-03-02T00:00:00.000Z");
51
+ assert.equal(r.validFrom, undefined);
52
+ });
53
+
54
+ test("through <date> is an alias for until (exclusive end)", () => {
55
+ const r = resolveEventTime("through 2026-03-01", ANCHOR);
56
+ assert.equal(r.ok, true);
57
+ assert.equal(r.validUntil, "2026-03-02T00:00:00.000Z");
58
+ });
59
+
60
+ test("until <datetime> uses the datetime verbatim (not start-of-next-day)", () => {
61
+ const r = resolveEventTime("until 2026-03-01T18:00:00Z", ANCHOR);
62
+ assert.equal(r.ok, true);
63
+ assert.equal(r.validUntil, "2026-03-01T18:00:00.000Z");
64
+ });
65
+
66
+ test("today resolves to the anchor's start-of-day", () => {
67
+ const r = resolveEventTime("today", ANCHOR);
68
+ assert.equal(r.ok, true);
69
+ assert.equal(r.validFrom, "2026-06-15T00:00:00.000Z");
70
+ });
71
+
72
+ test("yesterday resolves to the previous calendar day", () => {
73
+ const r = resolveEventTime("yesterday", ANCHOR);
74
+ assert.equal(r.ok, true);
75
+ assert.equal(r.validFrom, "2026-06-14T00:00:00.000Z");
76
+ });
77
+
78
+ test("tomorrow resolves to the next calendar day", () => {
79
+ const r = resolveEventTime("tomorrow", ANCHOR);
80
+ assert.equal(r.ok, true);
81
+ assert.equal(r.validFrom, "2026-06-16T00:00:00.000Z");
82
+ });
83
+
84
+ test("last week resolves to 7 days before anchor", () => {
85
+ const r = resolveEventTime("last week", ANCHOR);
86
+ assert.equal(r.ok, true);
87
+ assert.equal(r.validFrom, "2026-06-08T00:00:00.000Z");
88
+ });
89
+
90
+ test("this month resolves to the 1st of the anchor's month", () => {
91
+ const r = resolveEventTime("this month", ANCHOR);
92
+ assert.equal(r.ok, true);
93
+ assert.equal(r.validFrom, "2026-06-01T00:00:00.000Z");
94
+ });
95
+
96
+ test("last month resolves to the 1st of the previous month", () => {
97
+ const r = resolveEventTime("last month", ANCHOR);
98
+ assert.equal(r.ok, true);
99
+ assert.equal(r.validFrom, "2026-05-01T00:00:00.000Z");
100
+ });
101
+
102
+ test("next year resolves to Jan 1 of the next year", () => {
103
+ const r = resolveEventTime("next year", ANCHOR);
104
+ assert.equal(r.ok, true);
105
+ assert.equal(r.validFrom, "2027-01-01T00:00:00.000Z");
106
+ });
107
+
108
+ test("last December crosses the year boundary (anchor in June 2026)", () => {
109
+ // Anchor is June 2026; "last December" = December 2025.
110
+ const r = resolveEventTime("last December", ANCHOR);
111
+ assert.equal(r.ok, true);
112
+ assert.equal(r.validFrom, "2025-12-01T00:00:00.000Z");
113
+ });
114
+
115
+ test("next March resolves forward across the year boundary", () => {
116
+ // Anchor June 2026; "next March" = March 2027.
117
+ const r = resolveEventTime("next March", ANCHOR);
118
+ assert.equal(r.ok, true);
119
+ assert.equal(r.validFrom, "2027-03-01T00:00:00.000Z");
120
+ });
121
+
122
+ test("this Q3 resolves to July 1 of the anchor's year", () => {
123
+ const r = resolveEventTime("this Q3", ANCHOR);
124
+ assert.equal(r.ok, true);
125
+ assert.equal(r.validFrom, "2026-07-01T00:00:00.000Z");
126
+ });
127
+
128
+ test("bare month+year resolves to the 1st of that month", () => {
129
+ const r = resolveEventTime("March 2025", ANCHOR);
130
+ assert.equal(r.ok, true);
131
+ assert.equal(r.validFrom, "2025-03-01T00:00:00.000Z");
132
+ });
133
+
134
+ test("abbreviated month+year resolves (Dec 2024)", () => {
135
+ const r = resolveEventTime("Dec 2024", ANCHOR);
136
+ assert.equal(r.ok, true);
137
+ assert.equal(r.validFrom, "2024-12-01T00:00:00.000Z");
138
+ });
139
+
140
+ test("leap day resolves correctly (Feb 29 2024)", () => {
141
+ const r = resolveEventTime("2024-02-29", ANCHOR);
142
+ assert.equal(r.ok, true);
143
+ assert.equal(r.validFrom, "2024-02-29T00:00:00.000Z");
144
+ });
145
+
146
+ test("timezone-edge anchor: 23:59 UTC vs 00:00 UTC do not shift the day", () => {
147
+ // "today" anchored at 23:59:59 UTC must still be the same UTC day.
148
+ const late = resolveEventTime("today", "2026-06-15T23:59:59.000Z");
149
+ assert.equal(late.validFrom, "2026-06-15T00:00:00.000Z");
150
+ // Anchored at 00:00:00 UTC — same day.
151
+ const early = resolveEventTime("today", "2026-06-15T00:00:00.000Z");
152
+ assert.equal(early.validFrom, "2026-06-15T00:00:00.000Z");
153
+ });
154
+
155
+ test("resolution is anchored to the source turn, never Date.now()", () => {
156
+ // "yesterday" against a 2025 anchor must yield a 2025 date, not today's
157
+ // yesterday — this is the replay/import correctness guarantee.
158
+ const r = resolveEventTime("yesterday", "2025-01-10T08:00:00.000Z");
159
+ assert.equal(r.ok, true);
160
+ assert.equal(r.validFrom, "2025-01-09T00:00:00.000Z");
161
+ });
162
+
163
+ // ── Failure modes ─────────────────────────────────────────────────────────
164
+
165
+ test("empty / whitespace expression → ok:false", () => {
166
+ assert.equal(resolveEventTime("", ANCHOR).ok, false);
167
+ assert.equal(resolveEventTime(" ", ANCHOR).ok, false);
168
+ assert.equal(resolveEventTime(undefined, ANCHOR).ok, false);
169
+ assert.equal(resolveEventTime(null, ANCHOR).ok, false);
170
+ });
171
+
172
+ test("unresolvable garbage → ok:false (no partial output)", () => {
173
+ const r = resolveEventTime("sometime maybe", ANCHOR);
174
+ assert.equal(r.ok, false);
175
+ assert.equal(r.validFrom, undefined);
176
+ assert.equal(r.validUntil, undefined);
177
+ });
178
+
179
+ test("invalid month name → ok:false", () => {
180
+ const r = resolveEventTime("last Smarch", ANCHOR);
181
+ assert.equal(r.ok, false);
182
+ });
183
+
184
+ test("overflowed date (Feb 30) → ok:false, never Invalid Date", () => {
185
+ const r = resolveEventTime("2026-02-30", ANCHOR);
186
+ assert.equal(r.ok, false);
187
+ assert.equal(r.validFrom, undefined);
188
+ });
189
+
190
+ test("malformed anchor timestamp → ok:false (no silent default)", () => {
191
+ const r = resolveEventTime("2026-03-01", "not-a-timestamp");
192
+ assert.equal(r.ok, false);
193
+ });
194
+
195
+ test("since <garbage> → ok:false (does not fall back to anchor)", () => {
196
+ const r = resolveEventTime("since forever", ANCHOR);
197
+ assert.equal(r.ok, false);
198
+ });
199
+
200
+ test("until <invalid month> → ok:false", () => {
201
+ const r = resolveEventTime("until Smarch", ANCHOR);
202
+ assert.equal(r.ok, false);
203
+ });
204
+
205
+ test("case-insensitive: LAST MARCH resolves like last March", () => {
206
+ const r = resolveEventTime("LAST MARCH", ANCHOR);
207
+ assert.equal(r.ok, true);
208
+ // Anchor June 2026 → last March = March 2026.
209
+ assert.equal(r.validFrom, "2026-03-01T00:00:00.000Z");
210
+ });
211
+
212
+ test("until <month-name> end bound lands on start of following month", () => {
213
+ // "until March" against a June anchor → exclusive end at April 1.
214
+ const r = resolveEventTime("until March", ANCHOR);
215
+ assert.equal(r.ok, true);
216
+ assert.equal(r.validUntil, "2026-04-01T00:00:00.000Z");
217
+ });
218
+
219
+ test("interval is half-open: validFrom inclusive, validUntil exclusive", () => {
220
+ // A fact valid "since 2026-03-01" "until 2026-03-01" has a zero-width
221
+ // interval — the two bounds are equal, meaning nothing is inside [a, a).
222
+ const from = resolveEventTime("since 2026-03-01", ANCHOR).validFrom!;
223
+ const until = resolveEventTime("until 2026-03-01", ANCHOR).validUntil!;
224
+ assert.equal(dayMs(until) > dayMs(from), true, "exclusive end must exceed inclusive start");
225
+ });
226
+
227
+ // ── Review fixes (cursor quarter + codex month-year after since) ─────────
228
+
229
+ test("last quarter moves the quarter INDEX back, not the year (cursor review)", () => {
230
+ // Anchor June 2026 = Q2. "last quarter" must be Q1 = Jan 1 2026, not Apr 1.
231
+ const r = resolveEventTime("last quarter", ANCHOR);
232
+ assert.equal(r.ok, true);
233
+ assert.equal(r.validFrom, "2026-01-01T00:00:00.000Z");
234
+ });
235
+
236
+ test("next quarter moves the quarter INDEX forward (cursor review)", () => {
237
+ // Anchor June 2026 = Q2. "next quarter" must be Q3 = July 1 2026.
238
+ const r = resolveEventTime("next quarter", ANCHOR);
239
+ assert.equal(r.ok, true);
240
+ assert.equal(r.validFrom, "2026-07-01T00:00:00.000Z");
241
+ });
242
+
243
+ test("this quarter stays the current quarter (Q2 = April)", () => {
244
+ const r = resolveEventTime("this quarter", ANCHOR);
245
+ assert.equal(r.ok, true);
246
+ assert.equal(r.validFrom, "2026-04-01T00:00:00.000Z");
247
+ });
248
+
249
+ test("last quarter wraps the year boundary (anchor Q1 → prev Q4 prior year)", () => {
250
+ // Anchor Feb 2026 = Q1. "last quarter" must be Q4 2025 = Oct 1 2025.
251
+ const r = resolveEventTime("last quarter", "2026-02-15T12:00:00.000Z");
252
+ assert.equal(r.ok, true);
253
+ assert.equal(r.validFrom, "2025-10-01T00:00:00.000Z");
254
+ });
255
+
256
+ test("since <month> <year> resolves with the explicit year (codex review)", () => {
257
+ const r = resolveEventTime("since March 2025", ANCHOR);
258
+ assert.equal(r.ok, true);
259
+ assert.equal(r.validFrom, "2025-03-01T00:00:00.000Z");
260
+ });
261
+
262
+ test("since <season> <year> resolves (codex review)", () => {
263
+ const r = resolveEventTime("since spring 2024", ANCHOR);
264
+ assert.equal(r.ok, true);
265
+ assert.equal(r.validFrom, "2024-03-01T00:00:00.000Z");
266
+ });
267
+
268
+ test("until <month> <year> exclusive end is start of following month (codex review)", () => {
269
+ const r = resolveEventTime("until March 2025", ANCHOR);
270
+ assert.equal(r.ok, true);
271
+ assert.equal(r.validUntil, "2025-04-01T00:00:00.000Z");
272
+ });
273
+
274
+ test("since <bare year> resolves to January 1 of that year (codex review r2)", () => {
275
+ const r = resolveEventTime("since 2024", ANCHOR);
276
+ assert.equal(r.ok, true);
277
+ assert.equal(r.validFrom, "2024-01-01T00:00:00.000Z");
278
+ });
279
+
280
+ test("bare four-digit year resolves to January 1 (codex review r2)", () => {
281
+ const r = resolveEventTime("2023", ANCHOR);
282
+ assert.equal(r.ok, true);
283
+ assert.equal(r.validFrom, "2023-01-01T00:00:00.000Z");
284
+ });
285
+
286
+ test("until <bare year> exclusive end is January 1 of the FOLLOWING year (codex review r2)", () => {
287
+ const r = resolveEventTime("until 2024", ANCHOR);
288
+ assert.equal(r.ok, true);
289
+ assert.equal(r.validUntil, "2025-01-01T00:00:00.000Z");
290
+ });
291
+
292
+ test("until end of <month> strips the prefix and resolves (codex review r2)", () => {
293
+ const r = resolveEventTime("until end of March", ANCHOR);
294
+ assert.equal(r.ok, true);
295
+ // "end of March" backwards-looking from June 2026 anchor → exclusive end
296
+ // at the start of the month AFTER March 2026 = April 1 2026.
297
+ assert.equal(r.validUntil, "2026-04-01T00:00:00.000Z");
298
+ });
299
+
300
+ test("until end of <month> <year> strips the prefix and resolves (codex review r2)", () => {
301
+ const r = resolveEventTime("until end of March 2025", ANCHOR);
302
+ assert.equal(r.ok, true);
303
+ assert.equal(r.validUntil, "2025-04-01T00:00:00.000Z");
304
+ });
305
+
306
+ test("last Q2 from May rolls back a year — anchor inside target quarter (codex review r2)", () => {
307
+ // Anchor May 2026 is inside Q2. "last Q2" must be Q2 2025 = April 1 2025.
308
+ const r = resolveEventTime("last Q2", "2026-05-15T12:00:00.000Z");
309
+ assert.equal(r.ok, true);
310
+ assert.equal(r.validFrom, "2025-04-01T00:00:00.000Z");
311
+ });
312
+
313
+ test("last Q2 from June rolls back a year — anchor in last month of target quarter (codex review r2)", () => {
314
+ const r = resolveEventTime("last Q2", "2026-06-15T12:00:00.000Z");
315
+ assert.equal(r.ok, true);
316
+ assert.equal(r.validFrom, "2025-04-01T00:00:00.000Z");
317
+ });
318
+
319
+ test("last Q2 from March stays current year — target quarter not yet started (codex review r2)", () => {
320
+ // Anchor March 2026. Q2 2026 hasn't started, so "last Q2" = Q2 2025.
321
+ const r = resolveEventTime("last Q2", "2026-03-15T12:00:00.000Z");
322
+ assert.equal(r.ok, true);
323
+ assert.equal(r.validFrom, "2025-04-01T00:00:00.000Z");
324
+ });
325
+
326
+ test("last Q2 from July stays current year — target quarter already completed (codex review r2)", () => {
327
+ // Anchor July 2026. Q2 2026 ended, so "last Q2" = Q2 2026 = April 1 2026.
328
+ const r = resolveEventTime("last Q2", "2026-07-15T12:00:00.000Z");
329
+ assert.equal(r.ok, true);
330
+ assert.equal(r.validFrom, "2026-04-01T00:00:00.000Z");
331
+ });
332
+
333
+ test("next Q2 from May rolls forward a year — anchor inside target quarter (codex review r2)", () => {
334
+ const r = resolveEventTime("next Q2", "2026-05-15T12:00:00.000Z");
335
+ assert.equal(r.ok, true);
336
+ assert.equal(r.validFrom, "2027-04-01T00:00:00.000Z");
337
+ });
338
+
339
+ test("until <current month> does not roll back a year (cursor review r2)", () => {
340
+ // Anchor mid-March 2026. "until March" should end at the current month's end.
341
+ const r = resolveEventTime("until March", "2026-03-15T12:00:00.000Z");
342
+ assert.equal(r.ok, true);
343
+ assert.equal(r.validUntil, "2026-04-01T00:00:00.000Z");
344
+ });
345
+
346
+ test("until <past month> rolls back correctly (cursor review r2 regression)", () => {
347
+ // Anchor June 2026. "until March" → March already ended this year → April 1 2026.
348
+ const r = resolveEventTime("until March", "2026-06-15T12:00:00.000Z");
349
+ assert.equal(r.ok, true);
350
+ assert.equal(r.validUntil, "2026-04-01T00:00:00.000Z");
351
+ });
352
+
353
+ test("until <future month> rolls back a year (cursor review r2 regression)", () => {
354
+ // Anchor January 2026. "until March" → March hasn't happened yet → April 1 2025.
355
+ const r = resolveEventTime("until March", "2026-01-15T12:00:00.000Z");
356
+ assert.equal(r.ok, true);
357
+ assert.equal(r.validUntil, "2025-04-01T00:00:00.000Z");
358
+ });
359
+
360
+ test("this winter from January rolls back to previous December (codex review r2)", () => {
361
+ const r = resolveEventTime("this winter", "2026-01-15T00:00:00.000Z");
362
+ assert.equal(r.ok, true);
363
+ assert.equal(r.validFrom, "2025-12-01T00:00:00.000Z");
364
+ });
365
+
366
+ test("this winter from February rolls back to previous December (codex review r2)", () => {
367
+ const r = resolveEventTime("this winter", "2026-02-15T00:00:00.000Z");
368
+ assert.equal(r.ok, true);
369
+ assert.equal(r.validFrom, "2025-12-01T00:00:00.000Z");
370
+ });
371
+
372
+ test("this winter from December stays in the current year (codex review r2)", () => {
373
+ const r = resolveEventTime("this winter", "2026-12-15T00:00:00.000Z");
374
+ assert.equal(r.ok, true);
375
+ assert.equal(r.validFrom, "2026-12-01T00:00:00.000Z");
376
+ });
377
+
378
+ test("this spring from January stays in the current year (season rollback regression)", () => {
379
+ const r = resolveEventTime("this spring", "2026-01-15T00:00:00.000Z");
380
+ assert.equal(r.ok, true);
381
+ assert.equal(r.validFrom, "2026-03-01T00:00:00.000Z");
382
+ });
383
+
384
+ test("until <season> <year> advances by the full 3-month season (codex review r2)", () => {
385
+ const r = resolveEventTime("until spring 2025", ANCHOR);
386
+ assert.equal(r.ok, true);
387
+ assert.equal(r.validUntil, "2025-06-01T00:00:00.000Z");
388
+ });
389
+
390
+ test("through <season> <year> advances by the full 3-month season (codex review r2)", () => {
391
+ const r = resolveEventTime("through summer 2025", ANCHOR);
392
+ assert.equal(r.ok, true);
393
+ assert.equal(r.validUntil, "2025-09-01T00:00:00.000Z");
394
+ });
395
+
396
+ test("until <month> <year> still advances by 1 month (season fix regression)", () => {
397
+ const r = resolveEventTime("until March 2025", ANCHOR);
398
+ assert.equal(r.ok, true);
399
+ assert.equal(r.validUntil, "2025-04-01T00:00:00.000Z");
400
+ });
401
+
402
+ test("last summer from July rolls back a year — anchor inside season (codex review r2)", () => {
403
+ const r = resolveEventTime("last summer", "2026-07-15T12:00:00.000Z");
404
+ assert.equal(r.ok, true);
405
+ assert.equal(r.validFrom, "2025-06-01T00:00:00.000Z");
406
+ });
407
+
408
+ test("last summer from March rolls back — season not yet started (codex review r2)", () => {
409
+ const r = resolveEventTime("last summer", "2026-03-15T12:00:00.000Z");
410
+ assert.equal(r.ok, true);
411
+ assert.equal(r.validFrom, "2025-06-01T00:00:00.000Z");
412
+ });
413
+
414
+ test("last summer from September stays current year — season already passed (codex review r2)", () => {
415
+ const r = resolveEventTime("last summer", "2026-09-15T12:00:00.000Z");
416
+ assert.equal(r.ok, true);
417
+ assert.equal(r.validFrom, "2026-06-01T00:00:00.000Z");
418
+ });
419
+
420
+ test("last winter from January rolls back two years — inside winter tail (codex review r2)", () => {
421
+ const r = resolveEventTime("last winter", "2026-01-15T12:00:00.000Z");
422
+ assert.equal(r.ok, true);
423
+ assert.equal(r.validFrom, "2024-12-01T00:00:00.000Z");
424
+ });
425
+
426
+ test("since <bare month> from before that month rolls back (codex review r2)", () => {
427
+ // "since March" from January 2026 → March 2025 (most recent past March).
428
+ const r = resolveEventTime("since March", "2026-01-15T12:00:00.000Z");
429
+ assert.equal(r.ok, true);
430
+ assert.equal(r.validFrom, "2025-03-01T00:00:00.000Z");
431
+ });
432
+
433
+ test("since <bare month> from after that month stays current year (codex review r2 regression)", () => {
434
+ // "since March" from June 2026 → March 2026 (already happened).
435
+ const r = resolveEventTime("since March", "2026-06-15T12:00:00.000Z");
436
+ assert.equal(r.ok, true);
437
+ assert.equal(r.validFrom, "2026-03-01T00:00:00.000Z");
438
+ });
439
+
440
+ test("since <month> <year> with explicit year does not roll back (codex review r2 regression)", () => {
441
+ const r = resolveEventTime("since March 2026", "2026-01-15T12:00:00.000Z");
442
+ assert.equal(r.ok, true);
443
+ assert.equal(r.validFrom, "2026-03-01T00:00:00.000Z");
444
+ });
445
+
446
+ test("until <bare season> resolves end bound (codex review r2)", () => {
447
+ // "until spring" from June → spring ended May → exclusive end June 1 2026.
448
+ const r = resolveEventTime("until spring", "2026-06-15T12:00:00.000Z");
449
+ assert.equal(r.ok, true);
450
+ assert.equal(r.validUntil, "2026-06-01T00:00:00.000Z");
451
+ });
452
+
453
+ test("through <bare season> from inside the season does not roll back (codex review r2)", () => {
454
+ // "through summer" from July → we're in summer → end = Sep 1 2026.
455
+ const r = resolveEventTime("through summer", "2026-07-15T12:00:00.000Z");
456
+ assert.equal(r.ok, true);
457
+ assert.equal(r.validUntil, "2026-09-01T00:00:00.000Z");
458
+ });
459
+
460
+ test("until end of <season> strips prefix and resolves (codex review r2)", () => {
461
+ // "until end of spring" from June → same as "until spring".
462
+ const r = resolveEventTime("until end of spring", "2026-06-15T12:00:00.000Z");
463
+ assert.equal(r.ok, true);
464
+ assert.equal(r.validUntil, "2026-06-01T00:00:00.000Z");
465
+ });
466
+
467
+ test("until <bare season> from before the season rolls back (codex review r2)", () => {
468
+ // "until spring" from January → spring hasn't happened → last spring ended Jun 2025.
469
+ const r = resolveEventTime("until spring", "2026-01-15T12:00:00.000Z");
470
+ assert.equal(r.ok, true);
471
+ assert.equal(r.validUntil, "2025-06-01T00:00:00.000Z");
472
+ });
473
+
474
+ // ── Review r5c+ : bare winter end-bound wraparound + since-quarter pin ────
475
+
476
+ test("until <winter> from January resolves to the current winter's end (codex r5c)", () => {
477
+ // Anchor Jan 2026 sits in the winter that started Dec 2025. The exclusive
478
+ // end of THAT winter is March 1 2026 — not March 2027 (the next winter).
479
+ // Without the winter-wraparound year adjustment, the season start was built
480
+ // as Dec 2026, pushing the exclusive end a full year too far forward.
481
+ const r = resolveEventTime("until winter", "2026-01-15T12:00:00.000Z");
482
+ assert.equal(r.ok, true);
483
+ assert.equal(r.validUntil, "2026-03-01T00:00:00.000Z");
484
+ });
485
+
486
+ test("until <winter> from February resolves to the current winter's end (codex r5c)", () => {
487
+ const r = resolveEventTime("until winter", "2026-02-15T12:00:00.000Z");
488
+ assert.equal(r.ok, true);
489
+ assert.equal(r.validUntil, "2026-03-01T00:00:00.000Z");
490
+ });
491
+
492
+ test("through <winter> is an alias for until and wraps the same way (codex r5c)", () => {
493
+ const r = resolveEventTime("through winter", "2026-01-15T12:00:00.000Z");
494
+ assert.equal(r.ok, true);
495
+ assert.equal(r.validUntil, "2026-03-01T00:00:00.000Z");
496
+ });
497
+
498
+ test("until <winter> from December stays in the upcoming March (inside-winter regression)", () => {
499
+ // Anchor Dec 2026 is inside the winter that started Dec 2026; its exclusive
500
+ // end is March 1 2027. The wraparound fix must NOT over-roll this case.
501
+ const r = resolveEventTime("until winter", "2026-12-15T12:00:00.000Z");
502
+ assert.equal(r.ok, true);
503
+ assert.equal(r.validUntil, "2027-03-01T00:00:00.000Z");
504
+ });
505
+
506
+ test("since <quarter> rolls back like a bare month — 'since' is backwards-looking", () => {
507
+ // "since Q2" from January 2026: Q2 2026 (April) is still in the future, and
508
+ // "since" denotes an already-true interval, so the most recent PAST Q2 — Q2
509
+ // 2025 = April 1 2025 — is the correct validFrom. Quarter tokens are treated
510
+ // consistently with bare month/season names under the since-rollback guard.
511
+ const r = resolveEventTime("since Q2", "2026-01-15T12:00:00.000Z");
512
+ assert.equal(r.ok, true);
513
+ assert.equal(r.validFrom, "2025-04-01T00:00:00.000Z");
514
+ });