@deksden-com/dd-flow-cli 0.9.0-beta.37 → 0.9.0-beta.38
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.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @deksden-com/dd-flow-cli
|
|
2
2
|
|
|
3
|
+
## 0.9.0-beta.38
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 44e3c80: Allow control operations to recheck failed provider cleanup after a leaderless process group exits naturally. Coalesce concurrent finalization retries, preserve the original exit and process lease, and keep live or unproven groups blocked without sending them signals.
|
|
8
|
+
|
|
3
9
|
## 0.9.0-beta.37
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -1031,6 +1037,7 @@ record` command with the bounded 15-probe contract.
|
|
|
1031
1037
|
- 16f68a3: Add router-native engine snapshot commands and routed project-command dispatch.
|
|
1032
1038
|
|
|
1033
1039
|
Also include the runtime/dashboard compatibility wave needed by the current Memory Bank canon:
|
|
1040
|
+
|
|
1034
1041
|
- target-based dashboard `open`/`refresh` commands and related-command help;
|
|
1035
1042
|
- persisted FIFO lane waiters and merge wait-acquire specialization;
|
|
1036
1043
|
- `migration plan/report/verify` evidence helpers for controlled `mb-upgrade` runtime migrations;
|
package/dist/build-info.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"cli_package": "@deksden-com/dd-flow-cli",
|
|
3
|
-
"cli_version": "0.9.0-beta.
|
|
4
|
-
"cli_commit": "
|
|
5
|
-
"built_at": "2026-09-
|
|
3
|
+
"cli_version": "0.9.0-beta.38",
|
|
4
|
+
"cli_commit": "e1d723e620ee5aeec961c2bee1de1e72fcfb71a9",
|
|
5
|
+
"built_at": "2026-09-08T03:57:03.109Z",
|
|
6
6
|
"built_with_canon": {
|
|
7
7
|
"version": "4.0.6",
|
|
8
8
|
"commit": "c6fc50cb3b5526ea0162ee4454d1ee36f17be2da",
|
|
@@ -212,12 +212,16 @@ export class Runtime {
|
|
|
212
212
|
if (this.active) { this.active.reject(error); this.active = null; }
|
|
213
213
|
const patch = beforeInit ? { shutdown_state: "failed", startup_error: errorPayload(error), provider_exit: { code, signal }, active_tree: false } : { provider_exit: { code, signal }, active_tree: interrupted };
|
|
214
214
|
await providerRegistered;
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
215
|
+
this.retryProviderFinalization = async (graceMs = 1_000) => {
|
|
216
|
+
try {
|
|
217
|
+
await stopProcessGroup(providerChild, graceMs);
|
|
218
|
+
await this.persist(patch);
|
|
219
|
+
await finishDaemonProcess(this.config, providerProcess, beforeInit || interrupted ? "failed" : "stopped", beforeInit || interrupted ? "provider_interrupted" : "provider_stopped");
|
|
220
|
+
this.retryProviderFinalization = null;
|
|
221
|
+
} catch (cleanup) { await this.persist({ shutdown_state: "cleanup_failed", active_tree: true, cleanup_error: errorPayload(cleanup) }); throw cleanup; }
|
|
222
|
+
finally { if (beforeInit) this.server?.close(); }
|
|
223
|
+
};
|
|
224
|
+
await this.retryProviderFinalization();
|
|
221
225
|
}).then(resolve, reject);
|
|
222
226
|
});
|
|
223
227
|
});
|
|
@@ -328,13 +332,25 @@ export class Runtime {
|
|
|
328
332
|
await observeModel({ journal: this.config.journal, harness: "antigravity-cli", sessionId: conversationId, parentSessionId: parent, requested: this.config, observed, source: "native.hook", evidence: payload.model ? "configured" : "unavailable", reason: payload.model ? null : "hook_omits_current_model" });
|
|
329
333
|
const eventId = createHash("sha256").update(JSON.stringify({ daemon: this.config.daemonId, event, conversationId, turn_generation: this.turnGeneration, fully_idle: payload.fullyIdle ?? null, termination_reason: payload.terminationReason ?? null, execution: payload.executionNum ?? null, step: payload.stepIdx ?? null, tool: payload.toolCall?.name ?? null, args: payload.toolCall?.args ?? null })).digest("hex"); await this.persist(completed ? { active_tree: false } : {}); await this.journal("hook", { stale, hook_event: event, event_id: eventId, conversation_id: conversationId, turn_generation: this.turnGeneration, execution_num: execution, step_index: step, termination_reason: payload.terminationReason ?? null, fully_idle: payload.fullyIdle ?? null }); completed?.resolve(settled); return { event_id: eventId, daemon_id: this.config.daemonId, parent_conversation_id: parent, profile: observed, requested_profile: { provider: this.config.provider, model: this.config.model, reasoning: this.config.reasoning, mode: this.config.mode }, project_root: this.config.projectRoot, dd_flow_bin: this.config.ddFlowBin, dd_flow_home: this.config.ddFlowHome };
|
|
330
334
|
}
|
|
331
|
-
async
|
|
335
|
+
async finalizeProviderForControl() {
|
|
336
|
+
const pending = this.providerFinalization;
|
|
337
|
+
try { await pending; }
|
|
338
|
+
catch (error) {
|
|
339
|
+
// A leaderless group may have exited naturally since the last check.
|
|
340
|
+
// Only control may recheck it; startup never retries failed cleanup.
|
|
341
|
+
if (this.providerFinalization !== pending) return await this.providerFinalization;
|
|
342
|
+
if (error.code !== "process_group_ownership_unknown" || !this.retryProviderFinalization) throw error;
|
|
343
|
+
this.providerFinalization = this.retryProviderFinalization(5_000);
|
|
344
|
+
await this.providerFinalization;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
async cancel() { cancelPendingDispatch(this); if (!this.child) return { ...this.receipt(), settled: Boolean(this.exited) }; if (!this.exited) { try { process.kill(-this.child.pid, "SIGINT"); } catch (error) { if (error.code !== "ESRCH") throw error; } const deadline = Date.now() + 5000; while (!this.exited && Date.now() < deadline) await new Promise(resolve => setTimeout(resolve, 100)); if (!this.exited) await stopProcessGroup(this.child, 5_000); } await this.finalizeProviderForControl(); await this.persist({ active_tree: false }); return { ...this.receipt(), cancelled: true, settled: Boolean(this.exited) };
|
|
332
348
|
}
|
|
333
349
|
async close(cancelTree) { if (cancelTree) cancelPendingDispatch(this); if (!cancelTree && (this.active || this.state.active_tree || this.state.unclaimed_activity || (this.lastResult && !this.receipt().settled))) throw new DaemonError("tree_not_settled", "Antigravity root or child tree is still running"); if (cancelTree) await this.cancel(); else if (this.child && !this.exited) this.child.stdin.end(); const deadline = Date.now() + 5000; while (!this.exited && Date.now() < deadline) await new Promise(resolve => setTimeout(resolve, 100)); if (!this.exited) await this.cancel(); await this.providerFinalization; }
|
|
334
350
|
async abortProvider(reason) {
|
|
335
351
|
const child = this.child, providerProcess = this.providerProcess;
|
|
336
352
|
await stopProcessGroup(child);
|
|
337
|
-
await this.
|
|
353
|
+
await this.finalizeProviderForControl();
|
|
338
354
|
await finishDaemonProcess(this.config, providerProcess, "failed", reason);
|
|
339
355
|
}
|
|
340
356
|
async finishResource(state = "stopped", reason = "daemon_stopped") { await finishDaemonProcess(this.config, this.state.resource_process, state, reason); }
|