@plurnk/plurnk-service 1.3.12 → 1.4.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 (469) hide show
  1. package/.env.defaults +84 -77
  2. package/INSTALL.md +50 -25
  3. package/README.md +24 -10
  4. package/SPEC.md +2311 -928
  5. package/dist/Paths.d.ts +4 -1
  6. package/dist/Paths.d.ts.map +1 -1
  7. package/dist/Paths.js +23 -21
  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 +3 -3
  18. package/dist/content/index.d.ts.map +1 -1
  19. package/dist/content/index.js +1 -1
  20. package/dist/content/index.js.map +1 -1
  21. package/dist/content/line-marker.d.ts +6 -9
  22. package/dist/content/line-marker.d.ts.map +1 -1
  23. package/dist/content/line-marker.js +7 -11
  24. package/dist/content/line-marker.js.map +1 -1
  25. package/dist/content/matcher.d.ts +14 -25
  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-resolve.d.ts +8 -4
  36. package/dist/content/read-resolve.d.ts.map +1 -1
  37. package/dist/content/read-resolve.js +101 -49
  38. package/dist/content/read-resolve.js.map +1 -1
  39. package/dist/core/BranchReceipt.d.ts +7 -0
  40. package/dist/core/BranchReceipt.d.ts.map +1 -0
  41. package/dist/core/BranchReceipt.js +27 -0
  42. package/dist/core/BranchReceipt.js.map +1 -0
  43. package/dist/core/BudgetOverflow.d.ts +23 -0
  44. package/dist/core/BudgetOverflow.d.ts.map +1 -0
  45. package/dist/core/BudgetOverflow.js +61 -0
  46. package/dist/core/BudgetOverflow.js.map +1 -0
  47. package/dist/core/BudgetReadout.d.ts +8 -0
  48. package/dist/core/BudgetReadout.d.ts.map +1 -0
  49. package/dist/core/BudgetReadout.js +79 -0
  50. package/dist/core/BudgetReadout.js.map +1 -0
  51. package/dist/core/ChannelWrite.d.ts +28 -9
  52. package/dist/core/ChannelWrite.d.ts.map +1 -1
  53. package/dist/core/ChannelWrite.js +28 -21
  54. package/dist/core/ChannelWrite.js.map +1 -1
  55. package/dist/core/ChannelWrite.sql +11 -10
  56. package/dist/core/CoreSchemeServices.d.ts +10 -4
  57. package/dist/core/CoreSchemeServices.d.ts.map +1 -1
  58. package/dist/core/CoreSchemeServices.js +7 -1
  59. package/dist/core/CoreSchemeServices.js.map +1 -1
  60. package/dist/core/Dispatcher.d.ts +29 -20
  61. package/dist/core/Dispatcher.d.ts.map +1 -1
  62. package/dist/core/Dispatcher.js +1488 -599
  63. package/dist/core/Dispatcher.js.map +1 -1
  64. package/dist/core/DurableStatement.d.ts +6 -0
  65. package/dist/core/DurableStatement.d.ts.map +1 -0
  66. package/dist/core/DurableStatement.js +51 -0
  67. package/dist/core/DurableStatement.js.map +1 -0
  68. package/dist/core/Engine.d.ts +48 -20
  69. package/dist/core/Engine.d.ts.map +1 -1
  70. package/dist/core/Engine.js +1208 -789
  71. package/dist/core/Engine.js.map +1 -1
  72. package/dist/core/Engine.sql +309 -217
  73. package/dist/core/EnvFlags.js +1 -1
  74. package/dist/core/EnvFlags.js.map +1 -1
  75. package/dist/core/ErrorDetail.d.ts +6 -0
  76. package/dist/core/ErrorDetail.d.ts.map +1 -0
  77. package/dist/core/ErrorDetail.js +20 -0
  78. package/dist/core/ErrorDetail.js.map +1 -0
  79. package/dist/core/ExecutorRegistry.d.ts +14 -3
  80. package/dist/core/ExecutorRegistry.d.ts.map +1 -1
  81. package/dist/core/ExecutorRegistry.js +56 -30
  82. package/dist/core/ExecutorRegistry.js.map +1 -1
  83. package/dist/core/GitBranch.d.ts +20 -0
  84. package/dist/core/GitBranch.d.ts.map +1 -0
  85. package/dist/core/GitBranch.js +110 -0
  86. package/dist/core/GitBranch.js.map +1 -0
  87. package/dist/core/JournalTurn.d.ts +9 -0
  88. package/dist/core/JournalTurn.d.ts.map +1 -0
  89. package/dist/core/JournalTurn.js +14 -0
  90. package/dist/core/JournalTurn.js.map +1 -0
  91. package/dist/core/JournalTurn.sql +10 -0
  92. package/dist/core/LogBody.d.ts +17 -0
  93. package/dist/core/LogBody.d.ts.map +1 -0
  94. package/dist/core/LogBody.js +148 -0
  95. package/dist/core/LogBody.js.map +1 -0
  96. package/dist/core/LoopFlagsReader.d.ts +7 -0
  97. package/dist/core/LoopFlagsReader.d.ts.map +1 -0
  98. package/dist/core/LoopFlagsReader.js +33 -0
  99. package/dist/core/LoopFlagsReader.js.map +1 -0
  100. package/dist/core/LoopLifecycle.d.ts +8 -1
  101. package/dist/core/LoopLifecycle.d.ts.map +1 -1
  102. package/dist/core/LoopLifecycle.js +55 -9
  103. package/dist/core/LoopLifecycle.js.map +1 -1
  104. package/dist/core/LoopLifecycle.sql +9 -3
  105. package/dist/core/NoticeChannel.d.ts +13 -0
  106. package/dist/core/NoticeChannel.d.ts.map +1 -0
  107. package/dist/core/NoticeChannel.js +40 -0
  108. package/dist/core/NoticeChannel.js.map +1 -0
  109. package/dist/core/Owner.d.ts +0 -1
  110. package/dist/core/Owner.d.ts.map +1 -1
  111. package/dist/core/Owner.js +2 -5
  112. package/dist/core/Owner.js.map +1 -1
  113. package/dist/core/PacketBuilder.d.ts +25 -24
  114. package/dist/core/PacketBuilder.d.ts.map +1 -1
  115. package/dist/core/PacketBuilder.js +313 -375
  116. package/dist/core/PacketBuilder.js.map +1 -1
  117. package/dist/core/ProblemLog.d.ts +26 -0
  118. package/dist/core/ProblemLog.d.ts.map +1 -0
  119. package/dist/core/ProblemLog.js +58 -0
  120. package/dist/core/ProblemLog.js.map +1 -0
  121. package/dist/core/ProposalLifecycle.d.ts +15 -21
  122. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  123. package/dist/core/ProposalLifecycle.js +291 -78
  124. package/dist/core/ProposalLifecycle.js.map +1 -1
  125. package/dist/core/ProviderInstantiate.d.ts.map +1 -1
  126. package/dist/core/ProviderInstantiate.js +51 -48
  127. package/dist/core/ProviderInstantiate.js.map +1 -1
  128. package/dist/core/SchemeRegistry.d.ts +14 -8
  129. package/dist/core/SchemeRegistry.d.ts.map +1 -1
  130. package/dist/core/SchemeRegistry.js +189 -114
  131. package/dist/core/SchemeRegistry.js.map +1 -1
  132. package/dist/core/ServiceTeardown.d.ts +11 -0
  133. package/dist/core/ServiceTeardown.d.ts.map +1 -0
  134. package/dist/core/ServiceTeardown.js +70 -0
  135. package/dist/core/ServiceTeardown.js.map +1 -0
  136. package/dist/core/StoredPacket.d.ts +29 -0
  137. package/dist/core/StoredPacket.d.ts.map +1 -0
  138. package/dist/core/StoredPacket.js +147 -0
  139. package/dist/core/StoredPacket.js.map +1 -0
  140. package/dist/core/StrikeRail.d.ts +1 -2
  141. package/dist/core/StrikeRail.d.ts.map +1 -1
  142. package/dist/core/StrikeRail.js +25 -55
  143. package/dist/core/StrikeRail.js.map +1 -1
  144. package/dist/core/WorkerControlAddress.d.ts +17 -0
  145. package/dist/core/WorkerControlAddress.d.ts.map +1 -0
  146. package/dist/core/WorkerControlAddress.js +44 -0
  147. package/dist/core/WorkerControlAddress.js.map +1 -0
  148. package/dist/core/WorkerName.d.ts +31 -0
  149. package/dist/core/WorkerName.d.ts.map +1 -0
  150. package/dist/core/WorkerName.js +95 -0
  151. package/dist/core/WorkerName.js.map +1 -0
  152. package/dist/core/WorkerName.sql +36 -0
  153. package/dist/core/WorkspaceGate.d.ts +14 -0
  154. package/dist/core/WorkspaceGate.d.ts.map +1 -0
  155. package/dist/core/WorkspaceGate.js +155 -0
  156. package/dist/core/WorkspaceGate.js.map +1 -0
  157. package/dist/core/caps/CapsResolve.d.ts +1 -1
  158. package/dist/core/caps/CapsResolve.d.ts.map +1 -1
  159. package/dist/core/caps/CapsResolve.js.map +1 -1
  160. package/dist/core/caps/DbChannelCaps.d.ts +5 -11
  161. package/dist/core/caps/DbChannelCaps.d.ts.map +1 -1
  162. package/dist/core/caps/DbChannelCaps.js +24 -8
  163. package/dist/core/caps/DbChannelCaps.js.map +1 -1
  164. package/dist/core/caps/DbEntryCaps.d.ts +4 -13
  165. package/dist/core/caps/DbEntryCaps.d.ts.map +1 -1
  166. package/dist/core/caps/DbEntryCaps.js +15 -6
  167. package/dist/core/caps/DbEntryCaps.js.map +1 -1
  168. package/dist/core/caps/DbNotifyCaps.d.ts +1 -1
  169. package/dist/core/caps/DbNotifyCaps.d.ts.map +1 -1
  170. package/dist/core/caps/DbNotifyCaps.js +12 -11
  171. package/dist/core/caps/DbNotifyCaps.js.map +1 -1
  172. package/dist/core/caps/DbProjectionCaps.d.ts +5 -5
  173. package/dist/core/caps/DbProjectionCaps.d.ts.map +1 -1
  174. package/dist/core/caps/DbProjectionCaps.js +21 -4
  175. package/dist/core/caps/DbProjectionCaps.js.map +1 -1
  176. package/dist/core/caps/DbSubscriptionCaps.d.ts +4 -4
  177. package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -1
  178. package/dist/core/caps/DbSubscriptionCaps.js +57 -62
  179. package/dist/core/caps/DbSubscriptionCaps.js.map +1 -1
  180. package/dist/core/caps/DbTagCaps.d.ts +5 -12
  181. package/dist/core/caps/DbTagCaps.d.ts.map +1 -1
  182. package/dist/core/caps/DbTagCaps.js +14 -7
  183. package/dist/core/caps/DbTagCaps.js.map +1 -1
  184. package/dist/core/content-hash.js +1 -1
  185. package/dist/core/content-hash.js.map +1 -1
  186. package/dist/core/env-defaults.d.ts.map +1 -1
  187. package/dist/core/env-defaults.js.map +1 -1
  188. package/dist/core/fork.d.ts.map +1 -1
  189. package/dist/core/fork.js +55 -30
  190. package/dist/core/fork.js.map +1 -1
  191. package/dist/core/fork.sql +41 -27
  192. package/dist/core/git-env.d.ts +2 -0
  193. package/dist/core/git-env.d.ts.map +1 -1
  194. package/dist/core/git-env.js +13 -18
  195. package/dist/core/git-env.js.map +1 -1
  196. package/dist/core/git-iso.d.ts.map +1 -1
  197. package/dist/core/git-iso.js +9 -15
  198. package/dist/core/git-iso.js.map +1 -1
  199. package/dist/core/git-membership.d.ts +1 -1
  200. package/dist/core/git-membership.d.ts.map +1 -1
  201. package/dist/core/git-membership.js +198 -146
  202. package/dist/core/git-membership.js.map +1 -1
  203. package/dist/core/git-state.d.ts.map +1 -1
  204. package/dist/core/git-state.js +10 -11
  205. package/dist/core/git-state.js.map +1 -1
  206. package/dist/core/owner.sql +1 -1
  207. package/dist/core/packet-inject.d.ts.map +1 -1
  208. package/dist/core/packet-inject.js +7 -11
  209. package/dist/core/packet-inject.js.map +1 -1
  210. package/dist/core/packet-wire.d.ts +2 -20
  211. package/dist/core/packet-wire.d.ts.map +1 -1
  212. package/dist/core/packet-wire.js +242 -368
  213. package/dist/core/packet-wire.js.map +1 -1
  214. package/dist/core/plurnk-uri.d.ts +12 -1
  215. package/dist/core/plurnk-uri.d.ts.map +1 -1
  216. package/dist/core/plurnk-uri.js +49 -29
  217. package/dist/core/plurnk-uri.js.map +1 -1
  218. package/dist/core/results.d.ts +16 -5
  219. package/dist/core/results.d.ts.map +1 -1
  220. package/dist/core/results.js +27 -18
  221. package/dist/core/results.js.map +1 -1
  222. package/dist/core/ruler_count.d.ts +4 -0
  223. package/dist/core/ruler_count.d.ts.map +1 -0
  224. package/dist/core/ruler_count.js +7 -0
  225. package/dist/core/ruler_count.js.map +1 -0
  226. package/dist/core/scheme-types.d.ts +9 -11
  227. package/dist/core/scheme-types.d.ts.map +1 -1
  228. package/dist/core/scheme-types.js.map +1 -1
  229. package/dist/core/search-gate.d.ts.map +1 -1
  230. package/dist/core/search-gate.js +3 -11
  231. package/dist/core/search-gate.js.map +1 -1
  232. package/dist/core/teaching-corpus.d.ts +6 -0
  233. package/dist/core/teaching-corpus.d.ts.map +1 -0
  234. package/dist/core/teaching-corpus.js +23 -0
  235. package/dist/core/teaching-corpus.js.map +1 -0
  236. package/dist/core/teaching.d.ts +0 -1
  237. package/dist/core/teaching.d.ts.map +1 -1
  238. package/dist/core/teaching.js +2 -8
  239. package/dist/core/teaching.js.map +1 -1
  240. package/dist/core/token-ruler.d.ts.map +1 -1
  241. package/dist/core/token-ruler.js +3 -16
  242. package/dist/core/token-ruler.js.map +1 -1
  243. package/dist/core/turn-scheduler.d.ts +1 -1
  244. package/dist/core/turn-scheduler.d.ts.map +1 -1
  245. package/dist/core/turn-scheduler.js +1 -1
  246. package/dist/core/turn-scheduler.js.map +1 -1
  247. package/dist/core/worker-cap.d.ts +2 -4
  248. package/dist/core/worker-cap.d.ts.map +1 -1
  249. package/dist/core/worker-cap.js +13 -4
  250. package/dist/core/worker-cap.js.map +1 -1
  251. package/dist/core/{run-ops.sql → worker-ops.sql} +11 -11
  252. package/dist/core/workspace-settings.d.ts.map +1 -1
  253. package/dist/core/workspace-settings.js +17 -9
  254. package/dist/core/workspace-settings.js.map +1 -1
  255. package/dist/digest/Digest.d.ts +2 -1
  256. package/dist/digest/Digest.d.ts.map +1 -1
  257. package/dist/digest/Digest.js +337 -138
  258. package/dist/digest/Digest.js.map +1 -1
  259. package/dist/digest/digest.sql +19 -10
  260. package/dist/index.d.ts.map +1 -1
  261. package/dist/index.js +3 -5
  262. package/dist/index.js.map +1 -1
  263. package/dist/matrix/live-specimen.d.ts +9 -0
  264. package/dist/matrix/live-specimen.d.ts.map +1 -0
  265. package/dist/matrix/live-specimen.js +37 -0
  266. package/dist/matrix/live-specimen.js.map +1 -0
  267. package/dist/observe/api.d.ts +6 -0
  268. package/dist/observe/api.d.ts.map +1 -0
  269. package/dist/observe/api.js +11 -0
  270. package/dist/observe/api.js.map +1 -0
  271. package/dist/observe/init.d.ts +7 -0
  272. package/dist/observe/init.d.ts.map +1 -0
  273. package/dist/observe/init.js +159 -0
  274. package/dist/observe/init.js.map +1 -0
  275. package/dist/observe/metrics.d.ts +6 -0
  276. package/dist/observe/metrics.d.ts.map +1 -0
  277. package/dist/observe/metrics.js +15 -0
  278. package/dist/observe/metrics.js.map +1 -0
  279. package/dist/observe/spans.d.ts +4 -0
  280. package/dist/observe/spans.d.ts.map +1 -0
  281. package/dist/observe/spans.js +51 -0
  282. package/dist/observe/spans.js.map +1 -0
  283. package/dist/schemes/EffectPolicy.d.ts +1 -0
  284. package/dist/schemes/EffectPolicy.d.ts.map +1 -1
  285. package/dist/schemes/EffectPolicy.js +5 -2
  286. package/dist/schemes/EffectPolicy.js.map +1 -1
  287. package/dist/schemes/Exec.d.ts +6 -11
  288. package/dist/schemes/Exec.d.ts.map +1 -1
  289. package/dist/schemes/Exec.js +364 -247
  290. package/dist/schemes/Exec.js.map +1 -1
  291. package/dist/schemes/ExecOutputScheme.d.ts +8 -7
  292. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  293. package/dist/schemes/ExecOutputScheme.js +48 -9
  294. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  295. package/dist/schemes/File.d.ts +7 -11
  296. package/dist/schemes/File.d.ts.map +1 -1
  297. package/dist/schemes/File.js +279 -142
  298. package/dist/schemes/File.js.map +1 -1
  299. package/dist/schemes/Log.d.ts +4 -8
  300. package/dist/schemes/Log.d.ts.map +1 -1
  301. package/dist/schemes/Log.js +475 -208
  302. package/dist/schemes/Log.js.map +1 -1
  303. package/dist/schemes/Log.sql +62 -30
  304. package/dist/schemes/Prompt.d.ts +3 -2
  305. package/dist/schemes/Prompt.d.ts.map +1 -1
  306. package/dist/schemes/Prompt.js +9 -6
  307. package/dist/schemes/Prompt.js.map +1 -1
  308. package/dist/schemes/Skill.d.ts +1 -1
  309. package/dist/schemes/Skill.d.ts.map +1 -1
  310. package/dist/schemes/Skill.js +2 -3
  311. package/dist/schemes/Skill.js.map +1 -1
  312. package/dist/schemes/Worker.d.ts +8 -16
  313. package/dist/schemes/Worker.d.ts.map +1 -1
  314. package/dist/schemes/Worker.js +179 -69
  315. package/dist/schemes/Worker.js.map +1 -1
  316. package/dist/schemes/_entry-chunk.d.ts.map +1 -1
  317. package/dist/schemes/_entry-chunk.js +12 -5
  318. package/dist/schemes/_entry-chunk.js.map +1 -1
  319. package/dist/schemes/_entry-crud.d.ts +10 -9
  320. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  321. package/dist/schemes/_entry-crud.js +59 -13
  322. package/dist/schemes/_entry-crud.js.map +1 -1
  323. package/dist/schemes/_entry-crud.sql +20 -8
  324. package/dist/schemes/_entry-find.d.ts +20 -15
  325. package/dist/schemes/_entry-find.d.ts.map +1 -1
  326. package/dist/schemes/_entry-find.js +339 -174
  327. package/dist/schemes/_entry-find.js.map +1 -1
  328. package/dist/schemes/_entry-find.sql +20 -8
  329. package/dist/schemes/_entry-graph.d.ts +4 -2
  330. package/dist/schemes/_entry-graph.d.ts.map +1 -1
  331. package/dist/schemes/_entry-graph.js +55 -31
  332. package/dist/schemes/_entry-graph.js.map +1 -1
  333. package/dist/schemes/_entry-graph.sql +37 -22
  334. package/dist/schemes/_entry-manifest.d.ts +10 -15
  335. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  336. package/dist/schemes/_entry-manifest.js +50 -268
  337. package/dist/schemes/_entry-manifest.js.map +1 -1
  338. package/dist/schemes/_entry-ops.d.ts +9 -14
  339. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  340. package/dist/schemes/_entry-ops.js +149 -77
  341. package/dist/schemes/_entry-ops.js.map +1 -1
  342. package/dist/schemes/_entry-ops.sql +1 -1
  343. package/dist/schemes/_entry-semantic.d.ts +23 -8
  344. package/dist/schemes/_entry-semantic.d.ts.map +1 -1
  345. package/dist/schemes/_entry-semantic.js +141 -60
  346. package/dist/schemes/_entry-semantic.js.map +1 -1
  347. package/dist/schemes/_entry-semantic.sql +63 -45
  348. package/dist/schemes/_entry-send.d.ts +3 -4
  349. package/dist/schemes/_entry-send.d.ts.map +1 -1
  350. package/dist/schemes/_entry-send.js +48 -23
  351. package/dist/schemes/_entry-send.js.map +1 -1
  352. package/dist/schemes/_path-scope.d.ts +23 -0
  353. package/dist/schemes/_path-scope.d.ts.map +1 -0
  354. package/dist/schemes/_path-scope.js +61 -0
  355. package/dist/schemes/_path-scope.js.map +1 -0
  356. package/dist/schemes/_search-candidate.d.ts +20 -0
  357. package/dist/schemes/_search-candidate.d.ts.map +1 -0
  358. package/dist/schemes/_search-candidate.js +19 -0
  359. package/dist/schemes/_search-candidate.js.map +1 -0
  360. package/dist/schemes/_search-exclusion.d.ts +7 -0
  361. package/dist/schemes/_search-exclusion.d.ts.map +1 -0
  362. package/dist/schemes/_search-exclusion.js +23 -0
  363. package/dist/schemes/_search-exclusion.js.map +1 -0
  364. package/dist/schemes/_search-index.d.ts +6 -0
  365. package/dist/schemes/_search-index.d.ts.map +1 -0
  366. package/dist/schemes/_search-index.js +326 -0
  367. package/dist/schemes/_search-index.js.map +1 -0
  368. package/dist/schemes/cosine.js +1 -1
  369. package/dist/schemes/cosine.js.map +1 -1
  370. package/dist/schemes/exec-abort.js +3 -3
  371. package/dist/schemes/exec-abort.js.map +1 -1
  372. package/dist/schemes/exec-env.js +3 -3
  373. package/dist/schemes/exec-env.js.map +1 -1
  374. package/dist/server/BranchBatches.d.ts +48 -0
  375. package/dist/server/BranchBatches.d.ts.map +1 -0
  376. package/dist/server/BranchBatches.js +591 -0
  377. package/dist/server/BranchBatches.js.map +1 -0
  378. package/dist/server/Daemon.d.ts +36 -66
  379. package/dist/server/Daemon.d.ts.map +1 -1
  380. package/dist/server/Daemon.js +920 -446
  381. package/dist/server/Daemon.js.map +1 -1
  382. package/dist/server/DaemonModule.d.ts +31 -0
  383. package/dist/server/DaemonModule.d.ts.map +1 -0
  384. package/dist/server/DaemonModule.js +2 -0
  385. package/dist/server/DaemonModule.js.map +1 -0
  386. package/dist/server/branch-batch.sql +152 -0
  387. package/dist/server/client-input.d.ts +12 -0
  388. package/dist/server/client-input.d.ts.map +1 -1
  389. package/dist/server/client-input.js +262 -57
  390. package/dist/server/client-input.js.map +1 -1
  391. package/dist/server/dispatch-as-plurnk.d.ts +1 -1
  392. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -1
  393. package/dist/server/dispatch-as-plurnk.js +15 -7
  394. package/dist/server/dispatch-as-plurnk.js.map +1 -1
  395. package/dist/server/drain.sql +92 -62
  396. package/dist/server/envelope.d.ts +2 -5
  397. package/dist/server/envelope.d.ts.map +1 -1
  398. package/dist/server/envelope.js +119 -95
  399. package/dist/server/envelope.js.map +1 -1
  400. package/dist/server/envelope.sql +19 -23
  401. package/dist/server/exec-poll-backoff.js +1 -1
  402. package/dist/server/exec-poll-backoff.js.map +1 -1
  403. package/dist/server/lifecycle-recovery.sql +79 -2
  404. package/dist/server/logEntry.d.ts +3 -1
  405. package/dist/server/logEntry.d.ts.map +1 -1
  406. package/dist/server/logEntry.js +4 -2
  407. package/dist/server/logEntry.js.map +1 -1
  408. package/dist/server/logEntry.sql +1 -1
  409. package/dist/server/loop-model.d.ts.map +1 -1
  410. package/dist/server/loop-model.js +22 -9
  411. package/dist/server/loop-model.js.map +1 -1
  412. package/dist/server/loopDocs.d.ts.map +1 -1
  413. package/dist/server/loopDocs.js +5 -4
  414. package/dist/server/loopDocs.js.map +1 -1
  415. package/dist/server/seam-entry-read.sql +15 -10
  416. package/dist/server/seam-log-read.sql +2 -2
  417. package/dist/server/seam-loop.sql +1 -1
  418. package/dist/server/seam-proposal-list.sql +17 -7
  419. package/dist/service.d.ts.map +1 -1
  420. package/dist/service.js +66 -60
  421. package/dist/service.js.map +1 -1
  422. package/migrations/001_schema.sql +897 -0
  423. package/package.json +57 -26
  424. package/dist/core/PluginLoader.d.ts +0 -20
  425. package/dist/core/PluginLoader.d.ts.map +0 -1
  426. package/dist/core/PluginLoader.js +0 -142
  427. package/dist/core/PluginLoader.js.map +0 -1
  428. package/dist/core/TelemetryChannel.d.ts +0 -37
  429. package/dist/core/TelemetryChannel.d.ts.map +0 -1
  430. package/dist/core/TelemetryChannel.js +0 -80
  431. package/dist/core/TelemetryChannel.js.map +0 -1
  432. package/dist/core/path-decode.d.ts +0 -3
  433. package/dist/core/path-decode.d.ts.map +0 -1
  434. package/dist/core/path-decode.js +0 -9
  435. package/dist/core/path-decode.js.map +0 -1
  436. package/dist/core/plugin-attribution.d.ts +0 -5
  437. package/dist/core/plugin-attribution.d.ts.map +0 -1
  438. package/dist/core/plugin-attribution.js +0 -39
  439. package/dist/core/plugin-attribution.js.map +0 -1
  440. package/dist/core/world-state.d.ts +0 -10
  441. package/dist/core/world-state.d.ts.map +0 -1
  442. package/dist/core/world-state.js +0 -35
  443. package/dist/core/world-state.js.map +0 -1
  444. package/dist/core/world-state.sql +0 -35
  445. package/dist/core/zero-pin.d.ts +0 -3
  446. package/dist/core/zero-pin.d.ts.map +0 -1
  447. package/dist/core/zero-pin.js +0 -16
  448. package/dist/core/zero-pin.js.map +0 -1
  449. package/dist/server/auto.d.ts +0 -6
  450. package/dist/server/auto.d.ts.map +0 -1
  451. package/dist/server/auto.js +0 -63
  452. package/dist/server/auto.js.map +0 -1
  453. package/dist/server/clientTurn.d.ts +0 -6
  454. package/dist/server/clientTurn.d.ts.map +0 -1
  455. package/dist/server/clientTurn.js +0 -22
  456. package/dist/server/clientTurn.js.map +0 -1
  457. package/dist/server/clientTurn.sql +0 -10
  458. package/dist/server/noProposals.d.ts +0 -6
  459. package/dist/server/noProposals.d.ts.map +0 -1
  460. package/dist/server/noProposals.js +0 -37
  461. package/dist/server/noProposals.js.map +0 -1
  462. package/dist/server/version-info.d.ts +0 -14
  463. package/dist/server/version-info.d.ts.map +0 -1
  464. package/dist/server/version-info.js +0 -69
  465. package/dist/server/version-info.js.map +0 -1
  466. package/migrations/0000-00-00.01_schema.sql +0 -536
  467. package/migrations/0004_loop-provider.sql +0 -3
  468. package/migrations/0005_subscription-published-channel.sql +0 -3
  469. package/migrations/0006_loop-max-turns.sql +0 -3
@@ -1,12 +1,11 @@
1
- // FIND helper for entry-bearing schemes (SPEC §find; plurnk.md FIND row).
1
+ // FIND helper for entry-bearing schemes (SPEC {§find}; plurnk.md FIND row).
2
2
  // FIND resolves to the scheme's CATALOG ROWS — the very rows the manifest catalogs —
3
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).
4
+ // @graph) decides WHICH entries appear. Each selected entry appears once; its
5
+ // optional `matches` metadata records every addressable source/readable range.
6
+ // The content itself remains a READ.
8
7
  //
9
- // Slot semantics (plurnk.md §"Body matcher dispatch (FIND, READ, OPEN, FOLD)"):
8
+ // FIND slot semantics (contracts SPEC §4/§7):
10
9
  // target — required scope (path or glob); selects which entries are candidates
11
10
  // body — matcher (glob/regex/jsonpath/xpath/~semantic/@graph). A content matcher
12
11
  // runs against the entry's default-channel CONTENT (Matcher.matchAgainstContent
@@ -16,48 +15,28 @@
16
15
  // <L> — results pagination: select results N..M from the matched list
17
16
  import { LineMarkerOps } from "../content/index.js";
18
17
  import Matcher from "../content/matcher.js";
19
- import { decodePathParens } from "../core/path-decode.js";
18
+ import { entryPathnameOf } from "../core/plurnk-uri.js";
20
19
  import EntryGraph from "./_entry-graph.js";
21
20
  import EntryCrud from "./_entry-crud.js";
22
21
  import EntryManifest from "./_entry-manifest.js";
23
22
  import Owner from "../core/Owner.js";
24
23
  import EntrySemantic from "./_entry-semantic.js";
24
+ import Results from "../core/results.js";
25
+ import { resolveSearchCandidates } from "./_search-candidate.js";
26
+ import { pathFolderSummaries, pathScope, pathScopeMatches } from "./_path-scope.js";
27
+ // FIND result ordinals are also packet line coordinates. Keep each top-level
28
+ // item compact, adding only the boundary newline that makes row N addressable
29
+ // as line N while retaining one valid JSON array. {§find-result-catalog-rows}
30
+ export const renderFindContent = (results) => `[${results.map((result) => JSON.stringify(result)).join(",\n")}]`;
25
31
  export default class EntryFind {
26
32
  static #scopePathnameOf(statement) {
27
33
  const path = statement.target;
28
34
  if (path === null)
29
35
  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) };
36
+ // FIND addresses the same canonical entry identity as READ and direct
37
+ // CRUD. Both namespace authorities and network hosts are part of that
38
+ // identity and must survive the exact-entry lookup.
39
+ return entryPathnameOf(path);
61
40
  }
62
41
  static #unique(xs) {
63
42
  const seen = new Set();
@@ -73,41 +52,50 @@ export default class EntryFind {
73
52
  // order (rank for ~semantic, candidate order otherwise). Candidate selection (scope +
74
53
  // tags) runs in SQL (find_workspace_entry_candidates); a content matcher then runs against
75
54
  // 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
55
+ // plugin) and INCLUDES/EXCLUDES the entry - 200 keeps it, 204/203 drop it, and a
56
+ // 4xx matcher failure ends the whole operation. Path-scoping stays in the (target). Returns the
78
57
  // matched pathnames plus `locations` — each content hit's source line(s), keyed by pathname.
79
58
  static async #matchPathnames(statement, ctx, manifest, explicitOwnerId) {
80
- if (statement.target === null)
81
- return { status: 400, matches: [] };
59
+ if (statement.target === null) {
60
+ return {
61
+ status: 400,
62
+ matches: [],
63
+ error: "FIND requires a target.",
64
+ extensions: {
65
+ recovery: "Provide the FIND target.",
66
+ retryable: false,
67
+ },
68
+ };
69
+ }
82
70
  // Scope by the manifest's persisted entries.scheme (storedScheme; absent →
83
71
  // name). File persists under the reserved 'file' scheme ({§entry-identity-no-null}).
84
72
  const scheme = EntryCrud.identityScheme(manifest);
85
73
  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("/")) {
74
+ const scope = scopePathname === null
75
+ ? null
76
+ : pathScope(scopePathname, manifest.folderScopes === true);
77
+ // {§fs-errno} an exact-path miss is ENOENT; an empty glob or folder
78
+ // survey is a successful empty result.
79
+ if (scope?.kind === "exact" && scope.pathname.length > 0) {
93
80
  const exact = await ctx.db.crud_find_workspace_entry.get({
94
81
  workspace_id: ctx.workspaceId,
95
82
  owner_id: explicitOwnerId ?? await Owner.commonsId(ctx.db, ctx.workspaceId),
96
- scheme, pathname: scopePathname,
83
+ scheme, pathname: scope.pathname,
97
84
  });
98
- if (exact === undefined)
99
- return { status: 404, matches: [], error: `no entry at ${EntryManifest.toPath(scheme, scopePathname)}` };
85
+ if (exact === undefined) {
86
+ return {
87
+ status: 404,
88
+ matches: [],
89
+ error: `No entry exists at ${EntryManifest.toPath(scheme, scope.pathname)}.`,
90
+ extensions: { target: EntryManifest.toPath(scheme, scope.pathname) },
91
+ };
92
+ }
100
93
  }
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
94
+ // SQL receives only the literal prefix and returns a safe superset. Node's
95
+ // path matcher owns the shell-glob truth below: unlike SQLite GLOB, `*`
96
+ // cannot cross `/`, while `**` can. A declared folder scope remains a
97
+ // recursive prefix independent of glob syntax. {§find-scope-prefix-filter}
98
+ const tags = Array.isArray(statement.signal) ? statement.signal : []; // tag filter, AND semantics — {§find-tag-filter-and-semantics}
111
99
  const tagsParam = tags.length > 0 ? JSON.stringify(tags) : "[]";
112
100
  const { db, workspaceId } = ctx;
113
101
  const semantic = statement.body?.dialect === "semantic";
@@ -116,58 +104,159 @@ export default class EntryFind {
116
104
  owner_id: explicitOwnerId ?? await Owner.commonsId(db, workspaceId),
117
105
  scheme,
118
106
  ...(semantic ? {} : { channel: manifest.defaultChannel }),
119
- scope_pathname: scopeGlob,
107
+ scope_prefix: scope?.candidatePrefix ?? null,
120
108
  tags: tagsParam,
121
109
  });
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;
110
+ const candidatePathnames = statement.body === null && scope?.kind === "glob" && scope.shallowPrefix !== null
111
+ ? candidates.map((candidate) => candidate.pathname)
112
+ : undefined;
113
+ if (scope !== null) {
127
114
  try {
128
- re = new RegExp(statement.target.pattern, statement.target.flags || undefined);
115
+ candidates = candidates.filter((c) => pathScopeMatches(scope, c.pathname));
129
116
  }
130
117
  catch {
131
- return { status: 400, matches: [] };
118
+ return {
119
+ status: 400,
120
+ matches: [],
121
+ error: `The path glob '${scopePathname ?? ""}' is malformed.`,
122
+ extensions: {
123
+ target: scopePathname ?? "",
124
+ recovery: "Correct the target glob.",
125
+ retryable: false,
126
+ },
127
+ };
132
128
  }
133
- candidates = candidates.filter((c) => re.test(c.pathname));
134
129
  }
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.
130
+ // Every dialect resolves to one selection per resource. Content
131
+ // dialects already carry honest match evidence; relation dialects map
132
+ // their indexed source spans into readable TextRegions below.
137
133
  let matches;
138
134
  if (statement.body !== null && statement.body.dialect === "semantic") {
139
135
  // 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:
136
+ // other matcher. Passing entry identities into the ranker preserves ranking meaning:
141
137
  // constrain first, then rank, never rank the corpus and discard out-of-scope hits.
142
138
  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 } }));
139
+ if (mimetypes === undefined) {
140
+ return {
141
+ status: 501,
142
+ matches: [],
143
+ error: "Semantic search requires the mimetypes capability.",
144
+ extensions: {
145
+ stage: "semantic-search",
146
+ retryable: false,
147
+ },
148
+ };
149
+ }
150
+ const selection = EntrySemantic.resultSelection(statement.lineMarker);
151
+ const candidateSet = resolveSearchCandidates(candidates.map(({ pathname, deep_hash }) => ({ key: pathname, deepHash: deep_hash })));
152
+ if (candidateSet.state === "incomplete")
153
+ return {
154
+ status: 503,
155
+ matches: [],
156
+ error: `The persistent search index covers ${candidateSet.indexed} of ${candidateSet.total} selected entries.`,
157
+ extensions: {
158
+ search: candidateSet,
159
+ stage: "search-index",
160
+ recovery: "Wait for search indexing to complete before repeating the search.",
161
+ retryable: false,
162
+ },
163
+ };
164
+ const ranked = await EntrySemantic.rankCandidates(ctx.db, candidateSet.candidates, mimetypes, statement.body.raw, selection);
165
+ if (ranked.status !== 200) {
166
+ return {
167
+ status: ranked.status,
168
+ matches: [],
169
+ error: ranked.status === 501
170
+ ? "Similarity-threshold search requires an embedding provider."
171
+ : "The requested similarity threshold is outside the supported range.",
172
+ extensions: {
173
+ stage: "semantic-search",
174
+ ...(selection.threshold === null ? {} : { threshold: selection.threshold }),
175
+ recovery: ranked.status === 501
176
+ ? "Remove the decimal similarity threshold while embeddings are unavailable."
177
+ : "Use a similarity threshold greater than zero and less than one.",
178
+ retryable: false,
179
+ },
180
+ };
181
+ }
182
+ let selected = ranked.results;
183
+ if (selection.page !== null) {
184
+ const page = LineMarkerOps.page(selected, selection.page);
185
+ if (page.status !== 200) {
186
+ return {
187
+ status: page.status,
188
+ matches: [],
189
+ problem: page.problem,
190
+ range: page.range,
191
+ };
192
+ }
193
+ selected = page.items ?? [];
194
+ }
195
+ matches = await EntryFind.#addTextRegions(selected.map((x) => ({
196
+ key: x.key,
197
+ span: { lineStart: x.lineStart, lineEnd: x.lineEnd },
198
+ })), ctx, manifest, explicitOwnerId);
152
199
  }
153
200
  else if (statement.body === null) {
154
- matches = candidates.map((c) => ({ pathname: c.pathname, span: null }));
201
+ matches = candidates.map((c) => ({ pathname: c.pathname, matches: [] }));
155
202
  }
156
203
  else if (statement.body.dialect === "graph") {
157
- // @graph (plurnk-service#186): body is `@<sym` / `@>sym` / `@sym`. EntryGraph resolves
204
+ // {§relation-indexed-dialects} Body is `@<sym` / `@>sym` / `@sym`. EntryGraph resolves
158
205
  // the relation across (workspace, scheme), each as a (file, span); intersect with the
159
206
  // 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 } }));
207
+ const scopedCandidates = resolveSearchCandidates(candidates.map(({ pathname, deep_hash }) => ({ key: pathname, deepHash: deep_hash })));
208
+ if (scopedCandidates.state === "incomplete")
209
+ return {
210
+ status: 503,
211
+ matches: [],
212
+ error: `The persistent search index covers ${scopedCandidates.indexed} of ${scopedCandidates.total} selected entries.`,
213
+ extensions: {
214
+ search: scopedCandidates,
215
+ stage: "search-index",
216
+ recovery: "Wait for search indexing to complete before repeating the search.",
217
+ retryable: false,
218
+ },
219
+ };
220
+ const universeRows = await ctx.db.find_workspace_derivation_candidates.all({
221
+ workspace_id: ctx.workspaceId,
222
+ });
223
+ const universe = resolveSearchCandidates(universeRows.map(({ key, deep_hash }) => ({ key, deepHash: deep_hash })));
224
+ if (universe.state === "incomplete")
225
+ return {
226
+ status: 503,
227
+ matches: [],
228
+ error: `The persistent search index covers ${universe.indexed} of ${universe.total} entries in the relationship universe.`,
229
+ extensions: {
230
+ search: universe,
231
+ stage: "search-index",
232
+ recovery: "Wait for search indexing to complete before repeating the search.",
233
+ retryable: false,
234
+ },
235
+ };
236
+ const graph = await EntryGraph.matchCandidates(ctx.db, universe.candidates, scopedCandidates.candidates, statement.body.raw);
237
+ if (graph.status !== 200) {
238
+ return {
239
+ status: graph.status,
240
+ matches: [],
241
+ error: `The graph matcher '${statement.body.raw}' is malformed.`,
242
+ extensions: {
243
+ stage: "matcher",
244
+ dialect: "graph",
245
+ recovery: "Correct or remove the matcher.",
246
+ retryable: false,
247
+ },
248
+ };
249
+ }
250
+ matches = await EntryFind.#addTextRegions(graph.matches.map((m) => ({
251
+ key: m.key,
252
+ span: { lineStart: m.lineStart, lineEnd: m.lineEnd },
253
+ })), ctx, manifest, explicitOwnerId);
165
254
  }
166
255
  else {
167
256
  const { mimetypes } = ctx;
168
257
  if (mimetypes === undefined)
169
258
  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
259
+ // {§find-source-agnostic} — the shared content-matcher primitive (Log.find runs the same
171
260
  // one over log rows). Candidates key by pathname; each hit becomes a Match.
172
261
  const r = await Matcher.matchCandidates(statement.body, candidates.map((c) => {
173
262
  if (c.content === undefined || c.mimetype === undefined)
@@ -175,35 +264,57 @@ export default class EntryFind {
175
264
  return { key: c.pathname, content: c.content, mimetype: c.mimetype };
176
265
  }), mimetypes);
177
266
  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 } : {}) }));
267
+ return {
268
+ status: r.status,
269
+ matches: [],
270
+ problem: r.problem,
271
+ };
272
+ matches = r.matches.map((match) => ({ pathname: match.key, matches: match.matches }));
180
273
  }
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: [] };
274
+ if (statement.lineMarker !== null && statement.body?.dialect !== "semantic" && candidatePathnames === undefined) {
275
+ const page = LineMarkerOps.page(matches, statement.lineMarker);
276
+ if (page.status !== 200) {
277
+ if (statement.body !== null && matches.length === 0) {
278
+ const failure = Results.failure(`scheme:${manifest.name}`, "selection-range-unavailable", 416, `The ${statement.body.dialect} matcher selected 0 resources; <${statement.lineMarker.marks.join(",")}> cannot select from an empty result set.`, {
279
+ matches: [],
280
+ range: page.range,
281
+ }, {
282
+ stage: "selection",
283
+ dialect: statement.body.dialect,
284
+ matchedResources: 0,
285
+ range: page.range,
286
+ recovery: "Correct or remove the matcher before choosing a range.",
287
+ retryable: false,
288
+ });
289
+ if (failure.problem === undefined) {
290
+ throw new Error("FIND selection range failure has no Problem Details");
291
+ }
292
+ return {
293
+ status: failure.status,
294
+ matches: [],
295
+ problem: failure.problem,
296
+ range: page.range,
297
+ };
298
+ }
299
+ return {
300
+ status: page.status,
301
+ matches: [],
302
+ problem: page.problem,
303
+ range: page.range,
304
+ };
305
+ }
185
306
  matches = page.items ?? [];
186
307
  }
187
- return { status: 200, matches };
308
+ return { status: 200, matches, ...(scope === null ? {} : { scope }), ...(candidatePathnames === undefined ? {} : { candidatePathnames }) };
188
309
  }
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");
310
+ static async #addTextRegions(matches, ctx, manifest, explicitOwnerId) {
311
+ if (matches.every(({ span }) => span === null)) {
312
+ return [...new Set(matches.map(({ key }) => key))].map((pathname) => ({ pathname, matches: [] }));
313
+ }
194
314
  const scheme = EntryCrud.identityScheme(manifest);
195
315
  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) {
316
+ const candidates = [];
317
+ for (const pathname of new Set(matches.filter(({ span }) => span !== null).map(({ key }) => key))) {
207
318
  const row = await ctx.db.ops_read_channel.get({
208
319
  workspace_id: ctx.workspaceId,
209
320
  owner_id: ownerId,
@@ -212,89 +323,143 @@ export default class EntryFind {
212
323
  channel: manifest.defaultChannel,
213
324
  });
214
325
  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
- }
326
+ throw new Error(`EntryFind.#addTextRegions: matched entry ${pathname} has no default channel`);
327
+ candidates.push({ key: pathname, ...row });
235
328
  }
236
- return resolved;
329
+ const resolved = Matcher.addTextRegions(matches, candidates);
330
+ return resolved.map(({ key, matches: ranges }) => ({ pathname: key, matches: ranges }));
237
331
  }
238
332
  // FIND result = the scheme's catalog rows, filtered to the matched entries and kept in
239
333
  // 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
334
+ // {mimetype, tokens, lines}, tags, stream lifecycle) — FIND is the filtered, navigable slice of
335
+ // that catalog, rendered as a JSON array (application/json). {§find-result-catalog-rows}
242
336
  static async findWorkspaceEntries(statement, ctx, manifest, explicitOwnerId) {
243
337
  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);
338
+ const empty = { content: null, mimetype: null, results: [], itemsTokenTotal: 0, pathnames: [], matches: [] };
339
+ if (match.status !== 200) {
340
+ if (match.problem !== undefined) {
341
+ return Results.assert({
342
+ status: match.status,
343
+ problem: match.problem,
344
+ ...empty,
345
+ });
346
+ }
347
+ if (match.error === undefined) {
348
+ throw new Error(`EntryFind selection failed with status ${match.status} without Problem Details or a diagnostic.`);
349
+ }
350
+ 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, {
351
+ ...(match.range === undefined ? {} : { range: match.range }),
352
+ ...match.extensions,
353
+ });
354
+ }
355
+ // Internal matchers successfully return an empty candidate set. Public
356
+ // FIND owns its operation status: a matcher miss is 204, while a
357
+ // body-less empty catalog remains a successful survey. {§matcher-result-resource-selection}
358
+ if (statement.body !== null && match.matches.length === 0) {
359
+ return { status: 204, ...empty };
360
+ }
247
361
  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).
362
+ // The catalog row is keyed by its addressable path; align each selected
363
+ // resource to its row through the same EntryManifest.toPath the catalog
364
+ // uses. Resource order is preserved (rank for ~semantic).
252
365
  // {§entry-owner} — the alignment draws from the SAME owner the candidates matched, so a
253
366
  // match never pairs with a coordinate-twin sibling's catalog metadata.
254
367
  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 = [];
368
+ let results = [];
256
369
  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) {
370
+ let itemsTokenTotal = 0;
371
+ for (const m of match.matches) {
265
372
  const row = byPath.get(EntryManifest.toPath(scheme, m.pathname));
266
373
  if (row === undefined)
267
374
  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);
375
+ results.push(m.matches.length > 0 ? { ...row, matches: m.matches } : row);
376
+ matches.push(m);
377
+ itemsTokenTotal += Object.values(row.channels).reduce((sum, channel) => sum + channel.tokens, 0);
378
+ }
379
+ // A terminal single-star catalog is a one-level map. Keep real entries
380
+ // at that level and collapse deeper descendants into exact, actionable
381
+ // `dir/**` scopes. The summaries are navigation metadata, not hidden
382
+ // matches: READ(*) still fans out only over the direct real entries.
383
+ if (statement.body === null && match.scope !== undefined && match.candidatePathnames !== undefined) {
384
+ for (const folder of pathFolderSummaries(match.scope, match.candidatePathnames)) {
385
+ let tokens = 0;
386
+ let items = 0;
387
+ for (const pathname of folder.pathnames) {
388
+ const row = byPath.get(EntryManifest.toPath(scheme, pathname));
389
+ if (row === undefined)
390
+ continue;
391
+ items++;
392
+ tokens += Object.values(row.channels).reduce((sum, channel) => sum + channel.tokens, 0);
393
+ }
394
+ if (items > 0) {
395
+ results.push({ path: EntryManifest.toPath(scheme, folder.selector), items, tokens });
396
+ itemsTokenTotal += tokens;
397
+ }
273
398
  }
274
- if (!seenPath.has(m.pathname)) {
275
- seenPath.add(m.pathname);
276
- itemsTokenTotal += Object.values(row.channels).reduce((s, c) => s + c.tokens, 0);
399
+ results.sort((a, b) => a.path.localeCompare(b.path));
400
+ // `<L>` pages the catalog the model actually sees, folder summaries
401
+ // included. Only retained real-entry rows remain fan-out matches.
402
+ if (statement.lineMarker !== null) {
403
+ const page = LineMarkerOps.page(results, statement.lineMarker);
404
+ if (page.status !== 200) {
405
+ if (page.problem === undefined) {
406
+ throw new Error("FIND pagination failed without Problem Details");
407
+ }
408
+ return Results.assert({
409
+ status: page.status,
410
+ problem: page.problem,
411
+ content: null,
412
+ mimetype: null,
413
+ results: [],
414
+ itemsTokenTotal: 0,
415
+ pathnames: [],
416
+ matches: [],
417
+ });
418
+ }
419
+ results = page.items ?? [];
420
+ const retained = new Set(results.filter((item) => item.items === undefined).map((item) => item.path));
421
+ for (let i = matches.length - 1; i >= 0; i--) {
422
+ if (!retained.has(EntryManifest.toPath(scheme, matches[i].pathname)))
423
+ matches.splice(i, 1);
424
+ }
425
+ itemsTokenTotal = results.reduce((sum, item) => sum + (item.items === undefined
426
+ ? Object.values(item.channels).reduce((channelSum, channel) => channelSum + channel.tokens, 0)
427
+ : item.tokens ?? 0), 0);
277
428
  }
278
429
  }
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).
430
+ // {§find-count-not-contents}: over the independent render limit, retain
431
+ // count and aggregate weight but never the enumerated rows. Zero disables.
286
432
  const budget = Number.parseInt(process.env.PLURNK_SERVICE_FIND_MAX_MATCHES ?? "0", 10);
287
433
  if (budget > 0 && results.length > budget) {
288
- const steer = `${results.length} entries match, exceeding the render budget (${budget}) not enumerated.`;
434
+ const noun = results.some((item) => item.items !== undefined) ? "catalog items" : "entries";
435
+ const steer = `${results.length} ${noun} match, exceeding the render budget (${budget}) — not enumerated.`;
289
436
  // Count-forward means COUNT ONLY. Retaining the enumerated arrays behind a
290
437
  // terse rendered steer defeated the contract twice: callers could still fan
291
438
  // 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 };
439
+ // Omitted count + aggregate weight are the complete bounded result.
440
+ return {
441
+ status: 200,
442
+ content: steer,
443
+ mimetype: "text/markdown",
444
+ results: [],
445
+ itemsTokenTotal,
446
+ pathnames: [],
447
+ matches: [],
448
+ omittedItems: results.length,
449
+ maximumItems: budget,
450
+ };
294
451
  }
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 };
452
+ // Compact within rows; the single top-level boundary newline makes
453
+ // result ordinal N the universally numbered packet line N.
454
+ return {
455
+ status: 200,
456
+ content: renderFindContent(results),
457
+ mimetype: "application/json",
458
+ results,
459
+ itemsTokenTotal,
460
+ pathnames: matches.map(({ pathname }) => pathname),
461
+ matches,
462
+ };
298
463
  }
299
464
  }
300
465
  //# sourceMappingURL=_entry-find.js.map