@plurnk/plurnk-service 1.0.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 (343) hide show
  1. package/.env.defaults +208 -0
  2. package/INSTALL.md +69 -0
  3. package/LICENSE +21 -0
  4. package/README.md +46 -0
  5. package/SPEC.md +1511 -0
  6. package/dist/Paths.d.ts +13 -0
  7. package/dist/Paths.d.ts.map +1 -0
  8. package/dist/Paths.js +60 -0
  9. package/dist/Paths.js.map +1 -0
  10. package/dist/content/edited-span.d.ts +2 -0
  11. package/dist/content/edited-span.d.ts.map +1 -0
  12. package/dist/content/edited-span.js +33 -0
  13. package/dist/content/edited-span.js.map +1 -0
  14. package/dist/content/index.d.ts +10 -0
  15. package/dist/content/index.d.ts.map +1 -0
  16. package/dist/content/index.js +11 -0
  17. package/dist/content/index.js.map +1 -0
  18. package/dist/content/line-marker.d.ts +15 -0
  19. package/dist/content/line-marker.d.ts.map +1 -0
  20. package/dist/content/line-marker.js +21 -0
  21. package/dist/content/line-marker.js.map +1 -0
  22. package/dist/content/matcher.d.ts +44 -0
  23. package/dist/content/matcher.d.ts.map +1 -0
  24. package/dist/content/matcher.js +126 -0
  25. package/dist/content/matcher.js.map +1 -0
  26. package/dist/content/mimetype-binary.d.ts +8 -0
  27. package/dist/content/mimetype-binary.d.ts.map +1 -0
  28. package/dist/content/mimetype-binary.js +17 -0
  29. package/dist/content/mimetype-binary.js.map +1 -0
  30. package/dist/content/path-mimetype.d.ts +5 -0
  31. package/dist/content/path-mimetype.d.ts.map +1 -0
  32. package/dist/content/path-mimetype.js +15 -0
  33. package/dist/content/path-mimetype.js.map +1 -0
  34. package/dist/content/read-resolve.d.ts +20 -0
  35. package/dist/content/read-resolve.d.ts.map +1 -0
  36. package/dist/content/read-resolve.js +68 -0
  37. package/dist/content/read-resolve.js.map +1 -0
  38. package/dist/core/ChannelWrite.d.ts +100 -0
  39. package/dist/core/ChannelWrite.d.ts.map +1 -0
  40. package/dist/core/ChannelWrite.js +112 -0
  41. package/dist/core/ChannelWrite.js.map +1 -0
  42. package/dist/core/ChannelWrite.sql +84 -0
  43. package/dist/core/Db.d.ts +14 -0
  44. package/dist/core/Db.d.ts.map +1 -0
  45. package/dist/core/Db.js +7 -0
  46. package/dist/core/Db.js.map +1 -0
  47. package/dist/core/Dispatcher.d.ts +67 -0
  48. package/dist/core/Dispatcher.d.ts.map +1 -0
  49. package/dist/core/Dispatcher.js +1021 -0
  50. package/dist/core/Dispatcher.js.map +1 -0
  51. package/dist/core/Engine.d.ts +113 -0
  52. package/dist/core/Engine.d.ts.map +1 -0
  53. package/dist/core/Engine.js +1410 -0
  54. package/dist/core/Engine.js.map +1 -0
  55. package/dist/core/Engine.sql +538 -0
  56. package/dist/core/EnvFlags.d.ts +13 -0
  57. package/dist/core/EnvFlags.d.ts.map +1 -0
  58. package/dist/core/EnvFlags.js +84 -0
  59. package/dist/core/EnvFlags.js.map +1 -0
  60. package/dist/core/ExecutorRegistry.d.ts +45 -0
  61. package/dist/core/ExecutorRegistry.d.ts.map +1 -0
  62. package/dist/core/ExecutorRegistry.js +128 -0
  63. package/dist/core/ExecutorRegistry.js.map +1 -0
  64. package/dist/core/PacketBuilder.d.ts +67 -0
  65. package/dist/core/PacketBuilder.d.ts.map +1 -0
  66. package/dist/core/PacketBuilder.js +524 -0
  67. package/dist/core/PacketBuilder.js.map +1 -0
  68. package/dist/core/PluginLoader.d.ts +17 -0
  69. package/dist/core/PluginLoader.d.ts.map +1 -0
  70. package/dist/core/PluginLoader.js +97 -0
  71. package/dist/core/PluginLoader.js.map +1 -0
  72. package/dist/core/ProposalLifecycle.d.ts +59 -0
  73. package/dist/core/ProposalLifecycle.d.ts.map +1 -0
  74. package/dist/core/ProposalLifecycle.js +215 -0
  75. package/dist/core/ProposalLifecycle.js.map +1 -0
  76. package/dist/core/ProviderInstantiate.d.ts +9 -0
  77. package/dist/core/ProviderInstantiate.d.ts.map +1 -0
  78. package/dist/core/ProviderInstantiate.js +156 -0
  79. package/dist/core/ProviderInstantiate.js.map +1 -0
  80. package/dist/core/SchemeRegistry.d.ts +26 -0
  81. package/dist/core/SchemeRegistry.d.ts.map +1 -0
  82. package/dist/core/SchemeRegistry.js +205 -0
  83. package/dist/core/SchemeRegistry.js.map +1 -0
  84. package/dist/core/StrikeRail.d.ts +28 -0
  85. package/dist/core/StrikeRail.d.ts.map +1 -0
  86. package/dist/core/StrikeRail.js +165 -0
  87. package/dist/core/StrikeRail.js.map +1 -0
  88. package/dist/core/TelemetryChannel.d.ts +37 -0
  89. package/dist/core/TelemetryChannel.d.ts.map +1 -0
  90. package/dist/core/TelemetryChannel.js +77 -0
  91. package/dist/core/TelemetryChannel.js.map +1 -0
  92. package/dist/core/TokenGauge.d.ts +16 -0
  93. package/dist/core/TokenGauge.d.ts.map +1 -0
  94. package/dist/core/TokenGauge.js +58 -0
  95. package/dist/core/TokenGauge.js.map +1 -0
  96. package/dist/core/caps/CapsResolve.d.ts +5 -0
  97. package/dist/core/caps/CapsResolve.d.ts.map +1 -0
  98. package/dist/core/caps/CapsResolve.js +13 -0
  99. package/dist/core/caps/CapsResolve.js.map +1 -0
  100. package/dist/core/caps/DbChannelCaps.d.ts +16 -0
  101. package/dist/core/caps/DbChannelCaps.d.ts.map +1 -0
  102. package/dist/core/caps/DbChannelCaps.js +41 -0
  103. package/dist/core/caps/DbChannelCaps.js.map +1 -0
  104. package/dist/core/caps/DbEntryCaps.d.ts +19 -0
  105. package/dist/core/caps/DbEntryCaps.d.ts.map +1 -0
  106. package/dist/core/caps/DbEntryCaps.js +28 -0
  107. package/dist/core/caps/DbEntryCaps.js.map +1 -0
  108. package/dist/core/caps/DbNotifyCaps.d.ts +8 -0
  109. package/dist/core/caps/DbNotifyCaps.d.ts.map +1 -0
  110. package/dist/core/caps/DbNotifyCaps.js +35 -0
  111. package/dist/core/caps/DbNotifyCaps.js.map +1 -0
  112. package/dist/core/caps/DbSubscriptionCaps.d.ts +10 -0
  113. package/dist/core/caps/DbSubscriptionCaps.d.ts.map +1 -0
  114. package/dist/core/caps/DbSubscriptionCaps.js +86 -0
  115. package/dist/core/caps/DbSubscriptionCaps.js.map +1 -0
  116. package/dist/core/caps/DbTagCaps.d.ts +17 -0
  117. package/dist/core/caps/DbTagCaps.d.ts.map +1 -0
  118. package/dist/core/caps/DbTagCaps.js +37 -0
  119. package/dist/core/caps/DbTagCaps.js.map +1 -0
  120. package/dist/core/caps/SchemeCtxImpl.d.ts +18 -0
  121. package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -0
  122. package/dist/core/caps/SchemeCtxImpl.js +42 -0
  123. package/dist/core/caps/SchemeCtxImpl.js.map +1 -0
  124. package/dist/core/env-defaults.d.ts +19 -0
  125. package/dist/core/env-defaults.d.ts.map +1 -0
  126. package/dist/core/env-defaults.js +89 -0
  127. package/dist/core/env-defaults.js.map +1 -0
  128. package/dist/core/fork.d.ts +6 -0
  129. package/dist/core/fork.d.ts.map +1 -0
  130. package/dist/core/fork.js +84 -0
  131. package/dist/core/fork.js.map +1 -0
  132. package/dist/core/fork.sql +85 -0
  133. package/dist/core/git-membership.d.ts +23 -0
  134. package/dist/core/git-membership.d.ts.map +1 -0
  135. package/dist/core/git-membership.js +366 -0
  136. package/dist/core/git-membership.js.map +1 -0
  137. package/dist/core/git-state.d.ts +15 -0
  138. package/dist/core/git-state.d.ts.map +1 -0
  139. package/dist/core/git-state.js +67 -0
  140. package/dist/core/git-state.js.map +1 -0
  141. package/dist/core/packet-inject.d.ts +5 -0
  142. package/dist/core/packet-inject.d.ts.map +1 -0
  143. package/dist/core/packet-inject.js +48 -0
  144. package/dist/core/packet-inject.js.map +1 -0
  145. package/dist/core/packet-wire.d.ts +46 -0
  146. package/dist/core/packet-wire.d.ts.map +1 -0
  147. package/dist/core/packet-wire.js +453 -0
  148. package/dist/core/packet-wire.js.map +1 -0
  149. package/dist/core/path-decode.d.ts +2 -0
  150. package/dist/core/path-decode.d.ts.map +1 -0
  151. package/dist/core/path-decode.js +8 -0
  152. package/dist/core/path-decode.js.map +1 -0
  153. package/dist/core/plugin-attribution.d.ts +5 -0
  154. package/dist/core/plugin-attribution.d.ts.map +1 -0
  155. package/dist/core/plugin-attribution.js +39 -0
  156. package/dist/core/plugin-attribution.js.map +1 -0
  157. package/dist/core/plurnk-uri.d.ts +7 -0
  158. package/dist/core/plurnk-uri.d.ts.map +1 -0
  159. package/dist/core/plurnk-uri.js +52 -0
  160. package/dist/core/plurnk-uri.js.map +1 -0
  161. package/dist/core/resolveForLoop.d.ts +5 -0
  162. package/dist/core/resolveForLoop.d.ts.map +1 -0
  163. package/dist/core/resolveForLoop.js +12 -0
  164. package/dist/core/resolveForLoop.js.map +1 -0
  165. package/dist/core/results.d.ts +12 -0
  166. package/dist/core/results.d.ts.map +1 -0
  167. package/dist/core/results.js +27 -0
  168. package/dist/core/results.js.map +1 -0
  169. package/dist/core/run-cap.d.ts +8 -0
  170. package/dist/core/run-cap.d.ts.map +1 -0
  171. package/dist/core/run-cap.js +20 -0
  172. package/dist/core/run-cap.js.map +1 -0
  173. package/dist/core/run-ops.sql +43 -0
  174. package/dist/core/scheme-types.d.ts +45 -0
  175. package/dist/core/scheme-types.d.ts.map +1 -0
  176. package/dist/core/scheme-types.js +6 -0
  177. package/dist/core/scheme-types.js.map +1 -0
  178. package/dist/core/session-settings.d.ts +23 -0
  179. package/dist/core/session-settings.d.ts.map +1 -0
  180. package/dist/core/session-settings.js +55 -0
  181. package/dist/core/session-settings.js.map +1 -0
  182. package/dist/core/teaching.d.ts +3 -0
  183. package/dist/core/teaching.d.ts.map +1 -0
  184. package/dist/core/teaching.js +13 -0
  185. package/dist/core/teaching.js.map +1 -0
  186. package/dist/core/types.d.ts +3 -0
  187. package/dist/core/types.d.ts.map +1 -0
  188. package/dist/core/types.js +2 -0
  189. package/dist/core/types.js.map +1 -0
  190. package/dist/digest/Digest.d.ts +20 -0
  191. package/dist/digest/Digest.d.ts.map +1 -0
  192. package/dist/digest/Digest.js +451 -0
  193. package/dist/digest/Digest.js.map +1 -0
  194. package/dist/digest/Digest.sql +1 -0
  195. package/dist/digest/digest.sql +55 -0
  196. package/dist/index.d.ts +18 -0
  197. package/dist/index.d.ts.map +1 -0
  198. package/dist/index.js +28 -0
  199. package/dist/index.js.map +1 -0
  200. package/dist/schemes/EffectPolicy.d.ts +6 -0
  201. package/dist/schemes/EffectPolicy.d.ts.map +1 -0
  202. package/dist/schemes/EffectPolicy.js +18 -0
  203. package/dist/schemes/EffectPolicy.js.map +1 -0
  204. package/dist/schemes/Exec.d.ts +39 -0
  205. package/dist/schemes/Exec.d.ts.map +1 -0
  206. package/dist/schemes/Exec.js +510 -0
  207. package/dist/schemes/Exec.js.map +1 -0
  208. package/dist/schemes/ExecOutputScheme.d.ts +20 -0
  209. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -0
  210. package/dist/schemes/ExecOutputScheme.js +39 -0
  211. package/dist/schemes/ExecOutputScheme.js.map +1 -0
  212. package/dist/schemes/File.d.ts +42 -0
  213. package/dist/schemes/File.d.ts.map +1 -0
  214. package/dist/schemes/File.js +356 -0
  215. package/dist/schemes/File.js.map +1 -0
  216. package/dist/schemes/Known.d.ts +17 -0
  217. package/dist/schemes/Known.d.ts.map +1 -0
  218. package/dist/schemes/Known.js +40 -0
  219. package/dist/schemes/Known.js.map +1 -0
  220. package/dist/schemes/Log.d.ts +22 -0
  221. package/dist/schemes/Log.d.ts.map +1 -0
  222. package/dist/schemes/Log.js +269 -0
  223. package/dist/schemes/Log.js.map +1 -0
  224. package/dist/schemes/Log.sql +59 -0
  225. package/dist/schemes/Plurnk.d.ts +17 -0
  226. package/dist/schemes/Plurnk.d.ts.map +1 -0
  227. package/dist/schemes/Plurnk.js +46 -0
  228. package/dist/schemes/Plurnk.js.map +1 -0
  229. package/dist/schemes/Run.d.ts +25 -0
  230. package/dist/schemes/Run.d.ts.map +1 -0
  231. package/dist/schemes/Run.js +172 -0
  232. package/dist/schemes/Run.js.map +1 -0
  233. package/dist/schemes/Skill.d.ts +17 -0
  234. package/dist/schemes/Skill.d.ts.map +1 -0
  235. package/dist/schemes/Skill.js +40 -0
  236. package/dist/schemes/Skill.js.map +1 -0
  237. package/dist/schemes/Unknown.d.ts +17 -0
  238. package/dist/schemes/Unknown.d.ts.map +1 -0
  239. package/dist/schemes/Unknown.js +39 -0
  240. package/dist/schemes/Unknown.js.map +1 -0
  241. package/dist/schemes/_entry-chunk.d.ts +11 -0
  242. package/dist/schemes/_entry-chunk.d.ts.map +1 -0
  243. package/dist/schemes/_entry-chunk.js +100 -0
  244. package/dist/schemes/_entry-chunk.js.map +1 -0
  245. package/dist/schemes/_entry-crud.d.ts +31 -0
  246. package/dist/schemes/_entry-crud.d.ts.map +1 -0
  247. package/dist/schemes/_entry-crud.js +77 -0
  248. package/dist/schemes/_entry-crud.js.map +1 -0
  249. package/dist/schemes/_entry-crud.sql +101 -0
  250. package/dist/schemes/_entry-find.d.ts +32 -0
  251. package/dist/schemes/_entry-find.d.ts.map +1 -0
  252. package/dist/schemes/_entry-find.js +226 -0
  253. package/dist/schemes/_entry-find.js.map +1 -0
  254. package/dist/schemes/_entry-find.sql +54 -0
  255. package/dist/schemes/_entry-graph.d.ts +16 -0
  256. package/dist/schemes/_entry-graph.d.ts.map +1 -0
  257. package/dist/schemes/_entry-graph.js +94 -0
  258. package/dist/schemes/_entry-graph.js.map +1 -0
  259. package/dist/schemes/_entry-graph.sql +52 -0
  260. package/dist/schemes/_entry-manifest.d.ts +25 -0
  261. package/dist/schemes/_entry-manifest.d.ts.map +1 -0
  262. package/dist/schemes/_entry-manifest.js +266 -0
  263. package/dist/schemes/_entry-manifest.js.map +1 -0
  264. package/dist/schemes/_entry-ops.d.ts +32 -0
  265. package/dist/schemes/_entry-ops.d.ts.map +1 -0
  266. package/dist/schemes/_entry-ops.js +216 -0
  267. package/dist/schemes/_entry-ops.js.map +1 -0
  268. package/dist/schemes/_entry-ops.sql +31 -0
  269. package/dist/schemes/_entry-semantic.d.ts +38 -0
  270. package/dist/schemes/_entry-semantic.d.ts.map +1 -0
  271. package/dist/schemes/_entry-semantic.js +202 -0
  272. package/dist/schemes/_entry-semantic.js.map +1 -0
  273. package/dist/schemes/_entry-semantic.sql +95 -0
  274. package/dist/schemes/_entry-send.d.ts +11 -0
  275. package/dist/schemes/_entry-send.d.ts.map +1 -0
  276. package/dist/schemes/_entry-send.js +66 -0
  277. package/dist/schemes/_entry-send.js.map +1 -0
  278. package/dist/schemes/cosine.d.ts +4 -0
  279. package/dist/schemes/cosine.d.ts.map +1 -0
  280. package/dist/schemes/cosine.js +9 -0
  281. package/dist/schemes/cosine.js.map +1 -0
  282. package/dist/schemes/exec-abort.d.ts +15 -0
  283. package/dist/schemes/exec-abort.d.ts.map +1 -0
  284. package/dist/schemes/exec-abort.js +29 -0
  285. package/dist/schemes/exec-abort.js.map +1 -0
  286. package/dist/schemes/exec-env.d.ts +5 -0
  287. package/dist/schemes/exec-env.d.ts.map +1 -0
  288. package/dist/schemes/exec-env.js +34 -0
  289. package/dist/schemes/exec-env.js.map +1 -0
  290. package/dist/server/Daemon.d.ts +244 -0
  291. package/dist/server/Daemon.d.ts.map +1 -0
  292. package/dist/server/Daemon.js +1119 -0
  293. package/dist/server/Daemon.js.map +1 -0
  294. package/dist/server/client-input.d.ts +11 -0
  295. package/dist/server/client-input.d.ts.map +1 -0
  296. package/dist/server/client-input.js +145 -0
  297. package/dist/server/client-input.js.map +1 -0
  298. package/dist/server/clientTurn.d.ts +6 -0
  299. package/dist/server/clientTurn.d.ts.map +1 -0
  300. package/dist/server/clientTurn.js +23 -0
  301. package/dist/server/clientTurn.js.map +1 -0
  302. package/dist/server/clientTurn.sql +10 -0
  303. package/dist/server/dispatch-as-plurnk.d.ts +7 -0
  304. package/dist/server/dispatch-as-plurnk.d.ts.map +1 -0
  305. package/dist/server/dispatch-as-plurnk.js +23 -0
  306. package/dist/server/dispatch-as-plurnk.js.map +1 -0
  307. package/dist/server/drain.sql +124 -0
  308. package/dist/server/envelope.d.ts +53 -0
  309. package/dist/server/envelope.d.ts.map +1 -0
  310. package/dist/server/envelope.js +172 -0
  311. package/dist/server/envelope.js.map +1 -0
  312. package/dist/server/envelope.sql +76 -0
  313. package/dist/server/logEntry.d.ts +35 -0
  314. package/dist/server/logEntry.d.ts.map +1 -0
  315. package/dist/server/logEntry.js +49 -0
  316. package/dist/server/logEntry.js.map +1 -0
  317. package/dist/server/logEntry.sql +10 -0
  318. package/dist/server/loopDocs.d.ts +6 -0
  319. package/dist/server/loopDocs.d.ts.map +1 -0
  320. package/dist/server/loopDocs.js +22 -0
  321. package/dist/server/loopDocs.js.map +1 -0
  322. package/dist/server/noProposals.d.ts +6 -0
  323. package/dist/server/noProposals.d.ts.map +1 -0
  324. package/dist/server/noProposals.js +37 -0
  325. package/dist/server/noProposals.js.map +1 -0
  326. package/dist/server/seam-entry-read.sql +21 -0
  327. package/dist/server/seam-log-read.sql +21 -0
  328. package/dist/server/seam-loop.sql +9 -0
  329. package/dist/server/seam-proposal-list.sql +13 -0
  330. package/dist/server/version-info.d.ts +14 -0
  331. package/dist/server/version-info.d.ts.map +1 -0
  332. package/dist/server/version-info.js +69 -0
  333. package/dist/server/version-info.js.map +1 -0
  334. package/dist/server/yolo.d.ts +6 -0
  335. package/dist/server/yolo.d.ts.map +1 -0
  336. package/dist/server/yolo.js +64 -0
  337. package/dist/server/yolo.js.map +1 -0
  338. package/dist/service.d.ts +6 -0
  339. package/dist/service.d.ts.map +1 -0
  340. package/dist/service.js +309 -0
  341. package/dist/service.js.map +1 -0
  342. package/migrations/0000-00-00.01_schema.sql +500 -0
  343. package/package.json +86 -0
@@ -0,0 +1,538 @@
1
+ -- Engine SQL. SPEC §arch (architecture), §scheme (op dispatch + log).
2
+
3
+ -- PREP: engine_loop_status
4
+ SELECT status FROM loops WHERE id = $loop_id;
5
+
6
+ -- PREP: engine_run_has_live_child
7
+ -- A non-terminal CHILD run (run:// spawn/fork set parent_run_id) — a "live thing the run holds",
8
+ -- like an open stream. A SEND[200] while one exists is a premature-terminate (§send-premature-terminate).
9
+ -- Live = a child whose LATEST loop is still pending/running/parked (100/102/202) — the SAME definition
10
+ -- engine_child_runs_live uses for the Child Runs orientation, so the 409 gate and the section the model
11
+ -- reads NEVER disagree: a refused termination is always backed by a child the model can SEE and KILL
12
+ -- (§child-orientation). An inherited/historical loop (a fork copies the parent's loops) is not the
13
+ -- latest, so it never makes a concluded child look forever-live.
14
+ SELECT 1 AS live FROM runs r
15
+ JOIN loops l ON l.id = (SELECT id FROM loops WHERE run_id = r.id ORDER BY sequence DESC, id DESC LIMIT 1)
16
+ WHERE r.parent_run_id = $run_id AND l.status IN (100, 102, 202) LIMIT 1;
17
+
18
+ -- PREP: engine_count_active_loops_for_run
19
+ -- Wake-on-completion uses this to decide whether to open a new loop or
20
+ -- let the existing one pick up the channel transition at the next turn
21
+ -- boundary. Status 102 = "in progress" (any non-terminal state).
22
+ SELECT COUNT(*) AS n FROM loops WHERE run_id = $run_id AND status = 102;
23
+
24
+ -- PREP: engine_get_loop_flags
25
+ -- Loads the loop's persisted flags (json). Default '{}'; YOLO listener and
26
+ -- SchemeRegistry.resolveForLoop merge over DEFAULT_LOOP_FLAGS for missing
27
+ -- fields. Migration 014.
28
+ SELECT flags FROM loops WHERE id = $loop_id;
29
+
30
+ -- PREP: engine_set_loop_flags
31
+ -- Updates the loop's persisted flags (json). Called by loop.run RPC handler.
32
+ UPDATE loops SET flags = $flags WHERE id = $loop_id;
33
+
34
+ -- PREP: engine_tag_loop_attributions
35
+ -- #249 — tag the loop with its active plugins' attribution tags (string[] JSON), write-once: the
36
+ -- active set is loop-stable, so the `= '[]'` guard keeps later turns from rewriting it.
37
+ UPDATE loops SET attributions = $attributions WHERE id = $loop_id AND attributions = '[]';
38
+
39
+ -- PREP: engine_set_loop_open_paths
40
+ -- #260 — persist the loop.run-passed @file paths (string[] JSON) on the loop before the drain
41
+ -- starts, so runTurn foists a turn-0 READ of each (same seam as the #250 AGENTS.md auto-read).
42
+ UPDATE loops SET open_paths = $open_paths WHERE id = $loop_id;
43
+
44
+ -- PREP: engine_get_loop_open_paths
45
+ -- #260 — runTurn reads the loop's @file foist-paths at turn 0.
46
+ SELECT open_paths FROM loops WHERE id = $loop_id;
47
+
48
+ -- PREP: engine_get_loop_prompt
49
+ -- Loop's prompt + sequence — runTurn reads it on turn 1 to foist a
50
+ -- system-origin EDIT against plurnk://prompt/<run>/<loop>/1 (§packet), at the
51
+ -- turn's first action sequence. Prompts are first-class log entries
52
+ -- (no synthetic / shim layer).
53
+ SELECT prompt, sequence FROM loops WHERE id = $loop_id;
54
+
55
+ -- PREP: engine_reclaim_queued_loop
56
+ -- §run-lifecycle-wake-requeue-not-terminal — atomic 100→102 re-claim by loop id. A wake
57
+ -- re-queued this loop while ITS OWN live drain was between turns; the drain re-claims and
58
+ -- keeps running (the injected prompt is already the next turn). Conditional so a racing
59
+ -- claimant can never double-claim.
60
+ UPDATE loops SET status = 102 WHERE id = $loop_id AND status = 100;
61
+
62
+ -- PREP: engine_loop_set_status
63
+ -- The universal terminal setter. terminal_message carries either the loop's deliverable
64
+ -- (the SEND body) or the engine's abandonment reason (max_turns / budget_overflow /
65
+ -- strike_threshold) — rides the §run-scheme delta.
66
+ UPDATE loops SET status = $status, terminal_message = $message WHERE id = $loop_id;
67
+
68
+ -- PREP: engine_loop_mark_terminated_by
69
+ -- #379/#380 — name the engine/client act on a terminal the model didn't choose: 'collapse'
70
+ -- (∅-wait conclude) or 'cancel' (external loop.cancel). Stamped right after the terminal
71
+ -- setter by those two paths only; the model's own terminals leave it NULL.
72
+ UPDATE loops SET terminated_by = $terminated_by WHERE id = $loop_id;
73
+
74
+ -- PREP: engine_loop_cancel_external
75
+ -- #380 — an external cancel writes the loop's terminal ROW (a dead loop must never read as
76
+ -- live 102 — the #311 rule, applied to the 499 path; before this, the 499 existed only in the
77
+ -- broadcast) with the cancel's provenance: terminated_by='cancel', the reason as the
78
+ -- abandonment message. Conditional on non-terminal so a KILL-then-abort race never rewrites
79
+ -- an already-terminal row.
80
+ UPDATE loops SET status = 499, terminal_message = $message, terminated_by = 'cancel'
81
+ WHERE id = $loop_id AND status NOT IN (200, 413, 429, 499, 500, 504, 508);
82
+
83
+ -- PREP: engine_run_cancel_live_loops
84
+ -- #380, the PARKED case — a 202-blocked loop has no drain to observe the abort (the drain
85
+ -- tears down on 202), so loop.cancel terminalizes the run's live loops itself. 102/202 only:
86
+ -- queued (100) loops stay enqueued per §methods-loop-cancel. RETURNING feeds the
87
+ -- loop/terminated broadcast for exactly the loops this cancel killed.
88
+ UPDATE loops SET status = 499, terminal_message = $message, terminated_by = 'cancel'
89
+ WHERE run_id = $run_id AND status IN (102, 202)
90
+ RETURNING id;
91
+
92
+ -- PREP: engine_terminate_run_live_loops
93
+ -- §op-synchronous — KILL(run) is a DECISIVE op, not a fork/spawn/stream, so it must complete
94
+ -- before the turn moves on. Synchronously flip every LIVE loop of the run to 499 (killed) so the
95
+ -- same-turn premature-terminate gate (engine_run_has_live_child) sees it dead immediately; the
96
+ -- physical scope reap (drain abort, stream teardown) then proceeds async via cancelRun. The
97
+ -- loops_stamp_terminated_at trigger stamps terminated_at on the 499 transition (the §run-scheme delta).
98
+ UPDATE loops SET status = 499, terminal_message = $message
99
+ WHERE run_id = $run_id AND status IN (100, 102, 202);
100
+
101
+ -- PREP: session_get_settings
102
+ -- #231 — the session's client-chosen open-context bag ({ manifestItems?, mdDocs? }),
103
+ -- read at turn-0 with precedence over env.
104
+ SELECT settings FROM sessions WHERE id = $session_id;
105
+
106
+ -- PREP: engine_target_diverged_this_turn
107
+ -- #note10 — did this entry diverge on disk THIS turn? A source=file env-delta for the
108
+ -- target, materialized into this run's log at the current turn, means the model's view
109
+ -- predates the ambient change — a YOLO auto-accept of a same-turn EDIT would clobber it.
110
+ SELECT 1 AS hit
111
+ FROM log_entries
112
+ WHERE run_id = $run_id AND turn_id = $turn_id
113
+ AND origin = 'plurnk' AND source = 'file' AND op = 'EDIT'
114
+ AND scheme IS $scheme AND pathname = $pathname
115
+ LIMIT 1;
116
+
117
+ -- PREP: engine_list_session_entry_tags
118
+ -- #note13 — every (entry, tag) in the session, for the manifest catalog's tags field.
119
+ SELECT et.entry_id, et.tag
120
+ FROM entry_tags et
121
+ JOIN entries e ON e.id = et.entry_id
122
+ WHERE e.session_id = $session_id
123
+ ORDER BY et.entry_id, et.tag;
124
+
125
+ -- PREP: engine_list_run_entries
126
+ -- §run-scheme — the building run's OWN run-scope entries (catalogRowsFor source for a run-scope
127
+ -- FIND/foist). Byte-for-byte engine_list_session_entries but scope='run' + an owner-prefix glob
128
+ -- (`/<owner>/*`) so it yields exactly one run's scratch — its perspective, not a sibling's. Additive.
129
+ SELECT e.id AS entry_id, e.scheme, e.pathname, ec.name AS channel, ec.content, ec.mimetype, COALESCE(tc.tokens, ec.tokens) AS tokens, e.deep_hash,
130
+ CAST(unixepoch('now') - unixepoch(s.opened_at) AS INTEGER) AS seconds
131
+ FROM entries e
132
+ JOIN entry_channels ec ON ec.entry_id = e.id
133
+ LEFT JOIN token_counts tc ON tc.content_hash = ec.content_hash AND tc.tokenizer_id = $tokenizer_id
134
+ LEFT JOIN subscriptions s ON s.entry_id = e.id AND s.closed_at IS NULL
135
+ WHERE e.scope = 'run' AND e.session_id = $session_id AND e.pathname GLOB $owner_prefix
136
+ ORDER BY e.updated_at ASC, e.id ASC, ec.name;
137
+
138
+ -- PREP: engine_list_run_entry_tags
139
+ -- §run-scheme — (entry, tag) for the building run's own run-scope entries (the run-scope catalog's tags field).
140
+ SELECT et.entry_id, et.tag
141
+ FROM entry_tags et
142
+ JOIN entries e ON e.id = et.entry_id
143
+ WHERE e.session_id = $session_id AND e.scope = 'run' AND e.pathname GLOB $owner_prefix
144
+ ORDER BY et.entry_id, et.tag;
145
+
146
+ -- PREP: engine_run_scratch_count
147
+ -- §run-scheme — distinct run-scope entry count owned by the building run, to decide whether the
148
+ -- turn-0 catalog foists a FIND(run:///**) (a run with no scratch foists nothing).
149
+ SELECT COUNT(DISTINCT e.id) AS entries
150
+ FROM entries e
151
+ WHERE e.scope = 'run' AND e.session_id = $session_id AND e.pathname GLOB $owner_prefix;
152
+
153
+ -- PREP: engine_next_turn_sequence
154
+ SELECT COALESCE(MAX(sequence), 0) + 1 AS next FROM turns WHERE loop_id = $loop_id;
155
+
156
+ -- PREP: engine_loop_usage
157
+ -- Per-loop usage totals — SUM the loop's turns (§tokenomics stores usage per turn).
158
+ -- Surfaced on loop.run + loop/terminated (#197). `context` is the LAST turn's prompt tokens — the
159
+ -- honest window-occupancy numerator (#263), distinct from the summed `prompt` (which overcounts a
160
+ -- context that grows across turns).
161
+ SELECT COALESCE(SUM(usage_prompt), 0) AS prompt,
162
+ COALESCE(SUM(usage_completion), 0) AS completion,
163
+ COALESCE(SUM(usage_cost_pico), 0) AS cost_pico,
164
+ (SELECT usage_prompt FROM turns WHERE loop_id = $loop_id ORDER BY sequence DESC LIMIT 1) AS context,
165
+ -- #274 — the LAST turn's model window (denominator), so numerator + denominator come from
166
+ -- the same loop/model; NULL when the provider reports no window.
167
+ (SELECT usage_context_size FROM turns WHERE loop_id = $loop_id ORDER BY sequence DESC LIMIT 1) AS context_size,
168
+ -- #252 — the opaque provider meta blob from the LATEST turn (e.g. balancePico, a
169
+ -- point-in-time snapshot; latest wins). Service-unenforced passthrough to the client.
170
+ (SELECT meta FROM turns WHERE loop_id = $loop_id ORDER BY sequence DESC LIMIT 1) AS meta
171
+ FROM turns WHERE loop_id = $loop_id;
172
+
173
+ -- PREP: engine_loop_turn_seqs
174
+ -- Look up (loop_seq, turn_seq) for a given (loop_id, turn_id). Used by
175
+ -- #writeLog when an op needs to address itself or its output by log
176
+ -- coordinate (e.g. EXEC's stream entry at exec:///<loop_seq>/<turn_seq>/<sequence>/EXEC).
177
+ SELECT l.sequence AS loop_seq, t.sequence AS turn_seq
178
+ FROM loops l, turns t
179
+ WHERE l.id = $loop_id AND t.id = $turn_id;
180
+
181
+ -- PREP: engine_open_turn
182
+ -- Turn-as-container model: insert a turn row at runTurn open with a
183
+ -- placeholder packet and status=102 (in-progress). Pre-model writes
184
+ -- (the user prompt; later, system signals/telemetry events) land into
185
+ -- this row before the provider is called. The turn is then "closed"
186
+ -- via engine_close_turn with the final packet + status + usage stats
187
+ -- after dispatch completes.
188
+ INSERT INTO turns (loop_id, sequence, status, packet)
189
+ VALUES ($loop_id, $sequence, 102, '{}')
190
+ RETURNING id;
191
+
192
+ -- PREP: engine_close_turn
193
+ -- Updates the turn with the response packet, terminal status, and
194
+ -- provider usage stats once dispatch is complete. Paired with
195
+ -- engine_open_turn at runTurn boundaries.
196
+ UPDATE turns SET
197
+ status = $status,
198
+ packet = $packet,
199
+ usage_prompt = $usage_prompt,
200
+ usage_completion = $usage_completion,
201
+ usage_reasoning = $usage_reasoning,
202
+ usage_cached = $usage_cached,
203
+ usage_cost_pico = $usage_cost_pico,
204
+ usage_context_size = $usage_context_size,
205
+ finish_reason = $finish_reason,
206
+ model = $model,
207
+ meta = $meta
208
+ WHERE id = $id;
209
+
210
+ -- PREP: engine_list_session_entries
211
+ -- Every entry of a session — all schemes, all channels — the source behind the entry
212
+ -- catalog (catalogRowsFor / FIND) and the per-turn derivation pump (maintainDerivations).
213
+ -- Session-scoped (persists across runs); FOLD doesn't drop from the catalog.
214
+ -- `seconds` is the live age of an active stream: now − the open subscription's
215
+ -- opened_at (closed_at IS NULL). NULL for static entries. unixepoch parses the
216
+ -- stored '...%fZ' timestamp directly; re-evaluated every render like tokens.
217
+ SELECT e.id AS entry_id, e.scheme, e.pathname, ec.name AS channel, ec.content, ec.mimetype, COALESCE(tc.tokens, ec.tokens) AS tokens, e.deep_hash,
218
+ CAST(unixepoch('now') - unixepoch(s.opened_at) AS INTEGER) AS seconds
219
+ FROM entries e
220
+ JOIN entry_channels ec ON ec.entry_id = e.id
221
+ LEFT JOIN token_counts tc ON tc.content_hash = ec.content_hash AND tc.tokenizer_id = $tokenizer_id
222
+ LEFT JOIN subscriptions s ON s.entry_id = e.id AND s.closed_at IS NULL
223
+ -- entries are session-scoped, shared across runs — §machine-processes-one-filesystem
224
+ WHERE e.scope = 'session' AND e.session_id = $session_id
225
+ -- User Note 5 — mtime-ascending: dormant entries hold the stable prompt-cache prefix; churn clusters at the tail.
226
+ ORDER BY e.updated_at ASC, e.id ASC, ec.name;
227
+
228
+ -- PREP: engine_scheme_catalog_summary
229
+ -- Per-scheme entry tally (distinct count; scheme=null → file). Sources the turn-0 per-scheme
230
+ -- foist so the model sees which schemes hold content without running FIND(known://**) itself;
231
+ -- the foist FIND carries each scheme's live token weight.
232
+ SELECT e.scheme AS scheme,
233
+ COUNT(DISTINCT e.id) AS entries
234
+ FROM entries e
235
+ JOIN entry_channels ec ON ec.entry_id = e.id
236
+ WHERE e.scope = 'session' AND e.session_id = $session_id
237
+ GROUP BY e.scheme
238
+ ORDER BY e.scheme;
239
+
240
+ -- PREP: engine_run_prior_turn_time
241
+ -- §env-delta — timestamp of this run's most recent turn BEFORE the current one
242
+ -- (the "since I last looked" boundary). NULL on the run's first turn → no deltas.
243
+ SELECT MAX(t.timestamp) AS since
244
+ FROM turns t JOIN loops l ON l.id = t.loop_id
245
+ WHERE l.run_id = $run_id AND t.id != $turn_id;
246
+
247
+ -- PREP: engine_pull_env_deltas
248
+ -- §env-delta — other actors' resolved EDITs on shared entries since this run last
249
+ -- looked. Real edits (origin model/client) AND the plurnk run's fs-sync fictions
250
+ -- (origin=plurnk on the reserved 'plurnk' run); excludes this run's own rows and
251
+ -- other runs' already-materialized deltas (origin=plurnk on a real run). plurnk:///
252
+ -- entries (manifest/prompt/doc) never surface. This is the environment door (§actor-boundary-two-doors); the voice door is inject.
253
+ SELECT le.run_id, le.scheme, le.pathname, le.rx, le.source
254
+ FROM log_entries le
255
+ JOIN runs r ON r.id = le.run_id
256
+ WHERE r.session_id = $session_id
257
+ AND le.op = 'EDIT'
258
+ AND le.state = 'resolved'
259
+ AND le.status_rx IN (200, 201)
260
+ AND (le.scheme IS NULL OR le.scheme != 'plurnk')
261
+ AND le.run_id != $run_id
262
+ AND le.at > $since
263
+ AND (le.origin != 'plurnk'
264
+ OR le.run_id = (SELECT id FROM runs WHERE session_id = $session_id AND name = 'plurnk'))
265
+ ORDER BY le.at;
266
+
267
+ -- PREP: engine_insert_env_delta
268
+ -- §env-delta — materialize a pulled cross-actor edit as a FOLDED delta (expanded=0)
269
+ -- in this run's log. origin=plurnk; source carries the cause (sibling run id or
270
+ -- 'file'); rx reuses the originating row's result span (§edit-result-render).
271
+ INSERT INTO log_entries (
272
+ run_id, loop_id, turn_id, sequence, origin, source,
273
+ op, scheme, pathname, tx, mimetype_tx, rx, mimetype_rx, status_rx, expanded
274
+ ) VALUES (
275
+ $run_id, $loop_id, $turn_id, $sequence, 'plurnk', $source,
276
+ 'EDIT', $scheme, $pathname, '', 'text/plain', $rx, 'application/json', 200, 0
277
+ );
278
+
279
+ -- PREP: engine_run_stream_channels
280
+ -- §exec-stream — every stream channel the run owns (an EXEC's stdout/stderr live on the
281
+ -- runtime-tag entry), with content + state + coordinate, so the per-turn injector can emit the
282
+ -- channel's unshown byte-delta. Stays listed until its last delta is shown (cursor == content len).
283
+ SELECT s.id AS subscription_id, e.scheme AS runtime, e.pathname AS coord,
284
+ ec.name AS channel, ec.content AS content, ec.state AS state, s.close_status AS close_status
285
+ FROM subscriptions s
286
+ JOIN entries e ON e.id = s.entry_id
287
+ JOIN entry_channels ec ON ec.entry_id = s.entry_id
288
+ WHERE s.run_id = $run_id
289
+ ORDER BY s.id, ec.name;
290
+
291
+ -- PREP: engine_stream_cursor
292
+ -- §exec-stream — bytes of this channel already shown to the run: the streamEnd recorded on its
293
+ -- latest foisted delta (the caller defaults to 0 when none exists yet).
294
+ SELECT attrs
295
+ FROM log_entries
296
+ WHERE run_id = $run_id AND origin = 'plurnk' AND op = 'READ'
297
+ AND scheme = $scheme AND pathname = $pathname AND fragment = $fragment
298
+ ORDER BY id DESC LIMIT 1;
299
+
300
+ -- PREP: engine_insert_stream_delta
301
+ -- §exec-stream / §env-delta — materialize a channel's unshown byte-delta as a
302
+ -- foisted READ@200 row (the model READs the stream it never typed). origin=plurnk; fragment is
303
+ -- the channel; attrs.streamEnd is the next turn's cursor; expanded=1 when the channel has CLOSED
304
+ -- (the terminal delta auto-OPENs), 0 while it streams (ongoing deltas fold). §exec-stream
305
+ INSERT INTO log_entries (
306
+ run_id, loop_id, turn_id, sequence, origin, source,
307
+ op, scheme, pathname, fragment, tx, mimetype_tx, rx, mimetype_rx, status_rx, attrs, expanded
308
+ ) VALUES (
309
+ $run_id, $loop_id, $turn_id, $sequence, 'plurnk', NULL,
310
+ 'READ', $scheme, $pathname, $fragment, '', 'text/plain', $rx, 'application/json', 200, $attrs, $expanded
311
+ );
312
+
313
+ -- PREP: engine_pull_loop_terminations
314
+ -- §run-scheme — sibling runs' loops that reached a terminal status since this run last
315
+ -- looked (the loop-termination ambient delta). Carries terminal_message — the SEND[200]
316
+ -- deliverable or the abandonment reason — plus terminated_by so a collapse/cancel renders
317
+ -- its marker (#379). Excludes this run's own loops.
318
+ SELECT l.run_id, r.name AS run_name, l.status, l.prompt, l.terminal_message, l.terminated_by
319
+ FROM loops l
320
+ JOIN runs r ON r.id = l.run_id
321
+ WHERE r.session_id = $session_id
322
+ AND l.terminated_at IS NOT NULL
323
+ AND l.terminated_at > $since
324
+ AND l.run_id != $run_id
325
+ ORDER BY l.terminated_at;
326
+
327
+ -- PREP: engine_insert_loop_termination_delta
328
+ -- §run-scheme — materialize a sibling's loop-termination as a delta: a SEND from
329
+ -- run:///<name> carrying the terminal status + message (the deliverable). origin=plurnk,
330
+ -- source=the terminated run — uniform with the env-delta. Born OPEN for a 2xx deliverable
331
+ -- (a child's success must reach the parent open + awakening), folded otherwise.
332
+ INSERT INTO log_entries (
333
+ run_id, loop_id, turn_id, sequence, origin, source,
334
+ op, scheme, pathname, tx, mimetype_tx, rx, mimetype_rx, status_rx, expanded
335
+ ) VALUES (
336
+ $run_id, $loop_id, $turn_id, $sequence, 'plurnk', $source,
337
+ 'SEND', 'run', $pathname, '', 'text/plain', $rx, 'text/markdown', $status,
338
+ CASE WHEN $status >= 200 AND $status < 300 THEN 1 ELSE 0 END
339
+ );
340
+
341
+ -- PREP: engine_entry_tags
342
+ SELECT tag FROM entry_tags WHERE entry_id = $entry_id ORDER BY tag;
343
+
344
+ -- PREP: engine_child_runs_live
345
+ -- The run's LIVE child runs — latest loop non-terminal (100 pending / 102 processing / 202 parked).
346
+ -- Powers the Child Runs orienting section (§child-orientation): terse `* <status> run://<name>`
347
+ -- pointers so the model SEES what it holds live and reasons for itself (READ/KILL), never told to.
348
+ -- Empty → section omitted.
349
+ SELECT r.name, l.status
350
+ FROM runs r
351
+ JOIN loops l ON l.id = (SELECT id FROM loops WHERE run_id = r.id ORDER BY sequence DESC, id DESC LIMIT 1)
352
+ WHERE r.parent_run_id = $run_id AND l.status IN (100, 102, 202)
353
+ ORDER BY r.name;
354
+
355
+ -- PREP: engine_child_streams_open
356
+ -- The run's OPEN streams (subscriptions not yet closed) — their addressable coord. Powers the Child
357
+ -- Streams orienting section (§child-orientation): terse `* active <runtime>:///<coord>` pointers the
358
+ -- model OPENs/READs/KILLs. Empty → section omitted.
359
+ SELECT s.scheme, e.pathname
360
+ FROM subscriptions s
361
+ JOIN entries e ON e.id = s.entry_id
362
+ WHERE s.run_id = $run_id AND s.closed_at IS NULL
363
+ ORDER BY e.pathname;
364
+
365
+ -- PREP: engine_render_telemetry_errors
366
+ -- SPEC §telemetry: 4xx/5xx log rows are mirrored into the packet's telemetry as
367
+ -- LogCoordinate pointers, forcing the model to confront failures instead of letting
368
+ -- them rot in log:///. Window = the current turn AND the immediately-prior one
369
+ -- (>= current_turn_seq - 1): prior-turn for action failures the model just caused,
370
+ -- current-turn so a same-turn engine error (the grinder's budget-overflow row, minted
371
+ -- pre-generate then re-derived) surfaces THIS turn rather than a turn late.
372
+ -- §telemetry-uniform-error-channel
373
+ SELECT
374
+ le.op, le.sequence, le.status_rx, le.rx, le.mimetype_rx,
375
+ le.scheme, le.pathname,
376
+ t.sequence AS turn_seq, l.sequence AS loop_seq
377
+ FROM log_entries le
378
+ JOIN turns t ON t.id = le.turn_id
379
+ JOIN loops l ON l.id = le.loop_id
380
+ WHERE le.loop_id = $loop_id
381
+ AND le.status_rx >= 400
382
+ -- §log-row-self-explains: every >=400 row points at ITSELF — the op row carries its failure
383
+ -- message on its meta line (packet-wire), so the pointer leads to a record that states its why.
384
+ AND t.sequence >= $current_turn_seq - 1
385
+ ORDER BY t.sequence, le.sequence;
386
+
387
+ -- PREP: engine_grinder_fold_newest_turn
388
+ -- §grinder-layer1-rollback — THE DOCTRINE: the log is the model's memory and the model ALONE
389
+ -- curates it (FOLD/KILL). The grinder never touches history — it only blocks NEW memories from
390
+ -- landing when there is no room: one set-op folds the still-open rows of the newest turn
391
+ -- boundary — the immediately-prior turn's emissions and the current turn's pre-model rows
392
+ -- (foists, wake surfaces). Turn 1 is the same rule (no prior turn; its foists are the newest).
393
+ -- Folded, never deleted; op='error' rows are EXEMPT (§grinder-errors-exempt), and so is the
394
+ -- user PROMPT (#382 — the task frame the engine foisted is not the model's curatable memory;
395
+ -- the engine never reclaims the definition of the task it set).
396
+ UPDATE log_entries SET expanded = 0
397
+ WHERE loop_id = $loop_id AND expanded = 1 AND op != 'error'
398
+ AND NOT (COALESCE(scheme, '') = 'plurnk' AND COALESCE(pathname, '') LIKE '/prompt/%') -- NULL-safe: a model row's scheme is NULL
399
+ AND (turn_id = $turn_id
400
+ OR turn_id = (SELECT MAX(id) FROM turns WHERE loop_id = $loop_id AND id < $turn_id));
401
+
402
+ -- PREP: engine_fold_log_entry
403
+ -- §prompt-fold (User Note 6): fold a single log row by id — collapse to its
404
+ -- coordinate, body elided in the render, re-OPENable. Used for the foisted prompt
405
+ -- EDIT, which duplicates packet.user.prompt: logged for forensics, born folded.
406
+ UPDATE log_entries SET expanded = 0 WHERE id = $id;
407
+
408
+ -- PREP: engine_render_log
409
+ -- Render-time log assembly (SPEC §packet packet.system.log).
410
+ -- Yields log_entries for the whole RUN — the conversation's working
411
+ -- memory carries across loops within a session's run, not just the
412
+ -- current loop. Coordinate is log:///<loop_seq>/<turn_seq>/<sequence>/<op>.
413
+ -- Status 202 entries in state='proposed' are model-invisible until resolved.
414
+ -- `expanded = 0` rows are FOLDED — listed but collapsed to their coordinate
415
+ -- (FOLD); the renderer elides the body. §open-fold: folded rows stay listed, re-OPENable.
416
+ SELECT
417
+ l.sequence AS loop_seq,
418
+ t.sequence AS turn_seq,
419
+ le.sequence,
420
+ -- le.origin is attribution, never a render filter; the run's actor — §actor-boundary-origin-not-filter §machine-processes-run-origin
421
+ le.origin,
422
+ le.op, le.suffix, le.signal,
423
+ le.scheme, le.username, le.password,
424
+ le.hostname, le.port, le.pathname,
425
+ le.params, le.fragment,
426
+ le.status_rx, le.rx, le.mimetype_rx,
427
+ le.tx, le.mimetype_tx,
428
+ le.state, le.outcome, le.expanded, le.source, le.attrs
429
+ FROM log_entries le
430
+ JOIN turns t ON t.id = le.turn_id
431
+ JOIN loops l ON l.id = le.loop_id
432
+ -- WHERE renders exactly one run's log — §actor-boundary-isolation §machine-processes-run-is-its-log
433
+ -- the AND NOT clauses keep proposed (202) rows hidden until resolved (§proposal-proposed-hidden),
434
+ -- and SUCCESSFUL OPEN/FOLD render-directive rows out of the packet (#382 — recorded in the DB for
435
+ -- forensics, suppressed from materialization so a curation receipt rents zero packet space; the
436
+ -- successful fold that hid the task frame in run43 left NO trace, the database dig. A FAILED
437
+ -- OPEN/FOLD still renders — errors are signals, §telemetry-uniform-error-channel).
438
+ WHERE le.run_id = $run_id
439
+ AND NOT (le.status_rx = 202 AND le.state = 'proposed')
440
+ AND NOT (le.op IN ('OPEN', 'FOLD') AND le.status_rx < 400)
441
+ ORDER BY l.sequence, t.sequence, le.sequence;
442
+
443
+ -- PREP: engine_insert_log_entry
444
+ -- Default state='resolved' covers the common path (non-proposing schemes
445
+ -- return their final status immediately). Status 202 + state='proposed'
446
+ -- triggers the proposal lifecycle (engine pauses dispatch; client resolves
447
+ -- via loop/resolve RPC; entry transitions through engine_resolve_log_entry).
448
+ INSERT INTO log_entries (
449
+ run_id, loop_id, turn_id, sequence, origin, source,
450
+ op, suffix, signal,
451
+ scheme, username, password, hostname, port,
452
+ pathname, params, fragment, lineMarker,
453
+ tx, mimetype_tx, rx, mimetype_rx, status_rx, tokens,
454
+ state, outcome, attrs
455
+ ) VALUES (
456
+ $run_id, $loop_id, $turn_id, $sequence, $origin, $source,
457
+ $op, $suffix, $signal,
458
+ $scheme, $username, $password, $hostname, $port,
459
+ $pathname, $params, $fragment, $lineMarker,
460
+ $tx, $mimetype_tx, $rx, $mimetype_rx, $status_rx, $tokens,
461
+ $state, $outcome, $attrs
462
+ )
463
+ RETURNING id;
464
+
465
+ -- PREP: engine_resolve_log_entry
466
+ -- Transitions a proposed log entry to its terminal state. Used by the
467
+ -- proposal lifecycle (loop/resolve RPC, YOLO auto-accept, timeout, abort).
468
+ -- Updates status_rx + rx + state + outcome atomically.
469
+ UPDATE log_entries
470
+ SET state = $state,
471
+ outcome = $outcome,
472
+ status_rx = $status_rx,
473
+ rx = $rx
474
+ WHERE id = $id
475
+ AND state = 'proposed';
476
+
477
+ -- PREP: engine_turn_retrievals
478
+ -- §send-premature-terminate — the pending set's retrieval leg: THIS turn's READ/FIND/OPEN rows,
479
+ -- whose results the model cannot have seen (they fold back next packet). A [200] over them is
480
+ -- discarding answers it asked for.
481
+ SELECT id FROM log_entries
482
+ WHERE turn_id = $turn_id AND origin = 'model' AND op IN ('READ', 'FIND', 'OPEN');
483
+
484
+ -- PREP: engine_turn_failures
485
+ -- §send-200-failed-ops — THIS turn's failed op results (the model's own ops, status >= 400), whose
486
+ -- errors the model cannot have seen (they land next packet). A [200] over them concludes blind
487
+ -- past a failure — refused 409; [499] abandons regardless (declaring failure IS weighing it).
488
+ -- op='error' rows are EXCLUDED: the error CHANNEL is already-surfaced signal (the grinder's
489
+ -- overflow row mints pre-packet — the recovery turn SAW it; §grinder-hard-413-recovery's
490
+ -- concluding-is-legitimate stands), and the current emission's parse errors ride the threaded
491
+ -- count instead (they mint as rows only after dispatch).
492
+ SELECT id FROM log_entries
493
+ WHERE turn_id = $turn_id AND origin = 'model' AND status_rx >= 400 AND op != 'error';
494
+
495
+ -- PREP: engine_demote_turn_status
496
+ -- §send-premature-terminate — a terminal REFUSED at dispatch (the pending-set 409) demotes the
497
+ -- turn to a continue AFTER the close already persisted the provisional status (the close writes
498
+ -- packet+usage as soon as the model responds; ops dispatch after). The record must match the
499
+ -- truth the return value carries: the loop never went terminal, so the turn didn't either.
500
+ UPDATE turns SET status = $status WHERE id = $id;
501
+
502
+ -- PREP: token_count_get
503
+ -- #312 — the keyed token-derivation lookup: one content blob, one tokenizer identity, one count.
504
+ SELECT tokens FROM token_counts WHERE content_hash = $content_hash AND tokenizer_id = $tokenizer_id;
505
+
506
+ -- PREP: token_count_upsert
507
+ INSERT INTO token_counts (content_hash, tokenizer_id, tokens) VALUES ($content_hash, $tokenizer_id, $tokens)
508
+ ON CONFLICT (content_hash, tokenizer_id) DO UPDATE SET tokens = excluded.tokens;
509
+
510
+ -- PREP: token_stale_channels
511
+ -- #312 — the pump's recount worklist: body channels whose (content_hash, active tokenizer) pair
512
+ -- has no derivation row yet. A model swap to a NEW tokenizer identity makes every row miss (the
513
+ -- bulk recount); a swap between vocab-sharing models misses nothing.
514
+ SELECT ec.entry_id, ec.content, ec.content_hash
515
+ FROM entry_channels ec
516
+ JOIN entries e ON e.id = ec.entry_id
517
+ WHERE e.session_id = $session_id AND ec.name = 'body' AND ec.content_hash IS NOT NULL
518
+ AND NOT EXISTS (SELECT 1 FROM token_counts tc WHERE tc.content_hash = ec.content_hash AND tc.tokenizer_id = $tokenizer_id);
519
+
520
+
521
+ -- PREP: engine_loop_sequence
522
+ -- The loop's PER-RUN sequence — the model-facing coordinate (prompt/<run>/<loop-seq>/<turn-seq>,
523
+ -- matching the log's loop-relative numbering). The raw db id leaked into prompt paths and the
524
+ -- model's first loop read as prompt/2/1 (the docs loop holds id 1). Owner: minor but annoying.
525
+ SELECT sequence FROM loops WHERE id = $loop_id;
526
+
527
+ -- PREP: engine_run_has_undelivered_child_term
528
+ -- A child run whose loop TERMINATED after the current turn's timestamp — its deliverable
529
+ -- (the §run-scheme collect delta) is queued for the NEXT packet build and has not been seen.
530
+ -- The 1ms-wide fan-out race: workers concluding DURING the parent's generation are not "live"
531
+ -- (the wait's J leg misses them) but their results are pending — concluding or ∅-collapsing
532
+ -- over them silently discards deliverables the model spawned. {§send-undelivered-child-term}
533
+ SELECT 1 AS pending FROM loops l
534
+ JOIN runs r ON r.id = l.run_id
535
+ WHERE r.parent_run_id = $run_id
536
+ AND l.terminated_at IS NOT NULL
537
+ AND l.terminated_at > (SELECT timestamp FROM turns WHERE id = $turn_id)
538
+ LIMIT 1;
@@ -0,0 +1,13 @@
1
+ export interface FlagDescriptor {
2
+ flagName: string;
3
+ envName: string;
4
+ defaultValue: string;
5
+ description: string | null;
6
+ }
7
+ export default class EnvFlags {
8
+ #private;
9
+ static parseEnvDefaultsContent(content: string): FlagDescriptor[];
10
+ static parseEnvDefaults(path: string): Promise<FlagDescriptor[]>;
11
+ static formatFlagsHelp(flags: FlagDescriptor[]): string;
12
+ }
13
+ //# sourceMappingURL=EnvFlags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnvFlags.d.ts","sourceRoot":"","sources":["../../src/core/EnvFlags.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,CAAC,OAAO,OAAO,QAAQ;;IAkBzB,MAAM,CAAC,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CA4BhE;IAED,OAAa,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAGrE;IAID,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,CAYtD;CACJ"}
@@ -0,0 +1,84 @@
1
+ // Auto-derives admin-CLI flags from the service's .env.defaults. Per the "speak in DSL,
2
+ // not plumbing" / single-source-of-truth ethos: .env.defaults is the
3
+ // canonical config doc (§operator-config-env-defaults); the CLI's --flag surface mirrors it.
4
+ //
5
+ // Rules:
6
+ // - Each PLURNK_* env var becomes a --kebab-cased flag (prefix stripped).
7
+ // - Comment line(s) immediately above (no blank line between) become the
8
+ // -h description. Section headers (# --- xxx ---) are delimiters,
9
+ // not descriptions.
10
+ // - Multi-line descriptions are joined with spaces.
11
+ // - Vars without a comment are still accepted as flags but hidden from -h.
12
+ import { readFile } from "node:fs/promises";
13
+ export default class EnvFlags {
14
+ static #isSectionDelimiter(line) { return /^#\s*---/.test(line); }
15
+ static #isCommentLine(line) { return /^\s*#/.test(line); }
16
+ static #isBlank(line) { return line.trim().length === 0; }
17
+ static #extractCommentText(line) { return line.replace(/^\s*#\s?/, "").trim(); }
18
+ static #envNameToFlag(envName) {
19
+ return "--" + envName.replace(/^PLURNK_/, "").toLowerCase().replace(/_/g, "-");
20
+ }
21
+ static #stripQuotes(s) {
22
+ if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
23
+ return s.slice(1, -1);
24
+ }
25
+ return s;
26
+ }
27
+ static parseEnvDefaultsContent(content) {
28
+ const lines = content.split("\n");
29
+ const flags = [];
30
+ let buffer = [];
31
+ for (const line of lines) {
32
+ if (EnvFlags.#isBlank(line)) {
33
+ buffer = [];
34
+ continue;
35
+ }
36
+ if (EnvFlags.#isSectionDelimiter(line)) {
37
+ buffer = [];
38
+ continue;
39
+ }
40
+ if (EnvFlags.#isCommentLine(line)) {
41
+ const text = EnvFlags.#extractCommentText(line);
42
+ if (text.length === 0) {
43
+ buffer = [];
44
+ continue;
45
+ }
46
+ buffer.push(text);
47
+ continue;
48
+ }
49
+ // Variable assignment line
50
+ const match = line.match(/^(PLURNK_[A-Z_]+)=(.*)$/);
51
+ if (match === null) {
52
+ buffer = [];
53
+ continue;
54
+ }
55
+ const envName = match[1];
56
+ const defaultValue = EnvFlags.#stripQuotes(match[2].trim());
57
+ const description = buffer.length > 0 ? buffer.join(" ") : null;
58
+ flags.push({ flagName: EnvFlags.#envNameToFlag(envName), envName, defaultValue, description });
59
+ buffer = [];
60
+ }
61
+ return flags;
62
+ }
63
+ static async parseEnvDefaults(path) {
64
+ const content = await readFile(path, "utf8");
65
+ return EnvFlags.parseEnvDefaultsContent(content);
66
+ }
67
+ // One-line-per-flag terse format. Descriptions, when present, share the
68
+ // flag's line; otherwise the env name and default carry the meaning.
69
+ static formatFlagsHelp(flags) {
70
+ if (flags.length === 0)
71
+ return "";
72
+ const lines = [];
73
+ const flagWidth = Math.max(...flags.map((f) => f.flagName.length));
74
+ for (const f of flags) {
75
+ const pad = " ".repeat(Math.max(0, flagWidth - f.flagName.length) + 2);
76
+ const trailer = f.description !== null
77
+ ? `${f.description} (${f.envName}=${f.defaultValue})`
78
+ : `${f.envName}=${f.defaultValue}`;
79
+ lines.push(` ${f.flagName}${pad}${trailer}`);
80
+ }
81
+ return lines.join("\n");
82
+ }
83
+ }
84
+ //# sourceMappingURL=EnvFlags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnvFlags.js","sourceRoot":"","sources":["../../src/core/EnvFlags.ts"],"names":[],"mappings":"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"}