@deksden-com/dd-flow-cli 0.9.0-beta.7 → 0.9.0-beta.75

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 (123) hide show
  1. package/CHANGELOG.md +404 -0
  2. package/README.md +65 -0
  3. package/dist/build-info.json +10 -10
  4. package/dist/cli/help.js +81 -9
  5. package/dist/cli/run-cli.js +442 -46
  6. package/dist/harness-runtime/bin/dd-agy.mjs +37 -0
  7. package/dist/harness-runtime/bin/dd-codex.mjs +25 -0
  8. package/dist/harness-runtime/bin/dd-droid.mjs +33 -0
  9. package/dist/harness-runtime/bin/dd-grok.mjs +30 -0
  10. package/dist/harness-runtime/bin/dd-opencode.mjs +21 -0
  11. package/dist/harness-runtime/bin/dd-zcode.mjs +83 -0
  12. package/dist/harness-runtime/lib/daemon-operations.mjs +215 -0
  13. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +423 -0
  14. package/dist/harness-runtime/lib/dd-agy.mjs +59 -0
  15. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +141 -0
  16. package/dist/harness-runtime/lib/dd-codex.mjs +438 -0
  17. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +125 -0
  18. package/dist/harness-runtime/lib/dd-droid.mjs +471 -0
  19. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +274 -0
  20. package/dist/harness-runtime/lib/dd-grok.mjs +174 -0
  21. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +198 -0
  22. package/dist/harness-runtime/lib/dd-opencode.mjs +98 -0
  23. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +644 -0
  24. package/dist/harness-runtime/lib/dd-zcode.mjs +910 -0
  25. package/dist/harness-runtime/lib/delegation-instructions.d.mts +10 -0
  26. package/dist/harness-runtime/lib/delegation-instructions.mjs +121 -0
  27. package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
  28. package/dist/harness-runtime/lib/driver-recovery.mjs +129 -0
  29. package/dist/harness-runtime/lib/droid-observation.mjs +66 -0
  30. package/dist/harness-runtime/lib/managed-daemon.mjs +260 -0
  31. package/dist/harness-runtime/lib/model-observations.mjs +77 -0
  32. package/dist/harness-runtime/lib/native-hook-command.mjs +34 -0
  33. package/dist/harness-runtime/lib/observation-clock.mjs +36 -0
  34. package/dist/harness-runtime/lib/operation-context.mjs +5 -0
  35. package/dist/harness-runtime/lib/operation-errors.mjs +19 -0
  36. package/dist/harness-runtime/lib/process-json.mjs +70 -0
  37. package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
  38. package/dist/harness-runtime/lib/runner-events.mjs +200 -0
  39. package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
  40. package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
  41. package/dist/harness-runtime/lib/tool-observations.d.mts +17 -0
  42. package/dist/harness-runtime/lib/tool-observations.mjs +153 -0
  43. package/dist/runtime/context.js +3 -1
  44. package/dist/schemas/agent-profile.schema.json +1 -1
  45. package/dist/schemas/code-review-result.schema.json +2 -2
  46. package/dist/schemas/code-work-batch.schema.json +4 -3
  47. package/dist/schemas/code-work-result.schema.json +4 -4
  48. package/dist/schemas/harness-config.schema.json +23 -0
  49. package/dist/schemas/plan-review-result.schema.json +2 -2
  50. package/dist/schemas/run-control-receipt.schema.json +99 -0
  51. package/dist/schemas/run-control-request.schema.json +36 -0
  52. package/dist/schemas/vnext-protocol-plan.schema.json +2 -2
  53. package/dist/services/cleanup.js +8 -5
  54. package/dist/services/cli-operation-classifier.js +11 -1
  55. package/dist/services/code-checks.js +543 -96
  56. package/dist/services/controller-fanout.js +116 -0
  57. package/dist/services/dashboard.js +9 -0
  58. package/dist/services/engines.js +50 -19
  59. package/dist/services/eval-snapshots.js +639 -60
  60. package/dist/services/execution-policy.js +177 -0
  61. package/dist/services/external-work-launch.js +110 -0
  62. package/dist/services/harness-adapter.js +147 -24
  63. package/dist/services/harness-config.js +68 -0
  64. package/dist/services/hooks.js +413 -168
  65. package/dist/services/lanes.js +1 -1
  66. package/dist/services/lifecycle-command.js +74 -6
  67. package/dist/services/lifecycle-invocations.js +637 -0
  68. package/dist/services/managed-daemon-binding.js +38 -0
  69. package/dist/services/managed-processes.js +138 -22
  70. package/dist/services/merge-queue.js +6 -6
  71. package/dist/services/merge-server.js +75 -29
  72. package/dist/services/migrations.js +1 -1
  73. package/dist/services/native-daemon-history.js +49 -0
  74. package/dist/services/native-session-control.js +39 -0
  75. package/dist/services/projects.js +7 -3
  76. package/dist/services/prompts.js +4 -2
  77. package/dist/services/protocols.js +11 -2
  78. package/dist/services/recovery-observation-budget.js +61 -0
  79. package/dist/services/recovery-snapshot-database.js +107 -0
  80. package/dist/services/run-control-receipt.js +56 -0
  81. package/dist/services/run-control-worker.js +363 -0
  82. package/dist/services/run-control.js +876 -0
  83. package/dist/services/run-controller-adapter.js +211 -0
  84. package/dist/services/run-controller-capture.js +134 -0
  85. package/dist/services/run-controller-process.js +189 -0
  86. package/dist/services/run-controller-recovery.js +222 -0
  87. package/dist/services/run-controller-state.js +31 -0
  88. package/dist/services/run-controller.js +733 -0
  89. package/dist/services/run-engine-bindings.js +20 -62
  90. package/dist/services/run-fork.js +124 -0
  91. package/dist/services/run-observations.js +112 -0
  92. package/dist/services/run-recovery-runtime.js +69 -0
  93. package/dist/services/run-recovery.js +327 -0
  94. package/dist/services/runs.js +280 -40
  95. package/dist/services/runtime-budget.js +362 -0
  96. package/dist/services/runtime-scope-capture.js +50 -0
  97. package/dist/services/runtime-scope-control.js +450 -0
  98. package/dist/services/runtime-scope-resume.js +543 -0
  99. package/dist/services/runtime-scope-stop.js +99 -0
  100. package/dist/services/runtime-scope-worker.js +210 -0
  101. package/dist/services/runtime-service.js +96 -0
  102. package/dist/services/schema-validation.js +12 -12
  103. package/dist/services/stage-context.js +2 -2
  104. package/dist/services/stage-lifecycle.js +32 -10
  105. package/dist/services/stage-pause.js +25 -13
  106. package/dist/services/usage.js +37 -93
  107. package/dist/services/vnext-code-review.js +149 -89
  108. package/dist/services/vnext-code.js +224 -216
  109. package/dist/services/vnext-execution-profile.js +5 -3
  110. package/dist/services/vnext-fanout.js +135 -21
  111. package/dist/services/vnext-merge.js +258 -89
  112. package/dist/services/vnext-plan-review.js +75 -64
  113. package/dist/services/vnext-plan.js +77 -29
  114. package/dist/services/vnext-protocolize.js +21 -14
  115. package/dist/services/vnext-specify.js +26 -16
  116. package/dist/services/work-registry.js +605 -157
  117. package/dist/services/workspace-bootstrap.js +76 -0
  118. package/dist/shared/errors.js +12 -0
  119. package/dist/storage/database.js +341 -31
  120. package/dist/storage/writer-contract.js +77 -0
  121. package/dist/storage/writer-migration.js +102 -0
  122. package/package.json +20 -13
  123. package/tools/repair-paused-run-status.mjs +59 -0
@@ -515,7 +515,7 @@ function ensureQueuedLaneWaiter(context, input) {
515
515
  function tryAcquireQueuedLaneLock(context, input) {
516
516
  expireStaleLocks(context, input.projectId);
517
517
  expireStaleWaiters(context, input.projectId);
518
- context.db.exec("BEGIN IMMEDIATE");
518
+ context.db.beginWriteTransaction();
519
519
  try {
520
520
  const existingLock = activeLaneLock(context, input.projectId, input.lane);
521
521
  if (existingLock?.worker_id === input.workerId) {
@@ -32,7 +32,7 @@ function parseLifecycleCommandInner(command, wrapped) {
32
32
  const heredoc = stripHeredocBodies(command);
33
33
  let entries;
34
34
  try {
35
- entries = parse(heredoc.command, (name) => `$${name}`);
35
+ entries = parse(withoutFileDescriptors(heredoc.command), (name) => `$${name}`);
36
36
  }
37
37
  catch {
38
38
  // A command that cannot be tokenized cannot create a trusted claim. The
@@ -56,11 +56,11 @@ function parseLifecycleCommandInner(command, wrapped) {
56
56
  if (!found.length)
57
57
  return { kind: "none" };
58
58
  const first = found[0];
59
- if (found.length !== 1 || composed || first.nestedCompound) {
59
+ if (found.length !== 1 || composed || first.nestedCompound || (heredoc.present && !heredoc.safe)) {
60
60
  return {
61
61
  kind: "compound",
62
62
  invocation: { ...first.invocation, rewriteSafe: false },
63
- reason: found.length !== 1 ? "multiple_lifecycle_invocations" : first.nestedCompound ? "nested_compound_invocation" : "shell_composition"
63
+ reason: found.length !== 1 ? "multiple_lifecycle_invocations" : first.nestedCompound ? "nested_compound_invocation" : heredoc.present && !heredoc.safe ? "unsafe_heredoc" : "shell_composition"
64
64
  };
65
65
  }
66
66
  return { kind: "standalone", invocation: first.invocation };
@@ -138,7 +138,7 @@ function invocationFromSegment(segment, heredoc, wrapped, inheritedEnv) {
138
138
  executable,
139
139
  argv,
140
140
  env,
141
- args: parseCommandArgs(argv.slice(2)),
141
+ args: parseCommandArgs(argv.slice(operation === "recovery_accept" ? 3 : 2)),
142
142
  command: quote(segment.words),
143
143
  rewriteSafe: !heredoc && !wrapped && !segment.dynamic,
144
144
  wrapped,
@@ -170,15 +170,28 @@ function wrappedInvocationFromSegment(segment) {
170
170
  return parseLifecycleCommandInner(payload, true);
171
171
  }
172
172
  function lifecycleOperation(argv) {
173
+ // The CLI handles help before dispatch, wherever the flag occurs.
174
+ if (argv.some(arg => arg === "--help" || arg === "-h"))
175
+ return null;
176
+ if (argv[0] === "run" && argv[1] === "recovery" && argv[2] === "accept")
177
+ return "recovery_accept";
173
178
  const key = `${argv[0] ?? ""} ${argv[1] ?? ""}`;
174
179
  if (key === "session register")
175
180
  return "session_register";
176
181
  if (key === "stage start")
177
182
  return "stage_start";
183
+ if (key === "stage finish")
184
+ return "stage_finish";
185
+ if (key === "stage pause")
186
+ return "stage_pause";
178
187
  if (key === "stage resume")
179
188
  return "stage_resume";
180
189
  if (key === "work start")
181
190
  return "work_start";
191
+ if (key === "work finish")
192
+ return "work_finish";
193
+ if (key === "work fail")
194
+ return "work_fail";
182
195
  return null;
183
196
  }
184
197
  export function parseCommandArgs(argv) {
@@ -213,6 +226,58 @@ export function commandPosition(invocation, index) {
213
226
  function assignment(word) {
214
227
  return /^[A-Za-z_][A-Za-z0-9_]*=/.test(word);
215
228
  }
229
+ /** Source offsets matter: shell-quote loses the difference between `2>&1`
230
+ * and the literal argument `2 >&1`. Only inspect unquoted shell syntax. */
231
+ function shellSyntaxOffsets(command) {
232
+ const offsets = [];
233
+ let quoted = null, escaped = false;
234
+ for (let i = 0; i < command.length; i++) {
235
+ const char = command[i];
236
+ if (escaped) {
237
+ escaped = false;
238
+ continue;
239
+ }
240
+ if (char === "\\" && quoted !== "'") {
241
+ escaped = true;
242
+ continue;
243
+ }
244
+ if (quoted) {
245
+ if (char === quoted)
246
+ quoted = null;
247
+ continue;
248
+ }
249
+ if (char === "'" || char === '"') {
250
+ quoted = char;
251
+ continue;
252
+ }
253
+ if (char === "#" && (i === 0 || /\s/.test(command[i - 1]))) {
254
+ offsets.push(i);
255
+ break;
256
+ }
257
+ if (char === "<" || char === ">")
258
+ offsets.push(i);
259
+ }
260
+ return offsets;
261
+ }
262
+ function descriptorStart(command, index) {
263
+ let start = index;
264
+ while (start > 0 && /[0-9]/.test(command[start - 1]))
265
+ start--;
266
+ return start === 0 || /[\s;&|]/.test(command[start - 1]) ? start : index;
267
+ }
268
+ export function shellSuffixOffset(command) {
269
+ const offset = shellSyntaxOffsets(command)[0];
270
+ return offset === undefined ? command.length : descriptorStart(command, offset);
271
+ }
272
+ function withoutFileDescriptors(command) {
273
+ for (const index of shellSyntaxOffsets(command).reverse()) {
274
+ if (command[index] === "#")
275
+ continue;
276
+ const start = descriptorStart(command, index);
277
+ command = command.slice(0, start) + command.slice(index);
278
+ }
279
+ return command;
280
+ }
216
281
  function addAssignment(env, word) {
217
282
  const separator = word.indexOf("=");
218
283
  env[word.slice(0, separator)] = word.slice(separator + 1);
@@ -223,6 +288,7 @@ function stripHeredocBodies(command) {
223
288
  const pending = [];
224
289
  let active;
225
290
  let present = false;
291
+ let count = 0, quoted = true;
226
292
  for (const line of lines) {
227
293
  if (active) {
228
294
  const candidate = active.stripTabs ? line.replace(/^\t+/, "") : line;
@@ -233,13 +299,15 @@ function stripHeredocBodies(command) {
233
299
  if (line.trim())
234
300
  output.push(line);
235
301
  const found = heredocDelimiters(line);
302
+ count += found.length;
303
+ quoted &&= found.every(item => item.quoted);
236
304
  if (found.length) {
237
305
  present = true;
238
306
  active = found[0];
239
307
  pending.push(...found.slice(1));
240
308
  }
241
309
  }
242
- return { command: output.join(" ; "), present };
310
+ return { command: output.join(" ; "), present, safe: count === 1 && quoted && !active && pending.length === 0 };
243
311
  }
244
312
  function heredocDelimiters(line) {
245
313
  const result = [];
@@ -282,7 +350,7 @@ function heredocDelimiters(line) {
282
350
  index += 1;
283
351
  const delimiter = line.slice(start, index);
284
352
  if (delimiter)
285
- result.push({ delimiter, stripTabs });
353
+ result.push({ delimiter, stripTabs, quoted: delimiterQuote !== null });
286
354
  }
287
355
  return result;
288
356
  }