@deksden-com/dd-flow-cli 0.9.0-beta.136 → 0.9.0-beta.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.
- package/CHANGELOG.md +12 -0
- package/README.md +9 -0
- package/dist/build-info.json +6 -6
- package/dist/cli/argument-values.js +5 -5
- package/dist/cli/command-inputs.js +89 -20
- package/dist/cli/command-metadata.js +56 -3
- package/dist/cli/command-option-descriptions.js +5 -0
- package/dist/cli/executor-onboarding.js +8 -3
- package/dist/cli/flows.js +29 -0
- package/dist/cli/help.js +240 -6
- package/dist/cli/input-preparation.js +54 -5
- package/dist/cli/memory-flow-admission.js +44 -0
- package/dist/cli/memory-init-invocation.js +78 -0
- package/dist/cli/memory-init.js +240 -0
- package/dist/cli/memory-storage-admission.js +53 -0
- package/dist/cli/native-hook-ingress.js +1 -1
- package/dist/cli/response-file.js +2 -0
- package/dist/cli/run-cli.js +283 -160
- package/dist/cli/setup.js +9 -7
- package/dist/cli.js +54 -2
- package/dist/domain/stage-handler-identities.js +20 -0
- package/dist/harness-runtime/DD-ZCODE.md +13 -0
- package/dist/harness-runtime/bin/dd-opencode.mjs +3 -3
- package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
- package/dist/harness-runtime/lib/daemon-operations.mjs +4 -3
- package/dist/harness-runtime/lib/dd-agy-daemon.mjs +4 -2
- package/dist/harness-runtime/lib/dd-codex-daemon.mjs +11 -5
- package/dist/harness-runtime/lib/dd-codex.mjs +22 -10
- package/dist/harness-runtime/lib/dd-droid-daemon.mjs +2 -1
- package/dist/harness-runtime/lib/dd-droid.mjs +2 -1
- package/dist/harness-runtime/lib/dd-grok-daemon.mjs +4 -2
- package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +20 -5
- package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +45 -10
- package/dist/harness-runtime/lib/dd-zcode.mjs +7 -3
- package/dist/harness-runtime/lib/delegation-instructions.mjs +5 -3
- package/dist/harness-runtime/lib/lifecycle-command.mjs +1 -0
- package/dist/harness-runtime/lib/managed-daemon.d.mts +1 -0
- package/dist/harness-runtime/lib/managed-daemon.mjs +50 -15
- package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
- package/dist/harness-runtime/lib/native-hook-command.mjs +1 -1
- package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
- package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
- package/dist/harness-runtime/lib/opencode-plugin.mjs +5 -1
- package/dist/harness-runtime/lib/operation-progress.mjs +3 -1
- package/dist/runtime/context.js +1 -1
- package/dist/schemas/discovery-result.schema.json +184 -0
- package/dist/schemas/execution-bundle.schema.json +205 -0
- package/dist/schemas/execution-settings.schema.json +162 -0
- package/dist/schemas/flow-descriptor.schema.json +54 -0
- package/dist/schemas/flow-run.schema.json +22 -0
- package/dist/schemas/harness-catalog.schema.json +80 -0
- package/dist/schemas/mb-init-compose-result.schema.json +457 -0
- package/dist/schemas/mb-init-discover-result.schema.json +500 -0
- package/dist/schemas/mb-init-finish-result.schema.json +422 -0
- package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
- package/dist/schemas/mb-init-review-result.schema.json +396 -0
- package/dist/schemas/mb-init-verify-result.schema.json +391 -0
- package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
- package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
- package/dist/schemas/memory-composition-work-result.schema.json +38 -0
- package/dist/schemas/memory-repair-work-result.schema.json +49 -0
- package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
- package/dist/schemas/memory-review-work-result.schema.json +43 -0
- package/dist/schemas/model-catalog.schema.json +153 -0
- package/dist/schemas/profile-settings.schema.json +122 -0
- package/dist/schemas/release-manifest.schema.json +291 -0
- package/dist/schemas/run-engine-binding.schema.json +1 -1
- package/dist/services/check-runner-evidence.js +51 -4
- package/dist/services/cli-operation-classifier.js +8 -47
- package/dist/services/code-checks.js +387 -34
- package/dist/services/controller-child-observer.js +99 -0
- package/dist/services/controller-execution.js +88 -0
- package/dist/services/controller-fanout.js +79 -13
- package/dist/services/dashboard.js +8 -2
- package/dist/services/descriptor-coordinator-session.js +35 -0
- package/dist/services/descriptor-root-work.js +53 -0
- package/dist/services/descriptor-run-settlement.js +105 -0
- package/dist/services/descriptor-run-start.js +449 -0
- package/dist/services/descriptor-stage-coordinator.js +197 -0
- package/dist/services/descriptor-stage-settlement.js +222 -0
- package/dist/services/descriptor-stage-start.js +139 -0
- package/dist/services/engines.js +39 -22
- package/dist/services/eval-snapshots.js +83 -25
- package/dist/services/execution-bundles.js +263 -0
- package/dist/services/execution-policy.js +20 -16
- package/dist/services/external-work-launch.js +91 -11
- package/dist/services/flow-catalog.js +21 -0
- package/dist/services/flow-descriptors.js +82 -0
- package/dist/services/frozen-engine.js +242 -0
- package/dist/services/generic-execution.js +164 -0
- package/dist/services/harness-adapter.js +28 -2
- package/dist/services/hooks.js +24 -6
- package/dist/services/hybrid-contracts.js +31 -3
- package/dist/services/ids.js +29 -1
- package/dist/services/installation-lock.js +7 -4
- package/dist/services/installed-flow-source.js +183 -0
- package/dist/services/lifecycle-invocations.js +257 -78
- package/dist/services/memory-accepted-composition.js +77 -0
- package/dist/services/memory-baseline-preservation.js +65 -0
- package/dist/services/memory-completed-correction-wave.js +320 -0
- package/dist/services/memory-compose-handler.js +258 -0
- package/dist/services/memory-composition-acceptance.js +199 -0
- package/dist/services/memory-composition-graph.js +134 -0
- package/dist/services/memory-composition-registration.js +146 -0
- package/dist/services/memory-composition-work-custody.js +151 -0
- package/dist/services/memory-composition-work-results.js +96 -0
- package/dist/services/memory-corrected-review-acceptance.js +129 -0
- package/dist/services/memory-corrected-review-batch.js +30 -0
- package/dist/services/memory-corrected-review-findings.js +106 -0
- package/dist/services/memory-corrected-review-inputs.js +210 -0
- package/dist/services/memory-corrected-review-projection.js +78 -0
- package/dist/services/memory-corrected-review-receipt.js +170 -0
- package/dist/services/memory-corrected-review-registration.js +191 -0
- package/dist/services/memory-correction-check-receipt.js +219 -0
- package/dist/services/memory-correction-input-owner.js +6 -0
- package/dist/services/memory-discover-handler.js +104 -0
- package/dist/services/memory-finish-evidence.js +435 -0
- package/dist/services/memory-finish-handler.js +215 -0
- package/dist/services/memory-finish-integration.js +280 -0
- package/dist/services/memory-finish-readiness.js +122 -0
- package/dist/services/memory-git-integration.js +151 -0
- package/dist/services/memory-historical-corrected-review.js +206 -0
- package/dist/services/memory-historical-original-review.js +130 -0
- package/dist/services/memory-historical-repair-registration.js +99 -0
- package/dist/services/memory-historical-second-review.js +128 -0
- package/dist/services/memory-init-bootstrap-readiness.js +210 -0
- package/dist/services/memory-init-contexts.js +89 -0
- package/dist/services/memory-init-controller-start.js +84 -0
- package/dist/services/memory-init-engine-release.js +223 -0
- package/dist/services/memory-init-git-policy.js +136 -0
- package/dist/services/memory-init-lint-capability.js +185 -0
- package/dist/services/memory-init-native-capacity.js +241 -0
- package/dist/services/memory-init-preflight.js +312 -0
- package/dist/services/memory-init-project-bootstrap.js +599 -0
- package/dist/services/memory-init-request-candidate.js +157 -0
- package/dist/services/memory-init-request-input.js +66 -0
- package/dist/services/memory-init-resource-storage.js +125 -0
- package/dist/services/memory-init-run-allocation.js +81 -0
- package/dist/services/memory-init-run-bundle.js +98 -0
- package/dist/services/memory-init-start.js +175 -0
- package/dist/services/memory-init-startup-custody.js +80 -0
- package/dist/services/memory-init-startup-input.js +240 -0
- package/dist/services/memory-init-storage.js +81 -0
- package/dist/services/memory-init-stores.js +359 -0
- package/dist/services/memory-init-worktrunk-capability.js +172 -0
- package/dist/services/memory-layer-publication.js +611 -0
- package/dist/services/memory-layer.js +156 -0
- package/dist/services/memory-lint-config.js +85 -0
- package/dist/services/memory-native-review-copy.js +165 -0
- package/dist/services/memory-normal-flow-entry.js +75 -0
- package/dist/services/memory-ordinary-defaults.js +112 -0
- package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
- package/dist/services/memory-preflight-handler.js +259 -0
- package/dist/services/memory-repair-current-view.js +299 -0
- package/dist/services/memory-repair-document-delta.js +451 -0
- package/dist/services/memory-repair-history.js +491 -0
- package/dist/services/memory-repair-physical-binding.js +312 -0
- package/dist/services/memory-repair-publication-files.js +152 -0
- package/dist/services/memory-repair-publication-intent.js +27 -0
- package/dist/services/memory-repair-publication-plan.js +160 -0
- package/dist/services/memory-repair-publication-source.js +225 -0
- package/dist/services/memory-repair-publication.js +794 -0
- package/dist/services/memory-repair-registration.js +239 -0
- package/dist/services/memory-repair-work-baseline.js +413 -0
- package/dist/services/memory-repair-work-completion.js +97 -0
- package/dist/services/memory-repair-work-custody.js +73 -0
- package/dist/services/memory-repair-work-results.js +89 -0
- package/dist/services/memory-repair-workspace.js +252 -0
- package/dist/services/memory-repair-writer-copy.js +735 -0
- package/dist/services/memory-result-binding.js +173 -0
- package/dist/services/memory-retained-review-authority.js +129 -0
- package/dist/services/memory-retained-review-results.js +70 -0
- package/dist/services/memory-retained-second-baseline.js +102 -0
- package/dist/services/memory-retained-second-repairs.js +156 -0
- package/dist/services/memory-review-acceptance.js +214 -0
- package/dist/services/memory-review-correction-plan.js +171 -0
- package/dist/services/memory-review-handler.js +585 -0
- package/dist/services/memory-review-inputs.js +200 -0
- package/dist/services/memory-review-receipt.js +180 -0
- package/dist/services/memory-review-registration.js +108 -0
- package/dist/services/memory-review-work-custody.js +124 -0
- package/dist/services/memory-review-work-input.js +72 -0
- package/dist/services/memory-review-work-results.js +73 -0
- package/dist/services/memory-second-corrected-review-inputs.js +165 -0
- package/dist/services/memory-second-correction-plan.js +76 -0
- package/dist/services/memory-second-repair-baseline.js +91 -0
- package/dist/services/memory-second-repair-launch.js +614 -0
- package/dist/services/memory-second-repair-registration.js +88 -0
- package/dist/services/memory-second-repair-source.js +187 -0
- package/dist/services/memory-second-review-acceptance.js +115 -0
- package/dist/services/memory-source-observations.js +117 -0
- package/dist/services/memory-stage-dispatch.js +28 -0
- package/dist/services/memory-stage-results.js +199 -0
- package/dist/services/memory-verification-acceptance.js +135 -0
- package/dist/services/memory-verification-checks.js +252 -0
- package/dist/services/memory-verification-receipt.js +159 -0
- package/dist/services/memory-verify-handler.js +135 -0
- package/dist/services/memory-work-result-preparation.js +63 -0
- package/dist/services/projects.js +17 -2
- package/dist/services/recovery-snapshot-database.js +416 -1
- package/dist/services/repair-intents.js +1 -1
- package/dist/services/review-copy.js +10 -2
- package/dist/services/run-control.js +80 -9
- package/dist/services/run-controller-capture.js +10 -3
- package/dist/services/run-controller-process.js +21 -0
- package/dist/services/run-controller-recovery.js +3 -1
- package/dist/services/run-controller-state.js +1 -1
- package/dist/services/run-controller.js +184 -48
- package/dist/services/run-recovery-guard.js +2 -0
- package/dist/services/run-recovery.js +145 -5
- package/dist/services/run-start-custody.js +177 -0
- package/dist/services/runs.js +319 -25
- package/dist/services/stage-context.js +9 -1
- package/dist/services/stage-handlers.js +74 -0
- package/dist/services/stage-lifecycle.js +2 -1
- package/dist/services/stage-report-renderer.js +76 -0
- package/dist/services/stage-work-graph.js +17 -0
- package/dist/services/vnext-code.js +3 -3
- package/dist/services/vnext-execution-profile.js +2 -2
- package/dist/services/vnext-fanout.js +136 -10
- package/dist/services/vnext-merge.js +8 -3
- package/dist/services/vnext-plan-review.js +6 -4
- package/dist/services/vnext-protocolize.js +60 -2
- package/dist/services/work-registry.js +616 -71
- package/dist/services/workspace-files.js +1 -1
- package/dist/storage/database.js +84 -6
- package/dist/storage/writer-contract.js +11 -7
- package/package.json +13 -3
- package/tools/create-canon-release.mjs +33 -0
- package/tools/produce-hybrid-release.mjs +41 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
4
|
+
import { Writable } from "node:stream";
|
|
5
|
+
import { once } from "node:events";
|
|
6
|
+
import { createContext } from "../runtime/context.js";
|
|
7
|
+
import { AppError, errorRecord } from "../shared/errors.js";
|
|
8
|
+
import { hybridDigest } from "../services/hybrid-contracts.js";
|
|
9
|
+
import { readMemoryInitStartupInput } from "../services/memory-init-startup-custody.js";
|
|
10
|
+
import { readMemoryInitRequestInput } from "../services/memory-init-request-input.js";
|
|
11
|
+
import { prepareMemoryInitFreshRequest, prepareMemoryInitSelection, startMemoryInitRun } from "../services/memory-init-start.js";
|
|
12
|
+
import { PreparedMemoryInitLintCapability } from "../services/memory-init-lint-capability.js";
|
|
13
|
+
import { PreparedMemoryInitWorktrunkCapability } from "../services/memory-init-worktrunk-capability.js";
|
|
14
|
+
import { produceMemoryInitNativeCapacity } from "../services/memory-init-native-capacity.js";
|
|
15
|
+
import { openMemoryInitStores, assertMemoryInitStorePrerequisites } from "../services/memory-init-stores.js";
|
|
16
|
+
import { prepareMemoryInitControllerStart } from "../services/memory-init-controller-start.js";
|
|
17
|
+
import { runControllerStatus } from "../services/run-controller.js";
|
|
18
|
+
import { requireRun } from "../services/run-controller-state.js";
|
|
19
|
+
import { requireProjectByRoot } from "../services/projects.js";
|
|
20
|
+
import { routeArgsThroughEngine } from "../services/engines.js";
|
|
21
|
+
import { parseRuntimeBudget } from "../services/runtime-budget.js";
|
|
22
|
+
import { prepareFileBytes } from "./input-preparation.js";
|
|
23
|
+
import { prepareMemoryInitInvocation, assertMemoryInitInvocationReplay } from "./memory-init-invocation.js";
|
|
24
|
+
import { parseOutputOptions } from "./output-options.js";
|
|
25
|
+
import { prepareResponseDestination, writeResponseFile } from "./response-file.js";
|
|
26
|
+
import { writePreparationError } from "./error-output.js";
|
|
27
|
+
import { onboardExecutor } from "../services/executor-onboarding.js";
|
|
28
|
+
import { readOperatorProfiles, readOperatorProfileInput } from "../services/operator-profiles.js";
|
|
29
|
+
import { resolveDdFlowHome } from "../storage/paths.js";
|
|
30
|
+
import { askExecutorChoice } from "./executor-onboarding.js";
|
|
31
|
+
/** Backpressure bounds the observing client's output; closing it never controls the RUN. */
|
|
32
|
+
export async function writeMemoryInitObservation(stdout, text) {
|
|
33
|
+
const disconnected = () => Boolean(stdout.destroyed);
|
|
34
|
+
if (disconnected())
|
|
35
|
+
return false;
|
|
36
|
+
const waiting = new AbortController();
|
|
37
|
+
try {
|
|
38
|
+
// Observe errors even when write returns true: a short pipe write can
|
|
39
|
+
// report EPIPE asynchronously. Writable emits callback errors as events.
|
|
40
|
+
const closed = once(stdout, "close", { signal: waiting.signal });
|
|
41
|
+
const written = new Promise(resolve => {
|
|
42
|
+
stdout.write(text, error => { if (!error)
|
|
43
|
+
resolve(); });
|
|
44
|
+
});
|
|
45
|
+
await Promise.race([written, closed]);
|
|
46
|
+
return !disconnected();
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (error.code === "EPIPE")
|
|
50
|
+
return false;
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
waiting.abort();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Both public spellings enter this owner. The controller, never this observer,
|
|
58
|
+
* owns Sessions and productive dispatch; disconnect does not request stop. */
|
|
59
|
+
export async function runMemoryInitCli(args, env = process.env, io = process) {
|
|
60
|
+
let context;
|
|
61
|
+
let effects = false;
|
|
62
|
+
try {
|
|
63
|
+
const output = parseOutputOptions(args), invocation = prepareMemoryInitInvocation(output.args);
|
|
64
|
+
parseRuntimeBudget(env.DD_FLOW_RUNTIME_BUDGET);
|
|
65
|
+
if (output.responseFile)
|
|
66
|
+
prepareResponseDestination(output.responseFile);
|
|
67
|
+
const reader = createContext(env, "read_existing");
|
|
68
|
+
let retained;
|
|
69
|
+
try {
|
|
70
|
+
retained = readMemoryInitStartupInput(reader, invocation.scope);
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
reader.db.close?.();
|
|
74
|
+
}
|
|
75
|
+
let prepared;
|
|
76
|
+
if (retained) {
|
|
77
|
+
if (retained.payload.schema_id !== "dd-flow/memory-init-startup-input@3")
|
|
78
|
+
throw new AppError("memory_init_original_request_required", "Public init replay requires independently retained original input", 1, { effect: "no_effect" });
|
|
79
|
+
const raw = readMemoryInitRequestInput(retained.payload.request_input, invocation.scope, retained.payload.objective);
|
|
80
|
+
// A supplied file is an explicit selector and must still match. Omitted
|
|
81
|
+
// files never reopen mutable profile inputs during exact replay.
|
|
82
|
+
if (invocation.profileFile)
|
|
83
|
+
invocation.execution.rootProfile = readOperatorProfileInput(invocation.profileFile);
|
|
84
|
+
assertMemoryInitInvocationReplay(invocation, raw.selection, retained.payload.request_input.intake_sha256);
|
|
85
|
+
if (invocation.nativeConfigHome) {
|
|
86
|
+
const reference = retained.payload.execution.snapshot.settings.delegation.native_capacity_receipt;
|
|
87
|
+
const encoded = retained.payload.execution.receipt_blobs?.find(([checksum]) => checksum === reference?.sha256)?.[1];
|
|
88
|
+
if (!encoded || JSON.parse(Buffer.from(encoded, "base64").toString("utf8")).input.native_config_home !== invocation.nativeConfigHome)
|
|
89
|
+
throw new AppError("memory_init_request_conflict", "Native private configuration selection changed", 1, { effect: "no_effect" });
|
|
90
|
+
}
|
|
91
|
+
context = openMemoryInitStores(env, { scope: invocation.scope, selectionSha256: hybridDigest(raw.selection) }).context;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
if (!invocation.intakeFile || !invocation.intakeSha256 || !invocation.gitPolicy)
|
|
95
|
+
throw new AppError("usage", "Fresh init requires original intake file/hash and explicit Git route/integration branch", 2, { phase: "prepare", effect: "no_effect" });
|
|
96
|
+
const raw = prepareFileBytes(invocation.intakeFile, "original init intake", 64 * 1024).bytes;
|
|
97
|
+
if (createHash("sha256").update(raw).digest("hex") !== invocation.intakeSha256)
|
|
98
|
+
throw new AppError("memory_init_intake_changed", "Original intake bytes differ from --intake-sha256", 2, { phase: "prepare", effect: "no_effect" });
|
|
99
|
+
let objective;
|
|
100
|
+
try {
|
|
101
|
+
objective = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(raw);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
throw new AppError("usage", "Original init intake must be UTF-8", 2, { phase: "prepare", effect: "no_effect" });
|
|
105
|
+
}
|
|
106
|
+
// Controller birth/lease confirmation uses this OS observation. Known
|
|
107
|
+
// inability must refuse before candidate, stores or project publication.
|
|
108
|
+
const identity = spawnSync("ps", ["-o", "lstart=", "-p", String(process.pid)], { env: { ...env, TZ: "UTC", LC_ALL: "C" }, encoding: "utf8", timeout: 1000, shell: false, windowsHide: true });
|
|
109
|
+
if (identity.error || identity.signal || identity.status !== 0 || !identity.stdout.trim())
|
|
110
|
+
throw new AppError("memory_init_runtime_unavailable", "Controller physical identity observation is unavailable", 1, { phase: "prepare", effect: "no_effect", next_action: "restore_system_process_observation" });
|
|
111
|
+
const stdin = io.stdin ?? process.stdin;
|
|
112
|
+
const nonInteractive = invocation.nonInteractive || output.json || output.progressJsonl
|
|
113
|
+
|| !stdin.isTTY || !io.stderr.isTTY;
|
|
114
|
+
const selected = await onboardExecutor({
|
|
115
|
+
...(typeof invocation.execution.rootProfile === "string" ? { profileId: invocation.execution.rootProfile } : {}),
|
|
116
|
+
...(invocation.profileFile ? { profileFile: invocation.profileFile } : {})
|
|
117
|
+
}, () => readOperatorProfiles(resolveDdFlowHome(env)), { allowSkip: false, nonInteractive }, settings => askExecutorChoice(settings, { stdin, stderr: io.stderr }, { allowSave: false, allowSkip: false }));
|
|
118
|
+
if (selected.source === "explicit-file" || selected.source === "explicit-profile")
|
|
119
|
+
invocation.execution.rootProfile = selected.profile;
|
|
120
|
+
else if (invocation.execution.rootProfile === undefined && selected.source === "explicit-id")
|
|
121
|
+
invocation.execution.rootProfile = selected.profile.id;
|
|
122
|
+
let native;
|
|
123
|
+
if (invocation.execution.delegation?.mode === "native") {
|
|
124
|
+
if (!invocation.allowLiveProbe)
|
|
125
|
+
throw new AppError("usage", "Fresh native init requires --allow-live-probe", 2, { effect: "no_effect" });
|
|
126
|
+
const admissionReader = createContext(env, "read_existing");
|
|
127
|
+
let profile;
|
|
128
|
+
try {
|
|
129
|
+
const baseline = prepareMemoryInitSelection(admissionReader, invocation.scope, { execution: {
|
|
130
|
+
...invocation.execution, delegation: { mode: "external", max_parallel: invocation.execution.delegation.max_parallel ?? 1 }
|
|
131
|
+
}, gitPolicy: invocation.gitPolicy, objective });
|
|
132
|
+
PreparedMemoryInitLintCapability.prepare(baseline.target, env);
|
|
133
|
+
PreparedMemoryInitWorktrunkCapability.prepare(baseline.target, env);
|
|
134
|
+
baseline.engine.admitMemoryInitFlow(baseline.source, "dd-flow/memory-init-startup-input@3");
|
|
135
|
+
assertMemoryInitStorePrerequisites(env, invocation.scope);
|
|
136
|
+
const snapshot = baseline.execution.snapshot();
|
|
137
|
+
profile = snapshot.profiles.find(entry => entry.id === snapshot.settings.root_profile).profile;
|
|
138
|
+
if (snapshot.profiles.some(entry => hybridDigest({ ...entry.profile, id: profile.id }) !== hybridDigest(profile)))
|
|
139
|
+
throw new AppError("generic_execution_invalid", "Native delegation cannot change execution profiles", 2, { effect: "no_effect" });
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
admissionReader.db.close?.();
|
|
143
|
+
}
|
|
144
|
+
// From here a failed reply cannot imply no effect: daemon/child custody
|
|
145
|
+
// is independent from later startup publication and RUN allocation.
|
|
146
|
+
effects = true;
|
|
147
|
+
native = await produceMemoryInitNativeCapacity({ home: resolveDdFlowHome(env), scope: invocation.scope, profile,
|
|
148
|
+
maximum: invocation.execution.delegation.max_parallel ?? 1,
|
|
149
|
+
...(invocation.nativeConfigHome !== undefined ? { nativeConfigHome: invocation.nativeConfigHome } : {}),
|
|
150
|
+
allowLiveProbe: invocation.allowLiveProbe, env, requestSha256: hybridDigest({ scope: invocation.scope,
|
|
151
|
+
execution: invocation.execution, gitPolicy: invocation.gitPolicy, objective, intake: invocation.intakeSha256 }) });
|
|
152
|
+
invocation.execution.delegation.nativeCapacityReceipt = native.reference;
|
|
153
|
+
}
|
|
154
|
+
const owner = prepareMemoryInitFreshRequest(env, invocation.scope, { execution: invocation.execution, gitPolicy: invocation.gitPolicy, objective,
|
|
155
|
+
...(native ? { receipts: native.receipts, receiptBytes: native.receiptBytes } : {}) }, raw);
|
|
156
|
+
context = owner.context;
|
|
157
|
+
prepared = owner.prepared;
|
|
158
|
+
}
|
|
159
|
+
// Beyond this boundary, absence of a success receipt is not no-effect.
|
|
160
|
+
effects = true;
|
|
161
|
+
const started = startMemoryInitRun(context, invocation.scope, prepared ? () => prepared : undefined);
|
|
162
|
+
if (invocation.prepareOnly) {
|
|
163
|
+
const run = requireRun(context, requireProjectByRoot(context, invocation.scope.projectRoot).id, started.runId);
|
|
164
|
+
const response = { ok: true, action: "flow_mb_init_prepared", flow_id: "mb-init", ...started,
|
|
165
|
+
run_id: started.runId, request_id: invocation.scope.requestId, run_root: run.run_root,
|
|
166
|
+
project_root: run.project_root, workspace_root: run.workspace_root };
|
|
167
|
+
await writeMemoryInitObservation(io.stdout, `${JSON.stringify(writeResponseFile(response, output), null, output.json || output.progressJsonl ? undefined : 2)}\n`);
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
const launch = prepareMemoryInitControllerStart(context, invocation.scope);
|
|
171
|
+
// Use the existing RUN-bound router: a global CLI must not launch its own
|
|
172
|
+
// controller code in place of the independently frozen RUN executable.
|
|
173
|
+
const receiptChunks = [];
|
|
174
|
+
let receiptSize = 0, oversizedReceipt = false;
|
|
175
|
+
const capture = new Writable({ write(chunk, _, next) {
|
|
176
|
+
receiptSize += Buffer.byteLength(chunk);
|
|
177
|
+
if (receiptSize > 1024 * 1024)
|
|
178
|
+
oversizedReceipt = true;
|
|
179
|
+
else
|
|
180
|
+
receiptChunks.push(Buffer.from(chunk));
|
|
181
|
+
next();
|
|
182
|
+
} });
|
|
183
|
+
const routed = await routeArgsThroughEngine(context, ["run", "drive", "launch", "--project-root", launch.input.projectRoot,
|
|
184
|
+
"--run", launch.input.runId, "--request-id", launch.input.requestId, "--context-file", launch.input.contextFile,
|
|
185
|
+
"--context-sha256", launch.input.contextSha256, "--json"], { stdout: capture, stderr: io.stderr }, undefined, { ...env, DD_FLOW_ENGINE_MODE: undefined }, invocation.scope.projectRoot);
|
|
186
|
+
if (!routed?.routed || routed.inProcess || routed.exitCode !== 0 || oversizedReceipt)
|
|
187
|
+
throw new AppError("memory_init_controller_launch_unknown", "Observe or reconcile the exact RUN-bound controller launch", 1, { effect: "unknown" });
|
|
188
|
+
let receipt;
|
|
189
|
+
try {
|
|
190
|
+
receipt = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(Buffer.concat(receiptChunks)));
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
throw new AppError("memory_init_controller_launch_unknown", "Selected engine returned no valid controller receipt", 1, { effect: "unknown" });
|
|
194
|
+
}
|
|
195
|
+
const accepted = receipt.controller;
|
|
196
|
+
if (receipt.ok !== true || !accepted || accepted.run_id !== started.runId || accepted.request_id !== invocation.scope.requestId)
|
|
197
|
+
throw new AppError("memory_init_controller_launch_unknown", "Selected engine returned a foreign controller receipt", 1, { effect: "unknown" });
|
|
198
|
+
const emit = (result) => writeMemoryInitObservation(io.stdout, `${JSON.stringify(result, null, output.json || output.progressJsonl ? undefined : 2)}\n`);
|
|
199
|
+
if (output.progressJsonl && !await emit({ ok: true, action: "flow_accepted", flow_id: "mb-init", ...started, ...receipt }))
|
|
200
|
+
return 0;
|
|
201
|
+
let result = receipt;
|
|
202
|
+
if (!invocation.detach) {
|
|
203
|
+
let after = 0;
|
|
204
|
+
let recentEvents = [];
|
|
205
|
+
for (;;) {
|
|
206
|
+
// The client has no ownership of the detached controller process.
|
|
207
|
+
if (io.stdout.destroyed)
|
|
208
|
+
return 0;
|
|
209
|
+
result = runControllerStatus(context, { projectRoot: invocation.scope.projectRoot, runId: started.runId, after });
|
|
210
|
+
const events = result.events, controller = result.controller;
|
|
211
|
+
after = result.next_cursor;
|
|
212
|
+
recentEvents = [...recentEvents, ...events].slice(-100);
|
|
213
|
+
if (output.progressJsonl && events.length && !await emit({ ok: true, action: "flow_progress", flow_id: "mb-init", ...result }))
|
|
214
|
+
return 0;
|
|
215
|
+
if (!controller)
|
|
216
|
+
throw new AppError("memory_init_controller_receipt_missing", "Observe or reconcile the retained controller", 1, { effect: "unknown" });
|
|
217
|
+
if (["completed", "cancelled", "superseded", "recovery_required", "failed", "waiting_for_user", "waiting_for_context"].includes(controller.status)) {
|
|
218
|
+
result = { ...result, events: recentEvents };
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
await delay(250);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const response = { ...result, action: "flow_mb_init", flow_id: "mb-init", run_id: started.runId, request_id: invocation.scope.requestId };
|
|
225
|
+
if (!await emit(writeResponseFile(response, output)))
|
|
226
|
+
return 0;
|
|
227
|
+
const status = result.controller?.status;
|
|
228
|
+
return ["recovery_required", "failed", "cancelled", "superseded"].includes(status ?? "") ? 1 : 0;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
const record = errorRecord(error);
|
|
232
|
+
if (effects)
|
|
233
|
+
record.details = { ...record.details, effect: record.details.effect === "partial" ? "partial" : "unknown", next_action: "observe_or_reconcile_exact_request" };
|
|
234
|
+
writePreparationError(io, args, record);
|
|
235
|
+
return record.exitCode;
|
|
236
|
+
}
|
|
237
|
+
finally {
|
|
238
|
+
context?.db.close?.();
|
|
239
|
+
}
|
|
240
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { prepareCommandRoute } from "./command-inputs.js";
|
|
4
|
+
import { parseOutputOptions } from "./output-options.js";
|
|
5
|
+
import { createContext } from "../runtime/context.js";
|
|
6
|
+
import { getResourceDatabase } from "../storage/database.js";
|
|
7
|
+
import { withStoreCleanup } from "../storage/native-cleanup.js";
|
|
8
|
+
import { PreparedMemoryInitRuntimeStorage } from "../services/memory-init-storage.js";
|
|
9
|
+
import { PreparedMemoryInitResourceStorage } from "../services/memory-init-resource-storage.js";
|
|
10
|
+
import { hybridDigest } from "../services/hybrid-contracts.js";
|
|
11
|
+
import { AppError, errorRecord } from "../shared/errors.js";
|
|
12
|
+
import { writePreparationError } from "./error-output.js";
|
|
13
|
+
/** Selected engine's non-migrating operation admission. No AppContext initialize. */
|
|
14
|
+
export function runMemoryStorageAdmissionCli(args, env = process.env, io = process) {
|
|
15
|
+
try {
|
|
16
|
+
const output = parseOutputOptions(args), route = prepareCommandRoute(output.args);
|
|
17
|
+
if (route.key !== "runtime storage admit" || output.responseFile || output.progressJsonl) {
|
|
18
|
+
throw new AppError("usage", "Storage admission accepts stdout output only", 2, { effect: "no_effect" });
|
|
19
|
+
}
|
|
20
|
+
const home = env.DD_FLOW_HOME;
|
|
21
|
+
if (!home || !path.isAbsolute(home) || path.resolve(home) !== home || fs.realpathSync(home) !== home) {
|
|
22
|
+
throw new AppError("usage", "Storage admission requires an explicit canonical absolute DD_FLOW_HOME", 2, { effect: "no_effect" });
|
|
23
|
+
}
|
|
24
|
+
const file = path.join(home, "db.sqlite"), owner = fs.lstatSync(file);
|
|
25
|
+
if (!owner.isFile() || owner.nlink !== 1)
|
|
26
|
+
throw new AppError("run_storage_unprepared", "RUN storage must be a regular single-linked file", 1, { effect: "no_effect" });
|
|
27
|
+
const resource = PreparedMemoryInitResourceStorage.prepare({ ddFlowHome: home, env });
|
|
28
|
+
const context = createContext(env, "prepared_existing");
|
|
29
|
+
const facts = withStoreCleanup(() => {
|
|
30
|
+
const run = PreparedMemoryInitRuntimeStorage.prepare(context);
|
|
31
|
+
const resourceWriter = getResourceDatabase(path.dirname(resource.facts().store_path), "prepared_existing");
|
|
32
|
+
return withStoreCleanup(() => {
|
|
33
|
+
if (resourceWriter.get("SELECT dd_flow_writer_version() AS version")?.version !== resource.facts().executing_writer_version) {
|
|
34
|
+
throw new AppError("store_writer_incompatible", "Resource connection writer differs from admitted storage", 1, { effect: "no_effect" });
|
|
35
|
+
}
|
|
36
|
+
resource.revalidate({ ddFlowHome: home, env });
|
|
37
|
+
const current = fs.lstatSync(file);
|
|
38
|
+
if (!current.isFile() || current.nlink !== 1 || current.dev !== owner.dev || current.ino !== owner.ino) {
|
|
39
|
+
throw new AppError("run_storage_changed", "RUN store changed during admission", 1, { effect: "no_effect" });
|
|
40
|
+
}
|
|
41
|
+
return { schema_id: "dd-flow/memory-init-engine-storage@1", operation: "memory-init", route: "verified-no-op", outcome: "no-op",
|
|
42
|
+
run: { ...run.facts(), store_dev: owner.dev, store_ino: owner.ino }, resource: resource.facts() };
|
|
43
|
+
}, () => resourceWriter.close?.());
|
|
44
|
+
}, () => context.db.close?.());
|
|
45
|
+
io.stdout.write(`${JSON.stringify({ ok: true, action: "runtime_storage_admit", facts, sha256: hybridDigest(facts) }, null, output.json ? undefined : 2)}\n`);
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const record = errorRecord(error);
|
|
50
|
+
writePreparationError(io, args, record);
|
|
51
|
+
return record.exitCode;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -8,7 +8,7 @@ export function isNativeHookIngress(args) {
|
|
|
8
8
|
}
|
|
9
9
|
export async function dispatchNativeHook(args, stdin, env) {
|
|
10
10
|
const started = performance.now();
|
|
11
|
-
const deadline = env.DD_FLOW_HOOK_DEADLINE_AT
|
|
11
|
+
const deadline = env.DD_FLOW_HOOK_DEADLINE_AT ? Number(env.DD_FLOW_HOOK_DEADLINE_AT) : undefined;
|
|
12
12
|
if (deadline !== undefined && !Number.isSafeInteger(deadline))
|
|
13
13
|
throw new AppError("hook_deadline_invalid", "Native hook deadline must be an absolute millisecond timestamp", 1, { effect: "unknown" });
|
|
14
14
|
const phase = (name) => {
|
|
@@ -25,6 +25,8 @@ export function prepareResponseDestination(value) {
|
|
|
25
25
|
parent = next;
|
|
26
26
|
parentStat = inspect(parent);
|
|
27
27
|
}
|
|
28
|
+
if (parentStat?.isSymbolicLink())
|
|
29
|
+
parentStat = fs.statSync(parent);
|
|
28
30
|
const targetStat = inspect(file);
|
|
29
31
|
if (!parentStat?.isDirectory() || targetStat && !targetStat.isFile())
|
|
30
32
|
throw new Error();
|