@ricsam/r5d-worker 0.0.136 → 0.0.138

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 (240) hide show
  1. package/README.md +4 -94
  2. package/dist/cjs/package.json +1 -1
  3. package/dist/mjs/main.mjs +46 -7537
  4. package/dist/mjs/package.json +1 -1
  5. package/dist/mjs/personal/action-scheduler.mjs +31 -0
  6. package/dist/mjs/personal/client.mjs +215 -0
  7. package/dist/mjs/personal/runtime.mjs +328 -0
  8. package/dist/mjs/personal/tcp.mjs +217 -0
  9. package/dist/mjs/runtime/adapter.mjs +42 -0
  10. package/dist/mjs/runtime/client.mjs +95 -0
  11. package/dist/mjs/runtime/daemon.mjs +131 -0
  12. package/dist/mjs/runtime/executor.mjs +436 -0
  13. package/dist/mjs/runtime/index.mjs +15 -0
  14. package/dist/mjs/runtime/protocol.mjs +139 -0
  15. package/dist/mjs/runtime/pty-host.mjs +156 -0
  16. package/dist/mjs/runtime/pty.mjs +127 -0
  17. package/dist/mjs/runtime/releases/artifacts.mjs +201 -0
  18. package/dist/mjs/runtime/releases/grants.mjs +93 -0
  19. package/dist/mjs/runtime/releases/main.mjs +101 -0
  20. package/dist/mjs/runtime/releases/manager.mjs +541 -0
  21. package/dist/mjs/runtime/releases/process.mjs +88 -0
  22. package/dist/mjs/runtime/releases/retirement.mjs +18 -0
  23. package/dist/mjs/runtime/releases/rpc-client.mjs +184 -0
  24. package/dist/mjs/runtime/releases/rpc-main.mjs +213 -0
  25. package/dist/mjs/runtime/releases/rpc-protocol.mjs +103 -0
  26. package/dist/mjs/runtime/storage.mjs +156 -0
  27. package/dist/mjs/runtime/workspace/artifacts.mjs +121 -0
  28. package/dist/mjs/runtime/workspace/authority.mjs +1355 -0
  29. package/dist/mjs/runtime/workspace/contracts.mjs +60 -0
  30. package/dist/mjs/runtime/workspace/file-write.mjs +23 -0
  31. package/dist/mjs/runtime/workspace/files.mjs +308 -0
  32. package/dist/mjs/runtime/workspace/http-body.mjs +45 -0
  33. package/dist/mjs/runtime/workspace/storage-client.mjs +59 -0
  34. package/dist/mjs/runtime/workspace/storage-wire.mjs +53 -0
  35. package/dist/types/main.d.ts +0 -1167
  36. package/dist/types/personal/action-scheduler.d.ts +23 -0
  37. package/dist/types/personal/client.d.ts +14 -0
  38. package/dist/types/personal/runtime.d.ts +121 -0
  39. package/dist/types/personal/tcp.d.ts +14 -0
  40. package/dist/types/runtime/client.d.ts +17 -0
  41. package/dist/types/runtime/daemon.d.ts +8 -0
  42. package/dist/types/runtime/executor.d.ts +35 -0
  43. package/dist/types/runtime/index.d.ts +5 -0
  44. package/dist/types/runtime/protocol.d.ts +544 -0
  45. package/dist/types/runtime/pty.d.ts +30 -0
  46. package/dist/types/runtime/releases/artifacts.d.ts +51 -0
  47. package/dist/types/runtime/releases/grants.d.ts +16 -0
  48. package/dist/types/runtime/releases/manager.d.ts +145 -0
  49. package/dist/types/runtime/releases/process.d.ts +14 -0
  50. package/dist/types/runtime/releases/retirement.d.ts +15 -0
  51. package/dist/types/runtime/releases/rpc-client.d.ts +52 -0
  52. package/dist/types/runtime/releases/rpc-main.d.ts +10 -0
  53. package/dist/types/runtime/releases/rpc-protocol.d.ts +1139 -0
  54. package/dist/types/runtime/storage.d.ts +21 -0
  55. package/dist/types/runtime/test-harness.d.ts +53 -0
  56. package/dist/types/runtime/workspace/artifacts.d.ts +30 -0
  57. package/dist/types/runtime/workspace/authority.d.ts +338 -0
  58. package/dist/types/runtime/workspace/contracts.d.ts +86 -0
  59. package/dist/types/runtime/workspace/file-write.d.ts +14 -0
  60. package/dist/types/runtime/workspace/files.d.ts +21 -0
  61. package/dist/types/runtime/workspace/http-body.d.ts +9 -0
  62. package/dist/types/runtime/workspace/storage-client.d.ts +23 -0
  63. package/dist/types/runtime/workspace/storage-wire.d.ts +138 -0
  64. package/package.json +8 -6
  65. package/dist/cjs/atomic-rename.cjs +0 -303
  66. package/dist/cjs/browser-upload.cjs +0 -73
  67. package/dist/cjs/cli-update.cjs +0 -108
  68. package/dist/cjs/command-launcher.cjs +0 -423
  69. package/dist/cjs/control-command-policy.cjs +0 -177
  70. package/dist/cjs/git-blob-hash.cjs +0 -41
  71. package/dist/cjs/git-identity.cjs +0 -39
  72. package/dist/cjs/git-process-environment.cjs +0 -133
  73. package/dist/cjs/inline-output.cjs +0 -62
  74. package/dist/cjs/main.cjs +0 -7511
  75. package/dist/cjs/managed-paths.cjs +0 -215
  76. package/dist/cjs/plan-lint.cjs +0 -165
  77. package/dist/cjs/plan-parser.cjs +0 -127
  78. package/dist/cjs/plan-paths.cjs +0 -53
  79. package/dist/cjs/port-forward-client.cjs +0 -206
  80. package/dist/cjs/process-tree.cjs +0 -117
  81. package/dist/cjs/project-checkout-garbage.cjs +0 -219
  82. package/dist/cjs/project-mirror-fetch-policy.cjs +0 -82
  83. package/dist/cjs/project-mirror-refs-token.cjs +0 -85
  84. package/dist/cjs/project-workspace-state.cjs +0 -972
  85. package/dist/cjs/project-worktrees.cjs +0 -1713
  86. package/dist/cjs/pty-output-coalescer.cjs +0 -87
  87. package/dist/cjs/recovery-journal-protocol.cjs +0 -56
  88. package/dist/cjs/recovery-journal-runtime.cjs +0 -133
  89. package/dist/cjs/recovery-journal-thread.cjs +0 -9
  90. package/dist/cjs/recovery-journal.cjs +0 -742
  91. package/dist/cjs/recovery-output-window.cjs +0 -77
  92. package/dist/cjs/recovery-protocol.cjs +0 -31
  93. package/dist/cjs/recovery-store.cjs +0 -252
  94. package/dist/cjs/registry-auth.cjs +0 -310
  95. package/dist/cjs/repository-transition-policy.cjs +0 -49
  96. package/dist/cjs/runtime-version.cjs +0 -88
  97. package/dist/cjs/session-file-mutations.cjs +0 -61
  98. package/dist/cjs/supervisor.cjs +0 -147
  99. package/dist/cjs/three-way-merge.cjs +0 -346
  100. package/dist/cjs/working-tree-mirror.cjs +0 -1872
  101. package/dist/cjs/workspace-automatic-sync-policy.cjs +0 -79
  102. package/dist/cjs/workspace-branch-incarnation-policy.cjs +0 -37
  103. package/dist/cjs/workspace-command-sync-policy.cjs +0 -112
  104. package/dist/cjs/workspace-command-targets.cjs +0 -63
  105. package/dist/cjs/workspace-filesystem-executor-thread.cjs +0 -36
  106. package/dist/cjs/workspace-filesystem-executor.cjs +0 -327
  107. package/dist/cjs/workspace-filesystem-job-types.cjs +0 -144
  108. package/dist/cjs/workspace-filesystem-jobs.cjs +0 -59
  109. package/dist/cjs/workspace-git-sync.cjs +0 -3450
  110. package/dist/cjs/workspace-hydration-ledger.cjs +0 -66
  111. package/dist/cjs/workspace-hydration-merge.cjs +0 -433
  112. package/dist/cjs/workspace-hydration-recovery-state.cjs +0 -53
  113. package/dist/cjs/workspace-incident-state.cjs +0 -37
  114. package/dist/cjs/workspace-merge-projection.cjs +0 -467
  115. package/dist/cjs/workspace-mount-boundary.cjs +0 -71
  116. package/dist/cjs/workspace-mount-hold-fence.cjs +0 -120
  117. package/dist/cjs/workspace-mutation-gate.cjs +0 -127
  118. package/dist/cjs/workspace-path-move.cjs +0 -195
  119. package/dist/cjs/workspace-preserve-only-policy.cjs +0 -36
  120. package/dist/cjs/workspace-project-config-policy.cjs +0 -53
  121. package/dist/cjs/workspace-projection-ledger.cjs +0 -81
  122. package/dist/cjs/workspace-publication-evidence.cjs +0 -46
  123. package/dist/cjs/workspace-sync-coalescer.cjs +0 -58
  124. package/dist/mjs/atomic-rename.mjs +0 -261
  125. package/dist/mjs/browser-upload.mjs +0 -42
  126. package/dist/mjs/command-launcher.mjs +0 -393
  127. package/dist/mjs/control-command-policy.mjs +0 -146
  128. package/dist/mjs/git-blob-hash.mjs +0 -16
  129. package/dist/mjs/git-identity.mjs +0 -15
  130. package/dist/mjs/git-process-environment.mjs +0 -105
  131. package/dist/mjs/inline-output.mjs +0 -37
  132. package/dist/mjs/managed-paths.mjs +0 -174
  133. package/dist/mjs/plan-lint.mjs +0 -129
  134. package/dist/mjs/plan-parser.mjs +0 -94
  135. package/dist/mjs/plan-paths.mjs +0 -25
  136. package/dist/mjs/port-forward-client.mjs +0 -172
  137. package/dist/mjs/project-checkout-garbage.mjs +0 -178
  138. package/dist/mjs/project-mirror-fetch-policy.mjs +0 -56
  139. package/dist/mjs/project-mirror-refs-token.mjs +0 -53
  140. package/dist/mjs/project-workspace-state.mjs +0 -937
  141. package/dist/mjs/project-worktrees.mjs +0 -1657
  142. package/dist/mjs/pty-output-coalescer.mjs +0 -61
  143. package/dist/mjs/recovery-journal-protocol.mjs +0 -30
  144. package/dist/mjs/recovery-journal-runtime.mjs +0 -112
  145. package/dist/mjs/recovery-journal-thread.mjs +0 -8
  146. package/dist/mjs/recovery-journal.mjs +0 -694
  147. package/dist/mjs/recovery-output-window.mjs +0 -53
  148. package/dist/mjs/recovery-protocol.mjs +0 -6
  149. package/dist/mjs/recovery-store.mjs +0 -217
  150. package/dist/mjs/registry-auth.mjs +0 -269
  151. package/dist/mjs/repository-transition-policy.mjs +0 -22
  152. package/dist/mjs/runtime-version.mjs +0 -54
  153. package/dist/mjs/session-file-mutations.mjs +0 -37
  154. package/dist/mjs/supervisor.mjs +0 -114
  155. package/dist/mjs/three-way-merge.mjs +0 -318
  156. package/dist/mjs/working-tree-mirror.mjs +0 -1817
  157. package/dist/mjs/workspace-automatic-sync-policy.mjs +0 -48
  158. package/dist/mjs/workspace-branch-incarnation-policy.mjs +0 -13
  159. package/dist/mjs/workspace-command-sync-policy.mjs +0 -84
  160. package/dist/mjs/workspace-command-targets.mjs +0 -37
  161. package/dist/mjs/workspace-filesystem-executor-thread.mjs +0 -38
  162. package/dist/mjs/workspace-filesystem-executor.mjs +0 -287
  163. package/dist/mjs/workspace-filesystem-job-types.mjs +0 -116
  164. package/dist/mjs/workspace-filesystem-jobs.mjs +0 -55
  165. package/dist/mjs/workspace-git-sync.mjs +0 -3407
  166. package/dist/mjs/workspace-hydration-ledger.mjs +0 -42
  167. package/dist/mjs/workspace-hydration-merge.mjs +0 -399
  168. package/dist/mjs/workspace-hydration-recovery-state.mjs +0 -29
  169. package/dist/mjs/workspace-incident-state.mjs +0 -12
  170. package/dist/mjs/workspace-merge-projection.mjs +0 -433
  171. package/dist/mjs/workspace-mount-boundary.mjs +0 -37
  172. package/dist/mjs/workspace-mount-hold-fence.mjs +0 -95
  173. package/dist/mjs/workspace-mutation-gate.mjs +0 -103
  174. package/dist/mjs/workspace-path-move.mjs +0 -160
  175. package/dist/mjs/workspace-preserve-only-policy.mjs +0 -11
  176. package/dist/mjs/workspace-project-config-policy.mjs +0 -27
  177. package/dist/mjs/workspace-projection-ledger.mjs +0 -57
  178. package/dist/mjs/workspace-publication-evidence.mjs +0 -21
  179. package/dist/mjs/workspace-sync-coalescer.mjs +0 -34
  180. package/dist/types/atomic-rename.d.ts +0 -78
  181. package/dist/types/browser-upload.d.ts +0 -7
  182. package/dist/types/command-launcher.d.ts +0 -104
  183. package/dist/types/control-command-policy.d.ts +0 -53
  184. package/dist/types/git-blob-hash.d.ts +0 -10
  185. package/dist/types/git-identity.d.ts +0 -9
  186. package/dist/types/git-process-environment.d.ts +0 -9
  187. package/dist/types/inline-output.d.ts +0 -3
  188. package/dist/types/managed-paths.d.ts +0 -19
  189. package/dist/types/plan-lint.d.ts +0 -16
  190. package/dist/types/plan-parser.d.ts +0 -38
  191. package/dist/types/plan-paths.d.ts +0 -36
  192. package/dist/types/port-forward-client.d.ts +0 -8
  193. package/dist/types/project-checkout-garbage.d.ts +0 -86
  194. package/dist/types/project-mirror-fetch-policy.d.ts +0 -84
  195. package/dist/types/project-mirror-refs-token.d.ts +0 -53
  196. package/dist/types/project-workspace-state.d.ts +0 -188
  197. package/dist/types/project-worktrees.d.ts +0 -397
  198. package/dist/types/pty-output-coalescer.d.ts +0 -20
  199. package/dist/types/recovery-journal-protocol.d.ts +0 -35
  200. package/dist/types/recovery-journal-runtime.d.ts +0 -12
  201. package/dist/types/recovery-journal-thread.d.ts +0 -1
  202. package/dist/types/recovery-journal.d.ts +0 -248
  203. package/dist/types/recovery-output-window.d.ts +0 -19
  204. package/dist/types/recovery-protocol.d.ts +0 -59
  205. package/dist/types/recovery-store.d.ts +0 -52
  206. package/dist/types/registry-auth.d.ts +0 -47
  207. package/dist/types/repository-transition-policy.d.ts +0 -26
  208. package/dist/types/runtime-version.d.ts +0 -1
  209. package/dist/types/session-file-mutations.d.ts +0 -22
  210. package/dist/types/supervisor-daemonized-fixture.d.ts +0 -1
  211. package/dist/types/supervisor-launcher-cleanup-fixture.d.ts +0 -1
  212. package/dist/types/supervisor-signal-fixture.d.ts +0 -1
  213. package/dist/types/supervisor.d.ts +0 -23
  214. package/dist/types/three-way-merge.d.ts +0 -77
  215. package/dist/types/working-tree-mirror.d.ts +0 -424
  216. package/dist/types/workspace-automatic-sync-policy.d.ts +0 -57
  217. package/dist/types/workspace-branch-incarnation-policy.d.ts +0 -14
  218. package/dist/types/workspace-command-sync-policy.d.ts +0 -57
  219. package/dist/types/workspace-command-targets.d.ts +0 -37
  220. package/dist/types/workspace-filesystem-executor-thread.d.ts +0 -1
  221. package/dist/types/workspace-filesystem-executor.d.ts +0 -123
  222. package/dist/types/workspace-filesystem-job-types.d.ts +0 -288
  223. package/dist/types/workspace-filesystem-jobs.d.ts +0 -7
  224. package/dist/types/workspace-git-sync.d.ts +0 -495
  225. package/dist/types/workspace-hydration-ledger.d.ts +0 -43
  226. package/dist/types/workspace-hydration-merge.d.ts +0 -95
  227. package/dist/types/workspace-hydration-recovery-state.d.ts +0 -10
  228. package/dist/types/workspace-incident-state.d.ts +0 -19
  229. package/dist/types/workspace-merge-projection.d.ts +0 -60
  230. package/dist/types/workspace-mount-boundary.d.ts +0 -10
  231. package/dist/types/workspace-mount-hold-fence.d.ts +0 -42
  232. package/dist/types/workspace-mutation-gate.d.ts +0 -42
  233. package/dist/types/workspace-path-move.d.ts +0 -21
  234. package/dist/types/workspace-preserve-only-policy.d.ts +0 -15
  235. package/dist/types/workspace-project-config-policy.d.ts +0 -48
  236. package/dist/types/workspace-projection-ledger.d.ts +0 -59
  237. package/dist/types/workspace-publication-evidence.d.ts +0 -17
  238. package/dist/types/workspace-sync-coalescer.d.ts +0 -28
  239. /package/dist/types/{credential-authority-lock-fixture.d.ts → runtime/adapter.d.ts} +0 -0
  240. /package/dist/types/{recovery-journal-stall-fixture.d.ts → runtime/releases/main.d.ts} +0 -0
@@ -1,146 +0,0 @@
1
- const CONTROL_COMMAND_PROGRAM = "r5dctl";
2
- const CONTROL_COMMAND_RUNTIME_MS = 12e4;
3
- const CONTROL_COMMAND_MAX_ARGV = 64;
4
- const CONTROL_COMMAND_MAX_LENGTH = 4096;
5
- const CONTROL_GLOBAL_FLAGS_WITH_VALUE = /* @__PURE__ */ new Set(["-p", "--project", "-s", "--session", "-b", "--branch"]);
6
- const CONTROL_GLOBAL_FLAGS = /* @__PURE__ */ new Set(["--json", "-h", "--help", "-v", "--version"]);
7
- const REFUSED_ANYWHERE = /* @__PURE__ */ new Set(["-f", "--follow", "--watch", "--base-url", "--config", "--token", "--api-key"]);
8
- const CONTROL_VERBS = {
9
- session: /* @__PURE__ */ new Set(["status", "stop", "prompt", "claim", "claims", "process-log"]),
10
- sessions: /* @__PURE__ */ new Set(["recent"]),
11
- describe: /* @__PURE__ */ new Set(["project", "branch", "session", "branch-operation", "branch-deletion"]),
12
- get: /* @__PURE__ */ new Set(["projects", "branches", "sessions", "envs", "env"]),
13
- conversation: /* @__PURE__ */ new Set(["overview", "inspect-node", "inspect-work"]),
14
- ps: /* @__PURE__ */ new Set(["list", "history", "inspect", "stop"]),
15
- workspace: /* @__PURE__ */ new Set(["status"]),
16
- auth: /* @__PURE__ */ new Set(["status"]),
17
- create: /* @__PURE__ */ new Set(["session"]),
18
- update: /* @__PURE__ */ new Set(["session"]),
19
- delete: /* @__PURE__ */ new Set(["session"]),
20
- "answer-questions": null,
21
- "answer-env-request": null
22
- };
23
- const CODE_LOADING_ENV_PATTERN = /^(NODE_OPTIONS|NODE_PATH|NODE_REPL_EXTERNAL_MODULE|BUN_OPTIONS|BUN_CONFIG_[A-Z_]+|LD_PRELOAD|LD_LIBRARY_PATH|LD_AUDIT|DYLD_[A-Z_]+|PATH|PATHEXT|PYTHONPATH|PERL5OPT|RUBYOPT|SHELL|ENV|BASH_ENV)$/i;
24
- const BARE_WORD = /^[A-Za-z0-9_@%+=:,./-]+$/;
25
- const DOUBLE_QUOTED_FORBIDDEN = /[$`\\!]/;
26
- function tokenizePlainInvocation(command) {
27
- if (command.length > CONTROL_COMMAND_MAX_LENGTH) return { reason: "command is longer than the control lane allows" };
28
- if (/[\r\n]/.test(command)) return { reason: "multi-line commands are shell scripts" };
29
- const argv = [];
30
- let index = 0;
31
- while (index < command.length) {
32
- const char = command[index];
33
- if (char === " " || char === " ") {
34
- index += 1;
35
- continue;
36
- }
37
- let word = "";
38
- let quotedParts = 0;
39
- let bareParts = 0;
40
- while (index < command.length && command[index] !== " " && command[index] !== " ") {
41
- const current = command[index];
42
- if (current === "'") {
43
- const end = command.indexOf("'", index + 1);
44
- if (end < 0) return { reason: "unterminated single quote" };
45
- word += command.slice(index + 1, end);
46
- quotedParts += 1;
47
- index = end + 1;
48
- continue;
49
- }
50
- if (current === '"') {
51
- const end = command.indexOf('"', index + 1);
52
- if (end < 0) return { reason: "unterminated double quote" };
53
- const inner = command.slice(index + 1, end);
54
- if (DOUBLE_QUOTED_FORBIDDEN.test(inner)) return { reason: "double-quoted text would be expanded by the shell" };
55
- word += inner;
56
- quotedParts += 1;
57
- index = end + 1;
58
- continue;
59
- }
60
- let bare = "";
61
- while (index < command.length && !/[\s'"]/.test(command[index])) {
62
- bare += command[index];
63
- index += 1;
64
- }
65
- if (!BARE_WORD.test(bare)) return { reason: `shell syntax in "${bare}" is not part of a plain invocation` };
66
- word += bare;
67
- bareParts += 1;
68
- }
69
- if (quotedParts + bareParts > 1) return { reason: "adjacent quoted and bare text is shell concatenation" };
70
- argv.push(word);
71
- if (argv.length > CONTROL_COMMAND_MAX_ARGV) return { reason: "too many arguments for a control command" };
72
- }
73
- if (argv.length === 0) return { reason: "empty command" };
74
- return { argv };
75
- }
76
- function assertControlCommandArgv(argv) {
77
- if (argv.length === 0 || argv.length > CONTROL_COMMAND_MAX_ARGV) throw new Error("Control commands are a single r5dctl invocation");
78
- if (argv[0] !== CONTROL_COMMAND_PROGRAM) throw new Error(`Control commands must start with ${CONTROL_COMMAND_PROGRAM}`);
79
- if (argv.reduce((length, argument) => length + (typeof argument === "string" ? argument.length : 0) + 1, 0) > CONTROL_COMMAND_MAX_LENGTH)
80
- throw new Error("Control command arguments exceed the length limit");
81
- for (const argument of argv) {
82
- if (typeof argument !== "string" || argument.includes("\0") || /[\r\n]/.test(argument)) throw new Error("Control command arguments must be plain text");
83
- if (REFUSED_ANYWHERE.has(argument.split("=", 1)[0])) throw new Error(`Control command option is not allowed (${argument.split("=", 1)[0]})`);
84
- if (argument === "--") throw new Error("Control commands cannot use `--`");
85
- }
86
- let position = 1;
87
- while (position < argv.length) {
88
- const argument = argv[position];
89
- if (CONTROL_GLOBAL_FLAGS.has(argument)) {
90
- position += 1;
91
- continue;
92
- }
93
- if (CONTROL_GLOBAL_FLAGS_WITH_VALUE.has(argument)) {
94
- if (position + 1 >= argv.length) throw new Error(`Missing value for ${argument}`);
95
- position += 2;
96
- continue;
97
- }
98
- if (argument.startsWith("-")) throw new Error(`Global flag ${argument} is not allowed in a control command`);
99
- break;
100
- }
101
- const verb = argv[position];
102
- if (verb === void 0) throw new Error("Control commands need a coordination verb (for example `r5dctl ps list`)");
103
- const allowed = Object.hasOwn(CONTROL_VERBS, verb) ? CONTROL_VERBS[verb] : void 0;
104
- if (allowed === void 0) throw new Error(`r5dctl ${verb} is not a coordination command`);
105
- if (allowed === null) return;
106
- const subject = argv[position + 1];
107
- if (subject === void 0 || !allowed.has(subject)) {
108
- throw new Error(`r5dctl ${verb}${subject ? ` ${subject}` : ""} is not a coordination command`);
109
- }
110
- }
111
- function resolveControlCommandExecutable(trustedPath, which, program = CONTROL_COMMAND_PROGRAM) {
112
- const resolved = trustedPath ? which(program, { PATH: trustedPath }) : null;
113
- if (!resolved) throw new Error(`${program} is not installed on the worker's trusted PATH; control commands are unavailable until it is`);
114
- return resolved;
115
- }
116
- function controlCommandEnvironment(environment, trustedPath) {
117
- const result = {};
118
- for (const [key, value] of Object.entries(environment)) {
119
- if (value === void 0 || CODE_LOADING_ENV_PATTERN.test(key)) continue;
120
- result[key] = value;
121
- }
122
- if (trustedPath !== void 0) result.PATH = trustedPath;
123
- return result;
124
- }
125
- function classifyControlCommand(command) {
126
- const tokenized = tokenizePlainInvocation(command.trim());
127
- if ("reason" in tokenized) return { control: false, reason: tokenized.reason };
128
- const { argv } = tokenized;
129
- if (argv[0] !== CONTROL_COMMAND_PROGRAM) return { control: false, reason: "not an r5dctl invocation" };
130
- try {
131
- assertControlCommandArgv(argv);
132
- } catch (error) {
133
- return { control: false, reason: error instanceof Error ? error.message : String(error) };
134
- }
135
- return { control: true, argv };
136
- }
137
- export {
138
- CONTROL_COMMAND_MAX_ARGV,
139
- CONTROL_COMMAND_MAX_LENGTH,
140
- CONTROL_COMMAND_PROGRAM,
141
- CONTROL_COMMAND_RUNTIME_MS,
142
- assertControlCommandArgv,
143
- classifyControlCommand,
144
- controlCommandEnvironment,
145
- resolveControlCommandExecutable
146
- };
@@ -1,16 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- function gitObjectHashAlgorithmFor(objectId) {
3
- if (/^[0-9a-f]{40}$/u.test(objectId)) return "sha1";
4
- if (/^[0-9a-f]{64}$/u.test(objectId)) return "sha256";
5
- return null;
6
- }
7
- function gitBlobHash(content, algorithm) {
8
- const hash = createHash(algorithm);
9
- hash.update(`blob ${content.length}\0`);
10
- hash.update(content);
11
- return hash.digest("hex");
12
- }
13
- export {
14
- gitBlobHash,
15
- gitObjectHashAlgorithmFor
16
- };
@@ -1,15 +0,0 @@
1
- function configureVisibleGitIdentity(branchPath, identity, runGit) {
2
- if (!identity) {
3
- return;
4
- }
5
- const name = identity.name.trim();
6
- const email = identity.email.trim();
7
- if (!name || !email) {
8
- throw new Error("Git identity must include name and email");
9
- }
10
- runGit(["config", "user.name", name], { cwd: branchPath });
11
- runGit(["config", "user.email", email], { cwd: branchPath });
12
- }
13
- export {
14
- configureVisibleGitIdentity
15
- };
@@ -1,105 +0,0 @@
1
- import { devNull } from "node:os";
2
- const ALLOWED_GIT_ENVIRONMENT_KEYS = [
3
- "PATH",
4
- "USER",
5
- "LOGNAME",
6
- "SHELL",
7
- "TMPDIR",
8
- "TMP",
9
- "TEMP",
10
- "TZ",
11
- "LANG",
12
- "LANGUAGE",
13
- "LC_ALL",
14
- "LC_CTYPE",
15
- "LC_COLLATE",
16
- "LC_MESSAGES",
17
- "LC_MONETARY",
18
- "LC_NUMERIC",
19
- "LC_TIME",
20
- "LC_ADDRESS",
21
- "LC_IDENTIFICATION",
22
- "LC_MEASUREMENT",
23
- "LC_NAME",
24
- "LC_PAPER",
25
- "LC_TELEPHONE",
26
- "SystemRoot",
27
- "SYSTEMROOT",
28
- "WINDIR",
29
- "COMSPEC",
30
- "PATHEXT",
31
- "SSL_CERT_FILE",
32
- "SSL_CERT_DIR",
33
- "CURL_CA_BUNDLE",
34
- "GIT_SSL_CAINFO",
35
- "GIT_SSL_CAPATH",
36
- "GIT_EXEC_PATH",
37
- "GIT_OPTIONAL_LOCKS"
38
- ];
39
- function workerGitProcessEnvironment(source = process.env) {
40
- const environment = {
41
- GIT_TERMINAL_PROMPT: "0",
42
- GIT_CONFIG_GLOBAL: devNull,
43
- GIT_CONFIG_NOSYSTEM: "1",
44
- GIT_ATTR_NOSYSTEM: "1"
45
- };
46
- for (const key of ALLOWED_GIT_ENVIRONMENT_KEYS) {
47
- if (source[key] !== void 0) environment[key] = source[key];
48
- }
49
- return environment;
50
- }
51
- function gitHttpAuthorizationClearArgs(remoteUrl) {
52
- let remote;
53
- try {
54
- remote = new URL(remoteUrl);
55
- } catch {
56
- return ["-c", "http.extraHeader="];
57
- }
58
- if ((remote.protocol === "https:" || remote.protocol === "http:") && (remote.username || remote.password)) {
59
- throw new Error("Git credentials must not be embedded in a remote URL");
60
- }
61
- if (remote.protocol !== "https:" && remote.protocol !== "http:") return ["-c", "http.extraHeader="];
62
- remote.hash = "";
63
- remote.search = "";
64
- return ["-c", "http.extraHeader=", "-c", `http.${remote.origin}/.extraHeader=`, "-c", `http.${remote.href}.extraHeader=`];
65
- }
66
- function gitCredentialHelperConfigArgs(credentialHelper) {
67
- return [
68
- "-c",
69
- "credential.helper=",
70
- ...credentialHelper ? ["-c", `credential.helper=${credentialHelper}`] : [],
71
- "-c",
72
- "credential.useHttpPath=false"
73
- ];
74
- }
75
- function gitCredentialUsernameConfigKey(remoteUrl) {
76
- const remote = new URL(remoteUrl);
77
- if ((remote.protocol === "https:" || remote.protocol === "http:") && (remote.username || remote.password)) {
78
- throw new Error("Git credentials must not be embedded in a remote URL");
79
- }
80
- if (remote.protocol !== "https:" && remote.protocol !== "http:") {
81
- throw new Error("Git credential usernames require an HTTP remote URL");
82
- }
83
- remote.hash = "";
84
- remote.search = "";
85
- return `credential.${remote.href}.username`;
86
- }
87
- function gitCredentialUsernameConfigArgs(remoteUrl, credentialUsername) {
88
- if (!credentialUsername) return [];
89
- if (/[\0\r\n]/.test(credentialUsername)) throw new Error("Invalid Git credential username");
90
- return ["-c", `${gitCredentialUsernameConfigKey(remoteUrl)}=${credentialUsername}`];
91
- }
92
- function gitTransportSecurityArgs(remoteUrl, credentialHelper, credentialUsername) {
93
- return [
94
- ...gitHttpAuthorizationClearArgs(remoteUrl),
95
- ...gitCredentialHelperConfigArgs(credentialHelper),
96
- ...gitCredentialUsernameConfigArgs(remoteUrl, credentialUsername)
97
- ];
98
- }
99
- export {
100
- gitCredentialHelperConfigArgs,
101
- gitCredentialUsernameConfigKey,
102
- gitHttpAuthorizationClearArgs,
103
- gitTransportSecurityArgs,
104
- workerGitProcessEnvironment
105
- };
@@ -1,37 +0,0 @@
1
- const WORKER_INLINE_OUTPUT_MAX_BYTES = 8 * 1024 * 1024;
2
- async function collectWorkerInlineOutput(stream, maxBytes = WORKER_INLINE_OUTPUT_MAX_BYTES, signal) {
3
- if (!stream) return "";
4
- signal?.throwIfAborted();
5
- const reader = stream.getReader();
6
- const abort = () => {
7
- void reader.cancel().catch(() => {
8
- });
9
- };
10
- signal?.addEventListener("abort", abort, { once: true });
11
- const decoder = new TextDecoder();
12
- const parts = [];
13
- let bytes = 0;
14
- try {
15
- while (true) {
16
- const next = await reader.read();
17
- signal?.throwIfAborted();
18
- if (next.done) break;
19
- bytes += next.value.byteLength;
20
- if (bytes > maxBytes) {
21
- void reader.cancel().catch(() => {
22
- });
23
- throw new Error(`Inline command output exceeded ${maxBytes} bytes. Use streaming execution for large output.`);
24
- }
25
- parts.push(decoder.decode(next.value, { stream: true }));
26
- }
27
- parts.push(decoder.decode());
28
- return parts.join("");
29
- } finally {
30
- signal?.removeEventListener("abort", abort);
31
- reader.releaseLock();
32
- }
33
- }
34
- export {
35
- WORKER_INLINE_OUTPUT_MAX_BYTES,
36
- collectWorkerInlineOutput
37
- };
@@ -1,174 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- const BRANCH_NAME_MAX_LENGTH = 45;
4
- const BRANCH_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*(?:\/[a-z0-9]+(?:-[a-z0-9]+)*)*$/;
5
- const PROJECT_SEGMENT_PATTERN = /^[a-z0-9._-]+$/;
6
- const WINDOWS_RESERVED_PATH_SEGMENT = /^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\..*)?$/i;
7
- const INTERNAL_PROJECT_PATH_SEGMENTS = /* @__PURE__ */ new Set([".r5d-retired-checkouts"]);
8
- function lstatIfExists(targetPath) {
9
- try {
10
- return fs.lstatSync(targetPath);
11
- } catch (error) {
12
- if (error.code === "ENOENT") return null;
13
- throw error;
14
- }
15
- }
16
- function fsyncDirectory(directoryPath) {
17
- const descriptor = fs.openSync(directoryPath, "r");
18
- try {
19
- fs.fsyncSync(descriptor);
20
- } finally {
21
- fs.closeSync(descriptor);
22
- }
23
- }
24
- function fsyncCreatedDirectoryChain(directoryPath, preexistingAncestorPath) {
25
- let current = path.resolve(directoryPath);
26
- const ancestor = path.resolve(preexistingAncestorPath);
27
- const relative = path.relative(ancestor, current);
28
- if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
29
- throw new Error(`Managed root escaped its durability ancestor: ${current}`);
30
- }
31
- while (true) {
32
- fsyncDirectory(current);
33
- if (current === ancestor) return;
34
- current = path.dirname(current);
35
- }
36
- }
37
- function canonicalizeManagedRoot(root) {
38
- const resolvedRoot = path.resolve(root.rootPath);
39
- let preexistingAncestor = resolvedRoot;
40
- while (!lstatIfExists(preexistingAncestor)) {
41
- const parent = path.dirname(preexistingAncestor);
42
- if (parent === preexistingAncestor) {
43
- throw new Error(`Could not find an existing ancestor for ${root.label} (${resolvedRoot})`);
44
- }
45
- preexistingAncestor = parent;
46
- }
47
- let canonicalPreexistingAncestor;
48
- try {
49
- canonicalPreexistingAncestor = fs.realpathSync(preexistingAncestor);
50
- if (!fs.statSync(canonicalPreexistingAncestor).isDirectory()) {
51
- throw new Error("the nearest existing ancestor is not a directory");
52
- }
53
- } catch (error) {
54
- throw new Error(`Could not validate the existing ancestor of ${root.label} (${resolvedRoot})`, { cause: error });
55
- }
56
- try {
57
- fs.mkdirSync(resolvedRoot, { recursive: true });
58
- } catch (error) {
59
- throw new Error(`Could not prepare ${root.label} (${resolvedRoot}) for overlap validation`, { cause: error });
60
- }
61
- const rootStats = fs.statSync(resolvedRoot, { bigint: true });
62
- if (!rootStats.isDirectory()) {
63
- throw new Error(`Managed root is not a directory: ${root.label} (${resolvedRoot})`);
64
- }
65
- const canonicalRoot = fs.realpathSync(resolvedRoot);
66
- fsyncCreatedDirectoryChain(canonicalRoot, canonicalPreexistingAncestor);
67
- return {
68
- ...root,
69
- rootPath: canonicalRoot,
70
- identity: { device: rootStats.dev, inode: rootStats.ino }
71
- };
72
- }
73
- function pathContains(root, candidate) {
74
- const relative = path.relative(root, candidate);
75
- return relative === "" || !relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative);
76
- }
77
- function identitiesMatch(left, right) {
78
- return left.device === right.device && left.inode === right.inode;
79
- }
80
- function pathOrFilesystemContains(root, candidate) {
81
- if (pathContains(root.rootPath, candidate.rootPath) || identitiesMatch(root.identity, candidate.identity)) {
82
- return true;
83
- }
84
- let ancestor = path.dirname(candidate.rootPath);
85
- while (true) {
86
- const stats = fs.statSync(ancestor, { bigint: true });
87
- if (identitiesMatch(root.identity, { device: stats.dev, inode: stats.ino })) return true;
88
- const parent = path.dirname(ancestor);
89
- if (parent === ancestor) return false;
90
- ancestor = parent;
91
- }
92
- }
93
- function assertDisjointManagedRoots(roots) {
94
- const canonical = roots.map(canonicalizeManagedRoot);
95
- for (let leftIndex = 0; leftIndex < canonical.length; leftIndex += 1) {
96
- const left = canonical[leftIndex];
97
- for (let rightIndex = leftIndex + 1; rightIndex < canonical.length; rightIndex += 1) {
98
- const right = canonical[rightIndex];
99
- if (pathOrFilesystemContains(left, right) || pathOrFilesystemContains(right, left)) {
100
- throw new Error(`Managed roots overlap: ${left.label} (${left.rootPath}) and ${right.label} (${right.rootPath}) must be disjoint`);
101
- }
102
- }
103
- }
104
- }
105
- function validateManagedBranchName(branchName) {
106
- if (typeof branchName !== "string" || branchName.length === 0) {
107
- throw new Error("Branch name is required");
108
- }
109
- if (branchName.length > BRANCH_NAME_MAX_LENGTH) {
110
- throw new Error(`Branch name must be ${BRANCH_NAME_MAX_LENGTH} characters or fewer`);
111
- }
112
- if (!BRANCH_NAME_PATTERN.test(branchName)) {
113
- throw new Error(`Invalid branch name from server: ${branchName}`);
114
- }
115
- const reserved = branchName.split("/").find((segment) => WINDOWS_RESERVED_PATH_SEGMENT.test(segment));
116
- if (reserved) {
117
- throw new Error(`Invalid branch name from server: reserved path segment '${reserved}'`);
118
- }
119
- }
120
- function validateCheckoutPathSegments(value) {
121
- if (!Array.isArray(value) || value.length !== 2) {
122
- throw new Error("Invalid checkout path from server: expected namespace and project segments");
123
- }
124
- const segments = value;
125
- for (const segment of segments) {
126
- if (typeof segment !== "string" || !PROJECT_SEGMENT_PATTERN.test(segment) || segment !== segment.toLowerCase() || segment === "." || segment === ".." || segment === ".git" || INTERNAL_PROJECT_PATH_SEGMENTS.has(segment) || segment.endsWith(".") || WINDOWS_RESERVED_PATH_SEGMENT.test(segment)) {
127
- throw new Error(`Invalid checkout path segment from server: ${String(segment)}`);
128
- }
129
- }
130
- return [segments[0], segments[1]];
131
- }
132
- function assertPathInside(root, candidate, label) {
133
- const resolvedRoot = path.resolve(root);
134
- const resolvedCandidate = path.resolve(candidate);
135
- const relative = path.relative(resolvedRoot, resolvedCandidate);
136
- if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
137
- throw new Error(`${label} escapes its managed root: ${candidate}`);
138
- }
139
- }
140
- function assertNoSymlinkComponents(root, candidate) {
141
- assertPathInside(root, candidate, "Checkout path");
142
- const relative = path.relative(path.resolve(root), path.resolve(candidate));
143
- let current = path.resolve(root);
144
- for (const component of relative.split(path.sep).filter(Boolean)) {
145
- current = path.join(current, component);
146
- if (!fs.existsSync(current)) break;
147
- if (fs.lstatSync(current).isSymbolicLink()) {
148
- throw new Error(`Checkout path contains a symbolic link: ${current}`);
149
- }
150
- }
151
- }
152
- function managedProjectRoot(projectsRoot, checkoutPathSegments) {
153
- const segments = validateCheckoutPathSegments(checkoutPathSegments);
154
- const result = path.join(projectsRoot, ...segments);
155
- assertNoSymlinkComponents(projectsRoot, result);
156
- return result;
157
- }
158
- function managedBranchPath(projectsRoot, checkoutPathSegments, branchName) {
159
- validateManagedBranchName(branchName);
160
- const projectRoot = managedProjectRoot(projectsRoot, checkoutPathSegments);
161
- const result = path.join(projectRoot, ...branchName.split("/"));
162
- assertNoSymlinkComponents(projectRoot, result);
163
- return result;
164
- }
165
- export {
166
- BRANCH_NAME_MAX_LENGTH,
167
- BRANCH_NAME_PATTERN,
168
- assertDisjointManagedRoots,
169
- assertPathInside,
170
- managedBranchPath,
171
- managedProjectRoot,
172
- validateCheckoutPathSegments,
173
- validateManagedBranchName
174
- };
@@ -1,129 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import picomatch from "picomatch";
4
- import { getTasksSectionRange, PLAN_TASK_LINE_REGEX } from "./plan-parser.mjs";
5
- import { PLAN_EXTENSION } from "./plan-paths.mjs";
6
- import { PLAN_TASK_ID_REGEX } from "./plan-parser.mjs";
7
- const LEGACY_SCHEMA_FIELD_REGEX = /^\s*(type|status|parent|phase|discovered_problem)\s*:/m;
8
- function lintPlanContent(planId, content) {
9
- const errors = [];
10
- const lines = content.split(/\r?\n/);
11
- if (/^---(?:\r?\n|$)/.test(content)) {
12
- errors.push({
13
- planId,
14
- severity: "error",
15
- message: "YAML frontmatter is not supported. Use plain Markdown with a ## Tasks checklist.",
16
- line: 1
17
- });
18
- }
19
- if (LEGACY_SCHEMA_FIELD_REGEX.test(content)) {
20
- errors.push({
21
- planId,
22
- severity: "error",
23
- message: "Legacy plan schema fields are not supported. Remove type/status/parent/phase/discovered_problem metadata."
24
- });
25
- }
26
- const titleLineIndex = lines.findIndex((line) => /^# .+\S\s*$/.test(line));
27
- if (titleLineIndex === -1) {
28
- errors.push({
29
- planId,
30
- severity: "error",
31
- message: "Plan must start with or contain an H1 title, for example '# Implementation Plan'."
32
- });
33
- }
34
- const range = getTasksSectionRange(content);
35
- if (!range) {
36
- errors.push({
37
- planId,
38
- severity: "error",
39
- message: "Plan is missing a ## Tasks section."
40
- });
41
- return errors;
42
- }
43
- const taskIds = /* @__PURE__ */ new Set();
44
- let taskCount = 0;
45
- for (let index = range.startIndex + 1; index < range.endIndex; index += 1) {
46
- const line = lines[index] ?? "";
47
- if (line.trim() === "") continue;
48
- const match = line.match(PLAN_TASK_LINE_REGEX);
49
- if (!match || !match[3].trim()) {
50
- errors.push({
51
- planId,
52
- severity: "error",
53
- line: index + 1,
54
- message: 'Malformed task line. Use "- [ ] task-id: Description" or "- [x] task-id: Description".'
55
- });
56
- continue;
57
- }
58
- taskCount += 1;
59
- const taskId = match[2];
60
- if (taskIds.has(taskId)) {
61
- errors.push({
62
- planId,
63
- severity: "error",
64
- line: index + 1,
65
- message: `Duplicate task id "${taskId}".`
66
- });
67
- }
68
- taskIds.add(taskId);
69
- }
70
- if (taskCount === 0) {
71
- errors.push({
72
- planId,
73
- severity: "error",
74
- message: "Plan must include at least one task in the ## Tasks section.",
75
- line: range.startIndex + 1
76
- });
77
- }
78
- return errors;
79
- }
80
- async function lintPlans(plansDir, glob) {
81
- const errors = [];
82
- let entries;
83
- try {
84
- entries = await fs.readdir(plansDir, { withFileTypes: true });
85
- } catch (error) {
86
- if (error.code !== "ENOENT") throw error;
87
- entries = [];
88
- }
89
- const matches = glob ? picomatch(glob) : null;
90
- let lintedPlanCount = 0;
91
- for (const entry of entries) {
92
- if (!entry.isFile() || !entry.name.endsWith(PLAN_EXTENSION)) continue;
93
- const planId = entry.name.slice(0, -PLAN_EXTENSION.length);
94
- if (!PLAN_TASK_ID_REGEX.test(planId) || matches && !matches(entry.name) && !matches(planId)) continue;
95
- const content = await fs.readFile(path.join(plansDir, entry.name), "utf8");
96
- lintedPlanCount += 1;
97
- errors.push(...lintPlanContent(planId, content));
98
- }
99
- return {
100
- type: "plan_lint",
101
- errors,
102
- errorCount: errors.filter((error) => error.severity === "error").length,
103
- warningCount: errors.filter((error) => error.severity === "warning").length,
104
- lintedPlanCount
105
- };
106
- }
107
- function formatPlanLintErrors(errors) {
108
- if (errors.length === 0) return "";
109
- const lines = ["## Plan Lint Errors", ""];
110
- const byPlan = /* @__PURE__ */ new Map();
111
- for (const error of errors) {
112
- byPlan.set(error.planId, [...byPlan.get(error.planId) ?? [], error]);
113
- }
114
- for (const [planId, planErrors] of byPlan) {
115
- lines.push(`### ${planId}.plan.md`);
116
- for (const error of planErrors) {
117
- const location = error.line ? ` line ${error.line}` : "";
118
- lines.push(`- ${error.severity.toUpperCase()}${location}: ${error.message}`);
119
- }
120
- lines.push("");
121
- }
122
- lines.push("Fix these issues by editing the Markdown plan file.");
123
- return lines.join("\n");
124
- }
125
- export {
126
- formatPlanLintErrors,
127
- lintPlanContent,
128
- lintPlans
129
- };