@plurnk/plurnk-service 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (381) hide show
  1. package/.env.defaults +49 -42
  2. package/INSTALL.md +48 -11
  3. package/README.md +12 -2
  4. package/SPEC.md +1166 -475
  5. package/digest-sql/channel-dispositions/dispositions.sql +15 -0
  6. package/digest-sql/channel-state/state.sql +6 -0
  7. package/digest-sql/curation/curation.sql +5 -0
  8. package/digest-sql/derivations/derivations.sql +4 -0
  9. package/digest-sql/embeddings/embeddings.sql +4 -0
  10. package/digest-sql/entry-dispositions/dispositions.sql +15 -0
  11. package/digest-sql/entry-state/state.sql +6 -0
  12. package/digest-sql/token-counts/token-counts.sql +2 -0
  13. package/dist/Paths.d.ts +0 -4
  14. package/dist/Paths.d.ts.map +1 -1
  15. package/dist/Paths.js +1 -21
  16. package/dist/Paths.js.map +1 -1
  17. package/dist/build-info.json +1 -1
  18. package/dist/content/read-projector.d.ts.map +1 -1
  19. package/dist/content/read-projector.js +4 -3
  20. package/dist/content/read-projector.js.map +1 -1
  21. package/dist/core/BudgetReadout.d.ts.map +1 -1
  22. package/dist/core/BudgetReadout.js +12 -22
  23. package/dist/core/BudgetReadout.js.map +1 -1
  24. package/dist/core/ChannelWrite.d.ts +8 -3
  25. package/dist/core/ChannelWrite.d.ts.map +1 -1
  26. package/dist/core/ChannelWrite.js +40 -8
  27. package/dist/core/ChannelWrite.js.map +1 -1
  28. package/dist/core/ChannelWrite.sql +19 -5
  29. package/dist/core/CoreSchemeServices.d.ts +7 -3
  30. package/dist/core/CoreSchemeServices.d.ts.map +1 -1
  31. package/dist/core/CoreSchemeServices.js +8 -1
  32. package/dist/core/CoreSchemeServices.js.map +1 -1
  33. package/dist/core/Dispatcher.d.ts +15 -6
  34. package/dist/core/Dispatcher.d.ts.map +1 -1
  35. package/dist/core/Dispatcher.js +352 -306
  36. package/dist/core/Dispatcher.js.map +1 -1
  37. package/dist/core/Engine.d.ts +22 -10
  38. package/dist/core/Engine.d.ts.map +1 -1
  39. package/dist/core/Engine.js +86 -46
  40. package/dist/core/Engine.js.map +1 -1
  41. package/dist/core/Engine.sql +202 -177
  42. package/dist/core/EntryAddressBinding.d.ts +32 -0
  43. package/dist/core/EntryAddressBinding.d.ts.map +1 -0
  44. package/dist/core/EntryAddressBinding.js +93 -0
  45. package/dist/core/EntryAddressBinding.js.map +1 -0
  46. package/dist/core/ExecutorRegistry.d.ts +12 -6
  47. package/dist/core/ExecutorRegistry.d.ts.map +1 -1
  48. package/dist/core/ExecutorRegistry.js +34 -31
  49. package/dist/core/ExecutorRegistry.js.map +1 -1
  50. package/dist/core/HostPaths.d.ts +29 -0
  51. package/dist/core/HostPaths.d.ts.map +1 -0
  52. package/dist/core/HostPaths.js +74 -0
  53. package/dist/core/HostPaths.js.map +1 -0
  54. package/dist/core/LegacyHome.d.ts +10 -0
  55. package/dist/core/LegacyHome.d.ts.map +1 -0
  56. package/dist/core/LegacyHome.js +170 -0
  57. package/dist/core/LegacyHome.js.map +1 -0
  58. package/dist/core/LogBody.d.ts +1 -1
  59. package/dist/core/LogBody.d.ts.map +1 -1
  60. package/dist/core/LogBody.js +21 -3
  61. package/dist/core/LogBody.js.map +1 -1
  62. package/dist/core/LogEntryProjection.js +1 -1
  63. package/dist/core/LogEntryProjection.js.map +1 -1
  64. package/dist/core/LogVisibility.d.ts +28 -0
  65. package/dist/core/LogVisibility.d.ts.map +1 -0
  66. package/dist/core/LogVisibility.js +215 -0
  67. package/dist/core/LogVisibility.js.map +1 -0
  68. package/dist/core/LoopLifecycle.d.ts +1 -0
  69. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  70. package/dist/core/LoopLifecycle.js +8 -0
  71. package/dist/core/LoopLifecycle.js.map +1 -1
  72. package/dist/core/LoopLifecycle.sql +10 -0
  73. package/dist/core/OperatorConfig.d.ts +6 -0
  74. package/dist/core/OperatorConfig.d.ts.map +1 -0
  75. package/dist/core/OperatorConfig.js +95 -0
  76. package/dist/core/OperatorConfig.js.map +1 -0
  77. package/dist/core/OverflowTurn.d.ts +11 -0
  78. package/dist/core/OverflowTurn.d.ts.map +1 -0
  79. package/dist/core/OverflowTurn.js +81 -0
  80. package/dist/core/OverflowTurn.js.map +1 -0
  81. package/dist/core/Owner.js +3 -3
  82. package/dist/core/Owner.js.map +1 -1
  83. package/dist/core/PacketBuilder.d.ts +7 -15
  84. package/dist/core/PacketBuilder.d.ts.map +1 -1
  85. package/dist/core/PacketBuilder.js +64 -127
  86. package/dist/core/PacketBuilder.js.map +1 -1
  87. package/dist/core/ProblemLog.js +1 -1
  88. package/dist/core/ProblemLog.js.map +1 -1
  89. package/dist/core/ProposalLifecycle.d.ts +4 -1
  90. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  91. package/dist/core/ProposalLifecycle.js +86 -47
  92. package/dist/core/ProposalLifecycle.js.map +1 -1
  93. package/dist/core/ProviderInstantiate.d.ts +9 -5
  94. package/dist/core/ProviderInstantiate.d.ts.map +1 -1
  95. package/dist/core/ProviderInstantiate.js +99 -104
  96. package/dist/core/ProviderInstantiate.js.map +1 -1
  97. package/dist/core/ReasoningEvent.d.ts +13 -0
  98. package/dist/core/ReasoningEvent.d.ts.map +1 -0
  99. package/dist/core/ReasoningEvent.js +6 -0
  100. package/dist/core/ReasoningEvent.js.map +1 -0
  101. package/dist/core/ResourceMutations.d.ts +15 -19
  102. package/dist/core/ResourceMutations.d.ts.map +1 -1
  103. package/dist/core/ResourceMutations.js +118 -41
  104. package/dist/core/ResourceMutations.js.map +1 -1
  105. package/dist/core/SchemeRegistry.d.ts +12 -12
  106. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  107. package/dist/core/SchemeRegistry.js +58 -57
  108. package/dist/core/SchemeRegistry.js.map +1 -1
  109. package/dist/core/ToolResources.d.ts +19 -0
  110. package/dist/core/ToolResources.d.ts.map +1 -0
  111. package/dist/core/ToolResources.js +123 -0
  112. package/dist/core/ToolResources.js.map +1 -0
  113. package/dist/core/Turn.d.ts +27 -0
  114. package/dist/core/Turn.d.ts.map +1 -0
  115. package/dist/core/Turn.js +43 -0
  116. package/dist/core/Turn.js.map +1 -0
  117. package/dist/core/Turn.sql +72 -0
  118. package/dist/core/TurnOps.d.ts +7 -0
  119. package/dist/core/TurnOps.d.ts.map +1 -0
  120. package/dist/core/TurnOps.js +73 -0
  121. package/dist/core/TurnOps.js.map +1 -0
  122. package/dist/core/TurnRunner.d.ts +56 -5
  123. package/dist/core/TurnRunner.d.ts.map +1 -1
  124. package/dist/core/TurnRunner.js +1163 -929
  125. package/dist/core/TurnRunner.js.map +1 -1
  126. package/dist/core/WorkerName.d.ts +2 -1
  127. package/dist/core/WorkerName.d.ts.map +1 -1
  128. package/dist/core/WorkerName.js +2 -1
  129. package/dist/core/WorkerName.js.map +1 -1
  130. package/dist/core/WorkerName.sql +17 -2
  131. package/dist/core/WorkspaceGate.js +1 -1
  132. package/dist/core/WorkspaceGate.js.map +1 -1
  133. package/dist/core/caps/CapsResolve.d.ts +2 -2
  134. package/dist/core/caps/CapsResolve.d.ts.map +1 -1
  135. package/dist/core/caps/CapsResolve.js +5 -7
  136. package/dist/core/caps/CapsResolve.js.map +1 -1
  137. package/dist/core/caps/DbChannelCaps.d.ts +1 -1
  138. package/dist/core/caps/DbChannelCaps.d.ts.map +1 -1
  139. package/dist/core/caps/DbChannelCaps.js +13 -11
  140. package/dist/core/caps/DbChannelCaps.js.map +1 -1
  141. package/dist/core/caps/DbEntryCaps.d.ts +5 -5
  142. package/dist/core/caps/DbEntryCaps.d.ts.map +1 -1
  143. package/dist/core/caps/DbEntryCaps.js +27 -30
  144. package/dist/core/caps/DbEntryCaps.js.map +1 -1
  145. package/dist/core/caps/DbNotifyCaps.d.ts +1 -1
  146. package/dist/core/caps/DbNotifyCaps.d.ts.map +1 -1
  147. package/dist/core/caps/DbNotifyCaps.js +5 -3
  148. package/dist/core/caps/DbNotifyCaps.js.map +1 -1
  149. package/dist/core/caps/DbSubscriptionCaps.d.ts +3 -3
  150. package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -1
  151. package/dist/core/caps/DbSubscriptionCaps.js +16 -26
  152. package/dist/core/caps/DbSubscriptionCaps.js.map +1 -1
  153. package/dist/core/caps/SchemeCtxImpl.d.ts +6 -4
  154. package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
  155. package/dist/core/caps/SchemeCtxImpl.js +37 -5
  156. package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
  157. package/dist/core/env-defaults.d.ts.map +1 -1
  158. package/dist/core/env-defaults.js +7 -5
  159. package/dist/core/env-defaults.js.map +1 -1
  160. package/dist/core/file-creation-policy.d.ts +9 -0
  161. package/dist/core/file-creation-policy.d.ts.map +1 -0
  162. package/dist/core/file-creation-policy.js +25 -0
  163. package/dist/core/file-creation-policy.js.map +1 -0
  164. package/dist/core/fork.d.ts +4 -1
  165. package/dist/core/fork.d.ts.map +1 -1
  166. package/dist/core/fork.js +39 -16
  167. package/dist/core/fork.js.map +1 -1
  168. package/dist/core/fork.sql +83 -40
  169. package/dist/core/git-env.d.ts +0 -1
  170. package/dist/core/git-env.d.ts.map +1 -1
  171. package/dist/core/git-env.js +0 -3
  172. package/dist/core/git-env.js.map +1 -1
  173. package/dist/core/git-membership.d.ts +19 -1
  174. package/dist/core/git-membership.d.ts.map +1 -1
  175. package/dist/core/git-membership.js +233 -74
  176. package/dist/core/git-membership.js.map +1 -1
  177. package/dist/core/git-state.d.ts.map +1 -1
  178. package/dist/core/git-state.js +13 -14
  179. package/dist/core/git-state.js.map +1 -1
  180. package/dist/core/operation-target-groups.d.ts +3 -0
  181. package/dist/core/operation-target-groups.d.ts.map +1 -0
  182. package/dist/core/operation-target-groups.js +53 -0
  183. package/dist/core/operation-target-groups.js.map +1 -0
  184. package/dist/core/packet-inject.d.ts +0 -1
  185. package/dist/core/packet-inject.d.ts.map +1 -1
  186. package/dist/core/packet-inject.js +6 -13
  187. package/dist/core/packet-inject.js.map +1 -1
  188. package/dist/core/packet-wire.d.ts +4 -0
  189. package/dist/core/packet-wire.d.ts.map +1 -1
  190. package/dist/core/packet-wire.js +226 -53
  191. package/dist/core/packet-wire.js.map +1 -1
  192. package/dist/core/plurnk-uri.d.ts +14 -3
  193. package/dist/core/plurnk-uri.d.ts.map +1 -1
  194. package/dist/core/plurnk-uri.js +62 -24
  195. package/dist/core/plurnk-uri.js.map +1 -1
  196. package/dist/core/scheme-types.d.ts +1 -0
  197. package/dist/core/scheme-types.d.ts.map +1 -1
  198. package/dist/core/teaching.d.ts.map +1 -1
  199. package/dist/core/teaching.js +4 -5
  200. package/dist/core/teaching.js.map +1 -1
  201. package/dist/core/worker-ops.sql +10 -6
  202. package/dist/core/worker-settings.d.ts +10 -0
  203. package/dist/core/worker-settings.d.ts.map +1 -0
  204. package/dist/core/worker-settings.js +32 -0
  205. package/dist/core/worker-settings.js.map +1 -0
  206. package/dist/core/workspace-settings.d.ts +2 -11
  207. package/dist/core/workspace-settings.d.ts.map +1 -1
  208. package/dist/core/workspace-settings.js +7 -47
  209. package/dist/core/workspace-settings.js.map +1 -1
  210. package/dist/digest/Digest.d.ts.map +1 -1
  211. package/dist/digest/Digest.js +164 -92
  212. package/dist/digest/Digest.js.map +1 -1
  213. package/dist/digest/digest.sql +9 -3
  214. package/dist/observe/genai.d.ts +9 -0
  215. package/dist/observe/genai.d.ts.map +1 -0
  216. package/dist/observe/genai.js +31 -0
  217. package/dist/observe/genai.js.map +1 -0
  218. package/dist/observe/spans.d.ts +3 -3
  219. package/dist/observe/spans.d.ts.map +1 -1
  220. package/dist/observe/spans.js +20 -5
  221. package/dist/observe/spans.js.map +1 -1
  222. package/dist/schemes/EffectPolicy.d.ts +3 -0
  223. package/dist/schemes/EffectPolicy.d.ts.map +1 -1
  224. package/dist/schemes/EffectPolicy.js +38 -6
  225. package/dist/schemes/EffectPolicy.js.map +1 -1
  226. package/dist/schemes/Exec.d.ts +3 -2
  227. package/dist/schemes/Exec.d.ts.map +1 -1
  228. package/dist/schemes/Exec.js +109 -34
  229. package/dist/schemes/Exec.js.map +1 -1
  230. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  231. package/dist/schemes/ExecOutputScheme.js +5 -4
  232. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  233. package/dist/schemes/File.d.ts.map +1 -1
  234. package/dist/schemes/File.js +170 -80
  235. package/dist/schemes/File.js.map +1 -1
  236. package/dist/schemes/Log.d.ts +6 -2
  237. package/dist/schemes/Log.d.ts.map +1 -1
  238. package/dist/schemes/Log.js +73 -22
  239. package/dist/schemes/Log.js.map +1 -1
  240. package/dist/schemes/Log.sql +25 -7
  241. package/dist/schemes/Prompt.d.ts +2 -3
  242. package/dist/schemes/Prompt.d.ts.map +1 -1
  243. package/dist/schemes/Prompt.js +5 -9
  244. package/dist/schemes/Prompt.js.map +1 -1
  245. package/dist/schemes/QuestionTool.d.ts +10 -0
  246. package/dist/schemes/QuestionTool.d.ts.map +1 -0
  247. package/dist/schemes/QuestionTool.js +81 -0
  248. package/dist/schemes/QuestionTool.js.map +1 -0
  249. package/dist/schemes/Skill.d.ts.map +1 -1
  250. package/dist/schemes/Skill.js +6 -1
  251. package/dist/schemes/Skill.js.map +1 -1
  252. package/dist/schemes/Worker.d.ts.map +1 -1
  253. package/dist/schemes/Worker.js +97 -34
  254. package/dist/schemes/Worker.js.map +1 -1
  255. package/dist/schemes/_entry-crud.d.ts +5 -5
  256. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  257. package/dist/schemes/_entry-crud.js +22 -17
  258. package/dist/schemes/_entry-crud.js.map +1 -1
  259. package/dist/schemes/_entry-crud.sql +77 -24
  260. package/dist/schemes/_entry-find.d.ts +8 -5
  261. package/dist/schemes/_entry-find.d.ts.map +1 -1
  262. package/dist/schemes/_entry-find.js +121 -40
  263. package/dist/schemes/_entry-find.js.map +1 -1
  264. package/dist/schemes/_entry-find.sql +16 -11
  265. package/dist/schemes/_entry-graph.sql +2 -6
  266. package/dist/schemes/_entry-manifest.d.ts +2 -2
  267. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  268. package/dist/schemes/_entry-manifest.js +18 -6
  269. package/dist/schemes/_entry-manifest.js.map +1 -1
  270. package/dist/schemes/_entry-ops.d.ts +6 -5
  271. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  272. package/dist/schemes/_entry-ops.js +39 -46
  273. package/dist/schemes/_entry-ops.js.map +1 -1
  274. package/dist/schemes/_entry-ops.sql +9 -6
  275. package/dist/schemes/_entry-send.d.ts +2 -2
  276. package/dist/schemes/_entry-send.d.ts.map +1 -1
  277. package/dist/schemes/_entry-send.js +16 -14
  278. package/dist/schemes/_entry-send.js.map +1 -1
  279. package/dist/schemes/_search-index.d.ts.map +1 -1
  280. package/dist/schemes/_search-index.js +39 -25
  281. package/dist/schemes/_search-index.js.map +1 -1
  282. package/dist/server/Daemon.d.ts +98 -15
  283. package/dist/server/Daemon.d.ts.map +1 -1
  284. package/dist/server/Daemon.js +864 -348
  285. package/dist/server/Daemon.js.map +1 -1
  286. package/dist/server/DaemonModule.d.ts +84 -19
  287. package/dist/server/DaemonModule.d.ts.map +1 -1
  288. package/dist/server/DrainSupervisor.d.ts +15 -10
  289. package/dist/server/DrainSupervisor.d.ts.map +1 -1
  290. package/dist/server/DrainSupervisor.js +70 -19
  291. package/dist/server/DrainSupervisor.js.map +1 -1
  292. package/dist/server/Functionality.d.ts +44 -0
  293. package/dist/server/Functionality.d.ts.map +1 -0
  294. package/dist/server/Functionality.js +422 -0
  295. package/dist/server/Functionality.js.map +1 -0
  296. package/dist/server/FunctionalityManager.d.ts +22 -0
  297. package/dist/server/FunctionalityManager.d.ts.map +1 -0
  298. package/dist/server/FunctionalityManager.js +121 -0
  299. package/dist/server/FunctionalityManager.js.map +1 -0
  300. package/dist/server/SkillsFunctionality.d.ts +61 -0
  301. package/dist/server/SkillsFunctionality.d.ts.map +1 -0
  302. package/dist/server/SkillsFunctionality.js +449 -0
  303. package/dist/server/SkillsFunctionality.js.map +1 -0
  304. package/dist/server/WorkerCapabilities.d.ts +21 -0
  305. package/dist/server/WorkerCapabilities.d.ts.map +1 -0
  306. package/dist/server/WorkerCapabilities.js +214 -0
  307. package/dist/server/WorkerCapabilities.js.map +1 -0
  308. package/dist/server/WorkerResidency.d.ts +40 -0
  309. package/dist/server/WorkerResidency.d.ts.map +1 -0
  310. package/dist/server/WorkerResidency.js +283 -0
  311. package/dist/server/WorkerResidency.js.map +1 -0
  312. package/dist/server/client-input.d.ts +6 -2
  313. package/dist/server/client-input.d.ts.map +1 -1
  314. package/dist/server/client-input.js +72 -32
  315. package/dist/server/client-input.js.map +1 -1
  316. package/dist/server/dispatch-as-plurnk.d.ts +2 -2
  317. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
  318. package/dist/server/dispatch-as-plurnk.js +109 -23
  319. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  320. package/dist/server/drain.sql +33 -13
  321. package/dist/server/envelope.d.ts +7 -2
  322. package/dist/server/envelope.d.ts.map +1 -1
  323. package/dist/server/envelope.js +12 -6
  324. package/dist/server/envelope.js.map +1 -1
  325. package/dist/server/envelope.sql +36 -4
  326. package/dist/server/lifecycle-recovery.sql +24 -17
  327. package/dist/server/logEntry.d.ts +2 -1
  328. package/dist/server/logEntry.d.ts.map +1 -1
  329. package/dist/server/logEntry.js +3 -2
  330. package/dist/server/logEntry.js.map +1 -1
  331. package/dist/server/logEntry.sql +7 -0
  332. package/dist/server/loop-model.d.ts +2 -2
  333. package/dist/server/loop-model.d.ts.map +1 -1
  334. package/dist/server/loop-model.js +23 -33
  335. package/dist/server/loop-model.js.map +1 -1
  336. package/dist/server/loopDocs.d.ts +2 -1
  337. package/dist/server/loopDocs.d.ts.map +1 -1
  338. package/dist/server/loopDocs.js +88 -21
  339. package/dist/server/loopDocs.js.map +1 -1
  340. package/dist/server/loopDocs.sql +14 -8
  341. package/dist/server/model-catalog.d.ts +3 -0
  342. package/dist/server/model-catalog.d.ts.map +1 -0
  343. package/dist/server/model-catalog.js +83 -0
  344. package/dist/server/model-catalog.js.map +1 -0
  345. package/dist/server/model-route.d.ts +7 -0
  346. package/dist/server/model-route.d.ts.map +1 -0
  347. package/dist/server/model-route.js +47 -0
  348. package/dist/server/model-route.js.map +1 -0
  349. package/dist/server/module-discovery.d.ts +13 -0
  350. package/dist/server/module-discovery.d.ts.map +1 -0
  351. package/dist/server/module-discovery.js +103 -0
  352. package/dist/server/module-discovery.js.map +1 -0
  353. package/dist/server/seam-entry-read.sql +9 -7
  354. package/dist/server/seam-log-read.sql +1 -1
  355. package/dist/server/seam-loop.sql +10 -1
  356. package/dist/server/seam-proposal-list.sql +4 -2
  357. package/dist/server/worker-capabilities.sql +19 -0
  358. package/dist/service.d.ts.map +1 -1
  359. package/dist/service.js +193 -124
  360. package/dist/service.js.map +1 -1
  361. package/migrations/001_schema.sql +905 -196
  362. package/package.json +40 -38
  363. package/dist/core/ExecutableTools.d.ts +0 -11
  364. package/dist/core/ExecutableTools.d.ts.map +0 -1
  365. package/dist/core/ExecutableTools.js +0 -49
  366. package/dist/core/ExecutableTools.js.map +0 -1
  367. package/dist/core/JournalTurn.d.ts +0 -9
  368. package/dist/core/JournalTurn.d.ts.map +0 -1
  369. package/dist/core/JournalTurn.js +0 -14
  370. package/dist/core/JournalTurn.js.map +0 -1
  371. package/dist/core/JournalTurn.sql +0 -10
  372. package/dist/core/git-iso.d.ts +0 -13
  373. package/dist/core/git-iso.d.ts.map +0 -1
  374. package/dist/core/git-iso.js +0 -267
  375. package/dist/core/git-iso.js.map +0 -1
  376. package/dist/core/search-gate.d.ts +0 -17
  377. package/dist/core/search-gate.d.ts.map +0 -1
  378. package/dist/core/search-gate.js +0 -77
  379. package/dist/core/search-gate.js.map +0 -1
  380. package/dist/digest/Digest.sql +0 -1
  381. package/dist/server/workspace-capabilities.sql +0 -19
@@ -6,17 +6,16 @@
6
6
  //
7
7
  // test/digest/digest.md Health triage rollup (clean/degenerate-win/failed loops) +
8
8
  // worker-shape header + waterfall (per-loop health verdict; per-turn:
9
- // status, ⚠ errs=N, model emission summary, indented op list)
9
+ // status, ⚠ errs=N, source-artifact summary, indented op list)
10
10
  // test/digest/digest.json Same data, machine-queryable
11
11
  // test/digest/reasoning.md Every provider attempt's reasoning and admission result
12
12
  // test/digest/requiem.md Out-of-band model audit
13
13
  // test/digest/requiem.json Exact audit messages, responses, usage, and cost
14
- // test/digest/packetNNN.packet.md Journal-only turn note when no model request exists.
15
- // test/digest/packetNNN.system.md BYTE-FOR-BYTE the system message the LLM
16
- // received on TURN N (0-based).
14
+ // test/digest/packetNNN.system.md BYTE-FOR-BYTE the system message sent
15
+ // when the turn involved a provider.
17
16
  // test/digest/packetNNN.user.md Same for the user message.
18
17
  // test/digest/packetNNN.response.md Request-only note when no response was admitted.
19
- // test/digest/packetNNN.assistant.md Model emission (content string).
18
+ // test/digest/packetNNN.assistant.md Exact persisted turnOps, regardless of producer.
20
19
  // test/digest/packetNNN.assistantRaw.json Opaque provider response.
21
20
  // test/digest/packetNNN.attemptNNN.rejected.assistant.md
22
21
  // Rejected provider emission.
@@ -25,17 +24,15 @@
25
24
  // test/digest/packetNNN.attemptNNN.rejected.parse-errors.json
26
25
  // Admission errors for that attempt.
27
26
  //
28
- // packet files are byte-identical to what Engine emits, because Engine and
29
- // digest both project through PacketWire (one renderer, no drift).
27
+ // Provider request slots are byte-identical to what Engine emits because both
28
+ // paths project through PacketWire. Assistant files preserve durable turnOps.
30
29
  //
31
30
  // SQL lives in the co-located digest.sql; opened the sqlrite way (SqlRiteSync,
32
31
  // the sync CLI/script facade). Each PREP block is read through its own accessor.
33
- import { DatabaseSync } from "node:sqlite";
34
32
  import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
35
33
  import { dirname, join, resolve } from "node:path";
36
34
  import { randomUUID } from "node:crypto";
37
35
  import { fileURLToPath } from "node:url";
38
- import { homedir } from "node:os";
39
36
  import { isDeepStrictEqual } from "node:util";
40
37
  import SqlRiteSync from "@possumtech/sqlrite/sync";
41
38
  import { observedSync } from "../observe/spans.js";
@@ -43,7 +40,9 @@ import PacketWire from "../core/packet-wire.js";
43
40
  import LogBody from "../core/LogBody.js";
44
41
  import StoredPacket from "../core/StoredPacket.js";
45
42
  import { renderTarget } from "../core/plurnk-uri.js";
43
+ import EntryManifest from "../schemes/_entry-manifest.js";
46
44
  import ProviderInstantiate from "../core/ProviderInstantiate.js";
45
+ import HostPaths from "../core/HostPaths.js";
47
46
  import { aggregateProviderAccounting, ProviderError, validateProviderRequestAccounting, } from "@plurnk/plurnk-providers";
48
47
  import { providerRequestFromStorageRow, } from "../core/provider-accounting.js";
49
48
  import { Validator, } from "@plurnk/plurnk-contracts";
@@ -122,7 +121,7 @@ export default class Digest {
122
121
  return providerRequestFromStorageRow(row);
123
122
  }
124
123
  static #accounting(rows) {
125
- return rows.some((row) => row.state !== "settled")
124
+ return rows.length === 0 || rows.some((row) => row.state !== "settled")
126
125
  ? null
127
126
  : aggregateProviderAccounting(rows.map((row) => Digest.#requestAccounting(row)));
128
127
  }
@@ -166,7 +165,7 @@ export default class Digest {
166
165
  const stream = Digest.#parseJson(le.attrs, {}).stream;
167
166
  return typeof stream === "string" ? stream : null;
168
167
  }
169
- static #renderOpLine(le, label = le.op ?? "model emission") {
168
+ static #renderOpLine(le, label = le.op ?? "source artifact") {
170
169
  const target = Digest.#renderTarget(le) ?? "—";
171
170
  const stream = Digest.#renderStream(le);
172
171
  const state = le.state !== "resolved" ? ` state=${le.state}` : "";
@@ -184,12 +183,12 @@ export default class Digest {
184
183
  }
185
184
  static #renderGroupedOpLine(row) {
186
185
  const attrs = Digest.#parseJson(row.attrs, {});
187
- const materialized = row.origin === "plurnk" && row.op === "EDIT" && attrs.kind === "entry_materialized";
186
+ const materialized = row.origin === "_plurnk" && row.op === "EDIT" && attrs.kind === "entry_materialized";
188
187
  const actionlessKind = row.op === null
189
188
  ? LogBody.actionlessKind({ op: row.op, attrs })
190
189
  : null;
191
- const label = actionlessKind === "model_emission"
192
- ? "model emission"
190
+ const label = actionlessKind === "emissionAttempt"
191
+ ? "emission attempt"
193
192
  : actionlessKind ?? row.op ?? "actionless row";
194
193
  return Digest.#renderOpLine(row, materialized ? "materialized entry" : label);
195
194
  }
@@ -267,9 +266,12 @@ export default class Digest {
267
266
  const attemptBadge = attemptConditions.length === 0
268
267
  ? ""
269
268
  : ` ⚠ ${attemptConditions.join(" ")}/${attempts.length}`;
270
- const head = `T${turn.sequence}: status=${turn.status} finish=${finishReason}${rails} model=${model} ${tokens}${cost}${errBadge}${attemptBadge}`;
269
+ const lifecycle = `T${turn.sequence}: producer=${turn.producer} kind=${turn.kind} status=${turn.status}${turn.completed_at === null ? " state=open" : ""}`;
270
+ const head = turn.kind === "inference"
271
+ ? `${lifecycle} finish=${finishReason}${rails} model=${model} ${tokens}${cost}${errBadge}${attemptBadge}`
272
+ : `${lifecycle}${errBadge}`;
271
273
  const summary = packet === null
272
- ? " ↳ model packet: (none)"
274
+ ? null
273
275
  : content.length > 0
274
276
  ? ` ↳ emission: ${Digest.#summarize(content, 100)}`
275
277
  : assistant !== null
@@ -281,19 +283,27 @@ export default class Digest {
281
283
  ? ` ↳ reasoning: ${Digest.#summarize(reasoning, 100)}`
282
284
  : null;
283
285
  const opLines = Digest.#renderOpLines(m.logEntriesByTurn.get(turn.id) ?? []);
284
- return [head, summary, ...(reasoningLine ? [reasoningLine] : []), ...opLines].join("\n");
286
+ return [head, ...(summary ? [summary] : []), ...(reasoningLine ? [reasoningLine] : []), ...opLines].join("\n");
285
287
  }
286
288
  static #renderWorkerShape(worker, m) {
287
289
  // every worker has exactly one rollup row — digest_worker_rollups is FROM workers
288
290
  const roll = m.workerRollups.get(worker.id);
289
291
  const opMix = (m.opMixByWorker.get(worker.id) ?? []).map((o) => `${o.op}=${o.n}`).join(" ");
290
- const accounting = Digest.#accounting(m.requestsByWorker.get(worker.id) ?? []);
291
- const costStr = accounting === null || accounting.costUsd === null ? "unknown" : `$${accounting.costUsd}`;
292
+ const requests = m.requestsByWorker.get(worker.id) ?? [];
293
+ const accounting = Digest.#accounting(requests);
294
+ const usageStr = requests.length === 0
295
+ ? "no provider requests"
296
+ : Digest.#usageSummary(accounting);
297
+ const costStr = requests.length === 0
298
+ ? "n/a"
299
+ : accounting === null || accounting.costUsd === null
300
+ ? "unknown"
301
+ : `$${accounting.costUsd}`;
292
302
  return [
293
303
  `Loops: ${roll.loops}`,
294
304
  `Turns: ${roll.turns}`,
295
305
  `Last turn: ${roll.last_status !== null ? `status=${roll.last_status}` : "(none)"}`,
296
- `Tokens: ${Digest.#usageSummary(accounting)}`,
306
+ `Tokens: ${usageStr}`,
297
307
  `Cost: ${costStr}`,
298
308
  `Op mix: ${opMix.length > 0 ? opMix : "(no ops)"}`,
299
309
  ].join("\n");
@@ -309,11 +319,12 @@ export default class Digest {
309
319
  const bareCalls = m.modelCalls.filter((call) => call.kind === "bare").length;
310
320
  const pendingRequests = m.providerRequests.filter((request) => request.state === "pending").length;
311
321
  lines.push(`Workspaces: ${m.workspaces.length} Workers: ${m.workers.length} Loops: ${m.loops.length} Turns: ${m.turns.length} Model calls: ${m.modelCalls.length} (${bareCalls} BARE, ${erroredCalls} errored, ${pendingCalls} open) Emission attempts: ${m.turnAttempts.length} (${rejectedAttempts} rejected) Provider requests: ${m.providerRequests.length} (${pendingRequests} open) Log entries: ${m.logEntries.length}`);
312
- lines.push(`Semantic: body=${m.embeddings.body_entries} attached=${m.embeddings.derivation_complete} (vector=${m.embeddings.vector_complete} lexical=${m.embeddings.lexical} excluded=${m.embeddings.excluded} nonsemantic=${m.embeddings.nonsemantic} failed=${m.embeddings.failed}) unattached=${m.embeddings.unfinished} artifacts=${m.embeddings.derivation_artifacts_complete} complete/${m.embeddings.derivation_artifacts_building} building chunks=${m.embeddings.chunk_rows} models=${m.embeddings.models} token-derivations=${m.embeddings.token_derivations}`);
322
+ lines.push(`Semantic: channels=${m.embeddings.channel_entries} attached=${m.embeddings.derivation_complete} (vector=${m.embeddings.vector_complete} lexical=${m.embeddings.lexical} excluded=${m.embeddings.excluded} nonsemantic=${m.embeddings.nonsemantic} failed=${m.embeddings.failed}) unattached=${m.embeddings.unfinished} artifacts=${m.embeddings.derivation_artifacts_complete} complete/${m.embeddings.derivation_artifacts_building} building chunks=${m.embeddings.chunk_rows} models=${m.embeddings.models} token-derivations=${m.embeddings.token_derivations}`);
313
323
  if (m.embeddings.dispositions.length > 0) {
314
324
  lines.push("Semantic dispositions:");
315
325
  for (const row of m.embeddings.dispositions) {
316
- lines.push(` ${row.disposition} ${row.pathname}${row.reason === null ? "" : ` — ${row.reason}`}`);
326
+ const address = `${EntryManifest.toPath(row.scheme, row.authority, row.pathname)}#${row.channel}`;
327
+ lines.push(` ${row.disposition} ${address}${row.reason === null ? "" : ` — ${row.reason}`}`);
317
328
  }
318
329
  }
319
330
  // Triage rollup up top: how many conversations limped vs died vs ran clean, and the total
@@ -368,12 +379,17 @@ export default class Digest {
368
379
  const lines = [];
369
380
  lines.push(`# plurnk-service reasoning`);
370
381
  lines.push("");
371
- lines.push("Every provider attempt in turn order. Rejected attempts remain explicit forensic evidence.");
382
+ lines.push("Turn chronology with every provider attempt. Rejected attempts remain explicit forensic evidence.");
372
383
  for (const t of m.turns) {
373
384
  const loop = m.loopsById.get(t.loop_id);
374
385
  const worker = loop ? m.workersById.get(loop.worker_id) : undefined;
375
386
  lines.push("");
376
- lines.push(`## Worker ${worker?.id ?? "?"} / Loop ${loop?.sequence ?? "?"} / Turn ${t.sequence} (id=${t.id})`);
387
+ lines.push(`## Worker ${worker?.id ?? "?"} / Loop ${loop?.sequence ?? "?"} / Turn ${t.sequence} (id=${t.id}, producer=${t.producer}, kind=${t.kind})`);
388
+ if (t.kind !== "inference") {
389
+ lines.push("");
390
+ lines.push("(operation turn; no provider inference)");
391
+ continue;
392
+ }
377
393
  const attempts = m.attemptsByTurn.get(t.id) ?? [];
378
394
  if (attempts.length === 0) {
379
395
  const reasoning = t.packet !== null && StoredPacket.isAdmitted(t.packet)
@@ -419,41 +435,62 @@ export default class Digest {
419
435
  }
420
436
  return lines.join("\n");
421
437
  }
422
- // Per-turn packet files, byte-identical to the wire (Engine and digest both
423
- // project through PacketWire). system/user are markdown; assistantRaw is JSON.
438
+ static #turnOpsSource(m, turn) {
439
+ const rows = (m.logEntriesByTurn.get(turn.id) ?? []).filter((row) => row.op === null
440
+ && LogBody.actionlessKind({ op: row.op, attrs: row.attrs }) === "turnOps");
441
+ if (rows.length > 1) {
442
+ throw new TypeError(`digest: turn ${turn.id} has ${rows.length} turnOps rows; expected at most one`);
443
+ }
444
+ const row = rows[0];
445
+ if (row === undefined)
446
+ return null;
447
+ const body = LogBody.resolve({
448
+ op: row.op,
449
+ attrs: row.attrs,
450
+ tx: null,
451
+ rx: row.rx,
452
+ mimetypeRx: row.mimetype_rx,
453
+ });
454
+ if (body.mimetype !== "text/vnd.plurnk") {
455
+ throw new TypeError(`digest: turn ${turn.id} turnOps has mimetype ${JSON.stringify(body.mimetype)}; expected text/vnd.plurnk`);
456
+ }
457
+ return body.content;
458
+ }
459
+ // Per-turn forensic files. turnOps is the source authority; PacketWire
460
+ // reproduces provider request slots, and assistantRaw preserves provider bytes.
424
461
  static #writePacketFiles(m) {
425
462
  const written = [];
426
- // 0-based TURN index, NOT the DB id. id-sorted so the index is chronological.
427
- m.turns.toSorted((a, b) => a.id - b.id).forEach((t, index) => {
428
- const packet = t.packet;
429
- const padded = String(index).padStart(3, "0");
430
- if (packet === null) {
431
- const file = `packet${padded}.packet.md`;
432
- const note = `# Turn ${index} — no model packet\n\nThis journal-only turn dispatched operations without assembling a model request. See digest.md for its log rows.\n`;
433
- writeFileSync(join(m.digestDir, file), note);
434
- written.push(file);
435
- return;
463
+ m.turns
464
+ .map((turn) => ({ turn, source: Digest.#turnOpsSource(m, turn) }))
465
+ .filter(({ turn, source }) => turn.packet !== null || source !== null)
466
+ .toSorted((a, b) => a.turn.id - b.turn.id)
467
+ .forEach(({ turn, source }, ordinal) => {
468
+ const padded = String(ordinal).padStart(3, "0");
469
+ const files = [];
470
+ const packet = turn.packet;
471
+ if (packet !== null) {
472
+ files.push([`packet${padded}.system.md`, PacketWire.renderSlot(packet.sections, "system")], [`packet${padded}.user.md`, PacketWire.renderSlot(packet.sections, "user")]);
436
473
  }
437
- const systemMd = PacketWire.renderSlot(packet.sections, "system");
438
- const userMd = PacketWire.renderSlot(packet.sections, "user");
439
- const files = [
440
- [`packet${padded}.system.md`, systemMd],
441
- [`packet${padded}.user.md`, userMd],
442
- ];
443
- if (StoredPacket.isAdmitted(packet)) {
444
- files.push([`packet${padded}.assistant.md`, packet.assistant.content], [`packet${padded}.assistantRaw.json`, JSON.stringify(packet.assistantRaw, null, 2)]);
474
+ if (source !== null) {
475
+ files.push([`packet${padded}.assistant.md`, source]);
445
476
  }
446
- else {
477
+ if (packet !== null && StoredPacket.isAdmitted(packet)) {
478
+ if (source !== null && packet.assistant.content !== source) {
479
+ throw new TypeError(`digest: turn ${turn.id} packet assistant differs from its turnOps source`);
480
+ }
481
+ files.push([`packet${padded}.assistantRaw.json`, JSON.stringify(packet.assistantRaw, null, 2)]);
482
+ }
483
+ else if (packet !== null) {
447
484
  files.push([
448
485
  `packet${padded}.response.md`,
449
- `# Turn ${index} — request only\n\nNo provider response was admitted. Rejected attempt evidence, when present, is written separately.\n`,
486
+ `# Packet ${ordinal} — request only\n\nNo provider response was admitted. Rejected attempt evidence, when present, is written separately.\n`,
450
487
  ]);
451
488
  }
452
489
  for (const [file, body] of files) {
453
490
  writeFileSync(join(m.digestDir, file), body);
454
491
  written.push(file);
455
492
  }
456
- for (const attempt of m.attemptsByTurn.get(t.id) ?? []) {
493
+ for (const attempt of m.attemptsByTurn.get(turn.id) ?? []) {
457
494
  if (attempt.accepted === 1)
458
495
  continue;
459
496
  const attemptPadded = String(attempt.sequence).padStart(3, "0");
@@ -511,7 +548,9 @@ export default class Digest {
511
548
  accounting: Digest.#accounting(m.requestsByLoop.get(l.id) ?? []),
512
549
  })),
513
550
  turns: m.turns.map((t) => ({
514
- id: t.id, loop_id: t.loop_id, sequence: t.sequence, status: t.status,
551
+ id: t.id, loop_id: t.loop_id, sequence: t.sequence,
552
+ producer: t.producer, kind: t.kind,
553
+ status: t.status, completed_at: t.completed_at,
515
554
  accounting: Digest.#accounting(m.requestsByTurn.get(t.id) ?? []),
516
555
  finish_reason: t.finish_reason, model: t.model,
517
556
  attributions: t.packet?.attributions ?? [],
@@ -579,24 +618,22 @@ export default class Digest {
579
618
  : { stream: Digest.#renderStream(le) }),
580
619
  ...(le.status_rx >= 400 ? { problem: Digest.#rowProblem(le) } : {}),
581
620
  })),
582
- log_curation_effects: m.curationEffects.map(({ tags_added, tags_removed, ...effect }) => ({
621
+ log_curation_effects: m.curationEffects.map(({ folded_before, folded_after, tags_added, tags_removed, ...effect }) => ({
583
622
  ...effect,
623
+ folded_before: Digest.#parseJson(folded_before, []),
624
+ folded_after: Digest.#parseJson(folded_after, []),
584
625
  tags_added: Digest.#parseJson(tags_added, []),
585
626
  tags_removed: Digest.#parseJson(tags_removed, []),
586
627
  })),
587
628
  }, null, 2);
588
629
  }
589
- // Default DB path — mirrors the service (`Service.#expandHome(PLURNK_SERVICE_DB_PATH)`; the
590
- // `.env.defaults` floor is `~/.plurnk/plurnk.db`). The old repo-local default broke when
591
- // the DB moved to `~/.plurnk`; a no-arg digest now reads the service's actual DB.
630
+ // Default DB path mirrors the host path contract and an explicit service override.
592
631
  static defaultDbPath() {
632
+ const paths = new HostPaths();
593
633
  const env = process.env.PLURNK_SERVICE_DB_PATH;
594
- if (env !== undefined && env.length > 0) {
595
- if (env === "~")
596
- return homedir();
597
- return env.startsWith("~/") ? resolve(homedir(), env.slice(2)) : env;
598
- }
599
- return resolve(homedir(), ".plurnk", "plurnk.db");
634
+ return env !== undefined && env.length > 0
635
+ ? resolve(paths.expandUserPath(env))
636
+ : paths.databaseFile;
600
637
  }
601
638
  // {§digest-requiem}: one out-of-band audit per model-bearing worker, with exact
602
639
  // historical evidence and a required witness provider.
@@ -625,8 +662,9 @@ export default class Digest {
625
662
  attempts.push(attempt);
626
663
  attemptsByTurn.set(attempt.turn_id, attempts);
627
664
  }
628
- // Each worker's turns that carry a model request, ordered; the last is
629
- // the worker's final context. A worker with only journal turns is silent.
665
+ // Each worker's inference turns that carry a model request, ordered; the
666
+ // last is the worker's final context. A worker without inference evidence
667
+ // is silent.
630
668
  const byWorker = new Map();
631
669
  for (const t of db.digest_turns.all()) {
632
670
  const loop = loopById.get(t.loop_id);
@@ -846,6 +884,17 @@ export default class Digest {
846
884
  // mode) inspect cleanly; this tool only reads. The DB is quiescent at
847
885
  // digest time, so each PREP reads on its own — no cross-query snapshot.
848
886
  const db = new SqlRiteSync({ path: dbPath, dir: [moduleDir] });
887
+ const tables = new Set(db.digest_schema_tables.all().map(({ name }) => name));
888
+ const columns = new Map();
889
+ const has = (table) => tables.has(table);
890
+ const hasColumn = (table, column) => {
891
+ let names = columns.get(table);
892
+ if (names === undefined) {
893
+ names = new Set(db.digest_schema_columns.all({ table }).map(({ name }) => name));
894
+ columns.set(table, names);
895
+ }
896
+ return names.has(column);
897
+ };
849
898
  let workspaces = db.digest_workspaces.all();
850
899
  let workers = db.digest_workers.all();
851
900
  let loops = db.digest_loops.all();
@@ -861,50 +910,73 @@ export default class Digest {
861
910
  let curationEffects = [];
862
911
  let workerRollupRows = db.digest_worker_rollups.all();
863
912
  let opMixRows = db.digest_worker_op_mix.all();
864
- // The semantic-state analytic (owner ask), feature-detected per table: a HISTORICAL
865
- // specimen may predate token_counts/derivation_embeddings — an old db is a fact to read,
866
- // not a contract violation. Absent tables read as -1. node:sqlite directly (SqlRite's
867
- // eager prepare would refuse the whole open over one missing optional table).
868
- const probe = new DatabaseSync(dbPath, { readOnly: true });
869
- const has = (t) => probe.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(t) !== undefined;
870
- const hasColumn = (table, column) => probe.prepare(`SELECT 1 FROM pragma_table_info(?) WHERE name=?`).get(table, column) !== undefined;
871
- const one = (q) => Number(probe.prepare(q).get().n);
872
- const semanticStateAvailable = has("entries") && has("entry_channels") && hasColumn("entries", "deep_hash");
913
+ // Historical specimens may predate individual forensic analytics. The
914
+ // base statement set discovers their schema; only compatible static
915
+ // SqlRite packs are opened, so absence remains evidence rather than an
916
+ // eager-prepare failure or a reason to assemble SQL in TypeScript.
917
+ const channelDerivations = has("entry_channels") && hasColumn("entry_channels", "deep_hash");
918
+ const legacyEntryDerivations = has("entries") && hasColumn("entries", "deep_hash");
919
+ const semanticStateAvailable = has("entries") && has("entry_channels")
920
+ && (channelDerivations || legacyEntryDerivations);
921
+ const hasDisposition = semanticStateAvailable
922
+ && has("derivations")
923
+ && hasColumn("derivations", "disposition");
924
+ const queryRoot = resolve(moduleDir, "..", "..", "digest-sql");
925
+ const queryDirs = [
926
+ ...(has("log_curation_effects") ? [join(queryRoot, "curation")] : []),
927
+ ...(semanticStateAvailable
928
+ ? [join(queryRoot, channelDerivations ? "channel-state" : "entry-state")]
929
+ : []),
930
+ ...(hasDisposition
931
+ ? [join(queryRoot, channelDerivations ? "channel-dispositions" : "entry-dispositions")]
932
+ : []),
933
+ ...(semanticStateAvailable && has("derivations") ? [join(queryRoot, "derivations")] : []),
934
+ ...(has("derivation_embeddings") ? [join(queryRoot, "embeddings")] : []),
935
+ ...(has("token_counts") ? [join(queryRoot, "token-counts")] : []),
936
+ ];
937
+ const analytics = queryDirs.length === 0
938
+ ? null
939
+ : new SqlRiteSync({ path: dbPath, dir: queryDirs });
873
940
  if (has("log_curation_effects")) {
874
- curationEffects = probe.prepare(`
875
- SELECT operation_log_entry_id, target_log_entry_id, expanded_before,
876
- tags_added, tags_removed
877
- FROM log_curation_effects
878
- ORDER BY operation_log_entry_id, target_log_entry_id
879
- `).all();
941
+ curationEffects = analytics.digest_curation_effects.all();
880
942
  }
881
- const body = semanticStateAvailable
882
- ? "FROM entries e JOIN entry_channels ec ON ec.entry_id=e.id AND ec.name='body'"
883
- : "";
884
- const hasDisposition = has("derivations") && hasColumn("derivations", "disposition");
885
- const dispositionCount = (value) => hasDisposition
886
- ? one(`SELECT count(*) n ${body} JOIN derivations d ON d.deep_hash=e.deep_hash WHERE d.disposition='${value}'`)
887
- : -1;
943
+ const semanticState = semanticStateAvailable
944
+ ? (analytics[channelDerivations ? "digest_channel_semantic_state" : "digest_entry_semantic_state"].get()
945
+ ?? { channel_entries: 0, derivation_complete: 0, unfinished: 0 })
946
+ : null;
947
+ const dispositionCounts = hasDisposition
948
+ ? analytics[channelDerivations ? "digest_channel_disposition_counts" : "digest_entry_disposition_counts"].all()
949
+ : [];
950
+ const dispositionCount = (value) => dispositionCounts.find(({ disposition }) => disposition === value)?.n ?? (hasDisposition ? 0 : -1);
888
951
  const dispositions = hasDisposition
889
- ? probe.prepare(`SELECT e.pathname, d.disposition, d.reason ${body} JOIN derivations d ON d.deep_hash=e.deep_hash WHERE d.disposition <> 'vector' ORDER BY d.disposition, e.pathname`).all()
952
+ ? analytics[channelDerivations ? "digest_channel_dispositions" : "digest_entry_dispositions"].all()
890
953
  : [];
954
+ const derivationState = semanticStateAvailable && has("derivations")
955
+ ? analytics.digest_derivation_state.get()
956
+ : undefined;
957
+ const embeddingState = has("derivation_embeddings")
958
+ ? analytics.digest_embedding_state.get()
959
+ : undefined;
960
+ const tokenState = has("token_counts")
961
+ ? analytics.digest_token_count.get()
962
+ : undefined;
891
963
  const embeddings = {
892
- body_entries: semanticStateAvailable ? one(`SELECT count(*) n ${body}`) : -1,
893
- derivation_complete: semanticStateAvailable ? one(`SELECT count(*) n ${body} WHERE e.deep_hash IS NOT NULL`) : -1,
964
+ channel_entries: semanticState?.channel_entries ?? -1,
965
+ derivation_complete: semanticState?.derivation_complete ?? -1,
894
966
  vector_complete: dispositionCount("vector"),
895
967
  lexical: dispositionCount("lexical"),
896
968
  excluded: dispositionCount("excluded"),
897
969
  nonsemantic: dispositionCount("nonsemantic"),
898
970
  failed: dispositionCount("failed"),
899
971
  dispositions,
900
- unfinished: semanticStateAvailable ? one(`SELECT count(*) n ${body} WHERE e.deep_hash IS NULL`) : -1,
901
- derivation_artifacts_complete: semanticStateAvailable && has("derivations") ? one("SELECT count(*) n FROM derivations WHERE state='complete'") : -1,
902
- derivation_artifacts_building: semanticStateAvailable && has("derivations") ? one("SELECT count(*) n FROM derivations WHERE state='building'") : -1,
903
- chunk_rows: has("derivation_embeddings") ? one("SELECT count(*) n FROM derivation_embeddings") : -1,
904
- models: has("derivation_embeddings") ? one("SELECT count(DISTINCT embedding_model) n FROM derivation_embeddings") : -1,
905
- token_derivations: has("token_counts") ? one("SELECT count(*) n FROM token_counts") : -1,
972
+ unfinished: semanticState?.unfinished ?? -1,
973
+ derivation_artifacts_complete: derivationState?.complete ?? -1,
974
+ derivation_artifacts_building: derivationState?.building ?? -1,
975
+ chunk_rows: embeddingState?.chunks ?? -1,
976
+ models: embeddingState?.models ?? -1,
977
+ token_derivations: tokenState?.n ?? -1,
906
978
  };
907
- probe.close();
979
+ analytics?.close();
908
980
  db.close();
909
981
  // {§digest-programmatic-surface} — optional worker/workspace selectors narrow the
910
982
  // kept worker graph and its dependent evidence rather than emitting the whole DB.