@plurnk/plurnk-service 3.0.0 → 3.2.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 (280) hide show
  1. package/.env.defaults +38 -21
  2. package/INSTALL.md +38 -1
  3. package/README.md +3 -0
  4. package/SPEC.md +681 -268
  5. package/dist/build-info.json +1 -1
  6. package/dist/completions/_plurnk-service +13 -0
  7. package/dist/completions/plurnk-service.bash +19 -0
  8. package/dist/completions/plurnk-service.fish +94 -0
  9. package/dist/content/path-mimetype.d.ts.map +1 -1
  10. package/dist/content/path-mimetype.js +2 -8
  11. package/dist/content/path-mimetype.js.map +1 -1
  12. package/dist/core/AdmittedTurnExecutor.d.ts +2 -2
  13. package/dist/core/AdmittedTurnExecutor.d.ts.map +1 -1
  14. package/dist/core/AdmittedTurnExecutor.js +36 -32
  15. package/dist/core/AdmittedTurnExecutor.js.map +1 -1
  16. package/dist/core/BudgetReadout.d.ts +7 -2
  17. package/dist/core/BudgetReadout.d.ts.map +1 -1
  18. package/dist/core/BudgetReadout.js +36 -5
  19. package/dist/core/BudgetReadout.js.map +1 -1
  20. package/dist/{schemes/_derivation-use.d.ts → core/ContentUse.d.ts} +3 -3
  21. package/dist/core/ContentUse.d.ts.map +1 -0
  22. package/dist/{schemes/_derivation-use.js → core/ContentUse.js} +8 -7
  23. package/dist/core/ContentUse.js.map +1 -0
  24. package/dist/core/DataStatementRunner.d.ts.map +1 -1
  25. package/dist/core/DataStatementRunner.js +8 -20
  26. package/dist/core/DataStatementRunner.js.map +1 -1
  27. package/dist/core/Dispatcher.d.ts +11 -3
  28. package/dist/core/Dispatcher.d.ts.map +1 -1
  29. package/dist/core/Dispatcher.js +186 -109
  30. package/dist/core/Dispatcher.js.map +1 -1
  31. package/dist/core/EditMutations.js +1 -1
  32. package/dist/core/EditMutations.js.map +1 -1
  33. package/dist/core/Engine.d.ts +1 -1
  34. package/dist/core/Engine.d.ts.map +1 -1
  35. package/dist/core/Engine.js +4 -7
  36. package/dist/core/Engine.js.map +1 -1
  37. package/dist/core/EnvFlags.js +1 -1
  38. package/dist/core/EnvFlags.js.map +1 -1
  39. package/dist/core/FabricatedLog.d.ts +1 -0
  40. package/dist/core/FabricatedLog.d.ts.map +1 -1
  41. package/dist/core/FabricatedLog.js +8 -0
  42. package/dist/core/FabricatedLog.js.map +1 -1
  43. package/dist/core/FileAddress.d.ts +12 -0
  44. package/dist/core/FileAddress.d.ts.map +1 -0
  45. package/dist/core/FileAddress.js +73 -0
  46. package/dist/core/FileAddress.js.map +1 -0
  47. package/dist/core/FilePublication.d.ts +15 -0
  48. package/dist/core/FilePublication.d.ts.map +1 -0
  49. package/dist/core/FilePublication.js +143 -0
  50. package/dist/core/FilePublication.js.map +1 -0
  51. package/dist/core/FileSnapshot.d.ts +26 -0
  52. package/dist/core/FileSnapshot.d.ts.map +1 -0
  53. package/dist/core/FileSnapshot.js +179 -0
  54. package/dist/core/FileSnapshot.js.map +1 -0
  55. package/dist/core/KillHandler.d.ts.map +1 -1
  56. package/dist/core/KillHandler.js +4 -1
  57. package/dist/core/KillHandler.js.map +1 -1
  58. package/dist/core/LiveSubscription.d.ts.map +1 -1
  59. package/dist/core/LiveSubscription.js +14 -2
  60. package/dist/core/LiveSubscription.js.map +1 -1
  61. package/dist/core/LiveSubscriptions.d.ts +3 -1
  62. package/dist/core/LiveSubscriptions.d.ts.map +1 -1
  63. package/dist/core/LiveSubscriptions.js +16 -1
  64. package/dist/core/LiveSubscriptions.js.map +1 -1
  65. package/dist/core/LogBody.d.ts.map +1 -1
  66. package/dist/core/LogBody.js +3 -1
  67. package/dist/core/LogBody.js.map +1 -1
  68. package/dist/core/LoopDriver.d.ts.map +1 -1
  69. package/dist/core/LoopDriver.js +3 -0
  70. package/dist/core/LoopDriver.js.map +1 -1
  71. package/dist/core/LoopLifecycle.sql +1 -0
  72. package/dist/core/MembershipMaterialization.d.ts.map +1 -1
  73. package/dist/core/MembershipMaterialization.js +87 -143
  74. package/dist/core/MembershipMaterialization.js.map +1 -1
  75. package/dist/core/MessageResources.sql +31 -0
  76. package/dist/core/MutationEffects.d.ts +2 -1
  77. package/dist/core/MutationEffects.d.ts.map +1 -1
  78. package/dist/core/MutationEffects.js +14 -1
  79. package/dist/core/MutationEffects.js.map +1 -1
  80. package/dist/core/PacketBuilder.d.ts +2 -2
  81. package/dist/core/PacketBuilder.d.ts.map +1 -1
  82. package/dist/core/PacketBuilder.js +123 -51
  83. package/dist/core/PacketBuilder.js.map +1 -1
  84. package/dist/core/PacketBuilder.sql +21 -14
  85. package/dist/core/PathGlob.d.ts +6 -0
  86. package/dist/core/PathGlob.d.ts.map +1 -0
  87. package/dist/core/PathGlob.js +24 -0
  88. package/dist/core/PathGlob.js.map +1 -0
  89. package/dist/core/ProposalLifecycle.d.ts +2 -1
  90. package/dist/core/ProposalLifecycle.d.ts.map +1 -1
  91. package/dist/core/ProposalLifecycle.js +45 -33
  92. package/dist/core/ProposalLifecycle.js.map +1 -1
  93. package/dist/core/ProposalLifecycle.sql +4 -0
  94. package/dist/core/ReplyMetadata.d.ts +10 -0
  95. package/dist/core/ReplyMetadata.d.ts.map +1 -0
  96. package/dist/core/ReplyMetadata.js +20 -0
  97. package/dist/core/ReplyMetadata.js.map +1 -0
  98. package/dist/core/ResourceBindings.d.ts.map +1 -1
  99. package/dist/core/ResourceBindings.js +4 -3
  100. package/dist/core/ResourceBindings.js.map +1 -1
  101. package/dist/core/ResourceSelector.d.ts +1 -2
  102. package/dist/core/ResourceSelector.d.ts.map +1 -1
  103. package/dist/core/ResourceSelector.js +30 -9
  104. package/dist/core/ResourceSelector.js.map +1 -1
  105. package/dist/core/ResourceTransfers.d.ts +1 -1
  106. package/dist/core/ResourceTransfers.d.ts.map +1 -1
  107. package/dist/core/ResourceTransfers.js +26 -11
  108. package/dist/core/ResourceTransfers.js.map +1 -1
  109. package/dist/core/ServiceHelp.d.ts +6 -0
  110. package/dist/core/ServiceHelp.d.ts.map +1 -0
  111. package/dist/core/ServiceHelp.js +35 -0
  112. package/dist/core/ServiceHelp.js.map +1 -0
  113. package/dist/core/StoredPacket.d.ts +1 -0
  114. package/dist/core/StoredPacket.d.ts.map +1 -1
  115. package/dist/core/StoredPacket.js +4 -1
  116. package/dist/core/StoredPacket.js.map +1 -1
  117. package/dist/core/StrikeRail.d.ts.map +1 -1
  118. package/dist/core/StrikeRail.js +2 -2
  119. package/dist/core/StrikeRail.js.map +1 -1
  120. package/dist/core/TokenCalibration.d.ts +2 -2
  121. package/dist/core/TokenCalibration.d.ts.map +1 -1
  122. package/dist/core/TokenCalibration.js +12 -16
  123. package/dist/core/TokenCalibration.js.map +1 -1
  124. package/dist/core/TokenCalibration.sql +29 -6
  125. package/dist/core/TurnDispositionHandler.d.ts +1 -2
  126. package/dist/core/TurnDispositionHandler.d.ts.map +1 -1
  127. package/dist/core/TurnDispositionHandler.js +30 -26
  128. package/dist/core/TurnDispositionHandler.js.map +1 -1
  129. package/dist/core/TurnMaterialization.d.ts.map +1 -1
  130. package/dist/core/TurnMaterialization.js +11 -1
  131. package/dist/core/TurnMaterialization.js.map +1 -1
  132. package/dist/core/TurnOps.d.ts +5 -1
  133. package/dist/core/TurnOps.d.ts.map +1 -1
  134. package/dist/core/TurnOps.js +29 -2
  135. package/dist/core/TurnOps.js.map +1 -1
  136. package/dist/core/TurnRunner.d.ts.map +1 -1
  137. package/dist/core/TurnRunner.js +122 -56
  138. package/dist/core/TurnRunner.js.map +1 -1
  139. package/dist/core/TurnSources.sql +2 -2
  140. package/dist/core/caps/SchemeCtxImpl.d.ts +1 -0
  141. package/dist/core/caps/SchemeCtxImpl.d.ts.map +1 -1
  142. package/dist/core/caps/SchemeCtxImpl.js +5 -0
  143. package/dist/core/caps/SchemeCtxImpl.js.map +1 -1
  144. package/dist/core/git-membership.d.ts +1 -0
  145. package/dist/core/git-membership.d.ts.map +1 -1
  146. package/dist/core/git-membership.js +9 -11
  147. package/dist/core/git-membership.js.map +1 -1
  148. package/dist/core/glob_match.js +3 -3
  149. package/dist/core/glob_match.js.map +1 -1
  150. package/dist/core/mutation-types.d.ts +3 -0
  151. package/dist/core/mutation-types.d.ts.map +1 -1
  152. package/dist/core/namespace.d.ts +4 -1
  153. package/dist/core/namespace.d.ts.map +1 -1
  154. package/dist/core/namespace.js +14 -3
  155. package/dist/core/namespace.js.map +1 -1
  156. package/dist/core/packet-wire.d.ts +7 -1
  157. package/dist/core/packet-wire.d.ts.map +1 -1
  158. package/dist/core/packet-wire.js +98 -36
  159. package/dist/core/packet-wire.js.map +1 -1
  160. package/dist/core/plurnk-uri.d.ts +3 -2
  161. package/dist/core/plurnk-uri.d.ts.map +1 -1
  162. package/dist/core/plurnk-uri.js +23 -11
  163. package/dist/core/plurnk-uri.js.map +1 -1
  164. package/dist/core/recap-lines.d.ts +4 -0
  165. package/dist/core/recap-lines.d.ts.map +1 -0
  166. package/dist/core/recap-lines.js +11 -0
  167. package/dist/core/recap-lines.js.map +1 -0
  168. package/dist/core/scheme-types.d.ts +1 -0
  169. package/dist/core/scheme-types.d.ts.map +1 -1
  170. package/dist/core/sql-functions.d.ts +2 -0
  171. package/dist/core/sql-functions.d.ts.map +1 -0
  172. package/dist/core/sql-functions.js +5 -0
  173. package/dist/core/sql-functions.js.map +1 -0
  174. package/dist/core/sqlite-synchronous.d.ts +2 -0
  175. package/dist/core/sqlite-synchronous.d.ts.map +1 -0
  176. package/dist/core/sqlite-synchronous.js +4 -0
  177. package/dist/core/sqlite-synchronous.js.map +1 -0
  178. package/dist/core/turn-scheduler.d.ts.map +1 -1
  179. package/dist/core/turn-scheduler.js +1 -1
  180. package/dist/core/turn-scheduler.js.map +1 -1
  181. package/dist/evidence/EvidenceReader.d.ts.map +1 -1
  182. package/dist/evidence/EvidenceReader.js +23 -3
  183. package/dist/evidence/EvidenceReader.js.map +1 -1
  184. package/dist/evidence/digest.sql +7 -1
  185. package/dist/man/plurnk-service.1 +499 -0
  186. package/dist/schemes/Env.d.ts +26 -0
  187. package/dist/schemes/Env.d.ts.map +1 -0
  188. package/dist/schemes/Env.js +133 -0
  189. package/dist/schemes/Env.js.map +1 -0
  190. package/dist/schemes/Exec.d.ts.map +1 -1
  191. package/dist/schemes/Exec.js +15 -15
  192. package/dist/schemes/Exec.js.map +1 -1
  193. package/dist/schemes/ExecOutputScheme.d.ts +3 -2
  194. package/dist/schemes/ExecOutputScheme.d.ts.map +1 -1
  195. package/dist/schemes/ExecOutputScheme.js +9 -0
  196. package/dist/schemes/ExecOutputScheme.js.map +1 -1
  197. package/dist/schemes/File.d.ts +1 -0
  198. package/dist/schemes/File.d.ts.map +1 -1
  199. package/dist/schemes/File.js +233 -268
  200. package/dist/schemes/File.js.map +1 -1
  201. package/dist/schemes/Log.d.ts.map +1 -1
  202. package/dist/schemes/Log.js +97 -17
  203. package/dist/schemes/Log.js.map +1 -1
  204. package/dist/schemes/Log.sql +9 -0
  205. package/dist/schemes/Worker.js +1 -1
  206. package/dist/schemes/Worker.js.map +1 -1
  207. package/dist/schemes/_entry-crud.d.ts +2 -0
  208. package/dist/schemes/_entry-crud.d.ts.map +1 -1
  209. package/dist/schemes/_entry-crud.js +8 -5
  210. package/dist/schemes/_entry-crud.js.map +1 -1
  211. package/dist/schemes/_entry-crud.sql +15 -15
  212. package/dist/schemes/_entry-find.d.ts +2 -1
  213. package/dist/schemes/_entry-find.d.ts.map +1 -1
  214. package/dist/schemes/_entry-find.js +31 -19
  215. package/dist/schemes/_entry-find.js.map +1 -1
  216. package/dist/schemes/_entry-manifest.d.ts +2 -2
  217. package/dist/schemes/_entry-manifest.d.ts.map +1 -1
  218. package/dist/schemes/_entry-manifest.js +10 -8
  219. package/dist/schemes/_entry-manifest.js.map +1 -1
  220. package/dist/schemes/_entry-ops.d.ts.map +1 -1
  221. package/dist/schemes/_entry-ops.js +9 -7
  222. package/dist/schemes/_entry-ops.js.map +1 -1
  223. package/dist/schemes/_path-scope.d.ts.map +1 -1
  224. package/dist/schemes/_path-scope.js +12 -4
  225. package/dist/schemes/_path-scope.js.map +1 -1
  226. package/dist/schemes/_search-index.js +3 -3
  227. package/dist/schemes/_search-index.js.map +1 -1
  228. package/dist/schemes/exec-abort.js +2 -2
  229. package/dist/schemes/exec-abort.js.map +1 -1
  230. package/dist/schemes/exec-env.d.ts.map +1 -1
  231. package/dist/schemes/exec-env.js +7 -22
  232. package/dist/schemes/exec-env.js.map +1 -1
  233. package/dist/server/Daemon.d.ts +1 -0
  234. package/dist/server/Daemon.d.ts.map +1 -1
  235. package/dist/server/Daemon.js +45 -68
  236. package/dist/server/Daemon.js.map +1 -1
  237. package/dist/server/DrainSupervisor.d.ts +2 -3
  238. package/dist/server/DrainSupervisor.d.ts.map +1 -1
  239. package/dist/server/DrainSupervisor.js +34 -6
  240. package/dist/server/DrainSupervisor.js.map +1 -1
  241. package/dist/server/EnvFunctionality.d.ts +4 -2
  242. package/dist/server/EnvFunctionality.d.ts.map +1 -1
  243. package/dist/server/EnvFunctionality.js +23 -12
  244. package/dist/server/EnvFunctionality.js.map +1 -1
  245. package/dist/server/Functionality.d.ts.map +1 -1
  246. package/dist/server/Functionality.js +15 -8
  247. package/dist/server/Functionality.js.map +1 -1
  248. package/dist/server/FunctionalityManager.d.ts +1 -1
  249. package/dist/server/FunctionalityManager.d.ts.map +1 -1
  250. package/dist/server/FunctionalityManager.js +5 -1
  251. package/dist/server/FunctionalityManager.js.map +1 -1
  252. package/dist/server/MembersFunctionality.d.ts.map +1 -1
  253. package/dist/server/MembersFunctionality.js +12 -12
  254. package/dist/server/MembersFunctionality.js.map +1 -1
  255. package/dist/server/Retention.d.ts.map +1 -1
  256. package/dist/server/Retention.js +5 -5
  257. package/dist/server/Retention.js.map +1 -1
  258. package/dist/server/Retention.sql +49 -23
  259. package/dist/server/client-input.d.ts.map +1 -1
  260. package/dist/server/client-input.js +12 -3
  261. package/dist/server/client-input.js.map +1 -1
  262. package/dist/server/drain.sql +10 -9
  263. package/dist/server/lifecycle-recovery.sql +4 -1
  264. package/dist/service.d.ts.map +1 -1
  265. package/dist/service.js +9 -31
  266. package/dist/service.js.map +1 -1
  267. package/docs/copy-move.md +3 -0
  268. package/docs/env.md +32 -4
  269. package/docs/members.md +16 -1
  270. package/migrations/018_worker_owners.sql +1 -0
  271. package/migrations/019_interactive_owners.sql +1 -0
  272. package/migrations/020_log_projection.sql +1 -0
  273. package/migrations/021_packet_roles.sql +86 -0
  274. package/migrations/022_message_completion.sql +24 -0
  275. package/migrations/023_file_revisions.sql +54 -0
  276. package/migrations/024_proposal_decisions.sql +34 -0
  277. package/migrations/025_response_retention.sql +30 -0
  278. package/package.json +38 -34
  279. package/dist/schemes/_derivation-use.d.ts.map +0 -1
  280. package/dist/schemes/_derivation-use.js.map +0 -1
@@ -72,7 +72,7 @@ SELECT pr.id, pr.inference_call_id, a.id AS turn_attempt_id, ic.kind,
72
72
  pr.usage_input_no_cache, pr.usage_input_cache_read, pr.usage_input_cache_write,
73
73
  pr.usage_output_text, pr.usage_output_reasoning,
74
74
  pr.cost_kind, pr.cost_amount, pr.cost_currency, pr.cost_usd_equivalent,
75
- pr.cost_source, pr.cost_reason, pr.started_at, pr.completed_at
75
+ pr.cost_source, pr.cost_reason, pr.started_at, pr.completed_at, ic.payloads_retired_at
76
76
  FROM provider_requests pr
77
77
  JOIN inference_calls ic ON ic.id = pr.inference_call_id
78
78
  LEFT JOIN turn_attempts a ON a.model_call_id = ic.id
@@ -87,8 +87,11 @@ SELECT * FROM provider_requests WHERE id = $request_id;
87
87
 
88
88
  -- PREP: digest_log_entries
89
89
  SELECT id, worker_id, loop_id, turn_id, sequence, at, origin, source, model_call_id,
90
+ inherited_history, ambient_event_id,
90
91
  op, signal,
91
92
  scheme, hostname, port, pathname, query, fragment,
93
+ CASE WHEN scheme IS NULL AND mimetype_tx = 'application/json'
94
+ THEN coalesce(json_extract(tx, '$.source.target'), json_extract(tx, '$.target')) END AS target_tx,
92
95
  rx, status_rx, mimetype_rx,
93
96
  state, outcome, attrs, initial_folded,
94
97
  projection.active AS projection_active,
@@ -97,6 +100,9 @@ FROM log_entries le
97
100
  JOIN log_entry_projections projection ON projection.log_entry_id = le.id
98
101
  ORDER BY loop_id, turn_id, sequence;
99
102
 
103
+ -- PREP: digest_proposal_decisions
104
+ SELECT log_entry_id, decision, resolver, body, outcome, decided_at FROM proposal_decisions;
105
+
100
106
  -- PREP: digest_worker_rollups
101
107
  -- Structural per-worker aggregates. Accounting is derived through the shared
102
108
  -- exact-decimal provider contract rather than SQLite numeric arithmetic.
@@ -0,0 +1,499 @@
1
+ .TH PLURNK-SERVICE 1 "2026-10-12" "plurnk-service 3.2.0" "User Commands"
2
+ .SH NAME
3
+ plurnk-service \- persistent agent runtime
4
+ .SH SYNOPSIS
5
+ .nf
6
+ plurnk-service [options] [start|migrate]
7
+ plurnk-service [options] config [edit|defaults|check]
8
+ plurnk-service [options] share [<file.db>] [<folder>] [--workspace=<id>] [--requiem]
9
+ plurnk-service [options] requiem <file.db> <folder>
10
+ .fi
11
+ .SH DESCRIPTION
12
+ Runs the Plurnk daemon or performs a local administrative command.
13
+ The terminal client is plurnk(1).
14
+ .SH OPTIONS AND COMMANDS
15
+ .TP
16
+ .B --service-db-path
17
+ Database path; empty = $XDG_DATA_HOME/plurnk/plurnk.db (~/.local/share
18
+ by default). Module operational state: $XDG_STATE_HOME/plurnk
19
+ (~/.local/state/plurnk by default).
20
+ (PLURNK_SERVICE_DB_PATH=)
21
+ .TP
22
+ .B --service-state-root
23
+ A private daemon's root ({§state-root}): empty = the XDG homes; an
24
+ absolute path (a leading ~/ expands) roots data, state, cache and
25
+ runtime under it as <root>/{data,state,cache,runtime}/plurnk.
26
+ Configuration and the shared Agent Skills root never move;
27
+ PLURNK_SERVICE_DB_PATH still wins.
28
+ (PLURNK_SERVICE_STATE_ROOT=)
29
+ .TP
30
+ .B --service-share-folder
31
+ Where `share` writes when no folder is named: each share is a stamped
32
+ child folder. A leading ~/ expands; empty =
33
+ $XDG_STATE_HOME/plurnk/shares (~/.local/state/plurnk/shares by default).
34
+ (PLURNK_SERVICE_SHARE_FOLDER=)
35
+ .TP
36
+ .B --service-sqlite-synchronous
37
+ WAL durability ({§db-durability}): FULL syncs every commit; NORMAL may
38
+ lose recent commits on power loss; OFF may corrupt the database; EXTRA
39
+ equals FULL in WAL. Applied before migration.
40
+ (PLURNK_SERVICE_SQLITE_SYNCHRONOUS=FULL)
41
+ .TP
42
+ .B --service-sqlite-readers
43
+ Read-only database Workers beside the one writer Worker (database
44
+ Workers = 1 + readers); 0 = every read shares the writer. Non-negative
45
+ integer. Blank = sqlrite's own default.
46
+ (PLURNK_SERVICE_SQLITE_READERS=0)
47
+ .TP
48
+ .B --service-capabilities
49
+ CapabilityPolicy JSON: deny removes matching demands; only admits only
50
+ matches. Workspace policy may narrow this ceiling, never widen it.
51
+ (PLURNK_SERVICE_CAPABILITIES={})
52
+ .TP
53
+ .B --service-proposals
54
+ Proposal settlement: review asks the worker's owner; accept or reject
55
+ settles in core. Review without a capable owner rejects. Disconnect
56
+ alone never removes that capability.
57
+ (PLURNK_SERVICE_PROPOSALS=review)
58
+ .TP
59
+ .B --service-file-create-scope
60
+ New filesystem files: none | root | namespace (also outside root).
61
+ Existing-member writes unchanged.
62
+ (PLURNK_SERVICE_FILE_CREATE_SCOPE=root)
63
+ .TP
64
+ .B --service-members-model-scope
65
+ Model-added membership: none | root | namespace. Workspaces may narrow
66
+ it.
67
+ (PLURNK_SERVICE_MEMBERS_MODEL_SCOPE=namespace)
68
+ .TP
69
+ .B --members-enabled
70
+ Enable declared membership rules by default; per-alias _ENABLED
71
+ overrides this.
72
+ (PLURNK_MEMBERS_ENABLED=1)
73
+ .TP
74
+ .B --service-members-sample
75
+ Matched paths a members definition lists as its sample; the rest are
76
+ counted.
77
+ (PLURNK_SERVICE_MEMBERS_SAMPLE=20)
78
+ .TP
79
+ .B --service-git-allowed
80
+ Git membership, status, and branch integration: 1 = permitted; 0 =
81
+ denied service-wide.
82
+ (PLURNK_SERVICE_GIT_ALLOWED=1)
83
+ .TP
84
+ .B --service-git-auto
85
+ Include the repository containing project_root as members: 1 = yes; 0 =
86
+ explicit members only.
87
+ (PLURNK_SERVICE_GIT_AUTO=1)
88
+ .TP
89
+ .B --service-git-output-max-bytes
90
+ Maximum stdout/stderr bytes accepted from one native Git subprocess.
91
+ (PLURNK_SERVICE_GIT_OUTPUT_MAX_BYTES=67108864)
92
+ .TP
93
+ .B --service-file-materialize-max-bytes
94
+ Maximum bytes per workspace-file snapshot, 1..104857600. Larger sources
95
+ return 413 on READ/EDIT.
96
+ (PLURNK_SERVICE_FILE_MATERIALIZE_MAX_BYTES=104857600)
97
+ .TP
98
+ .B --service-max-turns
99
+ Opt-in model-call ceiling shared by the worker tree, including BARE and
100
+ resumes; -1 = uncapped. Runtime (_plurnk) ancestry supplies no ceiling.
101
+ Clients may tighten the model tree's limit.
102
+ (PLURNK_SERVICE_MAX_TURNS=-1)
103
+ .TP
104
+ .B --service-max-commands
105
+ Resolved actions per emission, including glob targets; -1 = unlimited.
106
+ WAIT remains exempt.
107
+ (PLURNK_SERVICE_MAX_COMMANDS=-1)
108
+ .TP
109
+ .B --service-workspace-workers-max-active
110
+ Concurrent live workers per workspace; -1 = unlimited. Excess spawns
111
+ return 508, not a queue.
112
+ (PLURNK_SERVICE_WORKSPACE_WORKERS_MAX_ACTIVE=-1)
113
+ .TP
114
+ .B --service-loop-timeout
115
+ Active execution allowance per task, positive ms; WAIT pauses it, wakes
116
+ retain it. Exhaustion: 504.
117
+ (PLURNK_SERVICE_LOOP_TIMEOUT=86400000)
118
+ .TP
119
+ .B --service-live-timeout
120
+ Live/demo whole-specimen deadline, ms; includes all prompts and cancels
121
+ before cleanup.
122
+ (PLURNK_SERVICE_LIVE_TIMEOUT=600000)
123
+ .TP
124
+ .B --service-stop-timeout-ms
125
+ End-to-end shutdown budget, positive ms; includes database and listener
126
+ cleanup.
127
+ (PLURNK_SERVICE_STOP_TIMEOUT_MS=30000)
128
+ .TP
129
+ .B --service-provider-recovery
130
+ Provider recovery window, ms; 0 = no reissue. Expiry parks workers with
131
+ a reviewer; without one the loop concludes. BARE returns the provider
132
+ failure.
133
+ (PLURNK_SERVICE_PROVIDER_RECOVERY=900000)
134
+ .TP
135
+ .B --service-provider-recovery-backoff
136
+ First recovery delay, ms; doubles on failure up to
137
+ PROVIDER_RECOVERY_BACKOFF_MAX below.
138
+ (PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF=5000)
139
+ .TP
140
+ .B --service-provider-recovery-backoff-max
141
+ Ceiling of that doubling delay, ms.
142
+ (PLURNK_SERVICE_PROVIDER_RECOVERY_BACKOFF_MAX=60000)
143
+ .TP
144
+ .B --service-max-strikes
145
+ Consecutive turn-contract strike threshold.
146
+ (PLURNK_SERVICE_MAX_STRIKES=3)
147
+ .TP
148
+ .B --service-emission-attempts
149
+ Completed responses allowed to produce an admissible turn against the
150
+ same packet.
151
+ (PLURNK_SERVICE_EMISSION_ATTEMPTS=3)
152
+ .TP
153
+ .B --service-min-cycles
154
+ Minimum repetitions before cycle detection fires.
155
+ (PLURNK_SERVICE_MIN_CYCLES=3)
156
+ .TP
157
+ .B --service-max-cycle-period
158
+ Maximum repeating period examined by cycle detection, turns.
159
+ (PLURNK_SERVICE_MAX_CYCLE_PERIOD=4)
160
+ .TP
161
+ .B --service-error-detail-limit
162
+ Maximum characters of runtime diagnostics exposed in model-facing
163
+ errors.
164
+ (PLURNK_SERVICE_ERROR_DETAIL_LIMIT=512)
165
+ .TP
166
+ .B --service-workspace-warm-ms
167
+ Idle workspace Functionality grace, ms; 0 = cool immediately; -1 = no
168
+ time limit.
169
+ (PLURNK_SERVICE_WORKSPACE_WARM_MS=900000)
170
+ .TP
171
+ .B --service-workspace-warm-max
172
+ Retained idle workspace snapshots; 0 = none; -1 = unlimited. Active work
173
+ is exempt.
174
+ (PLURNK_SERVICE_WORKSPACE_WARM_MAX=2)
175
+ .TP
176
+ .B --service-proposal-timeout-ms
177
+ Proposal wait, positive ms; empty = wait indefinitely. Expiry cancels
178
+ the proposal.
179
+ (PLURNK_SERVICE_PROPOSAL_TIMEOUT_MS=)
180
+ .TP
181
+ .B --service-exec-hold
182
+ Comma-separated runtime or runtime:effect names that hold the next turn
183
+ while executing; empty = none.
184
+ (PLURNK_SERVICE_EXEC_HOLD=)
185
+ .TP
186
+ .B --service-exec-hold-ms
187
+ Maximum turn hold, ms; expiry lets the loop continue while the stream
188
+ remains live.
189
+ (PLURNK_SERVICE_EXEC_HOLD_MS=300000)
190
+ .TP
191
+ .B --service-exec-concurrency
192
+ Concurrent EXEC producers per workspace; excess executions wait FIFO; -1
193
+ = unlimited.
194
+ (PLURNK_SERVICE_EXEC_CONCURRENCY=12)
195
+ .TP
196
+ .B --service-exec-input-timeout-ms
197
+ Live input delivery deadline, positive ms, including queued writes;
198
+ expiry retires input, not the process.
199
+ (PLURNK_SERVICE_EXEC_INPUT_TIMEOUT_MS=10000)
200
+ .TP
201
+ .B --service-exec-probe-timeout-ms
202
+ Deadline for one runtime's availability probe at boot, positive ms;
203
+ expiry reports it unavailable.
204
+ (PLURNK_SERVICE_EXEC_PROBE_TIMEOUT_MS=3000)
205
+ .TP
206
+ .B --service-exec-scratch
207
+ Directory a non-file execution source (`sh (log:///…)`) is written to
208
+ for its run, created 0700 on first use ({§exec-scratch-directory}).
209
+ Empty = $XDG_RUNTIME_DIR/plurnk, else the platform temporary directory.
210
+ An executor in another filesystem namespace (a container that mounts
211
+ only the repository) must see the same directory: point this at one it
212
+ mounts.
213
+ (PLURNK_SERVICE_EXEC_SCRATCH=)
214
+ .TP
215
+ .B --service-effect-host
216
+ What an operation that runs code or changes the world does: propose = it
217
+ needs a settlement; auto = it runs ungated. This covers a subprocess and
218
+ an outbound POST, PUT or DELETE alike.
219
+ (PLURNK_SERVICE_EFFECT_HOST=propose)
220
+ .TP
221
+ .B --service-effect-read
222
+ The same for an operation that only observes external state.
223
+ (PLURNK_SERVICE_EFFECT_READ=auto)
224
+ .TP
225
+ .B --service-effect-pure
226
+ The same for an operation with no observable effect.
227
+ (PLURNK_SERVICE_EFFECT_PURE=auto)
228
+ .TP
229
+ .B --service-optimistic-wait-ms
230
+ Brief settlement wait for new streams/completing siblings, ms; 0 = off;
231
+ quiescence ends it early.
232
+ (PLURNK_SERVICE_OPTIMISTIC_WAIT_MS=5000)
233
+ .TP
234
+ .B --service-wait-sec
235
+ Maximum park before reassessing live work, positive seconds; WAIT
236
+ [seconds] overrides one park.
237
+ (PLURNK_SERVICE_WAIT_SEC=300)
238
+ .TP
239
+ .B --service-exec-env-inherit
240
+ Ambient environment an EXEC subprocess may inherit from the host: exact
241
+ names, or one trailing-* prefix glob. This bounds inherited host values,
242
+ not explicit non-reserved values. PLURNK_* and provider credential names
243
+ remain excluded regardless of these selectors. Module-owned launches and
244
+ explicit MCP bindings follow their own launch contract. The shipped list
245
+ is what a shell, git, node and python need to run at all. An operator
246
+ who wants a non-reserved tool credential inherited by commands adds its
247
+ name.
248
+ (PLURNK_SERVICE_EXEC_ENV_INHERIT=PATH,HOME,USER,LOGNAME,SHELL,PWD,TMPDIR,TERM,TZ,LANG,LC_*,PAGER,GIT_PAGER,NO_COLOR,CI)
249
+ .TP
250
+ .B --service-exec-env-exclude
251
+ Names removed after INHERIT, same shapes; narrows without rewriting the
252
+ list above.
253
+ (PLURNK_SERVICE_EXEC_ENV_EXCLUDE=)
254
+ .TP
255
+ .B --service-exec-kill-grace-ms
256
+ Grace after a termination signal, ms; then SIGKILL the surviving process
257
+ group.
258
+ (PLURNK_SERVICE_EXEC_KILL_GRACE_MS=2000)
259
+ .TP
260
+ .B --service-line-anchor-context-lines
261
+ Minimum neighbors hashed on each side of an editable line anchor;
262
+ repeated handles widen context.
263
+ (PLURNK_SERVICE_LINE_ANCHOR_CONTEXT_LINES=2)
264
+ .TP
265
+ .B --service-edit-receipt-context-lines
266
+ Surrounding and changed lines shown at each EDIT boundary; overlapping
267
+ windows coalesce.
268
+ (PLURNK_SERVICE_EDIT_RECEIPT_CONTEXT_LINES=4)
269
+ .TP
270
+ .B --service-edit-receipt-removed-lines
271
+ Removed lines a pure deletion's receipt carries so it can be undone; a
272
+ longer span is cut and counted.
273
+ (PLURNK_SERVICE_EDIT_RECEIPT_REMOVED_LINES=40)
274
+ .TP
275
+ .B --service-git-status-paths
276
+ Paths named per class in the packet's git status; the rest are counted.
277
+ (PLURNK_SERVICE_GIT_STATUS_PATHS=8)
278
+ .TP
279
+ .B --service-budget-pressure
280
+ Above this share of the budget, measured before adding either, the
281
+ Context gauge names its largest rows and a packet within its budget
282
+ carries the budget_pressure notice ({§context-pressure-notice}).
283
+ (PLURNK_SERVICE_BUDGET_PRESSURE=80%)
284
+ .TP
285
+ .B --service-budget-largest-items
286
+ Heaviest retained log rows the pressured Context gauge names, as {path,
287
+ tokens}; 0 names none.
288
+ (PLURNK_SERVICE_BUDGET_LARGEST_ITEMS=5)
289
+ .TP
290
+ .B --service-preview-lines
291
+ First page of everything that comes back unasked in size: a READ or FIND
292
+ without a scope, a stream's delivery, a peer worker's message, a receipt
293
+ the model did not author ({§markerless-first-page}). Lines of text,
294
+ bytes of a byte view, results of a FIND; explicit scopes stay exact. 100
295
+ is a page for the million-token windows hosted models have; a deployment
296
+ with a small room tunes it down.
297
+ (PLURNK_SERVICE_PREVIEW_LINES=100)
298
+ .TP
299
+ .B --service-preview-chars
300
+ Independent bound on the same page, Unicode code points; CRLF counts as
301
+ one separator.
302
+ (PLURNK_SERVICE_PREVIEW_CHARS=16000)
303
+ .TP
304
+ .B --service-emission-history
305
+ Assistant replay ({§emission-history}): none, latest, or all eligible
306
+ turns from this loop, each as the NOTEs it wrote, in the model's voice;
307
+ every other operation is omitted. The context wall may omit the whole
308
+ section; source evidence never changes.
309
+ (PLURNK_SERVICE_EMISSION_HISTORY=all)
310
+ .TP
311
+ .B --service-reasoning-rows
312
+ Optional reasoning memory ({§reasoning-row}): 1 adds the turn's preview
313
+ before its emission or results, only when room remains after all
314
+ requested results and diagnostics. Otherwise omit it silently. 0
315
+ disables it.
316
+ (PLURNK_SERVICE_REASONING_ROWS=0)
317
+ .TP
318
+ .B --service-catalog-summary-chars
319
+ Code points of an entry's prose summary the catalog shows whole.
320
+ (PLURNK_SERVICE_CATALOG_SUMMARY_CHARS=256)
321
+ .TP
322
+ .B --service-log-read-page
323
+ Log entries one client read returns when it names no limit.
324
+ (PLURNK_SERVICE_LOG_READ_PAGE=100)
325
+ .TP
326
+ .B --service-log-read-max
327
+ Ceiling of one client log read, whatever limit it names.
328
+ (PLURNK_SERVICE_LOG_READ_MAX=1000)
329
+ .TP
330
+ .B --service-prompts-page
331
+ Root-conversation prompts one listing returns when it names no limit.
332
+ (PLURNK_SERVICE_PROMPTS_PAGE=100)
333
+ .TP
334
+ .B --service-model-catalog-page
335
+ Models one catalog page lists when the query names no limit.
336
+ (PLURNK_SERVICE_MODEL_CATALOG_PAGE=50)
337
+ .TP
338
+ .B --service-files-items
339
+ Turn-0 surveys: -1 = whole surveys (each fits the budget or lands as its
340
+ size); N > 0 caps file-map rows; 0 = off. Workspace settings.filesItems
341
+ overrides this default; other surveys stay whole.
342
+ (PLURNK_SERVICE_FILES_ITEMS=-1)
343
+ .TP
344
+ .B --service-docs-exclude
345
+ Scheme names omitted from discoverable references, comma-separated;
346
+ empty = none. Executable docs instead follow tool enablement. Extension
347
+ trust lives in plurnk-meta's defaults.
348
+ (PLURNK_SERVICE_DOCS_EXCLUDE=plurnk,file,exec)
349
+ .TP
350
+ .B --service-roots
351
+ Skills, plugin and standalone MCP configuration roots, comma-separated,
352
+ nearest first: project (the workspace project's .agents), plurnk
353
+ ($XDG_CONFIG_HOME/plurnk), global (~/.agents).
354
+ (PLURNK_SERVICE_ROOTS=project,plurnk,global)
355
+ .TP
356
+ .B --service-search-exclude
357
+ Comma-separated globs excluded from derivation, not READ. No slash =
358
+ basename; slash = pathname.
359
+ (PLURNK_SERVICE_SEARCH_EXCLUDE=*.min.*,*.map,package-lock.json,npm-shrinkwrap.json,packages.lock.json,yarn.lock,pnpm-lock.yaml,bun.lockb,Cargo.lock,poetry.lock,uv.lock,Pipfile.lock,Gemfile.lock,composer.lock,go.sum,flake.lock,gradle.lockfile,*/dist/*,dist/*,*/build/*,build/*,*/.next/*,.next/*,*/node_modules/*,node_modules/*,*/vendor/*,vendor/*,*/coverage/*,coverage/*,*/.vuepress/*,.vuepress/*,*/.nuxt/*,.nuxt/*)
360
+ .TP
361
+ .B --service-search-max-bytes
362
+ Bodies larger than this many bytes are not parsed or full-text indexed
363
+ (READ is unaffected); empty = unbounded.
364
+ (PLURNK_SERVICE_SEARCH_MAX_BYTES=)
365
+ .TP
366
+ .B --service-derive-concurrency
367
+ Concurrent parser derivations: empty = sqrt(available cores); -1 = all
368
+ cores; positive N = exact cap.
369
+ (PLURNK_SERVICE_DERIVE_CONCURRENCY=)
370
+ .TP
371
+ .B --service-derive-store-batch
372
+ Maximum symbol/reference rows per indexing SQLite statement.
373
+ (PLURNK_SERVICE_DERIVE_STORE_BATCH=1024)
374
+ .TP
375
+ .B --service-derive-progress-heartbeat-ms
376
+ Progress heartbeat, ms; starts, failures, and completion are immediate;
377
+ no-op passes stay silent.
378
+ (PLURNK_SERVICE_DERIVE_PROGRESS_HEARTBEAT_MS=15000)
379
+ .TP
380
+ .B --service-retain-packet-turns
381
+ Packet compositions kept per loop, newest first; -1 disables the count
382
+ limit, not the age limit.
383
+ (PLURNK_SERVICE_RETAIN_PACKET_TURNS=-1)
384
+ .TP
385
+ .B --service-retain-packet-ms
386
+ Packet compositions kept by age, ms since the turn completed; -1
387
+ disables the age limit.
388
+ (PLURNK_SERVICE_RETAIN_PACKET_MS=2592000000)
389
+ .TP
390
+ .B --service-retain-response-turns
391
+ Calls with captured payloads kept per loop, newest first; -1 disables
392
+ the count limit. These controls do not retire messages, turn sources,
393
+ operations, approval decisions or accounting.
394
+ (PLURNK_SERVICE_RETAIN_RESPONSE_TURNS=-1)
395
+ .TP
396
+ .B --service-retain-response-ms
397
+ Call payloads kept by age, ms since the turn completed; -1 disables the
398
+ age limit. Covers normalized responses and all physical-request
399
+ payloads, including failed retries. Identities, status, usage and cost
400
+ remain; retirement is timestamped on the logical call.
401
+ (PLURNK_SERVICE_RETAIN_RESPONSE_MS=2592000000)
402
+ .TP
403
+ .B --service-collect-packet-items
404
+ Collect packet items no turn's composition references (1), or keep them
405
+ (0).
406
+ (PLURNK_SERVICE_COLLECT_PACKET_ITEMS=1)
407
+ .TP
408
+ .B --service-collect-derivations
409
+ Collect derivations no channel, turn source, or log row cites (1), or
410
+ keep them (0).
411
+ (PLURNK_SERVICE_COLLECT_DERIVATIONS=1)
412
+ .TP
413
+ .B --service-collect-contents
414
+ Collect unreferenced text and native bodies (1), or keep them (0).
415
+ Retained messages, operations and packet attachments pin native bytes
416
+ ({§native-content-lifetime}).
417
+ (PLURNK_SERVICE_COLLECT_CONTENTS=1)
418
+ .TP
419
+ .B --service-retention-interval-ms
420
+ Retention cadence while the daemon runs, ms; 0 = at shutdown only.
421
+ (PLURNK_SERVICE_RETENTION_INTERVAL_MS=3600000)
422
+ .TP
423
+ .B --service-auto-vacuum
424
+ SQLite auto-vacuum mode the daemon keeps its file in
425
+ ({§db-space-reclamation}): incremental = retention passes return free
426
+ pages to the OS; none = the file only grows, and freed pages are reused.
427
+ A change takes effect at the next start through one VACUUM, which
428
+ rewrites the whole file (needs free disk about the file's size and
429
+ blocks the daemon for its duration).
430
+ (PLURNK_SERVICE_AUTO_VACUUM=incremental)
431
+ .TP
432
+ .B --service-reclaim-min-free-bytes
433
+ Free space, bytes, below which a retention pass leaves free pages for
434
+ SQLite to reuse instead of returning them; 0 = return every free page
435
+ each pass.
436
+ (PLURNK_SERVICE_RECLAIM_MIN_FREE_BYTES=0)
437
+ .TP
438
+ .B --host
439
+ Where the daemon listens, and so where a local client dials: one line
440
+ moves both.
441
+ (PLURNK_HOST=127.0.0.1)
442
+ .TP
443
+ .B --port
444
+ The daemon's TCP port, shared by all client interfaces.
445
+ (PLURNK_PORT=1066)
446
+ .TP
447
+ .B --env-file=<path>
448
+ layer env from <path> (repeatable; later wins; errors if
449
+ missing)
450
+ .TP
451
+ .B --env-file-if-exists=<path>
452
+ layer env from <path> if present (repeatable; later
453
+ wins)
454
+ .TP
455
+ .B --config=<path>
456
+ layer additional env from
457
+ <path>
458
+ .TP
459
+ .B config defaults
460
+ print every installed package's annotated
461
+ \&.env.defaults
462
+ .TP
463
+ .B config check
464
+ validate configuration without contacting a
465
+ provider
466
+ .TP
467
+ .B share
468
+ share a consistent copy of the database as a digest <folder> (default
469
+ database: the service's; default folder: a stamped child of
470
+ PLURNK_SERVICE_SHARE_FOLDER); --workspace=<id> limits it to one
471
+ workspace; --requiem adds the forensic interview (calls a
472
+ model)
473
+ .TP
474
+ .B requiem
475
+ add the forensic interview to a digest <folder> of <file.db> (calls a
476
+ model)
477
+ .TP
478
+ .B -v, --version
479
+ show executable
480
+ provenance
481
+ .TP
482
+ .B -h, --help
483
+ show this
484
+ help
485
+ .SH CONFIGURATION
486
+ Run plurnk-service config defaults for the installed configuration catalog,
487
+ or plurnk-service config check to validate configuration
488
+ without contacting a provider.
489
+ The package's INSTALL.md describes the configuration cascade
490
+ and resource scopes.
491
+ .SH FILES
492
+ .TP
493
+ .I $XDG_CONFIG_HOME/plurnk/.env
494
+ Operator configuration; ~/.config/plurnk/.env when XDG_CONFIG_HOME is unset.
495
+ .TP
496
+ .I plurnk.service
497
+ Optional systemd user unit shipped in the package; installation is manual.
498
+ .SH SEE ALSO
499
+ plurnk(1)
@@ -0,0 +1,26 @@
1
+ import type { FindStatement, KillStatement } from "@plurnk/plurnk-contracts";
2
+ import { type EditBatchResult, type RepresentationPreparationRequest, type RepresentationPreparationResult, type ResolvedEditStatement, type RuntimeSchemeFacet, type SchemeCtx, type SchemeResult } from "@plurnk/plurnk-schemes";
3
+ import type { EnvRecord } from "../server/EnvFunctionality.ts";
4
+ export interface EnvRegistry {
5
+ readonly env: NodeJS.ProcessEnv;
6
+ readonly record: Readonly<Record<string, EnvRecord>>;
7
+ }
8
+ export type EnvResolve = (workspaceId: number, workerId: number) => Promise<EnvRegistry>;
9
+ export type EnvWriteVerb = "replace" | "remove" | "disable";
10
+ export interface EnvWriteIdentity {
11
+ readonly workspaceId: number;
12
+ readonly workerId: number;
13
+ readonly scope: "worker";
14
+ }
15
+ export type EnvInvoke = (verb: EnvWriteVerb, params: unknown, identity: EnvWriteIdentity) => Promise<unknown>;
16
+ export default class EnvScheme implements RuntimeSchemeFacet {
17
+ #private;
18
+ readonly manifest: NonNullable<RuntimeSchemeFacet["manifest"]>;
19
+ constructor(resolve: EnvResolve, invoke: EnvInvoke);
20
+ claims(pathname: string): boolean;
21
+ prepareRepresentation(request: RepresentationPreparationRequest, ctx: SchemeCtx): Promise<RepresentationPreparationResult>;
22
+ prepareFind(statement: FindStatement, ctx: SchemeCtx): Promise<SchemeResult>;
23
+ editBatch(statements: readonly ResolvedEditStatement[], ctx: SchemeCtx): Promise<EditBatchResult>;
24
+ kill(statement: KillStatement, ctx: SchemeCtx): Promise<SchemeResult>;
25
+ }
26
+ //# sourceMappingURL=Env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Env.d.ts","sourceRoot":"","sources":["../../src/schemes/Env.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAc,MAAM,0BAA0B,CAAC;AACzF,OAAO,EAEH,KAAK,eAAe,EACpB,KAAK,gCAAgC,EACrC,KAAK,+BAA+B,EACpC,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,YAAY,EACpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;CACxD;AACD,MAAM,MAAM,UAAU,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AACzF,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC5D,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC5B;AACD,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAa9G,MAAM,CAAC,OAAO,OAAO,SAAU,YAAW,kBAAkB;;IACxD,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAE5D;IAIF,YAAY,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAGjD;IAGD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEhC;IA2CK,qBAAqB,CAAC,OAAO,EAAE,gCAAgC,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,+BAA+B,CAAC,CAU/H;IAIK,WAAW,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAejF;IAGK,SAAS,CAAC,UAAU,EAAE,SAAS,qBAAqB,EAAE,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC,CActG;IAIK,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,CAU1E;CACJ"}
@@ -0,0 +1,133 @@
1
+ import { Results, } from "@plurnk/plurnk-schemes";
2
+ import { OperationFailureError } from "../core/results.js";
3
+ const OWNER = "scheme:env";
4
+ const NAME = /^[A-Za-z_][A-Za-z0-9_]*$/u;
5
+ // {§execution-output-identity} — the manager's own output streams, which stay the executor's.
6
+ const STREAM = /^[0-9a-f]{8}$/u;
7
+ const ADDRESS = /^[a-z][a-z0-9+.-]*:\/\/[^/]*(\/.*)$/iu;
8
+ const nameOf = (pathname) => {
9
+ const name = pathname.replace(/^\//u, "");
10
+ return NAME.test(name) && !STREAM.test(name) ? name : null;
11
+ };
12
+ export default class EnvScheme {
13
+ manifest = {
14
+ authority: "resource", channels: {}, defaultChannel: "body", writableBy: ["model", "client", "_plurnk"],
15
+ };
16
+ #resolve;
17
+ #invoke;
18
+ constructor(resolve, invoke) {
19
+ this.#resolve = resolve;
20
+ this.#invoke = invoke;
21
+ }
22
+ // The registry is the namespace: every coordinate but the manager's own output streams.
23
+ claims(pathname) {
24
+ return !STREAM.test(pathname.replace(/^\//u, ""));
25
+ }
26
+ static #named(target) {
27
+ if (target === null || target.kind !== "url") {
28
+ return Results.failure(OWNER, "target-required", 400, "The operation needs an env:///NAME target.", {}, { retryable: false });
29
+ }
30
+ const name = (target.hostname ?? "") === "" ? nameOf(target.pathname) : null;
31
+ if (name === null)
32
+ return EnvScheme.#invalid(target.raw);
33
+ return { name, pathname: `/${name}` };
34
+ }
35
+ static #invalid(target) {
36
+ return Results.failure(OWNER, "name-invalid", 400, `'${target}' is not a name a shell can export; the form is env:///NAME.`, {}, { target, retryable: false });
37
+ }
38
+ static #missing(name) {
39
+ return Results.failure(OWNER, "entry-not-found", 404, `No name ${name} is in effect for this Worker's commands.`, {}, { target: `env:///${name}` });
40
+ }
41
+ static #whole(name, op) {
42
+ return Results.failure(OWNER, "value-whole", 400, `env:///${name} is one value: a scope or a pattern selects nothing in it.`, {}, {
43
+ target: `env:///${name}`, retryable: false,
44
+ recovery: op === "EDIT" ? `EDIT (env:///${name}) with the whole value as the body.` : `KILL (env:///${name}) retires the name.`,
45
+ });
46
+ }
47
+ // The family's refusal is the operation's result.
48
+ async #write(verb, params, ctx) {
49
+ try {
50
+ await this.#invoke(verb, params, { workspaceId: ctx.workspaceId, workerId: ctx.workerId, scope: "worker" });
51
+ return null;
52
+ }
53
+ catch (cause) {
54
+ if (cause instanceof OperationFailureError)
55
+ return cause.result;
56
+ throw cause;
57
+ }
58
+ }
59
+ #project(ctx, pathname, value) {
60
+ return ctx.entries.write(pathname, { channels: { body: { content: value, mimetype: "text/plain" } } });
61
+ }
62
+ // READ projects the value the Worker's commands receive now; a name no longer in effect
63
+ // withdraws its projection.
64
+ async prepareRepresentation(request, ctx) {
65
+ const name = request.authority === "" ? nameOf(request.pathname) : null;
66
+ if (name === null)
67
+ return EnvScheme.#invalid(`env://${request.authority}${request.pathname}`);
68
+ const value = (await this.#resolve(ctx.workspaceId, ctx.workerId)).env[name];
69
+ if (value === undefined) {
70
+ await ctx.entries.delete(request.pathname);
71
+ return EnvScheme.#missing(name);
72
+ }
73
+ const written = await this.#project(ctx, request.pathname, value);
74
+ return written.status >= 400 ? { status: written.status, problem: written.problem } : { status: 200 };
75
+ }
76
+ // FIND lists exactly what is in effect: stored projections of names no longer in effect are
77
+ // withdrawn and every current name is projected before the host selects among them.
78
+ async prepareFind(statement, ctx) {
79
+ const { env } = await this.#resolve(ctx.workspaceId, ctx.workerId);
80
+ const stored = await ctx.entries.operations.find({ ...statement, matcher: null, lineMarker: { marks: [1, -1] } });
81
+ if (stored.status === 200) {
82
+ for (const item of stored.results) {
83
+ const path = Array.isArray(item) ? item[0].path : undefined;
84
+ const pathname = path === undefined ? undefined : ADDRESS.exec(path)?.[1];
85
+ const name = pathname === undefined ? null : nameOf(pathname);
86
+ if (name !== null && env[name] === undefined)
87
+ await ctx.entries.delete(`/${name}`);
88
+ }
89
+ }
90
+ for (const [name, value] of Object.entries(env)) {
91
+ if (value !== undefined && nameOf(`/${name}`) !== null)
92
+ await this.#project(ctx, `/${name}`, value);
93
+ }
94
+ return { status: 200 };
95
+ }
96
+ // {§functionality-replacement} — EDIT assigns a whole value without changing enabledness.
97
+ async editBatch(statements, ctx) {
98
+ const statement = statements[0];
99
+ if (statement === undefined || statements.length > 1) {
100
+ return Results.failure(OWNER, "value-whole", 400, "One EDIT sets one value, whole.", {}, {
101
+ recovery: "EDIT (env:///NAME) with the value as the body, one statement per name.", retryable: false,
102
+ });
103
+ }
104
+ const named = EnvScheme.#named(statement.target);
105
+ if ("status" in named)
106
+ return named;
107
+ if (statement.lineMarker !== null || statement.matcher !== null)
108
+ return EnvScheme.#whole(named.name, "EDIT");
109
+ const refused = await this.#write("replace", { alias: named.name, definition: { value: statement.body ?? "" } }, ctx);
110
+ if (refused !== null)
111
+ return refused;
112
+ await ctx.entries.delete(named.pathname);
113
+ return { status: 200 };
114
+ }
115
+ // KILL retires the name from the Worker's commands: the family's `remove` for an entry the
116
+ // Worker owns, its `disable` for an inherited one, whose definition is kept.
117
+ async kill(statement, ctx) {
118
+ const named = EnvScheme.#named(statement.target);
119
+ if ("status" in named)
120
+ return named;
121
+ if (statement.lineMarker !== null || statement.matcher !== null)
122
+ return EnvScheme.#whole(named.name, "KILL");
123
+ const entry = (await this.#resolve(ctx.workspaceId, ctx.workerId)).record[named.name];
124
+ if (entry === undefined || entry.source === "masked" || entry.value === undefined)
125
+ return EnvScheme.#missing(named.name);
126
+ const refused = await this.#write(entry.source === "worker" ? "remove" : "disable", { alias: named.name }, ctx);
127
+ if (refused !== null)
128
+ return refused;
129
+ await ctx.entries.delete(named.pathname);
130
+ return { status: 200 };
131
+ }
132
+ }
133
+ //# sourceMappingURL=Env.js.map