@murphai/murph 1.3.0 → 1.3.1

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 (2199) hide show
  1. package/CHANGELOG.md +3077 -0
  2. package/config.schema.json +650 -30
  3. package/dist/cli-entry.js +1 -1
  4. package/dist/cli-entry.js.map +1 -1
  5. package/dist/commands/automation.d.ts +143 -104
  6. package/dist/commands/automation.d.ts.map +1 -1
  7. package/dist/commands/automation.js +71 -13
  8. package/dist/commands/automation.js.map +1 -1
  9. package/dist/commands/batch.d.ts +3 -0
  10. package/dist/commands/batch.d.ts.map +1 -1
  11. package/dist/commands/batch.js +18 -45
  12. package/dist/commands/batch.js.map +1 -1
  13. package/dist/commands/clinical-imports.d.ts +103 -103
  14. package/dist/commands/command-factory-primitives.d.ts +1 -1
  15. package/dist/commands/command-factory-primitives.d.ts.map +1 -1
  16. package/dist/commands/command-factory-primitives.js +1 -1
  17. package/dist/commands/command-factory-primitives.js.map +1 -1
  18. package/dist/commands/commons.d.ts +59 -0
  19. package/dist/commands/commons.d.ts.map +1 -1
  20. package/dist/commands/commons.js +81 -1
  21. package/dist/commands/commons.js.map +1 -1
  22. package/dist/commands/document.d.ts.map +1 -1
  23. package/dist/commands/document.js +31 -1
  24. package/dist/commands/document.js.map +1 -1
  25. package/dist/commands/encounter.d.ts +128 -128
  26. package/dist/commands/event.d.ts.map +1 -1
  27. package/dist/commands/event.js +7 -1
  28. package/dist/commands/event.js.map +1 -1
  29. package/dist/commands/experiment-progress-card-image.d.ts.map +1 -1
  30. package/dist/commands/experiment-progress-card-image.js +13 -4
  31. package/dist/commands/experiment-progress-card-image.js.map +1 -1
  32. package/dist/commands/experiment.d.ts.map +1 -1
  33. package/dist/commands/experiment.js +6 -0
  34. package/dist/commands/experiment.js.map +1 -1
  35. package/dist/commands/export-intake-read-helpers.d.ts.map +1 -1
  36. package/dist/commands/export-intake-read-helpers.js +7 -3
  37. package/dist/commands/export-intake-read-helpers.js.map +1 -1
  38. package/dist/commands/food.d.ts.map +1 -1
  39. package/dist/commands/food.js +12 -4
  40. package/dist/commands/food.js.map +1 -1
  41. package/dist/commands/meal.d.ts.map +1 -1
  42. package/dist/commands/meal.js +54 -3
  43. package/dist/commands/meal.js.map +1 -1
  44. package/dist/commands/measurement.d.ts +1 -0
  45. package/dist/commands/measurement.d.ts.map +1 -1
  46. package/dist/commands/measurement.js +48 -2
  47. package/dist/commands/measurement.js.map +1 -1
  48. package/dist/commands/medication.d.ts +6 -6
  49. package/dist/commands/model.js +7 -11
  50. package/dist/commands/model.js.map +1 -1
  51. package/dist/commands/occurred-at-option.d.ts.map +1 -1
  52. package/dist/commands/occurred-at-option.js +7 -41
  53. package/dist/commands/occurred-at-option.js.map +1 -1
  54. package/dist/commands/payload-schema-command.d.ts +2 -2
  55. package/dist/commands/payload-schema-command.d.ts.map +1 -1
  56. package/dist/commands/payload-schema-command.js +1 -1
  57. package/dist/commands/payload-schema-command.js.map +1 -1
  58. package/dist/commands/research.d.ts.map +1 -1
  59. package/dist/commands/research.js +26 -28
  60. package/dist/commands/research.js.map +1 -1
  61. package/dist/commands/route.d.ts.map +1 -1
  62. package/dist/commands/route.js +45 -1
  63. package/dist/commands/route.js.map +1 -1
  64. package/dist/commands/scheduled-log.d.ts +130 -124
  65. package/dist/commands/scheduled-log.d.ts.map +1 -1
  66. package/dist/commands/wearables.d.ts +1109 -20
  67. package/dist/commands/wearables.d.ts.map +1 -1
  68. package/dist/commands/wearables.js +102 -2
  69. package/dist/commands/wearables.js.map +1 -1
  70. package/dist/commands/workout-live.d.ts +3 -0
  71. package/dist/commands/workout-live.d.ts.map +1 -0
  72. package/dist/commands/workout-live.js +291 -0
  73. package/dist/commands/workout-live.js.map +1 -0
  74. package/dist/commands/workout.d.ts.map +1 -1
  75. package/dist/commands/workout.js +35 -11
  76. package/dist/commands/workout.js.map +1 -1
  77. package/dist/food-labels.d.ts +549 -277
  78. package/dist/food-labels.d.ts.map +1 -1
  79. package/dist/food-labels.js +19 -3
  80. package/dist/food-labels.js.map +1 -1
  81. package/dist/foreground-terminal-logging.js +0 -2
  82. package/dist/foreground-terminal-logging.js.map +1 -1
  83. package/dist/hosted-data-api-labels.d.ts +1683 -871
  84. package/dist/hosted-data-api-labels.d.ts.map +1 -1
  85. package/dist/hosted-data-api-labels.js +63 -1
  86. package/dist/hosted-data-api-labels.js.map +1 -1
  87. package/dist/incur.generated.d.ts +148 -2
  88. package/dist/incur.generated.d.ts.map +1 -1
  89. package/dist/mapbox-address.d.ts +41 -0
  90. package/dist/mapbox-address.d.ts.map +1 -0
  91. package/dist/mapbox-address.js +470 -0
  92. package/dist/mapbox-address.js.map +1 -0
  93. package/dist/mapbox-route-contracts.d.ts +60 -60
  94. package/dist/mapbox-route-contracts.d.ts.map +1 -1
  95. package/dist/mapbox-route-contracts.js +1 -1
  96. package/dist/mapbox-route-contracts.js.map +1 -1
  97. package/dist/mapbox-route-directions.js +1 -1
  98. package/dist/mapbox-route-directions.js.map +1 -1
  99. package/dist/research-scout-client.d.ts +3 -2
  100. package/dist/research-scout-client.d.ts.map +1 -1
  101. package/dist/research-scout-client.js +166 -37
  102. package/dist/research-scout-client.js.map +1 -1
  103. package/dist/research-scout.d.ts +1 -1
  104. package/dist/research-scout.d.ts.map +1 -1
  105. package/dist/research-scout.js +1 -1
  106. package/dist/research-scout.js.map +1 -1
  107. package/dist/supplement-labels.d.ts +545 -275
  108. package/dist/supplement-labels.d.ts.map +1 -1
  109. package/dist/supplement-labels.js +0 -1
  110. package/dist/supplement-labels.js.map +1 -1
  111. package/dist/vault-cli-command-manifest.d.ts +1878 -404
  112. package/dist/vault-cli-command-manifest.d.ts.map +1 -1
  113. package/dist/vault-cli-command-manifest.js +35 -10
  114. package/dist/vault-cli-command-manifest.js.map +1 -1
  115. package/dist/vault-cli-skill-hash.generated.d.ts +1 -1
  116. package/dist/vault-cli-skill-hash.generated.js +1 -1
  117. package/dist/vault-cli-vault-context.js +0 -1
  118. package/dist/vault-cli-vault-context.js.map +1 -1
  119. package/node_modules/@murphai/assistant-cli/dist/assistant/service.d.ts +9 -0
  120. package/node_modules/@murphai/assistant-cli/dist/assistant/service.d.ts.map +1 -1
  121. package/node_modules/@murphai/assistant-cli/dist/assistant/ui/chat-controller-models.d.ts.map +1 -1
  122. package/node_modules/@murphai/assistant-cli/dist/assistant/ui/chat-controller-models.js +0 -1
  123. package/node_modules/@murphai/assistant-cli/dist/assistant/ui/chat-controller-models.js.map +1 -1
  124. package/node_modules/@murphai/assistant-cli/dist/assistant/ui/ink.d.ts.map +1 -1
  125. package/node_modules/@murphai/assistant-cli/dist/assistant/ui/ink.js +4 -6
  126. package/node_modules/@murphai/assistant-cli/dist/assistant/ui/ink.js.map +1 -1
  127. package/node_modules/@murphai/assistant-cli/dist/assistant-daemon-client.d.ts.map +1 -1
  128. package/node_modules/@murphai/assistant-cli/dist/assistant-daemon-client.js +19 -9
  129. package/node_modules/@murphai/assistant-cli/dist/assistant-daemon-client.js.map +1 -1
  130. package/node_modules/@murphai/assistant-cli/dist/commands/assistant.d.ts.map +1 -1
  131. package/node_modules/@murphai/assistant-cli/dist/commands/assistant.js +20 -56
  132. package/node_modules/@murphai/assistant-cli/dist/commands/assistant.js.map +1 -1
  133. package/node_modules/@murphai/assistant-engine/README.md +69 -13
  134. package/node_modules/@murphai/assistant-engine/dist/assistant/active-turn-input-controller.d.ts +6 -3
  135. package/node_modules/@murphai/assistant-engine/dist/assistant/active-turn-input-controller.d.ts.map +1 -1
  136. package/node_modules/@murphai/assistant-engine/dist/assistant/active-turn-input-controller.js +52 -19
  137. package/node_modules/@murphai/assistant-engine/dist/assistant/active-turn-input-controller.js.map +1 -1
  138. package/node_modules/@murphai/assistant-engine/dist/assistant/active-turn-input-journal.d.ts +75 -70
  139. package/node_modules/@murphai/assistant-engine/dist/assistant/active-turn-input-journal.d.ts.map +1 -1
  140. package/node_modules/@murphai/assistant-engine/dist/assistant/active-turn-input-journal.js +42 -17
  141. package/node_modules/@murphai/assistant-engine/dist/assistant/active-turn-input-journal.js.map +1 -1
  142. package/node_modules/@murphai/assistant-engine/dist/assistant/ask-continuation.d.ts +3 -1
  143. package/node_modules/@murphai/assistant-engine/dist/assistant/ask-continuation.d.ts.map +1 -1
  144. package/node_modules/@murphai/assistant-engine/dist/assistant/ask-continuation.js +27 -7
  145. package/node_modules/@murphai/assistant-engine/dist/assistant/ask-continuation.js.map +1 -1
  146. package/node_modules/@murphai/assistant-engine/dist/assistant/attachment-evidence-model.d.ts.map +1 -1
  147. package/node_modules/@murphai/assistant-engine/dist/assistant/attachment-evidence-model.js +4 -1
  148. package/node_modules/@murphai/assistant-engine/dist/assistant/attachment-evidence-model.js.map +1 -1
  149. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/cross-session-route-state.d.ts +77 -0
  150. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/cross-session-route-state.d.ts.map +1 -0
  151. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/cross-session-route-state.js +777 -0
  152. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/cross-session-route-state.js.map +1 -0
  153. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/grouping.d.ts +1 -0
  154. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/grouping.d.ts.map +1 -1
  155. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/grouping.js +36 -4
  156. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/grouping.js.map +1 -1
  157. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/input-summary.d.ts.map +1 -1
  158. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/input-summary.js +3 -1
  159. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/input-summary.js.map +1 -1
  160. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/operation-scope.d.ts +3 -1
  161. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/operation-scope.d.ts.map +1 -1
  162. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/prompt-builder.d.ts +10 -2
  163. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/prompt-builder.d.ts.map +1 -1
  164. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/prompt-builder.js +33 -13
  165. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/prompt-builder.js.map +1 -1
  166. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/reply.d.ts +12 -1
  167. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/reply.d.ts.map +1 -1
  168. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/reply.js +803 -171
  169. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/reply.js.map +1 -1
  170. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/run-loop.d.ts +2 -0
  171. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/run-loop.d.ts.map +1 -1
  172. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/run-loop.js +42 -17
  173. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/run-loop.js.map +1 -1
  174. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/scanner.d.ts +2 -0
  175. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/scanner.d.ts.map +1 -1
  176. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/scanner.js +59 -30
  177. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/scanner.js.map +1 -1
  178. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/shared.d.ts +2 -1
  179. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/shared.d.ts.map +1 -1
  180. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/shared.js +3 -0
  181. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/shared.js.map +1 -1
  182. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/target-override.d.ts +10 -1
  183. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/target-override.d.ts.map +1 -1
  184. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/target-override.js +62 -1
  185. package/node_modules/@murphai/assistant-engine/dist/assistant/automation/target-override.js.map +1 -1
  186. package/node_modules/@murphai/assistant-engine/dist/assistant/automation.d.ts +1 -1
  187. package/node_modules/@murphai/assistant-engine/dist/assistant/automation.d.ts.map +1 -1
  188. package/node_modules/@murphai/assistant-engine/dist/assistant/automation.js +1 -1
  189. package/node_modules/@murphai/assistant-engine/dist/assistant/automation.js.map +1 -1
  190. package/node_modules/@murphai/assistant-engine/dist/assistant/channel-adapters.d.ts +1 -1
  191. package/node_modules/@murphai/assistant-engine/dist/assistant/channel-adapters.d.ts.map +1 -1
  192. package/node_modules/@murphai/assistant-engine/dist/assistant/channel-adapters.js +1 -1
  193. package/node_modules/@murphai/assistant-engine/dist/assistant/channel-adapters.js.map +1 -1
  194. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/descriptors.d.ts.map +1 -1
  195. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/descriptors.js +107 -44
  196. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/descriptors.js.map +1 -1
  197. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/helpers.d.ts +3 -1
  198. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/helpers.d.ts.map +1 -1
  199. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/helpers.js +34 -3
  200. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/helpers.js.map +1 -1
  201. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/runtime.d.ts +22 -14
  202. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/runtime.d.ts.map +1 -1
  203. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/runtime.js +352 -78
  204. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/runtime.js.map +1 -1
  205. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/types.d.ts +43 -8
  206. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/types.d.ts.map +1 -1
  207. package/node_modules/@murphai/assistant-engine/dist/assistant/channels/types.js.map +1 -1
  208. package/node_modules/@murphai/assistant-engine/dist/assistant/cli-surface-bootstrap.d.ts +1 -0
  209. package/node_modules/@murphai/assistant-engine/dist/assistant/cli-surface-bootstrap.d.ts.map +1 -1
  210. package/node_modules/@murphai/assistant-engine/dist/assistant/cli-surface-bootstrap.js +6 -5
  211. package/node_modules/@murphai/assistant-engine/dist/assistant/cli-surface-bootstrap.js.map +1 -1
  212. package/node_modules/@murphai/assistant-engine/dist/assistant/cli-surface-contract.generated.json +1 -1
  213. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-base-instructions.d.ts +1 -1
  214. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-base-instructions.d.ts.map +1 -1
  215. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-base-instructions.js +14 -7
  216. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-base-instructions.js.map +1 -1
  217. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-runtime.d.ts +17 -0
  218. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-runtime.d.ts.map +1 -1
  219. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-runtime.js +25 -19
  220. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-runtime.js.map +1 -1
  221. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-thread-route.d.ts.map +1 -1
  222. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-thread-route.js +9 -9
  223. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-thread-route.js.map +1 -1
  224. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-turn/planning.d.ts +3 -7
  225. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-turn/planning.d.ts.map +1 -1
  226. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-turn/planning.js +172 -48
  227. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-turn/planning.js.map +1 -1
  228. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-turn-runner.d.ts +5 -3
  229. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-turn-runner.d.ts.map +1 -1
  230. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-turn-runner.js +124 -25
  231. package/node_modules/@murphai/assistant-engine/dist/assistant/codex-turn-runner.js.map +1 -1
  232. package/node_modules/@murphai/assistant-engine/dist/assistant/content-types.d.ts +2 -0
  233. package/node_modules/@murphai/assistant-engine/dist/assistant/content-types.d.ts.map +1 -1
  234. package/node_modules/@murphai/assistant-engine/dist/assistant/context-snapshot.d.ts +4 -1
  235. package/node_modules/@murphai/assistant-engine/dist/assistant/context-snapshot.d.ts.map +1 -1
  236. package/node_modules/@murphai/assistant-engine/dist/assistant/context-snapshot.js +75 -19
  237. package/node_modules/@murphai/assistant-engine/dist/assistant/context-snapshot.js.map +1 -1
  238. package/node_modules/@murphai/assistant-engine/dist/assistant/conversation-persistence.d.ts +1 -1
  239. package/node_modules/@murphai/assistant-engine/dist/assistant/conversation-persistence.d.ts.map +1 -1
  240. package/node_modules/@murphai/assistant-engine/dist/assistant/conversation-persistence.js +0 -1
  241. package/node_modules/@murphai/assistant-engine/dist/assistant/conversation-persistence.js.map +1 -1
  242. package/node_modules/@murphai/assistant-engine/dist/assistant/conversation-ref.d.ts +1 -0
  243. package/node_modules/@murphai/assistant-engine/dist/assistant/conversation-ref.d.ts.map +1 -1
  244. package/node_modules/@murphai/assistant-engine/dist/assistant/conversation-ref.js +2 -0
  245. package/node_modules/@murphai/assistant-engine/dist/assistant/conversation-ref.js.map +1 -1
  246. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/authoring.d.ts +5 -1
  247. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/authoring.d.ts.map +1 -1
  248. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/authoring.js +178 -31
  249. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/authoring.js.map +1 -1
  250. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/canonical-jobs.d.ts +32 -1
  251. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/canonical-jobs.d.ts.map +1 -1
  252. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/canonical-jobs.js +147 -31
  253. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/canonical-jobs.js.map +1 -1
  254. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/delivery-reconciliation.d.ts +8 -0
  255. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/delivery-reconciliation.d.ts.map +1 -1
  256. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/delivery-reconciliation.js +73 -15
  257. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/delivery-reconciliation.js.map +1 -1
  258. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/execution.d.ts +3 -1
  259. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/execution.d.ts.map +1 -1
  260. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/execution.js +420 -112
  261. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/execution.js.map +1 -1
  262. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/mutations.d.ts.map +1 -1
  263. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/mutations.js +2 -0
  264. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/mutations.js.map +1 -1
  265. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/output-history.d.ts +11 -0
  266. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/output-history.d.ts.map +1 -0
  267. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/output-history.js +153 -0
  268. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/output-history.js.map +1 -0
  269. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/runtime-state.d.ts +47 -47
  270. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/runtime-state.d.ts.map +1 -1
  271. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/runtime-state.js +1 -1
  272. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/runtime-state.js.map +1 -1
  273. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/schedule.d.ts +8 -0
  274. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/schedule.d.ts.map +1 -1
  275. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/schedule.js +16 -0
  276. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/schedule.js.map +1 -1
  277. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/store.d.ts +49 -39
  278. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/store.d.ts.map +1 -1
  279. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/store.js +19 -1
  280. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/store.js.map +1 -1
  281. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/targets.d.ts.map +1 -1
  282. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/targets.js +1 -3
  283. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/targets.js.map +1 -1
  284. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/timing-verification.d.ts +2 -0
  285. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/timing-verification.d.ts.map +1 -0
  286. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/timing-verification.js +2 -0
  287. package/node_modules/@murphai/assistant-engine/dist/assistant/cron/timing-verification.js.map +1 -0
  288. package/node_modules/@murphai/assistant-engine/dist/assistant/cron.d.ts +9 -0
  289. package/node_modules/@murphai/assistant-engine/dist/assistant/cron.d.ts.map +1 -1
  290. package/node_modules/@murphai/assistant-engine/dist/assistant/cron.js +31 -2
  291. package/node_modules/@murphai/assistant-engine/dist/assistant/cron.js.map +1 -1
  292. package/node_modules/@murphai/assistant-engine/dist/assistant/delivery-service.d.ts +3 -0
  293. package/node_modules/@murphai/assistant-engine/dist/assistant/delivery-service.d.ts.map +1 -1
  294. package/node_modules/@murphai/assistant-engine/dist/assistant/delivery-service.js +32 -1
  295. package/node_modules/@murphai/assistant-engine/dist/assistant/delivery-service.js.map +1 -1
  296. package/node_modules/@murphai/assistant-engine/dist/assistant/device-activity-cron-tags.d.ts +2 -1
  297. package/node_modules/@murphai/assistant-engine/dist/assistant/device-activity-cron-tags.d.ts.map +1 -1
  298. package/node_modules/@murphai/assistant-engine/dist/assistant/device-activity-cron-tags.js +8 -0
  299. package/node_modules/@murphai/assistant-engine/dist/assistant/device-activity-cron-tags.js.map +1 -1
  300. package/node_modules/@murphai/assistant-engine/dist/assistant/execution-context.d.ts +91 -13
  301. package/node_modules/@murphai/assistant-engine/dist/assistant/execution-context.d.ts.map +1 -1
  302. package/node_modules/@murphai/assistant-engine/dist/assistant/execution-context.js +48 -11
  303. package/node_modules/@murphai/assistant-engine/dist/assistant/execution-context.js.map +1 -1
  304. package/node_modules/@murphai/assistant-engine/dist/assistant/execution-plan.d.ts.map +1 -1
  305. package/node_modules/@murphai/assistant-engine/dist/assistant/execution-plan.js +2 -8
  306. package/node_modules/@murphai/assistant-engine/dist/assistant/execution-plan.js.map +1 -1
  307. package/node_modules/@murphai/assistant-engine/dist/assistant/experiment-support-automations.d.ts.map +1 -1
  308. package/node_modules/@murphai/assistant-engine/dist/assistant/experiment-support-automations.js +8 -0
  309. package/node_modules/@murphai/assistant-engine/dist/assistant/experiment-support-automations.js.map +1 -1
  310. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-response-card-schema.d.ts +115 -0
  311. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-response-card-schema.d.ts.map +1 -0
  312. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-response-card-schema.js +162 -0
  313. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-response-card-schema.js.map +1 -0
  314. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-response-card.d.ts +3 -0
  315. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-response-card.d.ts.map +1 -0
  316. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-response-card.js +118 -0
  317. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-response-card.js.map +1 -0
  318. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-scorecard-schema.d.ts +83 -1
  319. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-scorecard-schema.d.ts.map +1 -1
  320. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-scorecard-schema.js +27 -22
  321. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-scorecard-schema.js.map +1 -1
  322. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-scorecard.js +8 -0
  323. package/node_modules/@murphai/assistant-engine/dist/assistant/group-challenge-scorecard.js.map +1 -1
  324. package/node_modules/@murphai/assistant-engine/dist/assistant/group-email-outbox.d.ts +20 -0
  325. package/node_modules/@murphai/assistant-engine/dist/assistant/group-email-outbox.d.ts.map +1 -0
  326. package/node_modules/@murphai/assistant-engine/dist/assistant/{newsletter-outbox.js → group-email-outbox.js} +65 -36
  327. package/node_modules/@murphai/assistant-engine/dist/assistant/group-email-outbox.js.map +1 -0
  328. package/node_modules/@murphai/assistant-engine/dist/assistant/group-newsletter-automation.d.ts +2 -48
  329. package/node_modules/@murphai/assistant-engine/dist/assistant/group-newsletter-automation.d.ts.map +1 -1
  330. package/node_modules/@murphai/assistant-engine/dist/assistant/group-newsletter-automation.js +14 -98
  331. package/node_modules/@murphai/assistant-engine/dist/assistant/group-newsletter-automation.js.map +1 -1
  332. package/node_modules/@murphai/assistant-engine/dist/assistant/group-room-model.d.ts +22 -3
  333. package/node_modules/@murphai/assistant-engine/dist/assistant/group-room-model.d.ts.map +1 -1
  334. package/node_modules/@murphai/assistant-engine/dist/assistant/group-room-model.js +87 -28
  335. package/node_modules/@murphai/assistant-engine/dist/assistant/group-room-model.js.map +1 -1
  336. package/node_modules/@murphai/assistant-engine/dist/assistant/group-shared-freshness.d.ts +2 -0
  337. package/node_modules/@murphai/assistant-engine/dist/assistant/group-shared-freshness.d.ts.map +1 -0
  338. package/node_modules/@murphai/assistant-engine/dist/assistant/group-shared-freshness.js +5 -0
  339. package/node_modules/@murphai/assistant-engine/dist/assistant/group-shared-freshness.js.map +1 -0
  340. package/node_modules/@murphai/assistant-engine/dist/assistant/group-shared-read-limits.d.ts +3 -2
  341. package/node_modules/@murphai/assistant-engine/dist/assistant/group-shared-read-limits.d.ts.map +1 -1
  342. package/node_modules/@murphai/assistant-engine/dist/assistant/group-shared-read-limits.js +21 -2
  343. package/node_modules/@murphai/assistant-engine/dist/assistant/group-shared-read-limits.js.map +1 -1
  344. package/node_modules/@murphai/assistant-engine/dist/assistant/hosted-image-completion.d.ts +31 -0
  345. package/node_modules/@murphai/assistant-engine/dist/assistant/hosted-image-completion.d.ts.map +1 -0
  346. package/node_modules/@murphai/assistant-engine/dist/assistant/hosted-image-completion.js +164 -0
  347. package/node_modules/@murphai/assistant-engine/dist/assistant/hosted-image-completion.js.map +1 -0
  348. package/node_modules/@murphai/assistant-engine/dist/assistant/hosted-tool-context.d.ts +77 -24
  349. package/node_modules/@murphai/assistant-engine/dist/assistant/hosted-tool-context.d.ts.map +1 -1
  350. package/node_modules/@murphai/assistant-engine/dist/assistant/hosted-tool-context.js +184 -63
  351. package/node_modules/@murphai/assistant-engine/dist/assistant/hosted-tool-context.js.map +1 -1
  352. package/node_modules/@murphai/assistant-engine/dist/assistant/input-source.d.ts +1 -0
  353. package/node_modules/@murphai/assistant-engine/dist/assistant/input-source.d.ts.map +1 -1
  354. package/node_modules/@murphai/assistant-engine/dist/assistant/input-source.js +2 -1
  355. package/node_modules/@murphai/assistant-engine/dist/assistant/input-source.js.map +1 -1
  356. package/node_modules/@murphai/assistant-engine/dist/assistant/input-store.d.ts +273 -269
  357. package/node_modules/@murphai/assistant-engine/dist/assistant/input-store.d.ts.map +1 -1
  358. package/node_modules/@murphai/assistant-engine/dist/assistant/input-store.js +6 -1
  359. package/node_modules/@murphai/assistant-engine/dist/assistant/input-store.js.map +1 -1
  360. package/node_modules/@murphai/assistant-engine/dist/assistant/linq-delivery-posture.d.ts +3 -0
  361. package/node_modules/@murphai/assistant-engine/dist/assistant/linq-delivery-posture.d.ts.map +1 -0
  362. package/node_modules/@murphai/assistant-engine/dist/assistant/linq-delivery-posture.js +20 -0
  363. package/node_modules/@murphai/assistant-engine/dist/assistant/linq-delivery-posture.js.map +1 -0
  364. package/node_modules/@murphai/assistant-engine/dist/assistant/local-service.d.ts.map +1 -1
  365. package/node_modules/@murphai/assistant-engine/dist/assistant/local-service.js +217 -84
  366. package/node_modules/@murphai/assistant-engine/dist/assistant/local-service.js.map +1 -1
  367. package/node_modules/@murphai/assistant-engine/dist/assistant/maintenance-evidence.d.ts +3 -3
  368. package/node_modules/@murphai/assistant-engine/dist/assistant/maintenance-evidence.d.ts.map +1 -1
  369. package/node_modules/@murphai/assistant-engine/dist/assistant/maintenance-evidence.js +245 -6
  370. package/node_modules/@murphai/assistant-engine/dist/assistant/maintenance-evidence.js.map +1 -1
  371. package/node_modules/@murphai/assistant-engine/dist/assistant/managed-automations.d.ts +22 -1
  372. package/node_modules/@murphai/assistant-engine/dist/assistant/managed-automations.d.ts.map +1 -1
  373. package/node_modules/@murphai/assistant-engine/dist/assistant/managed-automations.js +289 -34
  374. package/node_modules/@murphai/assistant-engine/dist/assistant/managed-automations.js.map +1 -1
  375. package/node_modules/@murphai/assistant-engine/dist/assistant/message-target-selection.d.ts +13 -22
  376. package/node_modules/@murphai/assistant-engine/dist/assistant/message-target-selection.d.ts.map +1 -1
  377. package/node_modules/@murphai/assistant-engine/dist/assistant/message-target-selection.js +8 -3
  378. package/node_modules/@murphai/assistant-engine/dist/assistant/message-target-selection.js.map +1 -1
  379. package/node_modules/@murphai/assistant-engine/dist/assistant/model-behavior.d.ts +3 -0
  380. package/node_modules/@murphai/assistant-engine/dist/assistant/model-behavior.d.ts.map +1 -1
  381. package/node_modules/@murphai/assistant-engine/dist/assistant/model-behavior.js +40 -7
  382. package/node_modules/@murphai/assistant-engine/dist/assistant/model-behavior.js.map +1 -1
  383. package/node_modules/@murphai/assistant-engine/dist/assistant/notification-turn.d.ts +16 -14
  384. package/node_modules/@murphai/assistant-engine/dist/assistant/notification-turn.d.ts.map +1 -1
  385. package/node_modules/@murphai/assistant-engine/dist/assistant/notification-turn.js +205 -56
  386. package/node_modules/@murphai/assistant-engine/dist/assistant/notification-turn.js.map +1 -1
  387. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-first-personal-read-automation.d.ts +14 -0
  388. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-first-personal-read-automation.d.ts.map +1 -0
  389. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-first-personal-read-automation.js +94 -0
  390. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-first-personal-read-automation.js.map +1 -0
  391. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-followup-automation.d.ts +22 -3
  392. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-followup-automation.d.ts.map +1 -1
  393. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-followup-automation.js +81 -7
  394. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-followup-automation.js.map +1 -1
  395. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-goal-checkin-automation.d.ts +1 -0
  396. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-goal-checkin-automation.d.ts.map +1 -1
  397. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-goal-checkin-automation.js +184 -83
  398. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-goal-checkin-automation.js.map +1 -1
  399. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-state.js +1 -1
  400. package/node_modules/@murphai/assistant-engine/dist/assistant/onboarding-state.js.map +1 -1
  401. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/automation-authority.d.ts.map +1 -1
  402. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/automation-authority.js +24 -1
  403. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/automation-authority.js.map +1 -1
  404. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/dispatch-state.d.ts +15 -3
  405. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/dispatch-state.d.ts.map +1 -1
  406. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/dispatch-state.js +314 -53
  407. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/dispatch-state.js.map +1 -1
  408. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/intents.d.ts +2 -0
  409. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/intents.d.ts.map +1 -1
  410. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/intents.js +1 -0
  411. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/intents.js.map +1 -1
  412. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/receipt-repair.d.ts.map +1 -1
  413. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/receipt-repair.js +5 -0
  414. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/receipt-repair.js.map +1 -1
  415. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/retry-policy.d.ts +4 -1
  416. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/retry-policy.d.ts.map +1 -1
  417. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/retry-policy.js +33 -8
  418. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/retry-policy.js.map +1 -1
  419. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/store.d.ts +37 -3
  420. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/store.d.ts.map +1 -1
  421. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/store.js +1031 -41
  422. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/store.js.map +1 -1
  423. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/summary.d.ts.map +1 -1
  424. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/summary.js +7 -0
  425. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox/summary.js.map +1 -1
  426. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox.d.ts +61 -8
  427. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox.d.ts.map +1 -1
  428. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox.js +561 -67
  429. package/node_modules/@murphai/assistant-engine/dist/assistant/outbox.js.map +1 -1
  430. package/node_modules/@murphai/assistant-engine/dist/assistant/private-completion-continuity.d.ts +23 -0
  431. package/node_modules/@murphai/assistant-engine/dist/assistant/private-completion-continuity.d.ts.map +1 -0
  432. package/node_modules/@murphai/assistant-engine/dist/assistant/private-completion-continuity.js +293 -0
  433. package/node_modules/@murphai/assistant-engine/dist/assistant/private-completion-continuity.js.map +1 -0
  434. package/node_modules/@murphai/assistant-engine/dist/assistant/prompt-time.d.ts +12 -0
  435. package/node_modules/@murphai/assistant-engine/dist/assistant/prompt-time.d.ts.map +1 -0
  436. package/node_modules/@murphai/assistant-engine/dist/assistant/prompt-time.js +38 -0
  437. package/node_modules/@murphai/assistant-engine/dist/assistant/prompt-time.js.map +1 -0
  438. package/node_modules/@murphai/assistant-engine/dist/assistant/provider-catalog.d.ts.map +1 -1
  439. package/node_modules/@murphai/assistant-engine/dist/assistant/provider-catalog.js +2 -2
  440. package/node_modules/@murphai/assistant-engine/dist/assistant/provider-catalog.js.map +1 -1
  441. package/node_modules/@murphai/assistant-engine/dist/assistant/provider-start-critical-path.d.ts +48 -0
  442. package/node_modules/@murphai/assistant-engine/dist/assistant/provider-start-critical-path.d.ts.map +1 -0
  443. package/node_modules/@murphai/assistant-engine/dist/assistant/provider-start-critical-path.js +101 -0
  444. package/node_modules/@murphai/assistant-engine/dist/assistant/provider-start-critical-path.js.map +1 -0
  445. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/codex-cli.d.ts +6 -0
  446. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/codex-cli.d.ts.map +1 -1
  447. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/codex-cli.js +62 -96
  448. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/codex-cli.js.map +1 -1
  449. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/helpers.d.ts +5 -2
  450. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/helpers.d.ts.map +1 -1
  451. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/helpers.js +412 -568
  452. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/helpers.js.map +1 -1
  453. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/types.d.ts +23 -1
  454. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/types.d.ts.map +1 -1
  455. package/node_modules/@murphai/assistant-engine/dist/assistant/providers/types.js.map +1 -1
  456. package/node_modules/@murphai/assistant-engine/dist/assistant/redaction.d.ts +2 -1
  457. package/node_modules/@murphai/assistant-engine/dist/assistant/redaction.d.ts.map +1 -1
  458. package/node_modules/@murphai/assistant-engine/dist/assistant/redaction.js +6 -1
  459. package/node_modules/@murphai/assistant-engine/dist/assistant/redaction.js.map +1 -1
  460. package/node_modules/@murphai/assistant-engine/dist/assistant/reminder-availability-maintenance.d.ts +17 -0
  461. package/node_modules/@murphai/assistant-engine/dist/assistant/reminder-availability-maintenance.d.ts.map +1 -0
  462. package/node_modules/@murphai/assistant-engine/dist/assistant/reminder-availability-maintenance.js +287 -0
  463. package/node_modules/@murphai/assistant-engine/dist/assistant/reminder-availability-maintenance.js.map +1 -0
  464. package/node_modules/@murphai/assistant-engine/dist/assistant/response-media.d.ts +33 -1
  465. package/node_modules/@murphai/assistant-engine/dist/assistant/response-media.d.ts.map +1 -1
  466. package/node_modules/@murphai/assistant-engine/dist/assistant/response-media.js +173 -3
  467. package/node_modules/@murphai/assistant-engine/dist/assistant/response-media.js.map +1 -1
  468. package/node_modules/@murphai/assistant-engine/dist/assistant/runtime-residue.d.ts +6 -0
  469. package/node_modules/@murphai/assistant-engine/dist/assistant/runtime-residue.d.ts.map +1 -1
  470. package/node_modules/@murphai/assistant-engine/dist/assistant/runtime-residue.js +61 -29
  471. package/node_modules/@murphai/assistant-engine/dist/assistant/runtime-residue.js.map +1 -1
  472. package/node_modules/@murphai/assistant-engine/dist/assistant/service-contracts.d.ts +17 -3
  473. package/node_modules/@murphai/assistant-engine/dist/assistant/service-contracts.d.ts.map +1 -1
  474. package/node_modules/@murphai/assistant-engine/dist/assistant/service-turn-routes.d.ts +1 -1
  475. package/node_modules/@murphai/assistant-engine/dist/assistant/service-turn-routes.d.ts.map +1 -1
  476. package/node_modules/@murphai/assistant-engine/dist/assistant/service-turn-routes.js +18 -8
  477. package/node_modules/@murphai/assistant-engine/dist/assistant/service-turn-routes.js.map +1 -1
  478. package/node_modules/@murphai/assistant-engine/dist/assistant/service-usage.d.ts +1 -0
  479. package/node_modules/@murphai/assistant-engine/dist/assistant/service-usage.d.ts.map +1 -1
  480. package/node_modules/@murphai/assistant-engine/dist/assistant/service-usage.js +23 -4
  481. package/node_modules/@murphai/assistant-engine/dist/assistant/service-usage.js.map +1 -1
  482. package/node_modules/@murphai/assistant-engine/dist/assistant/service.d.ts +12 -2
  483. package/node_modules/@murphai/assistant-engine/dist/assistant/service.d.ts.map +1 -1
  484. package/node_modules/@murphai/assistant-engine/dist/assistant/service.js +5 -3
  485. package/node_modules/@murphai/assistant-engine/dist/assistant/service.js.map +1 -1
  486. package/node_modules/@murphai/assistant-engine/dist/assistant/session-resolution.d.ts.map +1 -1
  487. package/node_modules/@murphai/assistant-engine/dist/assistant/session-resolution.js +71 -16
  488. package/node_modules/@murphai/assistant-engine/dist/assistant/session-resolution.js.map +1 -1
  489. package/node_modules/@murphai/assistant-engine/dist/assistant/shared.d.ts +1 -0
  490. package/node_modules/@murphai/assistant-engine/dist/assistant/shared.d.ts.map +1 -1
  491. package/node_modules/@murphai/assistant-engine/dist/assistant/shared.js +1 -0
  492. package/node_modules/@murphai/assistant-engine/dist/assistant/shared.js.map +1 -1
  493. package/node_modules/@murphai/assistant-engine/dist/assistant/state-secrets.d.ts +1 -1
  494. package/node_modules/@murphai/assistant-engine/dist/assistant/state-secrets.d.ts.map +1 -1
  495. package/node_modules/@murphai/assistant-engine/dist/assistant/state-secrets.js +0 -1
  496. package/node_modules/@murphai/assistant-engine/dist/assistant/state-secrets.js.map +1 -1
  497. package/node_modules/@murphai/assistant-engine/dist/assistant/store/persistence.d.ts +11 -3
  498. package/node_modules/@murphai/assistant-engine/dist/assistant/store/persistence.d.ts.map +1 -1
  499. package/node_modules/@murphai/assistant-engine/dist/assistant/store/persistence.js +410 -139
  500. package/node_modules/@murphai/assistant-engine/dist/assistant/store/persistence.js.map +1 -1
  501. package/node_modules/@murphai/assistant-engine/dist/assistant/store/types.d.ts +2 -0
  502. package/node_modules/@murphai/assistant-engine/dist/assistant/store/types.d.ts.map +1 -1
  503. package/node_modules/@murphai/assistant-engine/dist/assistant/store.d.ts.map +1 -1
  504. package/node_modules/@murphai/assistant-engine/dist/assistant/store.js +48 -13
  505. package/node_modules/@murphai/assistant-engine/dist/assistant/store.js.map +1 -1
  506. package/node_modules/@murphai/assistant-engine/dist/assistant/system-prompt.d.ts +4 -0
  507. package/node_modules/@murphai/assistant-engine/dist/assistant/system-prompt.d.ts.map +1 -1
  508. package/node_modules/@murphai/assistant-engine/dist/assistant/system-prompt.js +274 -128
  509. package/node_modules/@murphai/assistant-engine/dist/assistant/system-prompt.js.map +1 -1
  510. package/node_modules/@murphai/assistant-engine/dist/assistant/tool-validation-digest.d.ts +9 -0
  511. package/node_modules/@murphai/assistant-engine/dist/assistant/tool-validation-digest.d.ts.map +1 -1
  512. package/node_modules/@murphai/assistant-engine/dist/assistant/tool-validation-digest.js +133 -7
  513. package/node_modules/@murphai/assistant-engine/dist/assistant/tool-validation-digest.js.map +1 -1
  514. package/node_modules/@murphai/assistant-engine/dist/assistant/tool-validation-feedback.d.ts +11 -0
  515. package/node_modules/@murphai/assistant-engine/dist/assistant/tool-validation-feedback.d.ts.map +1 -0
  516. package/node_modules/@murphai/assistant-engine/dist/assistant/tool-validation-feedback.js +59 -0
  517. package/node_modules/@murphai/assistant-engine/dist/assistant/tool-validation-feedback.js.map +1 -0
  518. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-finalizer.d.ts.map +1 -1
  519. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-finalizer.js +109 -16
  520. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-finalizer.js.map +1 -1
  521. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-input.d.ts +2 -1
  522. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-input.d.ts.map +1 -1
  523. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-input.js.map +1 -1
  524. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-progress.d.ts +9 -2
  525. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-progress.d.ts.map +1 -1
  526. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-progress.js +49 -6
  527. package/node_modules/@murphai/assistant-engine/dist/assistant/turn-progress.js.map +1 -1
  528. package/node_modules/@murphai/assistant-engine/dist/assistant/turns.d.ts +1 -0
  529. package/node_modules/@murphai/assistant-engine/dist/assistant/turns.d.ts.map +1 -1
  530. package/node_modules/@murphai/assistant-engine/dist/assistant/turns.js +62 -22
  531. package/node_modules/@murphai/assistant-engine/dist/assistant/turns.js.map +1 -1
  532. package/node_modules/@murphai/assistant-engine/dist/assistant/vault-file-send.d.ts +7 -0
  533. package/node_modules/@murphai/assistant-engine/dist/assistant/vault-file-send.d.ts.map +1 -1
  534. package/node_modules/@murphai/assistant-engine/dist/assistant/vault-file-send.js +47 -1
  535. package/node_modules/@murphai/assistant-engine/dist/assistant/vault-file-send.js.map +1 -1
  536. package/node_modules/@murphai/assistant-engine/dist/assistant-ask.d.ts +4 -1
  537. package/node_modules/@murphai/assistant-engine/dist/assistant-ask.d.ts.map +1 -1
  538. package/node_modules/@murphai/assistant-engine/dist/assistant-ask.js +49 -23
  539. package/node_modules/@murphai/assistant-engine/dist/assistant-ask.js.map +1 -1
  540. package/node_modules/@murphai/assistant-engine/dist/assistant-channel-adapters.d.ts +1 -1
  541. package/node_modules/@murphai/assistant-engine/dist/assistant-channel-adapters.d.ts.map +1 -1
  542. package/node_modules/@murphai/assistant-engine/dist/assistant-channel-adapters.js +1 -1
  543. package/node_modules/@murphai/assistant-engine/dist/assistant-channel-adapters.js.map +1 -1
  544. package/node_modules/@murphai/assistant-engine/dist/assistant-channel-runtime.d.ts +1 -1
  545. package/node_modules/@murphai/assistant-engine/dist/assistant-channel-runtime.d.ts.map +1 -1
  546. package/node_modules/@murphai/assistant-engine/dist/assistant-channel-runtime.js +1 -1
  547. package/node_modules/@murphai/assistant-engine/dist/assistant-channel-runtime.js.map +1 -1
  548. package/node_modules/@murphai/assistant-engine/dist/assistant-cli-access.d.ts.map +1 -1
  549. package/node_modules/@murphai/assistant-engine/dist/assistant-cli-access.js +12 -1
  550. package/node_modules/@murphai/assistant-engine/dist/assistant-cli-access.js.map +1 -1
  551. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/action-diagnostics.d.ts +8 -4
  552. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/action-diagnostics.d.ts.map +1 -1
  553. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/action-diagnostics.js +136 -19
  554. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/action-diagnostics.js.map +1 -1
  555. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/action-outcome.d.ts +5 -0
  556. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/action-outcome.d.ts.map +1 -0
  557. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/action-outcome.js +36 -0
  558. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/action-outcome.js.map +1 -0
  559. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-protocol.d.ts +59 -0
  560. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-protocol.d.ts.map +1 -0
  561. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-protocol.js +181 -0
  562. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-protocol.js.map +1 -0
  563. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-requests.d.ts +5 -3
  564. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-requests.d.ts.map +1 -1
  565. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-requests.js +19 -5
  566. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-requests.js.map +1 -1
  567. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-rpc.d.ts +2 -3
  568. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-rpc.d.ts.map +1 -1
  569. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-rpc.js +7 -14
  570. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/app-server-rpc.js.map +1 -1
  571. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/ask-grok-tool.d.ts.map +1 -1
  572. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/ask-grok-tool.js +77 -11
  573. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/ask-grok-tool.js.map +1 -1
  574. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/command-family.d.ts +17 -0
  575. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/command-family.d.ts.map +1 -0
  576. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/command-family.js +200 -0
  577. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/command-family.js.map +1 -0
  578. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tool-catalog.d.ts +3387 -0
  579. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tool-catalog.d.ts.map +1 -0
  580. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tool-catalog.js +1379 -0
  581. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tool-catalog.js.map +1 -0
  582. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/ask-grok.d.ts +1 -1
  583. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/ask-grok.d.ts.map +1 -1
  584. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/ask-grok.js +2 -2
  585. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/ask-grok.js.map +1 -1
  586. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/assistant-style.d.ts +15 -32
  587. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/assistant-style.d.ts.map +1 -1
  588. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/assistant-style.js +11 -7
  589. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/assistant-style.js.map +1 -1
  590. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/automation.d.ts +26 -150
  591. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/automation.d.ts.map +1 -1
  592. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/automation.js +537 -103
  593. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/automation.js.map +1 -1
  594. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/clinical-records.js +4 -4
  595. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/clinical-records.js.map +1 -1
  596. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/connected-apps.d.ts +10 -54
  597. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/connected-apps.d.ts.map +1 -1
  598. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/connected-apps.js +134 -109
  599. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/connected-apps.js.map +1 -1
  600. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/device.d.ts +2 -12
  601. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/device.d.ts.map +1 -1
  602. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/device.js +1 -1
  603. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/device.js.map +1 -1
  604. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/dynamic-tool-wrapper.d.ts +2 -1
  605. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/dynamic-tool-wrapper.d.ts.map +1 -1
  606. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/dynamic-tool-wrapper.js +2 -1
  607. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/dynamic-tool-wrapper.js.map +1 -1
  608. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/generate-song.d.ts +9 -2
  609. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/generate-song.d.ts.map +1 -1
  610. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/generate-song.js +31 -3
  611. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/generate-song.js.map +1 -1
  612. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/generate-voice-memo.d.ts +7 -6
  613. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/generate-voice-memo.d.ts.map +1 -1
  614. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/generate-voice-memo.js +12 -8
  615. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/generate-voice-memo.js.map +1 -1
  616. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/group-room-model.d.ts +10 -19
  617. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/group-room-model.d.ts.map +1 -1
  618. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/group-room-model.js +19 -7
  619. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/group-room-model.js.map +1 -1
  620. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/labs.d.ts +2 -16
  621. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/labs.d.ts.map +1 -1
  622. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/labs.js +1 -1
  623. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/labs.js.map +1 -1
  624. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/pending-vault-files.d.ts +65 -0
  625. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/pending-vault-files.d.ts.map +1 -0
  626. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/pending-vault-files.js +214 -0
  627. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/pending-vault-files.js.map +1 -0
  628. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/phone-calls.d.ts +24 -16
  629. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/phone-calls.d.ts.map +1 -1
  630. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/phone-calls.js +78 -7
  631. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/phone-calls.js.map +1 -1
  632. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/physical-notes.d.ts +91 -0
  633. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/physical-notes.d.ts.map +1 -0
  634. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/physical-notes.js +199 -0
  635. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools/physical-notes.js.map +1 -0
  636. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools.d.ts +108 -2427
  637. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools.d.ts.map +1 -1
  638. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools.js +2248 -1509
  639. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/dynamic-tools.js.map +1 -1
  640. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/failures.d.ts.map +1 -1
  641. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/failures.js +39 -95
  642. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/failures.js.map +1 -1
  643. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/generate-image-tool.d.ts +5 -2
  644. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/generate-image-tool.d.ts.map +1 -1
  645. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/generate-image-tool.js +88 -101
  646. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/generate-image-tool.js.map +1 -1
  647. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/generate-voice-memo-tool.d.ts +58 -13
  648. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/generate-voice-memo-tool.d.ts.map +1 -1
  649. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/generate-voice-memo-tool.js +85 -122
  650. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/generate-voice-memo-tool.js.map +1 -1
  651. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/image-reference-resolver.d.ts.map +1 -1
  652. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/image-reference-resolver.js +5 -3
  653. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/image-reference-resolver.js.map +1 -1
  654. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/images.d.ts +15 -2
  655. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/images.d.ts.map +1 -1
  656. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/images.js +99 -8
  657. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/images.js.map +1 -1
  658. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/managed-voice-memo-runtime.d.ts +17 -0
  659. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/managed-voice-memo-runtime.d.ts.map +1 -0
  660. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/managed-voice-memo-runtime.js +12 -0
  661. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/managed-voice-memo-runtime.js.map +1 -0
  662. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/openai-image-generation.d.ts +7 -11
  663. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/openai-image-generation.d.ts.map +1 -1
  664. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/openai-image-generation.js +237 -52
  665. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/openai-image-generation.js.map +1 -1
  666. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/response-card-validation-feedback.d.ts +3 -0
  667. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/response-card-validation-feedback.d.ts.map +1 -0
  668. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/response-card-validation-feedback.js +7 -0
  669. package/node_modules/@murphai/assistant-engine/dist/assistant-codex/response-card-validation-feedback.js.map +1 -0
  670. package/node_modules/@murphai/assistant-engine/dist/assistant-codex-events.d.ts.map +1 -1
  671. package/node_modules/@murphai/assistant-engine/dist/assistant-codex-events.js +189 -486
  672. package/node_modules/@murphai/assistant-engine/dist/assistant-codex-events.js.map +1 -1
  673. package/node_modules/@murphai/assistant-engine/dist/assistant-codex.d.ts +34 -6
  674. package/node_modules/@murphai/assistant-engine/dist/assistant-codex.d.ts.map +1 -1
  675. package/node_modules/@murphai/assistant-engine/dist/assistant-codex.js +1014 -247
  676. package/node_modules/@murphai/assistant-engine/dist/assistant-codex.js.map +1 -1
  677. package/node_modules/@murphai/assistant-engine/dist/assistant-runtime-residue.d.ts +1 -1
  678. package/node_modules/@murphai/assistant-engine/dist/assistant-runtime-residue.d.ts.map +1 -1
  679. package/node_modules/@murphai/assistant-engine/dist/assistant-runtime-residue.js +1 -1
  680. package/node_modules/@murphai/assistant-engine/dist/assistant-runtime-residue.js.map +1 -1
  681. package/node_modules/@murphai/assistant-engine/dist/assistant-runtime.d.ts +2 -0
  682. package/node_modules/@murphai/assistant-engine/dist/assistant-runtime.d.ts.map +1 -1
  683. package/node_modules/@murphai/assistant-engine/dist/assistant-runtime.js +1 -0
  684. package/node_modules/@murphai/assistant-engine/dist/assistant-runtime.js.map +1 -1
  685. package/node_modules/@murphai/assistant-engine/dist/assistant-skill-assets.d.ts +23 -23
  686. package/node_modules/@murphai/assistant-engine/dist/assistant-skill-assets.d.ts.map +1 -1
  687. package/node_modules/@murphai/assistant-engine/dist/assistant-skill-assets.js +26 -26
  688. package/node_modules/@murphai/assistant-engine/dist/assistant-skill-assets.js.map +1 -1
  689. package/node_modules/@murphai/assistant-engine/dist/attachment-prompt-contracts.d.ts +27 -27
  690. package/node_modules/@murphai/assistant-engine/dist/attachment-prompt-contracts.d.ts.map +1 -1
  691. package/node_modules/@murphai/assistant-engine/dist/attachment-prompt-contracts.js +1 -1
  692. package/node_modules/@murphai/assistant-engine/dist/attachment-prompt-contracts.js.map +1 -1
  693. package/node_modules/@murphai/assistant-engine/dist/index.d.ts +8 -3
  694. package/node_modules/@murphai/assistant-engine/dist/index.d.ts.map +1 -1
  695. package/node_modules/@murphai/assistant-engine/dist/index.js +6 -1
  696. package/node_modules/@murphai/assistant-engine/dist/index.js.map +1 -1
  697. package/node_modules/@murphai/assistant-engine/dist/knowledge/documents.d.ts +1 -1
  698. package/node_modules/@murphai/assistant-engine/dist/knowledge/documents.d.ts.map +1 -1
  699. package/node_modules/@murphai/assistant-engine/dist/knowledge/documents.js +5 -1
  700. package/node_modules/@murphai/assistant-engine/dist/knowledge/documents.js.map +1 -1
  701. package/node_modules/@murphai/assistant-engine/dist/knowledge/service.d.ts +1 -0
  702. package/node_modules/@murphai/assistant-engine/dist/knowledge/service.d.ts.map +1 -1
  703. package/node_modules/@murphai/assistant-engine/dist/knowledge/service.js +16 -2
  704. package/node_modules/@murphai/assistant-engine/dist/knowledge/service.js.map +1 -1
  705. package/node_modules/@murphai/assistant-engine/dist/outbound-channel.d.ts +5 -2
  706. package/node_modules/@murphai/assistant-engine/dist/outbound-channel.d.ts.map +1 -1
  707. package/node_modules/@murphai/assistant-engine/dist/outbound-channel.js +4 -2
  708. package/node_modules/@murphai/assistant-engine/dist/outbound-channel.js.map +1 -1
  709. package/node_modules/@murphai/assistant-engine/skills/README.md +29 -0
  710. package/node_modules/@murphai/assistant-engine/skills/appointment-scheduling/SKILL.md +23 -0
  711. package/node_modules/@murphai/assistant-engine/skills/automatic-meal-capture/SKILL.md +130 -5
  712. package/node_modules/@murphai/assistant-engine/skills/behavior-followthrough/SKILL.md +157 -116
  713. package/node_modules/@murphai/assistant-engine/skills/body-composition/SKILL.md +137 -27
  714. package/node_modules/@murphai/assistant-engine/skills/body-composition/references/evidence.md +150 -0
  715. package/node_modules/@murphai/assistant-engine/skills/body-composition/references/fat-loss.md +132 -0
  716. package/node_modules/@murphai/assistant-engine/skills/body-composition/references/muscle-gain.md +135 -0
  717. package/node_modules/@murphai/assistant-engine/skills/body-composition/references/safety.md +171 -0
  718. package/node_modules/@murphai/assistant-engine/skills/body-composition/references/tracking-and-adjustment.md +193 -0
  719. package/node_modules/@murphai/assistant-engine/skills/cardiometabolic-health/SKILL.md +10 -1
  720. package/node_modules/@murphai/assistant-engine/skills/computer-use/SKILL.md +0 -4
  721. package/node_modules/@murphai/assistant-engine/skills/connected-apps/SKILL.md +86 -12
  722. package/node_modules/@murphai/assistant-engine/skills/connected-apps/references/provider-data-exports.md +209 -0
  723. package/node_modules/@murphai/assistant-engine/skills/daily-activity/SKILL.md +16 -0
  724. package/node_modules/@murphai/assistant-engine/skills/experiment-onboarding/SKILL.md +22 -9
  725. package/node_modules/@murphai/assistant-engine/skills/food-journal/SKILL.md +140 -15
  726. package/node_modules/@murphai/assistant-engine/skills/group-challenge/SKILL.md +17 -737
  727. package/node_modules/@murphai/assistant-engine/skills/group-challenge-scorecards/SKILL.md +17 -328
  728. package/node_modules/@murphai/assistant-engine/skills/group-chat/SKILL.md +18 -912
  729. package/node_modules/@murphai/assistant-engine/skills/group-newsletter/SKILL.md +16 -237
  730. package/node_modules/@murphai/assistant-engine/skills/groupchat-comedy/SKILL.md +19 -351
  731. package/node_modules/@murphai/assistant-engine/skills/hosted-low-usage/SKILL.md +309 -117
  732. package/node_modules/@murphai/assistant-engine/skills/micronutrients-supplements/SKILL.md +30 -8
  733. package/node_modules/@murphai/assistant-engine/skills/mobility-posture/SKILL.md +1 -1
  734. package/node_modules/@murphai/assistant-engine/skills/murph-family/SKILL.md +91 -26
  735. package/node_modules/@murphai/assistant-engine/skills/murph-onboarding/SKILL.md +75 -751
  736. package/node_modules/@murphai/assistant-engine/skills/murph-onboarding/references/aspiration-foundation-delegation.md +443 -0
  737. package/node_modules/@murphai/assistant-engine/skills/murph-onboarding/references/persistence-recovery-follow-up.md +155 -0
  738. package/node_modules/@murphai/assistant-engine/skills/murph-onboarding/references/return-launch-completion.md +246 -0
  739. package/node_modules/@murphai/assistant-engine/skills/music-generation/SKILL.md +31 -163
  740. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/SKILL.md +78 -7
  741. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/daily-nutrition-card-goals.md +285 -0
  742. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/daily-nutrition-card-safety.md +211 -0
  743. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/named-diets/carnivore-animal-based.md +145 -0
  744. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/named-diets/dash.md +183 -0
  745. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/named-diets/intermittent-fasting.md +153 -0
  746. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/named-diets/ketogenic.md +149 -0
  747. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/named-diets/low-carbohydrate.md +167 -0
  748. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/named-diets/mediterranean.md +141 -0
  749. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/named-diets/vegan-plant-based.md +175 -0
  750. package/node_modules/@murphai/assistant-engine/skills/nutrition-strategy/references/named-diets/vegetarian-spectrum.md +131 -0
  751. package/node_modules/@murphai/assistant-engine/skills/phone-calls/SKILL.md +47 -67
  752. package/node_modules/@murphai/assistant-engine/skills/physical-notes/SKILL.md +120 -0
  753. package/node_modules/@murphai/assistant-engine/skills/physical-therapy/SKILL.md +4 -2
  754. package/node_modules/@murphai/assistant-engine/skills/self-management-experiments/SKILL.md +19 -3
  755. package/node_modules/@murphai/assistant-engine/skills/shared/exercise-catalog-runtime.md +30 -19
  756. package/node_modules/@murphai/assistant-engine/skills/signup-link/SKILL.md +30 -0
  757. package/node_modules/@murphai/assistant-engine/skills/strength-training/SKILL.md +9 -0
  758. package/node_modules/@murphai/assistant-engine/skills/tracked-table/SKILL.md +202 -0
  759. package/node_modules/@murphai/assistant-engine/skills/workout-csv-import/SKILL.md +129 -0
  760. package/node_modules/@murphai/assistantd/dist/client.d.ts +2 -0
  761. package/node_modules/@murphai/assistantd/dist/client.d.ts.map +1 -1
  762. package/node_modules/@murphai/assistantd/dist/client.js +33 -0
  763. package/node_modules/@murphai/assistantd/dist/client.js.map +1 -1
  764. package/node_modules/@murphai/assistantd/dist/http-protocol.d.ts.map +1 -1
  765. package/node_modules/@murphai/assistantd/dist/http-protocol.js +25 -1
  766. package/node_modules/@murphai/assistantd/dist/http-protocol.js.map +1 -1
  767. package/node_modules/@murphai/clinical-records/dist/index.d.ts +660 -660
  768. package/node_modules/@murphai/clinical-records/dist/index.d.ts.map +1 -1
  769. package/node_modules/@murphai/clinical-records/dist/index.js +1 -1
  770. package/node_modules/@murphai/clinical-records/dist/index.js.map +1 -1
  771. package/node_modules/@murphai/core/dist/automation-availability.d.ts +51 -0
  772. package/node_modules/@murphai/core/dist/automation-availability.d.ts.map +1 -0
  773. package/node_modules/@murphai/core/dist/automation-availability.js +226 -0
  774. package/node_modules/@murphai/core/dist/automation-availability.js.map +1 -0
  775. package/node_modules/@murphai/core/dist/automation.d.ts +9 -2
  776. package/node_modules/@murphai/core/dist/automation.d.ts.map +1 -1
  777. package/node_modules/@murphai/core/dist/automation.js +107 -13
  778. package/node_modules/@murphai/core/dist/automation.js.map +1 -1
  779. package/node_modules/@murphai/core/dist/bank/habitat.d.ts.map +1 -1
  780. package/node_modules/@murphai/core/dist/bank/habitat.js +8 -1
  781. package/node_modules/@murphai/core/dist/bank/habitat.js.map +1 -1
  782. package/node_modules/@murphai/core/dist/domains/events/attachment-backed.d.ts.map +1 -1
  783. package/node_modules/@murphai/core/dist/domains/events/attachment-backed.js +9 -123
  784. package/node_modules/@murphai/core/dist/domains/events/attachment-backed.js.map +1 -1
  785. package/node_modules/@murphai/core/dist/domains/events/capture-lookup.d.ts +33 -0
  786. package/node_modules/@murphai/core/dist/domains/events/capture-lookup.d.ts.map +1 -1
  787. package/node_modules/@murphai/core/dist/domains/events/capture-lookup.js +119 -0
  788. package/node_modules/@murphai/core/dist/domains/events/capture-lookup.js.map +1 -1
  789. package/node_modules/@murphai/core/dist/domains/events/generated-image-capture-retention.d.ts +24 -0
  790. package/node_modules/@murphai/core/dist/domains/events/generated-image-capture-retention.d.ts.map +1 -0
  791. package/node_modules/@murphai/core/dist/domains/events/generated-image-capture-retention.js +409 -0
  792. package/node_modules/@murphai/core/dist/domains/events/generated-image-capture-retention.js.map +1 -0
  793. package/node_modules/@murphai/core/dist/domains/events/ledger.d.ts +13 -0
  794. package/node_modules/@murphai/core/dist/domains/events/ledger.d.ts.map +1 -1
  795. package/node_modules/@murphai/core/dist/domains/events/ledger.js +86 -7
  796. package/node_modules/@murphai/core/dist/domains/events/ledger.js.map +1 -1
  797. package/node_modules/@murphai/core/dist/domains/events.d.ts +6 -2
  798. package/node_modules/@murphai/core/dist/domains/events.d.ts.map +1 -1
  799. package/node_modules/@murphai/core/dist/domains/events.js +3 -1
  800. package/node_modules/@murphai/core/dist/domains/events.js.map +1 -1
  801. package/node_modules/@murphai/core/dist/domains/experiments.d.ts.map +1 -1
  802. package/node_modules/@murphai/core/dist/domains/experiments.js +5 -1
  803. package/node_modules/@murphai/core/dist/domains/experiments.js.map +1 -1
  804. package/node_modules/@murphai/core/dist/history/api.d.ts +8 -5
  805. package/node_modules/@murphai/core/dist/history/api.d.ts.map +1 -1
  806. package/node_modules/@murphai/core/dist/history/api.js +253 -20
  807. package/node_modules/@murphai/core/dist/history/api.js.map +1 -1
  808. package/node_modules/@murphai/core/dist/index.d.ts +8 -5
  809. package/node_modules/@murphai/core/dist/index.d.ts.map +1 -1
  810. package/node_modules/@murphai/core/dist/index.js +5 -3
  811. package/node_modules/@murphai/core/dist/index.js.map +1 -1
  812. package/node_modules/@murphai/core/dist/memory.d.ts.map +1 -1
  813. package/node_modules/@murphai/core/dist/memory.js +1 -0
  814. package/node_modules/@murphai/core/dist/memory.js.map +1 -1
  815. package/node_modules/@murphai/core/dist/mutations.d.ts +20 -2
  816. package/node_modules/@murphai/core/dist/mutations.d.ts.map +1 -1
  817. package/node_modules/@murphai/core/dist/mutations.js +618 -21
  818. package/node_modules/@murphai/core/dist/mutations.js.map +1 -1
  819. package/node_modules/@murphai/core/dist/operations/write-batch.d.ts +3 -0
  820. package/node_modules/@murphai/core/dist/operations/write-batch.d.ts.map +1 -1
  821. package/node_modules/@murphai/core/dist/operations/write-batch.js +33 -2
  822. package/node_modules/@murphai/core/dist/operations/write-batch.js.map +1 -1
  823. package/node_modules/@murphai/core/dist/public-mutations.d.ts +2 -1
  824. package/node_modules/@murphai/core/dist/public-mutations.d.ts.map +1 -1
  825. package/node_modules/@murphai/core/dist/public-mutations.js +7 -2
  826. package/node_modules/@murphai/core/dist/public-mutations.js.map +1 -1
  827. package/node_modules/@murphai/device-syncd/README.md +143 -0
  828. package/node_modules/@murphai/device-syncd/dist/client.d.ts +1 -0
  829. package/node_modules/@murphai/device-syncd/dist/client.d.ts.map +1 -1
  830. package/node_modules/@murphai/device-syncd/dist/client.js.map +1 -1
  831. package/node_modules/@murphai/device-syncd/dist/config/connect-routes.d.ts +25 -0
  832. package/node_modules/@murphai/device-syncd/dist/config/connect-routes.d.ts.map +1 -1
  833. package/node_modules/@murphai/device-syncd/dist/config/connect-routes.js +54 -0
  834. package/node_modules/@murphai/device-syncd/dist/config/connect-routes.js.map +1 -1
  835. package/node_modules/@murphai/device-syncd/dist/config/connect-targets.js +1 -1
  836. package/node_modules/@murphai/device-syncd/dist/config/connect-targets.js.map +1 -1
  837. package/node_modules/@murphai/device-syncd/dist/config/junction-client-config.d.ts +2 -1
  838. package/node_modules/@murphai/device-syncd/dist/config/junction-client-config.d.ts.map +1 -1
  839. package/node_modules/@murphai/device-syncd/dist/config/junction-client-config.js +2 -1
  840. package/node_modules/@murphai/device-syncd/dist/config/junction-client-config.js.map +1 -1
  841. package/node_modules/@murphai/device-syncd/dist/config/junction-config.d.ts +1 -0
  842. package/node_modules/@murphai/device-syncd/dist/config/junction-config.d.ts.map +1 -1
  843. package/node_modules/@murphai/device-syncd/dist/config/junction-config.js +9 -1
  844. package/node_modules/@murphai/device-syncd/dist/config/junction-config.js.map +1 -1
  845. package/node_modules/@murphai/device-syncd/dist/config/provider-configs.d.ts +2 -2
  846. package/node_modules/@murphai/device-syncd/dist/config/provider-configs.d.ts.map +1 -1
  847. package/node_modules/@murphai/device-syncd/dist/config/provider-configs.js +2 -2
  848. package/node_modules/@murphai/device-syncd/dist/config/provider-configs.js.map +1 -1
  849. package/node_modules/@murphai/device-syncd/dist/config/provider-env.d.ts +4 -2
  850. package/node_modules/@murphai/device-syncd/dist/config/provider-env.d.ts.map +1 -1
  851. package/node_modules/@murphai/device-syncd/dist/config/provider-env.js +6 -0
  852. package/node_modules/@murphai/device-syncd/dist/config/provider-env.js.map +1 -1
  853. package/node_modules/@murphai/device-syncd/dist/config/provider-manifests.d.ts +561 -0
  854. package/node_modules/@murphai/device-syncd/dist/config/provider-manifests.d.ts.map +1 -1
  855. package/node_modules/@murphai/device-syncd/dist/config/provider-manifests.js +203 -148
  856. package/node_modules/@murphai/device-syncd/dist/config/provider-manifests.js.map +1 -1
  857. package/node_modules/@murphai/device-syncd/dist/config/provider-types.d.ts +11 -0
  858. package/node_modules/@murphai/device-syncd/dist/config/provider-types.d.ts.map +1 -1
  859. package/node_modules/@murphai/device-syncd/dist/config/runtime-config.d.ts.map +1 -1
  860. package/node_modules/@murphai/device-syncd/dist/config/runtime-config.js +2 -2
  861. package/node_modules/@murphai/device-syncd/dist/config/runtime-config.js.map +1 -1
  862. package/node_modules/@murphai/device-syncd/dist/config/serializable-provider-configs.d.ts.map +1 -1
  863. package/node_modules/@murphai/device-syncd/dist/config/serializable-provider-configs.js +2 -0
  864. package/node_modules/@murphai/device-syncd/dist/config/serializable-provider-configs.js.map +1 -1
  865. package/node_modules/@murphai/device-syncd/dist/config.d.ts +1 -1
  866. package/node_modules/@murphai/device-syncd/dist/config.d.ts.map +1 -1
  867. package/node_modules/@murphai/device-syncd/dist/config.js +1 -1
  868. package/node_modules/@murphai/device-syncd/dist/config.js.map +1 -1
  869. package/node_modules/@murphai/device-syncd/dist/configured-provider-runtime-descriptors.d.ts +1 -1
  870. package/node_modules/@murphai/device-syncd/dist/configured-provider-runtime-descriptors.d.ts.map +1 -1
  871. package/node_modules/@murphai/device-syncd/dist/configured-provider-runtime-descriptors.js +1 -1
  872. package/node_modules/@murphai/device-syncd/dist/configured-provider-runtime-descriptors.js.map +1 -1
  873. package/node_modules/@murphai/device-syncd/dist/connect-config.d.ts +1 -1
  874. package/node_modules/@murphai/device-syncd/dist/connect-config.d.ts.map +1 -1
  875. package/node_modules/@murphai/device-syncd/dist/connect-config.js +1 -1
  876. package/node_modules/@murphai/device-syncd/dist/connect-config.js.map +1 -1
  877. package/node_modules/@murphai/device-syncd/dist/hosted-runtime.d.ts +44 -0
  878. package/node_modules/@murphai/device-syncd/dist/hosted-runtime.d.ts.map +1 -1
  879. package/node_modules/@murphai/device-syncd/dist/hosted-runtime.js +167 -1
  880. package/node_modules/@murphai/device-syncd/dist/hosted-runtime.js.map +1 -1
  881. package/node_modules/@murphai/device-syncd/dist/index.d.ts +1 -1
  882. package/node_modules/@murphai/device-syncd/dist/index.d.ts.map +1 -1
  883. package/node_modules/@murphai/device-syncd/dist/index.js +1 -1
  884. package/node_modules/@murphai/device-syncd/dist/index.js.map +1 -1
  885. package/node_modules/@murphai/device-syncd/dist/junction-historical-backfill-progress.d.ts +24 -0
  886. package/node_modules/@murphai/device-syncd/dist/junction-historical-backfill-progress.d.ts.map +1 -1
  887. package/node_modules/@murphai/device-syncd/dist/junction-historical-backfill-progress.js +444 -9
  888. package/node_modules/@murphai/device-syncd/dist/junction-historical-backfill-progress.js.map +1 -1
  889. package/node_modules/@murphai/device-syncd/dist/junction-resources.d.ts +16 -0
  890. package/node_modules/@murphai/device-syncd/dist/junction-resources.d.ts.map +1 -1
  891. package/node_modules/@murphai/device-syncd/dist/junction-resources.js +32 -0
  892. package/node_modules/@murphai/device-syncd/dist/junction-resources.js.map +1 -1
  893. package/node_modules/@murphai/device-syncd/dist/junction-timeseries-progress.d.ts +8 -0
  894. package/node_modules/@murphai/device-syncd/dist/junction-timeseries-progress.d.ts.map +1 -0
  895. package/node_modules/@murphai/device-syncd/dist/junction-timeseries-progress.js +13 -0
  896. package/node_modules/@murphai/device-syncd/dist/junction-timeseries-progress.js.map +1 -0
  897. package/node_modules/@murphai/device-syncd/dist/prepared-webhook.d.ts +29 -0
  898. package/node_modules/@murphai/device-syncd/dist/prepared-webhook.d.ts.map +1 -0
  899. package/node_modules/@murphai/device-syncd/dist/prepared-webhook.js +263 -0
  900. package/node_modules/@murphai/device-syncd/dist/prepared-webhook.js.map +1 -0
  901. package/node_modules/@murphai/device-syncd/dist/provider-configs.d.ts +1 -1
  902. package/node_modules/@murphai/device-syncd/dist/provider-configs.d.ts.map +1 -1
  903. package/node_modules/@murphai/device-syncd/dist/provider-configs.js +1 -1
  904. package/node_modules/@murphai/device-syncd/dist/provider-configs.js.map +1 -1
  905. package/node_modules/@murphai/device-syncd/dist/provider-label.d.ts +1 -0
  906. package/node_modules/@murphai/device-syncd/dist/provider-label.d.ts.map +1 -1
  907. package/node_modules/@murphai/device-syncd/dist/provider-label.js +4 -2
  908. package/node_modules/@murphai/device-syncd/dist/provider-label.js.map +1 -1
  909. package/node_modules/@murphai/device-syncd/dist/providers/junction-client.d.ts +23 -1
  910. package/node_modules/@murphai/device-syncd/dist/providers/junction-client.d.ts.map +1 -1
  911. package/node_modules/@murphai/device-syncd/dist/providers/junction-client.js +765 -192
  912. package/node_modules/@murphai/device-syncd/dist/providers/junction-client.js.map +1 -1
  913. package/node_modules/@murphai/device-syncd/dist/providers/junction.d.ts +2 -2
  914. package/node_modules/@murphai/device-syncd/dist/providers/junction.d.ts.map +1 -1
  915. package/node_modules/@murphai/device-syncd/dist/providers/junction.js +3250 -205
  916. package/node_modules/@murphai/device-syncd/dist/providers/junction.js.map +1 -1
  917. package/node_modules/@murphai/device-syncd/dist/providers/oura.d.ts.map +1 -1
  918. package/node_modules/@murphai/device-syncd/dist/providers/oura.js +2 -1
  919. package/node_modules/@murphai/device-syncd/dist/providers/oura.js.map +1 -1
  920. package/node_modules/@murphai/device-syncd/dist/providers/shared-oauth.d.ts +12 -3
  921. package/node_modules/@murphai/device-syncd/dist/providers/shared-oauth.d.ts.map +1 -1
  922. package/node_modules/@murphai/device-syncd/dist/providers/shared-oauth.js +50 -12
  923. package/node_modules/@murphai/device-syncd/dist/providers/shared-oauth.js.map +1 -1
  924. package/node_modules/@murphai/device-syncd/dist/providers/strava.d.ts +3 -1
  925. package/node_modules/@murphai/device-syncd/dist/providers/strava.d.ts.map +1 -1
  926. package/node_modules/@murphai/device-syncd/dist/providers/strava.js +51 -38
  927. package/node_modules/@murphai/device-syncd/dist/providers/strava.js.map +1 -1
  928. package/node_modules/@murphai/device-syncd/dist/providers/whoop.d.ts.map +1 -1
  929. package/node_modules/@murphai/device-syncd/dist/providers/whoop.js +11 -1
  930. package/node_modules/@murphai/device-syncd/dist/providers/whoop.js.map +1 -1
  931. package/node_modules/@murphai/device-syncd/dist/public-account.d.ts +52 -2
  932. package/node_modules/@murphai/device-syncd/dist/public-account.d.ts.map +1 -1
  933. package/node_modules/@murphai/device-syncd/dist/public-account.js +147 -1
  934. package/node_modules/@murphai/device-syncd/dist/public-account.js.map +1 -1
  935. package/node_modules/@murphai/device-syncd/dist/public-ingress.d.ts +9 -2
  936. package/node_modules/@murphai/device-syncd/dist/public-ingress.d.ts.map +1 -1
  937. package/node_modules/@murphai/device-syncd/dist/public-ingress.js +632 -199
  938. package/node_modules/@murphai/device-syncd/dist/public-ingress.js.map +1 -1
  939. package/node_modules/@murphai/device-syncd/dist/service.d.ts +17 -4
  940. package/node_modules/@murphai/device-syncd/dist/service.d.ts.map +1 -1
  941. package/node_modules/@murphai/device-syncd/dist/service.js +362 -43
  942. package/node_modules/@murphai/device-syncd/dist/service.js.map +1 -1
  943. package/node_modules/@murphai/device-syncd/dist/store/accounts.d.ts +3 -1
  944. package/node_modules/@murphai/device-syncd/dist/store/accounts.d.ts.map +1 -1
  945. package/node_modules/@murphai/device-syncd/dist/store/accounts.js +25 -2
  946. package/node_modules/@murphai/device-syncd/dist/store/accounts.js.map +1 -1
  947. package/node_modules/@murphai/device-syncd/dist/store/hosted-account-hydration.d.ts.map +1 -1
  948. package/node_modules/@murphai/device-syncd/dist/store/hosted-account-hydration.js +7 -1
  949. package/node_modules/@murphai/device-syncd/dist/store/hosted-account-hydration.js.map +1 -1
  950. package/node_modules/@murphai/device-syncd/dist/store/jobs.d.ts +13 -3
  951. package/node_modules/@murphai/device-syncd/dist/store/jobs.d.ts.map +1 -1
  952. package/node_modules/@murphai/device-syncd/dist/store/jobs.js +171 -20
  953. package/node_modules/@murphai/device-syncd/dist/store/jobs.js.map +1 -1
  954. package/node_modules/@murphai/device-syncd/dist/store/oauth-states.d.ts +3 -1
  955. package/node_modules/@murphai/device-syncd/dist/store/oauth-states.d.ts.map +1 -1
  956. package/node_modules/@murphai/device-syncd/dist/store/oauth-states.js +62 -4
  957. package/node_modules/@murphai/device-syncd/dist/store/oauth-states.js.map +1 -1
  958. package/node_modules/@murphai/device-syncd/dist/store/sources.d.ts +1 -0
  959. package/node_modules/@murphai/device-syncd/dist/store/sources.d.ts.map +1 -1
  960. package/node_modules/@murphai/device-syncd/dist/store/sources.js +56 -55
  961. package/node_modules/@murphai/device-syncd/dist/store/sources.js.map +1 -1
  962. package/node_modules/@murphai/device-syncd/dist/store/sync-state.d.ts +7 -2
  963. package/node_modules/@murphai/device-syncd/dist/store/sync-state.d.ts.map +1 -1
  964. package/node_modules/@murphai/device-syncd/dist/store/sync-state.js +82 -28
  965. package/node_modules/@murphai/device-syncd/dist/store/sync-state.js.map +1 -1
  966. package/node_modules/@murphai/device-syncd/dist/store/webhook-traces.js +2 -2
  967. package/node_modules/@murphai/device-syncd/dist/store/webhook-traces.js.map +1 -1
  968. package/node_modules/@murphai/device-syncd/dist/store.d.ts +19 -4
  969. package/node_modules/@murphai/device-syncd/dist/store.d.ts.map +1 -1
  970. package/node_modules/@murphai/device-syncd/dist/store.js +62 -11
  971. package/node_modules/@murphai/device-syncd/dist/store.js.map +1 -1
  972. package/node_modules/@murphai/device-syncd/dist/types.d.ts +169 -4
  973. package/node_modules/@murphai/device-syncd/dist/types.d.ts.map +1 -1
  974. package/node_modules/@murphai/device-syncd/dist/types.js +3 -0
  975. package/node_modules/@murphai/device-syncd/dist/types.js.map +1 -1
  976. package/node_modules/@murphai/device-syncd/package.json +8 -0
  977. package/node_modules/@murphai/health-commons/content/biomarkers/bilirubin.md +18 -0
  978. package/node_modules/@murphai/health-commons/content/biomarkers/carbon-dioxide.md +18 -0
  979. package/node_modules/@murphai/health-commons/content/biomarkers/potassium.md +18 -0
  980. package/node_modules/@murphai/health-commons/content/biomarkers/sodium.md +18 -0
  981. package/node_modules/@murphai/health-commons/content/families/general-eye-health.md +190 -0
  982. package/node_modules/@murphai/health-commons/content/families/photobiomodulation.md +97 -0
  983. package/node_modules/@murphai/health-commons/content/families/recovery-modalities.md +73 -0
  984. package/node_modules/@murphai/health-commons/content/protocols/whole-body-photobiomodulation/whole-body-red-and-near-infrared-light-exposure.md +1 -1
  985. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/cdc-contact-lens-infection-symptoms.md +20 -0
  986. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/cdc-contact-lens-prevention.md +20 -0
  987. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/cdc-stroke-signs.md +20 -0
  988. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/cochrane-blue-light-filtering-lenses.md +21 -0
  989. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/fda-buying-contact-lenses.md +20 -0
  990. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/fda-eye-drops.md +20 -0
  991. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/imi-myopia-interventions.md +20 -0
  992. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/medlineplus-eye-emergencies.md +20 -0
  993. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/medlineplus-eye-pain.md +20 -0
  994. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/nei-angle-closure-glaucoma.md +20 -0
  995. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/nei-areds2-faq.md +20 -0
  996. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/nei-contact-lenses.md +20 -0
  997. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/nei-dry-eye.md +20 -0
  998. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/nei-healthy-vision.md +21 -0
  999. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/nei-myopia.md +20 -0
  1000. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/nei-retinal-detachment.md +20 -0
  1001. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/nih-dream-omega3-dry-eye.md +21 -0
  1002. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/osha-computer-monitors.md +20 -0
  1003. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/pmc-9840372.md +22 -0
  1004. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/pmid-35597519.md +21 -0
  1005. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/pmid-36473088.md +21 -0
  1006. package/node_modules/@murphai/health-commons/content/sources/general-eye-health/pmid-37062428.md +21 -0
  1007. package/node_modules/@murphai/health-commons/content/sources/whole-body-photobiomodulation/clinicaltrials-gov-nct07047248-2026-04-23.md +0 -1
  1008. package/node_modules/@murphai/health-commons/dist/biomarker-fallback-ranges.d.ts +3 -0
  1009. package/node_modules/@murphai/health-commons/dist/biomarker-fallback-ranges.d.ts.map +1 -0
  1010. package/node_modules/@murphai/health-commons/dist/biomarker-fallback-ranges.js +2 -0
  1011. package/node_modules/@murphai/health-commons/dist/biomarker-fallback-ranges.js.map +1 -0
  1012. package/node_modules/@murphai/health-commons/dist/biomarker-runtime-artifacts.d.ts +17 -0
  1013. package/node_modules/@murphai/health-commons/dist/biomarker-runtime-artifacts.d.ts.map +1 -0
  1014. package/node_modules/@murphai/health-commons/dist/biomarker-runtime-artifacts.js +16 -0
  1015. package/node_modules/@murphai/health-commons/dist/biomarker-runtime-artifacts.js.map +1 -0
  1016. package/node_modules/@murphai/health-commons/dist/build.d.ts.map +1 -1
  1017. package/node_modules/@murphai/health-commons/dist/build.js +41 -7
  1018. package/node_modules/@murphai/health-commons/dist/build.js.map +1 -1
  1019. package/node_modules/@murphai/health-commons/dist/index.d.ts +1 -0
  1020. package/node_modules/@murphai/health-commons/dist/index.d.ts.map +1 -1
  1021. package/node_modules/@murphai/health-commons/dist/index.js +1 -0
  1022. package/node_modules/@murphai/health-commons/dist/index.js.map +1 -1
  1023. package/node_modules/@murphai/health-commons/dist/knowledge-index.d.ts +44 -0
  1024. package/node_modules/@murphai/health-commons/dist/knowledge-index.d.ts.map +1 -0
  1025. package/node_modules/@murphai/health-commons/dist/knowledge-index.js +540 -0
  1026. package/node_modules/@murphai/health-commons/dist/knowledge-index.js.map +1 -0
  1027. package/node_modules/@murphai/health-commons/dist/runtime.d.ts +17 -1
  1028. package/node_modules/@murphai/health-commons/dist/runtime.d.ts.map +1 -1
  1029. package/node_modules/@murphai/health-commons/dist/runtime.js +58 -4
  1030. package/node_modules/@murphai/health-commons/dist/runtime.js.map +1 -1
  1031. package/node_modules/@murphai/health-commons/generated/biomarker-desired-directions.json +410 -0
  1032. package/node_modules/@murphai/health-commons/generated/catalog.hash +1 -1
  1033. package/node_modules/@murphai/health-commons/generated/knowledge.sqlite +0 -0
  1034. package/node_modules/@murphai/health-commons/generated/protocol-family-graph.json +187 -46
  1035. package/node_modules/@murphai/health-commons/generated/protocol-index.json +47 -47
  1036. package/node_modules/@murphai/health-commons/generated/protocol-run-specs.json +967 -967
  1037. package/node_modules/@murphai/health-commons/generated/source-artifact-index.json +1 -1
  1038. package/node_modules/@murphai/health-commons/generated/source-identities.ndjson +28 -0
  1039. package/node_modules/@murphai/health-commons/generated/source-index.json +694 -2
  1040. package/node_modules/@murphai/health-commons/generated/web/browse/biomarkers.json +77 -9
  1041. package/node_modules/@murphai/health-commons/generated/web/browse/experiments.json +37 -37
  1042. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/absolute-basophils.json +1 -1
  1043. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/absolute-eosinophils.json +1 -1
  1044. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/absolute-immature-granulocytes.json +1 -1
  1045. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/absolute-lymphocytes.json +1 -1
  1046. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/absolute-monocytes.json +1 -1
  1047. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/absolute-neutrophils.json +1 -1
  1048. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/added-sugar-intake.json +1 -1
  1049. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/adherence.json +1 -1
  1050. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/adjusted-calcium.json +1 -1
  1051. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/adverse-symptoms.json +1 -1
  1052. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/alanine-aminotransferase.json +1 -1
  1053. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/albumin-globulin-ratio.json +1 -1
  1054. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/albumin.json +1 -1
  1055. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/alcohol-craving.json +1 -1
  1056. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/alcohol-free-days.json +1 -1
  1057. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/alcohol-intake.json +1 -1
  1058. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/alcohol-withdrawal-symptoms.json +1 -1
  1059. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/alkaline-phosphatase.json +1 -1
  1060. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ana-screen.json +1 -1
  1061. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/anion-gap.json +1 -1
  1062. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ankle-knee-to-wall-distance.json +1 -1
  1063. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/apolipoprotein-b.json +1 -1
  1064. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/arachidonic-acid-epa-ratio.json +1 -1
  1065. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/arachidonic-acid.json +1 -1
  1066. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/aspartate-aminotransferase.json +1 -1
  1067. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/basophil-percentage.json +1 -1
  1068. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/bedtime-delay.json +1 -1
  1069. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/bilirubin.json +3 -3
  1070. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/blood-glucose.json +1 -1
  1071. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/blood-ketones-beta-hydroxybutyrate.json +1 -1
  1072. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/blood-oxygen-spo2.json +1 -1
  1073. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/blood-pressure.json +1 -1
  1074. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/blood-urea-nitrogen.json +1 -1
  1075. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/body-fat-percent.json +1 -1
  1076. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/body-weight.json +1 -1
  1077. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/bun-creatinine-ratio.json +1 -1
  1078. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/c-peptide.json +1 -1
  1079. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/calcium.json +1 -1
  1080. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/carbon-dioxide.json +3 -3
  1081. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/chloride.json +1 -1
  1082. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/cholesterol-hdl-ratio.json +1 -1
  1083. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/chosen-primary-outcome-score.json +1 -1
  1084. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/continuous-glucose.json +1 -1
  1085. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/cortisol.json +1 -1
  1086. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/creatine-kinase.json +1 -1
  1087. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/daily-energy-intake-kcal.json +1 -1
  1088. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/daily-protein-g-per-kg.json +1 -1
  1089. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/daily-protein-grams.json +1 -1
  1090. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/daily-step-count.json +1 -1
  1091. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/daytime-sleepiness.json +1 -1
  1092. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/deep-sleep-minutes.json +4 -4
  1093. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/dha.json +1 -1
  1094. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/dhea-sulfate.json +1 -1
  1095. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/dietary-fiber-g-day.json +1 -1
  1096. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/digestive-comfort.json +1 -1
  1097. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/dpa.json +1 -1
  1098. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/egfr-ckd-epi.json +1 -1
  1099. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/egfr.json +1 -1
  1100. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/eosinophil-percentage.json +1 -1
  1101. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/epa.json +1 -1
  1102. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/estimated-gfr.json +1 -1
  1103. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/estimated-vo2max.json +1 -1
  1104. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/estradiol.json +1 -1
  1105. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/fasting-triglycerides.json +1 -1
  1106. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ferritin.json +1 -1
  1107. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/fib4.json +1 -1
  1108. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/follicle-stimulating-hormone.json +1 -1
  1109. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/free-t3.json +1 -1
  1110. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/free-t4.json +1 -1
  1111. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/free-testosterone.json +1 -1
  1112. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/gfr-mdrd-af-amer.json +1 -1
  1113. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/gfr-mdrd-non-af-amer.json +1 -1
  1114. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ggt.json +1 -1
  1115. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/gi-symptom-score.json +1 -1
  1116. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/gi-tolerance.json +1 -1
  1117. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/hba1c.json +1 -1
  1118. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/hbot-session-tolerability.json +1 -1
  1119. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/hdl-c.json +1 -1
  1120. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/hematocrit.json +1 -1
  1121. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/hemoglobin.json +1 -1
  1122. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/homocysteine.json +1 -1
  1123. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/hrv-rmssd.json +4 -4
  1124. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/hs-crp.json +1 -1
  1125. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/immature-granulocyte-percentage.json +1 -1
  1126. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/insulin.json +1 -1
  1127. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/iron-saturation.json +1 -1
  1128. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/iron.json +1 -1
  1129. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/lateral-knee-pain.json +1 -1
  1130. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldh.json +1 -1
  1131. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-c.json +1 -1
  1132. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-calculated.json +1 -1
  1133. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-chol-calc-nih.json +1 -1
  1134. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-cholesterol.json +1 -1
  1135. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-large-particles.json +1 -1
  1136. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-medium-particles.json +1 -1
  1137. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-particle-number.json +1 -1
  1138. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-pattern.json +1 -1
  1139. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-peak-size.json +1 -1
  1140. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/ldl-small-particles.json +1 -1
  1141. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/lead.json +1 -1
  1142. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/lean-body-mass.json +1 -1
  1143. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/lean-mass.json +1 -1
  1144. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/leg-heaviness-score.json +1 -1
  1145. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/linoleic-acid.json +1 -1
  1146. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/lipoprotein-a.json +1 -1
  1147. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/liver-enzyme-panel.json +1 -1
  1148. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/luteinizing-hormone.json +1 -1
  1149. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/lymphocyte-percentage.json +1 -1
  1150. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/macular-health-safety.json +1 -1
  1151. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/magnesium-rbc.json +1 -1
  1152. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/mean-corpuscular-hemoglobin-concentration.json +1 -1
  1153. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/mean-corpuscular-hemoglobin.json +1 -1
  1154. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/mean-corpuscular-volume.json +1 -1
  1155. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/mean-platelet-volume.json +1 -1
  1156. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/mercury.json +1 -1
  1157. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/methylmalonic-acid.json +1 -1
  1158. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/moderate-to-vigorous-activity-minutes.json +1 -1
  1159. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/monocyte-percentage.json +1 -1
  1160. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/mood-affect.json +1 -1
  1161. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/morning-blood-pressure.json +1 -1
  1162. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/muscle-soreness-score.json +1 -1
  1163. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/musculoskeletal-pain.json +1 -1
  1164. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/neutrophil-percentage.json +1 -1
  1165. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/non-hdl-c.json +1 -1
  1166. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/non-hdl-cholesterol.json +1 -1
  1167. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/omega-3-index.json +1 -1
  1168. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/omega-3-total-omegacheck.json +1 -1
  1169. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/omega-6-3-ratio.json +1 -1
  1170. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/omega-6-total.json +1 -1
  1171. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/omegacheck-total.json +1 -1
  1172. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/perceived-recovery-score.json +1 -1
  1173. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/perceived-recovery.json +1 -1
  1174. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/perceived-stiffness.json +1 -1
  1175. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/perceived-stress.json +1 -1
  1176. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/periocular-wrinkle-score.json +1 -1
  1177. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/phosphate.json +1 -1
  1178. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/platelet-count.json +1 -1
  1179. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/poc-troponin-i.json +1 -1
  1180. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/postprandial-glucose-excursion.json +1 -1
  1181. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/potassium.json +3 -3
  1182. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/pre-sleep-arousal.json +1 -1
  1183. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/prolactin.json +1 -1
  1184. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/psa-free.json +1 -1
  1185. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/psa-percent-free.json +1 -1
  1186. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/psa-total.json +1 -1
  1187. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/red-blood-cell-count.json +1 -1
  1188. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/red-cell-distribution-width.json +1 -1
  1189. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/rem-sleep-minutes.json +1 -1
  1190. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/resting-heart-rate.json +4 -4
  1191. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/rheumatoid-factor.json +1 -1
  1192. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/running-tolerance.json +1 -1
  1193. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/saturated-fat-g-day.json +1 -1
  1194. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/sedentary-time.json +1 -1
  1195. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/self-reported-mood.json +1 -1
  1196. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/serum-25-hydroxyvitamin-d.json +1 -1
  1197. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/serum-creatinine.json +1 -1
  1198. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/serum-uric-acid.json +1 -1
  1199. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/sex-hormone-binding-globulin.json +1 -1
  1200. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/shoulder-reach-distance.json +1 -1
  1201. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/sit-and-reach-distance.json +1 -1
  1202. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/skin-texture-roughness-score.json +1 -1
  1203. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/skin-tolerability-symptoms.json +1 -1
  1204. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/sleep-efficiency.json +4 -4
  1205. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/sleep-onset-latency.json +1 -1
  1206. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/sleep-quality.json +1 -1
  1207. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/sodium.json +3 -3
  1208. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/standardized-skin-photo-score.json +1 -1
  1209. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/step-floor-days.json +1 -1
  1210. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/stretching-adherence-sessions.json +1 -1
  1211. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/stretching-session-burden.json +1 -1
  1212. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/stretching-symptoms.json +1 -1
  1213. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/subjective-eye-strain.json +1 -1
  1214. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/subjective-satiety.json +1 -1
  1215. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/supplement-adherence.json +1 -1
  1216. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/task-performance.json +1 -1
  1217. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/thyroglobulin-antibodies.json +1 -1
  1218. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/thyroid-peroxidase-antibodies.json +1 -1
  1219. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/thyroid-stimulating-hormone.json +1 -1
  1220. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/toe-touch-distance.json +1 -1
  1221. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/total-cholesterol.json +1 -1
  1222. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/total-globulin.json +1 -1
  1223. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/total-iron-binding-capacity.json +1 -1
  1224. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/total-protein.json +1 -1
  1225. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/total-sleep-time.json +1 -1
  1226. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/total-testosterone.json +1 -1
  1227. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/training-performance.json +1 -1
  1228. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/training-volume.json +1 -1
  1229. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/triglycerides.json +1 -1
  1230. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/urine-albumin-creatinine-ratio.json +1 -1
  1231. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/urine-albumin-random-without-creatinine.json +1 -1
  1232. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/urine-protein.json +1 -1
  1233. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/visual-fatigue.json +1 -1
  1234. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/visual-performance.json +1 -1
  1235. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/vldl-cholesterol-calculated.json +1 -1
  1236. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/waist-circumference.json +1 -1
  1237. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/wake-after-sleep-onset.json +1 -1
  1238. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/wake-time-variability.json +1 -1
  1239. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/walking-bout-minutes.json +1 -1
  1240. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/walking-cadence.json +1 -1
  1241. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/walking-safety-events.json +1 -1
  1242. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/white-blood-cell-count.json +1 -1
  1243. package/node_modules/@murphai/health-commons/generated/web/bundles/biomarker/zinc.json +1 -1
  1244. package/node_modules/@murphai/health-commons/generated/web/bundles/measurement_method/clinic-imaging-upgrade.json +1 -1
  1245. package/node_modules/@murphai/health-commons/generated/web/bundles/measurement_method/home-standardized-photo-roi-analysis.json +1 -1
  1246. package/node_modules/@murphai/health-commons/generated/web/bundles/measurement_method/standardized-photo-score-workflow.json +1 -1
  1247. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/bryan-johnson-blueprint.json +1 -1
  1248. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/cold-plunge.json +1 -1
  1249. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/consistent-wake-time.json +1 -1
  1250. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/daily-step-floor.json +1 -1
  1251. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/finnish-sauna.json +1 -1
  1252. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/five-minute-tomorrow-list.json +1 -1
  1253. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/hyperbaric-oxygen-therapy.json +1 -1
  1254. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/morning-outdoor-light-exposure.json +1 -1
  1255. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/no-added-sugar-diet.json +1 -1
  1256. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/norwegian-4x4.json +1 -1
  1257. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/pneumatic-compression-pants.json +1 -1
  1258. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/protein-floor-high-protein-intake.json +3 -3
  1259. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/tabata-20-10-interval-training.json +1 -1
  1260. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/time-restricted-eating-18-6.json +1 -1
  1261. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/walking-after-every-meal.json +1 -1
  1262. package/node_modules/@murphai/health-commons/generated/web/bundles/protocol_variant/whole-body-red-and-near-infrared-light-exposure.json +7 -8
  1263. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/blood-oxygen-spo2/overview.json +1 -1
  1264. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/blood-oxygen-spo2/research.json +1 -1
  1265. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/deep-sleep-minutes/overview.json +2 -2
  1266. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/deep-sleep-minutes/research.json +1 -1
  1267. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/estimated-vo2max/overview.json +1 -1
  1268. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/estimated-vo2max/research.json +1 -1
  1269. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/hrv-rmssd/overview.json +2 -2
  1270. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/hrv-rmssd/research.json +1 -1
  1271. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/rem-sleep-minutes/overview.json +1 -1
  1272. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/rem-sleep-minutes/research.json +1 -1
  1273. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/resting-heart-rate/overview.json +2 -2
  1274. package/node_modules/@murphai/health-commons/generated/web/pages/biomarkers/resting-heart-rate/research.json +1 -1
  1275. package/node_modules/@murphai/health-commons/generated/web/routes/index.json +1 -1
  1276. package/node_modules/@murphai/health-commons/generated/web/shell/biomarkers/blood-oxygen-spo2.json +1 -1
  1277. package/node_modules/@murphai/health-commons/generated/web/shell/biomarkers/deep-sleep-minutes.json +1 -1
  1278. package/node_modules/@murphai/health-commons/generated/web/shell/biomarkers/estimated-vo2max.json +1 -1
  1279. package/node_modules/@murphai/health-commons/generated/web/shell/biomarkers/hrv-rmssd.json +1 -1
  1280. package/node_modules/@murphai/health-commons/generated/web/shell/biomarkers/rem-sleep-minutes.json +1 -1
  1281. package/node_modules/@murphai/health-commons/generated/web/shell/biomarkers/resting-heart-rate.json +1 -1
  1282. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/bryan-johnson-blueprint.json +1 -1
  1283. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/cold-plunge.json +1 -1
  1284. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/consistent-wake-time.json +1 -1
  1285. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/daily-step-floor.json +1 -1
  1286. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/finnish-sauna.json +1 -1
  1287. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/five-minute-tomorrow-list.json +1 -1
  1288. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/hyperbaric-oxygen-therapy.json +1 -1
  1289. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/morning-outdoor-light-exposure.json +1 -1
  1290. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/no-added-sugar-diet.json +1 -1
  1291. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/norwegian-4x4.json +1 -1
  1292. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/pneumatic-compression-pants.json +1 -1
  1293. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/protein-floor-high-protein-intake.json +1 -1
  1294. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/tabata-20-10-interval-training.json +1 -1
  1295. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/time-restricted-eating-18-6.json +1 -1
  1296. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/walking-after-every-meal.json +1 -1
  1297. package/node_modules/@murphai/health-commons/generated/web/shell/experiments/whole-body-red-and-near-infrared-light-exposure.json +3 -3
  1298. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/bryan-johnson-blueprint/protocol.json +1 -1
  1299. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/bryan-johnson-blueprint/research.json +1 -1
  1300. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/bryan-johnson-blueprint/results-public.json +2 -2
  1301. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/cold-plunge/protocol.json +1 -1
  1302. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/cold-plunge/research.json +1 -1
  1303. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/cold-plunge/results-public.json +2 -2
  1304. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/consistent-wake-time/protocol.json +1 -1
  1305. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/consistent-wake-time/research.json +1 -1
  1306. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/consistent-wake-time/results-public.json +2 -2
  1307. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/daily-step-floor/protocol.json +1 -1
  1308. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/daily-step-floor/research.json +1 -1
  1309. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/daily-step-floor/results-public.json +2 -2
  1310. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/finnish-sauna/protocol.json +1 -1
  1311. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/finnish-sauna/research.json +1 -1
  1312. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/finnish-sauna/results-public.json +2 -2
  1313. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/five-minute-tomorrow-list/protocol.json +1 -1
  1314. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/five-minute-tomorrow-list/research.json +1 -1
  1315. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/five-minute-tomorrow-list/results-public.json +2 -2
  1316. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/hyperbaric-oxygen-therapy/protocol.json +1 -1
  1317. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/hyperbaric-oxygen-therapy/research.json +1 -1
  1318. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/hyperbaric-oxygen-therapy/results-public.json +2 -2
  1319. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/morning-outdoor-light-exposure/protocol.json +1 -1
  1320. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/morning-outdoor-light-exposure/research.json +1 -1
  1321. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/morning-outdoor-light-exposure/results-public.json +2 -2
  1322. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/no-added-sugar-diet/protocol.json +1 -1
  1323. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/no-added-sugar-diet/research.json +1 -1
  1324. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/no-added-sugar-diet/results-public.json +2 -2
  1325. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/norwegian-4x4/protocol.json +1 -1
  1326. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/norwegian-4x4/research.json +1 -1
  1327. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/norwegian-4x4/results-public.json +2 -2
  1328. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/pneumatic-compression-pants/protocol.json +1 -1
  1329. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/pneumatic-compression-pants/research.json +1 -1
  1330. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/pneumatic-compression-pants/results-public.json +2 -2
  1331. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/protein-floor-high-protein-intake/protocol.json +1 -1
  1332. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/protein-floor-high-protein-intake/research.json +1 -1
  1333. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/protein-floor-high-protein-intake/results-public.json +2 -2
  1334. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/tabata-20-10-interval-training/protocol.json +1 -1
  1335. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/tabata-20-10-interval-training/research.json +1 -1
  1336. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/tabata-20-10-interval-training/results-public.json +2 -2
  1337. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/time-restricted-eating-18-6/protocol.json +1 -1
  1338. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/time-restricted-eating-18-6/research.json +1 -1
  1339. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/time-restricted-eating-18-6/results-public.json +2 -2
  1340. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/walking-after-every-meal/protocol.json +1 -1
  1341. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/walking-after-every-meal/research.json +1 -1
  1342. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/walking-after-every-meal/results-public.json +2 -2
  1343. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/whole-body-red-and-near-infrared-light-exposure/protocol.json +3 -3
  1344. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/whole-body-red-and-near-infrared-light-exposure/research.json +3 -3
  1345. package/node_modules/@murphai/health-commons/generated/web/tabs/experiments/whole-body-red-and-near-infrared-light-exposure/results-public.json +5 -5
  1346. package/node_modules/@murphai/health-commons/package.json +5 -0
  1347. package/node_modules/@murphai/health-metrics/dist/catalog.d.ts.map +1 -1
  1348. package/node_modules/@murphai/health-metrics/dist/catalog.js +22 -2
  1349. package/node_modules/@murphai/health-metrics/dist/catalog.js.map +1 -1
  1350. package/node_modules/@murphai/health-metrics/dist/definitions/activity.d.ts.map +1 -1
  1351. package/node_modules/@murphai/health-metrics/dist/definitions/activity.js +99 -0
  1352. package/node_modules/@murphai/health-metrics/dist/definitions/activity.js.map +1 -1
  1353. package/node_modules/@murphai/health-metrics/dist/definitions/body.d.ts.map +1 -1
  1354. package/node_modules/@murphai/health-metrics/dist/definitions/body.js +69 -2
  1355. package/node_modules/@murphai/health-metrics/dist/definitions/body.js.map +1 -1
  1356. package/node_modules/@murphai/health-metrics/dist/definitions/physiology.d.ts +55 -0
  1357. package/node_modules/@murphai/health-metrics/dist/definitions/physiology.d.ts.map +1 -0
  1358. package/node_modules/@murphai/health-metrics/dist/definitions/physiology.js +92 -0
  1359. package/node_modules/@murphai/health-metrics/dist/definitions/physiology.js.map +1 -0
  1360. package/node_modules/@murphai/health-metrics/dist/definitions/vitals.d.ts +1 -1
  1361. package/node_modules/@murphai/health-metrics/dist/index.d.ts +1 -0
  1362. package/node_modules/@murphai/health-metrics/dist/index.d.ts.map +1 -1
  1363. package/node_modules/@murphai/health-metrics/dist/index.js +1 -0
  1364. package/node_modules/@murphai/health-metrics/dist/index.js.map +1 -1
  1365. package/node_modules/@murphai/health-metrics/dist/lab-reference-ranges.d.ts +45 -0
  1366. package/node_modules/@murphai/health-metrics/dist/lab-reference-ranges.d.ts.map +1 -0
  1367. package/node_modules/@murphai/health-metrics/dist/lab-reference-ranges.js +502 -0
  1368. package/node_modules/@murphai/health-metrics/dist/lab-reference-ranges.js.map +1 -0
  1369. package/node_modules/@murphai/health-metrics/dist/normalize.d.ts.map +1 -1
  1370. package/node_modules/@murphai/health-metrics/dist/normalize.js +2 -0
  1371. package/node_modules/@murphai/health-metrics/dist/normalize.js.map +1 -1
  1372. package/node_modules/@murphai/health-metrics/dist/selectors.d.ts +3 -0
  1373. package/node_modules/@murphai/health-metrics/dist/selectors.d.ts.map +1 -1
  1374. package/node_modules/@murphai/health-metrics/dist/selectors.js +52 -6
  1375. package/node_modules/@murphai/health-metrics/dist/selectors.js.map +1 -1
  1376. package/node_modules/@murphai/health-metrics/dist/types.d.ts +1 -0
  1377. package/node_modules/@murphai/health-metrics/dist/types.d.ts.map +1 -1
  1378. package/node_modules/@murphai/health-metrics/dist/wearable-metric-catalog.d.ts +10 -1
  1379. package/node_modules/@murphai/health-metrics/dist/wearable-metric-catalog.d.ts.map +1 -1
  1380. package/node_modules/@murphai/health-metrics/dist/wearable-metric-catalog.js +29 -0
  1381. package/node_modules/@murphai/health-metrics/dist/wearable-metric-catalog.js.map +1 -1
  1382. package/node_modules/@murphai/importers/README.md +2 -0
  1383. package/node_modules/@murphai/importers/dist/assessment/import-assessment-response.js +1 -1
  1384. package/node_modules/@murphai/importers/dist/assessment/import-assessment-response.js.map +1 -1
  1385. package/node_modules/@murphai/importers/dist/core-port.d.ts +1 -0
  1386. package/node_modules/@murphai/importers/dist/core-port.d.ts.map +1 -1
  1387. package/node_modules/@murphai/importers/dist/core-port.js.map +1 -1
  1388. package/node_modules/@murphai/importers/dist/csv-sample-import-planner.d.ts +1 -0
  1389. package/node_modules/@murphai/importers/dist/csv-sample-import-planner.d.ts.map +1 -1
  1390. package/node_modules/@murphai/importers/dist/csv-sample-import-planner.js +1 -1
  1391. package/node_modules/@murphai/importers/dist/csv-sample-import-planner.js.map +1 -1
  1392. package/node_modules/@murphai/importers/dist/device-providers/import-device-provider-snapshot.js +1 -1
  1393. package/node_modules/@murphai/importers/dist/device-providers/import-device-provider-snapshot.js.map +1 -1
  1394. package/node_modules/@murphai/importers/dist/device-providers/index.d.ts +1 -1
  1395. package/node_modules/@murphai/importers/dist/device-providers/index.d.ts.map +1 -1
  1396. package/node_modules/@murphai/importers/dist/device-providers/index.js +1 -1
  1397. package/node_modules/@murphai/importers/dist/device-providers/index.js.map +1 -1
  1398. package/node_modules/@murphai/importers/dist/device-providers/junction-bounded-features.d.ts +27 -0
  1399. package/node_modules/@murphai/importers/dist/device-providers/junction-bounded-features.d.ts.map +1 -0
  1400. package/node_modules/@murphai/importers/dist/device-providers/junction-bounded-features.js +403 -0
  1401. package/node_modules/@murphai/importers/dist/device-providers/junction-bounded-features.js.map +1 -0
  1402. package/node_modules/@murphai/importers/dist/device-providers/junction-resources.d.ts +4 -12
  1403. package/node_modules/@murphai/importers/dist/device-providers/junction-resources.d.ts.map +1 -1
  1404. package/node_modules/@murphai/importers/dist/device-providers/junction-resources.js +18 -107
  1405. package/node_modules/@murphai/importers/dist/device-providers/junction-resources.js.map +1 -1
  1406. package/node_modules/@murphai/importers/dist/device-providers/junction-timeseries-fidelity.d.ts +285 -0
  1407. package/node_modules/@murphai/importers/dist/device-providers/junction-timeseries-fidelity.d.ts.map +1 -0
  1408. package/node_modules/@murphai/importers/dist/device-providers/junction-timeseries-fidelity.js +870 -0
  1409. package/node_modules/@murphai/importers/dist/device-providers/junction-timeseries-fidelity.js.map +1 -0
  1410. package/node_modules/@murphai/importers/dist/device-providers/junction.d.ts +38 -0
  1411. package/node_modules/@murphai/importers/dist/device-providers/junction.d.ts.map +1 -1
  1412. package/node_modules/@murphai/importers/dist/device-providers/junction.js +2682 -259
  1413. package/node_modules/@murphai/importers/dist/device-providers/junction.js.map +1 -1
  1414. package/node_modules/@murphai/importers/dist/device-providers/oura.js +1 -1
  1415. package/node_modules/@murphai/importers/dist/device-providers/oura.js.map +1 -1
  1416. package/node_modules/@murphai/importers/dist/device-providers/whoop.js +1 -1
  1417. package/node_modules/@murphai/importers/dist/device-providers/whoop.js.map +1 -1
  1418. package/node_modules/@murphai/importers/dist/document-importer.d.ts +1 -0
  1419. package/node_modules/@murphai/importers/dist/document-importer.d.ts.map +1 -1
  1420. package/node_modules/@murphai/importers/dist/document-importer.js +3 -1
  1421. package/node_modules/@murphai/importers/dist/document-importer.js.map +1 -1
  1422. package/node_modules/@murphai/importers/dist/index.d.ts +1 -0
  1423. package/node_modules/@murphai/importers/dist/index.d.ts.map +1 -1
  1424. package/node_modules/@murphai/importers/dist/index.js +1 -0
  1425. package/node_modules/@murphai/importers/dist/index.js.map +1 -1
  1426. package/node_modules/@murphai/importers/dist/meal-importer.d.ts.map +1 -1
  1427. package/node_modules/@murphai/importers/dist/meal-importer.js +2 -1
  1428. package/node_modules/@murphai/importers/dist/meal-importer.js.map +1 -1
  1429. package/node_modules/@murphai/importers/dist/preset-registry.js +1 -1
  1430. package/node_modules/@murphai/importers/dist/preset-registry.js.map +1 -1
  1431. package/node_modules/@murphai/importers/dist/shared.d.ts +1 -1
  1432. package/node_modules/@murphai/importers/dist/shared.d.ts.map +1 -1
  1433. package/node_modules/@murphai/importers/dist/shared.js +1 -1
  1434. package/node_modules/@murphai/importers/dist/shared.js.map +1 -1
  1435. package/node_modules/@murphai/importers/dist/workout-csv-planner.d.ts +49 -0
  1436. package/node_modules/@murphai/importers/dist/workout-csv-planner.d.ts.map +1 -0
  1437. package/node_modules/@murphai/importers/dist/workout-csv-planner.js +860 -0
  1438. package/node_modules/@murphai/importers/dist/workout-csv-planner.js.map +1 -0
  1439. package/node_modules/@murphai/inbox-services/dist/inbox-app/bootstrap-doctor-strategies.d.ts +2 -5
  1440. package/node_modules/@murphai/inbox-services/dist/inbox-app/bootstrap-doctor-strategies.d.ts.map +1 -1
  1441. package/node_modules/@murphai/inbox-services/dist/inbox-app/bootstrap-doctor-strategies.js +3 -50
  1442. package/node_modules/@murphai/inbox-services/dist/inbox-app/bootstrap-doctor-strategies.js.map +1 -1
  1443. package/node_modules/@murphai/inbox-services/dist/inbox-app/bootstrap-doctor.d.ts.map +1 -1
  1444. package/node_modules/@murphai/inbox-services/dist/inbox-app/bootstrap-doctor.js +9 -11
  1445. package/node_modules/@murphai/inbox-services/dist/inbox-app/bootstrap-doctor.js.map +1 -1
  1446. package/node_modules/@murphai/inbox-services/dist/inbox-app/environment.d.ts.map +1 -1
  1447. package/node_modules/@murphai/inbox-services/dist/inbox-app/environment.js +0 -160
  1448. package/node_modules/@murphai/inbox-services/dist/inbox-app/environment.js.map +1 -1
  1449. package/node_modules/@murphai/inbox-services/dist/inbox-app/runtime.d.ts.map +1 -1
  1450. package/node_modules/@murphai/inbox-services/dist/inbox-app/runtime.js +2 -4
  1451. package/node_modules/@murphai/inbox-services/dist/inbox-app/runtime.js.map +1 -1
  1452. package/node_modules/@murphai/inbox-services/dist/inbox-app/sources.d.ts +1 -1
  1453. package/node_modules/@murphai/inbox-services/dist/inbox-app/sources.d.ts.map +1 -1
  1454. package/node_modules/@murphai/inbox-services/dist/inbox-app/sources.js +2 -32
  1455. package/node_modules/@murphai/inbox-services/dist/inbox-app/sources.js.map +1 -1
  1456. package/node_modules/@murphai/inbox-services/dist/inbox-app/types.d.ts +2 -79
  1457. package/node_modules/@murphai/inbox-services/dist/inbox-app/types.d.ts.map +1 -1
  1458. package/node_modules/@murphai/inbox-services/dist/inbox-app/types.js +0 -1
  1459. package/node_modules/@murphai/inbox-services/dist/inbox-app/types.js.map +1 -1
  1460. package/node_modules/@murphai/inbox-services/dist/inbox-services/connectors.d.ts +1 -2
  1461. package/node_modules/@murphai/inbox-services/dist/inbox-services/connectors.d.ts.map +1 -1
  1462. package/node_modules/@murphai/inbox-services/dist/inbox-services/connectors.js +15 -37
  1463. package/node_modules/@murphai/inbox-services/dist/inbox-services/connectors.js.map +1 -1
  1464. package/node_modules/@murphai/inbox-services/dist/inbox-services/promotions.d.ts +21 -21
  1465. package/node_modules/@murphai/inbox-services/dist/inbox-services/promotions.d.ts.map +1 -1
  1466. package/node_modules/@murphai/inbox-services/dist/inbox-services/promotions.js +1 -1
  1467. package/node_modules/@murphai/inbox-services/dist/inbox-services/promotions.js.map +1 -1
  1468. package/node_modules/@murphai/inbox-services/dist/inbox-services/shared.d.ts +1 -1
  1469. package/node_modules/@murphai/inbox-services/dist/inbox-services/shared.d.ts.map +1 -1
  1470. package/node_modules/@murphai/inbox-services/dist/inbox-services/shared.js +0 -1
  1471. package/node_modules/@murphai/inbox-services/dist/inbox-services/shared.js.map +1 -1
  1472. package/node_modules/@murphai/inbox-services/dist/index.d.ts +1 -1
  1473. package/node_modules/@murphai/inbox-services/dist/index.d.ts.map +1 -1
  1474. package/node_modules/@murphai/inboxd/README.md +3 -3
  1475. package/node_modules/@murphai/inboxd/dist/connectors/email/normalize-parsed.d.ts.map +1 -1
  1476. package/node_modules/@murphai/inboxd/dist/connectors/email/normalize-parsed.js +56 -5
  1477. package/node_modules/@murphai/inboxd/dist/connectors/email/normalize-parsed.js.map +1 -1
  1478. package/node_modules/@murphai/inboxd/dist/connectors/linq/normalize.js +8 -0
  1479. package/node_modules/@murphai/inboxd/dist/connectors/linq/normalize.js.map +1 -1
  1480. package/node_modules/@murphai/inboxd/dist/connectors/telegram/normalize.d.ts +1 -0
  1481. package/node_modules/@murphai/inboxd/dist/connectors/telegram/normalize.d.ts.map +1 -1
  1482. package/node_modules/@murphai/inboxd/dist/connectors/telegram/normalize.js +1 -0
  1483. package/node_modules/@murphai/inboxd/dist/connectors/telegram/normalize.js.map +1 -1
  1484. package/node_modules/@murphai/inboxd/dist/index.d.ts +0 -5
  1485. package/node_modules/@murphai/inboxd/dist/index.d.ts.map +1 -1
  1486. package/node_modules/@murphai/inboxd/dist/index.js +0 -2
  1487. package/node_modules/@murphai/inboxd/dist/index.js.map +1 -1
  1488. package/node_modules/@murphai/inboxd/dist/indexing/attachment-storage-normalizer.d.ts.map +1 -1
  1489. package/node_modules/@murphai/inboxd/dist/indexing/attachment-storage-normalizer.js +141 -4
  1490. package/node_modules/@murphai/inboxd/dist/indexing/attachment-storage-normalizer.js.map +1 -1
  1491. package/node_modules/@murphai/messaging-ingress/README.md +5 -1
  1492. package/node_modules/@murphai/messaging-ingress/dist/linq-webhook.d.ts +27 -1
  1493. package/node_modules/@murphai/messaging-ingress/dist/linq-webhook.d.ts.map +1 -1
  1494. package/node_modules/@murphai/messaging-ingress/dist/linq-webhook.js +164 -17
  1495. package/node_modules/@murphai/messaging-ingress/dist/linq-webhook.js.map +1 -1
  1496. package/node_modules/@murphai/messaging-ingress/dist/telegram-webhook-payload.d.ts +1 -0
  1497. package/node_modules/@murphai/messaging-ingress/dist/telegram-webhook-payload.d.ts.map +1 -1
  1498. package/node_modules/@murphai/messaging-ingress/dist/telegram-webhook-payload.js +2 -0
  1499. package/node_modules/@murphai/messaging-ingress/dist/telegram-webhook-payload.js.map +1 -1
  1500. package/node_modules/@murphai/operator-config/dist/assistant/codex-resume-state.d.ts +3 -3
  1501. package/node_modules/@murphai/operator-config/dist/assistant/codex-resume-state.d.ts.map +1 -1
  1502. package/node_modules/@murphai/operator-config/dist/assistant/codex-resume-state.js +1 -1
  1503. package/node_modules/@murphai/operator-config/dist/assistant/codex-resume-state.js.map +1 -1
  1504. package/node_modules/@murphai/operator-config/dist/assistant/current-delivery-route.d.ts +1 -1
  1505. package/node_modules/@murphai/operator-config/dist/assistant/current-delivery-route.d.ts.map +1 -1
  1506. package/node_modules/@murphai/operator-config/dist/assistant/current-delivery-route.js +7 -19
  1507. package/node_modules/@murphai/operator-config/dist/assistant/current-delivery-route.js.map +1 -1
  1508. package/node_modules/@murphai/operator-config/dist/assistant/hosted-config.d.ts +31 -33
  1509. package/node_modules/@murphai/operator-config/dist/assistant/hosted-config.d.ts.map +1 -1
  1510. package/node_modules/@murphai/operator-config/dist/assistant/hosted-config.js +5 -8
  1511. package/node_modules/@murphai/operator-config/dist/assistant/hosted-config.js.map +1 -1
  1512. package/node_modules/@murphai/operator-config/dist/assistant/provider-config.d.ts +1 -15
  1513. package/node_modules/@murphai/operator-config/dist/assistant/provider-config.d.ts.map +1 -1
  1514. package/node_modules/@murphai/operator-config/dist/assistant/provider-config.js +52 -84
  1515. package/node_modules/@murphai/operator-config/dist/assistant/provider-config.js.map +1 -1
  1516. package/node_modules/@murphai/operator-config/dist/assistant/target-runtime.d.ts +31 -48
  1517. package/node_modules/@murphai/operator-config/dist/assistant/target-runtime.d.ts.map +1 -1
  1518. package/node_modules/@murphai/operator-config/dist/assistant/target-runtime.js +33 -56
  1519. package/node_modules/@murphai/operator-config/dist/assistant/target-runtime.js.map +1 -1
  1520. package/node_modules/@murphai/operator-config/dist/assistant-backend.d.ts +11 -11
  1521. package/node_modules/@murphai/operator-config/dist/assistant-backend.d.ts.map +1 -1
  1522. package/node_modules/@murphai/operator-config/dist/assistant-backend.js +33 -45
  1523. package/node_modules/@murphai/operator-config/dist/assistant-backend.js.map +1 -1
  1524. package/node_modules/@murphai/operator-config/dist/assistant-cli-contracts.d.ts +1713 -1566
  1525. package/node_modules/@murphai/operator-config/dist/assistant-cli-contracts.d.ts.map +1 -1
  1526. package/node_modules/@murphai/operator-config/dist/assistant-cli-contracts.js +193 -23
  1527. package/node_modules/@murphai/operator-config/dist/assistant-cli-contracts.js.map +1 -1
  1528. package/node_modules/@murphai/operator-config/dist/assistant-response-cards.d.ts +445 -0
  1529. package/node_modules/@murphai/operator-config/dist/assistant-response-cards.d.ts.map +1 -0
  1530. package/node_modules/@murphai/operator-config/dist/assistant-response-cards.js +1030 -0
  1531. package/node_modules/@murphai/operator-config/dist/assistant-response-cards.js.map +1 -0
  1532. package/node_modules/@murphai/operator-config/dist/command-helpers.d.ts +4 -2
  1533. package/node_modules/@murphai/operator-config/dist/command-helpers.d.ts.map +1 -1
  1534. package/node_modules/@murphai/operator-config/dist/command-helpers.js +36 -1
  1535. package/node_modules/@murphai/operator-config/dist/command-helpers.js.map +1 -1
  1536. package/node_modules/@murphai/operator-config/dist/device-cli-contracts.d.ts +181 -181
  1537. package/node_modules/@murphai/operator-config/dist/device-cli-contracts.d.ts.map +1 -1
  1538. package/node_modules/@murphai/operator-config/dist/device-cli-contracts.js +1 -1
  1539. package/node_modules/@murphai/operator-config/dist/device-cli-contracts.js.map +1 -1
  1540. package/node_modules/@murphai/operator-config/dist/device-sync-client.js +1 -1
  1541. package/node_modules/@murphai/operator-config/dist/device-sync-client.js.map +1 -1
  1542. package/node_modules/@murphai/operator-config/dist/elevenlabs-runtime.d.ts +3 -0
  1543. package/node_modules/@murphai/operator-config/dist/elevenlabs-runtime.d.ts.map +1 -1
  1544. package/node_modules/@murphai/operator-config/dist/elevenlabs-runtime.js +301 -63
  1545. package/node_modules/@murphai/operator-config/dist/elevenlabs-runtime.js.map +1 -1
  1546. package/node_modules/@murphai/operator-config/dist/hosted-assistant-config-constants.d.ts +3 -2
  1547. package/node_modules/@murphai/operator-config/dist/hosted-assistant-config-constants.d.ts.map +1 -1
  1548. package/node_modules/@murphai/operator-config/dist/hosted-assistant-config-constants.js +3 -0
  1549. package/node_modules/@murphai/operator-config/dist/hosted-assistant-config-constants.js.map +1 -1
  1550. package/node_modules/@murphai/operator-config/dist/hosted-assistant-config.d.ts.map +1 -1
  1551. package/node_modules/@murphai/operator-config/dist/hosted-assistant-config.js +2 -6
  1552. package/node_modules/@murphai/operator-config/dist/hosted-assistant-config.js.map +1 -1
  1553. package/node_modules/@murphai/operator-config/dist/http-json-retry.d.ts +7 -2
  1554. package/node_modules/@murphai/operator-config/dist/http-json-retry.d.ts.map +1 -1
  1555. package/node_modules/@murphai/operator-config/dist/http-json-retry.js +33 -14
  1556. package/node_modules/@murphai/operator-config/dist/http-json-retry.js.map +1 -1
  1557. package/node_modules/@murphai/operator-config/dist/inbox-cli-contracts.d.ts +427 -462
  1558. package/node_modules/@murphai/operator-config/dist/inbox-cli-contracts.d.ts.map +1 -1
  1559. package/node_modules/@murphai/operator-config/dist/inbox-cli-contracts.js +2 -14
  1560. package/node_modules/@murphai/operator-config/dist/inbox-cli-contracts.js.map +1 -1
  1561. package/node_modules/@murphai/operator-config/dist/linq-runtime.d.ts +35 -1
  1562. package/node_modules/@murphai/operator-config/dist/linq-runtime.d.ts.map +1 -1
  1563. package/node_modules/@murphai/operator-config/dist/linq-runtime.js +1115 -180
  1564. package/node_modules/@murphai/operator-config/dist/linq-runtime.js.map +1 -1
  1565. package/node_modules/@murphai/operator-config/dist/message-formatting.d.ts +1 -0
  1566. package/node_modules/@murphai/operator-config/dist/message-formatting.d.ts.map +1 -1
  1567. package/node_modules/@murphai/operator-config/dist/message-formatting.js +3 -1
  1568. package/node_modules/@murphai/operator-config/dist/message-formatting.js.map +1 -1
  1569. package/node_modules/@murphai/operator-config/dist/message-table-fallback.d.ts +7 -0
  1570. package/node_modules/@murphai/operator-config/dist/message-table-fallback.d.ts.map +1 -0
  1571. package/node_modules/@murphai/operator-config/dist/message-table-fallback.js +109 -0
  1572. package/node_modules/@murphai/operator-config/dist/message-table-fallback.js.map +1 -0
  1573. package/node_modules/@murphai/operator-config/dist/operator-config/self-delivery-targets.d.ts +12 -12
  1574. package/node_modules/@murphai/operator-config/dist/operator-config/self-delivery-targets.d.ts.map +1 -1
  1575. package/node_modules/@murphai/operator-config/dist/operator-config/self-delivery-targets.js +1 -1
  1576. package/node_modules/@murphai/operator-config/dist/operator-config/self-delivery-targets.js.map +1 -1
  1577. package/node_modules/@murphai/operator-config/dist/operator-config.d.ts +50 -53
  1578. package/node_modules/@murphai/operator-config/dist/operator-config.d.ts.map +1 -1
  1579. package/node_modules/@murphai/operator-config/dist/operator-config.js +4 -5
  1580. package/node_modules/@murphai/operator-config/dist/operator-config.js.map +1 -1
  1581. package/node_modules/@murphai/operator-config/dist/setup-cli-contracts.d.ts +225 -226
  1582. package/node_modules/@murphai/operator-config/dist/setup-cli-contracts.d.ts.map +1 -1
  1583. package/node_modules/@murphai/operator-config/dist/setup-cli-contracts.js +2 -2
  1584. package/node_modules/@murphai/operator-config/dist/setup-cli-contracts.js.map +1 -1
  1585. package/node_modules/@murphai/operator-config/dist/setup-runtime-env.d.ts.map +1 -1
  1586. package/node_modules/@murphai/operator-config/dist/setup-runtime-env.js +0 -19
  1587. package/node_modules/@murphai/operator-config/dist/setup-runtime-env.js.map +1 -1
  1588. package/node_modules/@murphai/operator-config/dist/vault-cli-contracts.d.ts +336 -294
  1589. package/node_modules/@murphai/operator-config/dist/vault-cli-contracts.d.ts.map +1 -1
  1590. package/node_modules/@murphai/operator-config/dist/vault-cli-contracts.js +36 -8
  1591. package/node_modules/@murphai/operator-config/dist/vault-cli-contracts.js.map +1 -1
  1592. package/node_modules/@murphai/operator-config/dist/workout-action-binding.d.ts +5 -0
  1593. package/node_modules/@murphai/operator-config/dist/workout-action-binding.d.ts.map +1 -0
  1594. package/node_modules/@murphai/operator-config/dist/workout-action-binding.js +84 -0
  1595. package/node_modules/@murphai/operator-config/dist/workout-action-binding.js.map +1 -0
  1596. package/node_modules/@murphai/operator-config/package.json +10 -5
  1597. package/node_modules/@murphai/parsers/dist/adapters/ffmpeg.d.ts +2 -0
  1598. package/node_modules/@murphai/parsers/dist/adapters/ffmpeg.d.ts.map +1 -1
  1599. package/node_modules/@murphai/parsers/dist/adapters/ffmpeg.js +18 -0
  1600. package/node_modules/@murphai/parsers/dist/adapters/ffmpeg.js.map +1 -1
  1601. package/node_modules/@murphai/query/README.md +9 -0
  1602. package/node_modules/@murphai/query/dist/automation.d.ts +5 -2
  1603. package/node_modules/@murphai/query/dist/automation.d.ts.map +1 -1
  1604. package/node_modules/@murphai/query/dist/automation.js +33 -8
  1605. package/node_modules/@murphai/query/dist/automation.js.map +1 -1
  1606. package/node_modules/@murphai/query/dist/browser-biomarkers.d.ts +2 -2
  1607. package/node_modules/@murphai/query/dist/browser-biomarkers.d.ts.map +1 -1
  1608. package/node_modules/@murphai/query/dist/browser-biomarkers.js +1 -1
  1609. package/node_modules/@murphai/query/dist/browser-biomarkers.js.map +1 -1
  1610. package/node_modules/@murphai/query/dist/browser-experiments.d.ts +2 -2
  1611. package/node_modules/@murphai/query/dist/browser-experiments.d.ts.map +1 -1
  1612. package/node_modules/@murphai/query/dist/browser-experiments.js +1 -1
  1613. package/node_modules/@murphai/query/dist/browser-experiments.js.map +1 -1
  1614. package/node_modules/@murphai/query/dist/browser-murph-age.d.ts +1 -1
  1615. package/node_modules/@murphai/query/dist/browser-murph-age.d.ts.map +1 -1
  1616. package/node_modules/@murphai/query/dist/browser-overview.d.ts +2 -1
  1617. package/node_modules/@murphai/query/dist/browser-overview.d.ts.map +1 -1
  1618. package/node_modules/@murphai/query/dist/browser-replica/biomarker-panel.d.ts +2 -2
  1619. package/node_modules/@murphai/query/dist/browser-replica/biomarker-panel.d.ts.map +1 -1
  1620. package/node_modules/@murphai/query/dist/browser-replica/build.d.ts.map +1 -1
  1621. package/node_modules/@murphai/query/dist/browser-replica/build.js +45 -27
  1622. package/node_modules/@murphai/query/dist/browser-replica/build.js.map +1 -1
  1623. package/node_modules/@murphai/query/dist/browser-replica/client-overview.d.ts +3 -3
  1624. package/node_modules/@murphai/query/dist/browser-replica/client-overview.d.ts.map +1 -1
  1625. package/node_modules/@murphai/query/dist/browser-replica/client-overview.js +3 -0
  1626. package/node_modules/@murphai/query/dist/browser-replica/client-overview.js.map +1 -1
  1627. package/node_modules/@murphai/query/dist/browser-replica/device-metrics.d.ts +2 -2
  1628. package/node_modules/@murphai/query/dist/browser-replica/device-metrics.d.ts.map +1 -1
  1629. package/node_modules/@murphai/query/dist/browser-replica/device-metrics.js.map +1 -1
  1630. package/node_modules/@murphai/query/dist/browser-replica/experiment-run-cards.d.ts +8 -0
  1631. package/node_modules/@murphai/query/dist/browser-replica/experiment-run-cards.d.ts.map +1 -0
  1632. package/node_modules/@murphai/query/dist/browser-replica/experiment-run-cards.js +548 -0
  1633. package/node_modules/@murphai/query/dist/browser-replica/experiment-run-cards.js.map +1 -0
  1634. package/node_modules/@murphai/query/dist/browser-replica/experiments.d.ts +22 -2
  1635. package/node_modules/@murphai/query/dist/browser-replica/experiments.d.ts.map +1 -1
  1636. package/node_modules/@murphai/query/dist/browser-replica/experiments.js +209 -63
  1637. package/node_modules/@murphai/query/dist/browser-replica/experiments.js.map +1 -1
  1638. package/node_modules/@murphai/query/dist/browser-replica/lab-result-status.d.ts +11 -0
  1639. package/node_modules/@murphai/query/dist/browser-replica/lab-result-status.d.ts.map +1 -0
  1640. package/node_modules/@murphai/query/dist/browser-replica/lab-result-status.js +233 -0
  1641. package/node_modules/@murphai/query/dist/browser-replica/lab-result-status.js.map +1 -0
  1642. package/node_modules/@murphai/query/dist/browser-replica/lab-results.d.ts +4 -3
  1643. package/node_modules/@murphai/query/dist/browser-replica/lab-results.d.ts.map +1 -1
  1644. package/node_modules/@murphai/query/dist/browser-replica/lab-results.js +24 -5
  1645. package/node_modules/@murphai/query/dist/browser-replica/lab-results.js.map +1 -1
  1646. package/node_modules/@murphai/query/dist/browser-replica/metric-buckets.d.ts +14 -0
  1647. package/node_modules/@murphai/query/dist/browser-replica/metric-buckets.d.ts.map +1 -0
  1648. package/node_modules/@murphai/query/dist/browser-replica/metric-buckets.js +25 -0
  1649. package/node_modules/@murphai/query/dist/browser-replica/metric-buckets.js.map +1 -0
  1650. package/node_modules/@murphai/query/dist/browser-replica/murph-age.d.ts +2 -2
  1651. package/node_modules/@murphai/query/dist/browser-replica/murph-age.d.ts.map +1 -1
  1652. package/node_modules/@murphai/query/dist/browser-replica/murph-age.js.map +1 -1
  1653. package/node_modules/@murphai/query/dist/browser-replica/parse.d.ts +8 -0
  1654. package/node_modules/@murphai/query/dist/browser-replica/parse.d.ts.map +1 -1
  1655. package/node_modules/@murphai/query/dist/browser-replica/parse.js +327 -7
  1656. package/node_modules/@murphai/query/dist/browser-replica/parse.js.map +1 -1
  1657. package/node_modules/@murphai/query/dist/browser-replica/query.d.ts +24 -1
  1658. package/node_modules/@murphai/query/dist/browser-replica/query.d.ts.map +1 -1
  1659. package/node_modules/@murphai/query/dist/browser-replica/query.js +246 -41
  1660. package/node_modules/@murphai/query/dist/browser-replica/query.js.map +1 -1
  1661. package/node_modules/@murphai/query/dist/browser-replica/search-row.d.ts +3 -0
  1662. package/node_modules/@murphai/query/dist/browser-replica/search-row.d.ts.map +1 -0
  1663. package/node_modules/@murphai/query/dist/browser-replica/search-row.js +16 -0
  1664. package/node_modules/@murphai/query/dist/browser-replica/search-row.js.map +1 -0
  1665. package/node_modules/@murphai/query/dist/browser-replica/shards.d.ts +76 -0
  1666. package/node_modules/@murphai/query/dist/browser-replica/shards.d.ts.map +1 -0
  1667. package/node_modules/@murphai/query/dist/browser-replica/shards.js +232 -0
  1668. package/node_modules/@murphai/query/dist/browser-replica/shards.js.map +1 -0
  1669. package/node_modules/@murphai/query/dist/browser-replica/shared.d.ts +143 -9
  1670. package/node_modules/@murphai/query/dist/browser-replica/shared.d.ts.map +1 -1
  1671. package/node_modules/@murphai/query/dist/browser-replica/shared.js +1 -0
  1672. package/node_modules/@murphai/query/dist/browser-replica/shared.js.map +1 -1
  1673. package/node_modules/@murphai/query/dist/browser-replica/tracked-experiments.d.ts +3 -3
  1674. package/node_modules/@murphai/query/dist/browser-replica/tracked-experiments.d.ts.map +1 -1
  1675. package/node_modules/@murphai/query/dist/browser-replica/tracked-experiments.js.map +1 -1
  1676. package/node_modules/@murphai/query/dist/browser-replica/training.d.ts +7 -0
  1677. package/node_modules/@murphai/query/dist/browser-replica/training.d.ts.map +1 -0
  1678. package/node_modules/@murphai/query/dist/browser-replica/training.js +241 -0
  1679. package/node_modules/@murphai/query/dist/browser-replica/training.js.map +1 -0
  1680. package/node_modules/@murphai/query/dist/browser-replica/views.d.ts +5 -5
  1681. package/node_modules/@murphai/query/dist/browser-replica/views.d.ts.map +1 -1
  1682. package/node_modules/@murphai/query/dist/browser-replica/views.js +3 -0
  1683. package/node_modules/@murphai/query/dist/browser-replica/views.js.map +1 -1
  1684. package/node_modules/@murphai/query/dist/browser-replica-client.d.ts +11 -4
  1685. package/node_modules/@murphai/query/dist/browser-replica-client.d.ts.map +1 -1
  1686. package/node_modules/@murphai/query/dist/browser-replica-client.js +7 -3
  1687. package/node_modules/@murphai/query/dist/browser-replica-client.js.map +1 -1
  1688. package/node_modules/@murphai/query/dist/browser-replica-server.d.ts +5 -0
  1689. package/node_modules/@murphai/query/dist/browser-replica-server.d.ts.map +1 -0
  1690. package/node_modules/@murphai/query/dist/browser-replica-server.js +5 -0
  1691. package/node_modules/@murphai/query/dist/browser-replica-server.js.map +1 -0
  1692. package/node_modules/@murphai/query/dist/browser-replica.d.ts +13 -5
  1693. package/node_modules/@murphai/query/dist/browser-replica.d.ts.map +1 -1
  1694. package/node_modules/@murphai/query/dist/browser-replica.js +9 -4
  1695. package/node_modules/@murphai/query/dist/browser-replica.js.map +1 -1
  1696. package/node_modules/@murphai/query/dist/browser.d.ts +2 -2
  1697. package/node_modules/@murphai/query/dist/browser.d.ts.map +1 -1
  1698. package/node_modules/@murphai/query/dist/browser.js +1 -1
  1699. package/node_modules/@murphai/query/dist/browser.js.map +1 -1
  1700. package/node_modules/@murphai/query/dist/canonical-observation-metrics.d.ts +16 -0
  1701. package/node_modules/@murphai/query/dist/canonical-observation-metrics.d.ts.map +1 -0
  1702. package/node_modules/@murphai/query/dist/canonical-observation-metrics.js +70 -0
  1703. package/node_modules/@murphai/query/dist/canonical-observation-metrics.js.map +1 -0
  1704. package/node_modules/@murphai/query/dist/experiment-adherence.d.ts +20 -0
  1705. package/node_modules/@murphai/query/dist/experiment-adherence.d.ts.map +1 -1
  1706. package/node_modules/@murphai/query/dist/experiment-adherence.js +175 -29
  1707. package/node_modules/@murphai/query/dist/experiment-adherence.js.map +1 -1
  1708. package/node_modules/@murphai/query/dist/experiment-progress-card.d.ts +1 -0
  1709. package/node_modules/@murphai/query/dist/experiment-progress-card.d.ts.map +1 -1
  1710. package/node_modules/@murphai/query/dist/experiment-progress-card.js +1 -0
  1711. package/node_modules/@murphai/query/dist/experiment-progress-card.js.map +1 -1
  1712. package/node_modules/@murphai/query/dist/experiments.d.ts.map +1 -1
  1713. package/node_modules/@murphai/query/dist/experiments.js +46 -22
  1714. package/node_modules/@murphai/query/dist/experiments.js.map +1 -1
  1715. package/node_modules/@murphai/query/dist/group-weekly.d.ts.map +1 -1
  1716. package/node_modules/@murphai/query/dist/group-weekly.js +52 -1
  1717. package/node_modules/@murphai/query/dist/group-weekly.js.map +1 -1
  1718. package/node_modules/@murphai/query/dist/health/shared.js +1 -1
  1719. package/node_modules/@murphai/query/dist/health/shared.js.map +1 -1
  1720. package/node_modules/@murphai/query/dist/index.d.ts +21 -4
  1721. package/node_modules/@murphai/query/dist/index.d.ts.map +1 -1
  1722. package/node_modules/@murphai/query/dist/index.js +14 -3
  1723. package/node_modules/@murphai/query/dist/index.js.map +1 -1
  1724. package/node_modules/@murphai/query/dist/knowledge-contracts.d.ts +78 -75
  1725. package/node_modules/@murphai/query/dist/knowledge-contracts.d.ts.map +1 -1
  1726. package/node_modules/@murphai/query/dist/knowledge-contracts.js +2 -1
  1727. package/node_modules/@murphai/query/dist/knowledge-contracts.js.map +1 -1
  1728. package/node_modules/@murphai/query/dist/knowledge-graph.d.ts +1 -0
  1729. package/node_modules/@murphai/query/dist/knowledge-graph.d.ts.map +1 -1
  1730. package/node_modules/@murphai/query/dist/knowledge-graph.js +17 -1
  1731. package/node_modules/@murphai/query/dist/knowledge-graph.js.map +1 -1
  1732. package/node_modules/@murphai/query/dist/meal-nutrition.d.ts +26 -0
  1733. package/node_modules/@murphai/query/dist/meal-nutrition.d.ts.map +1 -1
  1734. package/node_modules/@murphai/query/dist/meal-nutrition.js +111 -5
  1735. package/node_modules/@murphai/query/dist/meal-nutrition.js.map +1 -1
  1736. package/node_modules/@murphai/query/dist/metrics/index.d.ts.map +1 -1
  1737. package/node_modules/@murphai/query/dist/metrics/index.js +14 -1
  1738. package/node_modules/@murphai/query/dist/metrics/index.js.map +1 -1
  1739. package/node_modules/@murphai/query/dist/metrics/projection.d.ts.map +1 -1
  1740. package/node_modules/@murphai/query/dist/metrics/projection.js +110 -3
  1741. package/node_modules/@murphai/query/dist/metrics/projection.js.map +1 -1
  1742. package/node_modules/@murphai/query/dist/personal-patterns.d.ts +55 -0
  1743. package/node_modules/@murphai/query/dist/personal-patterns.d.ts.map +1 -0
  1744. package/node_modules/@murphai/query/dist/personal-patterns.js +401 -0
  1745. package/node_modules/@murphai/query/dist/personal-patterns.js.map +1 -0
  1746. package/node_modules/@murphai/query/dist/projection/schema.d.ts +1 -1
  1747. package/node_modules/@murphai/query/dist/projection/schema.d.ts.map +1 -1
  1748. package/node_modules/@murphai/query/dist/projection/schema.js +3 -1
  1749. package/node_modules/@murphai/query/dist/projection/schema.js.map +1 -1
  1750. package/node_modules/@murphai/query/dist/projection/wearable-summary-compose.js +4 -0
  1751. package/node_modules/@murphai/query/dist/projection/wearable-summary-compose.js.map +1 -1
  1752. package/node_modules/@murphai/query/dist/projection/wearable-summary-projector.d.ts.map +1 -1
  1753. package/node_modules/@murphai/query/dist/projection/wearable-summary-projector.js +2 -2
  1754. package/node_modules/@murphai/query/dist/projection/wearable-summary-projector.js.map +1 -1
  1755. package/node_modules/@murphai/query/dist/projection/wearable-summary-stored-codec.js +1 -1
  1756. package/node_modules/@murphai/query/dist/projection/wearable-summary-stored-codec.js.map +1 -1
  1757. package/node_modules/@murphai/query/dist/query-projection.d.ts +14 -0
  1758. package/node_modules/@murphai/query/dist/query-projection.d.ts.map +1 -1
  1759. package/node_modules/@murphai/query/dist/query-projection.js +31 -0
  1760. package/node_modules/@murphai/query/dist/query-projection.js.map +1 -1
  1761. package/node_modules/@murphai/query/dist/wearables/candidates.d.ts.map +1 -1
  1762. package/node_modules/@murphai/query/dist/wearables/candidates.js +6 -0
  1763. package/node_modules/@murphai/query/dist/wearables/candidates.js.map +1 -1
  1764. package/node_modules/@murphai/query/dist/wearables/public-output.d.ts.map +1 -1
  1765. package/node_modules/@murphai/query/dist/wearables/public-output.js +37 -2
  1766. package/node_modules/@murphai/query/dist/wearables/public-output.js.map +1 -1
  1767. package/node_modules/@murphai/query/dist/wearables/sleep-pattern.d.ts +5 -1
  1768. package/node_modules/@murphai/query/dist/wearables/sleep-pattern.d.ts.map +1 -1
  1769. package/node_modules/@murphai/query/dist/wearables/sleep-pattern.js +16 -3
  1770. package/node_modules/@murphai/query/dist/wearables/sleep-pattern.js.map +1 -1
  1771. package/node_modules/@murphai/query/dist/wearables/source-health.d.ts.map +1 -1
  1772. package/node_modules/@murphai/query/dist/wearables/source-health.js +27 -4
  1773. package/node_modules/@murphai/query/dist/wearables/source-health.js.map +1 -1
  1774. package/node_modules/@murphai/query/dist/wearables/types.d.ts +17 -4
  1775. package/node_modules/@murphai/query/dist/wearables/types.d.ts.map +1 -1
  1776. package/node_modules/@murphai/query/dist/wearables/types.js +34 -0
  1777. package/node_modules/@murphai/query/dist/wearables/types.js.map +1 -1
  1778. package/node_modules/@murphai/query/dist/wearables.d.ts.map +1 -1
  1779. package/node_modules/@murphai/query/dist/wearables.js +55 -4
  1780. package/node_modules/@murphai/query/dist/wearables.js.map +1 -1
  1781. package/node_modules/@murphai/query/package.json +10 -0
  1782. package/node_modules/@murphai/runtime-state/README.md +2 -2
  1783. package/node_modules/@murphai/runtime-state/dist/assistant-local-state-descriptors.d.ts.map +1 -1
  1784. package/node_modules/@murphai/runtime-state/dist/assistant-local-state-descriptors.js +15 -2
  1785. package/node_modules/@murphai/runtime-state/dist/assistant-local-state-descriptors.js.map +1 -1
  1786. package/node_modules/@murphai/runtime-state/dist/hosted-bundles.d.ts +1 -0
  1787. package/node_modules/@murphai/runtime-state/dist/hosted-bundles.d.ts.map +1 -1
  1788. package/node_modules/@murphai/runtime-state/dist/hosted-bundles.js +45 -20
  1789. package/node_modules/@murphai/runtime-state/dist/hosted-bundles.js.map +1 -1
  1790. package/node_modules/@murphai/runtime-state/dist/hosted-crypto-keyrings.d.ts +32 -1
  1791. package/node_modules/@murphai/runtime-state/dist/hosted-crypto-keyrings.d.ts.map +1 -1
  1792. package/node_modules/@murphai/runtime-state/dist/hosted-crypto-keyrings.js +327 -0
  1793. package/node_modules/@murphai/runtime-state/dist/hosted-crypto-keyrings.js.map +1 -1
  1794. package/node_modules/@murphai/runtime-state/dist/hosted-domain-crypto.d.ts +3 -1
  1795. package/node_modules/@murphai/runtime-state/dist/hosted-domain-crypto.d.ts.map +1 -1
  1796. package/node_modules/@murphai/runtime-state/dist/hosted-domain-crypto.js +23 -3
  1797. package/node_modules/@murphai/runtime-state/dist/hosted-domain-crypto.js.map +1 -1
  1798. package/node_modules/@murphai/runtime-state/dist/hosted-storage.d.ts +1 -1
  1799. package/node_modules/@murphai/runtime-state/dist/hosted-storage.d.ts.map +1 -1
  1800. package/node_modules/@murphai/runtime-state/dist/hosted-storage.js +1 -0
  1801. package/node_modules/@murphai/runtime-state/dist/hosted-storage.js.map +1 -1
  1802. package/node_modules/@murphai/runtime-state/dist/sqlite.d.ts.map +1 -1
  1803. package/node_modules/@murphai/runtime-state/dist/sqlite.js +22 -6
  1804. package/node_modules/@murphai/runtime-state/dist/sqlite.js.map +1 -1
  1805. package/node_modules/@murphai/setup-cli/README.md +1 -1
  1806. package/node_modules/@murphai/setup-cli/dist/index.d.ts +0 -1
  1807. package/node_modules/@murphai/setup-cli/dist/index.d.ts.map +1 -1
  1808. package/node_modules/@murphai/setup-cli/dist/index.js +0 -1
  1809. package/node_modules/@murphai/setup-cli/dist/index.js.map +1 -1
  1810. package/node_modules/@murphai/setup-cli/dist/setup-assistant-account.js +1 -1
  1811. package/node_modules/@murphai/setup-cli/dist/setup-assistant-account.js.map +1 -1
  1812. package/node_modules/@murphai/setup-cli/dist/setup-assistant-defaults.d.ts.map +1 -1
  1813. package/node_modules/@murphai/setup-cli/dist/setup-assistant-defaults.js +14 -24
  1814. package/node_modules/@murphai/setup-cli/dist/setup-assistant-defaults.js.map +1 -1
  1815. package/node_modules/@murphai/setup-cli/dist/setup-assistant.js +1 -1
  1816. package/node_modules/@murphai/setup-cli/dist/setup-assistant.js.map +1 -1
  1817. package/node_modules/@murphai/setup-cli/dist/setup-cli.d.ts +1 -2
  1818. package/node_modules/@murphai/setup-cli/dist/setup-cli.d.ts.map +1 -1
  1819. package/node_modules/@murphai/setup-cli/dist/setup-cli.js +2 -4
  1820. package/node_modules/@murphai/setup-cli/dist/setup-cli.js.map +1 -1
  1821. package/node_modules/@murphai/setup-cli/dist/setup-services/channels.d.ts +0 -4
  1822. package/node_modules/@murphai/setup-cli/dist/setup-services/channels.d.ts.map +1 -1
  1823. package/node_modules/@murphai/setup-cli/dist/setup-services/channels.js +126 -420
  1824. package/node_modules/@murphai/setup-cli/dist/setup-services/channels.js.map +1 -1
  1825. package/node_modules/@murphai/setup-cli/dist/setup-services.d.ts +0 -3
  1826. package/node_modules/@murphai/setup-cli/dist/setup-services.d.ts.map +1 -1
  1827. package/node_modules/@murphai/setup-cli/dist/setup-services.js +0 -7
  1828. package/node_modules/@murphai/setup-cli/dist/setup-services.js.map +1 -1
  1829. package/node_modules/@murphai/setup-cli/dist/setup-wizard-options.d.ts.map +1 -1
  1830. package/node_modules/@murphai/setup-cli/dist/setup-wizard-options.js +0 -7
  1831. package/node_modules/@murphai/setup-cli/dist/setup-wizard-options.js.map +1 -1
  1832. package/node_modules/@murphai/vault-usecases/dist/clinical-records.js +1 -1
  1833. package/node_modules/@murphai/vault-usecases/dist/clinical-records.js.map +1 -1
  1834. package/node_modules/@murphai/vault-usecases/dist/experiment-onboarding-options.d.ts +3 -3
  1835. package/node_modules/@murphai/vault-usecases/dist/experiment-onboarding-options.d.ts.map +1 -1
  1836. package/node_modules/@murphai/vault-usecases/dist/experiment-onboarding-options.js +1 -1
  1837. package/node_modules/@murphai/vault-usecases/dist/experiment-onboarding-options.js.map +1 -1
  1838. package/node_modules/@murphai/vault-usecases/dist/export-packs.d.ts +7 -0
  1839. package/node_modules/@murphai/vault-usecases/dist/export-packs.d.ts.map +1 -0
  1840. package/node_modules/@murphai/vault-usecases/dist/export-packs.js +45 -0
  1841. package/node_modules/@murphai/vault-usecases/dist/export-packs.js.map +1 -0
  1842. package/node_modules/@murphai/vault-usecases/dist/health-cli-descriptors.d.ts +28 -28
  1843. package/node_modules/@murphai/vault-usecases/dist/health-cli-descriptors.d.ts.map +1 -1
  1844. package/node_modules/@murphai/vault-usecases/dist/health-cli-descriptors.js +1 -1
  1845. package/node_modules/@murphai/vault-usecases/dist/health-cli-descriptors.js.map +1 -1
  1846. package/node_modules/@murphai/vault-usecases/dist/json-input.d.ts +1 -1
  1847. package/node_modules/@murphai/vault-usecases/dist/json-input.d.ts.map +1 -1
  1848. package/node_modules/@murphai/vault-usecases/dist/json-input.js +1 -1
  1849. package/node_modules/@murphai/vault-usecases/dist/json-input.js.map +1 -1
  1850. package/node_modules/@murphai/vault-usecases/dist/query-runtime.d.ts +5 -1
  1851. package/node_modules/@murphai/vault-usecases/dist/query-runtime.d.ts.map +1 -1
  1852. package/node_modules/@murphai/vault-usecases/dist/query-runtime.js.map +1 -1
  1853. package/node_modules/@murphai/vault-usecases/dist/testing/junction-wearable-fixture.d.ts +1 -1
  1854. package/node_modules/@murphai/vault-usecases/dist/testing/junction-wearable-fixture.d.ts.map +1 -1
  1855. package/node_modules/@murphai/vault-usecases/dist/usecases/capture.d.ts +21 -21
  1856. package/node_modules/@murphai/vault-usecases/dist/usecases/capture.d.ts.map +1 -1
  1857. package/node_modules/@murphai/vault-usecases/dist/usecases/capture.js +1 -1
  1858. package/node_modules/@murphai/vault-usecases/dist/usecases/capture.js.map +1 -1
  1859. package/node_modules/@murphai/vault-usecases/dist/usecases/clinical-imports.d.ts +193 -193
  1860. package/node_modules/@murphai/vault-usecases/dist/usecases/clinical-imports.d.ts.map +1 -1
  1861. package/node_modules/@murphai/vault-usecases/dist/usecases/clinical-imports.js +1 -1
  1862. package/node_modules/@murphai/vault-usecases/dist/usecases/clinical-imports.js.map +1 -1
  1863. package/node_modules/@murphai/vault-usecases/dist/usecases/document-meal-read.d.ts +12 -12
  1864. package/node_modules/@murphai/vault-usecases/dist/usecases/document-meal-read.d.ts.map +1 -1
  1865. package/node_modules/@murphai/vault-usecases/dist/usecases/document-meal-read.js +1 -1
  1866. package/node_modules/@murphai/vault-usecases/dist/usecases/document-meal-read.js.map +1 -1
  1867. package/node_modules/@murphai/vault-usecases/dist/usecases/encounter.d.ts +130 -130
  1868. package/node_modules/@murphai/vault-usecases/dist/usecases/encounter.d.ts.map +1 -1
  1869. package/node_modules/@murphai/vault-usecases/dist/usecases/encounter.js +1 -1
  1870. package/node_modules/@murphai/vault-usecases/dist/usecases/encounter.js.map +1 -1
  1871. package/node_modules/@murphai/vault-usecases/dist/usecases/event-record-mutations.d.ts +1 -0
  1872. package/node_modules/@murphai/vault-usecases/dist/usecases/event-record-mutations.d.ts.map +1 -1
  1873. package/node_modules/@murphai/vault-usecases/dist/usecases/event-record-mutations.js +22 -0
  1874. package/node_modules/@murphai/vault-usecases/dist/usecases/event-record-mutations.js.map +1 -1
  1875. package/node_modules/@murphai/vault-usecases/dist/usecases/experiment-journal-vault.d.ts +28 -5
  1876. package/node_modules/@murphai/vault-usecases/dist/usecases/experiment-journal-vault.d.ts.map +1 -1
  1877. package/node_modules/@murphai/vault-usecases/dist/usecases/experiment-journal-vault.js +225 -37
  1878. package/node_modules/@murphai/vault-usecases/dist/usecases/experiment-journal-vault.js.map +1 -1
  1879. package/node_modules/@murphai/vault-usecases/dist/usecases/food-autolog.d.ts +1 -1
  1880. package/node_modules/@murphai/vault-usecases/dist/usecases/food-autolog.d.ts.map +1 -1
  1881. package/node_modules/@murphai/vault-usecases/dist/usecases/food-autolog.js +1 -1
  1882. package/node_modules/@murphai/vault-usecases/dist/usecases/food-autolog.js.map +1 -1
  1883. package/node_modules/@murphai/vault-usecases/dist/usecases/food.d.ts.map +1 -1
  1884. package/node_modules/@murphai/vault-usecases/dist/usecases/food.js +0 -1
  1885. package/node_modules/@murphai/vault-usecases/dist/usecases/food.js.map +1 -1
  1886. package/node_modules/@murphai/vault-usecases/dist/usecases/integrated-services.d.ts.map +1 -1
  1887. package/node_modules/@murphai/vault-usecases/dist/usecases/integrated-services.js +77 -9
  1888. package/node_modules/@murphai/vault-usecases/dist/usecases/integrated-services.js.map +1 -1
  1889. package/node_modules/@murphai/vault-usecases/dist/usecases/measurement-read.d.ts +95 -13
  1890. package/node_modules/@murphai/vault-usecases/dist/usecases/measurement-read.d.ts.map +1 -1
  1891. package/node_modules/@murphai/vault-usecases/dist/usecases/measurement-read.js +136 -3
  1892. package/node_modules/@murphai/vault-usecases/dist/usecases/measurement-read.js.map +1 -1
  1893. package/node_modules/@murphai/vault-usecases/dist/usecases/measurement.d.ts.map +1 -1
  1894. package/node_modules/@murphai/vault-usecases/dist/usecases/measurement.js +3 -1
  1895. package/node_modules/@murphai/vault-usecases/dist/usecases/measurement.js.map +1 -1
  1896. package/node_modules/@murphai/vault-usecases/dist/usecases/provider-event.d.ts +4 -4
  1897. package/node_modules/@murphai/vault-usecases/dist/usecases/provider-event.d.ts.map +1 -1
  1898. package/node_modules/@murphai/vault-usecases/dist/usecases/provider-event.js +1 -1
  1899. package/node_modules/@murphai/vault-usecases/dist/usecases/provider-event.js.map +1 -1
  1900. package/node_modules/@murphai/vault-usecases/dist/usecases/recipe.d.ts +3 -3
  1901. package/node_modules/@murphai/vault-usecases/dist/usecases/recipe.d.ts.map +1 -1
  1902. package/node_modules/@murphai/vault-usecases/dist/usecases/recipe.js +1 -1
  1903. package/node_modules/@murphai/vault-usecases/dist/usecases/recipe.js.map +1 -1
  1904. package/node_modules/@murphai/vault-usecases/dist/usecases/runtime.d.ts.map +1 -1
  1905. package/node_modules/@murphai/vault-usecases/dist/usecases/runtime.js +2 -0
  1906. package/node_modules/@murphai/vault-usecases/dist/usecases/runtime.js.map +1 -1
  1907. package/node_modules/@murphai/vault-usecases/dist/usecases/types.d.ts +44 -1
  1908. package/node_modules/@murphai/vault-usecases/dist/usecases/types.d.ts.map +1 -1
  1909. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-core.d.ts +7 -1
  1910. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-core.d.ts.map +1 -1
  1911. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-core.js.map +1 -1
  1912. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-format.d.ts +2 -0
  1913. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-format.d.ts.map +1 -1
  1914. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-import.d.ts +60 -7
  1915. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-import.d.ts.map +1 -1
  1916. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-import.js +1282 -494
  1917. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-import.js.map +1 -1
  1918. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live-model.d.ts +84 -0
  1919. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live-model.d.ts.map +1 -0
  1920. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live-model.js +195 -0
  1921. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live-model.js.map +1 -0
  1922. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live-state.d.ts +36 -0
  1923. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live-state.d.ts.map +1 -0
  1924. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live-state.js +285 -0
  1925. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live-state.js.map +1 -0
  1926. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live.d.ts +122 -0
  1927. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live.d.ts.map +1 -0
  1928. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live.js +507 -0
  1929. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-live.js.map +1 -0
  1930. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-model.d.ts +1 -1
  1931. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-model.d.ts.map +1 -1
  1932. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-model.js +2 -0
  1933. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-model.js.map +1 -1
  1934. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-read.d.ts +13 -13
  1935. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-read.d.ts.map +1 -1
  1936. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-read.js +3 -2
  1937. package/node_modules/@murphai/vault-usecases/dist/usecases/workout-read.js.map +1 -1
  1938. package/node_modules/@murphai/vault-usecases/dist/usecases/workout.d.ts +25 -1
  1939. package/node_modules/@murphai/vault-usecases/dist/usecases/workout.d.ts.map +1 -1
  1940. package/node_modules/@murphai/vault-usecases/dist/usecases/workout.js +118 -3
  1941. package/node_modules/@murphai/vault-usecases/dist/usecases/workout.js.map +1 -1
  1942. package/node_modules/@murphai/vault-usecases/dist/vault-services.d.ts.map +1 -1
  1943. package/node_modules/@murphai/vault-usecases/dist/vault-services.js +3 -0
  1944. package/node_modules/@murphai/vault-usecases/dist/vault-services.js.map +1 -1
  1945. package/node_modules/@murphai/vault-usecases/dist/workouts.d.ts +1 -0
  1946. package/node_modules/@murphai/vault-usecases/dist/workouts.d.ts.map +1 -1
  1947. package/node_modules/@murphai/vault-usecases/dist/workouts.js +1 -0
  1948. package/node_modules/@murphai/vault-usecases/dist/workouts.js.map +1 -1
  1949. package/node_modules/@murphai/vault-usecases/package.json +4 -0
  1950. package/node_modules/ink/build/ansi-tokenizer.d.ts +38 -0
  1951. package/node_modules/ink/build/ansi-tokenizer.js +316 -0
  1952. package/node_modules/ink/build/ansi-tokenizer.js.map +1 -0
  1953. package/node_modules/ink/build/apply-styles.js +175 -0
  1954. package/node_modules/ink/build/build-layout.js +77 -0
  1955. package/node_modules/ink/build/calculate-wrapped-text.js +53 -0
  1956. package/node_modules/ink/build/colorize.d.ts +3 -0
  1957. package/node_modules/ink/build/colorize.js +48 -0
  1958. package/node_modules/ink/build/colorize.js.map +1 -0
  1959. package/node_modules/ink/build/components/AccessibilityContext.d.ts +3 -0
  1960. package/node_modules/ink/build/components/AccessibilityContext.js +5 -0
  1961. package/node_modules/ink/build/components/AccessibilityContext.js.map +1 -0
  1962. package/node_modules/ink/build/components/App.d.ts +18 -0
  1963. package/node_modules/ink/build/components/App.js +351 -0
  1964. package/node_modules/ink/build/components/App.js.map +1 -0
  1965. package/node_modules/ink/build/components/AppContext.d.ts +15 -0
  1966. package/node_modules/ink/build/components/AppContext.js +11 -0
  1967. package/node_modules/ink/build/components/AppContext.js.map +1 -0
  1968. package/node_modules/ink/build/components/BackgroundContext.d.ts +4 -0
  1969. package/node_modules/ink/build/components/BackgroundContext.js +3 -0
  1970. package/node_modules/ink/build/components/BackgroundContext.js.map +1 -0
  1971. package/node_modules/ink/build/components/Box.d.ts +117 -0
  1972. package/node_modules/ink/build/components/Box.js +34 -0
  1973. package/node_modules/ink/build/components/Box.js.map +1 -0
  1974. package/node_modules/ink/build/components/Color.js +62 -0
  1975. package/node_modules/ink/build/components/Cursor.d.ts +83 -0
  1976. package/node_modules/ink/build/components/Cursor.js +53 -0
  1977. package/node_modules/ink/build/components/Cursor.js.map +1 -0
  1978. package/node_modules/ink/build/components/CursorContext.d.ts +11 -0
  1979. package/node_modules/ink/build/components/CursorContext.js +8 -0
  1980. package/node_modules/ink/build/components/CursorContext.js.map +1 -0
  1981. package/node_modules/ink/build/components/ErrorBoundary.d.ts +18 -0
  1982. package/node_modules/ink/build/components/ErrorBoundary.js +23 -0
  1983. package/node_modules/ink/build/components/ErrorBoundary.js.map +1 -0
  1984. package/node_modules/ink/build/components/ErrorOverview.d.ts +6 -0
  1985. package/node_modules/ink/build/components/ErrorOverview.js +84 -0
  1986. package/node_modules/ink/build/components/ErrorOverview.js.map +1 -0
  1987. package/node_modules/ink/build/components/FocusContext.d.ts +16 -0
  1988. package/node_modules/ink/build/components/FocusContext.js +17 -0
  1989. package/node_modules/ink/build/components/FocusContext.js.map +1 -0
  1990. package/node_modules/ink/build/components/Newline.d.ts +13 -0
  1991. package/node_modules/ink/build/components/Newline.js +8 -0
  1992. package/node_modules/ink/build/components/Newline.js.map +1 -0
  1993. package/node_modules/ink/build/components/Spacer.d.ts +7 -0
  1994. package/node_modules/ink/build/components/Spacer.js +11 -0
  1995. package/node_modules/ink/build/components/Spacer.js.map +1 -0
  1996. package/node_modules/ink/build/components/Static.d.ts +24 -0
  1997. package/node_modules/ink/build/components/Static.js +28 -0
  1998. package/node_modules/ink/build/components/Static.js.map +1 -0
  1999. package/node_modules/ink/build/components/StderrContext.d.ts +15 -0
  2000. package/node_modules/ink/build/components/StderrContext.js +13 -0
  2001. package/node_modules/ink/build/components/StderrContext.js.map +1 -0
  2002. package/node_modules/ink/build/components/StdinContext.d.ts +22 -0
  2003. package/node_modules/ink/build/components/StdinContext.js +19 -0
  2004. package/node_modules/ink/build/components/StdinContext.js.map +1 -0
  2005. package/node_modules/ink/build/components/StdoutContext.d.ts +15 -0
  2006. package/node_modules/ink/build/components/StdoutContext.js +13 -0
  2007. package/node_modules/ink/build/components/StdoutContext.js.map +1 -0
  2008. package/node_modules/ink/build/components/Text.d.ts +55 -0
  2009. package/node_modules/ink/build/components/Text.js +50 -0
  2010. package/node_modules/ink/build/components/Text.js.map +1 -0
  2011. package/node_modules/ink/build/components/Transform.d.ts +16 -0
  2012. package/node_modules/ink/build/components/Transform.js +15 -0
  2013. package/node_modules/ink/build/components/Transform.js.map +1 -0
  2014. package/node_modules/ink/build/cursor-helpers.d.ts +38 -0
  2015. package/node_modules/ink/build/cursor-helpers.js +56 -0
  2016. package/node_modules/ink/build/cursor-helpers.js.map +1 -0
  2017. package/node_modules/ink/build/devtools-window-polyfill.d.ts +1 -0
  2018. package/node_modules/ink/build/devtools-window-polyfill.js +65 -0
  2019. package/node_modules/ink/build/devtools-window-polyfill.js.map +1 -0
  2020. package/node_modules/ink/build/devtools.d.ts +1 -0
  2021. package/node_modules/ink/build/devtools.js +11 -0
  2022. package/node_modules/ink/build/devtools.js.map +1 -0
  2023. package/node_modules/ink/build/dom.d.ts +56 -0
  2024. package/node_modules/ink/build/dom.js +124 -0
  2025. package/node_modules/ink/build/dom.js.map +1 -0
  2026. package/node_modules/ink/build/experimental/apply-style.js +140 -0
  2027. package/node_modules/ink/build/experimental/dom.js +123 -0
  2028. package/node_modules/ink/build/experimental/output.js +91 -0
  2029. package/node_modules/ink/build/experimental/reconciler.js +141 -0
  2030. package/node_modules/ink/build/experimental/renderer.js +81 -0
  2031. package/node_modules/ink/build/get-max-width.d.ts +3 -0
  2032. package/node_modules/ink/build/get-max-width.js +10 -0
  2033. package/node_modules/ink/build/get-max-width.js.map +1 -0
  2034. package/node_modules/ink/build/hooks/use-app.d.ts +5 -0
  2035. package/node_modules/ink/build/hooks/use-app.js +8 -0
  2036. package/node_modules/ink/build/hooks/use-app.js.map +1 -0
  2037. package/node_modules/ink/build/hooks/use-cursor.d.ts +12 -0
  2038. package/node_modules/ink/build/hooks/use-cursor.js +29 -0
  2039. package/node_modules/ink/build/hooks/use-cursor.js.map +1 -0
  2040. package/node_modules/ink/build/hooks/use-focus-manager.d.ts +28 -0
  2041. package/node_modules/ink/build/hooks/use-focus-manager.js +17 -0
  2042. package/node_modules/ink/build/hooks/use-focus-manager.js.map +1 -0
  2043. package/node_modules/ink/build/hooks/use-focus.d.ts +29 -0
  2044. package/node_modules/ink/build/hooks/use-focus.js +42 -0
  2045. package/node_modules/ink/build/hooks/use-focus.js.map +1 -0
  2046. package/node_modules/ink/build/hooks/use-input.d.ts +131 -0
  2047. package/node_modules/ink/build/hooks/use-input.js +124 -0
  2048. package/node_modules/ink/build/hooks/use-input.js.map +1 -0
  2049. package/node_modules/ink/build/hooks/use-is-screen-reader-enabled.d.ts +5 -0
  2050. package/node_modules/ink/build/hooks/use-is-screen-reader-enabled.js +11 -0
  2051. package/node_modules/ink/build/hooks/use-is-screen-reader-enabled.js.map +1 -0
  2052. package/node_modules/ink/build/hooks/use-stderr.d.ts +5 -0
  2053. package/node_modules/ink/build/hooks/use-stderr.js +8 -0
  2054. package/node_modules/ink/build/hooks/use-stderr.js.map +1 -0
  2055. package/node_modules/ink/build/hooks/use-stdin.d.ts +5 -0
  2056. package/node_modules/ink/build/hooks/use-stdin.js +8 -0
  2057. package/node_modules/ink/build/hooks/use-stdin.js.map +1 -0
  2058. package/node_modules/ink/build/hooks/use-stdout.d.ts +5 -0
  2059. package/node_modules/ink/build/hooks/use-stdout.js +8 -0
  2060. package/node_modules/ink/build/hooks/use-stdout.js.map +1 -0
  2061. package/node_modules/ink/build/hooks/useInput.js +38 -0
  2062. package/node_modules/ink/build/index.d.ts +34 -0
  2063. package/node_modules/ink/build/index.js +20 -0
  2064. package/node_modules/ink/build/index.js.map +1 -0
  2065. package/node_modules/ink/build/ink.d.ts +90 -0
  2066. package/node_modules/ink/build/ink.js +637 -0
  2067. package/node_modules/ink/build/ink.js.map +1 -0
  2068. package/node_modules/ink/build/input-parser.d.ts +7 -0
  2069. package/node_modules/ink/build/input-parser.js +154 -0
  2070. package/node_modules/ink/build/input-parser.js.map +1 -0
  2071. package/node_modules/ink/build/instance.js +205 -0
  2072. package/node_modules/ink/build/instances.d.ts +3 -0
  2073. package/node_modules/ink/build/instances.js +8 -0
  2074. package/node_modules/ink/build/instances.js.map +1 -0
  2075. package/node_modules/ink/build/kitty-keyboard.d.ts +23 -0
  2076. package/node_modules/ink/build/kitty-keyboard.js +32 -0
  2077. package/node_modules/ink/build/kitty-keyboard.js.map +1 -0
  2078. package/node_modules/ink/build/layout.d.ts +7 -0
  2079. package/node_modules/ink/build/layout.js +33 -0
  2080. package/node_modules/ink/build/layout.js.map +1 -0
  2081. package/node_modules/ink/build/log-update.d.ts +19 -0
  2082. package/node_modules/ink/build/log-update.js +242 -0
  2083. package/node_modules/ink/build/log-update.js.map +1 -0
  2084. package/node_modules/ink/build/measure-element.d.ts +16 -0
  2085. package/node_modules/ink/build/measure-element.js +9 -0
  2086. package/node_modules/ink/build/measure-element.js.map +1 -0
  2087. package/node_modules/ink/build/measure-text.d.ts +6 -0
  2088. package/node_modules/ink/build/measure-text.js +21 -0
  2089. package/node_modules/ink/build/measure-text.js.map +1 -0
  2090. package/node_modules/ink/build/options.d.ts +52 -0
  2091. package/node_modules/ink/build/options.js +2 -0
  2092. package/node_modules/ink/build/options.js.map +1 -0
  2093. package/node_modules/ink/build/output.d.ts +35 -0
  2094. package/node_modules/ink/build/output.js +183 -0
  2095. package/node_modules/ink/build/output.js.map +1 -0
  2096. package/node_modules/ink/build/parse-keypress.d.ts +22 -0
  2097. package/node_modules/ink/build/parse-keypress.js +493 -0
  2098. package/node_modules/ink/build/parse-keypress.js.map +1 -0
  2099. package/node_modules/ink/build/reconciler.d.ts +4 -0
  2100. package/node_modules/ink/build/reconciler.js +274 -0
  2101. package/node_modules/ink/build/reconciler.js.map +1 -0
  2102. package/node_modules/ink/build/render-background.d.ts +4 -0
  2103. package/node_modules/ink/build/render-background.js +25 -0
  2104. package/node_modules/ink/build/render-background.js.map +1 -0
  2105. package/node_modules/ink/build/render-border.d.ts +4 -0
  2106. package/node_modules/ink/build/render-border.js +73 -0
  2107. package/node_modules/ink/build/render-border.js.map +1 -0
  2108. package/node_modules/ink/build/render-node-to-output.d.ts +14 -0
  2109. package/node_modules/ink/build/render-node-to-output.js +147 -0
  2110. package/node_modules/ink/build/render-node-to-output.js.map +1 -0
  2111. package/node_modules/ink/build/render-to-string.d.ts +38 -0
  2112. package/node_modules/ink/build/render-to-string.js +115 -0
  2113. package/node_modules/ink/build/render-to-string.js.map +1 -0
  2114. package/node_modules/ink/build/render.d.ts +121 -0
  2115. package/node_modules/ink/build/render.js +55 -0
  2116. package/node_modules/ink/build/render.js.map +1 -0
  2117. package/node_modules/ink/build/renderer.d.ts +8 -0
  2118. package/node_modules/ink/build/renderer.js +55 -0
  2119. package/node_modules/ink/build/renderer.js.map +1 -0
  2120. package/node_modules/ink/build/sanitize-ansi.d.ts +2 -0
  2121. package/node_modules/ink/build/sanitize-ansi.js +27 -0
  2122. package/node_modules/ink/build/sanitize-ansi.js.map +1 -0
  2123. package/node_modules/ink/build/screen-reader-update.d.ts +13 -0
  2124. package/node_modules/ink/build/screen-reader-update.js +38 -0
  2125. package/node_modules/ink/build/screen-reader-update.js.map +1 -0
  2126. package/node_modules/ink/build/squash-text-nodes.d.ts +3 -0
  2127. package/node_modules/ink/build/squash-text-nodes.js +36 -0
  2128. package/node_modules/ink/build/squash-text-nodes.js.map +1 -0
  2129. package/node_modules/ink/build/styles.d.ts +240 -0
  2130. package/node_modules/ink/build/styles.js +232 -0
  2131. package/node_modules/ink/build/styles.js.map +1 -0
  2132. package/node_modules/ink/build/utils.d.ts +2 -0
  2133. package/node_modules/ink/build/utils.js +4 -0
  2134. package/node_modules/ink/build/utils.js.map +1 -0
  2135. package/node_modules/ink/build/wrap-text.d.ts +3 -0
  2136. package/node_modules/ink/build/wrap-text.js +31 -0
  2137. package/node_modules/ink/build/wrap-text.js.map +1 -0
  2138. package/node_modules/ink/build/write-synchronized.d.ts +4 -0
  2139. package/node_modules/ink/build/write-synchronized.js +7 -0
  2140. package/node_modules/ink/build/write-synchronized.js.map +1 -0
  2141. package/node_modules/ink/package.json +126 -0
  2142. package/package.json +35 -5
  2143. package/node_modules/@murphai/assistant-engine/dist/assistant/group-phone-call-preview-authority.d.ts +0 -24
  2144. package/node_modules/@murphai/assistant-engine/dist/assistant/group-phone-call-preview-authority.d.ts.map +0 -1
  2145. package/node_modules/@murphai/assistant-engine/dist/assistant/group-phone-call-preview-authority.js +0 -125
  2146. package/node_modules/@murphai/assistant-engine/dist/assistant/group-phone-call-preview-authority.js.map +0 -1
  2147. package/node_modules/@murphai/assistant-engine/dist/assistant/newsletter-outbox.d.ts +0 -19
  2148. package/node_modules/@murphai/assistant-engine/dist/assistant/newsletter-outbox.d.ts.map +0 -1
  2149. package/node_modules/@murphai/assistant-engine/dist/assistant/newsletter-outbox.js.map +0 -1
  2150. package/node_modules/@murphai/assistant-engine/skills/general-eye-health/SKILL.md +0 -77
  2151. package/node_modules/@murphai/assistant-engine/skills/general-eye-health/references/evidence-register.md +0 -34
  2152. package/node_modules/@murphai/assistant-engine/skills/general-eye-health/references/triage-and-contact-lenses.md +0 -103
  2153. package/node_modules/@murphai/assistant-engine/skills/recovery-modalities/SKILL.md +0 -57
  2154. package/node_modules/@murphai/assistant-engine/skills/red-light-therapy/SKILL.md +0 -145
  2155. package/node_modules/@murphai/assistant-engine/skills/red-light-therapy/device-seeds.json +0 -259
  2156. package/node_modules/@murphai/inboxd/dist/connectors/email/connector.d.ts +0 -57
  2157. package/node_modules/@murphai/inboxd/dist/connectors/email/connector.d.ts.map +0 -1
  2158. package/node_modules/@murphai/inboxd/dist/connectors/email/connector.js +0 -259
  2159. package/node_modules/@murphai/inboxd/dist/connectors/email/connector.js.map +0 -1
  2160. package/node_modules/@murphai/inboxd/dist/connectors/email/normalize.d.ts +0 -44
  2161. package/node_modules/@murphai/inboxd/dist/connectors/email/normalize.d.ts.map +0 -1
  2162. package/node_modules/@murphai/inboxd/dist/connectors/email/normalize.js +0 -212
  2163. package/node_modules/@murphai/inboxd/dist/connectors/email/normalize.js.map +0 -1
  2164. package/node_modules/@murphai/inboxd/dist/connectors/email/types.d.ts +0 -69
  2165. package/node_modules/@murphai/inboxd/dist/connectors/email/types.d.ts.map +0 -1
  2166. package/node_modules/@murphai/inboxd/dist/connectors/email/types.js +0 -2
  2167. package/node_modules/@murphai/inboxd/dist/connectors/email/types.js.map +0 -1
  2168. package/node_modules/@murphai/operator-config/dist/agentmail-runtime.d.ts +0 -194
  2169. package/node_modules/@murphai/operator-config/dist/agentmail-runtime.d.ts.map +0 -1
  2170. package/node_modules/@murphai/operator-config/dist/agentmail-runtime.js +0 -385
  2171. package/node_modules/@murphai/operator-config/dist/agentmail-runtime.js.map +0 -1
  2172. package/node_modules/@murphai/setup-cli/dist/setup-agentmail.d.ts +0 -30
  2173. package/node_modules/@murphai/setup-cli/dist/setup-agentmail.d.ts.map +0 -1
  2174. package/node_modules/@murphai/setup-cli/dist/setup-agentmail.js +0 -135
  2175. package/node_modules/@murphai/setup-cli/dist/setup-agentmail.js.map +0 -1
  2176. package/node_modules/incur/src/Cli.test.ts +0 -4808
  2177. package/node_modules/incur/src/Completions.test.ts +0 -543
  2178. package/node_modules/incur/src/Errors.test.ts +0 -100
  2179. package/node_modules/incur/src/Fetch.test.ts +0 -285
  2180. package/node_modules/incur/src/Filter.test.ts +0 -237
  2181. package/node_modules/incur/src/Formatter.test.ts +0 -326
  2182. package/node_modules/incur/src/Help.test.ts +0 -414
  2183. package/node_modules/incur/src/Mcp.test.ts +0 -413
  2184. package/node_modules/incur/src/Openapi.test.ts +0 -389
  2185. package/node_modules/incur/src/Parser.test.ts +0 -378
  2186. package/node_modules/incur/src/Schema.test.ts +0 -167
  2187. package/node_modules/incur/src/Skill.test.ts +0 -441
  2188. package/node_modules/incur/src/Skillgen.test.ts +0 -77
  2189. package/node_modules/incur/src/SyncMcp.test.ts +0 -136
  2190. package/node_modules/incur/src/SyncSkills.test.ts +0 -301
  2191. package/node_modules/incur/src/Typegen.test.ts +0 -205
  2192. package/node_modules/incur/src/bun-compile.test.ts +0 -84
  2193. package/node_modules/incur/src/e2e.test.ts +0 -3441
  2194. package/node_modules/incur/src/internal/configSchema.test.ts +0 -193
  2195. package/node_modules/incur/src/internal/dereference.test.ts +0 -695
  2196. package/node_modules/incur/src/internal/helpers.test.ts +0 -75
  2197. package/node_modules/incur/src/internal/pm.test.ts +0 -38
  2198. package/node_modules/incur/src/internal/utils.test.ts +0 -50
  2199. package/node_modules/incur/src/middleware.test.ts +0 -6
@@ -1,21 +1,21 @@
1
1
  import { createHmac, createHash, timingSafeEqual } from "node:crypto";
2
- import { HistoricalPullCompleted as JunctionHistoricalPullCompletedSchema } from "@junction-api/sdk/serialization";
3
- import { COMPANION_HRV_RMSSD_RESOURCE, parseCompanionHrvRmssdAdmissionId, parseSerializedCompanionHrvRmssdObservation, serializeCompanionHrvRmssdObservation, } from "@murphai/contracts";
4
- import { canNormalizeJunctionSleepCycleRecordToCompactStages, classifyJunctionSummaryNormalizationEvidence, } from "@murphai/importers/device-providers/junction";
5
- import { resolveJunctionOrigin } from "@murphai/importers/device-providers/junction-origin";
6
- import { JUNCTION_ALLOWED_SUMMARY_RESOURCES, JUNCTION_ALLOWED_TIMESERIES_RESOURCES, JUNCTION_DEFAULT_SUMMARY_RESOURCES, JUNCTION_DEFAULT_TIMESERIES_RESOURCES, JUNCTION_KNOWN_TIMESERIES_RESOURCES, isJunctionRawDirectIdentityContainerKey, isJunctionRawDirectIdentityKey, normalizeJunctionResourceName, } from "@murphai/importers/device-providers/junction-resources";
2
+ import { COMPANION_HRV_RMSSD_RESOURCE, JUNCTION_ALLOWED_SUMMARY_RESOURCES, JUNCTION_ALLOWED_TIMESERIES_RESOURCES, JUNCTION_DEFAULT_SUMMARY_RESOURCES, JUNCTION_DEFAULT_TIMESERIES_RESOURCES, JUNCTION_KNOWN_TIMESERIES_RESOURCES, normalizeJunctionResourceName, resolveJunctionTimeseriesResourcePolicy, usesJunctionTimeseriesIntervalStartOwnership, parseCompanionHrvRmssdAdmissionId, parseSerializedCompanionHrvRmssdObservation, serializeCompanionHrvRmssdObservation, } from "@murphai/contracts";
3
+ import { JUNCTION_ECG_VOLTAGE_FEATURE_SCHEMA, JUNCTION_WORKOUT_STREAM_FEATURE_SCHEMA, buildJunctionBoundedFeatureIdentity, buildJunctionDailyTimeseriesAggregateResourceId, canNormalizeJunctionSleepCycleRecordToCompactStages, classifyJunctionSummaryNormalizationEvidence, countAcceptedJunctionDailyTimeseriesProviderRecords, identifyJunctionBloodPressureProviderRecords, JUNCTION_DENSE_FIDELITY_RESOURCES, reduceJunctionElectrocardiogramVoltageRecords, reduceJunctionWorkoutStreamPayload, resolveJunctionBoundedFeatureRecords, resolveJunctionWeightProviderRecordIdentity, selectJunctionWorkoutStreamCandidates, } from "@murphai/importers/device-providers/junction";
4
+ import { normalizeJunctionSourceProviderSlug, resolveJunctionOrigin, } from "@murphai/importers/device-providers/junction-origin";
5
+ import { isJunctionRawDirectIdentityContainerKey, isJunctionRawDirectIdentityKey, } from "@murphai/importers/device-providers/junction-resources";
7
6
  import { JUNCTION_DEVICE_PROVIDER_DESCRIPTOR } from "@murphai/importers/device-providers/provider-descriptors";
8
7
  import { deviceSyncError, isDeviceSyncError } from "../errors.js";
8
+ import { JunctionTimeseriesProgressError } from "../junction-timeseries-progress.js";
9
9
  import { isHostedRuntimeIdShapedDiagnosticToken, sanitizeHostedRuntimeDiagnosticText, } from "../hosted-runtime.js";
10
10
  import { isJunctionCredentialIndependentInlineImportJob, resolveDeviceSyncJunctionInlineSourceProviderSlug, } from "../junction-inline-authority.js";
11
- import { addJunctionHistoricalBackfillEvidence, canCurrentRuntimeMutateJunctionHistoricalBackfillProgress, encodeJunctionHistoricalBackfillStatus, hasJunctionHistoricalBackfillEvidence, JUNCTION_HISTORICAL_BACKFILL_COVERAGE_VERSION, JUNCTION_HISTORICAL_BACKFILL_METADATA_KEYS, readJunctionHistoricalBackfillEvidence, readJunctionHistoricalBackfillStatus, } from "../junction-historical-backfill-progress.js";
11
+ import { addJunctionExtendedTimeseriesHistoryBackfillCoverage, addJunctionHistoricalBackfillEvidence, canRepresentJunctionExtendedTimeseriesHistoryBackfillCoverage, canCurrentRuntimeMutateJunctionExtendedTimeseriesHistoryBackfillCoverage, canCurrentRuntimeMutateJunctionHistoricalBackfillProgress, encodeJunctionHistoricalBackfillStatus, hasJunctionExtendedTimeseriesHistoryBackfillCoverage, hasJunctionHistoricalBackfillEvidence, JUNCTION_HISTORICAL_BACKFILL_COVERAGE_VERSION, JUNCTION_HISTORICAL_BACKFILL_METADATA_KEYS, readJunctionHistoricalBackfillEvidence, readJunctionHistoricalBackfillStatus, } from "../junction-historical-backfill-progress.js";
12
12
  import { DEVICE_SYNC_METADATA_MAX_STRING_LENGTH } from "../metadata.js";
13
- import { DEVICE_SYNC_HISTORICAL_DATA_RECONNECT_REQUIRED_ERROR_CODE, isJunctionHistoricalResetProviderSlug, requiresHistoricalResetDeviceSyncSource, } from "../public-account.js";
14
- import { assertValidJunctionClientUserIdSecret, normalizeJunctionDeviceSyncRuntimeConfig, } from "../configured-provider-runtime-descriptors.js";
13
+ import { DEVICE_SYNC_HISTORICAL_DATA_RECONNECT_REQUIRED_ERROR_CODE, DEVICE_SYNC_SOURCE_USER_DISCONNECTED_ERROR_CODE, resolveDeviceSyncSourceState, isDeviceSyncSourceAdmitted, isDeviceSyncSourceDisconnectFenced, isJunctionHistoricalResetProviderSlug, requiresHistoricalResetDeviceSyncSource, } from "../public-account.js";
14
+ import { assertValidJunctionClientUserIdSecret, buildJunctionDeviceSyncRuntimeDescriptor, normalizeJunctionClientUserIdNamespace, normalizeJunctionDeviceSyncRuntimeConfig, } from "../configured-provider-runtime-descriptors.js";
15
15
  import { addMilliseconds, normalizeString, sha256Text, subtractDays, } from "../shared.js";
16
- import { JUNCTION_COMPANION_HRV_OBSERVATION_INVALID_CODE, JUNCTION_COMPANION_HEALTH_METADATA_EVENT_TYPE, JUNCTION_COMPANION_HEALTH_METADATA_MAX_BATCH_BYTES, JUNCTION_COMPANION_HEALTH_METADATA_RESOURCE, JUNCTION_COMPANION_HEALTH_METADATA_SOURCE_PROVIDER, JUNCTION_COMPANION_HEALTH_METADATA_SOURCE_TYPE, JunctionCompanionHealthMetadataParseError, parseJunctionCompanionHealthMetadataBatch, } from "../junction-resources.js";
17
- import { JunctionClient, } from "./junction-client.js";
18
- import { resolveJunctionDeviceConnectRouteByProviderSlug } from "../config/connect-routes.js";
16
+ import { JUNCTION_COMPANION_HRV_OBSERVATION_INVALID_CODE, JUNCTION_COMPANION_HRV_SOURCE_PROVIDER, JUNCTION_COMPANION_HEALTH_METADATA_EVENT_TYPE, JUNCTION_COMPANION_HEALTH_METADATA_MAX_BATCH_BYTES, JUNCTION_COMPANION_HEALTH_METADATA_RESOURCE, JUNCTION_COMPANION_HEALTH_METADATA_SOURCE_PROVIDER, JUNCTION_COMPANION_HEALTH_METADATA_SOURCE_TYPE, JUNCTION_CALENDAR_REFRESH_EMPTY_IDENTITY_INVALID_CODE, JUNCTION_CALENDAR_REFRESH_JOB_INVALID_CODE, JunctionCompanionHealthMetadataParseError, parseJunctionCompanionHealthMetadataBatch, } from "../junction-resources.js";
17
+ import { JunctionClient, JUNCTION_MAX_USER_PROVIDERS, } from "./junction-client.js";
18
+ import { areJunctionDeviceConnectProviderSlugsEquivalent, resolveJunctionDeviceConnectRouteByProviderSlug, } from "../config/connect-routes.js";
19
19
  import { buildJunctionProviderSourceInstanceKey, JUNCTION_DEFAULT_PROVIDER_FILTER, normalizeJunctionProviderFilter, } from "../config/junction-connect-sources.js";
20
20
  import { classifyDeviceSyncWebhookAcceptanceMode } from "../types.js";
21
21
  import { evaluatePushPrimarySourceStaleness } from "../source-staleness.js";
@@ -24,14 +24,23 @@ export { JUNCTION_DEVICE_PROVIDER_DESCRIPTOR };
24
24
  export { JUNCTION_CONNECT_SOURCE_TARGETS, JUNCTION_DEFAULT_PROVIDER_FILTER, JUNCTION_LINK_PROVIDER_SLUGS, normalizeJunctionProviderFilter, resolveJunctionConnectSourceLabel, resolveJunctionConnectTargetForSourceId, } from "../config/junction-connect-sources.js";
25
25
  export const JUNCTION_PROVIDER_CONFIG_KEY = "junction";
26
26
  export { JUNCTION_DEFAULT_SUMMARY_RESOURCES, JUNCTION_DEFAULT_TIMESERIES_RESOURCES, };
27
+ const JUNCTION_WORKOUT_STREAM_PROGRESS_VERSION = 1;
28
+ const JUNCTION_DEPLOYED_FULL_JOB_PROGRESS_VERSION = 1;
29
+ const JUNCTION_ALLOWED_TIMESERIES_RESOURCE_SET = new Set(JUNCTION_ALLOWED_TIMESERIES_RESOURCES);
27
30
  const JUNCTION_WEBHOOK_ROOT_FIELDS = Object.freeze({
28
31
  eventType: "event_type",
29
32
  userId: "user_id",
30
33
  clientUserId: "client_user_id",
31
34
  data: "data",
32
35
  });
36
+ // Mirrors the pinned Junction SDK's `serialization.date()` wire validation.
37
+ // Keeping this predicate local avoids loading the SDK's generated runtime tree
38
+ // merely to identify one five-field completion envelope.
39
+ const JUNCTION_SDK_ISO_8601_DATE_PATTERN = /^([+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24:?00)([.,]\d+(?!:))?)?(\17[0-5]\d([.,]\d+)?)?([zZ]|([+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
33
40
  const JUNCTION_PROFILE_SUMMARY_RESOURCE = "profile";
34
41
  const JUNCTION_PROFILE_SUMMARY_CHECKED_AT_METADATA_KEY = "junctionProfileSummaryCheckedAt";
42
+ const JUNCTION_PROFILE_SUMMARY_NORMALIZATION_REVISION = 1;
43
+ const JUNCTION_PROFILE_SUMMARY_NORMALIZATION_REVISION_METADATA_KEY = "junctionProfileSummaryNormalizationRevision";
35
44
  // `profile` is deliberately excluded: it is a current-state snapshot, so
36
45
  // counting it as completion evidence would mark every backfill useful and
37
46
  // defeat empty-history detection. The provider fetches it through the separate
@@ -66,6 +75,12 @@ const JUNCTION_WEBHOOK_NESTED_RECORD_KEYS = Object.freeze([
66
75
  const JUNCTION_TIMESERIES_RESOURCE_NAMES = new Set([
67
76
  ...JUNCTION_KNOWN_TIMESERIES_RESOURCES,
68
77
  ]);
78
+ const JUNCTION_CLOSED_DAY_TIMESERIES_RESOURCES = new Set([
79
+ "steps",
80
+ "distance",
81
+ "calories_active",
82
+ "heartrate",
83
+ ]);
69
84
  const JUNCTION_KNOWN_WEBHOOK_RESOURCE_NAMES = new Set([
70
85
  ...JUNCTION_ALLOWED_SUMMARY_RESOURCES,
71
86
  ...JUNCTION_ALLOWED_TIMESERIES_RESOURCES,
@@ -73,12 +88,143 @@ const JUNCTION_KNOWN_WEBHOOK_RESOURCE_NAMES = new Set([
73
88
  ]);
74
89
  const DEFAULT_SUMMARY_BACKFILL_DAYS = JUNCTION_DEVICE_PROVIDER_DESCRIPTOR.sync.windows.backfillDays;
75
90
  const DEFAULT_TIMESERIES_BACKFILL_DAYS = 14;
91
+ const JUNCTION_NOTE_HISTORY_BACKFILL_VERSION = 2;
92
+ const JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY = Object.freeze({
93
+ history: "bounded",
94
+ });
95
+ const JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY = Object.freeze({
96
+ anchor: "current_day",
97
+ completion: "daily_aggregate",
98
+ history: "extended",
99
+ version: 1,
100
+ });
101
+ // This is the history-depth decision for every admitted resource. Only the
102
+ // sparse resources represented by the package-owned source/resource matrix
103
+ // receive extended history; all other resources use the bounded sync window.
104
+ const JUNCTION_TIMESERIES_BACKFILL_POLICIES = Object.freeze({
105
+ afib_burden: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
106
+ basal_body_temperature: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
107
+ blood_oxygen: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
108
+ blood_pressure: {
109
+ anchor: "source_first_seen",
110
+ completion: "exact_records",
111
+ history: "extended",
112
+ version: 1,
113
+ },
114
+ body_temperature: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
115
+ body_temperature_delta: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
116
+ caffeine: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
117
+ calories_active: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
118
+ distance: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
119
+ glucose: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
120
+ heartrate: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
121
+ heart_rate_recovery_one_minute: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
122
+ hrv: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
123
+ mindfulness_minutes: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
124
+ note: {
125
+ anchor: "current_day",
126
+ completion: "fetch_complete",
127
+ history: "extended",
128
+ version: JUNCTION_NOTE_HISTORY_BACKFILL_VERSION,
129
+ },
130
+ respiratory_rate: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
131
+ sleep_breathing_disturbance: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
132
+ steps: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
133
+ stress_level: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
134
+ vo2_max: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
135
+ water: JUNCTION_SPARSE_DAILY_TIMESERIES_BACKFILL_POLICY,
136
+ weight: {
137
+ anchor: "current_day",
138
+ completion: "exact_records",
139
+ history: "extended",
140
+ version: 1,
141
+ },
142
+ body_mass_index: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
143
+ carbohydrates: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
144
+ fat: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
145
+ forced_expiratory_volume_1: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
146
+ forced_vital_capacity: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
147
+ heart_rate_alert: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
148
+ inhaler_usage: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
149
+ insulin_injection: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
150
+ lean_body_mass: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
151
+ peak_expiratory_flow_rate: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
152
+ sleep_apnea_alert: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
153
+ waist_circumference: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
154
+ calories_basal: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
155
+ daylight_exposure: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
156
+ fall: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
157
+ floors_climbed: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
158
+ handwashing: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
159
+ stand_duration: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
160
+ stand_hour: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
161
+ uv_exposure: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
162
+ wheelchair_push: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
163
+ workout_distance: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
164
+ workout_duration: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
165
+ workout_swimming_stroke: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
166
+ electrocardiogram_voltage: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
167
+ workout_stream: JUNCTION_BOUNDED_TIMESERIES_BACKFILL_POLICY,
168
+ });
169
+ function resolveJunctionExtendedTimeseriesBackfillPolicy(resource) {
170
+ if (!Object.prototype.hasOwnProperty.call(JUNCTION_TIMESERIES_BACKFILL_POLICIES, resource)) {
171
+ return null;
172
+ }
173
+ const policy = JUNCTION_TIMESERIES_BACKFILL_POLICIES[resource];
174
+ return policy.history === "extended" ? policy : null;
175
+ }
176
+ const JUNCTION_DENSE_FIDELITY_RESOURCE_SET = new Set(JUNCTION_DENSE_FIDELITY_RESOURCES);
177
+ const JUNCTION_CALENDAR_DAY_AGGREGATE_RESOURCE_SET = new Set([
178
+ ...JUNCTION_DENSE_FIDELITY_RESOURCES,
179
+ "caffeine",
180
+ "water",
181
+ "mindfulness_minutes",
182
+ ]);
76
183
  const DEFAULT_RECONCILE_DAYS = JUNCTION_DEVICE_PROVIDER_DESCRIPTOR.sync.windows.reconcileDays;
77
- const DEFAULT_RECONCILE_INTERVAL_MS = JUNCTION_DEVICE_PROVIDER_DESCRIPTOR.sync.windows.reconcileIntervalMs;
78
184
  const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
79
185
  const DEFAULT_SETUP_TTL_MS = 30 * 60_000;
80
186
  const DEFAULT_WEBHOOK_TIMESTAMP_TOLERANCE_MS = 5 * 60_000;
81
187
  const TIMESERIES_CHUNK_MS = 24 * 60 * 60_000;
188
+ // A date-only provider query can contain source-local records from UTC-12.
189
+ // Delay calendar-day ownership until that date has closed in every admitted
190
+ // civil offset instead of treating UTC midnight as globally complete.
191
+ const JUNCTION_PROVIDER_CALENDAR_DAY_CLOSE_LAG_MS = 12 * 60 * 60_000;
192
+ const JUNCTION_MAX_SPARSE_CALENDAR_REFRESH_DAYS = 64;
193
+ const JUNCTION_SPARSE_CALENDAR_AGGREGATE_RESOURCE_SET = new Set([
194
+ "caffeine",
195
+ "water",
196
+ "mindfulness_minutes",
197
+ ]);
198
+ const TIMESERIES_HOUR_MS = 60 * 60_000;
199
+ // Three single-attempt pages allow ordinary pagination while capping provider
200
+ // wait at 24 seconds, below the hosted job's 45-second outer budget.
201
+ const JUNCTION_FULL_JOB_TIMESERIES_COLLECTION_WORK_LIMIT = Object.freeze({
202
+ maxAttemptsPerPage: 1,
203
+ maxPages: 3,
204
+ requestTimeoutMs: 8_000,
205
+ });
206
+ // Most hosted summary continuation units contain one resource. Match the
207
+ // bounded timeseries contract so a complete three-page unit remains below the
208
+ // 45-second outer maintenance budget and can persist its next cursor.
209
+ const JUNCTION_FULL_JOB_SUMMARY_COLLECTION_WORK_LIMIT = Object.freeze({
210
+ maxAttemptsPerPage: 1,
211
+ maxPages: 3,
212
+ requestTimeoutMs: 8_000,
213
+ });
214
+ // Sleep summaries and sleep cycles share canonical stage ownership, so they
215
+ // must be normalized in one import. Keep their combined worst-case provider
216
+ // wait at 30 seconds to leave room for projection/import inside the hosted
217
+ // worker's 45-second outer maintenance budget.
218
+ const JUNCTION_FULL_JOB_COUPLED_SUMMARY_COLLECTION_WORK_LIMIT = Object.freeze({
219
+ maxAttemptsPerPage: 1,
220
+ maxPages: 3,
221
+ requestTimeoutMs: 5_000,
222
+ });
223
+ const JUNCTION_FULL_JOB_INVENTORY_COLLECTION_WORK_LIMIT = Object.freeze({
224
+ maxAttemptsPerPage: 1,
225
+ maxPages: 1,
226
+ requestTimeoutMs: 8_000,
227
+ });
82
228
  const JUNCTION_MAX_DIAGNOSTIC_TIMESERIES_PROBE_DAYS = 14;
83
229
  const JUNCTION_DIAGNOSTIC_SHAPE_KEY_LIMIT = 24;
84
230
  const JUNCTION_DIAGNOSTIC_RESOURCE_NAME_LIMIT = 64;
@@ -88,18 +234,21 @@ const EMPTY_HISTORICAL_BACKFILL_RETRY_DELAYS_MS = Object.freeze([
88
234
  6 * 60 * 60_000,
89
235
  24 * 60 * 60_000,
90
236
  ]);
237
+ const JUNCTION_HISTORICAL_UNRESOLVED_PROVIDER_RECORD_IDENTITIES_VERSION = 1;
238
+ const JUNCTION_BLOOD_PRESSURE_PROVIDER_RECORD_IDENTITY_PATTERN = /^blood-pressure-[0-9a-f]{16}$/u;
91
239
  const JUNCTION_SCHEDULED_RECONCILE_PRIORITY = 40;
92
240
  const JUNCTION_HISTORICAL_BACKFILL_PRIORITY = 30;
93
241
  const JUNCTION_HISTORICAL_BACKFILL_RETRY_PRIORITY = 50;
94
242
  export function createJunctionDeviceSyncProvider(config) {
95
243
  const runtimeConfig = normalizeJunctionDeviceSyncRuntimeConfig(config);
96
244
  const client = new JunctionClient(toClientConfig(config));
97
- const { providerFilter, summaryResources, timeseriesResources } = runtimeConfig;
245
+ const { clientUserIdNamespace, providerFilter, reconcileIntervalMs, summaryResources, timeseriesResources, } = runtimeConfig;
98
246
  const summaryBackfillDays = config.summaryBackfillDays ?? DEFAULT_SUMMARY_BACKFILL_DAYS;
99
247
  const timeseriesBackfillDays = config.timeseriesBackfillDays ?? DEFAULT_TIMESERIES_BACKFILL_DAYS;
248
+ const extendedTimeseriesBackfillDays = config.timeseriesBackfillDays ?? summaryBackfillDays;
249
+ const extendedBackfillTimeseriesResources = timeseriesResources.filter((resource) => resolveJunctionExtendedTimeseriesBackfillPolicy(resource) !== null);
100
250
  const reconcileDays = config.reconcileDays ?? DEFAULT_RECONCILE_DAYS;
101
251
  const pushSourceRecoveryEnabled = config.pushSourceRecoveryEnabled === true;
102
- const reconcileIntervalMs = config.reconcileIntervalMs ?? DEFAULT_RECONCILE_INTERVAL_MS;
103
252
  const webhookTimestampToleranceMs = config.webhookTimestampToleranceMs ?? DEFAULT_WEBHOOK_TIMESTAMP_TOLERANCE_MS;
104
253
  async function beginConnection(context) {
105
254
  const ownerId = normalizeString(context.ownerId);
@@ -112,7 +261,7 @@ export function createJunctionDeviceSyncProvider(config) {
112
261
  });
113
262
  }
114
263
  const linkProvider = resolveJunctionLinkDirectProvider(providerFilter, context.sourceProviderSlug);
115
- const clientUserId = buildJunctionClientUserId(config.clientUserIdSecret, ownerId);
264
+ const clientUserId = buildJunctionClientUserId(config.clientUserIdSecret, ownerId, clientUserIdNamespace);
116
265
  const user = await client.createOrResolveUser(clientUserId);
117
266
  const linkToken = await client.createLinkToken({
118
267
  userId: user.userId,
@@ -152,7 +301,7 @@ export function createJunctionDeviceSyncProvider(config) {
152
301
  httpStatus: 400,
153
302
  });
154
303
  }
155
- const clientUserId = buildJunctionClientUserId(config.clientUserIdSecret, ownerId);
304
+ const clientUserId = buildJunctionClientUserId(config.clientUserIdSecret, ownerId, clientUserIdNamespace);
156
305
  const user = await client.createOrResolveUser(clientUserId);
157
306
  return {
158
307
  externalAccountId: user.userId,
@@ -206,6 +355,10 @@ export function createJunctionDeviceSyncProvider(config) {
206
355
  httpStatus: 400,
207
356
  });
208
357
  }
358
+ const sourceConnectionWork = buildSourceConnectionWork({
359
+ now: context.now,
360
+ sourceProviderSlug: context.sourceProviderSlug,
361
+ });
209
362
  return {
210
363
  externalAccountId,
211
364
  displayName: "Junction",
@@ -215,8 +368,7 @@ export function createJunctionDeviceSyncProvider(config) {
215
368
  providerConfigKey: JUNCTION_PROVIDER_CONFIG_KEY,
216
369
  },
217
370
  setupPhase: "link_returned",
218
- initialJobs: buildInitialJobs(context.now),
219
- nextReconcileAt: addMilliseconds(context.now, reconcileIntervalMs),
371
+ ...sourceConnectionWork,
220
372
  };
221
373
  }
222
374
  async function revokeAccess(account) {
@@ -261,8 +413,47 @@ export function createJunctionDeviceSyncProvider(config) {
261
413
  });
262
414
  }
263
415
  }
416
+ async function revokeSourceAccess(account, sourceProviderSlug) {
417
+ const userId = normalizeString(account.externalAccountId);
418
+ const targetProviderSlug = normalizeProviderSlug(sourceProviderSlug);
419
+ if (!userId || !targetProviderSlug) {
420
+ throw deviceSyncError({
421
+ code: "JUNCTION_SOURCE_DEREGISTER_INPUT_INVALID",
422
+ message: "Junction source cleanup requires a stored user and provider slug.",
423
+ retryable: false,
424
+ httpStatus: 409,
425
+ });
426
+ }
427
+ const providers = await client.listUserProviders(userId);
428
+ const targetIsRegistered = providers.some((provider) => mapJunctionSourceStatus(provider.status) !== "disconnected"
429
+ && (normalizeProviderSlug(provider.origin.sourceProviderSlug)
430
+ ?? normalizeProviderSlug(provider.slug)) === targetProviderSlug);
431
+ if (!targetIsRegistered) {
432
+ return;
433
+ }
434
+ await client.deregisterProvider({
435
+ providerSlug: targetProviderSlug,
436
+ userId,
437
+ });
438
+ }
439
+ async function isSourceAccessActive(account, sourceProviderSlug) {
440
+ const userId = normalizeString(account.externalAccountId);
441
+ const targetProviderSlug = normalizeProviderSlug(sourceProviderSlug);
442
+ if (!userId || !targetProviderSlug) {
443
+ throw deviceSyncError({
444
+ code: "JUNCTION_SOURCE_STATUS_INPUT_INVALID",
445
+ message: "Junction source status requires a stored user and provider slug.",
446
+ retryable: false,
447
+ httpStatus: 409,
448
+ });
449
+ }
450
+ return (await client.listUserProviders(userId)).some((provider) => mapJunctionSourceStatus(provider.status) === "connected"
451
+ && (normalizeProviderSlug(provider.origin.sourceProviderSlug)
452
+ ?? normalizeProviderSlug(provider.slug)) === targetProviderSlug);
453
+ }
264
454
  function createScheduledJobs(account, now) {
265
455
  const scheduledHistoricalBackfillJobs = buildScheduledHistoricalBackfillJobs(account, now);
456
+ const scheduledExtendedTimeseriesBackfillJobs = buildScheduledExtendedTimeseriesBackfillJobs(account, now);
266
457
  const nextReconcileAt = resolveJunctionNextReconcileAt(account, now, addMilliseconds(now, reconcileIntervalMs));
267
458
  return {
268
459
  jobs: [
@@ -273,11 +464,61 @@ export function createJunctionDeviceSyncProvider(config) {
273
464
  priority: JUNCTION_SCHEDULED_RECONCILE_PRIORITY,
274
465
  }),
275
466
  ...scheduledHistoricalBackfillJobs,
467
+ ...scheduledExtendedTimeseriesBackfillJobs,
276
468
  ...buildPushSourceRecoveryJobs(account, now),
277
469
  ],
278
470
  nextReconcileAt,
279
471
  };
280
472
  }
473
+ function buildScheduledExtendedTimeseriesBackfillJobs(account, now) {
474
+ return extendedBackfillTimeseriesResources.flatMap((resource) => {
475
+ const policy = resolveJunctionExtendedTimeseriesBackfillPolicy(resource);
476
+ if (!policy) {
477
+ return [];
478
+ }
479
+ if (!canCurrentRuntimeMutateJunctionExtendedTimeseriesHistoryBackfillCoverage(account.metadata, resource, policy.version)) {
480
+ return [];
481
+ }
482
+ const scheduledSources = new Map();
483
+ for (const sourceState of resolveJunctionAccountSourceStates(account.sources ?? [])) {
484
+ const identitySource = sourceState.identitySource;
485
+ const lifecycleSource = sourceState.lifecycleSource;
486
+ const sourceProviderSlug = normalizeProviderSlug(identitySource.sourceProviderSlug);
487
+ if (!sourceProviderSlug
488
+ || !isDeviceSyncSourceAdmitted([lifecycleSource], lifecycleSource.sourceProviderSlug)
489
+ || !isJunctionResourceAvailableInSummary(lifecycleSource.resourceAvailabilitySummary, resource)
490
+ || hasJunctionExtendedTimeseriesHistoryBackfillCoverage(account.metadata, sourceProviderSlug, resource, policy.version)
491
+ || !canRepresentJunctionExtendedTimeseriesHistoryBackfillCoverage(account.metadata, sourceProviderSlug, resource, policy.version)) {
492
+ continue;
493
+ }
494
+ const sourceFirstSeenAt = identitySource.firstSeenAt;
495
+ if (!sourceFirstSeenAt) {
496
+ throw junctionSourceStateUnavailableError();
497
+ }
498
+ const existingFirstSeenAt = scheduledSources.get(sourceProviderSlug);
499
+ if (!existingFirstSeenAt || Date.parse(sourceFirstSeenAt) < Date.parse(existingFirstSeenAt)) {
500
+ scheduledSources.set(sourceProviderSlug, sourceFirstSeenAt);
501
+ }
502
+ }
503
+ return [...scheduledSources.entries()].map(([sourceProviderSlug, firstSeenAt]) => {
504
+ // Exact blood-pressure history is anchored to source admission. Other
505
+ // sparse resources catch up the current extended-history window once.
506
+ const window = buildExtendedTimeseriesBackfillWindow({
507
+ anchorAt: policy.anchor === "source_first_seen" ? firstSeenAt : now,
508
+ days: extendedTimeseriesBackfillDays,
509
+ });
510
+ return buildExtendedTimeseriesBackfillJob({
511
+ availableAt: now,
512
+ ...(resource === "note" ? { historicalBackfillVersion: policy.version } : {}),
513
+ historicalWindowStart: window.windowStart,
514
+ resource,
515
+ sourceProviderSlug,
516
+ windowEnd: window.windowEnd,
517
+ windowStart: window.windowStart,
518
+ });
519
+ });
520
+ });
521
+ }
281
522
  /**
282
523
  * A dead push carrier cannot recover on its own and no pull can rediscover
283
524
  * its data, so the scheduler turns a detected stall into a bounded recovery
@@ -507,15 +748,22 @@ export function createJunctionDeviceSyncProvider(config) {
507
748
  }
508
749
  async function executeJob(context, job) {
509
750
  const skippedOptionalResources = [];
751
+ const completedWorkoutStreamIdentities = readJunctionWorkoutStreamCompletedIdentities(job);
510
752
  if (job.kind === "resource") {
511
- return executeResourceJob(context, job, skippedOptionalResources);
753
+ return executeResourceJob(context, job, skippedOptionalResources, completedWorkoutStreamIdentities);
512
754
  }
513
755
  if (job.kind === JUNCTION_PUSH_SOURCE_RECOVERY_JOB_KIND) {
514
756
  return executePushSourceRecoveryJob(context, job);
515
757
  }
758
+ if (isFullJobTimeseriesContinuation(job)) {
759
+ return executeFullJobTimeseriesContinuation(context, job, skippedOptionalResources, completedWorkoutStreamIdentities);
760
+ }
516
761
  const window = resolveJobWindow(job, context.now, job.kind === "backfill" ? summaryBackfillDays : reconcileDays);
517
762
  const isConnectHistoricalBackfill = isConnectHistoricalBackfillWindow(context.account, window);
518
763
  const sourceProviders = await client.listUserProviders(context.account.externalAccountId, {
764
+ ...(job.kind === "reconcile" && context.shouldYield
765
+ ? { collectionWorkLimit: JUNCTION_FULL_JOB_INVENTORY_COLLECTION_WORK_LIMIT }
766
+ : {}),
519
767
  signal: context.signal ?? null,
520
768
  });
521
769
  await projectJunctionSources(context, sourceProviders);
@@ -526,16 +774,43 @@ export function createJunctionDeviceSyncProvider(config) {
526
774
  const summaryDateQueryFormat = job.kind === "reconcile" && !isCurrentSummaryReconcile && isFullUtcDayWindow(summaryWindow)
527
775
  ? "date"
528
776
  : "datetime";
529
- const summaries = await fetchSummarySnapshots(context, summaryWindow.windowStart, summaryWindow.windowEnd, skippedOptionalResources, { dateQueryFormat: summaryDateQueryFormat });
530
- const profileSummaryResult = await fetchProfileSummaryOnce(context, skippedOptionalResources);
777
+ if (job.kind === "reconcile"
778
+ && context.shouldYield
779
+ && job.payload.summaryPhaseComplete !== true) {
780
+ const boundedSummaryResult = await executeBoundedSummaryReconcile({
781
+ context,
782
+ dateQueryFormat: summaryDateQueryFormat,
783
+ job,
784
+ skippedOptionalResources,
785
+ sourceProviders,
786
+ summaryWindow,
787
+ window,
788
+ });
789
+ if (boundedSummaryResult) {
790
+ return boundedSummaryResult;
791
+ }
792
+ }
793
+ const summaryPhaseComplete = job.kind === "reconcile" && job.payload.summaryPhaseComplete === true;
794
+ const summaries = summaryPhaseComplete
795
+ ? {}
796
+ : await fetchSummarySnapshots(context, summaryWindow.windowStart, summaryWindow.windowEnd, skippedOptionalResources, { dateQueryFormat: summaryDateQueryFormat });
797
+ const profileSummaryResult = summaryPhaseComplete
798
+ ? { checked: false, records: [] }
799
+ : await fetchProfileSummaryOnce(context, skippedOptionalResources);
531
800
  const profileMetadataPatch = profileSummaryResult.checked
532
801
  ? buildJunctionProfileSummaryCheckedMetadataPatch(context)
533
802
  : {};
534
803
  if (profileSummaryResult.records.length > 0) {
535
804
  summaries[JUNCTION_PROFILE_SUMMARY_RESOURCE] = profileSummaryResult.records;
536
805
  }
537
- const importConnections = sanitizeJunctionImportConnections(sourceProviders);
538
- const importSummaries = sanitizeJunctionImportSnapshots(summaries, sourceProviders);
806
+ const summaryHasFetchedRecords = hasJunctionSnapshotRecords(summaries);
807
+ const preparedSummaryImport = job.kind === "backfill"
808
+ && !summaryHasFetchedRecords
809
+ && context.shouldYield?.() === true
810
+ ? prepareJunctionImportSnapshotForSources(summaries, sourceProviders, context.account.sources ?? [])
811
+ : await prepareJunctionImportSnapshot(context, summaries, sourceProviders);
812
+ const importConnections = preparedSummaryImport.connections;
813
+ const importSummaries = preparedSummaryImport.snapshots;
539
814
  const summaryNormalizationEvidence = classifyJunctionSummaryNormalizationEvidence({
540
815
  connections: importConnections,
541
816
  importedAt: summaryWindow.windowEnd,
@@ -544,16 +819,9 @@ export function createJunctionDeviceSyncProvider(config) {
544
819
  windowStart: summaryWindow.windowStart,
545
820
  });
546
821
  const historicalSummaryHasRecords = hasJunctionHistoricalBackfillSummaryRecords(summaryNormalizationEvidence);
547
- const summaryHasFetchedRecords = hasJunctionSnapshotRecords(summaries);
548
822
  const baseTimeseriesWindowStart = job.kind === "backfill"
549
823
  ? maxIsoTimestamp(window.windowStart, subtractDays(window.windowEnd, timeseriesBackfillDays))
550
824
  : window.windowStart;
551
- const timeseriesCursor = job.kind === "backfill"
552
- ? readBackfillTimeseriesCursor(job, window)
553
- : null;
554
- const timeseriesWindowStart = timeseriesCursor
555
- ? maxIsoTimestamp(baseTimeseriesWindowStart, timeseriesCursor)
556
- : baseTimeseriesWindowStart;
557
825
  if (job.kind !== "backfill" || summaryHasFetchedRecords) {
558
826
  await context.importSnapshot({
559
827
  provider: "junction",
@@ -572,19 +840,24 @@ export function createJunctionDeviceSyncProvider(config) {
572
840
  const historicalPullSnapshot = isConnectHistoricalBackfill && !context.shouldYield?.()
573
841
  ? await loadJunctionHistoricalPullSnapshot(context)
574
842
  : null;
575
- const historicalSummaryCoverage = evaluateJunctionHistoricalBackfillCoverage(summaryNormalizationEvidence, sourceProviders, summaryResources, providerFilter, historicalPullSnapshot, isConnectHistoricalBackfill
843
+ const historicalSummaryCoverage = evaluateJunctionHistoricalBackfillCoverage(summaryNormalizationEvidence, preparedSummaryImport.sourceProviders, summaryResources, providerFilter, historicalPullSnapshot, isConnectHistoricalBackfill
576
844
  ? readJunctionHistoricalBackfillEvidence(context.account.metadata[JUNCTION_HISTORICAL_BACKFILL_METADATA_KEYS.evidence])
577
845
  : null, window);
578
- if (job.kind === "backfill"
579
- || shouldImportClosedTimeseriesForReconcile(context.account.lastSyncCompletedAt, window.windowEnd)) {
580
- const timeseriesImport = await importTimeseriesDailySnapshots(context, sourceProviders, timeseriesWindowStart, window.windowEnd, skippedOptionalResources);
846
+ const shouldImportBroadClosedTimeseries = job.kind === "backfill"
847
+ || shouldImportClosedTimeseriesForReconcile(context.account.lastSyncCompletedAt, window.windowEnd);
848
+ const hourlyFidelityWindow = shouldImportBroadClosedTimeseries
849
+ ? null
850
+ : resolveLatestGloballyClosedProviderDayWindow(baseTimeseriesWindowStart, window.windowEnd, context.now);
851
+ const dailyTimeseriesResources = timeseriesResources.filter((resource) => JUNCTION_CALENDAR_DAY_AGGREGATE_RESOURCE_SET.has(resource));
852
+ if (dailyTimeseriesResources.length > 0
853
+ && hourlyFidelityWindow) {
854
+ const timeseriesImport = await importTimeseriesDailyAggregateSnapshots(context, sourceProviders, hourlyFidelityWindow.windowStart, hourlyFidelityWindow.windowEnd, skippedOptionalResources, dailyTimeseriesResources);
581
855
  if (timeseriesImport.yieldedAt) {
582
856
  return withJunctionSkippedResourceMetadata(context, withJunctionMetadataPatch(buildYieldedJunctionJobResult({
583
857
  context,
584
858
  job,
585
859
  windowEnd: window.windowEnd,
586
- windowStart: job.kind === "backfill" ? window.windowStart : timeseriesImport.yieldedAt,
587
- timeseriesCursor: job.kind === "backfill" ? timeseriesImport.yieldedAt : null,
860
+ windowStart: timeseriesImport.yieldedAt,
588
861
  }), profileMetadataPatch), skippedOptionalResources);
589
862
  }
590
863
  }
@@ -623,7 +896,7 @@ export function createJunctionDeviceSyncProvider(config) {
623
896
  || (historicalSummaryCoverage.complete
624
897
  && historicalStatusBeforeJob?.status === "exhausted"))) {
625
898
  const pendingProviderSlugs = new Set(historicalSummaryCoverage.pendingProviderSlugs);
626
- const hasCoveredProvider = sourceProviders.some((provider) => {
899
+ const hasCoveredProvider = preparedSummaryImport.sourceProviders.some((provider) => {
627
900
  const providerSlug = resolveJunctionHistoricalCoverageProviderSlug(provider.origin.sourceProviderSlug ?? provider.slug, providerFilter);
628
901
  return providerSlug !== null
629
902
  && mapJunctionSourceStatus(provider.status) !== "disconnected"
@@ -639,6 +912,29 @@ export function createJunctionDeviceSyncProvider(config) {
639
912
  }
640
913
  }
641
914
  const nextReconcileAt = backfillFollowUp.nextReconcileAt ?? resolveJunctionNextReconcileAt(context.account, context.now, addMilliseconds(context.now, reconcileIntervalMs));
915
+ const shouldScheduleTimeseries = timeseriesResources.length > 0
916
+ && (job.kind === "backfill"
917
+ || shouldImportClosedTimeseriesForReconcile(context.account.lastSyncCompletedAt, window.windowEnd));
918
+ const timeseriesContinuation = shouldScheduleTimeseries
919
+ ? buildFullJobTimeseriesContinuationJob({
920
+ deferredEmptyBackfillAttempts: readDeferredEmptyBackfillAttempts(backfillFollowUp),
921
+ job,
922
+ timeseriesCursor: baseTimeseriesWindowStart,
923
+ timeseriesResourceCursor: timeseriesResources[0] ?? null,
924
+ timeseriesWindowHours: 24,
925
+ window,
926
+ workoutStreamCursor: null,
927
+ })
928
+ : null;
929
+ if (timeseriesContinuation) {
930
+ return withJunctionSkippedResourceMetadata(context, withJunctionMetadataPatch({
931
+ ...(backfillFollowUp.metadataPatch
932
+ ? { metadataPatch: backfillFollowUp.metadataPatch }
933
+ : {}),
934
+ nextReconcileAt,
935
+ scheduledJobs: [{ ...timeseriesContinuation, availableAt: context.now }],
936
+ }, profileMetadataPatch), skippedOptionalResources);
937
+ }
642
938
  return withJunctionSkippedResourceMetadata(context, withJunctionMetadataPatch({
643
939
  ...backfillFollowUp,
644
940
  nextReconcileAt,
@@ -772,7 +1068,7 @@ export function createJunctionDeviceSyncProvider(config) {
772
1068
  const timeseriesDiagnostics = [];
773
1069
  if (timeseriesProbeWindow) {
774
1070
  for (const resource of timeseriesResources) {
775
- const resourceResult = await runJunctionDiagnosticCall(() => client.listTimeseries({
1071
+ const resourceResult = await runJunctionDiagnosticCall(() => fetchJunctionTimeseriesWindow(client, {
776
1072
  resource,
777
1073
  userId: context.account.externalAccountId,
778
1074
  windowStart: timeseriesProbeWindow.windowStart,
@@ -969,7 +1265,7 @@ export function createJunctionDeviceSyncProvider(config) {
969
1265
  const sourceProviderSlug = normalizeProviderSlug(context.sourceProviderSlug);
970
1266
  const resourceCategory = endpoint;
971
1267
  const resourceResult = await runJunctionDiagnosticCall(() => resourceCategory === "timeseries"
972
- ? client.listTimeseries({
1268
+ ? fetchJunctionTimeseriesWindow(client, {
973
1269
  resource: normalizedResource,
974
1270
  sourceProviderSlug,
975
1271
  userId: context.account.externalAccountId,
@@ -990,9 +1286,7 @@ export function createJunctionDeviceSyncProvider(config) {
990
1286
  request: {
991
1287
  configuredResource: isConfiguredJunctionResource(resourceCategory, normalizedResource),
992
1288
  endpoint: resourceCategory,
993
- endpointKind: resourceCategory === "timeseries"
994
- ? "junction_timeseries_collection"
995
- : "junction_summary_collection",
1289
+ endpointKind: resolveJunctionDiagnosticEndpointKind(resourceCategory, normalizedResource),
996
1290
  queryParameterNames: resolveJunctionDiagnosticResourceQueryParameterNames(resourceCategory, normalizedResource, sourceProviderSlug),
997
1291
  resource: normalizedResource,
998
1292
  resourceCategory,
@@ -1003,8 +1297,9 @@ export function createJunctionDeviceSyncProvider(config) {
1003
1297
  },
1004
1298
  };
1005
1299
  }
1006
- async function executeResourceJob(context, job, skippedOptionalResources) {
1007
- if (normalizeString(job.payload.resource) === COMPANION_HRV_RMSSD_RESOURCE) {
1300
+ async function executeResourceJob(context, job, skippedOptionalResources, completedWorkoutStreamIdentities) {
1301
+ const resourceName = normalizeString(job.payload.resource);
1302
+ if (resourceName === COMPANION_HRV_RMSSD_RESOURCE) {
1008
1303
  let observation;
1009
1304
  let admissionId;
1010
1305
  try {
@@ -1024,6 +1319,9 @@ export function createJunctionDeviceSyncProvider(config) {
1024
1319
  retryable: false,
1025
1320
  });
1026
1321
  }
1322
+ if (!await isJunctionCompanionSourceCurrentlyAdmitted(context, JUNCTION_COMPANION_HRV_SOURCE_PROVIDER)) {
1323
+ return {};
1324
+ }
1027
1325
  await context.importSnapshot({
1028
1326
  provider: "junction",
1029
1327
  accountId: buildJunctionImportAccountId(context.account.externalAccountId),
@@ -1036,14 +1334,26 @@ export function createJunctionDeviceSyncProvider(config) {
1036
1334
  const window = resolveJobWindow(job, context.now, reconcileDays);
1037
1335
  if (normalizeString(job.payload.resource) === JUNCTION_COMPANION_HEALTH_METADATA_RESOURCE) {
1038
1336
  const records = parseJunctionCompanionHealthMetadataJob(job);
1337
+ if (!await isJunctionCompanionSourceCurrentlyAdmitted(context, JUNCTION_COMPANION_HEALTH_METADATA_SOURCE_PROVIDER)) {
1338
+ return {};
1339
+ }
1039
1340
  await importJunctionCompanionHealthMetadataSnapshot(context, records);
1040
1341
  return {
1041
1342
  nextReconcileAt: clampWebhookJobNextReconcileAt(context),
1042
1343
  };
1043
1344
  }
1345
+ const calendarRefreshDay = readJunctionSparseCalendarRefreshDay(job);
1044
1346
  const resource = normalizeJunctionResourceName(job.payload.resource);
1045
1347
  const resourceCategory = normalizeString(job.payload.resourceCategory);
1046
1348
  const sourceProviderSlug = normalizeProviderSlug(job.payload.sourceProviderSlug);
1349
+ if (!calendarRefreshDay
1350
+ && sourceProviderSlug
1351
+ && !isJunctionSourceAdmittedForImport(context.account.sources ?? [], sourceProviderSlug)
1352
+ && (resource === null
1353
+ || !isJunctionExtendedTimeseriesBackfillJob(job, resource)
1354
+ || isJunctionSourceProjectionFenced(context.account.sources ?? [], sourceProviderSlug))) {
1355
+ return {};
1356
+ }
1047
1357
  let listedSourceProviders = null;
1048
1358
  let projectedSourceProviders = null;
1049
1359
  const loadSourceProviders = async () => {
@@ -1065,10 +1375,73 @@ export function createJunctionDeviceSyncProvider(config) {
1065
1375
  projectedSourceProviders = sourceProviders;
1066
1376
  return sourceProviders;
1067
1377
  };
1378
+ if (calendarRefreshDay) {
1379
+ if (!resource
1380
+ || !JUNCTION_SPARSE_CALENDAR_AGGREGATE_RESOURCE_SET.has(resource)
1381
+ || !isConfiguredJunctionResource("timeseries", resource)) {
1382
+ throw deviceSyncError({
1383
+ code: JUNCTION_CALENDAR_REFRESH_JOB_INVALID_CODE,
1384
+ message: "Junction calendar refresh job did not name an admitted sparse resource.",
1385
+ retryable: false,
1386
+ });
1387
+ }
1388
+ const queuedCalendarSourceIdentity = readJunctionSparseCalendarSourceIdentity(job);
1389
+ const currentSources = context.listConnectionSources
1390
+ ? await context.listConnectionSources()
1391
+ : context.account.sources ?? [];
1392
+ const accountSourceIdentity = resolveJunctionAccountSourceIdentity(currentSources, queuedCalendarSourceIdentity.sourceProviderSlug, context.connectionSourceAdmissionMode !== "listed_only");
1393
+ if (!accountSourceIdentity
1394
+ || !isJunctionSourceAdmittedForImport(currentSources, sourceProviderSlug, context.connectionSourceAdmissionMode !== "listed_only", "connected")) {
1395
+ throw deviceSyncError({
1396
+ code: "JUNCTION_CALENDAR_REFRESH_SOURCE_AUTHORITY_UNAVAILABLE",
1397
+ message: "Junction calendar source authority is temporarily unavailable.",
1398
+ retryable: true,
1399
+ });
1400
+ }
1401
+ const sourceProviders = await loadAndProjectSourceProviders();
1402
+ const calendarSourceIdentity = {
1403
+ ...queuedCalendarSourceIdentity,
1404
+ sourceProviderSlug: accountSourceIdentity.sourceProviderSlug,
1405
+ ...(accountSourceIdentity.sourceInstanceId
1406
+ ? { sourceInstanceId: accountSourceIdentity.sourceInstanceId }
1407
+ : {}),
1408
+ };
1409
+ const calendarFetchSourceProviderSlug = resolveJunctionProviderRouteSlug(queuedCalendarSourceIdentity.sourceProviderSlug);
1410
+ const windowStart = `${calendarRefreshDay}T00:00:00.000Z`;
1411
+ const dailyImport = await importTimeseriesDailyAggregateSnapshots(context, sourceProviders, windowStart, addMilliseconds(windowStart, TIMESERIES_CHUNK_MS), skippedOptionalResources, [resource], calendarFetchSourceProviderSlug, calendarSourceIdentity);
1412
+ const expectedDailyAggregateResourceId = buildJunctionDailyTimeseriesAggregateResourceId({
1413
+ dayKey: calendarRefreshDay,
1414
+ resource,
1415
+ ...calendarSourceIdentity,
1416
+ });
1417
+ if (!dailyImport.yieldedAt
1418
+ && !dailyImport.appliedDailyAggregateResourceIds?.includes(expectedDailyAggregateResourceId)) {
1419
+ throw deviceSyncError({
1420
+ code: "JUNCTION_CALENDAR_REFRESH_DAILY_STATE_NOT_APPLIED",
1421
+ message: "Junction calendar refresh did not apply its owned daily state.",
1422
+ retryable: true,
1423
+ });
1424
+ }
1425
+ const followUp = dailyImport.yieldedAt
1426
+ ? buildJunctionSparseCalendarRefreshJob({
1427
+ dayKey: calendarRefreshDay,
1428
+ priority: job.priority,
1429
+ resource,
1430
+ ...calendarSourceIdentity,
1431
+ })
1432
+ : null;
1433
+ return withJunctionSkippedResourceMetadata(context, {
1434
+ ...(followUp ? { scheduledJobs: [followUp] } : {}),
1435
+ nextReconcileAt: clampWebhookJobNextReconcileAt(context),
1436
+ }, skippedOptionalResources);
1437
+ }
1068
1438
  const summaries = {};
1069
1439
  if (resource) {
1070
1440
  const directInput = readJunctionDirectResourceJobInput(job, window);
1071
1441
  if (directInput) {
1442
+ if (!isJunctionSourceAdmittedForImport(context.account.sources ?? [], directInput.sourceProviderSlug)) {
1443
+ return {};
1444
+ }
1072
1445
  // This lookup uses the stable provider-config authority, not the
1073
1446
  // replaceable per-connection credential epoch. It resolves source
1074
1447
  // provenance only; the accepted inline payload remains the data
@@ -1132,19 +1505,307 @@ export function createJunctionDeviceSyncProvider(config) {
1132
1505
  inferredCategory = fallback.category;
1133
1506
  }
1134
1507
  if (inferredCategory === "timeseries") {
1135
- const sourceProviders = await loadAndProjectSourceProviders();
1136
- const timeseriesImport = await importTimeseriesPreciseSnapshots(context, sourceProviders, window.windowStart, window.windowEnd, skippedOptionalResources, [effectiveResource], sourceProviderSlug);
1508
+ const extendedHistoricalBackfill = isJunctionExtendedTimeseriesBackfillJob(job, effectiveResource);
1509
+ const extendedHistoricalPolicy = extendedHistoricalBackfill
1510
+ ? resolveJunctionExtendedTimeseriesBackfillPolicy(effectiveResource)
1511
+ : null;
1512
+ if (extendedHistoricalPolicy
1513
+ && !canCurrentRuntimeMutateJunctionExtendedTimeseriesHistoryBackfillCoverage(context.account.metadata, effectiveResource, extendedHistoricalPolicy.version)) {
1514
+ return {};
1515
+ }
1516
+ if (extendedHistoricalPolicy
1517
+ && sourceProviderSlug
1518
+ && !canRepresentJunctionExtendedTimeseriesHistoryBackfillCoverage(context.account.metadata, sourceProviderSlug, effectiveResource, extendedHistoricalPolicy.version)) {
1519
+ throw deviceSyncError({
1520
+ code: "JUNCTION_EXTENDED_HISTORY_COVERAGE_UNREPRESENTABLE",
1521
+ message: "Junction extended-history completion could not be retained exactly.",
1522
+ retryable: false,
1523
+ });
1524
+ }
1525
+ const historicalWindowStart = toIsoTimestampIfValid(normalizeString(job.payload.historicalWindowStart))
1526
+ ?? window.windowStart;
1527
+ const dailyAggregateRetryAttempts = readHistoricalBackfillJobEmptyAttempts(job);
1528
+ let sourceProviders;
1529
+ let sourceIdentityAuthority;
1530
+ let currentSourceAdmission = "admitted";
1531
+ try {
1532
+ sourceProviders = await loadAndProjectSourceProviders();
1533
+ if (extendedHistoricalBackfill && sourceProviderSlug) {
1534
+ sourceIdentityAuthority = context.listConnectionSources
1535
+ ? await context.listConnectionSources()
1536
+ : context.account.sources ?? [];
1537
+ currentSourceAdmission = resolveJunctionCurrentSourceAdmissionFromSources(sourceIdentityAuthority, sourceProviderSlug, context.connectionSourceAdmissionMode !== "listed_only");
1538
+ }
1539
+ }
1540
+ catch (error) {
1541
+ if (extendedHistoricalBackfill
1542
+ && (job.payload.historicalProviderRecordsSeen === true
1543
+ || job.payload.historicalRecordsSeen === true)
1544
+ && isRetryableDeviceSyncFailure(error)) {
1545
+ return withJunctionExtendedTimeseriesBackfillFollowUp({
1546
+ context,
1547
+ importResult: {
1548
+ acceptedProviderRecordCount: 0,
1549
+ canonicalProviderRecordIdentities: [],
1550
+ canonicalEventCount: 0,
1551
+ canonicalEventDayKeys: [],
1552
+ canonicalSparseCalendarTargets: [],
1553
+ fetchComplete: false,
1554
+ providerRecordsExamined: false,
1555
+ providerRecordCount: 0,
1556
+ unresolvedProviderRecordIdentities: [],
1557
+ unresolvedProviderRecordCount: 0,
1558
+ unresolvedProviderRecordsWithoutStableIdentity: false,
1559
+ yieldedAt: null,
1560
+ },
1561
+ job,
1562
+ resource: effectiveResource,
1563
+ result: {
1564
+ nextReconcileAt: clampWebhookJobNextReconcileAt(context),
1565
+ },
1566
+ window,
1567
+ });
1568
+ }
1569
+ throw error;
1570
+ }
1571
+ if (currentSourceAdmission === "fenced") {
1572
+ return {};
1573
+ }
1574
+ if (extendedHistoricalBackfill
1575
+ && (currentSourceAdmission !== "admitted"
1576
+ || !isJunctionSourceResourceCurrentlyAvailable({
1577
+ connectionId: context.account.id,
1578
+ providers: sourceProviders,
1579
+ resource: effectiveResource,
1580
+ sourceProviderSlug,
1581
+ }))) {
1582
+ const result = {
1583
+ nextReconcileAt: clampWebhookJobNextReconcileAt(context),
1584
+ };
1585
+ if (job.payload.historicalProviderRecordsSeen !== true
1586
+ && job.payload.historicalRecordsSeen !== true) {
1587
+ return result;
1588
+ }
1589
+ return withJunctionExtendedTimeseriesBackfillFollowUp({
1590
+ context,
1591
+ importResult: {
1592
+ acceptedProviderRecordCount: 0,
1593
+ canonicalProviderRecordIdentities: [],
1594
+ canonicalEventCount: 0,
1595
+ canonicalEventDayKeys: [],
1596
+ canonicalSparseCalendarTargets: [],
1597
+ fetchComplete: false,
1598
+ providerRecordsExamined: false,
1599
+ providerRecordCount: 0,
1600
+ unresolvedProviderRecordIdentities: [],
1601
+ unresolvedProviderRecordCount: 0,
1602
+ unresolvedProviderRecordsWithoutStableIdentity: false,
1603
+ yieldedAt: null,
1604
+ },
1605
+ job,
1606
+ resource: effectiveResource,
1607
+ result,
1608
+ window,
1609
+ });
1610
+ }
1611
+ if (extendedHistoricalPolicy?.completion === "daily_aggregate"
1612
+ && window.windowStart === historicalWindowStart) {
1613
+ const historicalPullReadiness = resolveJunctionHistoricalPullReadiness({
1614
+ resource: effectiveResource,
1615
+ snapshot: await loadJunctionHistoricalPullSnapshot(context),
1616
+ sourceProviderSlug,
1617
+ });
1618
+ if (historicalPullReadiness === "no_obligation") {
1619
+ return withJunctionExtendedTimeseriesBackfillFollowUp({
1620
+ context,
1621
+ historicalPullReadiness,
1622
+ importResult: {
1623
+ acceptedProviderRecordCount: 0,
1624
+ canonicalProviderRecordIdentities: [],
1625
+ canonicalEventCount: 0,
1626
+ canonicalEventDayKeys: [],
1627
+ canonicalSparseCalendarTargets: [],
1628
+ fetchComplete: true,
1629
+ providerRecordsExamined: false,
1630
+ providerRecordCount: 0,
1631
+ unresolvedProviderRecordIdentities: [],
1632
+ unresolvedProviderRecordCount: 0,
1633
+ unresolvedProviderRecordsWithoutStableIdentity: false,
1634
+ yieldedAt: null,
1635
+ },
1636
+ job,
1637
+ resource: effectiveResource,
1638
+ result: { nextReconcileAt: clampWebhookJobNextReconcileAt(context) },
1639
+ window,
1640
+ });
1641
+ }
1642
+ if (historicalPullReadiness === "pending") {
1643
+ const retryDelayMs = EMPTY_HISTORICAL_BACKFILL_RETRY_DELAYS_MS.at(-1) ?? 0;
1644
+ return {
1645
+ nextReconcileAt: clampWebhookJobNextReconcileAt(context),
1646
+ scheduledJobs: [buildExtendedTimeseriesBackfillJob({
1647
+ availableAt: addMilliseconds(context.now, retryDelayMs),
1648
+ dedupeKey: job.dedupeKey,
1649
+ historicalWindowStart,
1650
+ resource: effectiveResource,
1651
+ sourceProviderSlug,
1652
+ windowEnd: window.windowEnd,
1653
+ windowStart: window.windowStart,
1654
+ })],
1655
+ };
1656
+ }
1657
+ if (historicalPullReadiness === "terminal_failure") {
1658
+ return { nextReconcileAt: clampWebhookJobNextReconcileAt(context) };
1659
+ }
1660
+ }
1661
+ const timeseriesPolicy = resolveJunctionTimeseriesResourcePolicy(effectiveResource);
1662
+ if (JUNCTION_DENSE_FIDELITY_RESOURCE_SET.has(effectiveResource)) {
1663
+ const dailyImport = await importTimeseriesDailyAggregateSnapshots(context, sourceProviders, window.windowStart, window.windowEnd, skippedOptionalResources, [effectiveResource], sourceProviderSlug);
1664
+ if (dailyImport.yieldedAt) {
1665
+ return withJunctionSkippedResourceMetadata(context, buildYieldedJunctionJobResult({
1666
+ context,
1667
+ job,
1668
+ windowEnd: window.windowEnd,
1669
+ windowStart: dailyImport.yieldedAt,
1670
+ }), skippedOptionalResources);
1671
+ }
1672
+ return withJunctionHistoricalCoverageVerification(context, job, window, withJunctionSkippedResourceMetadata(context, { nextReconcileAt: clampWebhookJobNextReconcileAt(context) }, skippedOptionalResources));
1673
+ }
1674
+ if (timeseriesPolicy?.historyWindow === "dense_timeseries"
1675
+ && (timeseriesPolicy.enabledByDefault === false
1676
+ || JUNCTION_CLOSED_DAY_TIMESERIES_RESOURCES.has(effectiveResource))) {
1677
+ const dailyImport = await importTimeseriesDailySnapshots(context, sourceProviders, window.windowStart, window.windowEnd, skippedOptionalResources, effectiveResource, sourceProviderSlug, completedWorkoutStreamIdentities);
1678
+ const result = withJunctionSkippedResourceMetadata(context, dailyImport.yieldedAt
1679
+ ? buildYieldedJunctionJobResult({
1680
+ context,
1681
+ job,
1682
+ windowEnd: window.windowEnd,
1683
+ windowStart: dailyImport.yieldedAt,
1684
+ workoutStreamCursor: effectiveResource === "workout_stream"
1685
+ ? dailyImport.workoutStreamCursor
1686
+ : undefined,
1687
+ })
1688
+ : { nextReconcileAt: clampWebhookJobNextReconcileAt(context) }, skippedOptionalResources);
1689
+ return result;
1690
+ }
1691
+ const timeseriesImport = await importTimeseriesPreciseSnapshots(context, sourceProviders, window.windowStart, window.windowEnd, skippedOptionalResources, [effectiveResource], sourceProviderSlug, {
1692
+ dateQueryFormat: extendedHistoricalPolicy?.completion === "daily_aggregate"
1693
+ ? "date"
1694
+ : "datetime",
1695
+ historicalProviderRecordsSeen: job.payload.historicalProviderRecordsSeen === true,
1696
+ preservePartialRetryableFailure: extendedHistoricalBackfill,
1697
+ ...(sourceIdentityAuthority ? { sourceIdentityAuthority } : {}),
1698
+ sourceStatusRequirement: extendedHistoricalBackfill
1699
+ ? "connected"
1700
+ : undefined,
1701
+ });
1702
+ const calendarRefreshJobs = JUNCTION_SPARSE_CALENDAR_AGGREGATE_RESOURCE_SET.has(effectiveResource)
1703
+ ? buildJunctionSparseCalendarRefreshJobs({
1704
+ asOf: context.now,
1705
+ priority: job.priority,
1706
+ resource: effectiveResource,
1707
+ targets: timeseriesImport.canonicalSparseCalendarTargets,
1708
+ })
1709
+ : [];
1710
+ const finalizePreciseImportResult = (result) => calendarRefreshJobs.length === 0
1711
+ ? result
1712
+ : {
1713
+ ...result,
1714
+ scheduledJobs: [
1715
+ ...(result.scheduledJobs ?? []),
1716
+ ...calendarRefreshJobs,
1717
+ ],
1718
+ };
1719
+ if (extendedHistoricalBackfill
1720
+ && timeseriesImport.postFetchSourceAdmission === "fenced") {
1721
+ return finalizePreciseImportResult({});
1722
+ }
1723
+ if (extendedHistoricalBackfill
1724
+ && timeseriesImport.postFetchSourceAdmission === "pending"
1725
+ && job.payload.historicalProviderRecordsSeen !== true
1726
+ && job.payload.historicalRecordsSeen !== true
1727
+ && timeseriesImport.providerRecordCount === 0) {
1728
+ return finalizePreciseImportResult(withJunctionSkippedResourceMetadata(context, {
1729
+ nextReconcileAt: clampWebhookJobNextReconcileAt(context),
1730
+ }, skippedOptionalResources));
1731
+ }
1732
+ const historicalRecordsSeen = extendedHistoricalBackfill
1733
+ ? job.payload.historicalRecordsSeen === true
1734
+ || timeseriesImport.canonicalEventCount > 0
1735
+ || (effectiveResource === "weight"
1736
+ && timeseriesImport.providerRecordsExamined)
1737
+ : undefined;
1738
+ const dailyAggregateNeedsRetry = extendedHistoricalPolicy?.completion === "daily_aggregate"
1739
+ && timeseriesImport.providerRecordCount > 0
1740
+ && timeseriesImport.acceptedProviderRecordCount < timeseriesImport.providerRecordCount
1741
+ && dailyAggregateRetryAttempts < EMPTY_HISTORICAL_BACKFILL_RETRY_DELAYS_MS.length;
1742
+ if (dailyAggregateNeedsRetry) {
1743
+ const retryAttempts = dailyAggregateRetryAttempts + 1;
1744
+ const retryDelayMs = EMPTY_HISTORICAL_BACKFILL_RETRY_DELAYS_MS[retryAttempts - 1] ?? 0;
1745
+ return finalizePreciseImportResult(withJunctionSkippedResourceMetadata(context, {
1746
+ nextReconcileAt: clampWebhookJobNextReconcileAt(context),
1747
+ scheduledJobs: [buildExtendedTimeseriesBackfillJob({
1748
+ availableAt: addMilliseconds(context.now, retryDelayMs),
1749
+ dedupeKey: job.dedupeKey,
1750
+ emptyBackfillAttempts: retryAttempts,
1751
+ historicalRecordsSeen,
1752
+ historicalWindowStart,
1753
+ resource: effectiveResource,
1754
+ sourceProviderSlug,
1755
+ windowEnd: window.windowEnd,
1756
+ windowStart: window.windowStart,
1757
+ })],
1758
+ }, skippedOptionalResources));
1759
+ }
1760
+ const historicalUnresolvedProviderRecords = extendedHistoricalBackfill
1761
+ && extendedHistoricalPolicy?.completion !== "daily_aggregate"
1762
+ ? resolveJunctionHistoricalUnresolvedProviderRecords(job, timeseriesImport)
1763
+ : undefined;
1764
+ const historicalUnresolvedProviderRecordCount = historicalUnresolvedProviderRecords === undefined
1765
+ ? undefined
1766
+ : countJunctionHistoricalUnresolvedProviderRecords(historicalUnresolvedProviderRecords);
1767
+ const historicalUnresolvedProviderRecordIdentitiesJson = historicalUnresolvedProviderRecords === undefined
1768
+ ? undefined
1769
+ : encodeJunctionHistoricalUnresolvedProviderRecords(historicalUnresolvedProviderRecords);
1770
+ const historicalProviderRecordsSeen = historicalUnresolvedProviderRecordCount === undefined
1771
+ ? undefined
1772
+ : historicalUnresolvedProviderRecordCount > 0;
1137
1773
  if (timeseriesImport.yieldedAt) {
1138
- return withJunctionSkippedResourceMetadata(context, buildYieldedJunctionJobResult({
1774
+ const yieldedResult = buildYieldedJunctionJobResult({
1139
1775
  context,
1776
+ emptyBackfillAttempts: extendedHistoricalPolicy?.completion === "daily_aggregate"
1777
+ ? 0
1778
+ : undefined,
1779
+ historicalProviderRecordsSeen,
1780
+ historicalRecordsSeen,
1781
+ historicalUnresolvedProviderRecordIdentitiesJson,
1782
+ historicalUnresolvedProviderRecordCount,
1140
1783
  job,
1141
1784
  windowEnd: window.windowEnd,
1142
1785
  windowStart: timeseriesImport.yieldedAt,
1143
- }), skippedOptionalResources);
1786
+ });
1787
+ return finalizePreciseImportResult(withJunctionSkippedResourceMetadata(context, yieldedResult, skippedOptionalResources));
1144
1788
  }
1145
- return withJunctionHistoricalCoverageVerification(context, job, window, withJunctionSkippedResourceMetadata(context, {
1789
+ const result = withJunctionSkippedResourceMetadata(context, {
1146
1790
  nextReconcileAt: clampWebhookJobNextReconcileAt(context),
1147
- }, skippedOptionalResources));
1791
+ }, skippedOptionalResources);
1792
+ const historicalPullReadiness = extendedHistoricalPolicy?.completion === "daily_aggregate"
1793
+ && timeseriesImport.fetchComplete
1794
+ ? resolveJunctionHistoricalPullReadiness({
1795
+ resource: effectiveResource,
1796
+ snapshot: await loadJunctionHistoricalPullSnapshot(context),
1797
+ sourceProviderSlug,
1798
+ })
1799
+ : undefined;
1800
+ return finalizePreciseImportResult(withJunctionHistoricalCoverageVerification(context, job, window, withJunctionExtendedTimeseriesBackfillFollowUp({
1801
+ context,
1802
+ historicalPullReadiness,
1803
+ importResult: timeseriesImport,
1804
+ job,
1805
+ resource: effectiveResource,
1806
+ result,
1807
+ window,
1808
+ })));
1148
1809
  }
1149
1810
  const dateQueryFormat = isFullUtcDayWindow(window) ? "date" : "datetime";
1150
1811
  summaries[effectiveResource] = await fetchOptionalJunctionResourceRecords(context, "summary", effectiveResource, skippedOptionalResources, () => client.listSummary({
@@ -1158,6 +1819,7 @@ export function createJunctionDeviceSyncProvider(config) {
1158
1819
  }));
1159
1820
  }
1160
1821
  const sourceProviders = await loadAndProjectSourceProviders();
1822
+ const preparedImport = await prepareJunctionImportSnapshot(context, summaries, sourceProviders);
1161
1823
  await context.importSnapshot({
1162
1824
  provider: "junction",
1163
1825
  accountId: buildJunctionImportAccountId(context.account.externalAccountId),
@@ -1165,8 +1827,8 @@ export function createJunctionDeviceSyncProvider(config) {
1165
1827
  importedAt: context.now,
1166
1828
  windowStart: window.windowStart,
1167
1829
  windowEnd: window.windowEnd,
1168
- connections: sanitizeJunctionImportConnections(sourceProviders),
1169
- summaries: sanitizeJunctionImportSnapshots(summaries, sourceProviders),
1830
+ connections: preparedImport.connections,
1831
+ summaries: preparedImport.snapshots,
1170
1832
  timeseries: {},
1171
1833
  });
1172
1834
  return withJunctionHistoricalCoverageVerification(context, job, window, withJunctionSkippedResourceMetadata(context, {
@@ -1211,6 +1873,167 @@ export function createJunctionDeviceSyncProvider(config) {
1211
1873
  ? scheduledAt
1212
1874
  : latestAt;
1213
1875
  }
1876
+ function withJunctionExtendedTimeseriesBackfillFollowUp(input) {
1877
+ if (!isJunctionExtendedTimeseriesBackfillJob(input.job, input.resource)) {
1878
+ return input.result;
1879
+ }
1880
+ const policy = resolveJunctionExtendedTimeseriesBackfillPolicy(input.resource);
1881
+ if (!policy) {
1882
+ return input.result;
1883
+ }
1884
+ const sourceProviderSlug = normalizeProviderSlug(input.job.payload.sourceProviderSlug);
1885
+ const historicalWindowStart = toIsoTimestampIfValid(normalizeString(input.job.payload.historicalWindowStart))
1886
+ ?? input.window.windowStart;
1887
+ const recordsSeen = input.job.payload.historicalRecordsSeen === true
1888
+ || input.importResult.canonicalEventCount > 0
1889
+ || (input.resource === "weight"
1890
+ && input.importResult.providerRecordsExamined);
1891
+ const unresolvedProviderRecords = input.resource === "weight"
1892
+ && input.importResult.fetchComplete
1893
+ && input.importResult.unresolvedProviderRecordCount === 0
1894
+ ? { identities: [], withoutStableIdentity: false }
1895
+ : resolveJunctionHistoricalUnresolvedProviderRecords(input.job, input.importResult);
1896
+ const unresolvedProviderRecordCount = countJunctionHistoricalUnresolvedProviderRecords(unresolvedProviderRecords);
1897
+ const unresolvedProviderRecordIdentitiesJson = encodeJunctionHistoricalUnresolvedProviderRecords(unresolvedProviderRecords);
1898
+ const unresolvedProviderRecordsSeen = unresolvedProviderRecordCount > 0;
1899
+ if (policy.completion === "daily_aggregate" && input.importResult.fetchComplete) {
1900
+ const historicalPullReadiness = input.historicalPullReadiness ?? "unavailable";
1901
+ const currentReconcileWindowStart = floorUtcDayTimestamp(subtractDays(floorUtcDayTimestamp(input.context.now), reconcileDays));
1902
+ if (historicalPullReadiness === "pending"
1903
+ || (historicalPullReadiness === "unavailable" && !recordsSeen)) {
1904
+ const retryDelayMs = EMPTY_HISTORICAL_BACKFILL_RETRY_DELAYS_MS.at(-1) ?? 0;
1905
+ return {
1906
+ ...input.result,
1907
+ scheduledJobs: [
1908
+ ...(input.result.scheduledJobs ?? []),
1909
+ buildExtendedTimeseriesBackfillJob({
1910
+ availableAt: addMilliseconds(input.context.now, retryDelayMs),
1911
+ dedupeKey: input.job.dedupeKey,
1912
+ historicalWindowStart,
1913
+ resource: input.resource,
1914
+ sourceProviderSlug,
1915
+ windowEnd: maxIsoTimestamp(input.window.windowEnd, currentReconcileWindowStart),
1916
+ windowStart: historicalWindowStart,
1917
+ }),
1918
+ ],
1919
+ };
1920
+ }
1921
+ if (Date.parse(input.window.windowEnd) < Date.parse(currentReconcileWindowStart)) {
1922
+ return {
1923
+ ...input.result,
1924
+ scheduledJobs: [
1925
+ ...(input.result.scheduledJobs ?? []),
1926
+ buildExtendedTimeseriesBackfillJob({
1927
+ availableAt: input.context.now,
1928
+ dedupeKey: input.job.dedupeKey,
1929
+ historicalRecordsSeen: recordsSeen,
1930
+ historicalWindowStart,
1931
+ resource: input.resource,
1932
+ sourceProviderSlug,
1933
+ windowEnd: currentReconcileWindowStart,
1934
+ windowStart: input.window.windowEnd,
1935
+ }),
1936
+ ],
1937
+ };
1938
+ }
1939
+ if (historicalPullReadiness === "terminal_failure") {
1940
+ return input.result;
1941
+ }
1942
+ return withJunctionMetadataPatch(input.result, buildJunctionExtendedTimeseriesBackfillCompletionMetadataPatch(input.context, input.job, input.resource, sourceProviderSlug));
1943
+ }
1944
+ // A complete note scan can close its one-time source coverage even when
1945
+ // no action-like tags exist. Neutral wearable-tag notes, including a
1946
+ // cleared tag state, do not create a separate backfill repair obligation.
1947
+ if (input.resource === "note" && input.importResult.fetchComplete) {
1948
+ return withJunctionMetadataPatch(input.result, buildJunctionExtendedTimeseriesBackfillCompletionMetadataPatch(input.context, input.job, input.resource, sourceProviderSlug));
1949
+ }
1950
+ const completionProven = input.importResult.fetchComplete && (policy.completion === "fetch_complete"
1951
+ || (policy.completion === "exact_records"
1952
+ && recordsSeen
1953
+ && unresolvedProviderRecordCount === 0));
1954
+ if (completionProven) {
1955
+ return withJunctionMetadataPatch(input.result, buildJunctionExtendedTimeseriesBackfillCompletionMetadataPatch(input.context, input.job, input.resource, sourceProviderSlug));
1956
+ }
1957
+ let emptyBackfillAttempts = readHistoricalBackfillJobEmptyAttempts(input.job) + 1;
1958
+ let retryDelayMs = EMPTY_HISTORICAL_BACKFILL_RETRY_DELAYS_MS[emptyBackfillAttempts - 1]
1959
+ ?? null;
1960
+ if (retryDelayMs === null
1961
+ && (!input.importResult.fetchComplete || unresolvedProviderRecordsSeen)) {
1962
+ emptyBackfillAttempts = EMPTY_HISTORICAL_BACKFILL_RETRY_DELAYS_MS.length;
1963
+ retryDelayMs =
1964
+ EMPTY_HISTORICAL_BACKFILL_RETRY_DELAYS_MS[emptyBackfillAttempts - 1]
1965
+ ?? null;
1966
+ }
1967
+ if (retryDelayMs === null) {
1968
+ return withJunctionMetadataPatch(input.result, buildJunctionExtendedTimeseriesBackfillCompletionMetadataPatch(input.context, input.job, input.resource, sourceProviderSlug));
1969
+ }
1970
+ return {
1971
+ ...input.result,
1972
+ scheduledJobs: [
1973
+ ...(input.result.scheduledJobs ?? []),
1974
+ buildExtendedTimeseriesBackfillJob({
1975
+ availableAt: addMilliseconds(input.context.now, retryDelayMs),
1976
+ dedupeKey: input.job.dedupeKey,
1977
+ emptyBackfillAttempts,
1978
+ ...(input.resource === "note"
1979
+ ? {
1980
+ historicalBackfillVersion: readJunctionNoteHistoryBackfillVersion(input.job.payload),
1981
+ }
1982
+ : {}),
1983
+ historicalProviderRecordsSeen: unresolvedProviderRecordsSeen,
1984
+ historicalRecordsSeen: recordsSeen,
1985
+ historicalUnresolvedProviderRecordIdentitiesJson: unresolvedProviderRecordIdentitiesJson,
1986
+ historicalUnresolvedProviderRecordCount: unresolvedProviderRecordCount,
1987
+ historicalWindowStart,
1988
+ resource: input.resource,
1989
+ sourceProviderSlug,
1990
+ windowEnd: input.window.windowEnd,
1991
+ windowStart: input.importResult.fetchComplete
1992
+ ? historicalWindowStart
1993
+ : input.window.windowStart,
1994
+ }),
1995
+ ],
1996
+ };
1997
+ }
1998
+ function buildJunctionExtendedTimeseriesBackfillCompletionMetadataPatch(context, job, resource, sourceProviderSlug) {
1999
+ if (!sourceProviderSlug) {
2000
+ return {};
2001
+ }
2002
+ const policy = resolveJunctionExtendedTimeseriesBackfillPolicy(resource);
2003
+ if (!policy) {
2004
+ return {};
2005
+ }
2006
+ if (!canCurrentRuntimeMutateJunctionExtendedTimeseriesHistoryBackfillCoverage(context.account.metadata, resource, policy.version)) {
2007
+ return {};
2008
+ }
2009
+ const admittedVersion = resource === "note"
2010
+ ? readJunctionNoteHistoryBackfillVersion(job.payload)
2011
+ : policy.version;
2012
+ if (admittedVersion !== policy.version) {
2013
+ // A semantic generation can only certify its own coverage. Older jobs
2014
+ // may still import facts without closing the current generation's bit.
2015
+ return {};
2016
+ }
2017
+ const coverage = addJunctionExtendedTimeseriesHistoryBackfillCoverage({
2018
+ metadata: context.account.metadata,
2019
+ providerSlug: sourceProviderSlug,
2020
+ resource,
2021
+ version: admittedVersion,
2022
+ });
2023
+ if (!coverage) {
2024
+ throw deviceSyncError({
2025
+ code: "JUNCTION_EXTENDED_HISTORY_COVERAGE_UNREPRESENTABLE",
2026
+ message: "Junction extended-history completion could not be retained exactly.",
2027
+ retryable: false,
2028
+ });
2029
+ }
2030
+ return { [coverage.metadataKey]: coverage.value };
2031
+ }
2032
+ function isJunctionExtendedTimeseriesBackfillJob(job, resource) {
2033
+ return job.kind === "resource"
2034
+ && job.payload.historicalBackfill === true
2035
+ && resolveJunctionExtendedTimeseriesBackfillPolicy(resource) !== null;
2036
+ }
1214
2037
  function withJunctionHistoricalCoverageVerification(context, job, resourceWindow, result) {
1215
2038
  const historicalState = readHistoricalBackfillStatus(context.account.metadata);
1216
2039
  const eventType = normalizeString(job.payload.eventType);
@@ -1303,7 +2126,8 @@ export function createJunctionDeviceSyncProvider(config) {
1303
2126
  const resource = inferJunctionWebhookResource(eventType, data);
1304
2127
  const sourceProviderSlug = extractJunctionWebhookSourceProviderSlug(data);
1305
2128
  const objectId = extractJunctionWebhookObjectId(data);
1306
- const occurredAt = extractJunctionWebhookOccurredAt(data) ?? context.now;
2129
+ const eventOccurredAt = extractJunctionWebhookOccurredAt(data);
2130
+ const occurredAt = eventOccurredAt ?? context.now;
1307
2131
  const window = buildJunctionWebhookWindow(data, occurredAt, context.now, resource);
1308
2132
  const webhookDataJsons = buildJunctionWebhookDataJobJsons({
1309
2133
  data,
@@ -1329,8 +2153,10 @@ export function createJunctionDeviceSyncProvider(config) {
1329
2153
  externalAccountDiagnostic: buildJunctionWebhookExternalAccountDiagnostic(externalAccountSelection),
1330
2154
  eventType,
1331
2155
  traceId: verified.messageId,
1332
- occurredAt,
2156
+ ...(eventOccurredAt ? { occurredAt: eventOccurredAt } : {}),
2157
+ providerSentAt: verified.providerSentAt,
1333
2158
  resourceCategory: resource?.category ?? null,
2159
+ sourceProviderSlug,
1334
2160
  // A historical-pull completion is a data-less notification, so accepting
1335
2161
  // its fetch job proves nothing arrived. Treating it as delivery would
1336
2162
  // refresh the arrival signal and hide the very stall this detects.
@@ -1350,23 +2176,109 @@ export function createJunctionDeviceSyncProvider(config) {
1350
2176
  if (isJunctionProfileSummaryResource(resource)) {
1351
2177
  continue;
1352
2178
  }
1353
- snapshots[resource] = await fetchOptionalJunctionResourceRecords(context, "summary", resource, skippedOptionalResources, () => client.listSummary({
2179
+ const request = {
1354
2180
  resource,
1355
2181
  signal: context.signal ?? null,
1356
2182
  userId: context.account.externalAccountId,
1357
2183
  windowStart,
1358
2184
  windowEnd,
1359
- ...(options.dateQueryFormat ? { dateQueryFormat: options.dateQueryFormat } : {}),
1360
- }));
2185
+ };
2186
+ if (options.dateQueryFormat) {
2187
+ request.dateQueryFormat = options.dateQueryFormat;
2188
+ }
2189
+ snapshots[resource] = await fetchOptionalJunctionResourceRecords(context, "summary", resource, skippedOptionalResources, () => client.listSummary(request));
1361
2190
  }
1362
2191
  return snapshots;
1363
2192
  }
1364
- async function fetchProfileSummaryOnce(context, skippedOptionalResources) {
2193
+ async function executeBoundedSummaryReconcile(input) {
2194
+ const profileAlreadyChecked = hasCheckedJunctionProfileSummary(input.context.account.metadata);
2195
+ const eligibleResources = summaryResources.filter((resource) => !isJunctionProfileSummaryResource(resource) || !profileAlreadyChecked);
2196
+ const eligibleUnits = eligibleResources.reduce((units, resource) => {
2197
+ if (resource === "sleep_cycle" && eligibleResources.includes("sleep")) {
2198
+ return units;
2199
+ }
2200
+ units.push(resource === "sleep" && eligibleResources.includes("sleep_cycle")
2201
+ ? ["sleep", "sleep_cycle"]
2202
+ : [resource]);
2203
+ return units;
2204
+ }, []);
2205
+ const requestedCursor = normalizeString(input.job.payload.summaryResourceCursor);
2206
+ const cursorIndex = requestedCursor
2207
+ ? eligibleUnits.findIndex((unit) => unit.includes(requestedCursor))
2208
+ : 0;
2209
+ const resources = eligibleUnits[cursorIndex >= 0 ? cursorIndex : 0] ?? null;
2210
+ if (!resources) {
2211
+ return null;
2212
+ }
2213
+ const summaries = {};
2214
+ let profileMetadataPatch = {};
2215
+ const profileResource = resources.find(isJunctionProfileSummaryResource);
2216
+ if (profileResource) {
2217
+ const profileSummaryResult = await fetchProfileSummaryOnce(input.context, input.skippedOptionalResources, { collectionWorkLimit: JUNCTION_FULL_JOB_SUMMARY_COLLECTION_WORK_LIMIT });
2218
+ if (profileSummaryResult.checked) {
2219
+ profileMetadataPatch = buildJunctionProfileSummaryCheckedMetadataPatch(input.context);
2220
+ }
2221
+ if (profileSummaryResult.records.length > 0) {
2222
+ summaries[profileResource] = profileSummaryResult.records;
2223
+ }
2224
+ }
2225
+ else {
2226
+ const collectionWorkLimit = resources.length > 1
2227
+ ? JUNCTION_FULL_JOB_COUPLED_SUMMARY_COLLECTION_WORK_LIMIT
2228
+ : JUNCTION_FULL_JOB_SUMMARY_COLLECTION_WORK_LIMIT;
2229
+ for (const resource of resources) {
2230
+ summaries[resource] = await fetchOptionalJunctionResourceRecords(input.context, "summary", resource, input.skippedOptionalResources, () => client.listSummary({
2231
+ collectionWorkLimit,
2232
+ dateQueryFormat: input.dateQueryFormat,
2233
+ resource,
2234
+ signal: input.context.signal ?? null,
2235
+ userId: input.context.account.externalAccountId,
2236
+ windowEnd: input.summaryWindow.windowEnd,
2237
+ windowStart: input.summaryWindow.windowStart,
2238
+ }));
2239
+ }
2240
+ }
2241
+ const preparedSummaryImport = await prepareJunctionImportSnapshot(input.context, summaries, input.sourceProviders);
2242
+ await input.context.importSnapshot({
2243
+ provider: "junction",
2244
+ accountId: buildJunctionImportAccountId(input.context.account.externalAccountId),
2245
+ connectionId: input.context.account.id,
2246
+ importedAt: input.summaryWindow.windowEnd,
2247
+ windowStart: input.summaryWindow.windowStart,
2248
+ windowEnd: input.summaryWindow.windowEnd,
2249
+ connections: preparedSummaryImport.connections,
2250
+ summaries: preparedSummaryImport.snapshots,
2251
+ timeseries: {},
2252
+ });
2253
+ const nextResource = eligibleUnits[cursorIndex >= 0 ? cursorIndex + 1 : 1]?.[0] ?? null;
2254
+ const sourceProviderSlug = normalizeProviderSlug(input.job.payload.sourceProviderSlug);
2255
+ const continuation = buildExactWindowJob({
2256
+ availableAt: input.context.now,
2257
+ kind: "reconcile",
2258
+ payload: {
2259
+ ...(sourceProviderSlug ? { sourceProviderSlug } : {}),
2260
+ ...(nextResource
2261
+ ? { summaryResourceCursor: nextResource }
2262
+ : { summaryPhaseComplete: true }),
2263
+ },
2264
+ priority: input.job.priority,
2265
+ windowEnd: input.window.windowEnd,
2266
+ windowStart: input.window.windowStart,
2267
+ });
2268
+ return withJunctionSkippedResourceMetadata(input.context, withJunctionMetadataPatch({
2269
+ nextReconcileAt: resolveJunctionNextReconcileAt(input.context.account, input.context.now, addMilliseconds(input.context.now, reconcileIntervalMs)),
2270
+ scheduledJobs: [continuation],
2271
+ }, profileMetadataPatch), input.skippedOptionalResources);
2272
+ }
2273
+ async function fetchProfileSummaryOnce(context, skippedOptionalResources, options = {}) {
1365
2274
  if (!summaryResources.some(isJunctionProfileSummaryResource)
1366
2275
  || hasCheckedJunctionProfileSummary(context.account.metadata)) {
1367
2276
  return { checked: false, records: [] };
1368
2277
  }
1369
2278
  const records = await fetchOptionalJunctionResourceRecords(context, "summary", JUNCTION_PROFILE_SUMMARY_RESOURCE, skippedOptionalResources, () => client.listProfileSummary({
2279
+ ...(options.collectionWorkLimit
2280
+ ? { collectionWorkLimit: options.collectionWorkLimit }
2281
+ : {}),
1370
2282
  signal: context.signal ?? null,
1371
2283
  userId: context.account.externalAccountId,
1372
2284
  }));
@@ -1384,21 +2296,29 @@ export function createJunctionDeviceSyncProvider(config) {
1384
2296
  let chunkStart = Date.parse(windowStart);
1385
2297
  const end = Date.parse(windowEnd);
1386
2298
  let optionalFailureLogged = false;
2299
+ const fetchChunkMs = resolveJunctionTimeseriesFetchChunkMs(resource);
1387
2300
  while (chunkStart < end) {
1388
- const chunkEnd = Math.min(chunkStart + TIMESERIES_CHUNK_MS, end);
2301
+ const chunkEnd = Math.min(chunkStart + fetchChunkMs, end);
1389
2302
  const chunkWindowStart = new Date(chunkStart).toISOString();
1390
2303
  const chunkWindowEnd = new Date(chunkEnd).toISOString();
1391
2304
  try {
1392
- const chunkRecords = await client.listTimeseries({
2305
+ const request = {
2306
+ collectionWorkLimit: options.collectionWorkLimit,
1393
2307
  resource,
1394
2308
  signal: context.signal ?? null,
1395
2309
  sourceProviderSlug,
1396
2310
  userId: context.account.externalAccountId,
1397
2311
  windowStart: chunkWindowStart,
1398
2312
  windowEnd: chunkWindowEnd,
1399
- ...(options.dateQueryFormat ? { dateQueryFormat: options.dateQueryFormat } : {}),
1400
- });
1401
- records.push(...filterJunctionTimeseriesRecordsToWindow(chunkRecords, chunkWindowStart, chunkWindowEnd));
2313
+ };
2314
+ if (options.dateQueryFormat) {
2315
+ request.dateQueryFormat = options.dateQueryFormat;
2316
+ }
2317
+ if (options.requireStructurallyCompleteCollection) {
2318
+ request.requireStructurallyCompleteCollection = true;
2319
+ }
2320
+ const chunkRecords = await fetchJunctionTimeseriesWindow(client, request);
2321
+ records.push(...filterJunctionTimeseriesRecordsToWindow(resource, chunkRecords, chunkWindowStart, chunkWindowEnd, options.dateQueryFormat));
1402
2322
  }
1403
2323
  catch (error) {
1404
2324
  const failure = classifyOptionalJunctionResourceFailure(error, "timeseries", resource, context.account.externalAccountId);
@@ -1418,21 +2338,55 @@ export function createJunctionDeviceSyncProvider(config) {
1418
2338
  }
1419
2339
  chunkStart = chunkEnd;
1420
2340
  }
2341
+ if (resource === "electrocardiogram_voltage" || resource === "workout_stream") {
2342
+ return resolveJunctionBoundedFeatureRecords(resource, records);
2343
+ }
1421
2344
  return dedupeJunctionTimeseriesRecords(resource, records);
1422
2345
  }
1423
- async function importTimeseriesPreciseSnapshots(context, sourceProviders, windowStart, windowEnd, skippedOptionalResources, resources, sourceProviderSlug) {
2346
+ async function importTimeseriesPreciseSnapshots(context, sourceProviders, windowStart, windowEnd, skippedOptionalResources, resources, sourceProviderSlug, options = {}) {
1424
2347
  const accumulatedTimeseries = {};
2348
+ let acceptedProviderRecordCount = 0;
1425
2349
  let executionWindowEnd = null;
1426
2350
  let executionWindowStart = null;
2351
+ let fetchComplete = true;
1427
2352
  let yieldedAt = null;
1428
- for (const window of buildPreciseTimeseriesWindows(windowStart, windowEnd)) {
2353
+ let canonicalEventDayKeys = [];
2354
+ let canonicalSparseCalendarTargets = [];
2355
+ let canonicalProviderRecordIdentities = [];
2356
+ let canonicalEventCount = 0;
2357
+ let providerRecordsExamined = false;
2358
+ let postFetchSourceAdmission;
2359
+ if (resources.length !== 1) {
2360
+ throw new TypeError("Precise Junction timeseries imports require exactly one resource.");
2361
+ }
2362
+ const resource = resources[0];
2363
+ const preciseWindows = buildPreciseTimeseriesWindows(windowStart, windowEnd, resolveJunctionTimeseriesImportChunkMs(resources));
2364
+ for (const [index, window] of preciseWindows.entries()) {
1429
2365
  if (context.shouldYield?.()) {
2366
+ fetchComplete = false;
1430
2367
  yieldedAt = window.windowStart;
1431
2368
  break;
1432
2369
  }
1433
2370
  const skippedResourceCountBeforeFetch = skippedOptionalResources.length;
1434
- const timeseries = await fetchTimeseriesSnapshots(context, window.windowStart, window.windowEnd, skippedOptionalResources, resources, sourceProviderSlug, { dateQueryFormat: "datetime" });
2371
+ let timeseries;
2372
+ try {
2373
+ timeseries = {
2374
+ [resource]: await fetchTimeseriesResourceInChunks(context, resource, window.windowStart, window.windowEnd, skippedOptionalResources, sourceProviderSlug, { dateQueryFormat: options.dateQueryFormat ?? "datetime" }),
2375
+ };
2376
+ }
2377
+ catch (error) {
2378
+ if (options.preservePartialRetryableFailure === true
2379
+ && (options.historicalProviderRecordsSeen === true
2380
+ || hasJunctionSnapshotRecords(accumulatedTimeseries))
2381
+ && (isRetryableDeviceSyncFailure(error)
2382
+ || isJunctionJobSignalAbort(error, context.signal))) {
2383
+ fetchComplete = false;
2384
+ break;
2385
+ }
2386
+ throw error;
2387
+ }
1435
2388
  if (skippedOptionalResources.length > skippedResourceCountBeforeFetch) {
2389
+ fetchComplete = false;
1436
2390
  break;
1437
2391
  }
1438
2392
  executionWindowStart ??= window.windowStart;
@@ -1443,58 +2397,654 @@ export function createJunctionDeviceSyncProvider(config) {
1443
2397
  ...records,
1444
2398
  ];
1445
2399
  }
2400
+ if (options.preservePartialRetryableFailure === true
2401
+ && index < preciseWindows.length - 1) {
2402
+ fetchComplete = false;
2403
+ yieldedAt = window.windowEnd;
2404
+ break;
2405
+ }
1446
2406
  }
1447
2407
  const dedupedTimeseries = dedupeJunctionTimeseriesSnapshotRecords(accumulatedTimeseries);
1448
- if (executionWindowStart && executionWindowEnd && hasJunctionSnapshotRecords(dedupedTimeseries)) {
1449
- await context.importSnapshot({
1450
- provider: "junction",
1451
- accountId: buildJunctionImportAccountId(context.account.externalAccountId),
1452
- connectionId: context.account.id,
1453
- importedAt: executionWindowEnd,
1454
- windowStart: executionWindowStart,
1455
- windowEnd: executionWindowEnd,
1456
- connections: sanitizeJunctionImportConnections(sourceProviders),
1457
- summaries: {},
1458
- timeseries: sanitizeJunctionImportSnapshots(dedupedTimeseries, sourceProviders),
1459
- });
2408
+ const providerRecordCount = countJunctionSnapshotRecords(dedupedTimeseries);
2409
+ let unresolvedProviderRecordIdentities = [];
2410
+ let unresolvedProviderRecordCount = providerRecordCount;
2411
+ let unresolvedProviderRecordsWithoutStableIdentity = providerRecordCount > 0;
2412
+ const requiresBloodPressureRecordResolution = resources.includes("blood_pressure");
2413
+ const successfulImportTerminatesWeightRows = resources.length === 1 && resources[0] === "weight";
2414
+ if (executionWindowStart && executionWindowEnd) {
2415
+ const identifyFetchedProviderRecords = (sourceIdentities) => requiresBloodPressureRecordResolution && providerRecordCount > 0
2416
+ ? identifyJunctionBloodPressureProviderRecords({
2417
+ connections: sanitizeJunctionImportConnections(sourceProviders, sourceIdentities),
2418
+ importedAt: executionWindowEnd,
2419
+ timeseries: sanitizeJunctionImportSnapshots(dedupedTimeseries, sourceProviders, { sourceIdentities }),
2420
+ windowStart: executionWindowStart,
2421
+ windowEnd: executionWindowEnd,
2422
+ })
2423
+ : null;
2424
+ const applyFetchedProviderRecordEvidence = (evidence) => {
2425
+ if (!evidence) {
2426
+ return;
2427
+ }
2428
+ unresolvedProviderRecordIdentities = uniqueJunctionProviderRecordIdentities(evidence.repairStableExternalRefResourceIds);
2429
+ unresolvedProviderRecordsWithoutStableIdentity =
2430
+ evidence.providerRecordCount !== providerRecordCount
2431
+ || evidence.repairStableExternalRefResourceIds.some((identity) => identity === null);
2432
+ unresolvedProviderRecordCount =
2433
+ unresolvedProviderRecordIdentities.length
2434
+ + (unresolvedProviderRecordsWithoutStableIdentity ? 1 : 0);
2435
+ };
2436
+ let fetchedProviderRecordIdentityEvidence = identifyFetchedProviderRecords(resolveJunctionAccountSourceIdentities(options.sourceIdentityAuthority ?? []));
2437
+ applyFetchedProviderRecordEvidence(fetchedProviderRecordIdentityEvidence);
2438
+ try {
2439
+ const currentSources = context.listConnectionSources
2440
+ ? await context.listConnectionSources()
2441
+ : context.account.sources ?? [];
2442
+ const importSourceIdentities = resolveJunctionAccountSourceIdentities(currentSources);
2443
+ if (sourceProviderSlug
2444
+ && options.sourceStatusRequirement === "connected") {
2445
+ postFetchSourceAdmission = resolveJunctionCurrentSourceAdmissionFromSources(currentSources, sourceProviderSlug, context.connectionSourceAdmissionMode !== "listed_only");
2446
+ if (postFetchSourceAdmission !== "admitted") {
2447
+ return {
2448
+ acceptedProviderRecordCount: 0,
2449
+ canonicalProviderRecordIdentities: [],
2450
+ canonicalEventCount: 0,
2451
+ canonicalEventDayKeys: [],
2452
+ canonicalSparseCalendarTargets: [],
2453
+ fetchComplete: false,
2454
+ postFetchSourceAdmission,
2455
+ providerRecordsExamined: false,
2456
+ providerRecordCount,
2457
+ unresolvedProviderRecordIdentities,
2458
+ unresolvedProviderRecordCount,
2459
+ unresolvedProviderRecordsWithoutStableIdentity,
2460
+ yieldedAt: null,
2461
+ };
2462
+ }
2463
+ }
2464
+ fetchedProviderRecordIdentityEvidence = identifyFetchedProviderRecords(importSourceIdentities);
2465
+ applyFetchedProviderRecordEvidence(fetchedProviderRecordIdentityEvidence);
2466
+ const preparedImport = prepareJunctionImportSnapshotForSources(dedupedTimeseries, sourceProviders, currentSources, {
2467
+ sourceIdentities: importSourceIdentities,
2468
+ }, {
2469
+ allowUnlistedSources: context.connectionSourceAdmissionMode !== "listed_only",
2470
+ sourceStatusRequirement: options.sourceStatusRequirement,
2471
+ });
2472
+ acceptedProviderRecordCount = countAcceptedJunctionDailyTimeseriesProviderRecords({
2473
+ connections: preparedImport.connections,
2474
+ importedAt: executionWindowEnd,
2475
+ timeseries: preparedImport.snapshots,
2476
+ windowEnd: executionWindowEnd,
2477
+ windowStart: executionWindowStart,
2478
+ });
2479
+ if (hasJunctionSnapshotRecords(preparedImport.snapshots)) {
2480
+ const receipt = await context.importSnapshot({
2481
+ provider: "junction",
2482
+ accountId: buildJunctionImportAccountId(context.account.externalAccountId),
2483
+ connectionId: context.account.id,
2484
+ importedAt: executionWindowEnd,
2485
+ windowStart: executionWindowStart,
2486
+ windowEnd: executionWindowEnd,
2487
+ timeseriesWindowKind: "precise",
2488
+ connections: preparedImport.connections,
2489
+ summaries: {},
2490
+ timeseries: preparedImport.snapshots,
2491
+ });
2492
+ providerRecordsExamined = true;
2493
+ canonicalEventCount = readProviderSnapshotCanonicalEventCount(receipt);
2494
+ canonicalEventDayKeys = readProviderSnapshotCanonicalEventDayKeys(receipt);
2495
+ canonicalSparseCalendarTargets = readProviderSnapshotCanonicalSparseCalendarTargets(receipt);
2496
+ if (fetchedProviderRecordIdentityEvidence) {
2497
+ const resolutionEvidence = resolveJunctionBloodPressureProviderRecordResolutionEvidence({
2498
+ canonicalEventCount,
2499
+ canonicalEventExternalRefResourceIds: readProviderSnapshotCanonicalEventExternalRefResourceIds(receipt),
2500
+ providerRecordCount,
2501
+ providerRecordIdentityEvidence: fetchedProviderRecordIdentityEvidence,
2502
+ });
2503
+ canonicalProviderRecordIdentities =
2504
+ resolutionEvidence.canonicalProviderRecordIdentities;
2505
+ unresolvedProviderRecordIdentities =
2506
+ resolutionEvidence.unresolvedProviderRecordIdentities;
2507
+ unresolvedProviderRecordsWithoutStableIdentity =
2508
+ resolutionEvidence.unresolvedProviderRecordsWithoutStableIdentity;
2509
+ unresolvedProviderRecordCount =
2510
+ unresolvedProviderRecordIdentities.length
2511
+ + (unresolvedProviderRecordsWithoutStableIdentity ? 1 : 0);
2512
+ }
2513
+ else if (successfulImportTerminatesWeightRows) {
2514
+ // A resolved import receipt means the weight normalizer examined
2515
+ // every delivered row. Valid readings became canonical events and
2516
+ // deterministic validation rejects are terminal; delivery errors
2517
+ // throw before this branch and retain the retry obligation.
2518
+ unresolvedProviderRecordCount = 0;
2519
+ unresolvedProviderRecordsWithoutStableIdentity = false;
2520
+ }
2521
+ else {
2522
+ unresolvedProviderRecordCount =
2523
+ canonicalEventCount >= providerRecordCount ? 0 : providerRecordCount;
2524
+ unresolvedProviderRecordsWithoutStableIdentity = unresolvedProviderRecordCount > 0;
2525
+ }
2526
+ }
2527
+ }
2528
+ catch (error) {
2529
+ if (options.preservePartialRetryableFailure === true
2530
+ && (options.historicalProviderRecordsSeen === true
2531
+ || providerRecordCount > 0)
2532
+ && (isRetryableDeviceSyncFailure(error)
2533
+ || isJunctionJobSignalAbort(error, context.signal))) {
2534
+ return {
2535
+ acceptedProviderRecordCount: 0,
2536
+ canonicalProviderRecordIdentities: [],
2537
+ canonicalEventCount: 0,
2538
+ canonicalEventDayKeys: [],
2539
+ canonicalSparseCalendarTargets: [],
2540
+ fetchComplete: false,
2541
+ providerRecordsExamined: false,
2542
+ providerRecordCount,
2543
+ unresolvedProviderRecordIdentities,
2544
+ unresolvedProviderRecordCount,
2545
+ unresolvedProviderRecordsWithoutStableIdentity,
2546
+ yieldedAt: null,
2547
+ };
2548
+ }
2549
+ throw error;
2550
+ }
1460
2551
  }
1461
2552
  return {
2553
+ acceptedProviderRecordCount,
2554
+ canonicalEventDayKeys,
2555
+ canonicalSparseCalendarTargets,
2556
+ canonicalProviderRecordIdentities,
2557
+ canonicalEventCount,
2558
+ fetchComplete,
2559
+ ...(postFetchSourceAdmission === undefined
2560
+ ? {}
2561
+ : { postFetchSourceAdmission }),
2562
+ providerRecordsExamined,
2563
+ providerRecordCount,
2564
+ unresolvedProviderRecordIdentities,
2565
+ unresolvedProviderRecordCount,
2566
+ unresolvedProviderRecordsWithoutStableIdentity,
1462
2567
  yieldedAt,
1463
2568
  };
1464
2569
  }
1465
- async function importTimeseriesDailySnapshots(context, sourceProviders, windowStart, windowEnd, skippedOptionalResources, resources, sourceProviderSlug) {
2570
+ async function importTimeseriesDailyAggregateSnapshots(context, sourceProviders, windowStart, windowEnd, skippedOptionalResources, resources, sourceProviderSlug, emptySparseCalendarSource) {
2571
+ const requestedResources = resources ?? timeseriesResources;
2572
+ const globallyClosedEndMs = resolveGloballyClosedProviderDayEnd(windowEnd, context.now);
2573
+ const appliedDailyAggregateResourceIds = new Set();
1466
2574
  for (const window of buildClosedDailyWindows(windowStart, windowEnd)) {
1467
2575
  if (context.shouldYield?.()) {
1468
2576
  return {
2577
+ appliedDailyAggregateResourceIds: [...appliedDailyAggregateResourceIds],
1469
2578
  yieldedAt: window.windowStart,
1470
2579
  };
1471
2580
  }
1472
- const timeseries = await fetchTimeseriesSnapshots(context, window.windowStart, window.windowEnd, skippedOptionalResources, resources, sourceProviderSlug, { dateQueryFormat: "date" });
1473
- if (!hasJunctionSnapshotRecords(timeseries)) {
2581
+ const windowResources = Date.parse(window.windowEnd) <= globallyClosedEndMs
2582
+ ? requestedResources
2583
+ : requestedResources.filter((resource) => !JUNCTION_CALENDAR_DAY_AGGREGATE_RESOURCE_SET.has(resource));
2584
+ if (windowResources.length === 0) {
1474
2585
  continue;
1475
2586
  }
1476
- await context.importSnapshot({
1477
- provider: "junction",
1478
- accountId: buildJunctionImportAccountId(context.account.externalAccountId),
1479
- connectionId: context.account.id,
1480
- importedAt: window.windowEnd,
1481
- windowStart: window.windowStart,
2587
+ const skippedResourceCountBeforeFetch = skippedOptionalResources.length;
2588
+ const timeseries = await fetchTimeseriesSnapshots(context, window.windowStart, window.windowEnd, skippedOptionalResources, windowResources, sourceProviderSlug, {
2589
+ dateQueryFormat: "date",
2590
+ requireStructurallyCompleteCollection: Boolean(emptySparseCalendarSource),
2591
+ });
2592
+ if (emptySparseCalendarSource
2593
+ && skippedOptionalResources.length > skippedResourceCountBeforeFetch) {
2594
+ throw deviceSyncError({
2595
+ code: "JUNCTION_CALENDAR_REFRESH_UNAVAILABLE",
2596
+ message: "Junction calendar refresh is temporarily unavailable.",
2597
+ retryable: true,
2598
+ });
2599
+ }
2600
+ if (emptySparseCalendarSource) {
2601
+ for (const resource of windowResources) {
2602
+ timeseries[resource] = filterJunctionSparseCalendarRecordsToSource(timeseries[resource] ?? [], {
2603
+ sourceProviderSlug: emptySparseCalendarSource.sourceProviderSlug,
2604
+ ...(emptySparseCalendarSource.sourceType
2605
+ ? { sourceType: emptySparseCalendarSource.sourceType }
2606
+ : {}),
2607
+ });
2608
+ }
2609
+ }
2610
+ if (!hasJunctionSnapshotRecords(timeseries) && emptySparseCalendarSource) {
2611
+ const [resource] = windowResources;
2612
+ if (!resource || !JUNCTION_SPARSE_CALENDAR_AGGREGATE_RESOURCE_SET.has(resource)) {
2613
+ throw deviceSyncError({
2614
+ code: JUNCTION_CALENDAR_REFRESH_EMPTY_IDENTITY_INVALID_CODE,
2615
+ message: "Junction empty calendar refresh lacked an admitted sparse identity.",
2616
+ retryable: false,
2617
+ });
2618
+ }
2619
+ timeseries[resource] = [buildJunctionEmptySparseCalendarAggregate({
2620
+ dayKey: window.windowStart.slice(0, 10),
2621
+ resource,
2622
+ ...emptySparseCalendarSource,
2623
+ })];
2624
+ }
2625
+ else if (!hasJunctionSnapshotRecords(timeseries)) {
2626
+ continue;
2627
+ }
2628
+ const preparedImport = await prepareJunctionImportSnapshot(context, timeseries, sourceProviders, {
2629
+ projectAccountSourceIdentities: true,
2630
+ sourceIdentities: emptySparseCalendarSource
2631
+ ? [{
2632
+ ...(emptySparseCalendarSource.sourceInstanceId
2633
+ ? { sourceInstanceId: emptySparseCalendarSource.sourceInstanceId }
2634
+ : {}),
2635
+ sourceProviderSlug: emptySparseCalendarSource.sourceProviderSlug,
2636
+ }]
2637
+ : [],
2638
+ });
2639
+ if (hasJunctionSnapshotRecords(preparedImport.snapshots)) {
2640
+ const receipt = await context.importSnapshot({
2641
+ provider: "junction",
2642
+ accountId: buildJunctionImportAccountId(context.account.externalAccountId),
2643
+ connectionId: context.account.id,
2644
+ importedAt: window.windowEnd,
2645
+ windowStart: window.windowStart,
2646
+ windowEnd: window.windowEnd,
2647
+ timeseriesWindowKind: "calendar_day",
2648
+ ...(emptySparseCalendarSource
2649
+ ? {
2650
+ strictSparseCalendarRepair: {
2651
+ dayKey: window.windowStart.slice(0, 10),
2652
+ resource: windowResources[0],
2653
+ ...emptySparseCalendarSource,
2654
+ sourceProviderSlug: normalizeJunctionSourceProviderSlug(emptySparseCalendarSource.sourceProviderSlug) ?? emptySparseCalendarSource.sourceProviderSlug,
2655
+ },
2656
+ }
2657
+ : {}),
2658
+ connections: preparedImport.connections,
2659
+ summaries: {},
2660
+ timeseries: preparedImport.snapshots,
2661
+ });
2662
+ for (const resourceId of readProviderSnapshotCanonicalEventExternalRefResourceIds(receipt) ?? []) {
2663
+ appliedDailyAggregateResourceIds.add(resourceId);
2664
+ }
2665
+ }
2666
+ }
2667
+ return {
2668
+ appliedDailyAggregateResourceIds: [...appliedDailyAggregateResourceIds],
2669
+ yieldedAt: null,
2670
+ };
2671
+ }
2672
+ async function importTimeseriesDailySnapshots(context, sourceProviders, windowStart, windowEnd, skippedOptionalResources, resource, sourceProviderSlug, completedWorkoutStreamIdentities = new Set()) {
2673
+ let resumeWorkoutStreamIdentities = new Set(completedWorkoutStreamIdentities);
2674
+ let madeProgress = false;
2675
+ for (const window of buildClosedDailyWindows(windowStart, windowEnd)) {
2676
+ let workoutStreamCursor = resource === "workout_stream"
2677
+ ? encodeJunctionWorkoutStreamCompletedIdentities(resumeWorkoutStreamIdentities)
2678
+ : null;
2679
+ if (context.shouldYield?.()) {
2680
+ if (madeProgress) {
2681
+ return {
2682
+ workoutStreamCursor,
2683
+ yieldedAt: window.windowStart,
2684
+ };
2685
+ }
2686
+ context.throwIfAborted?.();
2687
+ }
2688
+ if (resource === "workout_stream") {
2689
+ const workoutImport = await importJunctionWorkoutStreamWindow({
2690
+ allowImmediateYield: madeProgress,
2691
+ completedIdentities: resumeWorkoutStreamIdentities,
2692
+ context,
2693
+ skippedOptionalResources,
2694
+ sourceProviderSlug,
2695
+ sourceProviders,
2696
+ windowEnd: window.windowEnd,
2697
+ windowStart: window.windowStart,
2698
+ });
2699
+ workoutStreamCursor = workoutImport.workoutStreamCursor;
2700
+ madeProgress ||= workoutImport.madeProgress;
2701
+ if (workoutImport.yieldedAt) {
2702
+ return {
2703
+ workoutStreamCursor,
2704
+ yieldedAt: workoutImport.yieldedAt,
2705
+ };
2706
+ }
2707
+ madeProgress = true;
2708
+ }
2709
+ else {
2710
+ try {
2711
+ await importJunctionTimeseriesResourceSnapshot({
2712
+ context,
2713
+ dateQueryFormat: "date",
2714
+ resource,
2715
+ skippedOptionalResources,
2716
+ sourceProviderSlug,
2717
+ sourceProviders,
2718
+ windowEnd: window.windowEnd,
2719
+ windowStart: window.windowStart,
2720
+ });
2721
+ }
2722
+ catch (error) {
2723
+ if (isJunctionJobSignalAbort(error, context.signal)) {
2724
+ if (madeProgress) {
2725
+ return {
2726
+ workoutStreamCursor,
2727
+ yieldedAt: window.windowStart,
2728
+ };
2729
+ }
2730
+ throw error;
2731
+ }
2732
+ if (isRetryableDeviceSyncFailure(error)) {
2733
+ throw new JunctionTimeseriesProgressError(error, window.windowStart, workoutStreamCursor);
2734
+ }
2735
+ throw error;
2736
+ }
2737
+ madeProgress = true;
2738
+ }
2739
+ resumeWorkoutStreamIdentities = new Set();
2740
+ madeProgress = true;
2741
+ }
2742
+ return {
2743
+ workoutStreamCursor: null,
2744
+ yieldedAt: null,
2745
+ };
2746
+ }
2747
+ async function executeFullJobTimeseriesContinuation(context, job, skippedOptionalResources, completedWorkoutStreamIdentities) {
2748
+ const window = resolveJobWindow(job, context.now, job.kind === "backfill" ? summaryBackfillDays : reconcileDays);
2749
+ const baseTimeseriesWindowStart = job.kind === "backfill"
2750
+ ? maxIsoTimestamp(window.windowStart, subtractDays(window.windowEnd, timeseriesBackfillDays))
2751
+ : window.windowStart;
2752
+ const resourceCursor = readFullJobTimeseriesResourceCursor(job, timeseriesResources);
2753
+ const persistedTimeseriesCursor = readFullJobTimeseriesCursor(job, {
2754
+ windowEnd: window.windowEnd,
2755
+ windowStart: baseTimeseriesWindowStart,
2756
+ });
2757
+ const persistedTimeseriesWindowHours = readFullJobTimeseriesWindowHours(job);
2758
+ if (!resourceCursor || !persistedTimeseriesCursor) {
2759
+ throw invalidJunctionTimeseriesResourceProgress();
2760
+ }
2761
+ const timeseriesCursor = resourceCursor.restartFromWindowStart
2762
+ ? baseTimeseriesWindowStart
2763
+ : persistedTimeseriesCursor;
2764
+ const timeseriesWindowHours = resourceCursor.restartFromWindowStart
2765
+ ? 24
2766
+ : persistedTimeseriesWindowHours;
2767
+ const resource = resourceCursor.resource;
2768
+ const policy = resolveJunctionTimeseriesResourcePolicy(resource);
2769
+ if ((timeseriesWindowHours === 1
2770
+ && policy?.normalizationMode !== "hourly_or_session_feature")
2771
+ || (!resourceCursor.restartFromWindowStart
2772
+ && resource !== "workout_stream"
2773
+ && job.payload.workoutStreamCursor !== undefined)) {
2774
+ throw invalidJunctionTimeseriesResourceProgress();
2775
+ }
2776
+ const executionWindowEnd = new Date(Math.min(Date.parse(timeseriesCursor) + timeseriesWindowHours * TIMESERIES_HOUR_MS, Date.parse(window.windowEnd))).toISOString();
2777
+ let workoutStreamCursor = null;
2778
+ if (resource === "workout_stream") {
2779
+ try {
2780
+ const workoutImport = await importJunctionWorkoutStreamWindow({
2781
+ allowImmediateYield: false,
2782
+ collectionWorkLimit: JUNCTION_FULL_JOB_TIMESERIES_COLLECTION_WORK_LIMIT,
2783
+ completedIdentities: completedWorkoutStreamIdentities,
2784
+ context,
2785
+ skippedOptionalResources,
2786
+ sourceProviders: [],
2787
+ windowEnd: executionWindowEnd,
2788
+ windowStart: timeseriesCursor,
2789
+ });
2790
+ workoutStreamCursor = workoutImport.workoutStreamCursor;
2791
+ if (workoutImport.yieldedAt) {
2792
+ return buildFullJobTimeseriesContinuationResult({
2793
+ context,
2794
+ job,
2795
+ skippedOptionalResources,
2796
+ continuation: {
2797
+ timeseriesCursor,
2798
+ timeseriesResourceCursor: resource,
2799
+ timeseriesWindowHours,
2800
+ workoutStreamCursor,
2801
+ },
2802
+ window,
2803
+ });
2804
+ }
2805
+ }
2806
+ catch (error) {
2807
+ if (error instanceof JunctionTimeseriesProgressError) {
2808
+ if (!error.workoutStreamCursor
2809
+ || error.workoutStreamCursor === job.payload.workoutStreamCursor) {
2810
+ throw error.failure;
2811
+ }
2812
+ return buildFullJobTimeseriesContinuationResult({
2813
+ context,
2814
+ job,
2815
+ skippedOptionalResources,
2816
+ continuation: {
2817
+ timeseriesCursor,
2818
+ timeseriesResourceCursor: resource,
2819
+ timeseriesWindowHours,
2820
+ workoutStreamCursor: error.workoutStreamCursor,
2821
+ },
2822
+ window,
2823
+ });
2824
+ }
2825
+ throw error;
2826
+ }
2827
+ }
2828
+ else {
2829
+ try {
2830
+ const calendarDayAggregate = JUNCTION_CALENDAR_DAY_AGGREGATE_RESOURCE_SET.has(resource);
2831
+ const importWindow = calendarDayAggregate
2832
+ ? {
2833
+ windowEnd: floorUtcDayTimestamp(executionWindowEnd),
2834
+ windowStart: floorUtcDayTimestamp(timeseriesCursor),
2835
+ }
2836
+ : {
2837
+ windowEnd: executionWindowEnd,
2838
+ windowStart: timeseriesCursor,
2839
+ };
2840
+ if (Date.parse(importWindow.windowStart) < Date.parse(importWindow.windowEnd)) {
2841
+ await importJunctionTimeseriesResourceSnapshot({
2842
+ collectionWorkLimit: JUNCTION_FULL_JOB_TIMESERIES_COLLECTION_WORK_LIMIT,
2843
+ context,
2844
+ dateQueryFormat: timeseriesWindowHours === 1 ? "datetime" : "date",
2845
+ resource,
2846
+ skippedOptionalResources,
2847
+ sourceProviders: [],
2848
+ windowEnd: importWindow.windowEnd,
2849
+ windowStart: importWindow.windowStart,
2850
+ });
2851
+ }
2852
+ }
2853
+ catch (error) {
2854
+ if (isJunctionTimeseriesWindowTooLarge(error)
2855
+ && timeseriesWindowHours === 24
2856
+ && policy?.normalizationMode === "hourly_or_session_feature") {
2857
+ return buildFullJobTimeseriesContinuationResult({
2858
+ context,
2859
+ job,
2860
+ skippedOptionalResources,
2861
+ continuation: {
2862
+ timeseriesCursor,
2863
+ timeseriesResourceCursor: resource,
2864
+ timeseriesWindowHours: 1,
2865
+ workoutStreamCursor: null,
2866
+ },
2867
+ window,
2868
+ });
2869
+ }
2870
+ throw error;
2871
+ }
2872
+ }
2873
+ return buildFullJobTimeseriesContinuationResult({
2874
+ context,
2875
+ job,
2876
+ skippedOptionalResources,
2877
+ continuation: resolveNextFullJobTimeseriesContinuation({
2878
+ baseTimeseriesWindowStart,
2879
+ executionWindowEnd,
2880
+ resource,
2881
+ resources: timeseriesResources,
2882
+ timeseriesWindowHours,
1482
2883
  windowEnd: window.windowEnd,
1483
- connections: sanitizeJunctionImportConnections(sourceProviders),
1484
- summaries: {},
1485
- timeseries: sanitizeJunctionImportSnapshots(timeseries, sourceProviders),
2884
+ }),
2885
+ window,
2886
+ });
2887
+ }
2888
+ async function importJunctionTimeseriesResourceSnapshot(input) {
2889
+ const calendarDayAggregate = JUNCTION_CALENDAR_DAY_AGGREGATE_RESOURCE_SET.has(input.resource);
2890
+ if (calendarDayAggregate) {
2891
+ const windowEndMs = Date.parse(input.windowEnd);
2892
+ const globallyClosedProviderDayEnd = resolveGloballyClosedProviderDayEnd(input.windowEnd, input.context.now);
2893
+ if (!Number.isFinite(windowEndMs)
2894
+ || !Number.isFinite(globallyClosedProviderDayEnd)
2895
+ || windowEndMs > globallyClosedProviderDayEnd) {
2896
+ return;
2897
+ }
2898
+ }
2899
+ const records = await fetchTimeseriesResourceInChunks(input.context, input.resource, input.windowStart, input.windowEnd, input.skippedOptionalResources, input.sourceProviderSlug, {
2900
+ collectionWorkLimit: input.collectionWorkLimit,
2901
+ dateQueryFormat: input.dateQueryFormat,
2902
+ });
2903
+ if (records.length === 0) {
2904
+ return;
2905
+ }
2906
+ const preparedImport = await prepareJunctionImportSnapshot(input.context, { [input.resource]: records }, input.sourceProviders, { projectAccountSourceIdentities: calendarDayAggregate });
2907
+ if (!hasJunctionSnapshotRecords(preparedImport.snapshots)) {
2908
+ return;
2909
+ }
2910
+ await input.context.importSnapshot({
2911
+ provider: "junction",
2912
+ accountId: buildJunctionImportAccountId(input.context.account.externalAccountId),
2913
+ connectionId: input.context.account.id,
2914
+ importedAt: input.windowEnd,
2915
+ windowStart: input.windowStart,
2916
+ windowEnd: input.windowEnd,
2917
+ ...(calendarDayAggregate ? { timeseriesWindowKind: "calendar_day" } : {}),
2918
+ connections: preparedImport.connections,
2919
+ summaries: {},
2920
+ timeseries: preparedImport.snapshots,
2921
+ });
2922
+ }
2923
+ async function importJunctionWorkoutStreamWindow(input) {
2924
+ const policy = resolveJunctionTimeseriesResourcePolicy("workout_stream");
2925
+ const maxWorkouts = policy?.maxRecordsPerWindow;
2926
+ const maxSamples = policy?.maxSamplesPerRecord;
2927
+ if (!maxWorkouts || !maxSamples) {
2928
+ throw new TypeError("Junction workout_stream policy did not define bounded limits.");
2929
+ }
2930
+ let completedIdentities = new Set(input.completedIdentities);
2931
+ let madeProgress = false;
2932
+ const carryTerminalProgressOrThrow = (error) => {
2933
+ if (isJunctionJobSignalAbort(error, input.context.signal)) {
2934
+ if (input.allowImmediateYield || madeProgress) {
2935
+ return {
2936
+ madeProgress,
2937
+ workoutStreamCursor: encodeJunctionWorkoutStreamCompletedIdentities(completedIdentities),
2938
+ yieldedAt: input.windowStart,
2939
+ };
2940
+ }
2941
+ throw error;
2942
+ }
2943
+ if (isRetryableDeviceSyncFailure(error)) {
2944
+ throw new JunctionTimeseriesProgressError(error, input.windowStart, encodeJunctionWorkoutStreamCompletedIdentities(completedIdentities));
2945
+ }
2946
+ throw error;
2947
+ };
2948
+ let candidates;
2949
+ try {
2950
+ candidates = await listJunctionWorkoutStreamCandidates(client, {
2951
+ collectionWorkLimit: input.collectionWorkLimit,
2952
+ resource: "workout_stream",
2953
+ signal: input.context.signal ?? null,
2954
+ sourceProviderSlug: input.sourceProviderSlug,
2955
+ userId: input.context.account.externalAccountId,
2956
+ windowEnd: input.windowEnd,
2957
+ windowStart: input.windowStart,
1486
2958
  });
1487
2959
  }
2960
+ catch (error) {
2961
+ return carryTerminalProgressOrThrow(error);
2962
+ }
2963
+ const candidateIdentities = new Set(candidates.map((candidate) => candidate.identity));
2964
+ completedIdentities = new Set([...completedIdentities].filter((identity) => candidateIdentities.has(identity)));
2965
+ for (const [candidateIndex, candidate] of candidates.entries()) {
2966
+ if (completedIdentities.has(candidate.identity)) {
2967
+ continue;
2968
+ }
2969
+ if (input.context.shouldYield?.()) {
2970
+ if (input.allowImmediateYield || madeProgress) {
2971
+ return {
2972
+ madeProgress,
2973
+ workoutStreamCursor: encodeJunctionWorkoutStreamCompletedIdentities(completedIdentities),
2974
+ yieldedAt: input.windowStart,
2975
+ };
2976
+ }
2977
+ input.context.throwIfAborted?.();
2978
+ }
2979
+ let feature;
2980
+ try {
2981
+ feature = await fetchJunctionWorkoutStreamFeature(client, candidate, maxSamples, input.context.signal ?? null, input.collectionWorkLimit);
2982
+ }
2983
+ catch (error) {
2984
+ const failure = classifyOptionalJunctionResourceFailure(error, "timeseries", "workout_stream", input.context.account.externalAccountId);
2985
+ if (!failure) {
2986
+ return carryTerminalProgressOrThrow(addJunctionWorkoutStreamCandidateFailureContext(error, {
2987
+ aliasSource: candidate.workoutIdAliasSource,
2988
+ candidateCount: candidates.length,
2989
+ candidateOrdinal: candidateIndex + 1,
2990
+ }));
2991
+ }
2992
+ logSkippedOptionalJunctionResource(input.context, "timeseries", "workout_stream", failure);
2993
+ input.skippedOptionalResources.push({
2994
+ ...failure,
2995
+ resource: "workout_stream",
2996
+ resourceCategory: "timeseries",
2997
+ });
2998
+ completedIdentities.add(candidate.identity);
2999
+ madeProgress = true;
3000
+ continue;
3001
+ }
3002
+ if (feature === undefined) {
3003
+ input.context.logger.warn?.("Skipping Junction workout with unaligned metric cardinality.", {
3004
+ errorCode: "JUNCTION_WORKOUT_STREAM_CARDINALITY_MISMATCH",
3005
+ provider: "junction",
3006
+ resource: "workout_stream",
3007
+ resourceCategory: "timeseries",
3008
+ });
3009
+ completedIdentities.add(candidate.identity);
3010
+ madeProgress = true;
3011
+ continue;
3012
+ }
3013
+ try {
3014
+ const preparedImport = await prepareJunctionImportSnapshot(input.context, { workout_stream: [feature] }, input.sourceProviders);
3015
+ if (hasJunctionSnapshotRecords(preparedImport.snapshots)) {
3016
+ await input.context.importSnapshot({
3017
+ provider: "junction",
3018
+ accountId: buildJunctionImportAccountId(input.context.account.externalAccountId),
3019
+ connectionId: input.context.account.id,
3020
+ importedAt: input.windowEnd,
3021
+ windowStart: input.windowStart,
3022
+ windowEnd: input.windowEnd,
3023
+ connections: preparedImport.connections,
3024
+ summaries: {},
3025
+ timeseries: preparedImport.snapshots,
3026
+ });
3027
+ }
3028
+ }
3029
+ catch (error) {
3030
+ return carryTerminalProgressOrThrow(error);
3031
+ }
3032
+ completedIdentities.add(candidate.identity);
3033
+ madeProgress = true;
3034
+ }
1488
3035
  return {
3036
+ madeProgress,
3037
+ workoutStreamCursor: encodeJunctionWorkoutStreamCompletedIdentities(completedIdentities),
1489
3038
  yieldedAt: null,
1490
3039
  };
1491
3040
  }
1492
3041
  async function importJunctionDirectResourceSnapshot(context, sourceProviders, windowStart, windowEnd, resource, records, historicalEvidenceWindow) {
1493
3042
  const snapshots = { [resource]: [...records] };
1494
- const connections = sanitizeJunctionImportConnections(sourceProviders);
1495
- const summaries = sanitizeJunctionImportSnapshots(snapshots, sourceProviders, {
3043
+ const preparedImport = await prepareJunctionImportSnapshot(context, snapshots, sourceProviders, {
1496
3044
  blockedStringValues: [context.account.externalAccountId],
1497
3045
  });
3046
+ const connections = preparedImport.connections;
3047
+ const summaries = preparedImport.snapshots;
1498
3048
  const normalizationEvidence = classifyJunctionSummaryNormalizationEvidence({
1499
3049
  connections,
1500
3050
  importedAt: context.now,
@@ -1502,6 +3052,12 @@ export function createJunctionDeviceSyncProvider(config) {
1502
3052
  windowEnd,
1503
3053
  windowStart,
1504
3054
  }, historicalEvidenceWindow);
3055
+ if (!hasJunctionSnapshotRecords(summaries)) {
3056
+ return {
3057
+ durableDeliveryAccepted: false,
3058
+ normalizationEvidence,
3059
+ };
3060
+ }
1505
3061
  const receipt = await context.importSnapshot({
1506
3062
  provider: "junction",
1507
3063
  accountId: buildJunctionImportAccountId(context.account.externalAccountId),
@@ -1574,98 +3130,218 @@ export function createJunctionDeviceSyncProvider(config) {
1574
3130
  function buildYieldedJunctionJobResult(input) {
1575
3131
  const followUp = buildYieldedJunctionFollowUpJob(input);
1576
3132
  return {
1577
- ...(followUp ? { scheduledJobs: [followUp] } : {}),
3133
+ ...(followUp
3134
+ ? {
3135
+ scheduledJobs: [{
3136
+ ...followUp,
3137
+ ...(input.job.kind === "resource"
3138
+ ? {}
3139
+ : { availableAt: input.context.now }),
3140
+ ...(input.workoutStreamCursor !== undefined
3141
+ ? {
3142
+ maxAttempts: input.job.maxAttempts - Math.max(input.job.attempts - 1, 0),
3143
+ }
3144
+ : {}),
3145
+ }],
3146
+ }
3147
+ : {}),
1578
3148
  nextReconcileAt: input.job.kind === "resource"
1579
3149
  ? clampWebhookJobNextReconcileAt(input.context)
1580
3150
  : addMilliseconds(input.context.now, reconcileIntervalMs),
1581
3151
  };
1582
3152
  }
1583
- function buildYieldedJunctionFollowUpJob(input) {
1584
- if (Date.parse(input.windowStart) >= Date.parse(input.windowEnd)) {
3153
+ function buildDeferredNonConnectHistoricalBackfillRetry(input) {
3154
+ const emptyBackfillAttempts = readHistoricalBackfillJobEmptyAttempts(input.job);
3155
+ if (input.job.kind !== "backfill"
3156
+ || emptyBackfillAttempts === 0
3157
+ || isConnectHistoricalBackfillWindow(input.account, input.window)) {
1585
3158
  return null;
1586
3159
  }
1587
- if (input.job.kind === "backfill") {
1588
- const cursor = toIsoTimestampIfValid(input.timeseriesCursor);
1589
- if (!cursor || !isTimestampInHalfOpenWindow(cursor, input)) {
1590
- return null;
1591
- }
1592
- const emptyBackfillAttempts = readHistoricalBackfillJobEmptyAttempts(input.job);
1593
- const followUp = buildExactWindowJob({
1594
- kind: "backfill",
1595
- priority: input.job.priority,
1596
- windowEnd: input.windowEnd,
1597
- windowStart: input.windowStart,
1598
- });
1599
- return {
1600
- ...followUp,
1601
- payload: {
1602
- ...followUp.payload,
1603
- ...(emptyBackfillAttempts > 0 ? { emptyBackfillAttempts } : {}),
1604
- timeseriesCursor: cursor,
1605
- },
1606
- };
3160
+ const retryDelayMs = EMPTY_HISTORICAL_BACKFILL_RETRY_DELAYS_MS[emptyBackfillAttempts - 1] ?? null;
3161
+ if (retryDelayMs === null) {
3162
+ return null;
1607
3163
  }
1608
- if (input.job.kind === "reconcile") {
1609
- return buildExactWindowJob({
1610
- kind: input.job.kind,
1611
- priority: input.job.priority,
1612
- windowEnd: input.windowEnd,
1613
- windowStart: input.windowStart,
3164
+ const retryJob = buildExactWindowJob({
3165
+ kind: "backfill",
3166
+ priority: Math.max(input.job.priority, JUNCTION_HISTORICAL_BACKFILL_RETRY_PRIORITY),
3167
+ windowEnd: input.window.windowEnd,
3168
+ windowStart: input.window.windowStart,
3169
+ });
3170
+ return {
3171
+ ...retryJob,
3172
+ availableAt: addMilliseconds(input.now, retryDelayMs),
3173
+ payload: {
3174
+ ...(retryJob.payload ?? {}),
3175
+ emptyBackfillAttempts,
3176
+ },
3177
+ };
3178
+ }
3179
+ function buildFullJobTimeseriesContinuationResult(input) {
3180
+ const continuationJob = input.continuation
3181
+ ? buildFullJobTimeseriesContinuationJob({
3182
+ deferredEmptyBackfillAttempts: readHistoricalBackfillJobEmptyAttempts(input.job),
3183
+ job: input.job,
3184
+ ...input.continuation,
3185
+ window: input.window,
3186
+ })
3187
+ : null;
3188
+ const scheduledJob = continuationJob
3189
+ ? { ...continuationJob, availableAt: input.context.now }
3190
+ : buildDeferredNonConnectHistoricalBackfillRetry({
3191
+ account: input.context.account,
3192
+ job: input.job,
3193
+ now: input.context.now,
3194
+ window: input.window,
1614
3195
  });
3196
+ return withJunctionSkippedResourceMetadata(input.context, {
3197
+ ...(scheduledJob ? { scheduledJobs: [scheduledJob] } : {}),
3198
+ nextReconcileAt: resolveJunctionNextReconcileAt(input.context.account, input.context.now, addMilliseconds(input.context.now, reconcileIntervalMs)),
3199
+ }, input.skippedOptionalResources);
3200
+ }
3201
+ function buildFullJobTimeseriesContinuationJob(input) {
3202
+ if (input.job.kind !== "backfill" && input.job.kind !== "reconcile") {
3203
+ return null;
3204
+ }
3205
+ const timeseriesResourceCursor = normalizeFullJobTimeseriesResourceCursor(input.timeseriesResourceCursor, timeseriesResources);
3206
+ if (!timeseriesResourceCursor
3207
+ || !isTimestampInHalfOpenWindow(input.timeseriesCursor, {
3208
+ windowEnd: input.window.windowEnd,
3209
+ windowStart: input.job.kind === "backfill"
3210
+ ? maxIsoTimestamp(input.window.windowStart, subtractDays(input.window.windowEnd, timeseriesBackfillDays))
3211
+ : input.window.windowStart,
3212
+ })) {
3213
+ return null;
3214
+ }
3215
+ const sourceProviderSlug = normalizeProviderSlug(input.job.payload.sourceProviderSlug);
3216
+ return buildExactWindowJob({
3217
+ kind: input.job.kind,
3218
+ payload: {
3219
+ ...(input.deferredEmptyBackfillAttempts > 0
3220
+ ? { emptyBackfillAttempts: input.deferredEmptyBackfillAttempts }
3221
+ : {}),
3222
+ ...(sourceProviderSlug ? { sourceProviderSlug } : {}),
3223
+ timeseriesCursor: input.timeseriesCursor,
3224
+ timeseriesResourceCursor,
3225
+ ...(input.timeseriesWindowHours === 1 ? { timeseriesWindowHours: 1 } : {}),
3226
+ ...(input.workoutStreamCursor
3227
+ ? { workoutStreamCursor: input.workoutStreamCursor }
3228
+ : {}),
3229
+ },
3230
+ priority: input.job.priority,
3231
+ windowEnd: input.window.windowEnd,
3232
+ windowStart: input.window.windowStart,
3233
+ });
3234
+ }
3235
+ function buildYieldedJunctionFollowUpJob(input) {
3236
+ if (Date.parse(input.windowStart) >= Date.parse(input.windowEnd)) {
3237
+ return null;
1615
3238
  }
3239
+ const sourceProviderSlug = normalizeProviderSlug(input.job.payload.sourceProviderSlug);
1616
3240
  if (input.job.kind !== "resource") {
1617
3241
  return null;
1618
3242
  }
1619
- const payload = {
3243
+ const payload = stripUndefined({
1620
3244
  ...input.job.payload,
3245
+ emptyBackfillAttempts: input.emptyBackfillAttempts === undefined
3246
+ ? input.job.payload.emptyBackfillAttempts
3247
+ : input.emptyBackfillAttempts > 0
3248
+ ? input.emptyBackfillAttempts
3249
+ : undefined,
3250
+ ...(input.historicalProviderRecordsSeen === undefined
3251
+ ? {}
3252
+ : { historicalProviderRecordsSeen: input.historicalProviderRecordsSeen }),
3253
+ ...(input.historicalRecordsSeen === undefined
3254
+ ? {}
3255
+ : { historicalRecordsSeen: input.historicalRecordsSeen }),
3256
+ historicalUnresolvedProviderRecordIdentitiesJson: input.historicalUnresolvedProviderRecordIdentitiesJson === undefined
3257
+ ? input.job.payload.historicalUnresolvedProviderRecordIdentitiesJson
3258
+ : input.historicalUnresolvedProviderRecordIdentitiesJson,
3259
+ historicalUnresolvedProviderRecordCount: input.historicalUnresolvedProviderRecordCount === undefined
3260
+ ? input.job.payload.historicalUnresolvedProviderRecordCount
3261
+ : input.historicalUnresolvedProviderRecordCount > 0
3262
+ ? input.historicalUnresolvedProviderRecordCount
3263
+ : undefined,
1621
3264
  windowEnd: input.windowEnd,
1622
3265
  windowStart: input.windowStart,
1623
- };
3266
+ workoutStreamCursor: input.workoutStreamCursor || undefined,
3267
+ });
1624
3268
  return {
1625
3269
  kind: "resource",
1626
3270
  payload,
1627
3271
  priority: input.job.priority,
1628
- dedupeKey: sha256Text(JSON.stringify([
1629
- "junction",
1630
- "yield-follow-up",
1631
- input.windowStart,
1632
- input.windowEnd,
1633
- normalizeString(payload.eventType),
1634
- normalizeString(payload.objectId),
1635
- normalizeString(payload.occurredAt),
1636
- normalizeString(payload.resource),
1637
- normalizeString(payload.resourceCategory),
1638
- normalizeString(payload.sourceProviderSlug),
1639
- ])),
3272
+ dedupeKey: input.job.dedupeKey
3273
+ ?? buildJunctionExtendedTimeseriesBackfillDedupeKey(payload)
3274
+ ?? sha256Text(JSON.stringify([
3275
+ "junction",
3276
+ "yield-follow-up",
3277
+ input.windowStart,
3278
+ input.windowEnd,
3279
+ normalizeString(payload.eventType),
3280
+ normalizeString(payload.objectId),
3281
+ normalizeString(payload.occurredAt),
3282
+ normalizeString(payload.resource),
3283
+ normalizeString(payload.resourceCategory),
3284
+ normalizeString(payload.sourceProviderSlug),
3285
+ ])),
3286
+ };
3287
+ }
3288
+ function buildExtendedTimeseriesBackfillWindow(input) {
3289
+ const windowEnd = floorUtcDayTimestamp(input.anchorAt);
3290
+ return {
3291
+ windowEnd,
3292
+ windowStart: floorUtcDayTimestamp(subtractDays(windowEnd, input.days)),
1640
3293
  };
1641
3294
  }
1642
- function buildInitialJobs(now) {
3295
+ function hasTerminalJunctionHistoricalBackfill(account) {
3296
+ const status = readJunctionHistoricalBackfillStatus(account.metadata[JUNCTION_HISTORICAL_BACKFILL_METADATA_KEYS.status]);
3297
+ const connectWindow = buildConnectHistoricalBackfillWindow(account, summaryBackfillDays);
3298
+ return status?.coverageVersion === JUNCTION_HISTORICAL_BACKFILL_COVERAGE_VERSION
3299
+ && (status.status === "complete" || status.status === "exhausted")
3300
+ && normalizeString(account.metadata[JUNCTION_HISTORICAL_BACKFILL_METADATA_KEYS.windowStart]) === connectWindow.windowStart
3301
+ && normalizeString(account.metadata[JUNCTION_HISTORICAL_BACKFILL_METADATA_KEYS.windowEnd]) === connectWindow.windowEnd;
3302
+ }
3303
+ function buildInitialJobs(now, sourceProviderSlug) {
3304
+ const normalizedSourceProviderSlug = normalizeProviderSlug(sourceProviderSlug);
3305
+ const payload = normalizedSourceProviderSlug
3306
+ ? { sourceProviderSlug: normalizedSourceProviderSlug }
3307
+ : undefined;
1643
3308
  return [
1644
3309
  buildWindowJob({
1645
3310
  kind: "backfill",
1646
3311
  now,
3312
+ payload,
1647
3313
  windowStart: subtractDays(now, summaryBackfillDays),
1648
- priority: 30,
3314
+ priority: JUNCTION_HISTORICAL_BACKFILL_PRIORITY,
1649
3315
  }),
1650
3316
  buildWindowJob({
1651
3317
  kind: "reconcile",
1652
3318
  now,
3319
+ payload,
1653
3320
  windowStart: subtractDays(now, reconcileDays),
1654
- priority: 40,
3321
+ priority: JUNCTION_SCHEDULED_RECONCILE_PRIORITY,
1655
3322
  }),
1656
3323
  ];
1657
3324
  }
3325
+ function buildSourceConnectionWork(input) {
3326
+ return {
3327
+ initialJobs: buildInitialJobs(input.now, input.sourceProviderSlug),
3328
+ nextReconcileAt: addMilliseconds(input.now, reconcileIntervalMs),
3329
+ };
3330
+ }
1658
3331
  return {
1659
3332
  provider: "junction",
1660
- descriptor: JUNCTION_DEVICE_PROVIDER_DESCRIPTOR,
3333
+ descriptor: buildJunctionDeviceSyncRuntimeDescriptor(config),
1661
3334
  credentialPolicy: {
1662
3335
  kind: "provider_config",
1663
3336
  providerConfigKey: JUNCTION_PROVIDER_CONFIG_KEY,
1664
3337
  },
1665
3338
  connectionHandler: {
1666
3339
  beginConnection,
3340
+ buildSourceConnectionWork,
1667
3341
  completeConnection,
3342
+ isSourceAccessActive,
1668
3343
  revokeAccess,
3344
+ revokeSourceAccess,
1669
3345
  },
1670
3346
  sdkConnectionHandler: {
1671
3347
  ensureConnection: ensureSdkConnection,
@@ -1684,6 +3360,80 @@ export function createJunctionDeviceSyncProvider(config) {
1684
3360
  },
1685
3361
  };
1686
3362
  }
3363
+ async function fetchJunctionTimeseriesWindow(junctionClient, input) {
3364
+ const policy = resolveJunctionTimeseriesResourcePolicy(input.resource);
3365
+ if (!policy) {
3366
+ throw new TypeError(`Unknown Junction timeseries resource: ${input.resource}.`);
3367
+ }
3368
+ if (policy.fetchMode === "workout_stream") {
3369
+ const maxSamples = policy.maxSamplesPerRecord;
3370
+ if (!maxSamples) {
3371
+ throw new TypeError("Junction workout_stream policy did not define bounded limits.");
3372
+ }
3373
+ const candidates = await listJunctionWorkoutStreamCandidates(junctionClient, input);
3374
+ const features = [];
3375
+ for (const candidate of candidates) {
3376
+ const feature = await fetchJunctionWorkoutStreamFeature(junctionClient, candidate, maxSamples, input.signal ?? null);
3377
+ if (feature !== undefined) {
3378
+ features.push(feature);
3379
+ }
3380
+ }
3381
+ return features;
3382
+ }
3383
+ const records = await junctionClient.listTimeseries({
3384
+ ...input,
3385
+ maxRecords: input.maxRecords ?? policy.maxSamplesPerWindow,
3386
+ });
3387
+ if (policy.normalizationMode !== "ecg_recording_feature") {
3388
+ return records;
3389
+ }
3390
+ if (!policy.maxRecordsPerWindow || !policy.maxSamplesPerWindow) {
3391
+ throw new TypeError("Junction ECG voltage policy did not define bounded limits.");
3392
+ }
3393
+ return reduceJunctionElectrocardiogramVoltageRecords(records, {
3394
+ maxRecordings: policy.maxRecordsPerWindow,
3395
+ maxSamples: policy.maxSamplesPerWindow,
3396
+ });
3397
+ }
3398
+ async function listJunctionWorkoutStreamCandidates(junctionClient, input) {
3399
+ const maxWorkouts = resolveJunctionTimeseriesResourcePolicy("workout_stream")
3400
+ ?.maxRecordsPerWindow;
3401
+ if (!maxWorkouts) {
3402
+ throw new TypeError("Junction workout_stream policy did not define a workout limit.");
3403
+ }
3404
+ const indexRecords = await junctionClient.listSummary({
3405
+ collectionWorkLimit: input.collectionWorkLimit,
3406
+ resource: "workouts",
3407
+ signal: input.signal ?? null,
3408
+ sourceProviderSlug: input.sourceProviderSlug,
3409
+ userId: input.userId,
3410
+ windowStart: input.windowStart,
3411
+ windowEnd: input.windowEnd,
3412
+ maxRecords: maxWorkouts + 1,
3413
+ });
3414
+ const summaries = indexRecords.map((record) => withJunctionSourceProviderFallback(record, input.sourceProviderSlug));
3415
+ return selectJunctionWorkoutStreamCandidates(summaries, maxWorkouts);
3416
+ }
3417
+ async function fetchJunctionWorkoutStreamFeature(junctionClient, candidate, maxSamples, signal, collectionWorkLimit) {
3418
+ const stream = await junctionClient.getWorkoutStream({
3419
+ collectionWorkLimit,
3420
+ signal,
3421
+ workoutId: candidate.workoutId,
3422
+ });
3423
+ return reduceJunctionWorkoutStreamPayload({
3424
+ maxSamples,
3425
+ stream,
3426
+ summary: candidate.summary,
3427
+ });
3428
+ }
3429
+ function withJunctionSourceProviderFallback(value, sourceProviderSlug) {
3430
+ const record = readPlainObject(value);
3431
+ const normalizedSource = normalizeProviderSlug(sourceProviderSlug);
3432
+ if (!record || !normalizedSource || resolveJunctionOrigin(record).sourceProviderSlug) {
3433
+ return value;
3434
+ }
3435
+ return { ...record, sourceProviderSlug: normalizedSource };
3436
+ }
1687
3437
  function withJunctionSkippedResourceMetadata(context, result, skippedOptionalResources) {
1688
3438
  if (skippedOptionalResources.length === 0) {
1689
3439
  return result;
@@ -1711,6 +3461,7 @@ function withJunctionMetadataPatch(result, metadataPatch) {
1711
3461
  function buildJunctionProfileSummaryCheckedMetadataPatch(context) {
1712
3462
  return {
1713
3463
  [JUNCTION_PROFILE_SUMMARY_CHECKED_AT_METADATA_KEY]: context.now,
3464
+ [JUNCTION_PROFILE_SUMMARY_NORMALIZATION_REVISION_METADATA_KEY]: JUNCTION_PROFILE_SUMMARY_NORMALIZATION_REVISION,
1714
3465
  };
1715
3466
  }
1716
3467
  function buildJunctionSkippedResourceMetadataPatch(context, skippedOptionalResources) {
@@ -1740,7 +3491,29 @@ function isJunctionProfileSummaryResource(resource) {
1740
3491
  }
1741
3492
  function hasCheckedJunctionProfileSummary(metadata) {
1742
3493
  const checkedAt = normalizeString(metadata[JUNCTION_PROFILE_SUMMARY_CHECKED_AT_METADATA_KEY]);
1743
- return checkedAt !== undefined && Number.isFinite(Date.parse(checkedAt));
3494
+ return checkedAt !== undefined
3495
+ && Number.isFinite(Date.parse(checkedAt))
3496
+ && metadata[JUNCTION_PROFILE_SUMMARY_NORMALIZATION_REVISION_METADATA_KEY]
3497
+ === JUNCTION_PROFILE_SUMMARY_NORMALIZATION_REVISION;
3498
+ }
3499
+ function addJunctionWorkoutStreamCandidateFailureContext(error, input) {
3500
+ if (!isDeviceSyncError(error) || error.code !== "JUNCTION_API_REQUEST_FAILED") {
3501
+ return error;
3502
+ }
3503
+ return deviceSyncError({
3504
+ accountStatus: error.accountStatus,
3505
+ cause: error.cause,
3506
+ code: error.code,
3507
+ details: {
3508
+ ...error.details,
3509
+ requestCandidateAliasSource: input.aliasSource,
3510
+ requestCandidateCount: input.candidateCount,
3511
+ requestCandidateOrdinal: input.candidateOrdinal,
3512
+ },
3513
+ httpStatus: error.httpStatus,
3514
+ message: error.message,
3515
+ retryable: error.retryable,
3516
+ });
1744
3517
  }
1745
3518
  function classifyOptionalJunctionResourceFailure(error, resourceCategory, resource, accountExternalId) {
1746
3519
  if (!isDeviceSyncError(error) || error.code !== "JUNCTION_API_REQUEST_FAILED") {
@@ -1785,6 +3558,22 @@ function classifyOptionalJunctionResourceFailure(error, resourceCategory, resour
1785
3558
  ...(responseDetail ? { responseDetail } : {}),
1786
3559
  };
1787
3560
  }
3561
+ function isRetryableDeviceSyncFailure(error) {
3562
+ return isDeviceSyncError(error) && error.retryable;
3563
+ }
3564
+ function isJunctionJobSignalAbort(error, signal, depth = 0) {
3565
+ if (!signal?.aborted) {
3566
+ return false;
3567
+ }
3568
+ if (error === signal.reason) {
3569
+ return true;
3570
+ }
3571
+ if (depth >= 4 || typeof error !== "object" || error === null) {
3572
+ return false;
3573
+ }
3574
+ const cause = "cause" in error ? error.cause : undefined;
3575
+ return cause !== undefined && isJunctionJobSignalAbort(cause, signal, depth + 1);
3576
+ }
1788
3577
  function buildJunctionOptionalResourceResponseDetail(input) {
1789
3578
  // The generic redactor does not know the current Junction user id; strip it
1790
3579
  // explicitly before the shared sanitizer so provider prose that embeds the
@@ -2201,7 +3990,7 @@ function resolveJunctionDiagnosticMatrixResources(input) {
2201
3990
  }
2202
3991
  async function runJunctionDiagnosticMatrixRead(input) {
2203
3992
  const response = await runJunctionDiagnosticCall(() => input.category === "timeseries"
2204
- ? input.client.listTimeseries({
3993
+ ? fetchJunctionTimeseriesWindow(input.client, {
2205
3994
  resource: input.resource,
2206
3995
  sourceProviderSlug: input.sourceProviderSlug,
2207
3996
  userId: input.account.externalAccountId,
@@ -2219,9 +4008,7 @@ async function runJunctionDiagnosticMatrixRead(input) {
2219
4008
  request: {
2220
4009
  configuredResource: input.configuredResource,
2221
4010
  endpoint: input.category,
2222
- endpointKind: input.category === "timeseries"
2223
- ? "junction_timeseries_collection"
2224
- : "junction_summary_collection",
4011
+ endpointKind: resolveJunctionDiagnosticEndpointKind(input.category, input.resource),
2225
4012
  queryParameterNames: resolveJunctionDiagnosticResourceQueryParameterNames(input.category, input.resource, input.sourceProviderSlug),
2226
4013
  resource: input.resource,
2227
4014
  resourceCategory: input.category,
@@ -2231,6 +4018,14 @@ async function runJunctionDiagnosticMatrixRead(input) {
2231
4018
  response: describeJunctionDiagnosticRecords(response),
2232
4019
  };
2233
4020
  }
4021
+ function resolveJunctionDiagnosticEndpointKind(category, resource) {
4022
+ if (category === "summary") {
4023
+ return "junction_summary_collection";
4024
+ }
4025
+ return resolveJunctionTimeseriesResourcePolicy(resource)?.fetchMode === "workout_stream"
4026
+ ? "junction_workout_stream"
4027
+ : "junction_timeseries_collection";
4028
+ }
2234
4029
  function resolveJunctionDiagnosticResourceQueryParameterNames(category, resource, sourceProviderSlug) {
2235
4030
  if (category === "summary" && isJunctionProfileSummaryResource(resource)) {
2236
4031
  return sourceProviderSlug ? ["provider"] : [];
@@ -2645,10 +4440,12 @@ function normalizeDiagnosticTimeseriesProbeDays(value) {
2645
4440
  }
2646
4441
  return Math.min(value, JUNCTION_MAX_DIAGNOSTIC_TIMESERIES_PROBE_DAYS);
2647
4442
  }
2648
- export function buildJunctionClientUserId(secret, ownerId) {
4443
+ export function buildJunctionClientUserId(secret, ownerId, namespace) {
2649
4444
  const normalizedSecret = assertValidJunctionClientUserIdSecret(secret);
4445
+ const normalizedNamespace = normalizeJunctionClientUserIdNamespace(namespace);
2650
4446
  const digest = createHmac("sha256", normalizedSecret).update(ownerId).digest();
2651
- return `murph_${base32UrlEncode(digest)}`.slice(0, 32);
4447
+ const prefix = normalizedNamespace ? `murph_${normalizedNamespace}_` : "murph_";
4448
+ return `${prefix}${base32UrlEncode(digest)}`.slice(0, 32);
2652
4449
  }
2653
4450
  function resolveJunctionLinkDirectProvider(providerFilter, sourceProviderSlug) {
2654
4451
  const requested = normalizeString(sourceProviderSlug);
@@ -2671,6 +4468,7 @@ function toClientConfig(config) {
2671
4468
  apiKey: config.apiKey,
2672
4469
  environment: config.environment,
2673
4470
  region: config.region,
4471
+ apiBaseUrl: config.apiBaseUrl,
2674
4472
  allowedLinkHosts: config.allowedLinkHosts,
2675
4473
  requestTimeoutMs: config.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
2676
4474
  fetchImpl: config.fetchImpl,
@@ -2680,14 +4478,153 @@ function normalizeProviderSlug(value) {
2680
4478
  const normalized = normalizeString(value)?.toLowerCase().replace(/[^a-z0-9_]+/gu, "_").replace(/^_+|_+$/gu, "");
2681
4479
  return normalized || null;
2682
4480
  }
4481
+ function resolveJunctionProviderRouteSlug(value) {
4482
+ const normalized = normalizeProviderSlug(value);
4483
+ if (!normalized) {
4484
+ return null;
4485
+ }
4486
+ return resolveJunctionDeviceConnectRouteByProviderSlug(normalized)?.route.sourceProviderSlug
4487
+ ?? normalized;
4488
+ }
4489
+ function areJunctionProviderSlugsRouteEquivalent(left, right) {
4490
+ const normalizedLeft = normalizeProviderSlug(left);
4491
+ const normalizedRight = normalizeProviderSlug(right);
4492
+ return normalizedLeft !== null
4493
+ && normalizedRight !== null
4494
+ && areJunctionDeviceConnectProviderSlugsEquivalent(normalizedLeft, normalizedRight);
4495
+ }
4496
+ function resolveJunctionAccountSourceIdentities(sources) {
4497
+ const identities = [];
4498
+ for (const source of sources) {
4499
+ const identity = resolveJunctionAccountSourceIdentity(sources, source.sourceProviderSlug);
4500
+ if (identity
4501
+ && !identities.some((candidate) => candidate.sourceProviderSlug === identity.sourceProviderSlug)) {
4502
+ identities.push(identity);
4503
+ }
4504
+ }
4505
+ return identities;
4506
+ }
4507
+ function resolveJunctionAccountSourceStates(sources) {
4508
+ const states = [];
4509
+ for (const source of sources) {
4510
+ if (states.some((state) => areJunctionProviderSlugsRouteEquivalent(state.identitySource.sourceProviderSlug, source.sourceProviderSlug))) {
4511
+ continue;
4512
+ }
4513
+ const state = resolveJunctionAccountSourceState(sources, source.sourceProviderSlug);
4514
+ if (state) {
4515
+ states.push(state);
4516
+ }
4517
+ }
4518
+ return states;
4519
+ }
4520
+ function mergeJunctionAccountSourceIdentities(accountSourceIdentities, requestedSourceIdentities) {
4521
+ return [
4522
+ ...accountSourceIdentities,
4523
+ ...requestedSourceIdentities.filter((requestedIdentity) => !accountSourceIdentities.some((accountIdentity) => areJunctionProviderSlugsRouteEquivalent(requestedIdentity.sourceProviderSlug, accountIdentity.sourceProviderSlug))),
4524
+ ];
4525
+ }
4526
+ function resolveJunctionAccountSourceIdentity(sources, sourceProviderSlug, allowUnlistedSource = false) {
4527
+ const normalizedSourceProviderSlug = normalizeProviderSlug(sourceProviderSlug);
4528
+ if (!normalizedSourceProviderSlug) {
4529
+ return null;
4530
+ }
4531
+ const matchingSource = findJunctionAccountSource(sources, normalizedSourceProviderSlug);
4532
+ if (!matchingSource) {
4533
+ return allowUnlistedSource
4534
+ ? { sourceProviderSlug: normalizedSourceProviderSlug }
4535
+ : null;
4536
+ }
4537
+ const establishedSourceProviderSlug = normalizeProviderSlug(matchingSource.sourceProviderSlug);
4538
+ if (!establishedSourceProviderSlug) {
4539
+ return null;
4540
+ }
4541
+ const sourceInstanceId = matchingSource.sourceInstanceKey
4542
+ ? resolveJunctionOrigin({
4543
+ sourceInstanceId: matchingSource.sourceInstanceKey,
4544
+ sourceProviderSlug: establishedSourceProviderSlug,
4545
+ }).sourceInstanceId
4546
+ : undefined;
4547
+ return {
4548
+ ...(matchingSource.sourceInstanceKey
4549
+ ? {
4550
+ ...(sourceInstanceId ? { sourceInstanceId } : {}),
4551
+ sourceInstanceKey: matchingSource.sourceInstanceKey,
4552
+ }
4553
+ : {}),
4554
+ sourceProviderSlug: establishedSourceProviderSlug,
4555
+ };
4556
+ }
4557
+ function findJunctionAccountSource(sources, sourceProviderSlug) {
4558
+ return resolveJunctionAccountSourceState(sources, sourceProviderSlug)
4559
+ ?.identitySource;
4560
+ }
4561
+ function findJunctionAccountSources(sources, sourceProviderSlug) {
4562
+ return sources.filter((source) => areJunctionProviderSlugsRouteEquivalent(source.sourceProviderSlug, sourceProviderSlug));
4563
+ }
4564
+ function resolveJunctionAccountSourceState(sources, sourceProviderSlug) {
4565
+ const [first, ...rest] = findJunctionAccountSources(sources, sourceProviderSlug);
4566
+ if (!first) {
4567
+ return null;
4568
+ }
4569
+ return resolveDeviceSyncSourceState([first, ...rest], junctionSourceStateUnavailableError);
4570
+ }
2683
4571
  function stripUndefined(value) {
2684
4572
  return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
2685
4573
  }
2686
- function sanitizeJunctionImportConnections(providers) {
2687
- return providers.map((provider) => stripUndefined({
2688
- sourceProviderSlug: provider.origin.sourceProviderSlug ?? provider.slug,
2689
- sourceInstanceId: provider.origin.sourceInstanceId,
2690
- }));
4574
+ function sanitizeJunctionImportConnections(providers, sourceIdentities = []) {
4575
+ return providers.map((provider) => {
4576
+ const sourceProviderSlug = provider.origin.sourceProviderSlug ?? provider.slug;
4577
+ const projectedSourceIdentity = sourceIdentities.find((identity) => areJunctionProviderSlugsRouteEquivalent(sourceProviderSlug, identity.sourceProviderSlug));
4578
+ return stripUndefined({
4579
+ sourceProviderSlug: projectedSourceIdentity?.sourceProviderSlug ?? sourceProviderSlug,
4580
+ sourceInstanceId: projectedSourceIdentity?.sourceInstanceId ?? provider.origin.sourceInstanceId,
4581
+ });
4582
+ });
4583
+ }
4584
+ async function prepareJunctionImportSnapshot(context, snapshots, providers, options = {}, sourceStatusRequirement = "not_disconnected") {
4585
+ const currentSources = context.listConnectionSources
4586
+ ? await context.listConnectionSources()
4587
+ : context.account.sources ?? [];
4588
+ const sourceIdentities = options.projectAccountSourceIdentities
4589
+ ? mergeJunctionAccountSourceIdentities(resolveJunctionAccountSourceIdentities(currentSources), options.sourceIdentities ?? [])
4590
+ : options.sourceIdentities;
4591
+ return prepareJunctionImportSnapshotForSources(snapshots, providers, currentSources, { ...options, sourceIdentities }, {
4592
+ allowUnlistedSources: context.connectionSourceAdmissionMode !== "listed_only",
4593
+ sourceStatusRequirement,
4594
+ });
4595
+ }
4596
+ function prepareJunctionImportSnapshotForSources(snapshots, providers, currentSources, options = {}, admission = {}) {
4597
+ const allowUnlistedSources = admission.allowUnlistedSources ?? true;
4598
+ const sourceStatusRequirement = admission.sourceStatusRequirement ?? "not_disconnected";
4599
+ const sourceProviders = providers.filter((provider) => isJunctionSourceAdmittedForImport(currentSources, provider.origin.sourceProviderSlug ?? provider.slug, allowUnlistedSources, sourceStatusRequirement));
4600
+ return {
4601
+ connections: sanitizeJunctionImportConnections(sourceProviders, options.sourceIdentities),
4602
+ sourceProviders,
4603
+ snapshots: sanitizeJunctionImportSnapshots(filterJunctionImportSnapshots(snapshots, providers, currentSources, allowUnlistedSources, sourceStatusRequirement), providers, options),
4604
+ };
4605
+ }
4606
+ function filterJunctionImportSnapshots(snapshots, providers, sources, allowUnlistedSources = true, sourceStatusRequirement = "not_disconnected") {
4607
+ const sourceReferences = buildJunctionSourceReferenceMap(providers);
4608
+ const hasPendingSourceAdmission = resolveJunctionAccountSourceStates(sources).some(({ lifecycleSource }) => sourceStatusRequirement === "connected"
4609
+ ? !isDeviceSyncSourceAdmitted([lifecycleSource], lifecycleSource.sourceProviderSlug)
4610
+ : lifecycleSource.status === "disconnected"
4611
+ || isDeviceSyncSourceDisconnectFenced(lifecycleSource));
4612
+ return Object.fromEntries(Object.entries(snapshots).map(([resource, records]) => [
4613
+ resource,
4614
+ records.filter((record) => isJunctionImportRecordAdmitted(record, sourceReferences, sources, hasPendingSourceAdmission, allowUnlistedSources, sourceStatusRequirement)),
4615
+ ]));
4616
+ }
4617
+ function isJunctionImportRecordAdmitted(value, sourceReferences, sources, hasPendingSourceAdmission, allowUnlistedSources, sourceStatusRequirement) {
4618
+ const record = readPlainObject(value);
4619
+ if (!record) {
4620
+ return true;
4621
+ }
4622
+ const fallback = readJunctionSourceReference(record, sourceReferences);
4623
+ const sourceProviderSlug = normalizeProviderSlug(resolveJunctionOrigin(record, fallback).sourceProviderSlug);
4624
+ if (sourceProviderSlug) {
4625
+ return isJunctionSourceAdmittedForImport(sources, sourceProviderSlug, allowUnlistedSources, sourceStatusRequirement);
4626
+ }
4627
+ return !hasPendingSourceAdmission || !hasJunctionSourceReferenceIdentity(record);
2691
4628
  }
2692
4629
  function sanitizeJunctionImportSnapshots(snapshots, providers, options = {}) {
2693
4630
  const sourceReferences = buildJunctionSourceReferenceMap(providers);
@@ -2723,6 +4660,9 @@ function sanitizeJunctionImportSnapshotValue(value, sourceReferences, options =
2723
4660
  if (typeof value === "string") {
2724
4661
  return redactJunctionBlockedStringValue(value, options.blockedStringValues ?? []);
2725
4662
  }
4663
+ if (value instanceof Date) {
4664
+ return Number.isFinite(value.getTime()) ? value.toISOString() : null;
4665
+ }
2726
4666
  const record = readPlainObject(value);
2727
4667
  if (!record) {
2728
4668
  return value;
@@ -2736,11 +4676,18 @@ function sanitizeJunctionImportSnapshotValue(value, sourceReferences, options =
2736
4676
  hasJunctionSourceReferenceIdentity(record);
2737
4677
  const sourceInstanceId = fallbackSourceInstanceId ??
2738
4678
  (unresolvedPreservedSourceReference ? undefined : origin.sourceInstanceId);
4679
+ const sourceProviderSlug = normalizeProviderSlug(origin.sourceProviderSlug);
4680
+ const projectedSourceIdentity = options.sourceIdentities
4681
+ ?.find((identity) => areJunctionProviderSlugsRouteEquivalent(sourceProviderSlug, identity.sourceProviderSlug));
2739
4682
  return stripUndefined({
2740
4683
  ...sanitized,
2741
- sourceProviderSlug: normalizeProviderSlug(origin.sourceProviderSlug) ?? sanitized.sourceProviderSlug,
4684
+ sourceProviderSlug: projectedSourceIdentity?.sourceProviderSlug
4685
+ ?? sourceProviderSlug
4686
+ ?? sanitized.sourceProviderSlug,
2742
4687
  sourceType: origin.sourceType ?? sanitized.sourceType,
2743
- sourceInstanceId: sourceInstanceId ?? sanitized.sourceInstanceId,
4688
+ sourceInstanceId: projectedSourceIdentity?.sourceInstanceId
4689
+ ?? sourceInstanceId
4690
+ ?? sanitized.sourceInstanceId,
2744
4691
  });
2745
4692
  }
2746
4693
  function readJunctionSourceReference(record, sourceReferences) {
@@ -2838,17 +4785,39 @@ function isBlockedJunctionImportSourceIdentityContainerKey(key) {
2838
4785
  || normalized === "owner";
2839
4786
  }
2840
4787
  function dedupeJunctionTimeseriesRecords(resource, records) {
4788
+ const candidates = records.map((record) => ({
4789
+ contentKey: buildJunctionTimeseriesRecordContentKey(resource, record),
4790
+ key: buildJunctionTimeseriesRecordKey(resource, record),
4791
+ providerRowKey: buildJunctionTimeseriesProviderRowKey(resource, record),
4792
+ record,
4793
+ }));
4794
+ const contentKeysByProviderRow = new Map();
4795
+ for (const candidate of candidates) {
4796
+ if (!candidate.providerRowKey || !candidate.contentKey) {
4797
+ continue;
4798
+ }
4799
+ const contentKeys = contentKeysByProviderRow.get(candidate.providerRowKey)
4800
+ ?? new Set();
4801
+ contentKeys.add(candidate.contentKey);
4802
+ contentKeysByProviderRow.set(candidate.providerRowKey, contentKeys);
4803
+ }
4804
+ const conflictingProviderRows = new Set([...contentKeysByProviderRow.entries()]
4805
+ .filter(([, contentKeys]) => contentKeys.size > 1)
4806
+ .map(([providerRowKey]) => providerRowKey));
2841
4807
  const seen = new Set();
2842
4808
  const deduped = [];
2843
- for (const record of records) {
2844
- const key = buildJunctionTimeseriesRecordKey(resource, record);
2845
- if (key && seen.has(key)) {
4809
+ for (const candidate of candidates) {
4810
+ if (candidate.providerRowKey
4811
+ && conflictingProviderRows.has(candidate.providerRowKey)) {
4812
+ continue;
4813
+ }
4814
+ if (candidate.key && seen.has(candidate.key)) {
2846
4815
  continue;
2847
4816
  }
2848
- if (key) {
2849
- seen.add(key);
4817
+ if (candidate.key) {
4818
+ seen.add(candidate.key);
2850
4819
  }
2851
- deduped.push(record);
4820
+ deduped.push(candidate.record);
2852
4821
  }
2853
4822
  return deduped;
2854
4823
  }
@@ -2859,21 +4828,38 @@ function dedupeJunctionTimeseriesSnapshotRecords(snapshot) {
2859
4828
  }
2860
4829
  return deduped;
2861
4830
  }
2862
- function filterJunctionTimeseriesRecordsToWindow(records, windowStart, windowEnd) {
4831
+ function filterJunctionTimeseriesRecordsToWindow(resource, records, windowStart, windowEnd, dateQueryFormat) {
2863
4832
  const startMs = Date.parse(windowStart);
2864
4833
  const endMs = Date.parse(windowEnd);
2865
4834
  if (!Number.isFinite(startMs) || !Number.isFinite(endMs) || startMs >= endMs) {
2866
4835
  return [...records];
2867
4836
  }
4837
+ const policy = resolveJunctionTimeseriesResourcePolicy(resource);
4838
+ const preferIntervalStart = usesJunctionTimeseriesIntervalStartOwnership(policy);
2868
4839
  return records.filter((record) => {
2869
4840
  const entry = readPlainObject(record);
2870
4841
  if (!entry) {
2871
4842
  return true;
2872
4843
  }
2873
- const timestamp = resolveJunctionTimeseriesRecordTimestamp(entry);
2874
- if (!timestamp) {
4844
+ const rawTimestamp = resolveJunctionTimeseriesRecordRawTimestamp(entry, preferIntervalStart);
4845
+ if (!rawTimestamp) {
2875
4846
  return true;
2876
4847
  }
4848
+ if (dateQueryFormat === "date"
4849
+ && policy?.normalizationMode === "daily_aggregate") {
4850
+ if (JUNCTION_CALENDAR_DAY_AGGREGATE_RESOURCE_SET.has(resource)
4851
+ || resolveJunctionExtendedTimeseriesBackfillPolicy(resource)?.completion
4852
+ === "daily_aggregate") {
4853
+ // Junction's date-mode response owns the provider calendar day. Keep
4854
+ // every interval together even when an explicit offset crosses UTC
4855
+ // midnight; the importer owns provider-local day resolution.
4856
+ return true;
4857
+ }
4858
+ if (isJunctionFloatingCalendarTimestamp(rawTimestamp)) {
4859
+ return rawTimestamp.slice(0, 10) === windowStart.slice(0, 10);
4860
+ }
4861
+ }
4862
+ const timestamp = toIsoTimestampIfValid(rawTimestamp) ?? rawTimestamp;
2877
4863
  const recordedMs = Date.parse(timestamp);
2878
4864
  if (!Number.isFinite(recordedMs)) {
2879
4865
  return true;
@@ -2882,10 +4868,22 @@ function filterJunctionTimeseriesRecordsToWindow(records, windowStart, windowEnd
2882
4868
  });
2883
4869
  }
2884
4870
  function buildJunctionTimeseriesRecordKey(resource, record) {
4871
+ const providerRowKey = buildJunctionTimeseriesProviderRowKey(resource, record);
4872
+ if (providerRowKey) {
4873
+ return providerRowKey;
4874
+ }
2885
4875
  const entry = readPlainObject(record);
2886
4876
  if (!entry) {
2887
4877
  return null;
2888
4878
  }
4879
+ if ((resource === "electrocardiogram_voltage" && entry.schema === JUNCTION_ECG_VOLTAGE_FEATURE_SCHEMA)
4880
+ || (resource === "workout_stream" && entry.schema === JUNCTION_WORKOUT_STREAM_FEATURE_SCHEMA)) {
4881
+ return JSON.stringify([
4882
+ "junction-bounded-timeseries-feature",
4883
+ resource,
4884
+ buildJunctionBoundedFeatureIdentity(resource, entry),
4885
+ ]);
4886
+ }
2889
4887
  const origin = resolveJunctionOrigin(entry);
2890
4888
  const sourceProviderSlug = normalizeProviderSlug(origin.sourceProviderSlug);
2891
4889
  const timestamp = resolveJunctionTimeseriesRecordTimestamp(entry);
@@ -2902,26 +4900,237 @@ function buildJunctionTimeseriesRecordKey(resource, record) {
2902
4900
  ...junctionTimeseriesRecordValueIdentity(resource, entry),
2903
4901
  ]);
2904
4902
  }
2905
- // Blood-pressure readings carry their paired values as part of identity
2906
- // (the importer keeps distinct same-second readings as distinct events), so
2907
- // the pre-import dedupe key must not collapse same-timestamp rows whose
2908
- // values differ. A stable provider row id wins when present.
2909
- function junctionTimeseriesRecordValueIdentity(resource, entry) {
2910
- if (resource !== "blood_pressure") {
2911
- return [];
4903
+ function buildJunctionTimeseriesProviderRowKey(resource, record) {
4904
+ // The bounded fidelity importer owns same-row revision arbitration for these
4905
+ // resources. Keep each distinct semantic body in transport so it can select
4906
+ // an explicit newer revision or reject an ambiguous provider conflict.
4907
+ if (JUNCTION_CALENDAR_DAY_AGGREGATE_RESOURCE_SET.has(resource)) {
4908
+ return null;
4909
+ }
4910
+ const entry = readPlainObject(record);
4911
+ if (!entry) {
4912
+ return null;
4913
+ }
4914
+ const providerRowId = readJunctionTimeseriesProviderRowId(resource, entry);
4915
+ if (!providerRowId) {
4916
+ return null;
4917
+ }
4918
+ const origin = resolveJunctionOrigin(entry);
4919
+ const sourceProviderSlug = normalizeProviderSlug(origin.sourceProviderSlug);
4920
+ if (!sourceProviderSlug) {
4921
+ return null;
4922
+ }
4923
+ return JSON.stringify([
4924
+ "junction-timeseries-provider-row",
4925
+ resource,
4926
+ sourceProviderSlug,
4927
+ normalizeString(origin.sourceType) ?? "",
4928
+ normalizeString(origin.sourceInstanceId) ?? "",
4929
+ providerRowId,
4930
+ ]);
4931
+ }
4932
+ function buildJunctionTimeseriesRecordContentKey(resource, record) {
4933
+ const entry = readPlainObject(record);
4934
+ if (!entry) {
4935
+ return null;
4936
+ }
4937
+ return JSON.stringify([
4938
+ "junction-timeseries-content",
4939
+ resolveJunctionTimeseriesRecordTimestamp(entry) ?? "",
4940
+ normalizeString(entry.recordedAt ?? entry.recorded_at ?? entry.updatedAt ?? entry.updated_at)
4941
+ ?? "",
4942
+ String(entry.timeZoneOffsetMinutes
4943
+ ?? entry.time_zone_offset_minutes
4944
+ ?? entry.timezoneOffsetMinutes
4945
+ ?? entry.timezone_offset_minutes
4946
+ ?? entry.timezone_offset
4947
+ ?? entry.timezoneOffset
4948
+ ?? ""),
4949
+ normalizeString(entry.timestampSemantics ?? entry.timestamp_semantics) ?? "",
4950
+ normalizeString(entry.originConfidence ?? entry.origin_confidence) ?? "",
4951
+ ...junctionTimeseriesRecordValueIdentity(resource, entry, false),
4952
+ ]);
4953
+ }
4954
+ function junctionTimeseriesRecordNeedsSemanticIdentity(resource) {
4955
+ const policy = resolveJunctionTimeseriesResourcePolicy(resource);
4956
+ return resource === "blood_pressure"
4957
+ || resource === "note"
4958
+ || JUNCTION_CALENDAR_DAY_AGGREGATE_RESOURCE_SET.has(resource)
4959
+ || policy?.normalizationMode === "sparse_alert"
4960
+ || policy?.normalizationMode === "sparse_intervention"
4961
+ || policy?.normalizationMode === "sparse_observation"
4962
+ || policy?.normalizationMode === "sparse_reading";
4963
+ }
4964
+ function readJunctionTimeseriesProviderRowId(resource, entry) {
4965
+ if (!junctionTimeseriesRecordNeedsSemanticIdentity(resource)) {
4966
+ return null;
2912
4967
  }
2913
- // Same stable-id alias list as the importer's reading identity: rows
2914
- // distinguished only by a provider id must survive fetch-side dedupe.
2915
- for (const key of ["id", "resourceId", "resource_id", "externalId", "external_id"]) {
4968
+ const providerRowIdKeys = [
4969
+ "id",
4970
+ "resourceId",
4971
+ "resource_id",
4972
+ "externalId",
4973
+ "external_id",
4974
+ "providerId",
4975
+ "provider_id",
4976
+ ...(JUNCTION_CALENDAR_DAY_AGGREGATE_RESOURCE_SET.has(resource)
4977
+ ? ["recordId", "record_id", "sampleId", "sample_id"]
4978
+ : []),
4979
+ ];
4980
+ for (const key of providerRowIdKeys) {
2916
4981
  const rowId = normalizeString(entry[key]);
2917
4982
  if (rowId) {
2918
- return [rowId];
4983
+ return rowId;
4984
+ }
4985
+ }
4986
+ return null;
4987
+ }
4988
+ // Sparse records without stable provider row ids retain their semantic tuple
4989
+ // identity so same-time rows remain distinct when their canonical bodies differ.
4990
+ function junctionTimeseriesRecordValueIdentity(resource, entry, includeProviderRowId = true) {
4991
+ if (!junctionTimeseriesRecordNeedsSemanticIdentity(resource)) {
4992
+ return [];
4993
+ }
4994
+ const providerRowId = readJunctionTimeseriesProviderRowId(resource, entry) ?? "";
4995
+ if (resource === "weight") {
4996
+ if (includeProviderRowId && providerRowId) {
4997
+ return [providerRowId];
4998
+ }
4999
+ const { weightKilograms } = resolveJunctionWeightProviderRecordIdentity(entry);
5000
+ return weightKilograms === undefined ? [] : [`kg:${weightKilograms}`];
5001
+ }
5002
+ if (resource === "note") {
5003
+ if (includeProviderRowId && providerRowId) {
5004
+ return [providerRowId];
2919
5005
  }
5006
+ return [
5007
+ ...(Array.isArray(entry.tags) ? entry.tags : [])
5008
+ .flatMap((tag) => {
5009
+ const normalized = normalizeString(tag);
5010
+ return normalized ? [normalized] : [];
5011
+ })
5012
+ .sort(),
5013
+ ];
5014
+ }
5015
+ const fidelityPointResource = resource === "glucose"
5016
+ || resource === "blood_oxygen"
5017
+ || resource === "stress_level";
5018
+ const fidelityIntervalResource = resource === "caffeine"
5019
+ || resource === "water"
5020
+ || resource === "mindfulness_minutes";
5021
+ const rowId = includeProviderRowId ? providerRowId : "";
5022
+ const fidelitySourceRevision = String(entry.recordedAt
5023
+ ?? entry.recorded_at
5024
+ ?? entry.updatedAt
5025
+ ?? entry.updated_at
5026
+ ?? "");
5027
+ const timeZoneIdentity = [
5028
+ String(entry.timeZone ?? entry.timezone ?? entry.time_zone ?? ""),
5029
+ String(entry.timeZoneOffsetMinutes
5030
+ ?? entry.time_zone_offset_minutes
5031
+ ?? entry.timezoneOffsetMinutes
5032
+ ?? entry.timezone_offset_minutes
5033
+ ?? entry.utcOffsetMinutes
5034
+ ?? entry.utc_offset_minutes
5035
+ ?? ""),
5036
+ String(entry.timezone_offset
5037
+ ?? entry.timezoneOffset
5038
+ ?? entry.timeZoneOffset
5039
+ ?? entry.time_zone_offset
5040
+ ?? entry.timezoneOffsetSeconds
5041
+ ?? entry.timezone_offset_seconds
5042
+ ?? entry.timeZoneOffsetSeconds
5043
+ ?? entry.time_zone_offset_seconds
5044
+ ?? entry.utcOffsetSeconds
5045
+ ?? entry.utc_offset_seconds
5046
+ ?? ""),
5047
+ ];
5048
+ const providerDayIdentity = [
5049
+ String(entry.calendarDate
5050
+ ?? entry.calendar_date
5051
+ ?? entry.localDate
5052
+ ?? entry.local_date
5053
+ ?? ""),
5054
+ String(entry.timestampSemantics ?? entry.timestamp_semantics ?? ""),
5055
+ ];
5056
+ if (fidelityIntervalResource) {
5057
+ const intervalValue = resource === "mindfulness_minutes"
5058
+ ? entry.value ?? entry.mindfulnessMinutes ?? entry.mindfulness_minutes
5059
+ : resource === "caffeine"
5060
+ ? entry.value ?? entry.caffeine
5061
+ : entry.value ?? entry.water;
5062
+ return [
5063
+ rowId,
5064
+ String(entry.start ?? entry.startAt ?? entry.start_at ?? entry.timeStart ?? entry.time_start ?? ""),
5065
+ String(entry.end ?? entry.endAt ?? entry.end_at ?? entry.timeEnd ?? entry.time_end ?? ""),
5066
+ String(entry.unit ?? entry.valueUnit ?? entry.value_unit ?? ""),
5067
+ String(intervalValue ?? ""),
5068
+ ...providerDayIdentity,
5069
+ ...timeZoneIdentity,
5070
+ fidelitySourceRevision,
5071
+ ];
5072
+ }
5073
+ if (fidelityPointResource) {
5074
+ return [
5075
+ rowId,
5076
+ String(entry.observedAt
5077
+ ?? entry.observed_at
5078
+ ?? entry.observed_at_utc
5079
+ ?? entry.timestamp
5080
+ ?? entry.time
5081
+ ?? entry.date
5082
+ ?? entry.day
5083
+ ?? ""),
5084
+ String(entry.value ?? (resource === "glucose"
5085
+ ? entry.glucose ?? entry.bloodGlucose ?? entry.blood_glucose
5086
+ : resource === "blood_oxygen"
5087
+ ? entry.spo2
5088
+ ?? entry.spO2
5089
+ ?? entry.bloodOxygen
5090
+ ?? entry.blood_oxygen
5091
+ ?? entry.oxygenSaturation
5092
+ ?? entry.oxygen_saturation
5093
+ : entry.stressLevel
5094
+ ?? entry.stress_level
5095
+ ?? entry.averageStressLevel
5096
+ ?? entry.average_stress_level
5097
+ ?? readPlainObject(entry.stress)?.average
5098
+ ?? entry.stressLevelValue
5099
+ ?? entry.stress_level_value
5100
+ ?? entry.score) ?? ""),
5101
+ String(entry.unit ?? entry.valueUnit ?? entry.value_unit ?? ""),
5102
+ ...providerDayIdentity,
5103
+ ...timeZoneIdentity,
5104
+ fidelitySourceRevision,
5105
+ ];
2920
5106
  }
2921
- // Field names mirror the importer's blood-pressure value paths.
2922
- return [String(entry.systolic ?? ""), String(entry.diastolic ?? "")];
5107
+ if (resource === "blood_pressure") {
5108
+ return includeProviderRowId && providerRowId
5109
+ ? [providerRowId]
5110
+ : [String(entry.systolic ?? ""), String(entry.diastolic ?? "")];
5111
+ }
5112
+ return [
5113
+ ...(includeProviderRowId ? [providerRowId] : []),
5114
+ String(entry.start ?? ""),
5115
+ String(entry.end ?? ""),
5116
+ String(entry.value ?? ""),
5117
+ String(entry.unit ?? ""),
5118
+ String(entry.type ?? ""),
5119
+ String(entry.bolus_purpose ?? entry.bolusPurpose ?? ""),
5120
+ String(entry.delivery_form ?? entry.deliveryForm ?? ""),
5121
+ String(entry.delivery_mode ?? entry.deliveryMode ?? ""),
5122
+ ];
5123
+ }
5124
+ function resolveJunctionTimeseriesRecordTimestamp(record, preferIntervalStart = false) {
5125
+ const rawTimestamp = resolveJunctionTimeseriesRecordRawTimestamp(record, preferIntervalStart);
5126
+ return rawTimestamp
5127
+ ? toIsoTimestampIfValid(rawTimestamp) ?? rawTimestamp
5128
+ : null;
2923
5129
  }
2924
- function resolveJunctionTimeseriesRecordTimestamp(record) {
5130
+ function resolveJunctionTimeseriesRecordRawTimestamp(record, preferIntervalStart = false) {
5131
+ const intervalKeys = preferIntervalStart
5132
+ ? ["sessionStart", "session_start", "timeStart", "time_start", "start", "startAt", "start_at", "sessionEnd", "session_end", "timeEnd", "time_end", "end", "endAt", "end_at"]
5133
+ : ["sessionEnd", "session_end", "timeEnd", "time_end", "end", "endAt", "end_at", "sessionStart", "session_start", "timeStart", "time_start", "start", "startAt", "start_at"];
2925
5134
  for (const key of [
2926
5135
  "observedAt",
2927
5136
  "observed_at",
@@ -2930,21 +5139,26 @@ function resolveJunctionTimeseriesRecordTimestamp(record) {
2930
5139
  "time",
2931
5140
  "date",
2932
5141
  "day",
2933
- "end",
2934
- "endAt",
2935
- "end_at",
2936
- "start",
2937
- "startAt",
2938
- "start_at",
5142
+ ...intervalKeys,
2939
5143
  ]) {
2940
- const normalized = normalizeString(record[key]);
5144
+ const value = record[key];
5145
+ const normalized = value instanceof Date
5146
+ ? Number.isFinite(value.getTime()) ? value.toISOString() : null
5147
+ : normalizeString(value);
2941
5148
  if (!normalized) {
2942
5149
  continue;
2943
5150
  }
2944
- return toIsoTimestampIfValid(normalized) ?? normalized;
5151
+ return normalized;
2945
5152
  }
2946
5153
  return null;
2947
5154
  }
5155
+ function isJunctionFloatingCalendarTimestamp(value) {
5156
+ const normalized = value.trim();
5157
+ if (/z$/iu.test(normalized) || /[+-]\d{2}:?\d{2}$/u.test(normalized)) {
5158
+ return false;
5159
+ }
5160
+ return /^\d{4}-\d{2}-\d{2}(?:$|[ t]\d{2}:\d{2})/iu.test(normalized);
5161
+ }
2948
5162
  function buildJunctionRedirectUrl(callbackUrl, state) {
2949
5163
  const url = new URL(callbackUrl);
2950
5164
  url.searchParams.set("murph_state", state);
@@ -3016,6 +5230,115 @@ function resolveJobWindow(job, now, fallbackDays) {
3016
5230
  windowEnd,
3017
5231
  };
3018
5232
  }
5233
+ function readFullJobTimeseriesCursor(job, ownerWindow) {
5234
+ const cursor = toIsoTimestampIfValid(job.payload.timeseriesCursor);
5235
+ return cursor && isTimestampInHalfOpenWindow(cursor, ownerWindow)
5236
+ ? cursor
5237
+ : null;
5238
+ }
5239
+ function readFullJobTimeseriesWindowHours(job) {
5240
+ if (job.payload.timeseriesWindowHours === undefined) {
5241
+ return 24;
5242
+ }
5243
+ if (job.payload.timeseriesWindowHours !== 1) {
5244
+ throw invalidJunctionTimeseriesResourceProgress();
5245
+ }
5246
+ return 1;
5247
+ }
5248
+ function readFullJobTimeseriesResourceCursor(job, resources) {
5249
+ const configuredResource = normalizeFullJobTimeseriesResourceCursor(job.payload.timeseriesResourceCursor, resources);
5250
+ if (configuredResource) {
5251
+ return {
5252
+ resource: configuredResource,
5253
+ restartFromWindowStart: false,
5254
+ };
5255
+ }
5256
+ const previouslyConfiguredResource = normalizeFullJobTimeseriesResourceCursor(job.payload.timeseriesResourceCursor, JUNCTION_ALLOWED_TIMESERIES_RESOURCES);
5257
+ const firstConfiguredResource = resources[0];
5258
+ return previouslyConfiguredResource && firstConfiguredResource
5259
+ ? {
5260
+ resource: firstConfiguredResource,
5261
+ restartFromWindowStart: true,
5262
+ }
5263
+ : null;
5264
+ }
5265
+ function normalizeFullJobTimeseriesResourceCursor(value, resources) {
5266
+ const cursor = normalizeJunctionResourceName(value);
5267
+ if (cursor && resources.includes(cursor)) {
5268
+ return cursor;
5269
+ }
5270
+ if (typeof value !== "string") {
5271
+ return null;
5272
+ }
5273
+ let parsedValue;
5274
+ try {
5275
+ parsedValue = JSON.parse(value);
5276
+ }
5277
+ catch {
5278
+ return null;
5279
+ }
5280
+ const parsed = readPlainObject(parsedValue);
5281
+ const activeResource = normalizeJunctionResourceName(parsed?.a);
5282
+ const completedResources = parsed?.i;
5283
+ if (!parsed
5284
+ || parsed.v !== JUNCTION_DEPLOYED_FULL_JOB_PROGRESS_VERSION
5285
+ || Object.keys(parsed).some((key) => key !== "a" && key !== "i" && key !== "v")
5286
+ || !activeResource
5287
+ || !resources.includes(activeResource)
5288
+ || !Array.isArray(completedResources)
5289
+ || completedResources.length > JUNCTION_ALLOWED_TIMESERIES_RESOURCES.length
5290
+ || !completedResources.every((resource) => normalizeJunctionResourceName(resource) === resource
5291
+ && JUNCTION_ALLOWED_TIMESERIES_RESOURCE_SET.has(resource))) {
5292
+ return null;
5293
+ }
5294
+ const sortedCompletedResources = [...completedResources].sort();
5295
+ if (new Set(sortedCompletedResources).size !== sortedCompletedResources.length
5296
+ || sortedCompletedResources.includes(activeResource)
5297
+ || JSON.stringify({
5298
+ v: JUNCTION_DEPLOYED_FULL_JOB_PROGRESS_VERSION,
5299
+ a: activeResource,
5300
+ i: sortedCompletedResources,
5301
+ }) !== value) {
5302
+ return null;
5303
+ }
5304
+ return activeResource;
5305
+ }
5306
+ function isFullJobTimeseriesContinuation(job) {
5307
+ return (job.kind === "backfill" || job.kind === "reconcile")
5308
+ && Object.prototype.hasOwnProperty.call(job.payload, "timeseriesResourceCursor");
5309
+ }
5310
+ function isJunctionTimeseriesWindowTooLarge(error) {
5311
+ return isDeviceSyncError(error)
5312
+ && error.code === "JUNCTION_API_WINDOW_TOO_LARGE";
5313
+ }
5314
+ function resolveNextFullJobTimeseriesContinuation(input) {
5315
+ if (Date.parse(input.executionWindowEnd) < Date.parse(input.windowEnd)) {
5316
+ return {
5317
+ timeseriesCursor: input.executionWindowEnd,
5318
+ timeseriesResourceCursor: input.resource,
5319
+ timeseriesWindowHours: input.timeseriesWindowHours,
5320
+ workoutStreamCursor: null,
5321
+ };
5322
+ }
5323
+ const nextResource = input.resources[input.resources.indexOf(input.resource) + 1] ?? null;
5324
+ return nextResource
5325
+ ? {
5326
+ timeseriesCursor: input.baseTimeseriesWindowStart,
5327
+ timeseriesResourceCursor: nextResource,
5328
+ timeseriesWindowHours: 24,
5329
+ workoutStreamCursor: null,
5330
+ }
5331
+ : null;
5332
+ }
5333
+ function readDeferredEmptyBackfillAttempts(followUp) {
5334
+ for (const job of followUp.scheduledJobs ?? []) {
5335
+ const attempts = job.payload?.emptyBackfillAttempts;
5336
+ if (typeof attempts === "number" && Number.isSafeInteger(attempts) && attempts > 0) {
5337
+ return attempts;
5338
+ }
5339
+ }
5340
+ return 0;
5341
+ }
3019
5342
  function readBackfillTimeseriesCursor(job, ownerWindow) {
3020
5343
  const cursor = toIsoTimestampIfValid(job.payload.timeseriesCursor);
3021
5344
  return cursor && isTimestampInHalfOpenWindow(cursor, ownerWindow)
@@ -3059,6 +5382,19 @@ function shouldImportClosedTimeseriesForReconcile(lastSyncCompletedAt, windowEnd
3059
5382
  || !Number.isFinite(windowEndMs)
3060
5383
  || lastCompletedClosedDayMs < windowEndMs;
3061
5384
  }
5385
+ function resolveLatestGloballyClosedProviderDayWindow(windowStart, windowEnd, asOf) {
5386
+ const flooredWindowStartMs = Date.parse(floorUtcDayTimestamp(windowStart));
5387
+ const globallyClosedEndMs = resolveGloballyClosedProviderDayEnd(windowEnd, asOf);
5388
+ if (!Number.isFinite(flooredWindowStartMs)
5389
+ || !Number.isFinite(globallyClosedEndMs)
5390
+ || flooredWindowStartMs >= globallyClosedEndMs) {
5391
+ return null;
5392
+ }
5393
+ return {
5394
+ windowStart: new Date(globallyClosedEndMs - TIMESERIES_CHUNK_MS).toISOString(),
5395
+ windowEnd: new Date(globallyClosedEndMs).toISOString(),
5396
+ };
5397
+ }
3062
5398
  function buildClosedDailyWindows(windowStart, windowEnd) {
3063
5399
  const startMs = Date.parse(windowStart);
3064
5400
  const endMs = Date.parse(windowEnd);
@@ -3086,7 +5422,16 @@ function buildClosedDailyWindows(windowStart, windowEnd) {
3086
5422
  }
3087
5423
  return windows;
3088
5424
  }
3089
- function buildPreciseTimeseriesWindows(windowStart, windowEnd) {
5425
+ function resolveGloballyClosedProviderDayEnd(windowEnd, asOf) {
5426
+ const requestedClosedEndMs = Date.parse(floorUtcDayTimestamp(windowEnd));
5427
+ const asOfMs = Date.parse(asOf);
5428
+ if (!Number.isFinite(requestedClosedEndMs) || !Number.isFinite(asOfMs)) {
5429
+ return Number.NaN;
5430
+ }
5431
+ const globallyClosedEndMs = Date.parse(floorUtcDayTimestamp(new Date(asOfMs - JUNCTION_PROVIDER_CALENDAR_DAY_CLOSE_LAG_MS).toISOString()));
5432
+ return Math.min(requestedClosedEndMs, globallyClosedEndMs);
5433
+ }
5434
+ function buildPreciseTimeseriesWindows(windowStart, windowEnd, chunkMs = TIMESERIES_CHUNK_MS) {
3090
5435
  const startMs = Date.parse(windowStart);
3091
5436
  const endMs = Date.parse(windowEnd);
3092
5437
  if (!Number.isFinite(startMs) || !Number.isFinite(endMs) || startMs >= endMs) {
@@ -3095,7 +5440,7 @@ function buildPreciseTimeseriesWindows(windowStart, windowEnd) {
3095
5440
  const windows = [];
3096
5441
  let chunkStartMs = startMs;
3097
5442
  while (chunkStartMs < endMs) {
3098
- const chunkEndMs = Math.min(chunkStartMs + TIMESERIES_CHUNK_MS, endMs);
5443
+ const chunkEndMs = Math.min(chunkStartMs + chunkMs, endMs);
3099
5444
  if (chunkEndMs <= chunkStartMs) {
3100
5445
  break;
3101
5446
  }
@@ -3107,6 +5452,16 @@ function buildPreciseTimeseriesWindows(windowStart, windowEnd) {
3107
5452
  }
3108
5453
  return windows;
3109
5454
  }
5455
+ function resolveJunctionTimeseriesFetchChunkMs(resource) {
5456
+ const fetchChunkDays = resolveJunctionTimeseriesResourcePolicy(resource)?.fetchChunkDays ?? 1;
5457
+ return Math.max(1, fetchChunkDays) * TIMESERIES_CHUNK_MS;
5458
+ }
5459
+ function resolveJunctionTimeseriesImportChunkMs(resources) {
5460
+ if (resources.length === 0) {
5461
+ return TIMESERIES_CHUNK_MS;
5462
+ }
5463
+ return resources.reduce((smallest, resource) => Math.min(smallest, resolveJunctionTimeseriesFetchChunkMs(resource)), Number.POSITIVE_INFINITY);
5464
+ }
3110
5465
  function floorUtcDayTimestamp(timestamp) {
3111
5466
  const parsed = Date.parse(timestamp);
3112
5467
  if (!Number.isFinite(parsed)) {
@@ -3118,9 +5473,39 @@ function floorUtcDayTimestamp(timestamp) {
3118
5473
  function hasJunctionSnapshotRecords(snapshot) {
3119
5474
  return Object.values(snapshot).some((records) => records.length > 0);
3120
5475
  }
5476
+ function countJunctionSnapshotRecords(snapshot) {
5477
+ return Object.values(snapshot).reduce((recordCount, records) => recordCount + records.length, 0);
5478
+ }
3121
5479
  function hasJunctionHistoricalBackfillSummaryRecords(evidence) {
3122
5480
  return evidence.some(({ resource }) => isJunctionHistoricalBackfillCompletionSummaryResource(resource));
3123
5481
  }
5482
+ function resolveJunctionHistoricalPullReadiness(input) {
5483
+ const sourceProviderSlug = canonicalizeJunctionHistoricalProviderSlug(input.sourceProviderSlug)
5484
+ ?? normalizeProviderSlug(input.sourceProviderSlug);
5485
+ if (!sourceProviderSlug || !input.snapshot?.matchedUser) {
5486
+ return "unavailable";
5487
+ }
5488
+ const source = input.snapshot.sources.find((entry) => (canonicalizeJunctionHistoricalProviderSlug(entry.sourceProviderSlug)
5489
+ ?? normalizeProviderSlug(entry.sourceProviderSlug)) === sourceProviderSlug);
5490
+ if (!source) {
5491
+ return "unavailable";
5492
+ }
5493
+ const pulled = source.pulledResources.find((entry) => normalizeJunctionResourceName(entry.resource) === input.resource);
5494
+ if (pulled) {
5495
+ if (pulled.status === "success") {
5496
+ return "ready";
5497
+ }
5498
+ if (pulled.status === "failure") {
5499
+ return "terminal_failure";
5500
+ }
5501
+ return ["in_progress", "retrying", "scheduled"].includes(pulled.status)
5502
+ ? "pending"
5503
+ : "unavailable";
5504
+ }
5505
+ return source.notPulledResources.some((resource) => normalizeJunctionResourceName(resource) === input.resource)
5506
+ ? "no_obligation"
5507
+ : "unavailable";
5508
+ }
3124
5509
  function evaluateJunctionHistoricalBackfillCoverage(summaryEvidence, sourceProviders, configuredSummaryResources, providerFilter, historicalPullSnapshot, historicalPushEvidence, window) {
3125
5510
  const configuredResources = new Set(configuredSummaryResources.filter((resource) => JUNCTION_HISTORICAL_BACKFILL_REQUIRED_SUMMARY_RESOURCE_SET.has(resource)));
3126
5511
  const advertisedResourcesByProvider = new Map();
@@ -3273,6 +5658,22 @@ function isJunctionResourceAdvertisedAvailable(value) {
3273
5658
  return record.available === true
3274
5659
  || normalizeString(record.status)?.toLowerCase() === "available";
3275
5660
  }
5661
+ function isJunctionResourceAvailableInSummary(availabilitySummary, resource) {
5662
+ const normalizedResource = normalizeJunctionResourceName(resource);
5663
+ if (!normalizedResource || !availabilitySummary) {
5664
+ return false;
5665
+ }
5666
+ return Object.entries(availabilitySummary).some(([candidate, availability]) => normalizeJunctionResourceName(candidate) === normalizedResource
5667
+ && isJunctionResourceAdvertisedAvailable(availability));
5668
+ }
5669
+ function isJunctionSourceResourceCurrentlyAvailable(input) {
5670
+ if (!input.sourceProviderSlug) {
5671
+ return false;
5672
+ }
5673
+ return projectJunctionSourcesByProviderSlug(input.connectionId, input.providers).some((source) => source.sourceProviderSlug === input.sourceProviderSlug
5674
+ && source.status === "connected"
5675
+ && isJunctionResourceAvailableInSummary(source.resourceAvailabilitySummary, input.resource));
5676
+ }
3276
5677
  function isJunctionHistoricalBackfillCompletionSummaryResource(resource) {
3277
5678
  return JUNCTION_HISTORICAL_BACKFILL_COMPLETION_SUMMARY_RESOURCE_SET.has(resource);
3278
5679
  }
@@ -3416,6 +5817,155 @@ function readHistoricalBackfillJobEmptyAttempts(job) {
3416
5817
  const rawAttempts = job.payload.emptyBackfillAttempts;
3417
5818
  return typeof rawAttempts === "number" && Number.isInteger(rawAttempts) && rawAttempts > 0 ? rawAttempts : 0;
3418
5819
  }
5820
+ function readJunctionWorkoutStreamCompletedIdentities(job) {
5821
+ const encoded = job.payload.workoutStreamCursor;
5822
+ if (encoded === undefined) {
5823
+ return new Set();
5824
+ }
5825
+ const maxWorkouts = resolveJunctionTimeseriesResourcePolicy("workout_stream")
5826
+ ?.maxRecordsPerWindow;
5827
+ if (!maxWorkouts || typeof encoded !== "string" || encoded.length === 0) {
5828
+ throw invalidJunctionWorkoutStreamProgress();
5829
+ }
5830
+ let parsedValue;
5831
+ try {
5832
+ parsedValue = JSON.parse(encoded);
5833
+ }
5834
+ catch {
5835
+ throw invalidJunctionWorkoutStreamProgress();
5836
+ }
5837
+ const parsed = readPlainObject(parsedValue);
5838
+ const identities = parsed?.i;
5839
+ if (!parsed
5840
+ || parsed.v !== JUNCTION_WORKOUT_STREAM_PROGRESS_VERSION
5841
+ || Object.keys(parsed).some((key) => key !== "i" && key !== "v")
5842
+ || !Array.isArray(identities)
5843
+ || identities.length === 0
5844
+ || identities.length > maxWorkouts
5845
+ || !identities.every(isCanonicalJunctionWorkoutStreamCandidateIdentity)) {
5846
+ throw invalidJunctionWorkoutStreamProgress();
5847
+ }
5848
+ const sortedIdentities = [...identities].sort();
5849
+ if (new Set(sortedIdentities).size !== sortedIdentities.length
5850
+ || JSON.stringify({ v: JUNCTION_WORKOUT_STREAM_PROGRESS_VERSION, i: sortedIdentities })
5851
+ !== encoded) {
5852
+ throw invalidJunctionWorkoutStreamProgress();
5853
+ }
5854
+ return new Set(sortedIdentities);
5855
+ }
5856
+ function encodeJunctionWorkoutStreamCompletedIdentities(identities) {
5857
+ if (identities.size === 0) {
5858
+ return null;
5859
+ }
5860
+ const maxWorkouts = resolveJunctionTimeseriesResourcePolicy("workout_stream")
5861
+ ?.maxRecordsPerWindow;
5862
+ const sortedIdentities = [...identities].sort();
5863
+ if (!maxWorkouts
5864
+ || sortedIdentities.length > maxWorkouts
5865
+ || !sortedIdentities.every(isCanonicalJunctionWorkoutStreamCandidateIdentity)) {
5866
+ throw new TypeError("Junction workout stream progress exceeded its identity contract.");
5867
+ }
5868
+ return JSON.stringify({
5869
+ v: JUNCTION_WORKOUT_STREAM_PROGRESS_VERSION,
5870
+ i: sortedIdentities,
5871
+ });
5872
+ }
5873
+ function isCanonicalJunctionWorkoutStreamCandidateIdentity(value) {
5874
+ if (typeof value !== "string" || value.length === 0) {
5875
+ return false;
5876
+ }
5877
+ let identity;
5878
+ try {
5879
+ identity = JSON.parse(value);
5880
+ }
5881
+ catch {
5882
+ return false;
5883
+ }
5884
+ if (!Array.isArray(identity) || identity.length !== 4) {
5885
+ return false;
5886
+ }
5887
+ const [sourceProviderSlug, sourceType, sourceInstanceId, stableId] = identity;
5888
+ return isNonEmptyCanonicalIdentityPart(sourceProviderSlug)
5889
+ && (sourceType === null || isNonEmptyCanonicalIdentityPart(sourceType))
5890
+ && (sourceInstanceId === null || isNonEmptyCanonicalIdentityPart(sourceInstanceId))
5891
+ && isNonEmptyCanonicalIdentityPart(stableId)
5892
+ && JSON.stringify(identity) === value;
5893
+ }
5894
+ function isNonEmptyCanonicalIdentityPart(value) {
5895
+ return typeof value === "string" && value.length > 0 && value.trim() === value;
5896
+ }
5897
+ function invalidJunctionTimeseriesResourceProgress() {
5898
+ return deviceSyncError({
5899
+ code: "DEVICE_SYNC_JOB_PAYLOAD_INVALID",
5900
+ message: "Junction timeseries resource continuation metadata was invalid.",
5901
+ retryable: false,
5902
+ });
5903
+ }
5904
+ function invalidJunctionWorkoutStreamProgress() {
5905
+ return deviceSyncError({
5906
+ code: "DEVICE_SYNC_JOB_PAYLOAD_INVALID",
5907
+ message: "Junction workout stream continuation metadata was invalid.",
5908
+ retryable: false,
5909
+ });
5910
+ }
5911
+ function readJunctionHistoricalUnresolvedProviderRecords(job) {
5912
+ const encoded = job.payload.historicalUnresolvedProviderRecordIdentitiesJson;
5913
+ if (typeof encoded === "string") {
5914
+ try {
5915
+ const parsed = readPlainObject(JSON.parse(encoded));
5916
+ const rawIdentities = parsed?.i;
5917
+ const version = parsed?.v;
5918
+ if (version !== JUNCTION_HISTORICAL_UNRESOLVED_PROVIDER_RECORD_IDENTITIES_VERSION
5919
+ || !Array.isArray(rawIdentities)) {
5920
+ return { identities: [], withoutStableIdentity: true };
5921
+ }
5922
+ const validIdentities = rawIdentities.filter((identity) => typeof identity === "string"
5923
+ && JUNCTION_BLOOD_PRESSURE_PROVIDER_RECORD_IDENTITY_PATTERN.test(identity));
5924
+ const identities = [...new Set(validIdentities)].sort();
5925
+ return {
5926
+ identities,
5927
+ withoutStableIdentity: parsed?.u === true
5928
+ || validIdentities.length !== rawIdentities.length,
5929
+ };
5930
+ }
5931
+ catch {
5932
+ return { identities: [], withoutStableIdentity: true };
5933
+ }
5934
+ }
5935
+ const legacyUnresolvedEvidence = job.payload.historicalProviderRecordsSeen === true
5936
+ || (typeof job.payload.historicalUnresolvedProviderRecordCount === "number"
5937
+ && Number.isSafeInteger(job.payload.historicalUnresolvedProviderRecordCount)
5938
+ && job.payload.historicalUnresolvedProviderRecordCount > 0);
5939
+ return {
5940
+ identities: [],
5941
+ withoutStableIdentity: legacyUnresolvedEvidence,
5942
+ };
5943
+ }
5944
+ function resolveJunctionHistoricalUnresolvedProviderRecords(job, importResult) {
5945
+ const carried = readJunctionHistoricalUnresolvedProviderRecords(job);
5946
+ const identities = new Set(carried.identities);
5947
+ for (const identity of importResult.canonicalProviderRecordIdentities) {
5948
+ identities.delete(identity);
5949
+ }
5950
+ for (const identity of importResult.unresolvedProviderRecordIdentities) {
5951
+ identities.add(identity);
5952
+ }
5953
+ return {
5954
+ identities: [...identities].sort(),
5955
+ withoutStableIdentity: carried.withoutStableIdentity
5956
+ || importResult.unresolvedProviderRecordsWithoutStableIdentity,
5957
+ };
5958
+ }
5959
+ function countJunctionHistoricalUnresolvedProviderRecords(unresolved) {
5960
+ return unresolved.identities.length + (unresolved.withoutStableIdentity ? 1 : 0);
5961
+ }
5962
+ function encodeJunctionHistoricalUnresolvedProviderRecords(unresolved) {
5963
+ return JSON.stringify({
5964
+ v: JUNCTION_HISTORICAL_UNRESOLVED_PROVIDER_RECORD_IDENTITIES_VERSION,
5965
+ i: unresolved.identities,
5966
+ ...(unresolved.withoutStableIdentity ? { u: true } : {}),
5967
+ });
5968
+ }
3419
5969
  function buildConnectHistoricalBackfillWindow(account, summaryBackfillDays) {
3420
5970
  return {
3421
5971
  windowStart: floorUtcDayTimestamp(subtractDays(account.connectedAt, summaryBackfillDays)),
@@ -3427,6 +5977,7 @@ function buildWindowJob(input) {
3427
5977
  const windowStart = floorUtcDayTimestamp(input.windowStart);
3428
5978
  return buildExactWindowJob({
3429
5979
  kind: input.kind,
5980
+ payload: input.payload,
3430
5981
  windowStart,
3431
5982
  windowEnd,
3432
5983
  availableAt: input.now,
@@ -3434,6 +5985,15 @@ function buildWindowJob(input) {
3434
5985
  });
3435
5986
  }
3436
5987
  function buildExactWindowJob(input) {
5988
+ const windowPayload = input.payload;
5989
+ const sourceProviderSlug = normalizeString(windowPayload?.sourceProviderSlug);
5990
+ const dedupeIdentity = [
5991
+ "junction",
5992
+ input.kind,
5993
+ input.windowStart,
5994
+ input.windowEnd,
5995
+ ...(sourceProviderSlug ? [sourceProviderSlug] : []),
5996
+ ];
3437
5997
  return {
3438
5998
  kind: input.kind,
3439
5999
  payload: {
@@ -3443,9 +6003,261 @@ function buildExactWindowJob(input) {
3443
6003
  },
3444
6004
  priority: input.priority,
3445
6005
  ...(input.availableAt ? { availableAt: input.availableAt } : {}),
3446
- dedupeKey: sha256Text(JSON.stringify(["junction", input.kind, input.windowStart, input.windowEnd])),
6006
+ dedupeKey: sha256Text(JSON.stringify(dedupeIdentity)),
6007
+ };
6008
+ }
6009
+ function buildJunctionSparseCalendarRefreshJobs(input) {
6010
+ const targets = [...new Map(input.targets.map((target) => [
6011
+ JSON.stringify([
6012
+ target.dayKey,
6013
+ target.sourceProviderSlug,
6014
+ target.sourceType ?? null,
6015
+ target.sourceInstanceId ?? null,
6016
+ ]),
6017
+ target,
6018
+ ])).values()];
6019
+ const dayKeys = [...new Set(targets.map((target) => target.dayKey))].sort();
6020
+ if (dayKeys.length > JUNCTION_MAX_SPARSE_CALENDAR_REFRESH_DAYS
6021
+ || targets.length > JUNCTION_MAX_SPARSE_CALENDAR_REFRESH_DAYS) {
6022
+ throw deviceSyncError({
6023
+ code: "JUNCTION_CALENDAR_REFRESH_DAY_LIMIT_EXCEEDED",
6024
+ message: "Junction sparse import exceeded the calendar refresh day limit.",
6025
+ retryable: false,
6026
+ details: {
6027
+ affectedDayCount: dayKeys.length,
6028
+ affectedTargetCount: targets.length,
6029
+ maxAllowed: JUNCTION_MAX_SPARSE_CALENDAR_REFRESH_DAYS,
6030
+ },
6031
+ });
6032
+ }
6033
+ return targets
6034
+ .filter((target) => isGloballyClosedJunctionProviderDay(target.dayKey, input.asOf))
6035
+ .map((target) => buildJunctionSparseCalendarRefreshJob({
6036
+ dayKey: target.dayKey,
6037
+ priority: input.priority,
6038
+ resource: input.resource,
6039
+ sourceInstanceId: target.sourceInstanceId,
6040
+ sourceProviderSlug: target.sourceProviderSlug,
6041
+ sourceType: target.sourceType,
6042
+ }));
6043
+ }
6044
+ function buildJunctionSparseCalendarRefreshJob(input) {
6045
+ const windowStart = `${input.dayKey}T00:00:00.000Z`;
6046
+ const windowEnd = addMilliseconds(windowStart, TIMESERIES_CHUNK_MS);
6047
+ const sourceProviderSlug = normalizeProviderSlug(input.sourceProviderSlug);
6048
+ const sourceInstanceId = normalizeString(input.sourceInstanceId);
6049
+ const sourceType = normalizeString(input.sourceType);
6050
+ return {
6051
+ kind: "resource",
6052
+ payload: {
6053
+ calendarRefreshDay: input.dayKey,
6054
+ resource: input.resource,
6055
+ resourceCategory: "timeseries",
6056
+ ...(sourceInstanceId ? { sourceInstanceId } : {}),
6057
+ ...(sourceProviderSlug ? { sourceProviderSlug } : {}),
6058
+ ...(sourceType ? { sourceType } : {}),
6059
+ windowEnd,
6060
+ windowStart,
6061
+ },
6062
+ priority: input.priority,
6063
+ dedupeKey: sha256Text(JSON.stringify([
6064
+ "junction",
6065
+ "sparse-calendar-refresh",
6066
+ sourceProviderSlug,
6067
+ sourceType,
6068
+ sourceInstanceId,
6069
+ input.resource,
6070
+ input.dayKey,
6071
+ ])),
6072
+ };
6073
+ }
6074
+ function readJunctionSparseCalendarRefreshDay(job) {
6075
+ if (!("calendarRefreshDay" in job.payload)) {
6076
+ return null;
6077
+ }
6078
+ const dayKey = job.payload.calendarRefreshDay;
6079
+ if (!isCanonicalEventDayKey(dayKey)) {
6080
+ throw deviceSyncError({
6081
+ code: JUNCTION_CALENDAR_REFRESH_JOB_INVALID_CODE,
6082
+ message: "Junction calendar refresh job had an invalid provider day.",
6083
+ retryable: false,
6084
+ });
6085
+ }
6086
+ return dayKey;
6087
+ }
6088
+ function readJunctionSparseCalendarSourceIdentity(job) {
6089
+ const sourceProviderSlug = normalizeProviderSlug(job.payload.sourceProviderSlug);
6090
+ if (!sourceProviderSlug) {
6091
+ throw deviceSyncError({
6092
+ code: JUNCTION_CALENDAR_REFRESH_JOB_INVALID_CODE,
6093
+ message: "Junction calendar refresh job lacked its source provider identity.",
6094
+ retryable: false,
6095
+ });
6096
+ }
6097
+ const sourceInstanceId = normalizeString(job.payload.sourceInstanceId);
6098
+ const sourceType = normalizeString(job.payload.sourceType);
6099
+ return {
6100
+ ...(sourceInstanceId ? { sourceInstanceId } : {}),
6101
+ sourceProviderSlug,
6102
+ ...(sourceType ? { sourceType } : {}),
6103
+ };
6104
+ }
6105
+ function filterJunctionSparseCalendarRecordsToSource(records, source) {
6106
+ const sourceProviderSlug = normalizeProviderSlug(source.sourceProviderSlug);
6107
+ const sourceInstanceId = normalizeString(source.sourceInstanceId);
6108
+ const sourceType = normalizeString(source.sourceType);
6109
+ return records.flatMap((record) => {
6110
+ const entry = readPlainObject(record);
6111
+ if (!entry) {
6112
+ throw incompleteJunctionSparseCalendarCollectionError();
6113
+ }
6114
+ const origin = resolveJunctionOrigin(entry);
6115
+ const recordSourceProviderSlug = normalizeProviderSlug(origin.sourceProviderSlug);
6116
+ if (!recordSourceProviderSlug) {
6117
+ throw incompleteJunctionSparseCalendarCollectionError();
6118
+ }
6119
+ if (!areJunctionProviderSlugsRouteEquivalent(recordSourceProviderSlug, sourceProviderSlug)) {
6120
+ return [];
6121
+ }
6122
+ const recordSourceType = normalizeString(origin.sourceType);
6123
+ if (sourceType && !recordSourceType) {
6124
+ throw incompleteJunctionSparseCalendarCollectionError();
6125
+ }
6126
+ if (sourceType && recordSourceType !== sourceType) {
6127
+ return [];
6128
+ }
6129
+ const recordSourceInstanceId = normalizeString(origin.sourceInstanceId);
6130
+ if (sourceInstanceId && !recordSourceInstanceId) {
6131
+ throw incompleteJunctionSparseCalendarCollectionError();
6132
+ }
6133
+ if (sourceInstanceId && recordSourceInstanceId !== sourceInstanceId) {
6134
+ return [];
6135
+ }
6136
+ return [{
6137
+ ...entry,
6138
+ sourceProviderSlug,
6139
+ ...(sourceType ? { sourceType } : {}),
6140
+ ...(sourceInstanceId ? { sourceInstanceId } : {}),
6141
+ }];
6142
+ });
6143
+ }
6144
+ function incompleteJunctionSparseCalendarCollectionError() {
6145
+ return deviceSyncError({
6146
+ code: "JUNCTION_CALENDAR_REFRESH_INCOMPLETE_NORMALIZATION",
6147
+ message: "Junction calendar refresh response was not structurally complete.",
6148
+ retryable: true,
6149
+ httpStatus: 502,
6150
+ });
6151
+ }
6152
+ function buildJunctionEmptySparseCalendarAggregate(input) {
6153
+ return stripUndefined({
6154
+ authoritativeEmptyCalendarSet: true,
6155
+ calendarDate: input.dayKey,
6156
+ date: input.dayKey,
6157
+ sourceInstanceId: input.sourceInstanceId,
6158
+ sourceProviderSlug: input.sourceProviderSlug,
6159
+ sourceType: input.sourceType,
6160
+ value: 0,
6161
+ });
6162
+ }
6163
+ function isGloballyClosedJunctionProviderDay(dayKey, asOf) {
6164
+ if (!isCanonicalEventDayKey(dayKey)) {
6165
+ return false;
6166
+ }
6167
+ const windowEnd = addMilliseconds(`${dayKey}T00:00:00.000Z`, TIMESERIES_CHUNK_MS);
6168
+ return Date.parse(windowEnd) <= resolveGloballyClosedProviderDayEnd(windowEnd, asOf);
6169
+ }
6170
+ function buildJunctionExtendedTimeseriesBackfillDedupeKey(payload) {
6171
+ if (payload.historicalBackfill !== true) {
6172
+ return null;
6173
+ }
6174
+ const historicalWindowStart = toIsoTimestampIfValid(normalizeString(payload.historicalWindowStart));
6175
+ const resource = normalizeJunctionResourceName(payload.resource);
6176
+ const windowEnd = toIsoTimestampIfValid(normalizeString(payload.windowEnd));
6177
+ const policy = resource
6178
+ ? resolveJunctionExtendedTimeseriesBackfillPolicy(resource)
6179
+ : null;
6180
+ if (!historicalWindowStart
6181
+ || !resource
6182
+ || !windowEnd
6183
+ || !policy) {
6184
+ return null;
6185
+ }
6186
+ if (!["blood_pressure", "weight"].includes(resource)) {
6187
+ const coverageVersion = resource === "note"
6188
+ ? readJunctionNoteHistoryBackfillVersion(payload)
6189
+ : policy.version;
6190
+ return sha256Text(JSON.stringify([
6191
+ "junction",
6192
+ "extended-timeseries-backfill",
6193
+ normalizeProviderSlug(payload.sourceProviderSlug),
6194
+ resource,
6195
+ coverageVersion,
6196
+ ]));
6197
+ }
6198
+ return sha256Text(JSON.stringify([
6199
+ "junction",
6200
+ "extended-timeseries-backfill",
6201
+ normalizeProviderSlug(payload.sourceProviderSlug),
6202
+ resource,
6203
+ historicalWindowStart,
6204
+ windowEnd,
6205
+ ]));
6206
+ }
6207
+ function buildExtendedTimeseriesBackfillJob(input) {
6208
+ const payload = {
6209
+ ...(input.emptyBackfillAttempts && input.emptyBackfillAttempts > 0
6210
+ ? { emptyBackfillAttempts: input.emptyBackfillAttempts }
6211
+ : {}),
6212
+ historicalBackfill: true,
6213
+ ...(input.historicalBackfillVersion === undefined
6214
+ ? {}
6215
+ : { historicalBackfillVersion: input.historicalBackfillVersion }),
6216
+ ...(input.historicalProviderRecordsSeen
6217
+ ? { historicalProviderRecordsSeen: true }
6218
+ : {}),
6219
+ ...(input.historicalRecordsSeen
6220
+ ? { historicalRecordsSeen: true }
6221
+ : {}),
6222
+ ...(input.historicalUnresolvedProviderRecordIdentitiesJson
6223
+ ? {
6224
+ historicalUnresolvedProviderRecordIdentitiesJson: input.historicalUnresolvedProviderRecordIdentitiesJson,
6225
+ }
6226
+ : {}),
6227
+ ...(input.historicalUnresolvedProviderRecordCount
6228
+ && input.historicalUnresolvedProviderRecordCount > 0
6229
+ ? {
6230
+ historicalUnresolvedProviderRecordCount: input.historicalUnresolvedProviderRecordCount,
6231
+ }
6232
+ : {}),
6233
+ historicalWindowStart: input.historicalWindowStart,
6234
+ resource: input.resource,
6235
+ resourceCategory: "timeseries",
6236
+ ...(input.sourceProviderSlug
6237
+ ? { sourceProviderSlug: input.sourceProviderSlug }
6238
+ : {}),
6239
+ windowEnd: input.windowEnd,
6240
+ windowStart: input.windowStart,
6241
+ };
6242
+ const dedupeKey = input.dedupeKey
6243
+ ?? buildJunctionExtendedTimeseriesBackfillDedupeKey(payload);
6244
+ if (!dedupeKey) {
6245
+ throw new TypeError("Junction extended timeseries backfill identity was invalid.");
6246
+ }
6247
+ return {
6248
+ kind: "resource",
6249
+ payload,
6250
+ availableAt: input.availableAt,
6251
+ priority: JUNCTION_HISTORICAL_BACKFILL_PRIORITY,
6252
+ dedupeKey,
3447
6253
  };
3448
6254
  }
6255
+ function readJunctionNoteHistoryBackfillVersion(payload) {
6256
+ const version = payload.historicalBackfillVersion;
6257
+ return typeof version === "number" && Number.isSafeInteger(version) && version >= 1
6258
+ ? version
6259
+ : 1;
6260
+ }
3449
6261
  function buildJunctionWebhookJobs(input) {
3450
6262
  if (isJunctionProviderConnectionEvent(input.eventType)) {
3451
6263
  const backfillWindowStart = subtractDays(input.window.windowEnd, input.summaryBackfillDays);
@@ -3538,8 +6350,7 @@ function isJunctionHistoricalDataEvent(eventType) {
3538
6350
  return eventType.startsWith("historical.data.");
3539
6351
  }
3540
6352
  function isJunctionHistoricalPullCompletedWebhookData(data, externalAccountId) {
3541
- const completed = parseJunctionHistoricalPullCompletedWebhookData(data, externalAccountId);
3542
- if (completed && normalizeJunctionWebhookSourceProviderCandidate(completed.provider)) {
6353
+ if (isJunctionSdkHistoricalPullCompletedWebhookData(data, externalAccountId)) {
3543
6354
  return true;
3544
6355
  }
3545
6356
  if (hasJunctionHistoricalInlineRecordCarrierFields(data)) {
@@ -3547,14 +6358,19 @@ function isJunctionHistoricalPullCompletedWebhookData(data, externalAccountId) {
3547
6358
  }
3548
6359
  return isDocumentedJunctionHistoricalPullCompletedWebhookData(data, externalAccountId);
3549
6360
  }
3550
- function parseJunctionHistoricalPullCompletedWebhookData(data, externalAccountId) {
3551
- const parsed = JunctionHistoricalPullCompletedSchema.parse({
3552
- ...data,
3553
- [JUNCTION_WEBHOOK_ROOT_FIELDS.userId]: normalizeString(data[JUNCTION_WEBHOOK_ROOT_FIELDS.userId]) ?? externalAccountId,
3554
- }, {
3555
- unrecognizedObjectKeys: "passthrough",
3556
- });
3557
- return parsed.ok ? parsed.value : null;
6361
+ function isJunctionSdkHistoricalPullCompletedWebhookData(data, externalAccountId) {
6362
+ const userId = normalizeString(data[JUNCTION_WEBHOOK_ROOT_FIELDS.userId])
6363
+ ?? externalAccountId;
6364
+ const startDate = data.start_date;
6365
+ const endDate = data.end_date;
6366
+ return typeof userId === "string"
6367
+ && typeof startDate === "string"
6368
+ && JUNCTION_SDK_ISO_8601_DATE_PATTERN.test(startDate)
6369
+ && typeof endDate === "string"
6370
+ && JUNCTION_SDK_ISO_8601_DATE_PATTERN.test(endDate)
6371
+ && data.is_final === true
6372
+ && typeof data.provider === "string"
6373
+ && normalizeJunctionWebhookSourceProviderCandidate(data.provider) !== null;
3558
6374
  }
3559
6375
  const JUNCTION_HISTORICAL_INLINE_RECORD_CARRIER_FIELDS = new Set([
3560
6376
  "activities",
@@ -3975,6 +6791,7 @@ function verifyAndParseJunctionWebhookEnvelope(input) {
3975
6791
  return {
3976
6792
  messageId,
3977
6793
  payload,
6794
+ providerSentAt: new Date(timestampMs).toISOString(),
3978
6795
  };
3979
6796
  }
3980
6797
  function requireJunctionWebhookHeader(headers, name) {
@@ -4248,12 +7065,30 @@ async function projectJunctionSources(context, providers, options = {}) {
4248
7065
  const preserveHistoricalReconnectProviderSlugs = options.preserveHistoricalReconnectProviderSlugs === undefined
4249
7066
  ? null
4250
7067
  : new Set(options.preserveHistoricalReconnectProviderSlugs);
7068
+ const projectedSources = projectJunctionSourcesByProviderSlug(context.account.id, providers);
7069
+ if (projectedSources.length > JUNCTION_MAX_USER_PROVIDERS) {
7070
+ throw deviceSyncError({
7071
+ code: "JUNCTION_USER_PROVIDER_LIMIT",
7072
+ message: "Junction projected sources exceeded the supported provider bound.",
7073
+ retryable: true,
7074
+ httpStatus: 502,
7075
+ });
7076
+ }
4251
7077
  const existingSources = context.listConnectionSources
4252
- ? await context.listConnectionSources()
7078
+ ? [...await context.listConnectionSources()]
4253
7079
  : [];
4254
- const existingByInstanceKey = new Map(existingSources.map((source) => [source.sourceInstanceKey, source]));
4255
- for (const source of projectJunctionSourcesByProviderSlug(context.account.id, providers)) {
4256
- const existing = existingByInstanceKey.get(source.sourceInstanceKey) ?? existingSources.find((candidate) => normalizeProviderSlug(candidate.sourceProviderSlug) === source.sourceProviderSlug);
7080
+ const admissionSources = context.listConnectionSources
7081
+ ? existingSources
7082
+ : context.account.sources ?? [];
7083
+ for (const source of projectedSources) {
7084
+ const listedOnly = context.connectionSourceAdmissionMode === "listed_only";
7085
+ if ((listedOnly
7086
+ && !hasJunctionSourceListing(admissionSources, source.sourceProviderSlug))
7087
+ || isJunctionSourceProjectionFenced(admissionSources, source.sourceProviderSlug)) {
7088
+ continue;
7089
+ }
7090
+ const accountSourceIdentity = resolveJunctionAccountSourceIdentity(existingSources, source.sourceProviderSlug, true);
7091
+ const existing = findJunctionAccountSource(existingSources, source.sourceProviderSlug);
4257
7092
  const keepHistoricalReconnect = preserveHistoricalReconnect
4258
7093
  && (preserveHistoricalReconnectProviderSlugs === null
4259
7094
  || preserveHistoricalReconnectProviderSlugs.has(source.sourceProviderSlug))
@@ -4264,11 +7099,14 @@ async function projectJunctionSources(context, providers, options = {}) {
4264
7099
  && existing.lastErrorCode === DEVICE_SYNC_HISTORICAL_DATA_RECONNECT_REQUIRED_ERROR_CODE
4265
7100
  : requiresHistoricalResetDeviceSyncSource(existing));
4266
7101
  const historicalReconnectError = keepHistoricalReconnect ? existing : null;
4267
- await context.upsertConnectionSource({
4268
- sourceInstanceKey: existing?.sourceInstanceKey ?? source.sourceInstanceKey,
4269
- sourceProviderSlug: source.sourceProviderSlug,
7102
+ const persistedSource = await context.upsertConnectionSource({
7103
+ sourceInstanceKey: accountSourceIdentity?.sourceInstanceKey ?? source.sourceInstanceKey,
7104
+ sourceProviderSlug: accountSourceIdentity?.sourceProviderSlug ?? source.sourceProviderSlug,
4270
7105
  displayName: existing?.displayName ?? null,
4271
- status: keepHistoricalReconnect ? "error" : source.status,
7106
+ ...(existing?.firstSeenAt ? { firstSeenAt: existing.firstSeenAt } : {}),
7107
+ status: keepHistoricalReconnect
7108
+ ? "error"
7109
+ : source.status,
4272
7110
  resourceAvailabilitySummary: source.resourceAvailabilitySummary,
4273
7111
  // Only assert error fields when this projection saw an errored entry;
4274
7112
  // omitting the keys lets the store preserve existing detail while the
@@ -4283,7 +7121,118 @@ async function projectJunctionSources(context, providers, options = {}) {
4283
7121
  : {}),
4284
7122
  lastSeenAt: context.now,
4285
7123
  });
7124
+ const persistedIndex = existingSources.findIndex((candidate) => candidate.sourceInstanceKey === persistedSource.sourceInstanceKey);
7125
+ if (persistedIndex >= 0) {
7126
+ existingSources[persistedIndex] = persistedSource;
7127
+ }
7128
+ else {
7129
+ existingSources.push(persistedSource);
7130
+ }
7131
+ }
7132
+ }
7133
+ function isJunctionSourceAdmittedForImport(sources, sourceProviderSlug, allowUnlistedSources = true, sourceStatusRequirement = "not_disconnected") {
7134
+ const normalizedSourceProviderSlug = normalizeProviderSlug(sourceProviderSlug);
7135
+ if (!normalizedSourceProviderSlug) {
7136
+ return true;
7137
+ }
7138
+ const accountSourceIdentity = resolveJunctionAccountSourceIdentity(sources, normalizedSourceProviderSlug, allowUnlistedSources);
7139
+ if (!accountSourceIdentity) {
7140
+ return false;
7141
+ }
7142
+ const sourceState = resolveJunctionAccountSourceState(sources, accountSourceIdentity.sourceProviderSlug);
7143
+ if (!sourceState) {
7144
+ return allowUnlistedSources;
7145
+ }
7146
+ const lifecycleSource = sourceState.lifecycleSource;
7147
+ return sourceStatusRequirement === "connected"
7148
+ ? isDeviceSyncSourceAdmitted([lifecycleSource], lifecycleSource.sourceProviderSlug)
7149
+ : lifecycleSource.status !== "disconnected"
7150
+ && !isDeviceSyncSourceDisconnectFenced(lifecycleSource);
7151
+ }
7152
+ function isJunctionSourceProjectionFenced(sources, sourceProviderSlug) {
7153
+ const normalizedSourceProviderSlug = normalizeProviderSlug(sourceProviderSlug);
7154
+ if (!normalizedSourceProviderSlug) {
7155
+ return false;
7156
+ }
7157
+ const accountSourceIdentity = resolveJunctionAccountSourceIdentity(sources, normalizedSourceProviderSlug);
7158
+ if (!accountSourceIdentity) {
7159
+ return false;
7160
+ }
7161
+ const sourceState = resolveJunctionAccountSourceState(sources, accountSourceIdentity.sourceProviderSlug);
7162
+ return sourceState !== null
7163
+ && isDeviceSyncSourceDisconnectFenced(sourceState.lifecycleSource);
7164
+ }
7165
+ function hasJunctionSourceListing(sources, sourceProviderSlug) {
7166
+ const normalizedSourceProviderSlug = normalizeProviderSlug(sourceProviderSlug);
7167
+ if (!normalizedSourceProviderSlug) {
7168
+ return true;
7169
+ }
7170
+ return sources.some((source) => areJunctionProviderSlugsRouteEquivalent(source.sourceProviderSlug, normalizedSourceProviderSlug));
7171
+ }
7172
+ async function resolveJunctionCurrentSourceAdmission(context, sourceProviderSlug) {
7173
+ const sources = context.listConnectionSources
7174
+ ? await context.listConnectionSources()
7175
+ : context.account.sources ?? [];
7176
+ return resolveJunctionCurrentSourceAdmissionFromSources(sources, sourceProviderSlug, context.connectionSourceAdmissionMode !== "listed_only");
7177
+ }
7178
+ function resolveJunctionCurrentSourceAdmissionFromSources(sources, sourceProviderSlug, allowUnlistedSources) {
7179
+ if (isJunctionSourceProjectionFenced(sources, sourceProviderSlug)) {
7180
+ return "fenced";
7181
+ }
7182
+ return isJunctionSourceAdmittedForImport(sources, sourceProviderSlug, allowUnlistedSources, "connected")
7183
+ ? "admitted"
7184
+ : "pending";
7185
+ }
7186
+ async function isJunctionCompanionSourceCurrentlyAdmitted(context, sourceProviderSlug) {
7187
+ const normalizedSourceProviderSlug = normalizeProviderSlug(sourceProviderSlug);
7188
+ if (!context.listConnectionSources) {
7189
+ throw junctionCompanionSourceStateUnavailableError();
7190
+ }
7191
+ if (!normalizedSourceProviderSlug) {
7192
+ throw junctionCompanionSourceStateUnavailableError();
7193
+ }
7194
+ let sources;
7195
+ try {
7196
+ sources = await context.listConnectionSources({
7197
+ sourceProviderSlug: normalizedSourceProviderSlug,
7198
+ });
7199
+ }
7200
+ catch (error) {
7201
+ if (isDeviceSyncError(error) && error.retryable) {
7202
+ throw error;
7203
+ }
7204
+ throw junctionCompanionSourceStateUnavailableError(error);
7205
+ }
7206
+ if (isDeviceSyncSourceAdmitted(sources, normalizedSourceProviderSlug)) {
7207
+ return true;
7208
+ }
7209
+ if (sources.some((source) => source.lastErrorCode === DEVICE_SYNC_SOURCE_USER_DISCONNECTED_ERROR_CODE)) {
7210
+ return false;
4286
7211
  }
7212
+ throw deviceSyncError({
7213
+ code: "JUNCTION_COMPANION_SOURCE_NOT_READY",
7214
+ message: "Current companion source authorization is not ready. Retry shortly.",
7215
+ retryable: true,
7216
+ httpStatus: 503,
7217
+ });
7218
+ }
7219
+ function junctionSourceStateUnavailableError(cause) {
7220
+ return deviceSyncError({
7221
+ code: "JUNCTION_SOURCE_STATE_UNAVAILABLE",
7222
+ message: "Current Junction source state is unavailable. Retry shortly.",
7223
+ retryable: true,
7224
+ httpStatus: 503,
7225
+ ...(cause === undefined ? {} : { cause }),
7226
+ });
7227
+ }
7228
+ function junctionCompanionSourceStateUnavailableError(cause) {
7229
+ return deviceSyncError({
7230
+ code: "JUNCTION_COMPANION_SOURCE_STATE_UNAVAILABLE",
7231
+ message: "Current companion source authorization is unavailable. Retry shortly.",
7232
+ retryable: true,
7233
+ httpStatus: 503,
7234
+ ...(cause === undefined ? {} : { cause }),
7235
+ });
4287
7236
  }
4288
7237
  function projectJunctionSourcesByProviderSlug(connectionId, providers) {
4289
7238
  const projected = new Map();
@@ -4489,6 +7438,102 @@ function readPlainObject(value) {
4489
7438
  function readProviderSnapshotDurableDeliveryAccepted(value) {
4490
7439
  return readPlainObject(value)?.durableDeliveryAccepted === true;
4491
7440
  }
7441
+ function readProviderSnapshotCanonicalEventCount(value) {
7442
+ const canonicalEventCount = readPlainObject(value)?.canonicalEventCount;
7443
+ return typeof canonicalEventCount === "number"
7444
+ && Number.isSafeInteger(canonicalEventCount)
7445
+ && canonicalEventCount >= 0
7446
+ ? canonicalEventCount
7447
+ : 0;
7448
+ }
7449
+ function readProviderSnapshotCanonicalEventDayKeys(value) {
7450
+ const dayKeys = readPlainObject(value)?.canonicalEventDayKeys;
7451
+ if (!Array.isArray(dayKeys)) {
7452
+ return [];
7453
+ }
7454
+ return [...new Set(dayKeys.filter((dayKey) => isCanonicalEventDayKey(dayKey)))].sort();
7455
+ }
7456
+ function readProviderSnapshotCanonicalSparseCalendarTargets(value) {
7457
+ const rawTargets = readPlainObject(value)?.canonicalSparseCalendarTargets;
7458
+ if (!Array.isArray(rawTargets)) {
7459
+ return [];
7460
+ }
7461
+ return rawTargets.flatMap((rawTarget) => {
7462
+ const target = readPlainObject(rawTarget);
7463
+ if (!target) {
7464
+ return [];
7465
+ }
7466
+ const sourceProviderSlug = normalizeProviderSlug(target.sourceProviderSlug);
7467
+ if (!isCanonicalEventDayKey(target.dayKey) || !sourceProviderSlug) {
7468
+ return [];
7469
+ }
7470
+ const sourceType = normalizeString(target.sourceType);
7471
+ return [{
7472
+ dayKey: target.dayKey,
7473
+ ...(typeof target.sourceInstanceId === "string" || target.sourceInstanceId === null
7474
+ ? { sourceInstanceId: target.sourceInstanceId }
7475
+ : {}),
7476
+ sourceProviderSlug,
7477
+ ...(sourceType ? { sourceType } : {}),
7478
+ }];
7479
+ });
7480
+ }
7481
+ function isCanonicalEventDayKey(value) {
7482
+ if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}$/u.test(value)) {
7483
+ return false;
7484
+ }
7485
+ const parsed = new Date(`${value}T00:00:00.000Z`);
7486
+ return Number.isFinite(parsed.getTime()) && parsed.toISOString().slice(0, 10) === value;
7487
+ }
7488
+ function readProviderSnapshotCanonicalEventExternalRefResourceIds(value) {
7489
+ const record = readPlainObject(value);
7490
+ if (!record || !("canonicalEventExternalRefResourceIds" in record)) {
7491
+ return null;
7492
+ }
7493
+ const resourceIds = record.canonicalEventExternalRefResourceIds;
7494
+ return Array.isArray(resourceIds)
7495
+ && resourceIds.every((resourceId) => typeof resourceId === "string")
7496
+ ? resourceIds
7497
+ : null;
7498
+ }
7499
+ function uniqueJunctionProviderRecordIdentities(identities) {
7500
+ return [...new Set(identities.filter((identity) => identity !== null && JUNCTION_BLOOD_PRESSURE_PROVIDER_RECORD_IDENTITY_PATTERN.test(identity)))].sort();
7501
+ }
7502
+ function resolveJunctionBloodPressureProviderRecordResolutionEvidence(input) {
7503
+ const rawIdentities = input.providerRecordIdentityEvidence.repairStableExternalRefResourceIds;
7504
+ const stableIdentities = uniqueJunctionProviderRecordIdentities(rawIdentities);
7505
+ const identityEvidenceIncomplete = input.providerRecordIdentityEvidence.providerRecordCount !== input.providerRecordCount
7506
+ || rawIdentities.some((identity) => identity !== null
7507
+ && !JUNCTION_BLOOD_PRESSURE_PROVIDER_RECORD_IDENTITY_PATTERN.test(identity));
7508
+ // Older unit seams may only expose the aggregate count. They can prove an
7509
+ // all-canonical current scan, but never clear an exact carried obligation.
7510
+ if (input.canonicalEventExternalRefResourceIds === null) {
7511
+ const allCurrentRecordsCanonical = !identityEvidenceIncomplete
7512
+ && input.canonicalEventCount >= input.providerRecordCount;
7513
+ return {
7514
+ canonicalProviderRecordIdentities: [],
7515
+ unresolvedProviderRecordIdentities: allCurrentRecordsCanonical
7516
+ ? []
7517
+ : stableIdentities,
7518
+ unresolvedProviderRecordsWithoutStableIdentity: !allCurrentRecordsCanonical
7519
+ && (identityEvidenceIncomplete
7520
+ || rawIdentities.some((identity) => identity === null)),
7521
+ };
7522
+ }
7523
+ const canonicalResourceIds = new Set(input.canonicalEventExternalRefResourceIds.filter((resourceId) => JUNCTION_BLOOD_PRESSURE_PROVIDER_RECORD_IDENTITY_PATTERN.test(resourceId)));
7524
+ const stableIdentitySet = new Set(stableIdentities);
7525
+ const canonicalProviderRecordIdentities = stableIdentities.filter((identity) => canonicalResourceIds.has(identity));
7526
+ const unresolvedProviderRecordIdentities = stableIdentities.filter((identity) => !canonicalResourceIds.has(identity));
7527
+ const providerRecordsWithoutStableIdentity = rawIdentities.filter((identity) => identity === null).length;
7528
+ const canonicalRecordsWithoutStableIdentity = input.canonicalEventExternalRefResourceIds.filter((resourceId) => !stableIdentitySet.has(resourceId)).length;
7529
+ return {
7530
+ canonicalProviderRecordIdentities,
7531
+ unresolvedProviderRecordIdentities,
7532
+ unresolvedProviderRecordsWithoutStableIdentity: identityEvidenceIncomplete
7533
+ || input.canonicalEventExternalRefResourceIds.length !== input.canonicalEventCount
7534
+ || canonicalRecordsWithoutStableIdentity < providerRecordsWithoutStableIdentity,
7535
+ };
7536
+ }
4492
7537
  function base32UrlEncode(input) {
4493
7538
  const alphabet = "abcdefghijklmnopqrstuvwxyz234567";
4494
7539
  let bits = 0;