@deksden-com/dd-flow-cli 0.9.0-beta.137 → 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 +4 -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 +197 -0
- package/dist/cli/command-option-descriptions.js +191 -0
- package/dist/cli/completion-cli.js +70 -0
- package/dist/cli/completion.js +57 -0
- package/dist/cli/error-output.js +52 -0
- package/dist/cli/executor-onboarding.js +76 -0
- package/dist/cli/flows.js +29 -0
- package/dist/cli/harnesses.js +84 -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/models.js +39 -0
- package/dist/cli/native-hook-ingress.js +1 -1
- package/dist/cli/operator-profiles.js +61 -0
- package/dist/cli/output-options.js +35 -0
- package/dist/cli/response-file.js +71 -0
- package/dist/cli/run-cli.js +283 -160
- package/dist/cli/setup.js +149 -0
- package/dist/cli.js +54 -2
- package/dist/domain/stage-handler-identities.js +20 -0
- 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 +6 -4
- package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +9 -9
- 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 +2 -0
- 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/cli-upgrade-allowlist.js +27 -0
- package/dist/services/code-checks.js +387 -34
- package/dist/services/controller-execution.js +88 -0
- package/dist/services/controller-fanout.js +71 -12
- 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/discovery/agy-discovery.js +2 -0
- package/dist/services/discovery/codex-discovery.js +2 -0
- package/dist/services/discovery/droid-discovery.js +2 -0
- package/dist/services/discovery/grok-discovery.js +2 -0
- package/dist/services/discovery/opencode-discovery.js +2 -0
- package/dist/services/discovery/static.js +31 -0
- package/dist/services/discovery/zcode-discovery.js +2 -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/executor-onboarding.js +56 -0
- 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/harness-discovery.js +29 -0
- package/dist/services/harness-doctor.js +75 -0
- package/dist/services/harness-probe-effects.js +51 -0
- package/dist/services/harness-version-probe.js +100 -0
- package/dist/services/hooks.js +24 -6
- package/dist/services/hybrid-contracts.js +483 -0
- package/dist/services/ids.js +29 -1
- package/dist/services/installation-lock.js +95 -0
- 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/model-catalog.js +109 -0
- package/dist/services/model-discovery.js +46 -0
- package/dist/services/operator-profiles.js +236 -0
- package/dist/services/projects.js +17 -2
- package/dist/services/recovery-snapshot-database.js +416 -1
- package/dist/services/release-archive-producer.js +52 -0
- package/dist/services/release-archive.js +143 -0
- package/dist/services/release-cache.js +142 -0
- package/dist/services/release-compatibility.js +18 -0
- package/dist/services/release-download.js +67 -0
- package/dist/services/release-envelope.js +104 -0
- package/dist/services/release-manifest.js +45 -0
- package/dist/services/release-payload.js +114 -0
- package/dist/services/release-producer.js +63 -0
- package/dist/services/release-provenance.js +160 -0
- package/dist/services/release-registry.js +66 -0
- package/dist/services/release-source.js +194 -0
- 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 +101 -40
- 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/setup.js +377 -0
- package/dist/services/stage-context.js +9 -1
- package/dist/services/stage-handlers.js +74 -0
- package/dist/services/stage-report-renderer.js +63 -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 +70 -9
- package/dist/services/vnext-merge.js +8 -3
- package/dist/services/vnext-plan-review.js +6 -4
- 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
package/dist/cli/help.js
CHANGED
|
@@ -1,4 +1,171 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
import { commandInputs, commandAliases } from "./command-inputs.js";
|
|
3
|
+
import { commandKeyForPositions, globalOptionDocumentation, optionsForCommandTree, routerNativeRoute } from "./command-metadata.js";
|
|
1
4
|
const helpPages = new Map([
|
|
5
|
+
["flow mb-init", `dd-flow init / flow mb-init - managed project Memory Bank initialization
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
dd-flow init --project-root /absolute/project --workspace-root /absolute/workspace --request-id ID --intake-file /absolute/intake.txt --intake-sha256 SHA256 --git-route integration_branch_direct --integration-branch main [--profile ID-or-alias] [--detach] --json
|
|
9
|
+
dd-flow flow mb-init --project-root /absolute/project --workspace-root /absolute/workspace --request-id ID [--detach] --json
|
|
10
|
+
|
|
11
|
+
Both spellings share one command definition and dispatcher. Fresh execution
|
|
12
|
+
requires the original bounded UTF-8 intake bytes and explicit Git policy.
|
|
13
|
+
setup installs the computer-level canon; init initializes the specified project.
|
|
14
|
+
Missing executor defaults or prerequisites refuse before project publication.
|
|
15
|
+
Profiles, descriptor, engine and original request are frozen before dispatch.
|
|
16
|
+
|
|
17
|
+
Replay uses the exact retained request, not current defaults, aliases or canon.
|
|
18
|
+
Omitted selectors reuse original choices; supplied selectors must match them.
|
|
19
|
+
The original intake file need not survive replay: its supplied hash must match
|
|
20
|
+
the retained bytes. --stage-profile stage=profile and --work-profile profile
|
|
21
|
+
are repeatable approved overrides, frozen before launch.
|
|
22
|
+
|
|
23
|
+
--profile-file /absolute/profile.json is exclusive with --profile and supplies
|
|
24
|
+
one complete validated operation-only profile. It never saves a global profile
|
|
25
|
+
or changes defaults; a conflicting saved ID/alias refuses. Replay may omit this
|
|
26
|
+
file after removal; if supplied, its admitted profile must match the original.
|
|
27
|
+
When no default or explicit profile exists, an interactive terminal uses the
|
|
28
|
+
shared executor dialog. Creation is operation-only here; skip is not allowed.
|
|
29
|
+
--non-interactive, JSON and non-terminal input never ask and missing choices
|
|
30
|
+
refuse before project effects. Use profiles commands for explicit global saves.
|
|
31
|
+
|
|
32
|
+
The existing managed controller owns Sessions and execution. The default waits
|
|
33
|
+
for completion, recovery or a user/context boundary; --detach returns its
|
|
34
|
+
accepted receipt. Observer disconnection does not stop the controller.
|
|
35
|
+
--prepare-only publishes the normal project bootstrap and frozen RUN, but does
|
|
36
|
+
not launch a controller or provider Session. It is not a dry run and is exclusive
|
|
37
|
+
with --detach. A runner may then use run drive launch with its own context and
|
|
38
|
+
bounded stop/capture policy. Exact preparation replay never stops or replaces
|
|
39
|
+
an existing controller.
|
|
40
|
+
Use existing scoped run drive status / run control commands to observe,
|
|
41
|
+
answer, pause, stop or reconcile the retained RUN. Native/attached public
|
|
42
|
+
selection is not yet exposed; no failed route silently becomes native.`],
|
|
43
|
+
["flow", `dd-flow flow - engine-owned workflow catalog
|
|
44
|
+
|
|
45
|
+
Usage:
|
|
46
|
+
dd-flow flow list --json
|
|
47
|
+
dd-flow flow show <id> --json
|
|
48
|
+
|
|
49
|
+
Inspection never opens a runtime database, initializes a home or runs agents.
|
|
50
|
+
The catalog reports handler registration separately from RUN readiness. A
|
|
51
|
+
pending handler set cannot execute; registered handlers still require selected
|
|
52
|
+
canon, frozen descriptor/schema admission, workspace and execution readiness.
|
|
53
|
+
These inspection commands do not start init or qualify an installed route.`],
|
|
54
|
+
["models", `dd-flow models - reviewed seed and scoped offline observations
|
|
55
|
+
|
|
56
|
+
Usage:
|
|
57
|
+
dd-flow models list --json
|
|
58
|
+
dd-flow models show <model> --harness family --provider provider --json
|
|
59
|
+
dd-flow models list --harness family --provider provider --account-sha256 <digest> --observation-file /absolute/listing.json --json
|
|
60
|
+
|
|
61
|
+
No database, credentials, network, executable discovery or provider process is
|
|
62
|
+
opened. --seed-file selects reviewed seed-only catalog data; otherwise the
|
|
63
|
+
bundled adapter-derived seed is used. Families not yet curated are explicit.
|
|
64
|
+
Unknown seed settings are not profile defaults or model recommendations.
|
|
65
|
+
|
|
66
|
+
Observations require an exact harness/provider/account scope. A matching listed
|
|
67
|
+
model remains unknown for account access and flow qualification. Missing or
|
|
68
|
+
unavailable listing retains seed entries; a foreign scope is ignored. show
|
|
69
|
+
refuses an absent model rather than inventing availability. Exit 2 is invalid
|
|
70
|
+
input; exit 1 is missing/unreadable input or an absent selected model.`],
|
|
71
|
+
["completion", `dd-flow completion - shell completion from the accepted command grammar
|
|
72
|
+
|
|
73
|
+
Usage:
|
|
74
|
+
dd-flow completion bash
|
|
75
|
+
dd-flow completion zsh
|
|
76
|
+
dd-flow completion fish
|
|
77
|
+
|
|
78
|
+
Prints a shell script to stdout; it does not modify shell configuration. Load
|
|
79
|
+
the script in your shell after reviewing it. Zsh requires compinit first.
|
|
80
|
+
Scripts query completion candidates with literal argv; they do not initialize
|
|
81
|
+
a home, open a database, inspect profiles or invoke harness processes.`],
|
|
82
|
+
["harnesses", `dd-flow harnesses - static installation discovery
|
|
83
|
+
|
|
84
|
+
Usage:
|
|
85
|
+
dd-flow harnesses list --json
|
|
86
|
+
dd-flow harnesses show <family> --json
|
|
87
|
+
dd-flow harnesses discover [--harness family --executable /absolute/path] --json
|
|
88
|
+
dd-flow harnesses probe-version --harness family --allow-processes --allow-credentials --allow-writes [--executable /absolute/path --timeout-ms 3000] --json
|
|
89
|
+
dd-flow harnesses doctor --harness family --allow-processes --allow-credentials [--allow-services --allow-writes --executable /absolute/path] --json
|
|
90
|
+
|
|
91
|
+
Lists all six supported families, including missing installations. Multiple
|
|
92
|
+
installations require explicit selection. Presence does not establish version,
|
|
93
|
+
protocol, auth, model access or qualification. list/show/discover never launch a
|
|
94
|
+
process, inspect credentials, create a home or open a runtime database.
|
|
95
|
+
probe-version is an explicit diagnostic exception: it runs installed code only
|
|
96
|
+
after all three effect permissions are supplied. It bounds time/output and does
|
|
97
|
+
not establish protocol compatibility, account access or flow qualification.
|
|
98
|
+
doctor invokes the existing bundled adapter only after its classified effects
|
|
99
|
+
are admitted: Codex/OpenCode/Droid require services and writes; Agy requires
|
|
100
|
+
writes; ZCode/Grok require processes and credentials. ZCode also requires
|
|
101
|
+
--native-executable. OpenCode requires --state-dir for an existing daemon whose
|
|
102
|
+
executable binding matches; doctor never starts or stops that daemon.
|
|
103
|
+
For Droid, the OS ps utility must be available on PATH before doctor starts;
|
|
104
|
+
missing physical-settlement tooling refuses without launching a provider.
|
|
105
|
+
Reports are bounded/redacted observations, not native qualification or account access.
|
|
106
|
+
Use --timeout-ms 1..60000 to bound the diagnostic, not productive work.
|
|
107
|
+
Optional --provider and --account-sha256 must be supplied together. They bind
|
|
108
|
+
reported model names to an operator-declared, unverified scope, not an observed
|
|
109
|
+
credential identity. --model-observation-file explicitly publishes a standalone
|
|
110
|
+
snapshot usable by models list --observation-file. Listings are incomplete;
|
|
111
|
+
an absent adapter list is unavailable, never an empty verified inventory. No
|
|
112
|
+
account access or qualification is inferred; publication failure does not rerun
|
|
113
|
+
the admitted diagnostic. The destination must differ from --response-file.`],
|
|
114
|
+
["setup", `dd-flow setup - global installation readiness
|
|
115
|
+
|
|
116
|
+
Usage:
|
|
117
|
+
dd-flow setup --canon-source /path/to/release-bundle --trust-file operator-trust.json --request-id ID --skip-agent-setup --non-interactive --json
|
|
118
|
+
dd-flow setup update --canon-source /path/to/release-bundle --trust-file operator-trust.json --request-id ID --skip-agent-setup --json
|
|
119
|
+
dd-flow setup status --json
|
|
120
|
+
|
|
121
|
+
The local bundle contains release-envelope.json, canon.tgz and engine.tgz.
|
|
122
|
+
Trust uses dd-flow/release-trust@1 and must be selected independently of the
|
|
123
|
+
envelope. Stable is the default channel; preview/development require --channel.
|
|
124
|
+
Without --skip-agent-setup, select --profile or an existing global default.
|
|
125
|
+
--profile-file supplies a complete validated profile for headless onboarding;
|
|
126
|
+
it is mutually exclusive with --profile and --skip-agent-setup. Profile files
|
|
127
|
+
never import credentials or silently change operator defaults.
|
|
128
|
+
No missing profile is replaced by an automatically selected model.
|
|
129
|
+
In an interactive terminal, a missing profile opens an explicit executor choice
|
|
130
|
+
only after the authenticated installation is committed:
|
|
131
|
+
profile ID/alias, file:/absolute/profile.json, create or skip. create asks for
|
|
132
|
+
every profile field and explicit confirmation, without probing providers.
|
|
133
|
+
Separate yes/no questions authorize saving and global default selection; no
|
|
134
|
+
settings are written by the dialog itself. JSON/JSONL output,
|
|
135
|
+
--non-interactive and non-terminal input never prompt. Cancellation leaves the
|
|
136
|
+
installation committed and onboarding pending; replay the same request to resume
|
|
137
|
+
or explicitly skip onboarding. The separate onboarding receipt freezes the
|
|
138
|
+
selected profile and save/default consent before profile effects. A completed
|
|
139
|
+
onboarding replay never restores later settings. Existing request-bound profile
|
|
140
|
+
choices keep their original identity and recovery semantics.
|
|
141
|
+
--save-profile-intent supplies explicit frozen profile creation/default consent
|
|
142
|
+
for persistence. The selected profile must match; skip conflicts. Setup retains
|
|
143
|
+
the complete intent in its request and uses a profiles_saved checkpoint. A
|
|
144
|
+
committed replay never restores settings changed after the original installation.
|
|
145
|
+
Without a new explicit executor choice, an exact request retry reuses its retained
|
|
146
|
+
executor and save/default consent rather than asking again or choosing a new default.
|
|
147
|
+
Status inspects the selected installation and retained cache without opening or
|
|
148
|
+
migrating SQLite, registering a project, discovering providers or running agents.
|
|
149
|
+
Installation readiness and runtime qualification are separate facts.
|
|
150
|
+
`],
|
|
151
|
+
["profiles", `dd-flow profiles - home-only executor settings
|
|
152
|
+
|
|
153
|
+
Usage:
|
|
154
|
+
dd-flow profiles list --json
|
|
155
|
+
dd-flow profiles show <ID-or-alias> --json
|
|
156
|
+
dd-flow profiles create --file profile.json --expected-revision SHA256 [--set-default] --json
|
|
157
|
+
dd-flow profiles edit --file profile.json --expected-revision SHA256 --json
|
|
158
|
+
dd-flow profiles remove <ID> --expected-revision SHA256 --json
|
|
159
|
+
dd-flow profiles alias <alias> (--target ID | --remove) --expected-revision SHA256 --json
|
|
160
|
+
dd-flow profiles set-default [ID-or-alias | --clear] --expected-revision SHA256 --json
|
|
161
|
+
|
|
162
|
+
Read the current revision with profiles list before changing settings. Writes
|
|
163
|
+
are atomic and reject concurrent/stale changes. Aliases point directly to IDs,
|
|
164
|
+
not other aliases. Profile files use dd-flow/agent-profile@1 and reject secret
|
|
165
|
+
fields. Existing legacy IDs are imported on the first successful write without
|
|
166
|
+
editing their files. Thereafter profile-settings.json is the sole owner.
|
|
167
|
+
Existing RUNs use frozen snapshots, not mutable profile settings. This command
|
|
168
|
+
never registers a project, selects a model automatically or creates a runtime DB.`],
|
|
2
169
|
["runtime scope", `Usage:
|
|
3
170
|
dd-flow runtime scope fence --scope-id EVAL_ID --request-id ID --json
|
|
4
171
|
dd-flow runtime scope status --scope-id EVAL_ID --json
|
|
@@ -197,7 +364,7 @@ Usage:
|
|
|
197
364
|
dd-flow run recovery inspect|begin|seal|capture|resume <RUN-ID|RUN-short-id> --project-root <root> --json
|
|
198
365
|
dd-flow run snapshot create <RUN-ID|RUN-short-id> (--stage-entry <stage>|--candidate|--incomplete|--recovery-id <RCV-ID>) --project-root <root> --output <directory> --json
|
|
199
366
|
dd-flow run snapshot restore --snapshot <directory> --project-root <prepared-root> [--recovery-id <RCV-ID>] --json
|
|
200
|
-
dd-flow run snapshot bootstrap create --project-root <root> --output <directory> --json
|
|
367
|
+
dd-flow run snapshot bootstrap create --project-root <root> --output <directory> [--flow sdlc|mb-init] --json
|
|
201
368
|
dd-flow run snapshot bootstrap restore --snapshot <directory> --project-root <prepared-root> --json
|
|
202
369
|
dd-flow run fork --from <sealed-stage-entry-snapshot> --output <empty-directory> --engine-version <exact-version> --request-id <id> [--integrity-checksum <sha256>] --json
|
|
203
370
|
dd-flow run timeline <RUN-ID|RUN-short-id> --project-root <root> --json
|
|
@@ -559,8 +726,12 @@ Examples:
|
|
|
559
726
|
|
|
560
727
|
Usage:
|
|
561
728
|
dd-flow memory permissions preflight --root <project-root> --memory-bank <path> [--tasks <path>] --flow <flow> --mode <mode> --json
|
|
729
|
+
dd-flow memory finish integrate --run <run-id> --project-root <project-root> --json
|
|
730
|
+
dd-flow memory finish evidence --run <run-id> --project-root <project-root> --json
|
|
562
731
|
|
|
563
|
-
permissions preflight checks project, Memory Bank, and optional .tasks read/write permissions before memory flows mutate files. It never runs privileged repair commands. A completed assessment returns JSON on stdout with exit_code 0 when the flow can continue and exit_code 1 when permission blockers are found. Runtime/configuration mistakes exit 2 as structured errors
|
|
732
|
+
permissions preflight checks project, Memory Bank, and optional .tasks read/write permissions before memory flows mutate files. It never runs privileged repair commands. A completed assessment returns JSON on stdout with exit_code 0 when the flow can continue and exit_code 1 when permission blockers are found. Runtime/configuration mistakes exit 2 as structured errors.
|
|
733
|
+
|
|
734
|
+
finish integrate commits only the accepted Memory Bank and owned lint configuration, then performs the retained local integration route. It preserves unrelated files and never pushes or changes Git identity/configuration. An uncertain original Git effect must be observed, not blindly repeated. finish evidence then publishes actual coverage, integration and ordinary-entry preparation references; neither command accepts the finish result or completes the RUN.`
|
|
564
735
|
],
|
|
565
736
|
[
|
|
566
737
|
"memory permissions",
|
|
@@ -663,10 +834,73 @@ worktree plan suggests a project-scoped service checkout under DD_FLOW_HOME/proj
|
|
|
663
834
|
]
|
|
664
835
|
]);
|
|
665
836
|
export function helpForArgs(args) {
|
|
666
|
-
|
|
667
|
-
|
|
837
|
+
return resolveHelp(args)?.text;
|
|
838
|
+
}
|
|
839
|
+
export function hasHelpIntent(args) {
|
|
840
|
+
const end = args.indexOf("--");
|
|
841
|
+
return args.slice(0, end < 0 ? args.length : end).some(arg => arg === "--help" || arg === "-h");
|
|
842
|
+
}
|
|
843
|
+
/** Pure early resolver: no filesystem, runtime context, process dispatch or output-file access. */
|
|
844
|
+
export function resolveHelp(args) {
|
|
845
|
+
if (!hasHelpIntent(args))
|
|
668
846
|
return undefined;
|
|
847
|
+
const end = args.indexOf("--"), tokens = args.slice(0, end < 0 ? args.length : end);
|
|
848
|
+
const positions = [], selectors = [], supplied = [];
|
|
849
|
+
let json = false;
|
|
850
|
+
const switches = new Set([...globalOptionDocumentation.filter(o => o.kind === "switch").map(o => o.name),
|
|
851
|
+
...Object.values(commandInputs).flatMap(input => input.switches)]);
|
|
852
|
+
for (let index = 0; index < tokens.length; index++) {
|
|
853
|
+
const token = tokens[index];
|
|
854
|
+
if (token === "--help" || token === "-h")
|
|
855
|
+
continue;
|
|
856
|
+
if (token === "--option" || token.startsWith("--option=")) {
|
|
857
|
+
const value = token.startsWith("--option=") ? token.slice(9) : tokens[++index];
|
|
858
|
+
if (!value || value === "--help" || value === "-h")
|
|
859
|
+
throw helpUsage("--option requires one option selector");
|
|
860
|
+
selectors.push(value.replace(/^--/, ""));
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
if (token.startsWith("--")) {
|
|
864
|
+
const name = token.slice(2).split("=", 1)[0];
|
|
865
|
+
supplied.push(name);
|
|
866
|
+
if (token === "--json")
|
|
867
|
+
json = true;
|
|
868
|
+
if (!token.includes("=") && !switches.has(name) && tokens[index + 1] && !tokens[index + 1].startsWith("-"))
|
|
869
|
+
index++;
|
|
870
|
+
}
|
|
871
|
+
else if (token.startsWith("-"))
|
|
872
|
+
throw helpUsage(`Unknown short option: ${token}`);
|
|
873
|
+
else
|
|
874
|
+
positions.push(token);
|
|
669
875
|
}
|
|
670
|
-
|
|
671
|
-
|
|
876
|
+
if (selectors.length > 1)
|
|
877
|
+
throw helpUsage("--option must occur once");
|
|
878
|
+
const selected = commandKeyForPositions(positions);
|
|
879
|
+
const command = selected ?? positions.join(" ");
|
|
880
|
+
const commands = Object.keys(commandInputs).filter(key => !command || key === command || key.startsWith(`${command} `));
|
|
881
|
+
if (command && commands.length === 0)
|
|
882
|
+
throw helpUsage(`Unknown help command: ${command}`);
|
|
883
|
+
const optionMap = new Map(optionsForCommandTree(command).map(option => [option.name, option]));
|
|
884
|
+
// Invalid response transport is intentionally irrelevant to help, including missing/repeated values.
|
|
885
|
+
for (const name of supplied)
|
|
886
|
+
if (!optionMap.has(name))
|
|
887
|
+
throw helpUsage(`Unknown option --${name} for ${command || "root"}`);
|
|
888
|
+
const option = selectors.length ? optionMap.get(selectors[0]) : null;
|
|
889
|
+
if (selectors.length && !option)
|
|
890
|
+
throw helpUsage(`Unknown option selector: ${selectors[0]}`);
|
|
891
|
+
const options = [...optionMap.values()].sort((a, b) => a.name.localeCompare(b.name, "en"));
|
|
892
|
+
const input = selected ? commandInputs[selected] : undefined;
|
|
893
|
+
const canonical = commandAliases[command] ?? command;
|
|
894
|
+
const pageKey = [...helpPages.keys()].filter(key => key && (canonical === key || canonical.startsWith(`${key} `)))
|
|
895
|
+
.sort((a, b) => b.length - a.length)[0] ?? "";
|
|
896
|
+
const detail = (value) => `--${value.name}${value.kind === "value" ? " <value>" : ""}${value.required ? " (required)" : ""}${value.repeatable ? " (repeatable)" : ""}\n ${value.description}${value.choices.length ? `\n Allowed: ${value.choices.join(", ")}` : ""}`;
|
|
897
|
+
const usage = input ? `\nExact command: dd-flow ${command}${input.positions[0] ? ` <argument>${input.positions[0] > 1 ? ` × ${input.positions[0]}` : ""}` : ""}\n` : "";
|
|
898
|
+
return { json,
|
|
899
|
+
text: option ? `dd-flow ${command} --option ${option.name} --help\n\n${detail(option)}`
|
|
900
|
+
: `${helpPages.get(pageKey)}${usage}\n${input?.retired ? `Retired: ${input.retired}\n` : ""}\n${command ? "" : "Command paths:\n"}${input ? "" : commands.map(key => ` ${key}`).join("\n")}\n\nOptions:\n${options.map(detail).join("\n")}`,
|
|
901
|
+
data: { schema_id: "dd-flow/cli-help@1", command, alias_of: commandAliases[command] ?? null, commands, options, option: option ?? null,
|
|
902
|
+
router_native: selected ? routerNativeRoute(selected) : true, retired: input?.retired ?? null } };
|
|
903
|
+
}
|
|
904
|
+
function helpUsage(message) {
|
|
905
|
+
return new AppError("usage", `${message}; use dd-flow --help`, 2, { phase: "help", effect: "no_effect", recoverable: true, help_topic: "dd-flow --help" });
|
|
672
906
|
}
|
|
@@ -32,11 +32,42 @@ export function prepareError(error, input = {}) {
|
|
|
32
32
|
phase: "prepare", effect: "no_effect", recoverable: true, ...input, cause: code ?? String(error)
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
export function prepareTextFile(file, label = "input file") {
|
|
36
|
-
const prepared = prepareFileBytes(file, label);
|
|
37
|
-
|
|
35
|
+
export function prepareTextFile(file, label = "input file", maxBytes) {
|
|
36
|
+
const prepared = prepareFileBytes(file, label, maxBytes);
|
|
37
|
+
if (maxBytes === undefined)
|
|
38
|
+
return { file: prepared.file, text: prepared.bytes.toString("utf8") };
|
|
39
|
+
try {
|
|
40
|
+
return { file: prepared.file, text: new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(prepared.bytes) };
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return prepareError(new AppError("validation", `${label} must contain valid UTF-8`, 2), { file: prepared.file, label });
|
|
44
|
+
}
|
|
38
45
|
}
|
|
39
|
-
export function
|
|
46
|
+
export async function readBoundedUtf8Stream(stream, maxBytes) {
|
|
47
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0)
|
|
48
|
+
throw new AppError("usage", "Invalid input byte bound", 2);
|
|
49
|
+
const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
50
|
+
let data = "", byteLength = 0;
|
|
51
|
+
for await (const chunk of stream) {
|
|
52
|
+
const bytes = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
|
|
53
|
+
byteLength += bytes.length;
|
|
54
|
+
if (byteLength > maxBytes)
|
|
55
|
+
throw new AppError("usage", "Standard input exceeds its byte bound", 2);
|
|
56
|
+
try {
|
|
57
|
+
data += decoder.decode(bytes, { stream: true });
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new AppError("validation", "Standard input must contain valid UTF-8", 2);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
return data + decoder.decode();
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
throw new AppError("validation", "Standard input must contain valid UTF-8", 2);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function prepareFileBytes(file, label = "input file", maxBytes) {
|
|
40
71
|
const absolute = path.resolve(file);
|
|
41
72
|
let descriptor;
|
|
42
73
|
try {
|
|
@@ -45,7 +76,25 @@ export function prepareFileBytes(file, label = "input file") {
|
|
|
45
76
|
if (!stat.isFile()) {
|
|
46
77
|
throw new AppError("input_file_not_regular", `${label} must be a readable regular file: ${absolute}`, 2, { file: absolute, label });
|
|
47
78
|
}
|
|
48
|
-
|
|
79
|
+
if (maxBytes === undefined)
|
|
80
|
+
return { file: absolute, bytes: fs.readFileSync(descriptor) };
|
|
81
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0)
|
|
82
|
+
throw new AppError("usage", "Invalid input byte bound", 2);
|
|
83
|
+
const oversized = () => new AppError("usage", `${label} exceeds its byte bound`, 2);
|
|
84
|
+
if (stat.size > maxBytes)
|
|
85
|
+
throw oversized();
|
|
86
|
+
// Read at most one extra byte: the file can grow after fstat.
|
|
87
|
+
const buffer = Buffer.alloc(maxBytes + 1);
|
|
88
|
+
let length = 0;
|
|
89
|
+
while (length < buffer.length) {
|
|
90
|
+
const count = fs.readSync(descriptor, buffer, length, buffer.length - length, null);
|
|
91
|
+
if (!count)
|
|
92
|
+
break;
|
|
93
|
+
length += count;
|
|
94
|
+
}
|
|
95
|
+
if (length > maxBytes)
|
|
96
|
+
throw oversized();
|
|
97
|
+
return { file: absolute, bytes: buffer.subarray(0, length) };
|
|
49
98
|
}
|
|
50
99
|
catch (error) {
|
|
51
100
|
if (error?.code === "ENOENT") {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { prepareCommandRoute } from "./command-inputs.js";
|
|
2
|
+
import { parseOutputOptions } from "./output-options.js";
|
|
3
|
+
import { readBoundedUtf8Stream, prepareJsonText } from "./input-preparation.js";
|
|
4
|
+
import { PreparedInstalledFlowSource } from "../services/installed-flow-source.js";
|
|
5
|
+
import { hybridDigest } from "../services/hybrid-contracts.js";
|
|
6
|
+
import { AppError, errorRecord } from "../shared/errors.js";
|
|
7
|
+
import { writePreparationError } from "./error-output.js";
|
|
8
|
+
import { memoryInitStartupInputSchemas } from "../services/memory-init-startup-custody.js";
|
|
9
|
+
/** Executing engine's real handler admission only. The caller owns independent
|
|
10
|
+
* release/source selection; this command never opens storage or creates a RUN. */
|
|
11
|
+
export async function runMemoryFlowAdmissionCli(args, io = process) {
|
|
12
|
+
try {
|
|
13
|
+
const output = parseOutputOptions(args), route = prepareCommandRoute(output.args);
|
|
14
|
+
if (route.key !== "runtime flow admit" || output.responseFile || output.progressJsonl) {
|
|
15
|
+
throw new AppError("usage", "Flow admission accepts bounded stdin and stdout output only", 2, { effect: "no_effect" });
|
|
16
|
+
}
|
|
17
|
+
const input = prepareJsonText(await readBoundedUtf8Stream(io.stdin, 64 * 1024 * 1024), { file: "<stdin>", label: "flow admission" }).value;
|
|
18
|
+
if (!input || typeof input !== "object" || Array.isArray(input)
|
|
19
|
+
|| !["source,source_sha256", "source,source_sha256,startup_input_schema"].includes(Object.keys(input).sort().join())) {
|
|
20
|
+
throw new AppError("usage", "Flow admission requires an exact source snapshot and independent digest", 2, { effect: "no_effect" });
|
|
21
|
+
}
|
|
22
|
+
const selected = input;
|
|
23
|
+
const startupSchema = memoryInitStartupInputSchemas.find(schema => schema === selected.startup_input_schema);
|
|
24
|
+
if (Object.hasOwn(selected, "startup_input_schema") && startupSchema === undefined) {
|
|
25
|
+
throw new AppError("usage", "Executing engine does not support the requested startup input schema", 2, { effect: "no_effect" });
|
|
26
|
+
}
|
|
27
|
+
if (typeof selected.source_sha256 !== "string" || !/^[a-f0-9]{64}$/.test(selected.source_sha256)) {
|
|
28
|
+
throw new AppError("usage", "Flow admission requires a SHA-256 source digest", 2, { effect: "no_effect" });
|
|
29
|
+
}
|
|
30
|
+
const source = PreparedInstalledFlowSource.restoreRetained(selected.source, selected.source_sha256);
|
|
31
|
+
const flow = source.resolveRegisteredFlow();
|
|
32
|
+
const facts = { schema_id: startupSchema === undefined ? "dd-flow/memory-init-engine-flow@1" : "dd-flow/memory-init-engine-flow@2",
|
|
33
|
+
...(startupSchema === undefined ? {} : { startup_input_schema: startupSchema }),
|
|
34
|
+
flow_id: "mb-init", source_sha256: source.sha256,
|
|
35
|
+
descriptor_sha256: source.descriptorReference().sha256, stages: flow.descriptor.stages.map(stage => stage.id) };
|
|
36
|
+
io.stdout.write(`${JSON.stringify({ ok: true, action: "runtime_flow_admit", facts, sha256: hybridDigest(facts) }, null, output.json ? undefined : 2)}\n`);
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
const record = errorRecord(error);
|
|
41
|
+
writePreparationError(io, args, record);
|
|
42
|
+
return record.exitCode;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { AppError } from "../shared/errors.js";
|
|
3
|
+
import { hybridDigest } from "../services/hybrid-contracts.js";
|
|
4
|
+
import { prepareCommandRoute } from "./command-inputs.js";
|
|
5
|
+
const stages = new Set(["preflight", "discover", "compose", "verify", "review", "finish"]);
|
|
6
|
+
function refuse(message) {
|
|
7
|
+
throw new AppError("usage", message, 2, { phase: "prepare", effect: "no_effect" });
|
|
8
|
+
}
|
|
9
|
+
/** Pure invocation preparation. File bytes, stored replay and productive
|
|
10
|
+
* authority remain with their existing owners; no ambient defaults here. */
|
|
11
|
+
export function prepareMemoryInitInvocation(args) {
|
|
12
|
+
const route = prepareCommandRoute(args);
|
|
13
|
+
if (!["init", "flow mb-init"].includes(route.key))
|
|
14
|
+
refuse("Use init or flow mb-init");
|
|
15
|
+
const options = route.parsed.options;
|
|
16
|
+
const value = (name) => options.get(name)?.[0];
|
|
17
|
+
const scope = { projectRoot: value("project-root"), workspaceRoot: value("workspace-root"), requestId: value("request-id") };
|
|
18
|
+
if (![scope.projectRoot, scope.workspaceRoot].every(path.isAbsolute)
|
|
19
|
+
|| !/^[A-Za-z0-9][A-Za-z0-9_.-]{0,95}$/.test(scope.requestId))
|
|
20
|
+
refuse("Init needs absolute roots and a bounded request id");
|
|
21
|
+
const execution = {};
|
|
22
|
+
const maxParallel = value("max-parallel");
|
|
23
|
+
const delegation = value("delegation"), nativeConfigHome = value("native-config-home");
|
|
24
|
+
if (maxParallel !== undefined || delegation !== undefined)
|
|
25
|
+
execution.delegation = {
|
|
26
|
+
mode: delegation === "native" ? "native" : "external", max_parallel: Number(maxParallel ?? 1)
|
|
27
|
+
};
|
|
28
|
+
if (delegation === "native" && Number(maxParallel ?? 1) > 15)
|
|
29
|
+
refuse("Native concurrency must be 1..15");
|
|
30
|
+
if (nativeConfigHome !== undefined && (!path.isAbsolute(nativeConfigHome) || delegation !== "native")
|
|
31
|
+
|| options.has("allow-live-probe") && delegation !== "native")
|
|
32
|
+
refuse("Native probe options require explicit native delegation; an optional config home must be absolute");
|
|
33
|
+
const profile = value("profile");
|
|
34
|
+
const profileFile = value("profile-file");
|
|
35
|
+
if (profileFile !== undefined && (!path.isAbsolute(profileFile) || profile !== undefined))
|
|
36
|
+
refuse("--profile-file must be absolute and is exclusive with --profile");
|
|
37
|
+
if (profile !== undefined)
|
|
38
|
+
execution.rootProfile = profile;
|
|
39
|
+
for (const assignment of options.get("stage-profile") ?? []) {
|
|
40
|
+
const at = assignment.indexOf("="), stage = assignment.slice(0, at), profile = assignment.slice(at + 1);
|
|
41
|
+
if (at < 1 || !stages.has(stage) || !profile.trim() || execution.stageProfiles?.[stage] !== undefined)
|
|
42
|
+
refuse("--stage-profile requires a unique stage=profile assignment");
|
|
43
|
+
(execution.stageProfiles ??= {})[stage] = profile;
|
|
44
|
+
}
|
|
45
|
+
if (options.has("work-profile")) {
|
|
46
|
+
execution.workProfiles = [...options.get("work-profile")];
|
|
47
|
+
if (new Set(execution.workProfiles).size !== execution.workProfiles.length)
|
|
48
|
+
refuse("--work-profile must not repeat a profile");
|
|
49
|
+
}
|
|
50
|
+
const intakeFile = value("intake-file"), intakeSha256 = value("intake-sha256");
|
|
51
|
+
if (Boolean(intakeFile) !== Boolean(intakeSha256)
|
|
52
|
+
|| intakeSha256 !== undefined && !/^[a-f0-9]{64}$/.test(intakeSha256)
|
|
53
|
+
|| intakeFile !== undefined && !path.isAbsolute(intakeFile))
|
|
54
|
+
refuse("Original intake needs an absolute --intake-file and --intake-sha256 pair");
|
|
55
|
+
const gitRoute = value("git-route"), integrationBranch = value("integration-branch");
|
|
56
|
+
if (Boolean(gitRoute) !== Boolean(integrationBranch))
|
|
57
|
+
refuse("--git-route and --integration-branch must be supplied together");
|
|
58
|
+
const gitPolicy = gitRoute === undefined ? undefined : {
|
|
59
|
+
route: gitRoute, integrationBranch: integrationBranch
|
|
60
|
+
};
|
|
61
|
+
if (options.has("prepare-only") && options.has("detach"))
|
|
62
|
+
refuse("--prepare-only does not launch a controller and is exclusive with --detach");
|
|
63
|
+
return { scope, execution, gitPolicy, intakeFile, intakeSha256, profileFile, nativeConfigHome, allowLiveProbe: options.has("allow-live-probe"), nonInteractive: options.has("non-interactive"), detach: options.has("detach"), prepareOnly: options.has("prepare-only") };
|
|
64
|
+
}
|
|
65
|
+
/** Omitted selectors replay the retained choices, never current aliases.
|
|
66
|
+
* Supplied selectors must equal the original raw selection, not merely resolve
|
|
67
|
+
* to today's equivalent profile. Intake paths are locators, hashes bind bytes. */
|
|
68
|
+
export function assertMemoryInitInvocationReplay(invocation, original, intakeSha256) {
|
|
69
|
+
if (hybridDigest(invocation.scope) !== hybridDigest(original.scope)
|
|
70
|
+
|| invocation.intakeSha256 !== undefined && invocation.intakeSha256 !== intakeSha256
|
|
71
|
+
|| invocation.gitPolicy !== undefined && hybridDigest(invocation.gitPolicy) !== hybridDigest(original.git_policy)
|
|
72
|
+
|| Object.entries(invocation.execution).some(([key, value]) => !Object.hasOwn(original.execution, key)
|
|
73
|
+
|| hybridDigest(value) !== hybridDigest(key === "delegation" && invocation.execution.delegation?.mode === "native"
|
|
74
|
+
? { mode: original.execution.delegation?.mode, max_parallel: original.execution.delegation?.max_parallel }
|
|
75
|
+
: original.execution[key]))) {
|
|
76
|
+
throw new AppError("memory_init_request_conflict", "Request id belongs to different original init inputs", 1, { effect: "no_effect", next_action: "replay_exact_request_or_choose_new_id" });
|
|
77
|
+
}
|
|
78
|
+
}
|