@plurnk/plurnk-service 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/.env.defaults +22 -27
  2. package/INSTALL.md +22 -17
  3. package/README.md +1 -1
  4. package/SPEC.md +505 -362
  5. package/dist/build-info.json +1 -1
  6. package/dist/content/edit-collision.d.ts +5 -0
  7. package/dist/content/edit-collision.d.ts.map +1 -0
  8. package/dist/content/edit-collision.js +14 -0
  9. package/dist/content/edit-collision.js.map +1 -0
  10. package/dist/content/edit-receipt.d.ts +3 -2
  11. package/dist/content/edit-receipt.d.ts.map +1 -1
  12. package/dist/content/edit-receipt.js +58 -13
  13. package/dist/content/edit-receipt.js.map +1 -1
  14. package/dist/content/index.d.ts +4 -1
  15. package/dist/content/index.d.ts.map +1 -1
  16. package/dist/content/index.js +3 -1
  17. package/dist/content/index.js.map +1 -1
  18. package/dist/content/line-anchors.d.ts +41 -0
  19. package/dist/content/line-anchors.d.ts.map +1 -0
  20. package/dist/content/line-anchors.js +191 -0
  21. package/dist/content/line-anchors.js.map +1 -0
  22. package/dist/content/read-projector.d.ts +7 -1
  23. package/dist/content/read-projector.d.ts.map +1 -1
  24. package/dist/content/read-projector.js +46 -10
  25. package/dist/content/read-projector.js.map +1 -1
  26. package/dist/content/read-resolve.js +3 -3
  27. package/dist/content/read-resolve.js.map +1 -1
  28. package/dist/core/BudgetReadout.d.ts.map +1 -1
  29. package/dist/core/BudgetReadout.js +9 -2
  30. package/dist/core/BudgetReadout.js.map +1 -1
  31. package/dist/core/ChannelWrite.js +1 -1
  32. package/dist/core/ChannelWrite.js.map +1 -1
  33. package/dist/core/ChannelWrite.sql +3 -3
  34. package/dist/core/CoreSchemeServices.d.ts +1 -1
  35. package/dist/core/CoreSchemeServices.d.ts.map +1 -1
  36. package/dist/core/CoreSchemeServices.js +1 -1
  37. package/dist/core/CoreSchemeServices.js.map +1 -1
  38. package/dist/core/Dispatcher.d.ts +15 -5
  39. package/dist/core/Dispatcher.d.ts.map +1 -1
  40. package/dist/core/Dispatcher.js +220 -978
  41. package/dist/core/Dispatcher.js.map +1 -1
  42. package/dist/core/DurableStatement.d.ts.map +1 -1
  43. package/dist/core/DurableStatement.js +2 -0
  44. package/dist/core/DurableStatement.js.map +1 -1
  45. package/dist/core/Engine.d.ts +18 -43
  46. package/dist/core/Engine.d.ts.map +1 -1
  47. package/dist/core/Engine.js +90 -1554
  48. package/dist/core/Engine.js.map +1 -1
  49. package/dist/core/Engine.sql +192 -112
  50. package/dist/core/ExecutableTools.d.ts +10 -0
  51. package/dist/core/ExecutableTools.d.ts.map +1 -0
  52. package/dist/core/ExecutableTools.js +41 -0
  53. package/dist/core/ExecutableTools.js.map +1 -0
  54. package/dist/core/ExecutorRegistry.d.ts +3 -3
  55. package/dist/core/ExecutorRegistry.d.ts.map +1 -1
  56. package/dist/core/ExecutorRegistry.js +2 -2
  57. package/dist/core/ExecutorRegistry.js.map +1 -1
  58. package/dist/core/LogBody.d.ts +3 -0
  59. package/dist/core/LogBody.d.ts.map +1 -1
  60. package/dist/core/LogBody.js +21 -5
  61. package/dist/core/LogBody.js.map +1 -1
  62. package/dist/core/LogEntryProjection.d.ts +14 -0
  63. package/dist/core/LogEntryProjection.d.ts.map +1 -0
  64. package/dist/core/LogEntryProjection.js +38 -0
  65. package/dist/core/LogEntryProjection.js.map +1 -0
  66. package/dist/core/ModelCall.d.ts +27 -0
  67. package/dist/core/ModelCall.d.ts.map +1 -0
  68. package/dist/core/ModelCall.js +127 -0
  69. package/dist/core/ModelCall.js.map +1 -0
  70. package/dist/core/PacketBuilder.d.ts +14 -25
  71. package/dist/core/PacketBuilder.d.ts.map +1 -1
  72. package/dist/core/PacketBuilder.js +170 -244
  73. package/dist/core/PacketBuilder.js.map +1 -1
  74. package/dist/core/ProblemLog.d.ts +1 -1
  75. package/dist/core/ProblemLog.d.ts.map +1 -1
  76. package/dist/core/ProblemLog.js +15 -3
  77. package/dist/core/ProblemLog.js.map +1 -1
  78. package/dist/core/ProposalLifecycle.d.ts +2 -2
  79. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  80. package/dist/core/ProposalLifecycle.js +17 -9
  81. package/dist/core/ProposalLifecycle.js.map +1 -1
  82. package/dist/core/ProviderInstantiate.d.ts.map +1 -1
  83. package/dist/core/ProviderInstantiate.js +25 -8
  84. package/dist/core/ProviderInstantiate.js.map +1 -1
  85. package/dist/core/ResourceMutations.d.ts +73 -0
  86. package/dist/core/ResourceMutations.d.ts.map +1 -0
  87. package/dist/core/ResourceMutations.js +1142 -0
  88. package/dist/core/ResourceMutations.js.map +1 -0
  89. package/dist/core/SchemeRegistry.js +10 -10
  90. package/dist/core/SchemeRegistry.js.map +1 -1
  91. package/dist/core/StoredPacket.d.ts +2 -2
  92. package/dist/core/StoredPacket.js +7 -7
  93. package/dist/core/StrikeRail.d.ts +0 -1
  94. package/dist/core/StrikeRail.d.ts.map +1 -1
  95. package/dist/core/StrikeRail.js +6 -4
  96. package/dist/core/StrikeRail.js.map +1 -1
  97. package/dist/core/TurnRunner.d.ts +72 -0
  98. package/dist/core/TurnRunner.d.ts.map +1 -0
  99. package/dist/core/TurnRunner.js +1730 -0
  100. package/dist/core/TurnRunner.js.map +1 -0
  101. package/dist/core/caps/CapsResolve.js +1 -1
  102. package/dist/core/caps/CapsResolve.js.map +1 -1
  103. package/dist/core/caps/DbChannelCaps.js +4 -4
  104. package/dist/core/caps/DbChannelCaps.js.map +1 -1
  105. package/dist/core/caps/DbEntryCaps.d.ts +2 -1
  106. package/dist/core/caps/DbEntryCaps.d.ts.map +1 -1
  107. package/dist/core/caps/DbEntryCaps.js +8 -5
  108. package/dist/core/caps/DbEntryCaps.js.map +1 -1
  109. package/dist/core/caps/DbProjectionCaps.d.ts +1 -0
  110. package/dist/core/caps/DbProjectionCaps.d.ts.map +1 -1
  111. package/dist/core/caps/DbProjectionCaps.js +29 -0
  112. package/dist/core/caps/DbProjectionCaps.js.map +1 -1
  113. package/dist/core/caps/SchemeCtxImpl.d.ts +5 -2
  114. package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
  115. package/dist/core/caps/SchemeCtxImpl.js +6 -4
  116. package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
  117. package/dist/core/content-hash.js +2 -2
  118. package/dist/core/content-hash.js.map +1 -1
  119. package/dist/core/content-weight.d.ts +2 -0
  120. package/dist/core/content-weight.d.ts.map +1 -0
  121. package/dist/core/content-weight.js +4 -0
  122. package/dist/core/content-weight.js.map +1 -0
  123. package/dist/core/content_weight.d.ts +4 -0
  124. package/dist/core/content_weight.d.ts.map +1 -0
  125. package/dist/core/content_weight.js +6 -0
  126. package/dist/core/content_weight.js.map +1 -0
  127. package/dist/core/fork.d.ts.map +1 -1
  128. package/dist/core/fork.js +23 -7
  129. package/dist/core/fork.js.map +1 -1
  130. package/dist/core/fork.sql +38 -17
  131. package/dist/core/git-membership.d.ts.map +1 -1
  132. package/dist/core/git-membership.js +1 -2
  133. package/dist/core/git-membership.js.map +1 -1
  134. package/dist/core/git-state.js +1 -1
  135. package/dist/core/git-state.js.map +1 -1
  136. package/dist/core/packet-wire.d.ts +6 -3
  137. package/dist/core/packet-wire.d.ts.map +1 -1
  138. package/dist/core/packet-wire.js +257 -99
  139. package/dist/core/packet-wire.js.map +1 -1
  140. package/dist/core/provider-accounting.d.ts +24 -0
  141. package/dist/core/provider-accounting.d.ts.map +1 -0
  142. package/dist/core/provider-accounting.js +76 -0
  143. package/dist/core/provider-accounting.js.map +1 -0
  144. package/dist/core/scheme-types.d.ts +1 -1
  145. package/dist/core/scheme-types.d.ts.map +1 -1
  146. package/dist/core/search-gate.d.ts +2 -2
  147. package/dist/core/search-gate.d.ts.map +1 -1
  148. package/dist/core/search-gate.js +8 -8
  149. package/dist/core/search-gate.js.map +1 -1
  150. package/dist/core/turn-scheduler.js +1 -1
  151. package/dist/core/turn-scheduler.js.map +1 -1
  152. package/dist/digest/Digest.d.ts.map +1 -1
  153. package/dist/digest/Digest.js +221 -110
  154. package/dist/digest/Digest.js.map +1 -1
  155. package/dist/digest/digest.sql +40 -18
  156. package/dist/schemes/Exec.d.ts.map +1 -1
  157. package/dist/schemes/Exec.js +136 -110
  158. package/dist/schemes/Exec.js.map +1 -1
  159. package/dist/schemes/ExecOutputScheme.js +1 -1
  160. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  161. package/dist/schemes/File.d.ts +5 -4
  162. package/dist/schemes/File.d.ts.map +1 -1
  163. package/dist/schemes/File.js +25 -23
  164. package/dist/schemes/File.js.map +1 -1
  165. package/dist/schemes/Log.d.ts +11 -0
  166. package/dist/schemes/Log.d.ts.map +1 -1
  167. package/dist/schemes/Log.js +172 -107
  168. package/dist/schemes/Log.js.map +1 -1
  169. package/dist/schemes/Log.sql +48 -32
  170. package/dist/schemes/Prompt.d.ts +3 -3
  171. package/dist/schemes/Prompt.d.ts.map +1 -1
  172. package/dist/schemes/Prompt.js +4 -1
  173. package/dist/schemes/Prompt.js.map +1 -1
  174. package/dist/schemes/Skill.d.ts +4 -4
  175. package/dist/schemes/Skill.d.ts.map +1 -1
  176. package/dist/schemes/Skill.js +3 -0
  177. package/dist/schemes/Skill.js.map +1 -1
  178. package/dist/schemes/Worker.d.ts +4 -4
  179. package/dist/schemes/Worker.d.ts.map +1 -1
  180. package/dist/schemes/Worker.js +11 -7
  181. package/dist/schemes/Worker.js.map +1 -1
  182. package/dist/schemes/_entry-crud.d.ts +0 -1
  183. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  184. package/dist/schemes/_entry-crud.js +19 -13
  185. package/dist/schemes/_entry-crud.js.map +1 -1
  186. package/dist/schemes/_entry-crud.sql +4 -16
  187. package/dist/schemes/_entry-find.d.ts +17 -16
  188. package/dist/schemes/_entry-find.d.ts.map +1 -1
  189. package/dist/schemes/_entry-find.js +58 -52
  190. package/dist/schemes/_entry-find.js.map +1 -1
  191. package/dist/schemes/_entry-find.sql +2 -21
  192. package/dist/schemes/_entry-graph.sql +1 -1
  193. package/dist/schemes/_entry-manifest.d.ts +5 -17
  194. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  195. package/dist/schemes/_entry-manifest.js +32 -28
  196. package/dist/schemes/_entry-manifest.js.map +1 -1
  197. package/dist/schemes/_entry-ops.d.ts +5 -4
  198. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  199. package/dist/schemes/_entry-ops.js +89 -49
  200. package/dist/schemes/_entry-ops.js.map +1 -1
  201. package/dist/schemes/_entry-ops.sql +30 -4
  202. package/dist/schemes/_entry-send.js +4 -4
  203. package/dist/schemes/_entry-send.js.map +1 -1
  204. package/dist/schemes/_search-index.d.ts.map +1 -1
  205. package/dist/schemes/_search-index.js +10 -2
  206. package/dist/schemes/_search-index.js.map +1 -1
  207. package/dist/schemes/exec-abort.js +2 -2
  208. package/dist/schemes/exec-abort.js.map +1 -1
  209. package/dist/server/Daemon.d.ts +7 -42
  210. package/dist/server/Daemon.d.ts.map +1 -1
  211. package/dist/server/Daemon.js +139 -900
  212. package/dist/server/Daemon.js.map +1 -1
  213. package/dist/server/DrainSupervisor.d.ts +117 -0
  214. package/dist/server/DrainSupervisor.d.ts.map +1 -0
  215. package/dist/server/DrainSupervisor.js +802 -0
  216. package/dist/server/DrainSupervisor.js.map +1 -0
  217. package/dist/server/drain.sql +2 -2
  218. package/dist/server/envelope.d.ts +0 -2
  219. package/dist/server/envelope.d.ts.map +1 -1
  220. package/dist/server/envelope.js.map +1 -1
  221. package/dist/server/envelope.sql +2 -2
  222. package/dist/server/lifecycle-recovery.sql +28 -15
  223. package/dist/server/logEntry.d.ts +2 -1
  224. package/dist/server/logEntry.d.ts.map +1 -1
  225. package/dist/server/logEntry.js +14 -2
  226. package/dist/server/logEntry.js.map +1 -1
  227. package/dist/server/logEntry.sql +5 -1
  228. package/dist/server/seam-entry-read.sql +2 -2
  229. package/dist/service.js +1 -1
  230. package/dist/service.js.map +1 -1
  231. package/migrations/001_schema.sql +622 -216
  232. package/package.json +39 -34
  233. package/dist/core/BudgetOverflow.d.ts +0 -20
  234. package/dist/core/BudgetOverflow.d.ts.map +0 -1
  235. package/dist/core/BudgetOverflow.js +0 -49
  236. package/dist/core/BudgetOverflow.js.map +0 -1
  237. package/dist/core/caps/DbTagCaps.d.ts +0 -10
  238. package/dist/core/caps/DbTagCaps.d.ts.map +0 -1
  239. package/dist/core/caps/DbTagCaps.js +0 -46
  240. package/dist/core/caps/DbTagCaps.js.map +0 -1
  241. package/dist/core/ruler_count.d.ts +0 -4
  242. package/dist/core/ruler_count.d.ts.map +0 -1
  243. package/dist/core/ruler_count.js +0 -7
  244. package/dist/core/ruler_count.js.map +0 -1
  245. package/dist/core/token-ruler.d.ts +0 -2
  246. package/dist/core/token-ruler.d.ts.map +0 -1
  247. package/dist/core/token-ruler.js +0 -5
  248. package/dist/core/token-ruler.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  var _a;
2
2
  import { renderAddress, promptLoopPrefix } from "./plurnk-uri.js";
3
- import { rulerCount } from "./token-ruler.js";
3
+ import { contentWeight } from "./content-weight.js";
4
4
  import { docsExcludeSet } from "./teaching.js";
5
5
  import { Policy } from "@plurnk/plurnk-execs";
6
6
  import WorkspaceSettings from "./workspace-settings.js";
@@ -13,10 +13,12 @@ import { readTeachingSource } from "./teaching-corpus.js";
13
13
  // projection and digest projection are structurally one function — no
14
14
  // drift between wire and digest possible.
15
15
  import PacketWire from "./packet-wire.js";
16
- import { assertPromptTokenMeasurement, scopeEnvToAlias, resolveActiveAlias } from "@plurnk/plurnk-providers";
16
+ import LogEntryProjection from "./LogEntryProjection.js";
17
+ import { scopeEnvToAlias, resolveActiveAlias } from "@plurnk/plurnk-providers";
17
18
  import ProviderInstantiate from "./ProviderInstantiate.js";
18
- import BudgetOverflow from "./BudgetOverflow.js";
19
19
  import BudgetReadout from "./BudgetReadout.js";
20
+ import ExecutableTools from "./ExecutableTools.js";
21
+ import LineAnchors from "../content/line-anchors.js";
20
22
  const trimHorizontal = (value) => value.replace(/^[\t ]+|[\t ]+$/gu, "");
21
23
  const tableCells = (line) => {
22
24
  if (!line.startsWith("|") || !line.endsWith("|"))
@@ -86,128 +88,75 @@ const compactDefinitionTables = (markdown) => {
86
88
  return `| ${cells.map(trimHorizontal).join(" | ")} |${carriageReturn}`;
87
89
  }).join("\n");
88
90
  };
89
- // {§tokenomics-window-partition} — the four partition numbers. REQUIRED (fail-hard, the
90
- // providers-env convention): the ceiling is DERIVED from these, never set directly
91
- // (PLURNK_BUDGET_CEILING is retired — a settable ceiling let policy contradict physics).
92
- const readPartitionIntFrom = (env, name, min) => {
91
+ // {§tokenomics-prompt-projection-share} — the required alias-scoped share of
92
+ // provider-derived input capacity used only for automatic prompt projection.
93
+ const readRequiredPercentFrom = (env, name) => {
93
94
  const raw = env[name];
94
- const n = Number.parseInt(raw ?? "", 10);
95
- if (!Number.isFinite(n) || n < min)
96
- throw new Error(`${name} must be an integer >= ${min}; got ${raw}`);
97
- return n;
98
- };
99
- const readOptionalPositiveIntFrom = (env, name) => {
100
- const raw = env[name];
101
- if (raw === undefined || raw.length === 0)
102
- return null;
103
- const n = Number(raw);
104
- if (!Number.isInteger(n) || n <= 0)
105
- throw new Error(`${name} must be a positive integer; got ${raw}`);
106
- return n;
95
+ const match = /^([0-9]+(?:\.[0-9]+)?)%$/.exec(raw ?? "");
96
+ const percent = Number(match?.[1]);
97
+ if (!Number.isFinite(percent) || percent <= 0 || percent >= 100) {
98
+ throw new Error(`${name} must be a percentage in (0, 100); got ${JSON.stringify(raw)}`);
99
+ }
100
+ return percent / 100;
107
101
  };
108
102
  // Packet assembly (SPEC {§packet-assembly}) + the budget grinder ({§grinder}):
109
103
  // builds the spec'd request packet, measures it, and reclaims window on overflow.
110
104
  class PacketBuilder {
111
105
  #db;
112
106
  #schemes;
113
- #problems;
114
107
  // Boot-discovered runtime executors, late-injected on Engine after daemon
115
108
  // start() — read through a thunk so the post-construction set is visible.
116
109
  #executors;
117
- // {§tokenomics-window-partition} — the partition is PER-ALIAS, resolved per provider in
118
- // #partitionFor and cached by alias; no boot-time global read.
119
- constructor({ db, schemes, problems, executors }) {
110
+ // {§tokenomics-prompt-projection-share} — prompt projection is alias-scoped
111
+ // through the same environment contract as provider configuration.
112
+ constructor({ db, schemes, executors }) {
120
113
  this.#db = db;
121
114
  this.#schemes = schemes;
122
- this.#problems = problems;
123
115
  this.#executors = executors;
124
- // {§tokenomics-window-partition} — the envelope rides the provider; construction only runs the retired-knob shed
125
- // so a stale operator .env fails at BOOT, not first use.
116
+ // Retired capacity knobs fail at boot rather than silently becoming inert.
126
117
  const bootAlias = resolveActiveAlias(process.env)?.alias ?? "";
127
- this.#safetyFor(bootAlias);
128
- this.#promptBudgetCapFor(bootAlias);
118
+ this.#shedRetiredCapacityKnobs();
119
+ this.#promptProjectionFor(bootAlias);
129
120
  }
130
- // {§tokenomics-window-partition} — provider generation settings and core packet policy both resolve per alias.
131
- // scopeEnvToAlias resolves PLURNK_SERVICE_*_<alias> over the bare fallback with providers' own
132
- // battle-tested suffix parser. Cached per alias; the boot-global case falls back to the active
133
- // alias when a provider carries no side-table entry (a test Mock).
134
- // Provider context and response reserves remain provider-owned. Core owns only its virtual
135
- // prompt budget and the ruler's packing-safety margin.
136
- static #KNOBS = ["PLURNK_SERVICE_PROMPT_BUDGET", "PLURNK_SERVICE_SAFETY"];
137
- #shedChecked = false;
138
- #safetyFor(alias) {
139
- // {§tokenomics-window-partition} hard shed: the three misprefixed partition knobs moved to the
140
- // provider tier; a stale operator .env must never silently lose its envelope to the move.
141
- if (!this.#shedChecked) {
142
- this.#shedChecked = true;
143
- const MOVED = {
144
- CTX: "PLURNK_PROVIDERS_CONTEXT_WINDOW", CONTEXT_WINDOW: "PLURNK_PROVIDERS_CONTEXT_WINDOW",
145
- REASONING: "PLURNK_PROVIDERS_REASONING_RESERVE",
146
- ASSISTANT: "PLURNK_PROVIDERS_COMPLETION_RESERVE", COMPLETION: "PLURNK_PROVIDERS_COMPLETION_RESERVE",
147
- };
148
- for (const k of Object.keys(process.env)) {
149
- const m = /^PLURNK_SERVICE_(CTX|CONTEXT_WINDOW|REASONING|ASSISTANT|COMPLETION)(_.*)?$/.exec(k);
150
- if (m !== null)
151
- throw new Error(`${k} is retired: the envelope is provider-owned — the knob is ${MOVED[m[1]]}${m[2] ?? ""}.`);
152
- }
121
+ // Prompt projection is Core policy, scoped through the same alias contract as providers.
122
+ static #KNOBS = ["PLURNK_SERVICE_PROMPT_PROJECTION"];
123
+ #shedRetiredCapacityKnobs() {
124
+ const retired = {
125
+ PLURNK_SERVICE_PROMPT_BUDGET: "provider input capacity is derived from context and output budgets",
126
+ PLURNK_SERVICE_SAFETY: "provider request-shaped capacity admission owns physical headroom",
127
+ };
128
+ for (const key of Object.keys(process.env)) {
129
+ const match = /^(PLURNK_SERVICE_PROMPT_BUDGET|PLURNK_SERVICE_SAFETY)(?:_.*)?$/u.exec(key);
130
+ const reason = match === null ? undefined : retired[match[1]];
131
+ if (reason !== undefined)
132
+ throw new Error(`${key} is retired: ${reason}.`);
133
+ }
134
+ const moved = {
135
+ CTX: "PLURNK_PROVIDERS_CONTEXT_WINDOW",
136
+ CONTEXT_WINDOW: "PLURNK_PROVIDERS_CONTEXT_WINDOW",
137
+ REASONING: "PLURNK_PROVIDERS_REASONING_BUDGET",
138
+ ASSISTANT: "PLURNK_PROVIDERS_OUTPUT_BUDGET",
139
+ COMPLETION: "PLURNK_PROVIDERS_OUTPUT_BUDGET",
140
+ };
141
+ for (const key of Object.keys(process.env)) {
142
+ const match = /^PLURNK_SERVICE_(CTX|CONTEXT_WINDOW|REASONING|ASSISTANT|COMPLETION)(_.*)?$/u.exec(key);
143
+ if (match !== null)
144
+ throw new Error(`${key} is retired: the provider-owned knob is ${moved[match[1]]}${match[2] ?? ""}.`);
153
145
  }
154
- const view = scopeEnvToAlias(process.env, alias, _a.#KNOBS);
155
- return readPartitionIntFrom(view, "PLURNK_SERVICE_SAFETY", 0);
156
146
  }
157
- #promptBudgetCapFor(alias) {
147
+ #promptProjectionFor(alias) {
158
148
  const view = scopeEnvToAlias(process.env, alias, _a.#KNOBS);
159
- return readOptionalPositiveIntFrom(view, "PLURNK_SERVICE_PROMPT_BUDGET");
160
- }
161
- #partitionFor(provider) {
162
- const alias = ProviderInstantiate.aliasOf(provider) ?? resolveActiveAlias(process.env)?.alias ?? "";
163
- return { reasoning: provider.reasoningReserve ?? null, completion: provider.completionReserve ?? null, safety: this.#safetyFor(alias) };
149
+ return readRequiredPercentFrom(view, "PLURNK_SERVICE_PROMPT_PROJECTION");
164
150
  }
165
- // The generation envelope — REASONING + COMPLETION, one undifferentiated pool, passed on
166
- // every generate({maxTokens}): no decode is unbounded ({§tokenomics-window-partition}). Per
167
- // alias: gemma's measured envelope; a cloud alias's generous default the backend clamps.
168
- maxTokensFor(provider) {
169
- const { reasoning, completion } = this.#partitionFor(provider);
170
- if (reasoning === null || completion === null)
171
- return null; // {§tokenomics-window-unpollable-deliberate}: unknown envelope, no cap; the backend clamps
172
- return reasoning + completion;
173
- }
174
- // {§tokenomics-window-partition} — the natural prompt ceiling is the provider's
175
- // effective context window minus its response reserves and the service's ruler
176
- // safety. An optional service prompt budget may only tighten that result. It is
177
- // model-facing grinder policy, never provider physics or a generation setting.
178
- // The client-facing gauge, grinder ceiling, and persisted promptBudget use this one value.
179
- promptBudgetFor(provider) {
180
- return this.ceilingFor(provider); // ONE derivation — the gauge denominator IS the grinder ceiling
181
- }
182
- // {§tokenomics-agnostic-ruler} — the ceiling is the real window partition (window − reserves),
183
- // NO calibration ratio: the model-facing measure is the chars/2 ruler (an over-count for
184
- // typical text), so comparing ruler-weight to the real-token ceiling is itself the conservative
185
- // bias - the packet reports less room than the provider usually has; authoritative
186
- // provider request evidence guards the pathological tail at recovery admission.
187
- ceilingFor(provider) {
188
- const alias = ProviderInstantiate.aliasOf(provider) ?? resolveActiveAlias(process.env)?.alias ?? "";
189
- const operatorCap = this.#promptBudgetCapFor(alias);
190
- // Unknown provider physics stays unknown; an explicit virtual ceiling still bounds
191
- // PLURNK's packet without pretending to describe the backend.
192
- if (provider.contextWindow === null)
193
- return operatorCap;
194
- const { reasoning, completion, safety } = this.#partitionFor(provider);
195
- if (reasoning === null || completion === null)
196
- return operatorCap;
197
- const naturalBudget = provider.contextWindow - reasoning - completion - safety;
198
- if (naturalBudget <= 0) {
199
- // {§tokenomics-window-partition} — this contradiction has one cause: pinned absolute reserves
200
- // exceeding the window the provider detected (percent reserves derive and cannot contradict).
201
- throw new Error(`window partition contradiction for alias '${alias}': window ${provider.contextWindow} <= reserves ${reasoning}+${completion}+${safety}. Pinned PLURNK_PROVIDERS_{REASONING,COMPLETION}_RESERVE absolutes exceed the detected window — repin them under it, or use percent reserves, which derive from the window.`);
202
- }
203
- return operatorCap === null ? naturalBudget : Math.min(operatorCap, naturalBudget);
151
+ curationBudgetFor(provider) {
152
+ return provider.inputCapacity;
204
153
  }
205
154
  // {§packet-stored-shape} — assemble the system/user request before the
206
155
  // provider call; complete the same record with the provider response.
207
- async buildRequestPacket({ initialMessages, requirements = "", workspaceId, workerId, loopId, currentTurnSeq, provider, gitStatus, notices = [], transientOpenLogEntryId = null, }) {
156
+ async buildRequestPacket({ initialMessages, requirements = "", workspaceId, workerId, loopId, currentTurnSeq, provider, gitStatus, notices = [], transientOpenLogEntryId = null, promptProjection = "automatic", }) {
208
157
  const byRole = (role) => initialMessages.filter((m) => m.role === role).map((m) => m.content).join("\n\n");
209
158
  // plurnk.md (grammar/dialects) ONLY — the definition is the hot-path grammar.
210
- // The scheme catalogue is its own `schemes` section below tools ({§schemes-directory}),
159
+ // The resource catalogue is its own `schemes` section below tools ({§schemes-directory}),
211
160
  // NOT appended here: the language teaching is scheme-agnostic, so the service advertises
212
161
  // the installed scheme set at packet-time via SchemeRegistry.teach().
213
162
  const system_definition = compactDefinitionTables(byRole("system"));
@@ -239,12 +188,18 @@ class PacketBuilder {
239
188
  // {§emission-admission}: the definition remains the complete language authority.
240
189
  const log = await this.#buildLog(workerId, transientOpenLogEntryId);
241
190
  const failures = await this.buildFailurePointers(loopId, currentTurnSeq);
242
- const countTokens = rulerCount; // {§tokenomics-agnostic-ruler} — the ONE model-facing ruler (chars/2), not the provider
191
+ const weighContent = contentWeight;
243
192
  // {§tools-loop-affinity}: teaching and dispatch resolve the same loop flags.
244
193
  const activeSchemes = this.#schemes.resolveForLoop(await LoopFlagsReader.read(this.#db, loopId));
245
194
  const tools = this.#collectTools(await this.#workspaceEnabled(workspaceId), await WorkspaceSettings.questionsEnabled(this.#db, workspaceId), activeSchemes);
246
- const ceiling = this.ceilingFor(provider);
247
- const budgetReadout = BudgetReadout.draft(ceiling);
195
+ const curationBudget = this.curationBudgetFor(provider);
196
+ const alias = ProviderInstantiate.aliasOf(provider) ?? resolveActiveAlias(process.env)?.alias ?? "";
197
+ const promptProjectionWeight = promptProjection === "withheld"
198
+ ? 0
199
+ : curationBudget === null
200
+ ? null
201
+ : Math.floor(curationBudget * this.#promptProjectionFor(alias));
202
+ const budgetReadout = BudgetReadout.draft(curationBudget);
248
203
  // The canonical default order, trust boundary, and cache-locality bias are
249
204
  // specified at {§packet-cache-monotone}. Budget placeholders resolve only
250
205
  // after trusted whole-list transforms establish the packet being measured.
@@ -267,17 +222,23 @@ class PacketBuilder {
267
222
  .map((r) => ({ status: r.status, path: `worker://${r.name}` }));
268
223
  const defaults = [
269
224
  { name: "definition", slot: "system", header: null, content: system_definition },
270
- { name: "tools", slot: "system", header: "Registered Executable Tools", content: tools.executors },
225
+ // Stable privileged policy leads loop-dependent capabilities for
226
+ // prefix-cache locality. Empty policy sections simply disappear.
227
+ { name: "system-policy", slot: "system", header: "Policy", content: systemPolicy ?? "" },
228
+ { name: "project-policy", slot: "system", header: "Project Policy", content: projectPolicy ?? "" },
229
+ { name: "tools", slot: "system", header: "Registered Tools", content: tools.executors },
271
230
  ...(tools.optionalOperations.length > 0
272
231
  ? [{ name: "optional-operations", slot: "system", header: "Enabled Optional Operations", content: tools.optionalOperations }]
273
232
  : []),
274
- { name: "schemes", slot: "system", header: "Schemes", content: this.#schemes.teach() },
233
+ { name: "schemes", slot: "system", header: "Resources", content: this.#schemes.teach() },
275
234
  ...(inject !== null ? [{ name: "inject", slot: "system", header: "Operator Notes", content: inject }] : []),
276
- // policy: the client's privileged rules — ~/.plurnk/AGENTS.md (system) then <root>/AGENTS.md (project) — below grammar/tools/schemes, above budget-the-law. AGENTS is POLICY here, never a curatable READable entry. Empty content ⇒ section omitted.
277
- { name: "system-policy", slot: "system", header: "Policy", content: systemPolicy ?? "" },
278
- { name: "project-policy", slot: "system", header: "Project Policy", content: projectPolicy ?? "" },
279
235
  // The append-mostly log leads volatile user status ({§packet-cache-monotone}).
280
- { name: "log", slot: "user", header: "Log", content: PacketWire.renderLog(log, countTokens) },
236
+ {
237
+ name: "log",
238
+ slot: "user",
239
+ header: "Log",
240
+ content: PacketWire.renderLog(log, weighContent, promptProjectionWeight === null ? {} : { promptProjectionWeight }),
241
+ },
281
242
  // The per-turn status clump follows the log ({§packet-cache-monotone}).
282
243
  // child-orientation: what this worker holds live — streams then child workers — just above errors. Terse
283
244
  // pointers (the path is the actionable address the model READs/OPENs/KILLs), never advice. {§child-orientation}
@@ -286,7 +247,8 @@ class PacketBuilder {
286
247
  { name: "errors", slot: "user", header: "Errors", content: PacketWire.renderFailurePointers(failures) },
287
248
  { name: "notices", slot: "user", header: "Notices", content: PacketWire.renderNotices(notices) },
288
249
  { name: "git", slot: "user", header: "Git Status", content: PacketWire.renderGit(gitStatus, branchAssignment?.branch ?? null) },
289
- // budget — LAW (a hard ceiling the model must obey).
250
+ // Familiar token language is a deliberate final model projection;
251
+ // internally this is curation weight, never provider admission.
290
252
  { name: "budget", slot: "user", header: "Budget", content: budgetReadout },
291
253
  // The prompts section closes the status clump as a paths-only list;
292
254
  // bodies arrive through first-class prompt rows.
@@ -297,21 +259,21 @@ class PacketBuilder {
297
259
  // default list — add, remove, reorder — in-process, before measurement.
298
260
  let drafts = await this.#schemes.transformSections(defaults);
299
261
  const budgetSection = drafts.find((section) => section.name === "budget");
300
- if (budgetSection !== undefined && ceiling !== null) {
301
- const content = BudgetReadout.resolve(budgetSection.content, ceiling, (candidate) => {
262
+ if (budgetSection !== undefined && curationBudget !== null) {
263
+ const content = BudgetReadout.resolve(budgetSection.content, curationBudget, (candidate) => {
302
264
  const candidateDrafts = drafts.map((section) => section === budgetSection ? { ...section, content: candidate } : section);
303
- return countTokens(PacketWire.renderSlot(candidateDrafts, "system"))
304
- + countTokens(PacketWire.renderSlot(candidateDrafts, "user"));
265
+ return weighContent(PacketWire.renderSlot(candidateDrafts, "system"))
266
+ + weighContent(PacketWire.renderSlot(candidateDrafts, "user"));
305
267
  });
306
268
  drafts = drafts.map((section) => section === budgetSection ? { ...section, content } : section);
307
269
  }
308
270
  // Core alone turns validated drafts into measured durable sections.
309
271
  const sections = drafts.map((section) => ({
310
272
  ...section,
311
- tokens: countTokens(PacketWire.renderSection(section)),
273
+ weight: weighContent(PacketWire.renderSection(section)),
312
274
  }));
313
- const packetTokens = countTokens(PacketWire.renderSlot(sections, "system")) + countTokens(PacketWire.renderSlot(sections, "user"));
314
- return { tokens: packetTokens, sections, attributions: [] };
275
+ const renderWeight = weighContent(PacketWire.renderSlot(sections, "system")) + weighContent(PacketWire.renderSlot(sections, "user"));
276
+ return { weight: renderWeight, sections, attributions: [] };
315
277
  }
316
278
  // {§operator-config-workspace-execs} — the capability sheet and executor
317
279
  // documents share one workspace predicate with dispatch.
@@ -321,25 +283,24 @@ class PacketBuilder {
321
283
  return () => true;
322
284
  return (tag) => Policy.isEnabled(tag, execs);
323
285
  }
324
- // The ## Registered Executable Tools capability sheet. Each available executor
325
- // tag contributes its self-documenting example; the closed heading distinguishes
326
- // registered selectors from the open-ended general examples above it. {§tools-capability-sheet}
286
+ // The complete ## Registered Tools contract table. {§tools-capability-sheet}
327
287
  #collectTools(workspaceEnabled, questionsOn = false, activeSchemes) {
328
- // Registered executors and optional operations remain distinct fenced sheets.
288
+ // Registered executors and optional operations remain distinct sheets.
289
+ // The former is a contract table; only the latter is an operation example fence.
329
290
  // {§tools-capability-sheet} {§packet-operation-fences}
330
- const executorOps = [];
291
+ const executorTools = [];
331
292
  const notices = [];
332
293
  // {§send-300-choices} — the one-liner rides ONLY where questions are enabled (allowed +
333
294
  // client-requested); the fuller questions.md doc injects through docEntries the same way.
334
295
  const optionalOperations = questionsOn
335
- ? "```plurnk\n<<SEND[300]:Deploy where?;staging;production:SEND\n```"
296
+ ? "```plurnk\n## SEND0 [300]\nDeploy where?;staging;production\n```"
336
297
  : "";
337
298
  const executors = this.#executors();
338
299
  if (executors !== undefined) {
339
300
  const excluded = docsExcludeSet();
340
301
  const runtimes = executors.availableRuntimes();
341
- // {§tools-capability-sheet} The sheet's lines are EXEC-usage examples, keyed on the 'exec' scheme
342
- // (the op face, excludedInAsk). When inactive, say so POSITIVELY (a prose notice): plurnk.md
302
+ // {§tools-capability-sheet} The table is keyed on the exec scheme (the op face,
303
+ // excludedInAsk). When inactive, say so positively: plurnk.md
343
304
  // still teaches EXEC as language, and silent absence measurably invites confabulated runtimes.
344
305
  const execActive = activeSchemes === undefined || activeSchemes.has("exec");
345
306
  if (runtimes.length > 0 && !execActive) {
@@ -348,25 +309,24 @@ class PacketBuilder {
348
309
  else {
349
310
  for (const tag of runtimes) {
350
311
  if (excluded.has(tag))
351
- continue; // {§tools-capability-sheet} — exclude drops the example and doc
312
+ continue; // {§tools-capability-sheet} — exclude drops the row and doc
352
313
  if (!workspaceEnabled(tag))
353
314
  continue; // {§operator-config-workspace-execs}
354
315
  const entry = executors.entry(tag);
355
- // {§tools-capability-sheet} — the example is the bare op fenced below; the fuller doc
356
- // materializes at worker://plurnk/docs/<tag>.md. No example → no line.
357
- if (entry?.example)
358
- executorOps.push(entry.example);
316
+ if (entry !== undefined)
317
+ executorTools.push({ runtime: tag, invocation: entry.invocation });
359
318
  }
360
319
  }
361
320
  }
362
321
  const parts = [...notices];
363
- if (executorOps.length > 0)
364
- parts.push(`\`\`\`plurnk\n${executorOps.join("\n")}\n\`\`\``);
322
+ const directory = ExecutableTools.render(executorTools);
323
+ if (directory !== "")
324
+ parts.push(directory);
365
325
  return { executors: parts.join("\n\n"), optionalOperations };
366
326
  }
367
327
  // #note12 — the plugin-provided reference docs (schemes' + execs' `documentation`),
368
328
  // materialized at worker://plurnk/docs/<name>.md by LoopDocs (like operator
369
- // docs) so the catalog can expose each doc's token weight.
329
+ // docs) so the catalog can expose each doc's curation weight.
370
330
  async docEntries(workspaceId) {
371
331
  const out = await this.#schemes.docs(); // scheme docs already drop PLURNK_SERVICE_DOCS_EXCLUDE names
372
332
  // {§send-300-choices} {§teaching-corpus} — the conditional teaching: questions.md
@@ -394,96 +354,29 @@ class PacketBuilder {
394
354
  return out;
395
355
  }
396
356
  // SPEC {§grinder} — the budget grinder. Runs pre-LLM (in runTurn, after the packet
397
- // is built, before provider.generate); fires only on actual overflow. One rule:
398
- // fold the NEWEST turn boundary's open rows (errors exempt) — never history —
399
- // strike, rebuild, re-measure. Folds (never deletes). The strike it raises and
400
- // the hard-stop it can signal are returned to runLoop, which owns abandonment.
357
+ // is built, before provider.generate); fires only when curation weight exceeds
358
+ // the provider-derived curation budget. One
359
+ // reversible rule: roll back context introduced by the NEWEST turn boundary —
360
+ // rows born there plus exact older rows it transitioned folded→open — then
361
+ // rebuild and re-measure.
401
362
  // {§grinder-overflow-only} — fires only on actual overflow, never speculatively
402
- async enforceBudget({ packet, provider, workerId, loopId, turnId, mintSequence, rebuild }) {
403
- const ceiling = this.ceilingFor(provider);
404
- const measure = (p) => p.tokens;
405
- // {§tokenomics-window-unpollable-deliberate} — a null policy ceiling never triggers grinding. If a virtual ceiling
406
- // does trigger recovery while provider physics is unknown, physical admission
407
- // separately fails closed under {§tokenomics-physical-admission}.
408
- if (ceiling === null || measure(packet) <= ceiling) {
409
- return { packet, fit: true, struck: false, recorded: false };
363
+ async enforceBudget({ packet, provider, loopId, turnId, recordOverflow, rebuild }) {
364
+ const budget = this.curationBudgetFor(provider);
365
+ const measure = (p) => p.weight;
366
+ if (budget === null || measure(packet) <= budget) {
367
+ return { packet, fit: true, boundaryRolledBack: false };
410
368
  }
411
- // ONE rule, every turn — turn 1 and turn 101 alike ({§grinder-layer1-rollback}): fold the
412
- // NEWEST turn boundary's still-open rows (the prior turn's emissions + this turn's
413
- // pre-model rows; errors exempt) in one set-op, strike once, rebuild, re-measure.
414
- // The model owns history visibility. The grinder never reaches back; it folds only the
415
- // newest boundary required to produce a physically valid packet. Continued overflow
416
- // follows the explicit recovery/hard-stop contract ({§grinder-fold-strikes}).
417
- const usage = measure(packet);
369
+ const weight = measure(packet);
370
+ await recordOverflow({ weight, budget, excess: weight - budget });
371
+ // ONE rule, every turn ({§grinder-layer1-rollback}): atomically fold/tag
372
+ // context introduced by the newest boundary. Other older history remains
373
+ // model-owned; remaining curation debt is neither failure nor strike.
418
374
  await this.#db.engine_grinder_fold_newest_turn({ loop_id: loopId, turn_id: turnId });
419
- let current = await rebuild();
420
- if (measure(current) > ceiling) {
421
- // Engine owns the hard-overflow branch and records its one occurrence with
422
- // the enforced recovery constraint (or terminal physics), so this layer does
423
- // not mint a second, weaker account of the same failure.
424
- return { packet: current, fit: false, struck: true, recorded: false };
425
- }
426
- // The fold recovered the request. Preserve the triggering measurements on one
427
- // actionless row and rebuild once so its Problem surfaces in this same packet.
428
- await this.#problems.record({
429
- workerId,
430
- loopId,
431
- turnId,
432
- sequence: mintSequence,
433
- origin: "plurnk",
434
- source: "rail",
435
- result: BudgetOverflow.foldedResult(usage, ceiling),
436
- });
437
- current = await rebuild();
438
- return {
439
- packet: current,
440
- fit: measure(current) <= ceiling,
441
- struck: true,
442
- recorded: true,
443
- };
375
+ const current = await rebuild();
376
+ return { packet: current, fit: measure(current) <= budget, boundaryRolledBack: true };
444
377
  }
445
- // {§tokenomics-physical-admission}: one request-shaped physical predicate.
446
- // The exact PacketWire messages used for dispatch are the measurement input;
447
- // empirical estimates cannot authorize recovery against a hard window.
448
- async physicalAdmission(packet, provider, signal) {
449
- if (provider.contextWindow === null) {
450
- return {
451
- admitted: false,
452
- reason: "unknown_context_window",
453
- detail: `provider ${JSON.stringify(provider.model)} reports no physical context window`,
454
- capacity: null,
455
- };
456
- }
457
- const maxTokens = this.maxTokensFor(provider);
458
- if (maxTokens === null) {
459
- return {
460
- admitted: false,
461
- reason: "unknown_output_envelope",
462
- detail: `provider ${JSON.stringify(provider.model)} reports no resolved output envelope`,
463
- capacity: null,
464
- };
465
- }
466
- const capacity = provider.contextWindow - maxTokens;
467
- const measurement = assertPromptTokenMeasurement(await provider.countPromptTokens(PacketWire.packetToWireMessages(packet), signal), `provider ${JSON.stringify(provider.model)}`);
468
- if (measurement.kind === "estimate") {
469
- return {
470
- admitted: false,
471
- reason: "estimate",
472
- detail: `${measurement.source} is an empirical estimate and cannot authorize physical recovery: ${measurement.detail}`,
473
- capacity,
474
- measurement,
475
- };
476
- }
477
- if (measurement.tokens > capacity) {
478
- return {
479
- admitted: false,
480
- reason: "over_capacity",
481
- detail: `${measurement.kind} prompt measurement ${measurement.tokens} exceeds physical prompt capacity ${capacity}`,
482
- capacity,
483
- measurement,
484
- };
485
- }
486
- return { admitted: true, capacity, measurement };
378
+ async rollbackNewestBoundary(loopId, turnId) {
379
+ await this.#db.engine_grinder_fold_newest_turn({ loop_id: loopId, turn_id: turnId });
487
380
  }
488
381
  // Every prior-turn operation failure is durable before packet assembly.
489
382
  // The model-facing Errors section is only a terse projection of those rows;
@@ -492,7 +385,7 @@ class PacketBuilder {
492
385
  const rows = await this.#db.engine_render_errors.all({ loop_id: loopId, current_turn_seq: currentTurnSeq });
493
386
  return rows.map((r) => ({
494
387
  status: r.status_rx,
495
- coordinate: `${r.loop_seq}/${r.turn_seq}/${r.sequence}/${r.op}`,
388
+ coordinate: LogEntryProjection.coordinate(`${r.loop_seq}/${r.turn_seq}/${r.sequence}`, r),
496
389
  }));
497
390
  }
498
391
  // SPEC {§packet} the log section — chronological action-entries for the loop.
@@ -508,29 +401,62 @@ class PacketBuilder {
508
401
  // runTurn. They surface naturally in this query without synthetic
509
402
  // EDIT/READ delivery rows.
510
403
  const rows = await this.#db.engine_render_log.all({ worker_id: workerId });
511
- return rows.map((r) => ({
512
- coordinate: `${r.loop_seq}/${r.turn_seq}/${r.sequence}`,
513
- origin: r.origin,
514
- op: r.op,
515
- suffix: r.suffix,
516
- signal: r.signal === null ? null : JSON.parse(r.signal),
517
- target: {
518
- scheme: r.scheme,
519
- username: r.username, password: r.password,
520
- hostname: r.hostname, port: r.port,
521
- pathname: r.pathname,
522
- query: r.query,
523
- fragment: r.fragment,
524
- },
525
- status: r.status_rx,
526
- rx: r.mimetype_rx === "application/json" ? JSON.parse(r.rx) : r.rx,
527
- mimetype_rx: r.mimetype_rx,
528
- tx: r.mimetype_tx === "application/json" ? JSON.parse(r.tx) : r.tx,
529
- mimetype_tx: r.mimetype_tx,
530
- folded: r.expanded === 0 && r.id !== transientOpenLogEntryId,
531
- source: r.source,
532
- attrs: r.attrs === null ? null : JSON.parse(r.attrs),
533
- }));
404
+ return rows.map((r) => {
405
+ const tx = r.mimetype_tx === "application/json" ? JSON.parse(r.tx) : r.tx;
406
+ const rx = r.mimetype_rx === "application/json" ? JSON.parse(r.rx) : r.rx;
407
+ const rawLineAnchors = LogEntryProjection.op(r) === "READ"
408
+ && r.status_rx === 200
409
+ && rx !== null
410
+ && typeof rx === "object"
411
+ && Object.hasOwn(rx, "lineAnchors")
412
+ ? rx.lineAnchors
413
+ : undefined;
414
+ if (rawLineAnchors !== undefined && !Array.isArray(rawLineAnchors)) {
415
+ throw new TypeError("A READ result's lineAnchors field must be an array.");
416
+ }
417
+ const lineAnchors = rawLineAnchors;
418
+ const rawLineNumberWidth = LogEntryProjection.op(r) === "READ"
419
+ && r.status_rx === 200
420
+ && rx !== null
421
+ && typeof rx === "object"
422
+ && Object.hasOwn(rx, "lineNumberWidth")
423
+ ? rx.lineNumberWidth
424
+ : undefined;
425
+ if (rawLineNumberWidth !== undefined
426
+ && !LineAnchors.isLineNumberWidth(rawLineNumberWidth)) {
427
+ throw new TypeError("A READ result's lineNumberWidth field must be a valid decimal line width.");
428
+ }
429
+ if ((lineAnchors === undefined) !== (rawLineNumberWidth === undefined)) {
430
+ throw new TypeError("A READ result's lineAnchors and lineNumberWidth fields must appear together.");
431
+ }
432
+ const lineNumberWidth = rawLineNumberWidth;
433
+ return {
434
+ coordinate: `${r.loop_seq}/${r.turn_seq}/${r.sequence}`,
435
+ origin: r.origin,
436
+ op: r.op,
437
+ suffix: r.suffix,
438
+ signal: r.signal === null ? null : JSON.parse(r.signal),
439
+ target: {
440
+ scheme: r.scheme,
441
+ username: r.username, password: r.password,
442
+ hostname: r.hostname, port: r.port,
443
+ pathname: r.pathname,
444
+ query: r.query,
445
+ fragment: r.fragment,
446
+ },
447
+ status: r.status_rx,
448
+ rx,
449
+ mimetype_rx: r.mimetype_rx,
450
+ tx,
451
+ mimetype_tx: r.mimetype_tx,
452
+ folded: r.expanded === 0 && r.id !== transientOpenLogEntryId,
453
+ source: r.source,
454
+ attrs: r.attrs === null ? null : JSON.parse(r.attrs),
455
+ tags: JSON.parse(r.tags),
456
+ ...(lineAnchors === undefined ? {} : { lineAnchors }),
457
+ ...(lineNumberWidth === undefined ? {} : { lineNumberWidth }),
458
+ };
459
+ });
534
460
  }
535
461
  }
536
462
  _a = PacketBuilder;