@plurnk/plurnk-service 1.3.12 → 1.5.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 (488) hide show
  1. package/.env.defaults +95 -91
  2. package/INSTALL.md +54 -28
  3. package/README.md +25 -10
  4. package/SPEC.md +2426 -942
  5. package/dist/Paths.d.ts +4 -1
  6. package/dist/Paths.d.ts.map +1 -1
  7. package/dist/Paths.js +24 -23
  8. package/dist/Paths.js.map +1 -1
  9. package/dist/build-info.json +1 -1
  10. package/dist/content/edit-receipt.d.ts +13 -28
  11. package/dist/content/edit-receipt.d.ts.map +1 -1
  12. package/dist/content/edit-receipt.js +285 -104
  13. package/dist/content/edit-receipt.js.map +1 -1
  14. package/dist/content/edited-span.d.ts.map +1 -1
  15. package/dist/content/edited-span.js +2 -5
  16. package/dist/content/edited-span.js.map +1 -1
  17. package/dist/content/index.d.ts +4 -3
  18. package/dist/content/index.d.ts.map +1 -1
  19. package/dist/content/index.js +2 -1
  20. package/dist/content/index.js.map +1 -1
  21. package/dist/content/line-marker.d.ts +10 -9
  22. package/dist/content/line-marker.d.ts.map +1 -1
  23. package/dist/content/line-marker.js +8 -11
  24. package/dist/content/line-marker.js.map +1 -1
  25. package/dist/content/matcher.d.ts +15 -26
  26. package/dist/content/matcher.d.ts.map +1 -1
  27. package/dist/content/matcher.js +77 -107
  28. package/dist/content/matcher.js.map +1 -1
  29. package/dist/content/mimetype-binary.d.ts +2 -2
  30. package/dist/content/mimetype-binary.d.ts.map +1 -1
  31. package/dist/content/mimetype-binary.js +10 -10
  32. package/dist/content/mimetype-binary.js.map +1 -1
  33. package/dist/content/path-mimetype.js +3 -3
  34. package/dist/content/path-mimetype.js.map +1 -1
  35. package/dist/content/read-projector.d.ts +14 -0
  36. package/dist/content/read-projector.d.ts.map +1 -0
  37. package/dist/content/read-projector.js +86 -0
  38. package/dist/content/read-projector.js.map +1 -0
  39. package/dist/content/read-resolve.d.ts +6 -7
  40. package/dist/content/read-resolve.d.ts.map +1 -1
  41. package/dist/content/read-resolve.js +36 -59
  42. package/dist/content/read-resolve.js.map +1 -1
  43. package/dist/core/BranchReceipt.d.ts +6 -0
  44. package/dist/core/BranchReceipt.d.ts.map +1 -0
  45. package/dist/core/BranchReceipt.js +24 -0
  46. package/dist/core/BranchReceipt.js.map +1 -0
  47. package/dist/core/BudgetOverflow.d.ts +20 -0
  48. package/dist/core/BudgetOverflow.d.ts.map +1 -0
  49. package/dist/core/BudgetOverflow.js +49 -0
  50. package/dist/core/BudgetOverflow.js.map +1 -0
  51. package/dist/core/BudgetReadout.d.ts +8 -0
  52. package/dist/core/BudgetReadout.d.ts.map +1 -0
  53. package/dist/core/BudgetReadout.js +79 -0
  54. package/dist/core/BudgetReadout.js.map +1 -0
  55. package/dist/core/ChannelWrite.d.ts +31 -9
  56. package/dist/core/ChannelWrite.d.ts.map +1 -1
  57. package/dist/core/ChannelWrite.js +30 -23
  58. package/dist/core/ChannelWrite.js.map +1 -1
  59. package/dist/core/ChannelWrite.sql +14 -12
  60. package/dist/core/CoreSchemeServices.d.ts +18 -4
  61. package/dist/core/CoreSchemeServices.d.ts.map +1 -1
  62. package/dist/core/CoreSchemeServices.js +7 -1
  63. package/dist/core/CoreSchemeServices.js.map +1 -1
  64. package/dist/core/Dispatcher.d.ts +26 -21
  65. package/dist/core/Dispatcher.d.ts.map +1 -1
  66. package/dist/core/Dispatcher.js +1626 -671
  67. package/dist/core/Dispatcher.js.map +1 -1
  68. package/dist/core/DurableStatement.d.ts +6 -0
  69. package/dist/core/DurableStatement.d.ts.map +1 -0
  70. package/dist/core/DurableStatement.js +51 -0
  71. package/dist/core/DurableStatement.js.map +1 -0
  72. package/dist/core/Engine.d.ts +64 -29
  73. package/dist/core/Engine.d.ts.map +1 -1
  74. package/dist/core/Engine.js +1348 -835
  75. package/dist/core/Engine.js.map +1 -1
  76. package/dist/core/Engine.sql +329 -234
  77. package/dist/core/EnvFlags.js +1 -1
  78. package/dist/core/EnvFlags.js.map +1 -1
  79. package/dist/core/ErrorDetail.d.ts +6 -0
  80. package/dist/core/ErrorDetail.d.ts.map +1 -0
  81. package/dist/core/ErrorDetail.js +20 -0
  82. package/dist/core/ErrorDetail.js.map +1 -0
  83. package/dist/core/ExecutorRegistry.d.ts +14 -3
  84. package/dist/core/ExecutorRegistry.d.ts.map +1 -1
  85. package/dist/core/ExecutorRegistry.js +56 -30
  86. package/dist/core/ExecutorRegistry.js.map +1 -1
  87. package/dist/core/GitBranch.d.ts +20 -0
  88. package/dist/core/GitBranch.d.ts.map +1 -0
  89. package/dist/core/GitBranch.js +110 -0
  90. package/dist/core/GitBranch.js.map +1 -0
  91. package/dist/core/JournalTurn.d.ts +9 -0
  92. package/dist/core/JournalTurn.d.ts.map +1 -0
  93. package/dist/core/JournalTurn.js +14 -0
  94. package/dist/core/JournalTurn.js.map +1 -0
  95. package/dist/core/JournalTurn.sql +10 -0
  96. package/dist/core/LogBody.d.ts +18 -0
  97. package/dist/core/LogBody.d.ts.map +1 -0
  98. package/dist/core/LogBody.js +180 -0
  99. package/dist/core/LogBody.js.map +1 -0
  100. package/dist/core/LoopFlagsReader.d.ts +7 -0
  101. package/dist/core/LoopFlagsReader.d.ts.map +1 -0
  102. package/dist/core/LoopFlagsReader.js +33 -0
  103. package/dist/core/LoopFlagsReader.js.map +1 -0
  104. package/dist/core/LoopLifecycle.d.ts +8 -2
  105. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  106. package/dist/core/LoopLifecycle.js +54 -11
  107. package/dist/core/LoopLifecycle.js.map +1 -1
  108. package/dist/core/LoopLifecycle.sql +10 -7
  109. package/dist/core/NoticeChannel.d.ts +13 -0
  110. package/dist/core/NoticeChannel.d.ts.map +1 -0
  111. package/dist/core/NoticeChannel.js +40 -0
  112. package/dist/core/NoticeChannel.js.map +1 -0
  113. package/dist/core/Owner.d.ts +0 -1
  114. package/dist/core/Owner.d.ts.map +1 -1
  115. package/dist/core/Owner.js +2 -5
  116. package/dist/core/Owner.js.map +1 -1
  117. package/dist/core/PacketBuilder.d.ts +27 -25
  118. package/dist/core/PacketBuilder.d.ts.map +1 -1
  119. package/dist/core/PacketBuilder.js +321 -383
  120. package/dist/core/PacketBuilder.js.map +1 -1
  121. package/dist/core/ProblemLog.d.ts +26 -0
  122. package/dist/core/ProblemLog.d.ts.map +1 -0
  123. package/dist/core/ProblemLog.js +58 -0
  124. package/dist/core/ProblemLog.js.map +1 -0
  125. package/dist/core/ProposalLifecycle.d.ts +15 -21
  126. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  127. package/dist/core/ProposalLifecycle.js +291 -78
  128. package/dist/core/ProposalLifecycle.js.map +1 -1
  129. package/dist/core/ProviderInstantiate.d.ts.map +1 -1
  130. package/dist/core/ProviderInstantiate.js +51 -48
  131. package/dist/core/ProviderInstantiate.js.map +1 -1
  132. package/dist/core/SchemeRegistry.d.ts +14 -8
  133. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  134. package/dist/core/SchemeRegistry.js +189 -114
  135. package/dist/core/SchemeRegistry.js.map +1 -1
  136. package/dist/core/ServiceTeardown.d.ts +11 -0
  137. package/dist/core/ServiceTeardown.d.ts.map +1 -0
  138. package/dist/core/ServiceTeardown.js +70 -0
  139. package/dist/core/ServiceTeardown.js.map +1 -0
  140. package/dist/core/StoredPacket.d.ts +29 -0
  141. package/dist/core/StoredPacket.d.ts.map +1 -0
  142. package/dist/core/StoredPacket.js +147 -0
  143. package/dist/core/StoredPacket.js.map +1 -0
  144. package/dist/core/StrikeRail.d.ts +6 -3
  145. package/dist/core/StrikeRail.d.ts.map +1 -1
  146. package/dist/core/StrikeRail.js +27 -56
  147. package/dist/core/StrikeRail.js.map +1 -1
  148. package/dist/core/TerminalResult.d.ts +16 -0
  149. package/dist/core/TerminalResult.d.ts.map +1 -0
  150. package/dist/core/TerminalResult.js +49 -0
  151. package/dist/core/TerminalResult.js.map +1 -0
  152. package/dist/core/WorkerControlAddress.d.ts +17 -0
  153. package/dist/core/WorkerControlAddress.d.ts.map +1 -0
  154. package/dist/core/WorkerControlAddress.js +44 -0
  155. package/dist/core/WorkerControlAddress.js.map +1 -0
  156. package/dist/core/WorkerName.d.ts +31 -0
  157. package/dist/core/WorkerName.d.ts.map +1 -0
  158. package/dist/core/WorkerName.js +95 -0
  159. package/dist/core/WorkerName.js.map +1 -0
  160. package/dist/core/WorkerName.sql +36 -0
  161. package/dist/core/WorkspaceGate.d.ts +14 -0
  162. package/dist/core/WorkspaceGate.d.ts.map +1 -0
  163. package/dist/core/WorkspaceGate.js +155 -0
  164. package/dist/core/WorkspaceGate.js.map +1 -0
  165. package/dist/core/caps/CapsResolve.d.ts +5 -1
  166. package/dist/core/caps/CapsResolve.d.ts.map +1 -1
  167. package/dist/core/caps/CapsResolve.js +8 -4
  168. package/dist/core/caps/CapsResolve.js.map +1 -1
  169. package/dist/core/caps/DbChannelCaps.d.ts +5 -11
  170. package/dist/core/caps/DbChannelCaps.d.ts.map +1 -1
  171. package/dist/core/caps/DbChannelCaps.js +30 -12
  172. package/dist/core/caps/DbChannelCaps.js.map +1 -1
  173. package/dist/core/caps/DbEntryCaps.d.ts +5 -14
  174. package/dist/core/caps/DbEntryCaps.d.ts.map +1 -1
  175. package/dist/core/caps/DbEntryCaps.js +27 -8
  176. package/dist/core/caps/DbEntryCaps.js.map +1 -1
  177. package/dist/core/caps/DbNotifyCaps.d.ts +1 -1
  178. package/dist/core/caps/DbNotifyCaps.d.ts.map +1 -1
  179. package/dist/core/caps/DbNotifyCaps.js +18 -15
  180. package/dist/core/caps/DbNotifyCaps.js.map +1 -1
  181. package/dist/core/caps/DbProjectionCaps.d.ts +5 -5
  182. package/dist/core/caps/DbProjectionCaps.d.ts.map +1 -1
  183. package/dist/core/caps/DbProjectionCaps.js +21 -4
  184. package/dist/core/caps/DbProjectionCaps.js.map +1 -1
  185. package/dist/core/caps/DbSubscriptionCaps.d.ts +4 -6
  186. package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -1
  187. package/dist/core/caps/DbSubscriptionCaps.js +75 -66
  188. package/dist/core/caps/DbSubscriptionCaps.js.map +1 -1
  189. package/dist/core/caps/DbTagCaps.d.ts +5 -12
  190. package/dist/core/caps/DbTagCaps.d.ts.map +1 -1
  191. package/dist/core/caps/DbTagCaps.js +20 -11
  192. package/dist/core/caps/DbTagCaps.js.map +1 -1
  193. package/dist/core/caps/SchemeCtxImpl.d.ts +6 -1
  194. package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
  195. package/dist/core/caps/SchemeCtxImpl.js +6 -6
  196. package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
  197. package/dist/core/content-hash.js +1 -1
  198. package/dist/core/content-hash.js.map +1 -1
  199. package/dist/core/env-defaults.d.ts.map +1 -1
  200. package/dist/core/env-defaults.js.map +1 -1
  201. package/dist/core/fork.d.ts.map +1 -1
  202. package/dist/core/fork.js +55 -30
  203. package/dist/core/fork.js.map +1 -1
  204. package/dist/core/fork.sql +43 -29
  205. package/dist/core/git-env.d.ts +2 -0
  206. package/dist/core/git-env.d.ts.map +1 -1
  207. package/dist/core/git-env.js +13 -18
  208. package/dist/core/git-env.js.map +1 -1
  209. package/dist/core/git-iso.d.ts +3 -2
  210. package/dist/core/git-iso.d.ts.map +1 -1
  211. package/dist/core/git-iso.js +36 -27
  212. package/dist/core/git-iso.js.map +1 -1
  213. package/dist/core/git-membership.d.ts +2 -1
  214. package/dist/core/git-membership.d.ts.map +1 -1
  215. package/dist/core/git-membership.js +276 -162
  216. package/dist/core/git-membership.js.map +1 -1
  217. package/dist/core/git-state.d.ts +8 -1
  218. package/dist/core/git-state.d.ts.map +1 -1
  219. package/dist/core/git-state.js +44 -26
  220. package/dist/core/git-state.js.map +1 -1
  221. package/dist/core/namespace.d.ts +1 -0
  222. package/dist/core/namespace.d.ts.map +1 -1
  223. package/dist/core/namespace.js +20 -0
  224. package/dist/core/namespace.js.map +1 -1
  225. package/dist/core/optimistic-settlement.d.ts +2 -0
  226. package/dist/core/optimistic-settlement.d.ts.map +1 -0
  227. package/dist/core/optimistic-settlement.js +14 -0
  228. package/dist/core/optimistic-settlement.js.map +1 -0
  229. package/dist/core/owner.sql +1 -1
  230. package/dist/core/packet-inject.d.ts.map +1 -1
  231. package/dist/core/packet-inject.js +7 -11
  232. package/dist/core/packet-inject.js.map +1 -1
  233. package/dist/core/packet-wire.d.ts +3 -21
  234. package/dist/core/packet-wire.d.ts.map +1 -1
  235. package/dist/core/packet-wire.js +305 -385
  236. package/dist/core/packet-wire.js.map +1 -1
  237. package/dist/core/plurnk-uri.d.ts +12 -1
  238. package/dist/core/plurnk-uri.d.ts.map +1 -1
  239. package/dist/core/plurnk-uri.js +49 -29
  240. package/dist/core/plurnk-uri.js.map +1 -1
  241. package/dist/core/results.d.ts +18 -5
  242. package/dist/core/results.d.ts.map +1 -1
  243. package/dist/core/results.js +33 -18
  244. package/dist/core/results.js.map +1 -1
  245. package/dist/core/ruler_count.d.ts +4 -0
  246. package/dist/core/ruler_count.d.ts.map +1 -0
  247. package/dist/core/ruler_count.js +7 -0
  248. package/dist/core/ruler_count.js.map +1 -0
  249. package/dist/core/scheme-types.d.ts +3 -17
  250. package/dist/core/scheme-types.d.ts.map +1 -1
  251. package/dist/core/scheme-types.js.map +1 -1
  252. package/dist/core/search-gate.d.ts.map +1 -1
  253. package/dist/core/search-gate.js +3 -11
  254. package/dist/core/search-gate.js.map +1 -1
  255. package/dist/core/teaching-corpus.d.ts +6 -0
  256. package/dist/core/teaching-corpus.d.ts.map +1 -0
  257. package/dist/core/teaching-corpus.js +23 -0
  258. package/dist/core/teaching-corpus.js.map +1 -0
  259. package/dist/core/teaching.d.ts +0 -1
  260. package/dist/core/teaching.d.ts.map +1 -1
  261. package/dist/core/teaching.js +2 -8
  262. package/dist/core/teaching.js.map +1 -1
  263. package/dist/core/token-ruler.d.ts.map +1 -1
  264. package/dist/core/token-ruler.js +3 -16
  265. package/dist/core/token-ruler.js.map +1 -1
  266. package/dist/core/turn-scheduler.d.ts +1 -1
  267. package/dist/core/turn-scheduler.d.ts.map +1 -1
  268. package/dist/core/turn-scheduler.js +1 -1
  269. package/dist/core/turn-scheduler.js.map +1 -1
  270. package/dist/core/worker-cap.d.ts +2 -4
  271. package/dist/core/worker-cap.d.ts.map +1 -1
  272. package/dist/core/worker-cap.js +13 -4
  273. package/dist/core/worker-cap.js.map +1 -1
  274. package/dist/core/{run-ops.sql → worker-ops.sql} +14 -14
  275. package/dist/core/workspace-settings.d.ts.map +1 -1
  276. package/dist/core/workspace-settings.js +17 -9
  277. package/dist/core/workspace-settings.js.map +1 -1
  278. package/dist/digest/Digest.d.ts +2 -1
  279. package/dist/digest/Digest.d.ts.map +1 -1
  280. package/dist/digest/Digest.js +510 -149
  281. package/dist/digest/Digest.js.map +1 -1
  282. package/dist/digest/digest.sql +23 -10
  283. package/dist/index.d.ts.map +1 -1
  284. package/dist/index.js +3 -5
  285. package/dist/index.js.map +1 -1
  286. package/dist/observe/api.d.ts +6 -0
  287. package/dist/observe/api.d.ts.map +1 -0
  288. package/dist/observe/api.js +11 -0
  289. package/dist/observe/api.js.map +1 -0
  290. package/dist/observe/init.d.ts +7 -0
  291. package/dist/observe/init.d.ts.map +1 -0
  292. package/dist/observe/init.js +159 -0
  293. package/dist/observe/init.js.map +1 -0
  294. package/dist/observe/metrics.d.ts +6 -0
  295. package/dist/observe/metrics.d.ts.map +1 -0
  296. package/dist/observe/metrics.js +15 -0
  297. package/dist/observe/metrics.js.map +1 -0
  298. package/dist/observe/spans.d.ts +4 -0
  299. package/dist/observe/spans.d.ts.map +1 -0
  300. package/dist/observe/spans.js +51 -0
  301. package/dist/observe/spans.js.map +1 -0
  302. package/dist/schemes/EffectPolicy.d.ts +1 -0
  303. package/dist/schemes/EffectPolicy.d.ts.map +1 -1
  304. package/dist/schemes/EffectPolicy.js +5 -2
  305. package/dist/schemes/EffectPolicy.js.map +1 -1
  306. package/dist/schemes/Exec.d.ts +9 -14
  307. package/dist/schemes/Exec.d.ts.map +1 -1
  308. package/dist/schemes/Exec.js +402 -262
  309. package/dist/schemes/Exec.js.map +1 -1
  310. package/dist/schemes/ExecOutputScheme.d.ts +9 -9
  311. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  312. package/dist/schemes/ExecOutputScheme.js +49 -18
  313. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  314. package/dist/schemes/File.d.ts +7 -13
  315. package/dist/schemes/File.d.ts.map +1 -1
  316. package/dist/schemes/File.js +280 -151
  317. package/dist/schemes/File.js.map +1 -1
  318. package/dist/schemes/Log.d.ts +8 -12
  319. package/dist/schemes/Log.d.ts.map +1 -1
  320. package/dist/schemes/Log.js +402 -233
  321. package/dist/schemes/Log.js.map +1 -1
  322. package/dist/schemes/Log.sql +71 -32
  323. package/dist/schemes/Prompt.d.ts +3 -3
  324. package/dist/schemes/Prompt.d.ts.map +1 -1
  325. package/dist/schemes/Prompt.js +10 -10
  326. package/dist/schemes/Prompt.js.map +1 -1
  327. package/dist/schemes/Skill.d.ts +2 -3
  328. package/dist/schemes/Skill.d.ts.map +1 -1
  329. package/dist/schemes/Skill.js +2 -6
  330. package/dist/schemes/Skill.js.map +1 -1
  331. package/dist/schemes/Worker.d.ts +11 -19
  332. package/dist/schemes/Worker.d.ts.map +1 -1
  333. package/dist/schemes/Worker.js +210 -89
  334. package/dist/schemes/Worker.js.map +1 -1
  335. package/dist/schemes/_entry-chunk.d.ts.map +1 -1
  336. package/dist/schemes/_entry-chunk.js +12 -5
  337. package/dist/schemes/_entry-chunk.js.map +1 -1
  338. package/dist/schemes/_entry-crud.d.ts +11 -9
  339. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  340. package/dist/schemes/_entry-crud.js +72 -13
  341. package/dist/schemes/_entry-crud.js.map +1 -1
  342. package/dist/schemes/_entry-crud.sql +28 -10
  343. package/dist/schemes/_entry-find.d.ts +49 -18
  344. package/dist/schemes/_entry-find.d.ts.map +1 -1
  345. package/dist/schemes/_entry-find.js +348 -195
  346. package/dist/schemes/_entry-find.js.map +1 -1
  347. package/dist/schemes/_entry-find.sql +20 -8
  348. package/dist/schemes/_entry-graph.d.ts +4 -2
  349. package/dist/schemes/_entry-graph.d.ts.map +1 -1
  350. package/dist/schemes/_entry-graph.js +55 -31
  351. package/dist/schemes/_entry-graph.js.map +1 -1
  352. package/dist/schemes/_entry-graph.sql +37 -22
  353. package/dist/schemes/_entry-manifest.d.ts +10 -15
  354. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  355. package/dist/schemes/_entry-manifest.js +50 -268
  356. package/dist/schemes/_entry-manifest.js.map +1 -1
  357. package/dist/schemes/_entry-ops.d.ts +14 -15
  358. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  359. package/dist/schemes/_entry-ops.js +121 -110
  360. package/dist/schemes/_entry-ops.js.map +1 -1
  361. package/dist/schemes/_entry-ops.sql +2 -3
  362. package/dist/schemes/_entry-semantic.d.ts +22 -9
  363. package/dist/schemes/_entry-semantic.d.ts.map +1 -1
  364. package/dist/schemes/_entry-semantic.js +127 -67
  365. package/dist/schemes/_entry-semantic.js.map +1 -1
  366. package/dist/schemes/_entry-semantic.sql +63 -45
  367. package/dist/schemes/_entry-send.d.ts +3 -4
  368. package/dist/schemes/_entry-send.d.ts.map +1 -1
  369. package/dist/schemes/_entry-send.js +48 -23
  370. package/dist/schemes/_entry-send.js.map +1 -1
  371. package/dist/schemes/_path-scope.d.ts +23 -0
  372. package/dist/schemes/_path-scope.d.ts.map +1 -0
  373. package/dist/schemes/_path-scope.js +61 -0
  374. package/dist/schemes/_path-scope.js.map +1 -0
  375. package/dist/schemes/_search-candidate.d.ts +20 -0
  376. package/dist/schemes/_search-candidate.d.ts.map +1 -0
  377. package/dist/schemes/_search-candidate.js +19 -0
  378. package/dist/schemes/_search-candidate.js.map +1 -0
  379. package/dist/schemes/_search-exclusion.d.ts +7 -0
  380. package/dist/schemes/_search-exclusion.d.ts.map +1 -0
  381. package/dist/schemes/_search-exclusion.js +23 -0
  382. package/dist/schemes/_search-exclusion.js.map +1 -0
  383. package/dist/schemes/_search-index.d.ts +6 -0
  384. package/dist/schemes/_search-index.d.ts.map +1 -0
  385. package/dist/schemes/_search-index.js +328 -0
  386. package/dist/schemes/_search-index.js.map +1 -0
  387. package/dist/schemes/cosine.js +1 -1
  388. package/dist/schemes/cosine.js.map +1 -1
  389. package/dist/schemes/exec-abort.js +3 -3
  390. package/dist/schemes/exec-abort.js.map +1 -1
  391. package/dist/schemes/exec-env.js +3 -3
  392. package/dist/schemes/exec-env.js.map +1 -1
  393. package/dist/server/BranchBatches.d.ts +49 -0
  394. package/dist/server/BranchBatches.d.ts.map +1 -0
  395. package/dist/server/BranchBatches.js +592 -0
  396. package/dist/server/BranchBatches.js.map +1 -0
  397. package/dist/server/Daemon.d.ts +39 -71
  398. package/dist/server/Daemon.d.ts.map +1 -1
  399. package/dist/server/Daemon.js +1133 -491
  400. package/dist/server/Daemon.js.map +1 -1
  401. package/dist/server/DaemonModule.d.ts +31 -0
  402. package/dist/server/DaemonModule.d.ts.map +1 -0
  403. package/dist/server/DaemonModule.js +2 -0
  404. package/dist/server/DaemonModule.js.map +1 -0
  405. package/dist/server/branch-batch.sql +154 -0
  406. package/dist/server/client-input.d.ts +13 -0
  407. package/dist/server/client-input.d.ts.map +1 -1
  408. package/dist/server/client-input.js +268 -57
  409. package/dist/server/client-input.js.map +1 -1
  410. package/dist/server/dispatch-as-plurnk.d.ts +1 -1
  411. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
  412. package/dist/server/dispatch-as-plurnk.js +15 -7
  413. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  414. package/dist/server/drain.sql +96 -65
  415. package/dist/server/envelope.d.ts +4 -7
  416. package/dist/server/envelope.d.ts.map +1 -1
  417. package/dist/server/envelope.js +118 -95
  418. package/dist/server/envelope.js.map +1 -1
  419. package/dist/server/envelope.sql +18 -23
  420. package/dist/server/exec-poll-backoff.js +1 -1
  421. package/dist/server/exec-poll-backoff.js.map +1 -1
  422. package/dist/server/lifecycle-recovery.sql +112 -2
  423. package/dist/server/logEntry.d.ts +4 -2
  424. package/dist/server/logEntry.d.ts.map +1 -1
  425. package/dist/server/logEntry.js +6 -3
  426. package/dist/server/logEntry.js.map +1 -1
  427. package/dist/server/logEntry.sql +1 -1
  428. package/dist/server/loop-model.d.ts.map +1 -1
  429. package/dist/server/loop-model.js +22 -9
  430. package/dist/server/loop-model.js.map +1 -1
  431. package/dist/server/loopDocs.d.ts.map +1 -1
  432. package/dist/server/loopDocs.js +5 -4
  433. package/dist/server/loopDocs.js.map +1 -1
  434. package/dist/server/seam-entry-read.sql +15 -10
  435. package/dist/server/seam-log-read.sql +2 -2
  436. package/dist/server/seam-loop.sql +1 -1
  437. package/dist/server/seam-proposal-list.sql +17 -7
  438. package/dist/service.d.ts.map +1 -1
  439. package/dist/service.js +79 -61
  440. package/dist/service.js.map +1 -1
  441. package/migrations/001_schema.sql +1010 -0
  442. package/package.json +65 -32
  443. package/dist/core/PluginLoader.d.ts +0 -20
  444. package/dist/core/PluginLoader.d.ts.map +0 -1
  445. package/dist/core/PluginLoader.js +0 -142
  446. package/dist/core/PluginLoader.js.map +0 -1
  447. package/dist/core/TelemetryChannel.d.ts +0 -37
  448. package/dist/core/TelemetryChannel.d.ts.map +0 -1
  449. package/dist/core/TelemetryChannel.js +0 -80
  450. package/dist/core/TelemetryChannel.js.map +0 -1
  451. package/dist/core/path-decode.d.ts +0 -3
  452. package/dist/core/path-decode.d.ts.map +0 -1
  453. package/dist/core/path-decode.js +0 -9
  454. package/dist/core/path-decode.js.map +0 -1
  455. package/dist/core/plugin-attribution.d.ts +0 -5
  456. package/dist/core/plugin-attribution.d.ts.map +0 -1
  457. package/dist/core/plugin-attribution.js +0 -39
  458. package/dist/core/plugin-attribution.js.map +0 -1
  459. package/dist/core/world-state.d.ts +0 -10
  460. package/dist/core/world-state.d.ts.map +0 -1
  461. package/dist/core/world-state.js +0 -35
  462. package/dist/core/world-state.js.map +0 -1
  463. package/dist/core/world-state.sql +0 -35
  464. package/dist/core/zero-pin.d.ts +0 -3
  465. package/dist/core/zero-pin.d.ts.map +0 -1
  466. package/dist/core/zero-pin.js +0 -16
  467. package/dist/core/zero-pin.js.map +0 -1
  468. package/dist/server/auto.d.ts +0 -6
  469. package/dist/server/auto.d.ts.map +0 -1
  470. package/dist/server/auto.js +0 -63
  471. package/dist/server/auto.js.map +0 -1
  472. package/dist/server/clientTurn.d.ts +0 -6
  473. package/dist/server/clientTurn.d.ts.map +0 -1
  474. package/dist/server/clientTurn.js +0 -22
  475. package/dist/server/clientTurn.js.map +0 -1
  476. package/dist/server/clientTurn.sql +0 -10
  477. package/dist/server/noProposals.d.ts +0 -6
  478. package/dist/server/noProposals.d.ts.map +0 -1
  479. package/dist/server/noProposals.js +0 -37
  480. package/dist/server/noProposals.js.map +0 -1
  481. package/dist/server/version-info.d.ts +0 -14
  482. package/dist/server/version-info.d.ts.map +0 -1
  483. package/dist/server/version-info.js +0 -69
  484. package/dist/server/version-info.js.map +0 -1
  485. package/migrations/0000-00-00.01_schema.sql +0 -536
  486. package/migrations/0004_loop-provider.sql +0 -3
  487. package/migrations/0005_subscription-published-channel.sql +0 -3
  488. package/migrations/0006_loop-max-turns.sql +0 -3
@@ -1,63 +1,133 @@
1
- // FIND helper for entry-bearing schemes (SPEC §find; plurnk.md FIND row).
2
- // FIND resolves to the scheme's CATALOG ROWS — the very rows the manifest catalogs —
3
- // filtered to the statement's matches. A matcher (glob/regex/jsonpath/xpath/~semantic/
4
- // @graph) decides WHICH entries appear. A CONTENT matcher also stamps each row with
5
- // `matchLines` — the source line(s) where it hit (plurnk.md:31: FIND returns the matching
6
- // rows with the match lines in the metadata; the line CONTENT is a READ). The result is a
7
- // JSON array of catalog rows: the per-scheme slice of the catalog (§find-result-catalog-rows).
1
+ // FIND helper for entry-bearing schemes (SPEC {§find}; plurnk.md FIND row).
2
+ // FIND resolves one of two questions from the target shape. A broad target
3
+ // returns catalog resources; an exact matcher target returns flat addressable
4
+ // match locations. The content itself remains a READ.
8
5
  //
9
- // Slot semantics (plurnk.md §"Body matcher dispatch (FIND, READ, OPEN, FOLD)"):
6
+ // FIND slot semantics (contracts SPEC §4/§7):
10
7
  // target — required scope (path or glob); selects which entries are candidates
11
8
  // body — matcher (glob/regex/jsonpath/xpath/~semantic/@graph). A content matcher
12
9
  // runs against the entry's default-channel CONTENT (Matcher.matchAgainstContent
13
10
  // → the mimetypes plugin) and INCLUDES/EXCLUDES the entry — e.g.
14
11
  // `FIND(log:///**/error):/timeout/i` keeps logs whose content matches.
15
12
  // signal — tag filter: candidate entry must have ALL listed tags
16
- // <L> — results pagination: select results N..M from the matched list
13
+ // <L> — result pagination: resource or match-location positions N..M
14
+ import { DEFAULT_RETRIEVAL_LIMIT, renderJsonResult } from "@plurnk/plurnk-contracts";
17
15
  import { LineMarkerOps } from "../content/index.js";
18
16
  import Matcher from "../content/matcher.js";
19
- import { decodePathParens } from "../core/path-decode.js";
17
+ import { entryPathnameOf } from "../core/plurnk-uri.js";
20
18
  import EntryGraph from "./_entry-graph.js";
21
19
  import EntryCrud from "./_entry-crud.js";
22
20
  import EntryManifest from "./_entry-manifest.js";
23
21
  import Owner from "../core/Owner.js";
24
22
  import EntrySemantic from "./_entry-semantic.js";
23
+ import Results from "../core/results.js";
24
+ import { resolveSearchCandidates } from "./_search-candidate.js";
25
+ import { pathFolderSummaries, pathScope, pathScopeMatches } from "./_path-scope.js";
26
+ export const findItemTokens = (item) => item.items === undefined
27
+ ? Object.values(item.channels).reduce((sum, channel) => sum + channel.tokens, 0)
28
+ : item.tokens;
29
+ export const emptyFindFields = () => ({
30
+ content: null,
31
+ mimetype: null,
32
+ results: [],
33
+ itemsTokenTotal: 0,
34
+ returnedItemsTokenTotal: 0,
35
+ matchingPathCount: 0,
36
+ matchLocationCount: 0,
37
+ });
38
+ const uniqueMatchLocations = (locations) => {
39
+ const seen = new Set();
40
+ const unique = [];
41
+ for (const location of locations) {
42
+ const key = JSON.stringify(location);
43
+ if (seen.has(key))
44
+ continue;
45
+ seen.add(key);
46
+ unique.push(location);
47
+ }
48
+ return unique;
49
+ };
50
+ // {§find-result-projection} — selection remains grouped internally because
51
+ // schemes and curation operate on resources. This one public projection owns
52
+ // target-shape mode, pagination, counts, and rendering for every FIND source.
53
+ export const projectFindResult = (statement, scope, resources, scopes = []) => {
54
+ const resourcePaths = new Set();
55
+ for (const { item } of resources) {
56
+ if (resourcePaths.has(item.path)) {
57
+ throw new Error(`FIND selection contains duplicate resource ${JSON.stringify(item.path)}`);
58
+ }
59
+ resourcePaths.add(item.path);
60
+ }
61
+ const matchingPathCount = resources.length;
62
+ const matchLocationCount = resources.reduce((sum, { match }) => sum + uniqueMatchLocations(match.matches).length, 0);
63
+ const itemsTokenTotal = resources.reduce((sum, { item }) => sum + findItemTokens(item), 0)
64
+ + scopes.reduce((sum, item) => sum + item.tokens, 0);
65
+ const fields = {
66
+ content: null,
67
+ mimetype: null,
68
+ results: [],
69
+ itemsTokenTotal,
70
+ returnedItemsTokenTotal: 0,
71
+ matchingPathCount,
72
+ matchLocationCount,
73
+ };
74
+ const locationMode = statement.body !== null && scope.kind === "exact";
75
+ const completeItems = locationMode
76
+ ? uniqueMatchLocations(resources.flatMap(({ match }) => match.matches))
77
+ : [
78
+ ...resources.map(({ item, match }) => statement.body === null
79
+ ? item
80
+ : { ...item, matchLocationCount: uniqueMatchLocations(match.matches).length }),
81
+ ...scopes,
82
+ ];
83
+ if (!locationMode && scopes.length > 0) {
84
+ completeItems.sort((a, b) => (a.path ?? "").localeCompare(b.path ?? ""));
85
+ }
86
+ const marker = statement.body?.dialect === "semantic"
87
+ ? EntrySemantic.resultSelection(statement.lineMarker).page
88
+ : statement.lineMarker ?? { marks: [1, DEFAULT_RETRIEVAL_LIMIT] };
89
+ const unit = locationMode ? "matchLocation" : "resource";
90
+ const page = LineMarkerOps.page(completeItems, marker, {
91
+ unit,
92
+ allowEmpty: statement.body !== null || statement.lineMarker === null,
93
+ });
94
+ if (page.status !== 200) {
95
+ if (page.problem === undefined)
96
+ throw new Error("FIND pagination failed without Problem Details");
97
+ return Results.assert({ status: page.status, problem: page.problem, ...fields, range: page.range });
98
+ }
99
+ if (statement.body !== null && matchingPathCount === 0) {
100
+ return {
101
+ status: 204,
102
+ ...fields,
103
+ ...(page.range === undefined ? {} : { range: page.range }),
104
+ };
105
+ }
106
+ const results = page.items ?? [];
107
+ const returnedItemsTokenTotal = locationMode
108
+ ? itemsTokenTotal
109
+ : results.reduce((sum, item) => sum + findItemTokens(item), 0);
110
+ return {
111
+ status: 200,
112
+ content: renderJsonResult(results), // {§find-result-projection} {§json-result-rendering}
113
+ mimetype: "application/json",
114
+ results,
115
+ itemsTokenTotal,
116
+ returnedItemsTokenTotal,
117
+ matchingPathCount,
118
+ matchLocationCount,
119
+ ...(page.range === undefined ? {} : { range: page.range }),
120
+ };
121
+ };
25
122
  export default class EntryFind {
26
123
  static #scopePathnameOf(statement) {
27
124
  const path = statement.target;
28
125
  if (path === null)
29
126
  return null;
30
- if (path.kind === "regex")
31
- return path.raw; // regex source — parens are syntax, never encoded
32
- return decodePathParens(path.kind === "url" ? path.pathname : path.raw); // #239 item 4
33
- }
34
- static #paginate(items, marker) {
35
- const total = items.length;
36
- const { first, last } = marker;
37
- // #209 — a fractional marker is a semantic similarity threshold; on a
38
- // non-semantic (paginated) result it's nonsense → 416, never floored.
39
- if (!Number.isInteger(first) || (last !== null && !Number.isInteger(last)))
40
- return { status: 416 };
41
- if (last === null) {
42
- if (first === 0 || first === -1)
43
- return { status: 200, items: [] };
44
- if (first > 0 && first <= total)
45
- return { status: 200, items: [items[first - 1]] };
46
- return { status: 416 };
47
- }
48
- let n = first;
49
- let m = last;
50
- if (n === 0)
51
- n = 1;
52
- if (m === -1)
53
- m = total;
54
- if (n < 1 || n > total)
55
- return { status: 416 };
56
- if (m < 1 || m > total)
57
- return { status: 416 };
58
- if (n > m)
59
- return { status: 416 };
60
- return { status: 200, items: items.slice(n - 1, m) };
127
+ // FIND addresses the same canonical entry identity as READ and direct
128
+ // CRUD. Both namespace authorities and network hosts are part of that
129
+ // identity and must survive the exact-entry lookup.
130
+ return entryPathnameOf(path);
61
131
  }
62
132
  static #unique(xs) {
63
133
  const seen = new Set();
@@ -69,105 +139,202 @@ export default class EntryFind {
69
139
  }
70
140
  return out;
71
141
  }
72
- // Resolve a FIND to its matched workspace PATHNAMES — entry-level, unique, in result
142
+ // Resolve a FIND to its matched workspace resources — entry-level, unique, in result
73
143
  // order (rank for ~semantic, candidate order otherwise). Candidate selection (scope +
74
144
  // tags) runs in SQL (find_workspace_entry_candidates); a content matcher then runs against
75
145
  // each candidate's default-channel CONTENT (Matcher.matchAgainstContent → the mimetypes
76
- // plugin) and INCLUDES/EXCLUDES the entry — 200 keeps it, 204/415/203 drop it, 400
77
- // (malformed matcher) fails the whole op. Path-scoping stays in the (target). Returns the
78
- // matched pathnames plus `locations` — each content hit's source line(s), keyed by pathname.
79
- static async #matchPathnames(statement, ctx, manifest, explicitOwnerId) {
80
- if (statement.target === null)
81
- return { status: 400, matches: [] };
146
+ // plugin) and INCLUDES/EXCLUDES the entry - 200 keeps it, 204/203 drop it, and a
147
+ // 4xx matcher failure ends the whole operation. Path-scoping stays in the (target). Match
148
+ // locations remain grouped by resource internally until the target-shaped public projection.
149
+ static async #matchPathnames(statement, ctx, manifest, address) {
150
+ if (statement.target === null) {
151
+ return {
152
+ status: 400,
153
+ matches: [],
154
+ error: "FIND requires a target.",
155
+ extensions: {
156
+ recovery: "Provide the FIND target.",
157
+ retryable: false,
158
+ },
159
+ };
160
+ }
82
161
  // Scope by the manifest's persisted entries.scheme (storedScheme; absent →
83
162
  // name). File persists under the reserved 'file' scheme ({§entry-identity-no-null}).
84
163
  const scheme = EntryCrud.identityScheme(manifest);
85
- const scopePathname = EntryFind.#scopePathnameOf(statement);
86
- // {§fs-errno} — the green-lie pin (#545): a FIND whose target is an EXACT path (no glob,
87
- // no folder scope) that resolves to NO entry is ENOENT with its fact — certifying empty
88
- // over nothing taught run59's model that a real function did not exist. A glob/folder
89
- // scope with zero matches stays the blessed orienting empty (§render-rule, owner: an
90
- // empty survey says "don't look here").
91
- if (statement.target.kind !== "regex" && scopePathname !== null && scopePathname.length > 0
92
- && !scopePathname.includes("*") && !scopePathname.endsWith("/")) {
164
+ const scopePathname = address.pathname ?? EntryFind.#scopePathnameOf(statement);
165
+ const scope = scopePathname === null
166
+ ? null
167
+ : pathScope(scopePathname, manifest.folderScopes === true);
168
+ // {§fs-errno} — an exact-path miss is ENOENT; an empty glob or folder
169
+ // survey is a successful empty result.
170
+ if (scope?.kind === "exact" && scope.pathname.length > 0) {
93
171
  const exact = await ctx.db.crud_find_workspace_entry.get({
94
172
  workspace_id: ctx.workspaceId,
95
- owner_id: explicitOwnerId ?? await Owner.commonsId(ctx.db, ctx.workspaceId),
96
- scheme, pathname: scopePathname,
173
+ owner_id: address.ownerId ?? await Owner.commonsId(ctx.db, ctx.workspaceId),
174
+ scheme, pathname: scope.pathname,
97
175
  });
98
- if (exact === undefined)
99
- return { status: 404, matches: [], error: `no entry at ${EntryManifest.toPath(scheme, scopePathname)}` };
176
+ if (exact === undefined) {
177
+ return {
178
+ status: 404,
179
+ matches: [],
180
+ error: `No entry exists at ${EntryManifest.toPath(scheme, scope.pathname)}.`,
181
+ extensions: { target: EntryManifest.toPath(scheme, scope.pathname) },
182
+ };
183
+ }
100
184
  }
101
- // The target's GLOB scope. A FOLDER (trailing slash, incl. the scheme root `/`) expands to
102
- // its contents — append `*`; a bare ENTRY path stays exact (one entry); an explicit glob
103
- // passes through literally. The `*` is folderhood, not a blanket prefix — so FIND(README.md)
104
- // is the one entry, uniform with READ's target contract (#286). grammar 0.46 regex-in-path:
105
- // a `#pattern#flags` target filters by regex over the pathname (below), no scope glob.
106
- // §find-scope-prefix-filter
107
- const scopeGlob = statement.target.kind === "regex" || scopePathname === null || scopePathname.length === 0
108
- ? null
109
- : (scopePathname.endsWith("/") ? `${scopePathname}*` : scopePathname);
110
- const tags = Array.isArray(statement.signal) ? statement.signal : []; // tag filter, AND semantics — §find-tag-filter-and-semantics
185
+ // SQL receives only the literal prefix and returns a safe superset. Node's
186
+ // path matcher owns the shell-glob truth below: unlike SQLite GLOB, `*`
187
+ // cannot cross `/`, while `**` can. A declared folder scope remains a
188
+ // recursive prefix independent of glob syntax. {§find-scope-prefix-filter}
189
+ const tags = Array.isArray(statement.signal) ? statement.signal : []; // tag filter, AND semantics — {§find-tag-filter-and-semantics}
111
190
  const tagsParam = tags.length > 0 ? JSON.stringify(tags) : "[]";
112
191
  const { db, workspaceId } = ctx;
113
192
  const semantic = statement.body?.dialect === "semantic";
114
193
  let candidates = await db[semantic ? "find_workspace_entry_candidate_ids" : "find_workspace_entry_candidates"].all({
115
194
  workspace_id: workspaceId,
116
- owner_id: explicitOwnerId ?? await Owner.commonsId(db, workspaceId),
195
+ owner_id: address.ownerId ?? await Owner.commonsId(db, workspaceId),
117
196
  scheme,
118
197
  ...(semantic ? {} : { channel: manifest.defaultChannel }),
119
- scope_pathname: scopeGlob,
198
+ scope_prefix: scope?.candidatePrefix ?? null,
120
199
  tags: tagsParam,
121
200
  });
122
- // grammar 0.46 regex-in-path — a `#pattern#flags` target narrows candidates by regex
123
- // over their pathname (in TS; SQLite has no regex). Malformed pattern → 400, parallel
124
- // to a malformed body matcher.
125
- if (statement.target.kind === "regex") {
126
- let re;
201
+ const candidatePathnames = statement.body === null && scope?.kind === "glob" && scope.shallowPrefix !== null
202
+ ? candidates.map((candidate) => candidate.pathname)
203
+ : undefined;
204
+ if (scope !== null) {
127
205
  try {
128
- re = new RegExp(statement.target.pattern, statement.target.flags || undefined);
206
+ candidates = candidates.filter((c) => pathScopeMatches(scope, c.pathname));
129
207
  }
130
208
  catch {
131
- return { status: 400, matches: [] };
209
+ return {
210
+ status: 400,
211
+ matches: [],
212
+ error: `The path glob '${scopePathname ?? ""}' is malformed.`,
213
+ extensions: {
214
+ target: scopePathname ?? "",
215
+ recovery: "Correct the target glob.",
216
+ retryable: false,
217
+ },
218
+ };
132
219
  }
133
- candidates = candidates.filter((c) => re.test(c.pathname));
134
220
  }
135
- // Every dialect resolves to (file, span) items — one per match (#286). A body-less FIND
136
- // selects the whole entry (span: null); a matcher selects spans within it.
221
+ // Every dialect resolves to one selection per resource. Content
222
+ // dialects already carry honest match evidence; relation dialects map
223
+ // their indexed source spans into readable TextRegions below.
137
224
  let matches;
138
225
  if (statement.body !== null && statement.body.dialect === "semantic") {
139
226
  // Semantic rank is exhaustive within the SAME target/tag candidate set as every
140
- // other matcher. Passing entry identities into the ranker preserves top-K meaning:
227
+ // other matcher. Passing entry identities into the ranker preserves ranking meaning:
141
228
  // constrain first, then rank, never rank the corpus and discard out-of-scope hits.
142
229
  const { mimetypes } = ctx;
143
- if (mimetypes === undefined)
144
- return { status: 501, matches: [] };
145
- const marker = statement.lineMarker === null
146
- ? { first: EntrySemantic.defaultTopK(), last: null }
147
- : LineMarkerOps.firstLast(statement.lineMarker);
148
- const ranked = await EntrySemantic.rankSemantic(ctx.db, ctx.workspaceId, scheme, candidates.map(({ entry_id }) => entry_id), mimetypes, statement.body.raw, marker);
149
- if (ranked.status !== 200)
150
- return { status: ranked.status, matches: [] };
151
- matches = ranked.results.map((x) => ({ pathname: x.pathname, span: { lineStart: x.lineStart, lineEnd: x.lineEnd } }));
230
+ if (mimetypes === undefined) {
231
+ return {
232
+ status: 501,
233
+ matches: [],
234
+ error: "Semantic search requires the mimetypes capability.",
235
+ extensions: {
236
+ stage: "semantic-search",
237
+ retryable: false,
238
+ },
239
+ };
240
+ }
241
+ const selection = EntrySemantic.resultSelection(statement.lineMarker);
242
+ const candidateSet = resolveSearchCandidates(candidates.map(({ pathname, deep_hash }) => ({ key: pathname, deepHash: deep_hash })));
243
+ if (candidateSet.state === "incomplete")
244
+ return {
245
+ status: 503,
246
+ matches: [],
247
+ error: `The persistent search index covers ${candidateSet.indexed} of ${candidateSet.total} selected entries.`,
248
+ extensions: {
249
+ search: candidateSet,
250
+ stage: "search-index",
251
+ recovery: "Wait for search indexing to complete before repeating the search.",
252
+ retryable: false,
253
+ },
254
+ };
255
+ const ranked = await EntrySemantic.rankCandidates(ctx.db, candidateSet.candidates, mimetypes, statement.body.raw, selection);
256
+ if (ranked.status !== 200) {
257
+ return {
258
+ status: ranked.status,
259
+ matches: [],
260
+ error: ranked.status === 501
261
+ ? "Similarity-threshold search requires an embedding provider."
262
+ : "The requested similarity threshold is outside the supported range.",
263
+ extensions: {
264
+ stage: "semantic-search",
265
+ ...(selection.threshold === null ? {} : { threshold: selection.threshold }),
266
+ recovery: ranked.status === 501
267
+ ? "Remove the decimal similarity threshold while embeddings are unavailable."
268
+ : "Use a similarity threshold greater than zero and less than one.",
269
+ retryable: false,
270
+ },
271
+ };
272
+ }
273
+ matches = await EntryFind.#addTextRegions(ranked.results.map((x) => ({
274
+ key: x.key,
275
+ span: { lineStart: x.lineStart, lineEnd: x.lineEnd },
276
+ })), ctx, manifest, address.ownerId);
152
277
  }
153
278
  else if (statement.body === null) {
154
- matches = candidates.map((c) => ({ pathname: c.pathname, span: null }));
279
+ matches = candidates.map((c) => ({ pathname: c.pathname, matches: [] }));
155
280
  }
156
281
  else if (statement.body.dialect === "graph") {
157
- // @graph (plurnk-service#186): body is `@<sym` / `@>sym` / `@sym`. EntryGraph resolves
282
+ // {§relation-indexed-dialects} Body is `@<sym` / `@>sym` / `@sym`. EntryGraph resolves
158
283
  // the relation across (workspace, scheme), each as a (file, span); intersect with the
159
284
  // in-scope candidates (target glob + tags) for the final set.
160
- const inScope = new Set(candidates.map((c) => c.pathname));
161
- const graph = await EntryGraph.match(ctx.db, ctx.workspaceId, scheme, statement.body.raw);
162
- if (graph.status !== 200)
163
- return { status: graph.status, matches: [] };
164
- matches = graph.matches.filter((m) => inScope.has(m.pathname)).map((m) => ({ pathname: m.pathname, span: { lineStart: m.lineStart, lineEnd: m.lineEnd } }));
285
+ const scopedCandidates = resolveSearchCandidates(candidates.map(({ pathname, deep_hash }) => ({ key: pathname, deepHash: deep_hash })));
286
+ if (scopedCandidates.state === "incomplete")
287
+ return {
288
+ status: 503,
289
+ matches: [],
290
+ error: `The persistent search index covers ${scopedCandidates.indexed} of ${scopedCandidates.total} selected entries.`,
291
+ extensions: {
292
+ search: scopedCandidates,
293
+ stage: "search-index",
294
+ recovery: "Wait for search indexing to complete before repeating the search.",
295
+ retryable: false,
296
+ },
297
+ };
298
+ const universeRows = await ctx.db.find_workspace_derivation_candidates.all({
299
+ workspace_id: ctx.workspaceId,
300
+ });
301
+ const universe = resolveSearchCandidates(universeRows.map(({ key, deep_hash }) => ({ key, deepHash: deep_hash })));
302
+ if (universe.state === "incomplete")
303
+ return {
304
+ status: 503,
305
+ matches: [],
306
+ error: `The persistent search index covers ${universe.indexed} of ${universe.total} entries in the relationship universe.`,
307
+ extensions: {
308
+ search: universe,
309
+ stage: "search-index",
310
+ recovery: "Wait for search indexing to complete before repeating the search.",
311
+ retryable: false,
312
+ },
313
+ };
314
+ const graph = await EntryGraph.matchCandidates(ctx.db, universe.candidates, scopedCandidates.candidates, statement.body.raw);
315
+ if (graph.status !== 200) {
316
+ return {
317
+ status: graph.status,
318
+ matches: [],
319
+ error: `The graph matcher '${statement.body.raw}' is malformed.`,
320
+ extensions: {
321
+ stage: "matcher",
322
+ dialect: "graph",
323
+ recovery: "Correct or remove the matcher.",
324
+ retryable: false,
325
+ },
326
+ };
327
+ }
328
+ matches = await EntryFind.#addTextRegions(graph.matches.map((m) => ({
329
+ key: m.key,
330
+ span: { lineStart: m.lineStart, lineEnd: m.lineEnd },
331
+ })), ctx, manifest, address.ownerId);
165
332
  }
166
333
  else {
167
334
  const { mimetypes } = ctx;
168
335
  if (mimetypes === undefined)
169
336
  throw new Error("EntryFind.#matchPathnames: body matcher requires the mimetypes capability in ctx");
170
- // §find-source-agnostic — the shared content-matcher primitive (Log.find runs the same
337
+ // {§find-source-agnostic} — the shared content-matcher primitive (Log.find runs the same
171
338
  // one over log rows). Candidates key by pathname; each hit becomes a Match.
172
339
  const r = await Matcher.matchCandidates(statement.body, candidates.map((c) => {
173
340
  if (c.content === undefined || c.mimetype === undefined)
@@ -175,35 +342,23 @@ export default class EntryFind {
175
342
  return { key: c.pathname, content: c.content, mimetype: c.mimetype };
176
343
  }), mimetypes);
177
344
  if (r.status !== 200)
178
- return { status: r.status, matches: [] };
179
- matches = r.matches.map((m) => ({ pathname: m.key, span: m.span, ...(m.path !== undefined ? { path: m.path } : {}) }));
180
- }
181
- if (statement.lineMarker !== null && statement.body?.dialect !== "semantic") {
182
- const page = EntryFind.#paginate(matches, LineMarkerOps.firstLast(statement.lineMarker));
183
- if (page.status !== 200)
184
- return { status: page.status, matches: [] };
185
- matches = page.items ?? [];
345
+ return {
346
+ status: r.status,
347
+ matches: [],
348
+ problem: r.problem,
349
+ };
350
+ matches = r.matches.map((match) => ({ pathname: match.key, matches: match.matches }));
186
351
  }
187
- return { status: 200, matches };
352
+ return { status: 200, matches, ...(scope === null ? {} : { scope }), ...(candidatePathnames === undefined ? {} : { candidatePathnames }) };
188
353
  }
189
- static async #addReadableRows(matches, ctx, manifest, explicitOwnerId) {
190
- if (matches.every(({ span }) => span === null))
191
- return matches.map((match) => ({ ...match, span: null }));
192
- if (ctx.mimetypes === undefined)
193
- throw new Error("EntryFind.#addReadableRows: matched entries require the mimetypes capability");
354
+ static async #addTextRegions(matches, ctx, manifest, explicitOwnerId) {
355
+ if (matches.every(({ span }) => span === null)) {
356
+ return [...new Set(matches.map(({ key }) => key))].map((pathname) => ({ pathname, matches: [] }));
357
+ }
194
358
  const scheme = EntryCrud.identityScheme(manifest);
195
359
  const ownerId = explicitOwnerId ?? await Owner.commonsId(ctx.db, ctx.workspaceId);
196
- const grouped = new Map();
197
- for (let index = 0; index < matches.length; index += 1) {
198
- const match = matches[index];
199
- if (match.span === null)
200
- continue;
201
- const indices = grouped.get(match.pathname) ?? [];
202
- indices.push(index);
203
- grouped.set(match.pathname, indices);
204
- }
205
- const resolved = matches.map((match) => ({ ...match, span: null }));
206
- for (const [pathname, indices] of grouped) {
360
+ const candidates = [];
361
+ for (const pathname of new Set(matches.filter(({ span }) => span !== null).map(({ key }) => key))) {
207
362
  const row = await ctx.db.ops_read_channel.get({
208
363
  workspace_id: ctx.workspaceId,
209
364
  owner_id: ownerId,
@@ -212,89 +367,87 @@ export default class EntryFind {
212
367
  channel: manifest.defaultChannel,
213
368
  });
214
369
  if (row === undefined)
215
- throw new Error(`EntryFind.#addReadableRows: matched entry ${pathname} has no default channel`);
216
- const rows = await ctx.mimetypes.rowsForLines({ content: row.content, hint: row.mimetype }, indices.map((index) => ({
217
- line: matches[index].span.lineStart,
218
- endLine: matches[index].span.lineEnd,
219
- })));
220
- if (rows.length !== indices.length)
221
- throw new Error(`EntryFind.#addReadableRows: ${pathname} returned ${rows.length} rows for ${indices.length} spans`);
222
- for (let offset = 0; offset < indices.length; offset += 1) {
223
- const index = indices[offset];
224
- const match = matches[index];
225
- const readable = rows[offset];
226
- resolved[index] = {
227
- ...match,
228
- span: {
229
- ...match.span,
230
- rowStart: readable.row,
231
- rowEnd: readable.endRow,
232
- },
233
- };
234
- }
370
+ throw new Error(`EntryFind.#addTextRegions: matched entry ${pathname} has no default channel`);
371
+ candidates.push({ key: pathname, ...row });
235
372
  }
236
- return resolved;
373
+ const resolved = Matcher.addTextRegions(matches, candidates);
374
+ return resolved.map(({ key, matches: ranges }) => ({ pathname: key, matches: ranges }));
237
375
  }
238
376
  // FIND result = the scheme's catalog rows, filtered to the matched entries and kept in
239
377
  // match order. A catalog row is exactly what the manifest catalogs (path + per-channel
240
- // {mimetype, tokens, lines}, tags, seconds) — FIND is the filtered, navigable slice of
241
- // that catalog, rendered as a JSON array (application/json). §find-result-catalog-rows
242
- static async findWorkspaceEntries(statement, ctx, manifest, explicitOwnerId) {
243
- const match = await EntryFind.#matchPathnames(statement, ctx, manifest, explicitOwnerId);
244
- if (match.status !== 200)
245
- return { status: match.status, content: null, mimetype: null, results: [], itemsTokenTotal: 0, pathnames: [], matches: [], ...(match.error !== undefined ? { error: match.error } : {}) }; // {§fs-errno} — the ENOENT fact rides through
246
- const readableMatches = await EntryFind.#addReadableRows(match.matches, ctx, manifest, explicitOwnerId);
378
+ // {mimetype, tokens, lines}, tags, stream lifecycle) — FIND is the filtered, navigable slice of
379
+ // that catalog, rendered as a JSON array (application/json). {§find-result-projection}
380
+ static async findWorkspaceEntries(statement, ctx, manifest, address = {}) {
381
+ const match = await EntryFind.#matchPathnames(statement, ctx, manifest, address);
382
+ const empty = emptyFindFields();
383
+ if (match.status !== 200) {
384
+ if (match.problem !== undefined) {
385
+ return Results.assert({
386
+ status: match.status,
387
+ problem: match.problem,
388
+ ...empty,
389
+ });
390
+ }
391
+ if (match.error === undefined) {
392
+ throw new Error(`EntryFind selection failed with status ${match.status} without Problem Details or a diagnostic.`);
393
+ }
394
+ return Results.failure(`scheme:${manifest.name}`, match.status === 404 ? "entry-not-found" : match.status === 416 ? "range-not-satisfiable" : "find-failed", match.status, match.error, empty, match.extensions);
395
+ }
247
396
  const scheme = EntryCrud.identityScheme(manifest);
248
- // The catalog row is keyed by its addressable path; align each match to its row through
249
- // the same EntryManifest.toPath the catalog uses (single source of truth). Match order is
250
- // preserved (rank for ~semantic); a match whose entry has no row (e.g. the self-excluded
251
- // manifest) drops out. Each match becomes ONE result item carrying its span (#286).
397
+ // The catalog row is keyed by its addressable path; align each selected
398
+ // resource to its row through the same EntryManifest.toPath the catalog
399
+ // uses. Resource order is preserved (rank for ~semantic).
252
400
  // {§entry-owner} — the alignment draws from the SAME owner the candidates matched, so a
253
401
  // match never pairs with a coordinate-twin sibling's catalog metadata.
254
- const byPath = new Map((await EntryManifest.catalogRowsFor(ctx, scheme, explicitOwnerId ?? await Owner.commonsId(ctx.db, ctx.workspaceId))).map((r) => [r.path, r]));
255
- const results = [];
256
- const matches = [];
257
- const seenPath = new Set();
258
- let itemsTokenTotal = 0; // content weight summed per UNIQUE entry (items repeat a file across its matches)
259
- // Two granularities from one hit list (§matcher-selection-signal ÷ #286): `results` (the
260
- // rx the model reads) keeps EVERY hit — on a single-line document the per-hit matchPath is
261
- // the only thing distinguishing them; `matches` (the fan-out's delivery list) dedups by
262
- // (pathname, span) — N hits on one source line deliver that line ONCE, no identical-row noise.
263
- const seenSpan = new Set();
264
- for (const m of readableMatches) {
402
+ const byPath = new Map((await EntryManifest.catalogRowsFor(ctx, scheme, address.ownerId ?? await Owner.commonsId(ctx.db, ctx.workspaceId))).map((r) => [r.path, r]));
403
+ const resources = [];
404
+ for (const m of match.matches) {
265
405
  const row = byPath.get(EntryManifest.toPath(scheme, m.pathname));
266
406
  if (row === undefined)
267
407
  continue;
268
- results.push(m.span !== null ? { ...row, matchSpan: m.span, ...(m.path !== undefined ? { matchPath: m.path } : {}) } : row);
269
- const spanKey = `${m.pathname}\0${m.span === null ? "" : `${m.span.lineStart},${m.span.lineEnd}`}`;
270
- if (!seenSpan.has(spanKey)) {
271
- seenSpan.add(spanKey);
272
- matches.push(m);
273
- }
274
- if (!seenPath.has(m.pathname)) {
275
- seenPath.add(m.pathname);
276
- itemsTokenTotal += Object.values(row.channels).reduce((s, c) => s + c.tokens, 0);
408
+ resources.push({ item: row, match: m });
409
+ }
410
+ // A terminal single-star catalog is a one-level map. Keep real entries
411
+ // at that level and collapse deeper descendants into exact, actionable
412
+ // `dir/**` scopes. The summaries are navigation metadata, not hidden
413
+ // resource matches.
414
+ const scopes = [];
415
+ if (statement.body === null && match.scope !== undefined && match.candidatePathnames !== undefined) {
416
+ for (const folder of pathFolderSummaries(match.scope, match.candidatePathnames)) {
417
+ let tokens = 0;
418
+ let items = 0;
419
+ for (const pathname of folder.pathnames) {
420
+ const row = byPath.get(EntryManifest.toPath(scheme, pathname));
421
+ if (row === undefined)
422
+ continue;
423
+ items++;
424
+ tokens += Object.values(row.channels).reduce((sum, channel) => sum + channel.tokens, 0);
425
+ }
426
+ if (items > 0) {
427
+ scopes.push({ path: EntryManifest.toPath(scheme, folder.selector), items, tokens });
428
+ }
277
429
  }
278
430
  }
279
- // §find-count-not-contents (#418) — a repo-scale FIND(**) over a 19k-entry workspace can't
280
- // enumerate: materializing every match overflows the window (a clean grind should not be a
281
- // crash-and-recover). Over the render budget, the result is a COUNT + narrow steer instead
282
- // of the rows — the model sees "N match, too broad, narrow it" and adapts. INDEPENDENT of
283
- // the window size: even a 256k window shouldn't render a whole repo's catalog into a turn.
284
- // The meta line's count + itemsTokenTotal still self-describe the hit set. Budget is a knob
285
- // (reader-declared); 0/unset = no gate (small workspaces enumerate as before).
286
- const budget = Number.parseInt(process.env.PLURNK_SERVICE_FIND_MAX_MATCHES ?? "0", 10);
287
- if (budget > 0 && results.length > budget) {
288
- const steer = `${results.length} entries match, exceeding the render budget (${budget}) — not enumerated.`;
289
- // Count-forward means COUNT ONLY. Retaining the enumerated arrays behind a
290
- // terse rendered steer defeated the contract twice: callers could still fan
291
- // every hidden match into work, and the full objects stayed resident. The
292
- // overflow count + aggregate weight are the complete bounded result.
293
- return { status: 200, content: steer, mimetype: "text/markdown", results: [], itemsTokenTotal, pathnames: [], matches: [], overflow: results.length };
431
+ if (match.scope === undefined)
432
+ throw new Error("FIND selection succeeded without a path scope");
433
+ const projected = projectFindResult(statement, match.scope, resources, scopes);
434
+ if (address.pathname === undefined)
435
+ return projected;
436
+ // Exact FIND consumes the same selected canonical producer as exact
437
+ // READ. Query projection remains core-owned, while the durable default-
438
+ // channel outcome survives cold and warm acquisition identically.
439
+ const stored = await EntryCrud.readEntry(address.pathname, ctx, scheme, address.ownerId);
440
+ if (stored.status !== 200 || stored.entry === null) {
441
+ throw new Error(`EntryFind projected exact entry ${address.pathname} but could not read its canonical representation.`);
294
442
  }
295
- // Compact JSON — the model parses it natively; the `null, 2` pretty-print was ~36%
296
- // whitespace of the catalog body, tokens the wire doesn't need.
297
- return { status: 200, content: JSON.stringify(results), mimetype: "application/json", results, itemsTokenTotal, pathnames: [...seenPath], matches };
443
+ const producerResult = stored.entry.channels[manifest.defaultChannel]?.producerResult;
444
+ return producerResult === undefined
445
+ ? projected
446
+ : Results.assert({
447
+ ...producerResult,
448
+ ...projected,
449
+ status: producerResult.status,
450
+ });
298
451
  }
299
452
  }
300
453
  //# sourceMappingURL=_entry-find.js.map