@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
package/dist/cli/run-cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import { prepareResponseDestination, writeResponseFile } from "./response-file.js";
|
|
2
3
|
import { requiredOption, optionalOption, optionalNumber, optionalPositiveNumber } from "./argument-values.js";
|
|
3
4
|
import { resolveCommandPaths, resolveCommandProjectRoot } from "../services/command-context.js";
|
|
4
5
|
import { assertAuxiliaryCommandScope, cliManagedInvocationScope, manualRecoveryInvocationScope, assertManualRecoveryInvocationTarget } from "../services/lifecycle-invocations.js";
|
|
@@ -12,7 +13,14 @@ import { createContext, createRouterContext } from "../runtime/context.js";
|
|
|
12
13
|
import { dispatchNativeHook, isNativeHookIngress } from "./native-hook-ingress.js";
|
|
13
14
|
import { isRuntimeMaintenance, runtimeMaintenanceDiagnostics, withMaintenanceDiagnosticScope } from "./runtime-maintenance-diagnostics.js";
|
|
14
15
|
import { migrateStoreWriter } from "../storage/writer-migration.js";
|
|
15
|
-
import {
|
|
16
|
+
import { resolveHelp } from "./help.js";
|
|
17
|
+
import { renderHumanError, writePreparationError } from "./error-output.js";
|
|
18
|
+
import { runOperatorProfilesCli } from "./operator-profiles.js";
|
|
19
|
+
import { runSetupCli } from "./setup.js";
|
|
20
|
+
import { runCompletionCli } from "./completion-cli.js";
|
|
21
|
+
import { runHarnessesCli } from "./harnesses.js";
|
|
22
|
+
import { runModelsCli } from "./models.js";
|
|
23
|
+
import { parseOutputOptions } from "./output-options.js";
|
|
16
24
|
import { AppError, errorRecord, isAppError } from "../shared/errors.js";
|
|
17
25
|
import { entityReferenceVariants } from "../shared/entity-references.js";
|
|
18
26
|
import { writeJson, parseJsonObject } from "../shared/json.js";
|
|
@@ -22,7 +30,7 @@ import { getPlanStatus, preparePlanItemMutation, updatePlanItem } from "../servi
|
|
|
22
30
|
import { cancelMergeQueueJob, prepareMergeQueueCancellation, prepareMergeQueueWait, prepareMergeClaim, prepareMergeBundleClaim, claimNextMergeJob, claimMergeJob, claimMergeBundle, completeMergeBundle, prepareMergeBundleCompletion, completeMergeJob, prepareMergeJobCompletion, failMergeBundle, prepareMergeBundleFailure, failMergeJob, prepareMergeJobFailure, getMergeBundleStatus, getMergeQueueStatus, noteMergeJob, prepareMergeJobNote, waitNextMergeJob } from "../services/merge-queue.js";
|
|
23
31
|
import { getMergeWorkerStatus, oneShotMergeClaim, startMergeWorker, stopProjectMergeWorker } from "../services/merge-worker.js";
|
|
24
32
|
import { cleanupApply, cleanupScan, prepareCleanupApply } from "../services/cleanup.js";
|
|
25
|
-
import { getCodexHomeStatus, getCodexHooksStatus, handleCodexHook, handleAgyEvent, handleDroidEvent, handleGrokEvent, handleOpenCodeEvent, handleZcodeHook, handleZcodeEvent, isolatedDdFlowHomeFromHookStdin, claimBootstrapHookEvent, findRecentMatchingHookEvent, stageStartMatchKey, initCodexHome, prepareCodexHome, prepareCodexHooks, installCodexHooks, planCodexHome, printCodexHomeEnv, printCodexHooks, removeCodexHome, prepareCodexHomeRemoval, removeCodexHooks } from "../services/hooks.js";
|
|
33
|
+
import { getCodexHomeStatus, getCodexHooksStatus, handleCodexHook, handleAgyEvent, handleDroidEvent, handleGrokEvent, handleOpenCodeEvent, handleZcodeHook, handleZcodeEvent, isolatedDdFlowHomeFromHookStdin, claimBootstrapHookEvent, findRecentMatchingHookEvent, stageStartMatchKey, stageLifecycleMatchKey, initCodexHome, prepareCodexHome, prepareCodexHooks, installCodexHooks, planCodexHome, printCodexHomeEnv, printCodexHooks, removeCodexHome, prepareCodexHomeRemoval, removeCodexHooks } from "../services/hooks.js";
|
|
26
34
|
import { bootstrapWorktree, closeWorktree, createWorktreeRecord, prepareWorktreeCreate, prepareWorktreeBootstrap, prepareWorktreeClose, getWorktreeStatus, planWorktree } from "../services/worktrees.js";
|
|
27
35
|
import { acquireLaneLock, cancelLaneWaiter, prepareLaneWaiterCancellation, checkLaneWorkspace, getLaneWaiters, getLaneStatus, heartbeatLaneLock, releaseLaneLock, setLaneWorkspace, prepareLaneWorkspace, prepareLaneLock, waitAcquireLaneLock, waitForLaneLock } from "../services/lanes.js";
|
|
28
36
|
import { getProjectConfigStatus, prepareProjectConfigValue, setProjectConfigValue } from "../services/config.js";
|
|
@@ -30,12 +38,12 @@ import { getCanonStatus, registerCanonRoot, resolveCanonRoot, prepareCanonRegist
|
|
|
30
38
|
import { getRuntimeStatus } from "../services/status.js";
|
|
31
39
|
import { getCliVersionReport } from "../services/build-info.js";
|
|
32
40
|
import { parseCommandArgs } from "../services/lifecycle-command.js";
|
|
33
|
-
import { prepareError, prepareJsonFile, prepareJsonSchema, prepareJsonText, prepareTextFile } from "./input-preparation.js";
|
|
41
|
+
import { prepareError, prepareJsonFile, prepareJsonSchema, prepareJsonText, prepareTextFile, prepareFileBytes, readBoundedUtf8Stream } from "./input-preparation.js";
|
|
34
42
|
import { autoRefreshDashboards, dashboardData, getCmuxStatus, openDashboard, openGlobalDashboard, openProtocolDashboard, refreshAllDashboards, prepareDashboardRefresh, prepareDashboardRender, prepareGlobalDashboardRender, prepareDashboardOptions, refreshDashboard, refreshGlobalDashboard, renderDashboard, renderGlobalDashboard } from "../services/dashboard.js";
|
|
35
43
|
import { dashboardTargetSummary, preferredDashboardCommand, relatedDashboardCommands, resolveDashboardTarget } from "../services/dashboard-targets.js";
|
|
36
44
|
import { getFlowSessionStatus, prepareFlowSessionPayload, registerFlowSession, stopFlowSession, stopMergeWorker, syncFlowSessionUsage } from "../services/sessions.js";
|
|
37
45
|
import { getProtocolBranchContext } from "../services/branch-context.js";
|
|
38
|
-
import { attachFlowRunStage, prepareFlowRunStageAttachment,
|
|
46
|
+
import { attachFlowRunStage, readFlowRunExecutionBundle, prepareFlowRunStageAttachment, prepareRawFlowRunStageCompletion, completeFlowRun, prepareFlowRunCompletion, completeFlowRunStage, getFlowRunSessions, getFlowRunTimeline, getStoredFlowRunUsage, getFlowRunFlagsStatus, getFlowRunStatus, getFlowRunConfig, getFlowRunVariables, listFlowRuns, reviseFlowRunFlags, setFlowRunConfig, prepareFlowRunConfig, prepareFlowRunVariable, setFlowRunVariable, startFlowRun, resolveRun, prepareFlowRunStart } from "../services/runs.js";
|
|
39
47
|
import { previewNextEntityId } from "../services/ids.js";
|
|
40
48
|
import { validateSchema } from "../services/schema-validation.js";
|
|
41
49
|
import { preflightMemoryPermissions } from "../services/memory-permissions.js";
|
|
@@ -46,21 +54,34 @@ import { requireProjectByRoot } from "../services/projects.js";
|
|
|
46
54
|
import { resolveProjectRoot, resolveDdFlowHome } from "../storage/paths.js";
|
|
47
55
|
import { doctorEngines, bindRunEngine, prepareRunEngineBind, engineInfo, installCurrentEngine, listEngines, resolveEngine, resolveExplicitProjectRoot, resolveOperationProjectRoot, routeArgsThroughEngine } from "../services/engines.js";
|
|
48
56
|
import { preflightCliCompatibility } from "../services/compatibility-preflight.js";
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
import { dispatchVnextPlanReview,
|
|
53
|
-
import { addVnextCodeRepair,
|
|
54
|
-
import {
|
|
55
|
-
import { applyVnextMerge,
|
|
57
|
+
import { getVnextWorkStatus, isVnextSpecifyFlow, isVnextSpecifyRun, prepareVnextSpecifyStart } from "../services/vnext-specify.js";
|
|
58
|
+
import { isVnextProtocolizeRun, prepareProtocolizeResultPath, prepareVnextProtocolizeStart } from "../services/vnext-protocolize.js";
|
|
59
|
+
import { isVnextPlanRun, prepareVnextPlanStart, prepareVnextPlanFinish } from "../services/vnext-plan.js";
|
|
60
|
+
import { dispatchVnextPlanReview, isVnextPlanReviewRun, prepareVnextPlanReviewStart, recordVnextPlanReviewCapacity } from "../services/vnext-plan-review.js";
|
|
61
|
+
import { addVnextCodeRepair, prepareVnextCodeRepair, prepareVnextCodeStart } from "../services/vnext-code.js";
|
|
62
|
+
import { isVnextCodeReviewRun, prepareCodeReviewDecision, prepareVnextCodeReviewRepair, prepareVnextCodeReviewStart } from "../services/vnext-code-review.js";
|
|
63
|
+
import { applyVnextMerge, getVnextMergeRequest, isVnextMergeRun, prepareVnextMergeFinish, prepareVnextMergeStart, repairVnextMerge, routeVnextMergeRequest } from "../services/vnext-merge.js";
|
|
64
|
+
import { sdlcStageHandlers } from "../services/stage-handlers.js";
|
|
65
|
+
import { startMemoryStage, finishMemoryStage } from "../services/memory-stage-dispatch.js";
|
|
66
|
+
import { bindStageCoordinatorWork } from "../services/work-registry.js";
|
|
67
|
+
import { registerMemoryCompositionFromStage } from "../services/memory-compose-handler.js";
|
|
68
|
+
import { runMemoryVerificationChecks } from "../services/memory-verify-handler.js";
|
|
69
|
+
import { registerMemoryReviewFromStage, collectMemoryInitialReviewFromStage } from "../services/memory-review-handler.js";
|
|
70
|
+
import { PreparedRetainedMemoryReviewAuthority } from "../services/memory-retained-review-authority.js";
|
|
71
|
+
import { PreparedRetainedMemoryReviewResults } from "../services/memory-retained-review-results.js";
|
|
72
|
+
import { registerMemoryCorrectionsFromStage, registerMemorySecondCorrectionsFromStage, runMemoryCorrectionChecksFromStage, runMemorySecondCorrectionChecksFromStage, registerCorrectedMemoryReviewFromStage, registerSecondCorrectedMemoryReviewFromStage, collectCorrectedMemoryReviewFromStage, collectSecondCorrectedMemoryReviewFromStage } from "../services/memory-review-handler.js";
|
|
73
|
+
import { integrateMemoryFinishFromStage, registerMemoryFinishEvidenceFromStage } from "../services/memory-finish-handler.js";
|
|
74
|
+
import { registerMemoryRepairBaselineFromStage, registerMemorySecondRepairBaselineFromStage, reserveMemoryRepairWriterCopyFromStage, reserveMemorySecondRepairCopyFromStage, materializeMemoryRepairWriterCopyFromStage, materializeMemorySecondRepairCopyFromStage, prepareMemoryRepairDispatchFromStage, prepareMemorySecondRepairDispatchFromStage, registerMemoryRepairCurrentViewFromStage, registerMemorySecondRepairCurrentViewFromStage, registerMemoryRepairPublicationSourceFromStage, reserveMemoryRepairPublicationAgainstSourceFromStage, reserveMemorySecondRepairPublicationFromStage, applyMemoryRepairPublicationFromStage, applyMemorySecondRepairPublicationFromStage, finishMemoryRepairPublicationFromStage, finishMemorySecondRepairPublicationFromStage } from "../services/memory-review-handler.js";
|
|
56
75
|
import { mergeServerStatus, serveMergeRequests, stopMergeServer } from "../services/merge-server.js";
|
|
57
|
-
import { getVnextFanoutStatus, observeVnextNativeChildren, prepareNativeObservations, reconcileVnextFanout } from "../services/vnext-fanout.js";
|
|
58
|
-
import { pauseStageForUser, resumeStageAfterUser, prepareStagePause, prepareStageResume } from "../services/stage-pause.js";
|
|
76
|
+
import { getVnextFanoutStatus, memoryStageFanoutDescriptor, observeVnextNativeChildren, prepareNativeObservations, reconcileVnextFanout } from "../services/vnext-fanout.js";
|
|
77
|
+
import { pauseStageForUser, resumeStageAfterUser, prepareStagePause, prepareStageResume, stagePauseCommand } from "../services/stage-pause.js";
|
|
78
|
+
import { runtimeCommand } from "../services/runtime-command.js";
|
|
79
|
+
import { managedLifecycleCommand } from "../services/lifecycle-invocations.js";
|
|
59
80
|
import { blockStageForRuntime, unblockStageAfterRuntimeRepair, prepareStageRuntimeBlock, prepareStageRuntimeUnblock } from "../services/stage-blocker.js";
|
|
60
81
|
import { classifyCliOperation, requiresExplicitUpgradeAuthorization } from "../services/cli-operation-classifier.js";
|
|
61
82
|
import { prepareWorkerPrompt, renderWorkerPrompt } from "../services/prompts.js";
|
|
62
83
|
import { finishStage, prepareStageFinish, startStage, prepareLegacyStageStart } from "../services/stage-lifecycle.js";
|
|
63
|
-
import { addWorkBatch, prepareWorkBatch, prepareWorkDeps, prepareWorkDelete, prepareWorkSettlement, prepareWorkRetry, assertStageLifecycleOwner, assertWorkLifecycleOwner, cancelWork, deleteWork, failWork, finishWork, listWorks, mutateWorkDeps, prepareWorkResult, retryWork, showWork, startWork } from "../services/work-registry.js";
|
|
84
|
+
import { addWorkBatch, prepareWorkBatch, prepareWorkDeps, prepareWorkDelete, prepareWorkSettlement, prepareWorkRetry, assertStageLifecycleOwner, assertWorkLifecycleOwner, cancelWork, deleteWork, failWork, finishWork, listWorks, mutateWorkDeps, prepareWorkResult, workResultByteLimit, retryWork, showWork, startWork } from "../services/work-registry.js";
|
|
64
85
|
import { launchExternalWork } from "../services/external-work-launch.js";
|
|
65
86
|
import { createEvalBootstrapSnapshot, prepareEvalBootstrapSnapshot, createEvalRunSnapshot, prepareEvalRunSnapshotCreation, prepareVnextSpecifyRun, prepareEvalRunRestore, prepareEvalBootstrapRestore, restoreEvalBootstrapSnapshot, restoreEvalRunSnapshot } from "../services/eval-snapshots.js";
|
|
66
87
|
import { forkRunFromSnapshot, prepareRunFork } from "../services/run-fork.js";
|
|
@@ -89,6 +110,21 @@ export async function runCli(args, io = defaultIo, env = process.env) {
|
|
|
89
110
|
return withMaintenanceDiagnosticScope(() => runCliRequest(args, io, env));
|
|
90
111
|
}
|
|
91
112
|
async function runCliRequest(args, io, env) {
|
|
113
|
+
try {
|
|
114
|
+
const help = resolveHelp(args);
|
|
115
|
+
if (help) {
|
|
116
|
+
if (help.json)
|
|
117
|
+
writeJson(io.stdout, help.data);
|
|
118
|
+
else
|
|
119
|
+
io.stdout.write(`${help.text}\n`);
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
const record = errorRecord(error);
|
|
125
|
+
writePreparationError(io, args, record);
|
|
126
|
+
return record.exitCode;
|
|
127
|
+
}
|
|
92
128
|
let output;
|
|
93
129
|
try {
|
|
94
130
|
output = parseOutputOptions(args);
|
|
@@ -114,7 +150,7 @@ async function runCliRequest(args, io, env) {
|
|
|
114
150
|
catch (persistence) {
|
|
115
151
|
rejection.details.lifecycle_diagnostic_error = String(persistence);
|
|
116
152
|
}
|
|
117
|
-
|
|
153
|
+
writePreparationError(io, args, errorRecord(rejection));
|
|
118
154
|
return rejection.exitCode;
|
|
119
155
|
}
|
|
120
156
|
const progress = progressForCommand(output.args);
|
|
@@ -132,11 +168,16 @@ async function runCliRequest(args, io, env) {
|
|
|
132
168
|
io.stdout.write(`dd-flow ${payload.cli.version}\n`);
|
|
133
169
|
return 0;
|
|
134
170
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return
|
|
139
|
-
|
|
171
|
+
if (output.args[0] === "completion")
|
|
172
|
+
return runCompletionCli(args, io);
|
|
173
|
+
if (output.args[0] === "setup")
|
|
174
|
+
return runSetupCli(args, env, io);
|
|
175
|
+
if (output.args[0] === "harnesses")
|
|
176
|
+
return runHarnessesCli(args, env, io);
|
|
177
|
+
if (output.args[0] === "models")
|
|
178
|
+
return runModelsCli(args, io);
|
|
179
|
+
if (output.args[0] === "profiles")
|
|
180
|
+
return runOperatorProfilesCli(args, env, io);
|
|
140
181
|
const suppliedInvocationId = optionalOption(parseArgs(output.args.slice(2)), "invocation-id");
|
|
141
182
|
if (isNativeHookIngress(output.args)) {
|
|
142
183
|
writeJson(io.stdout, await dispatchNativeHook(output.args, await readStdin(io.stdin), env));
|
|
@@ -436,6 +477,8 @@ async function runCliRequest(args, io, env) {
|
|
|
436
477
|
if (invocationSettlement && error.details.effect !== "committed") {
|
|
437
478
|
try {
|
|
438
479
|
if (isAppError(error)) {
|
|
480
|
+
delete error.details.retry_command;
|
|
481
|
+
delete error.details.retry_instruction;
|
|
439
482
|
const settled = errorRecord(error);
|
|
440
483
|
settleLifecycleRejection(invocationSettlement.context, invocationSettlement.id, settled);
|
|
441
484
|
// Serialization owns a copy. Publish the committed settlement, not
|
|
@@ -446,6 +489,8 @@ async function runCliRequest(args, io, env) {
|
|
|
446
489
|
settleLifecycleInvocation(invocationSettlement.context, invocationSettlement.id, { error: { code: "unexpected", message: String(error), exitCode: 1, details: {} } });
|
|
447
490
|
}
|
|
448
491
|
catch (persistenceError) {
|
|
492
|
+
if (isAppError(error))
|
|
493
|
+
error.details.recoverable = false;
|
|
449
494
|
io.stderr.write(`Invocation settlement persistence failed: ${String(persistenceError)}\n`);
|
|
450
495
|
}
|
|
451
496
|
}
|
|
@@ -478,7 +523,7 @@ async function runCliRequest(args, io, env) {
|
|
|
478
523
|
else if (output.json)
|
|
479
524
|
writeJson(io.stderr, visible);
|
|
480
525
|
else
|
|
481
|
-
io.stderr.write(renderHumanError(payload));
|
|
526
|
+
io.stderr.write(renderHumanError(payload, args));
|
|
482
527
|
return isAppError(error) ? error.exitCode : 1;
|
|
483
528
|
}
|
|
484
529
|
finally {
|
|
@@ -540,115 +585,6 @@ function databaseModeForCommand(args, classification) {
|
|
|
540
585
|
return "read_existing";
|
|
541
586
|
return "initialize";
|
|
542
587
|
}
|
|
543
|
-
function renderHumanError(payload) {
|
|
544
|
-
const lines = [`dd-flow: ${payload.error.message}`];
|
|
545
|
-
const details = recordObject(payload.error.details);
|
|
546
|
-
const compatibility = recordObject(details?.compatibility);
|
|
547
|
-
const remediation = recordObject(details?.remediation);
|
|
548
|
-
if (compatibility) {
|
|
549
|
-
lines.push(`Compatibility: ${String(compatibility.verdict ?? "unknown")} (${String(compatibility.engine_resolution ?? "unknown")})`);
|
|
550
|
-
if (compatibility.blocked_operation)
|
|
551
|
-
lines.push(`Blocked operation: ${String(compatibility.blocked_operation)}`);
|
|
552
|
-
if (compatibility.install_hint)
|
|
553
|
-
lines.push(`Install compatible engine: ${String(compatibility.install_hint)}`);
|
|
554
|
-
}
|
|
555
|
-
if (remediation?.mb_upgrade_mode)
|
|
556
|
-
lines.push(`Upgrade mode: ${String(remediation.mb_upgrade_mode)}`);
|
|
557
|
-
if (details?.preferred_command)
|
|
558
|
-
lines.push(`Preferred command: ${String(details.preferred_command)}`);
|
|
559
|
-
const related = Array.isArray(details?.related_commands) ? details.related_commands.map(String) : [];
|
|
560
|
-
if (related.length > 0) {
|
|
561
|
-
lines.push("", "Related commands:");
|
|
562
|
-
for (const command of related)
|
|
563
|
-
lines.push(` ${command}`);
|
|
564
|
-
}
|
|
565
|
-
return `${lines.join("\n")}\n`;
|
|
566
|
-
}
|
|
567
|
-
function parseOutputOptions(args) {
|
|
568
|
-
const stripped = [];
|
|
569
|
-
let json = false;
|
|
570
|
-
let progressJsonl = false;
|
|
571
|
-
let responseFile = null;
|
|
572
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
573
|
-
const arg = args[index];
|
|
574
|
-
if (arg === undefined)
|
|
575
|
-
continue;
|
|
576
|
-
if (arg === "--json") {
|
|
577
|
-
json = true;
|
|
578
|
-
continue;
|
|
579
|
-
}
|
|
580
|
-
if (arg === "--progress-jsonl") {
|
|
581
|
-
progressJsonl = true;
|
|
582
|
-
continue;
|
|
583
|
-
}
|
|
584
|
-
if (arg === "--response-file") {
|
|
585
|
-
if (responseFile !== null)
|
|
586
|
-
throw new AppError("usage", "--response-file may be supplied only once", 2);
|
|
587
|
-
const file = args[++index];
|
|
588
|
-
if (!file?.trim() || file.startsWith("--"))
|
|
589
|
-
throw new AppError("usage", "--response-file requires a path", 2);
|
|
590
|
-
responseFile = file;
|
|
591
|
-
continue;
|
|
592
|
-
}
|
|
593
|
-
stripped.push(arg);
|
|
594
|
-
}
|
|
595
|
-
if (responseFile && !json)
|
|
596
|
-
throw new AppError("usage", "--response-file requires --json", 2);
|
|
597
|
-
const hookJsonOnly = stripped[0] === "codex" && stripped[1] === "hook" && stripped[2] === "handle";
|
|
598
|
-
return { json: json || hookJsonOnly, progressJsonl, args: stripped, hookJsonOnly, responseFile };
|
|
599
|
-
}
|
|
600
|
-
/** Validate the response destination without creating it. The response is an
|
|
601
|
-
* optional publication, but a known-bad destination should never be found
|
|
602
|
-
* only after a successful lifecycle mutation. */
|
|
603
|
-
function prepareResponseDestination(value) {
|
|
604
|
-
const file = path.resolve(value);
|
|
605
|
-
const parent = path.dirname(file);
|
|
606
|
-
try {
|
|
607
|
-
let ancestor = parent;
|
|
608
|
-
for (;;) {
|
|
609
|
-
try {
|
|
610
|
-
if (!fs.statSync(ancestor).isDirectory())
|
|
611
|
-
throw new AppError("response_file_parent_invalid", "--response-file parent must be a directory", 2, { file, parent });
|
|
612
|
-
break;
|
|
613
|
-
}
|
|
614
|
-
catch (error) {
|
|
615
|
-
if (error.code !== "ENOENT" || path.dirname(ancestor) === ancestor)
|
|
616
|
-
throw error;
|
|
617
|
-
ancestor = path.dirname(ancestor);
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
if (fs.existsSync(file) && !fs.statSync(file).isFile())
|
|
621
|
-
throw new AppError("response_file_invalid", "--response-file must name a regular file", 2, { file });
|
|
622
|
-
}
|
|
623
|
-
catch (error) {
|
|
624
|
-
return prepareError(error, { parameter: "response-file", file, parent });
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
/** Persist the complete machine response for harnesses that cap tool output.
|
|
628
|
-
* The visible response keeps routing fields but omits the potentially large
|
|
629
|
-
* rendered prompt; an agent can safely read the named file without rerunning
|
|
630
|
-
* the lifecycle command. */
|
|
631
|
-
function writeResponseFile(payload, output) {
|
|
632
|
-
if (!output.responseFile)
|
|
633
|
-
return payload;
|
|
634
|
-
const file = path.resolve(output.responseFile);
|
|
635
|
-
try {
|
|
636
|
-
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
637
|
-
const temporary = `${file}.tmp-${process.pid}-${crypto.randomUUID()}`;
|
|
638
|
-
fs.writeFileSync(temporary, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
|
639
|
-
fs.renameSync(temporary, file);
|
|
640
|
-
}
|
|
641
|
-
catch (error) {
|
|
642
|
-
// The lifecycle mutation may already be accepted. Do not retry it just
|
|
643
|
-
// because its optional full-response file could not be written.
|
|
644
|
-
return { ...(payload && typeof payload === "object" && !Array.isArray(payload) ? payload : { ok: true, result: payload }), response_file: file, response_file_error: String(error) };
|
|
645
|
-
}
|
|
646
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
647
|
-
return { ok: true, response_file: file };
|
|
648
|
-
const visible = { ...payload, response_file: file };
|
|
649
|
-
delete visible.worker_prompt_markdown;
|
|
650
|
-
return visible;
|
|
651
|
-
}
|
|
652
588
|
function progressForCommand(args) {
|
|
653
589
|
const [family, command, subcommand] = args;
|
|
654
590
|
if (family === "merge-queue" && command === "wait-next") {
|
|
@@ -936,7 +872,7 @@ async function prepareCliInputValue(args, context, io, scopeProjectRoot, respons
|
|
|
936
872
|
if (route.key === "run attach-stage")
|
|
937
873
|
prepareFlowRunStageAttachment(context, stageAttachmentInput(parsed));
|
|
938
874
|
if (route.key === "run complete-stage")
|
|
939
|
-
|
|
875
|
+
prepareRawFlowRunStageCompletion(context, stageCompletionInput(parsed));
|
|
940
876
|
if (route.key === "run override")
|
|
941
877
|
prepareFlowRunCompletion(context, runOverrideInput(parsed));
|
|
942
878
|
if (route.key === "engine bind-run")
|
|
@@ -1053,7 +989,7 @@ async function prepareCliInputValue(args, context, io, scopeProjectRoot, respons
|
|
|
1053
989
|
}
|
|
1054
990
|
if (route.key === "run snapshot bootstrap create") {
|
|
1055
991
|
try {
|
|
1056
|
-
prepareEvalBootstrapSnapshot(context, { projectRoot: requiredOption(parsed, "project-root"), output: requiredOption(parsed, "output") });
|
|
992
|
+
prepareEvalBootstrapSnapshot(context, { projectRoot: requiredOption(parsed, "project-root"), output: requiredOption(parsed, "output"), flow: optionalOption(parsed, "flow") });
|
|
1057
993
|
}
|
|
1058
994
|
catch (error) {
|
|
1059
995
|
return prepareError(error, { parameter: "project-root/output" });
|
|
@@ -1175,7 +1111,9 @@ async function prepareCliInputValue(args, context, io, scopeProjectRoot, respons
|
|
|
1175
1111
|
if (route.key === "work add-batch") {
|
|
1176
1112
|
const file = requiredOption(parsed, "file");
|
|
1177
1113
|
try {
|
|
1178
|
-
prepared.workBatch = prepareWorkBatch(context, { parentWorkId: requiredOption(parsed, "parent"), file
|
|
1114
|
+
prepared.workBatch = prepareWorkBatch(context, { parentWorkId: requiredOption(parsed, "parent"), file,
|
|
1115
|
+
...(optionalOption(parsed, "stage") ? { stage: optionalOption(parsed, "stage") } : {}),
|
|
1116
|
+
...(optionalOption(parsed, "request-key") ? { requestKey: optionalOption(parsed, "request-key") } : {}) });
|
|
1179
1117
|
}
|
|
1180
1118
|
catch (error) {
|
|
1181
1119
|
return prepareError(error, { parameter: "file/parent", file });
|
|
@@ -1264,6 +1202,21 @@ async function prepareCliInputValue(args, context, io, scopeProjectRoot, respons
|
|
|
1264
1202
|
throw new AppError("usage", "stage start requires --context-file together with --context-sha256", 2);
|
|
1265
1203
|
if ([hasOption(parsed, "intake-file"), hasOption(parsed, "intake-stdin"), Boolean(contextFile)].filter(Boolean).length > 1)
|
|
1266
1204
|
throw new AppError("usage", "Use exactly one of --intake-file, --intake-stdin or --context-file", 2);
|
|
1205
|
+
if (!hasOption(parsed, "bootstrap")) {
|
|
1206
|
+
const bundle = readFlowRunExecutionBundle(context, { projectRoot: requiredOption(parsed, "project-root"), runId: requiredPosition(parsed, 0, "run-id") });
|
|
1207
|
+
if (bundle)
|
|
1208
|
+
prepared.stageBindingBundle = { stage, bundle, ...(contextSha256 ? { contextSha256 } : {}) };
|
|
1209
|
+
if (bundle?.descriptor.descriptor.id === "mb-init") {
|
|
1210
|
+
bundle.descriptor.stage(stage);
|
|
1211
|
+
if (hasOption(parsed, "dir"))
|
|
1212
|
+
throw new AppError("usage", "Memory stage layout belongs to its frozen descriptor", 2);
|
|
1213
|
+
const loaded = contextFile && contextSha256 ? loadExternalStageContext({ file: contextFile, expectedSha256: contextSha256, stage }) : undefined;
|
|
1214
|
+
if (loaded)
|
|
1215
|
+
prepared.stageStart = { externalContext: loaded };
|
|
1216
|
+
prepared.memoryStage = { operation: "start", bytes: loaded ? Buffer.from(loaded.bytes) : Buffer.alloc(0) };
|
|
1217
|
+
return prepared;
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1267
1220
|
if (contextFile && contextSha256) {
|
|
1268
1221
|
try {
|
|
1269
1222
|
prepared.stageStart = { externalContext: loadExternalStageContext({ file: contextFile, expectedSha256: contextSha256, stage }) };
|
|
@@ -1354,7 +1307,8 @@ async function prepareCliInputValue(args, context, io, scopeProjectRoot, respons
|
|
|
1354
1307
|
const resultStdin = hasOption(parsed, "result-stdin");
|
|
1355
1308
|
if (Boolean(resultFile) === resultStdin)
|
|
1356
1309
|
throw new AppError("usage", "work finish requires exactly one of --result-file or --result-stdin", 2);
|
|
1357
|
-
|
|
1310
|
+
const maxBytes = workResultByteLimit(context, requiredPosition(parsed, 0, "work-id"));
|
|
1311
|
+
prepared.workFinish = { result: resultFile ? prepareTextFile(resultFile, "Work result", maxBytes).text : await readStdin(io.stdin, maxBytes) };
|
|
1358
1312
|
prepareWorkResult(context, requiredPosition(parsed, 0, "work-id"), prepared.workFinish.result);
|
|
1359
1313
|
}
|
|
1360
1314
|
if (family === "stage" && command === "fanout" && requiredPosition(parsed, 0, "fanout action") === "reconcile") {
|
|
@@ -1363,6 +1317,13 @@ async function prepareCliInputValue(args, context, io, scopeProjectRoot, respons
|
|
|
1363
1317
|
if (family === "stage" && command === "native" && requiredPosition(parsed, 0, "native action") === "observe") {
|
|
1364
1318
|
prepared.observations = prepareNativeObservations(prepareJsonFile(requiredOption(parsed, "observations-file"), "native observations").value);
|
|
1365
1319
|
}
|
|
1320
|
+
if (family === "memory" && (["compose", "corrections"].includes(command ?? "") && parsed.positional[0] === "register"
|
|
1321
|
+
|| command === "repair" && parsed.positional[0] === "publication-reserve")) {
|
|
1322
|
+
const bytes = prepareFileBytes(requiredOption(parsed, "result-file"), `Memory ${command} result`, 1024 * 1024).bytes;
|
|
1323
|
+
if (!bytes.length || bytes.length > 1024 * 1024)
|
|
1324
|
+
throw new AppError("usage", "Memory operation result exceeds its byte bound", 2);
|
|
1325
|
+
prepared.memoryOperationBytes = bytes;
|
|
1326
|
+
}
|
|
1366
1327
|
if (family !== "stage" || command !== "finish")
|
|
1367
1328
|
return prepared;
|
|
1368
1329
|
const projectRoot = requiredOption(parsed, "project-root");
|
|
@@ -1378,6 +1339,21 @@ async function prepareCliInputValue(args, context, io, scopeProjectRoot, respons
|
|
|
1378
1339
|
const semanticFile = optionalOption(parsed, "semantic-file") ?? optionalOption(parsed, "data");
|
|
1379
1340
|
const resultFile = optionalOption(parsed, "result-file") ?? semanticFile;
|
|
1380
1341
|
const runtime = run(projectRoot, runId);
|
|
1342
|
+
if (JSON.parse(runtime.indexJson).execution_bundle?.flow_id === "mb-init") {
|
|
1343
|
+
const bundle = readFlowRunExecutionBundle(context, { projectRoot, runId });
|
|
1344
|
+
if (!bundle || bundle.descriptor.descriptor.id !== "mb-init")
|
|
1345
|
+
throw new AppError("cli_input_unprepared", "Memory RUN bundle is unavailable", 1);
|
|
1346
|
+
bundle.descriptor.stage(stage);
|
|
1347
|
+
if (["dir", "outcome", "decision-file", "verification-file", "retry-check", "reason", "reason-file", "request", "work"].some(option => hasOption(parsed, option)))
|
|
1348
|
+
throw new AppError("usage", "Memory stage finish requires its registered JSON result, not legacy result options", 2);
|
|
1349
|
+
if (Boolean(resultFile) === resultStdin)
|
|
1350
|
+
throw new AppError("usage", "Memory stage finish requires exactly one result input", 2);
|
|
1351
|
+
const bytes = resultStdin ? Buffer.from(await readStdin(io.stdin, 1024 * 1024)) : prepareFileBytes(resultFile, "Memory stage result", 1024 * 1024).bytes;
|
|
1352
|
+
if (!bytes.length || bytes.length > 1024 * 1024)
|
|
1353
|
+
throw new AppError("usage", "Memory stage result exceeds its byte bound", 2);
|
|
1354
|
+
prepared.memoryStage = { operation: "finish", bytes };
|
|
1355
|
+
return prepared;
|
|
1356
|
+
}
|
|
1381
1357
|
const terminalReplay = (name) => {
|
|
1382
1358
|
let index;
|
|
1383
1359
|
try {
|
|
@@ -1649,9 +1625,10 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1649
1625
|
}
|
|
1650
1626
|
if (family === "stage" && command === "fanout") {
|
|
1651
1627
|
const action = requiredPosition(parsed, 0, "fanout action");
|
|
1652
|
-
const runId = requiredPosition(parsed, 1, "run-id");
|
|
1653
1628
|
const stage = requiredOption(parsed, "stage");
|
|
1654
1629
|
const projectRoot = requiredScopeProjectRoot(scopeProjectRoot, "stage fanout");
|
|
1630
|
+
const project = requireProjectByRoot(context, resolveProjectRoot(projectRoot));
|
|
1631
|
+
const runId = resolveRun(context, project.id, requiredPosition(parsed, 1, "run-id")).id;
|
|
1655
1632
|
if (action === "status")
|
|
1656
1633
|
return getVnextFanoutStatus(context, { projectRoot, runId, stage });
|
|
1657
1634
|
if (action === "reconcile")
|
|
@@ -1687,7 +1664,9 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1687
1664
|
});
|
|
1688
1665
|
}
|
|
1689
1666
|
if (family === "work" && command === "add-batch") {
|
|
1690
|
-
return addWorkBatch(context, { parentWorkId: requiredOption(parsed, "parent"), file: requiredOption(parsed, "file"), prepared: prepared.workBatch
|
|
1667
|
+
return addWorkBatch(context, { parentWorkId: requiredOption(parsed, "parent"), file: requiredOption(parsed, "file"), prepared: prepared.workBatch,
|
|
1668
|
+
...(optionalOption(parsed, "stage") ? { stage: optionalOption(parsed, "stage") } : {}),
|
|
1669
|
+
...(optionalOption(parsed, "request-key") ? { requestKey: optionalOption(parsed, "request-key") } : {}) });
|
|
1691
1670
|
}
|
|
1692
1671
|
if (family === "work" && command === "ls") {
|
|
1693
1672
|
return listWorks(context, { ...(optionalOption(parsed, "run") ? { runId: optionalOption(parsed, "run") } : {}), ...(optionalOption(parsed, "parent") ? { parentWorkId: optionalOption(parsed, "parent") } : {}), ...(optionalOption(parsed, "status") ? { status: optionalOption(parsed, "status") } : {}), ...(hasOption(parsed, "ready") ? { ready: true } : {}), ...(hasOption(parsed, "include-results") ? { includeResults: true } : {}), ...(optionalOption(parsed, "limit") ? { limit: Number(optionalOption(parsed, "limit")) } : {}) });
|
|
@@ -1724,7 +1703,8 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1724
1703
|
const retryReceiptId = optionalOption(parsed, "retry-check"), retryReason = prepared.retryReason;
|
|
1725
1704
|
if (Boolean(retryReceiptId) !== Boolean(retryReason))
|
|
1726
1705
|
throw new AppError("usage", "--retry-check and --reason must be supplied together", 2);
|
|
1727
|
-
const
|
|
1706
|
+
const maxBytes = workResultByteLimit(context, workId);
|
|
1707
|
+
const result = prepared.workFinish?.result ?? (resultFile ? prepareTextFile(resultFile, "Work result", maxBytes).text : await readStdin(io.stdin, maxBytes));
|
|
1728
1708
|
return await finishWork(context, workId, result, commandProgress(io, output), retryReceiptId ? { receiptId: retryReceiptId, reason: retryReason } : undefined);
|
|
1729
1709
|
}
|
|
1730
1710
|
if (family === "work" && command === "fail") {
|
|
@@ -1738,6 +1718,8 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1738
1718
|
if (family === "work" && command === "retry")
|
|
1739
1719
|
return retryWork(context, requiredPosition(parsed, 0, "work-id"), requiredOption(parsed, "reason"));
|
|
1740
1720
|
if (family === "stage" && command === "start") {
|
|
1721
|
+
if (prepared.stageBindingBundle)
|
|
1722
|
+
context = { ...context, stageBindingBundle: prepared.stageBindingBundle };
|
|
1741
1723
|
const dir = optionalOption(parsed, "dir");
|
|
1742
1724
|
const bootstrap = hasOption(parsed, "bootstrap");
|
|
1743
1725
|
const subject = optionalOption(parsed, "subject");
|
|
@@ -1755,6 +1737,34 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1755
1737
|
const projectRoot = requiredOption(parsed, "project-root");
|
|
1756
1738
|
const stage = requiredOption(parsed, "stage");
|
|
1757
1739
|
const externalContext = prepared.stageStart?.externalContext;
|
|
1740
|
+
if (prepared.memoryStage?.operation === "start") {
|
|
1741
|
+
const runId = requiredPosition(parsed, 0, "run-id");
|
|
1742
|
+
const event = hookEventId ?? findRecentMatchingHookEvent(context, {
|
|
1743
|
+
projectId: requireProjectByRoot(context, resolveProjectRoot(projectRoot)).id,
|
|
1744
|
+
matchKey: entityReferenceVariants(runId).map(reference => stageStartMatchKey(reference, stage, projectRoot, contextSha256)),
|
|
1745
|
+
errorCode: "trusted_session_binding_required", operation: "Memory stage start"
|
|
1746
|
+
}).eventKey;
|
|
1747
|
+
const work = startMemoryStage(context, { projectRoot, runId, stage, bytes: prepared.memoryStage.bytes });
|
|
1748
|
+
try {
|
|
1749
|
+
const binding = bindStageCoordinatorWork(context, { workId: work.work_id, hookEventId: event, stage,
|
|
1750
|
+
promptPath: work.prompt_path, resultPath: work.result_path, ...(contextSha256 ? { contextSha256 } : {}) });
|
|
1751
|
+
// The frozen semantic prompt is also restored by auxiliary owners in
|
|
1752
|
+
// other CLI contexts. Keep native invocation authority in this current
|
|
1753
|
+
// delivery, not in those immutable instruction/custody bytes.
|
|
1754
|
+
const finish = managedLifecycleCommand(context, runtimeCommand(context, ["stage", "finish", runId,
|
|
1755
|
+
"--stage", stage, "--project-root", projectRoot, "--result-file", work.result_path, "--json"]));
|
|
1756
|
+
const pause = stagePauseCommand(context, { projectRoot, runId, stage, workId: work.work_id });
|
|
1757
|
+
const orchestration = memoryStageFanoutDescriptor(context, { projectRoot, runId, stage });
|
|
1758
|
+
const delivery = { ...work, binding, ...(orchestration ? { orchestration } : {}), next: { finish_command: finish, pause_command: pause },
|
|
1759
|
+
worker_prompt_markdown: `${work.worker_prompt_markdown}\n## Current lifecycle commands\n\nWrite the semantic result to the assigned result path, then execute exactly:\n${finish}\n\nFor a required user choice, write the question file named by this command, then execute exactly:\n${pause}\n` };
|
|
1760
|
+
bindLifecyclePublishedPacket(context, delivery.worker_prompt_markdown);
|
|
1761
|
+
return controlLifecycleReply(context, { projectRoot, runId }, delivery);
|
|
1762
|
+
}
|
|
1763
|
+
catch (error) {
|
|
1764
|
+
throw new AppError("memory_stage_binding_pending", "Memory Stage allocated; trusted coordinator binding remains incomplete", 1, { effect: "committed", run_id: runId, stage, work_id: work.work_id, next_action: "reconcile_memory_stage_binding",
|
|
1765
|
+
cause: error instanceof AppError ? error.code : "coordinator_binding_failure" });
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1758
1768
|
const claimVnextStageStart = (runId) => {
|
|
1759
1769
|
registerProject(context, { root: projectRoot });
|
|
1760
1770
|
return findRecentMatchingHookEvent(context, {
|
|
@@ -1783,7 +1793,7 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1783
1793
|
})
|
|
1784
1794
|
: claimVnextStageStart(requiredPosition(parsed, 0, "run-id"));
|
|
1785
1795
|
}
|
|
1786
|
-
const result =
|
|
1796
|
+
const result = sdlcStageHandlers.specify.entry(context, {
|
|
1787
1797
|
projectRoot,
|
|
1788
1798
|
...(prepared.stageStart?.intakeMarkdown !== undefined ? { intakeMarkdown: prepared.stageStart.intakeMarkdown } : externalContext ? { intakeMarkdown: runnerIntake(externalContext) } : intakeFile ? { intakeFile } : { intakeMarkdown: await readStdin(io.stdin) }),
|
|
1789
1799
|
hookEventId,
|
|
@@ -1795,27 +1805,27 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1795
1805
|
}
|
|
1796
1806
|
if (!bootstrap && stage === "protocolize" && isVnextProtocolizeRun(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id") })) {
|
|
1797
1807
|
hookEventId ??= claimVnextStageStart(requiredPosition(parsed, 0, "run-id"));
|
|
1798
|
-
return attachExternalStageContext(await
|
|
1808
|
+
return attachExternalStageContext(await sdlcStageHandlers.protocolize.entry(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id"), hookEventId, ...(contextSha256 ? { contextSha256 } : {}), ...(externalContext ? { externalContext } : {}) }, prepared.protocolizeStart), externalContext);
|
|
1799
1809
|
}
|
|
1800
1810
|
if (!bootstrap && stage === "plan" && isVnextPlanRun(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id") })) {
|
|
1801
1811
|
hookEventId ??= claimVnextStageStart(requiredPosition(parsed, 0, "run-id"));
|
|
1802
|
-
return attachExternalStageContext(
|
|
1812
|
+
return attachExternalStageContext(sdlcStageHandlers.plan.entry(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id"), hookEventId, ...(contextSha256 ? { contextSha256 } : {}), ...(externalContext ? { externalContext } : {}) }, prepared.planStart), externalContext);
|
|
1803
1813
|
}
|
|
1804
1814
|
if (!bootstrap && stage === "plan-review" && isVnextPlanReviewRun(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id") })) {
|
|
1805
1815
|
hookEventId ??= claimVnextStageStart(requiredPosition(parsed, 0, "run-id"));
|
|
1806
|
-
return attachExternalStageContext(
|
|
1816
|
+
return attachExternalStageContext(sdlcStageHandlers["plan-review"].entry(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id"), hookEventId, ...(contextSha256 ? { contextSha256 } : {}), ...(externalContext ? { externalContext } : {}) }, prepared.planReviewStart), externalContext);
|
|
1807
1817
|
}
|
|
1808
1818
|
if (!bootstrap && stage === "code" && isVnextPlanRun(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id") })) {
|
|
1809
1819
|
hookEventId ??= claimVnextStageStart(requiredPosition(parsed, 0, "run-id"));
|
|
1810
|
-
return attachExternalStageContext(await
|
|
1820
|
+
return attachExternalStageContext(await sdlcStageHandlers.code.entry(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id"), hookEventId, progress: commandProgress(io, output), ...(contextSha256 ? { contextSha256 } : {}), ...(externalContext ? { externalContext } : {}) }, prepared.codeStart), externalContext);
|
|
1811
1821
|
}
|
|
1812
1822
|
if (!bootstrap && stage === "code-review" && isVnextCodeReviewRun(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id") })) {
|
|
1813
1823
|
hookEventId ??= claimVnextStageStart(requiredPosition(parsed, 0, "run-id"));
|
|
1814
|
-
return attachExternalStageContext(
|
|
1824
|
+
return attachExternalStageContext(sdlcStageHandlers["code-review"].entry(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id"), hookEventId, ...(contextSha256 ? { contextSha256 } : {}), ...(externalContext ? { externalContext } : {}) }, prepared.codeReviewStart), externalContext);
|
|
1815
1825
|
}
|
|
1816
1826
|
if (!bootstrap && stage === "merge" && isVnextMergeRun(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id") })) {
|
|
1817
1827
|
hookEventId ??= claimVnextStageStart(requiredPosition(parsed, 0, "run-id"));
|
|
1818
|
-
return attachExternalStageContext(await
|
|
1828
|
+
return attachExternalStageContext(await sdlcStageHandlers.merge.entry(context, { projectRoot, runId: requiredPosition(parsed, 0, "run-id"), hookEventId, progress: commandProgress(io, output), ...(contextSha256 ? { contextSha256 } : {}), ...(externalContext ? { externalContext } : {}) }, prepared.mergeStart), externalContext);
|
|
1819
1829
|
}
|
|
1820
1830
|
if (intakeStdin) {
|
|
1821
1831
|
throw new AppError("usage", "--intake-stdin is only available for vNext SPECIFY", 2);
|
|
@@ -1849,6 +1859,17 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1849
1859
|
const hookEventId = optionalOption(parsed, "hook-event-id");
|
|
1850
1860
|
if (retryCheckId && !retryReason?.trim())
|
|
1851
1861
|
throw new AppError("usage", "--retry-check requires --reason explaining the recovered environment", 2);
|
|
1862
|
+
if (prepared.memoryStage?.operation === "finish") {
|
|
1863
|
+
// Descriptor settlement validates exact coordinator custody and claims
|
|
1864
|
+
// the fresh hook atomically with result acceptance. Do not consume it
|
|
1865
|
+
// through the SDLC lifecycle owner before that settlement.
|
|
1866
|
+
return controlledReply(finishMemoryStage(context, { projectRoot, runId, stage, bytes: prepared.memoryStage.bytes,
|
|
1867
|
+
hookEventId: hookEventId ?? findRecentMatchingHookEvent(context, {
|
|
1868
|
+
projectId: requireProjectByRoot(context, resolveProjectRoot(projectRoot)).id,
|
|
1869
|
+
matchKey: entityReferenceVariants(runId).map(reference => stageLifecycleMatchKey("stage_finish", reference, stage, projectRoot)),
|
|
1870
|
+
errorCode: "trusted_session_binding_required", operation: "Memory stage finish"
|
|
1871
|
+
}).eventKey }));
|
|
1872
|
+
}
|
|
1852
1873
|
const protectedLifecycle = (stage === "specify" && isVnextSpecifyRun(context, { projectRoot, runId }))
|
|
1853
1874
|
|| (stage === "protocolize" && isVnextProtocolizeRun(context, { projectRoot, runId }))
|
|
1854
1875
|
|| (stage === "plan" && isVnextPlanRun(context, { projectRoot, runId }))
|
|
@@ -1868,7 +1889,7 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1868
1889
|
if (!resultFile && !resultStdin) {
|
|
1869
1890
|
throw new AppError("usage", "vNext SPECIFY finish requires --result-file or --result-stdin", 2);
|
|
1870
1891
|
}
|
|
1871
|
-
return controlledReply(await
|
|
1892
|
+
return controlledReply(await sdlcStageHandlers.specify.finish(context, {
|
|
1872
1893
|
projectRoot,
|
|
1873
1894
|
runId,
|
|
1874
1895
|
...(resultFile ? { resultFile } : prepared.stageFinish?.value ? {} : { resultJson: await readStdin(io.stdin) }),
|
|
@@ -1880,34 +1901,34 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
1880
1901
|
if (!resultFile || resultStdin || hasOption(parsed, "outcome")) {
|
|
1881
1902
|
throw new AppError("usage", "vNext PROTOCOLIZE requires exactly --result-file", 2);
|
|
1882
1903
|
}
|
|
1883
|
-
return controlledReply(await
|
|
1904
|
+
return controlledReply(await sdlcStageHandlers.protocolize.finish(context, { projectRoot, runId, resultFile, ...(prepared.stageFinish?.value ? { result: prepared.stageFinish.value } : {}) }));
|
|
1884
1905
|
}
|
|
1885
1906
|
if (stage === "plan" && isVnextPlanRun(context, { projectRoot, runId })) {
|
|
1886
1907
|
if (optionalOption(parsed, "code-work-batch-file"))
|
|
1887
1908
|
throw new AppError("usage", "vNext PLAN derives its CODE batch from accepted semantic plans; do not supply a batch file", 2);
|
|
1888
|
-
return controlledReply(await
|
|
1909
|
+
return controlledReply(await sdlcStageHandlers.plan.finish(context, { projectRoot, runId, ...(prepared.planFinish ? { prepared: prepared.planFinish } : {}) }));
|
|
1889
1910
|
}
|
|
1890
1911
|
if (stage === "plan-review" && isVnextPlanReviewRun(context, { projectRoot, runId })) {
|
|
1891
1912
|
if (resultStdin || hasOption(parsed, "outcome"))
|
|
1892
1913
|
throw new AppError("usage", "vNext PLAN-REVIEW uses --decision-file", 2);
|
|
1893
1914
|
const decisionFile = optionalOption(parsed, "decision-file");
|
|
1894
|
-
return controlledReply(await
|
|
1915
|
+
return controlledReply(await sdlcStageHandlers["plan-review"].finish(context, { projectRoot, runId, ...(decisionFile ? { decisionFile } : {}), ...(prepared.stageFinish?.value ? { decision: prepared.stageFinish.value, decisionText: prepared.stageFinish.text } : {}) }));
|
|
1895
1916
|
}
|
|
1896
1917
|
if (stage === "code" && isVnextPlanRun(context, { projectRoot, runId })) {
|
|
1897
1918
|
if (semanticFile || resultFile || resultStdin || hasOption(parsed, "outcome")) {
|
|
1898
1919
|
throw new AppError("usage", "vNext CODE finish accepts only --verification-file", 2);
|
|
1899
1920
|
}
|
|
1900
|
-
return controlledReply(await
|
|
1921
|
+
return controlledReply(await sdlcStageHandlers.code.finish(context, { projectRoot, runId, verificationFile: optionalOption(parsed, "verification-file") ?? path.join("<missing>", "code-verification.json"), ...(prepared.stageFinish?.value ? { verification: prepared.stageFinish.value } : {}), ...(retryCheckId ? { retryCheckId, retryReason: retryReason } : {}), progress: commandProgress(io, output) }));
|
|
1901
1922
|
}
|
|
1902
1923
|
if (stage === "code-review" && isVnextCodeReviewRun(context, { projectRoot, runId })) {
|
|
1903
1924
|
if (resultStdin || semanticFile || resultFile || hasOption(parsed, "outcome"))
|
|
1904
1925
|
throw new AppError("usage", "vNext CODE-REVIEW uses --decision-file", 2);
|
|
1905
|
-
return controlledReply(await
|
|
1926
|
+
return controlledReply(await sdlcStageHandlers["code-review"].finish(context, { projectRoot, runId, ...(optionalOption(parsed, "decision-file") ? { decisionFile: optionalOption(parsed, "decision-file") } : {}), ...(prepared.stageFinish?.value ? { decision: prepared.stageFinish.value, decisionText: prepared.stageFinish.text } : {}), ...(retryCheckId ? { retryCheckId, retryReason: retryReason } : {}), progress: commandProgress(io, output) }));
|
|
1906
1927
|
}
|
|
1907
1928
|
if (stage === "merge" && isVnextMergeRun(context, { projectRoot, runId })) {
|
|
1908
1929
|
if (resultStdin || semanticFile || resultFile || hasOption(parsed, "outcome"))
|
|
1909
1930
|
throw new AppError("usage", "vNext MERGE uses the Work result path returned by stage start", 2);
|
|
1910
|
-
return controlledReply(await
|
|
1931
|
+
return controlledReply(await sdlcStageHandlers.merge.finish(context, { projectRoot, runId, requestId: requiredOption(parsed, "request"), workId: requiredOption(parsed, "work"), ...(retryCheckId ? { retryCheckId, retryReason: retryReason } : {}), progress: commandProgress(io, output) }, prepared.mergeFinish));
|
|
1911
1932
|
}
|
|
1912
1933
|
if (hasOption(parsed, "outcome") || hasOption(parsed, "result-file") || resultStdin) {
|
|
1913
1934
|
throw new AppError("usage", "--outcome, --result-file and --result-stdin are only available for vNext SPECIFY", 2);
|
|
@@ -2055,7 +2076,7 @@ async function dispatch(args, context, io, scopeProjectRoot = null, classificati
|
|
|
2055
2076
|
return prepared.schemaValidation;
|
|
2056
2077
|
}
|
|
2057
2078
|
if (family === "memory") {
|
|
2058
|
-
return dispatchMemory(command, parsed);
|
|
2079
|
+
return dispatchMemory(context, command, parsed, prepared);
|
|
2059
2080
|
}
|
|
2060
2081
|
if (family === "migration") {
|
|
2061
2082
|
return dispatchMigration(context, command, parsed, classification, prepared);
|
|
@@ -2368,7 +2389,7 @@ function dispatchMergeWorker(context, command, parsed) {
|
|
|
2368
2389
|
}
|
|
2369
2390
|
throw new AppError("usage", `Unknown merge-worker command: ${command ?? "<empty>"}`, 2);
|
|
2370
2391
|
}
|
|
2371
|
-
function dispatchMemory(command, parsed) {
|
|
2392
|
+
function dispatchMemory(context, command, parsed, prepared) {
|
|
2372
2393
|
const subcommand = requiredPosition(parsed, 0, "memory subcommand");
|
|
2373
2394
|
if (command === "permissions" && subcommand === "preflight") {
|
|
2374
2395
|
return preflightMemoryPermissions({
|
|
@@ -2379,6 +2400,103 @@ function dispatchMemory(command, parsed) {
|
|
|
2379
2400
|
mode: requiredOption(parsed, "mode")
|
|
2380
2401
|
});
|
|
2381
2402
|
}
|
|
2403
|
+
const scope = () => {
|
|
2404
|
+
const projectRoot = requiredOption(parsed, "project-root");
|
|
2405
|
+
const project = requireProjectByRoot(context, resolveProjectRoot(projectRoot));
|
|
2406
|
+
return { projectRoot, runId: resolveRun(context, project.id, requiredOption(parsed, "run")).id };
|
|
2407
|
+
};
|
|
2408
|
+
if (command === "repair") {
|
|
2409
|
+
const wave = requiredOption(parsed, "wave");
|
|
2410
|
+
if (wave !== "1" && wave !== "2")
|
|
2411
|
+
throw new AppError("usage", "Memory repairs support only waves 1 and 2", 2);
|
|
2412
|
+
const work = { ...scope(), workId: requiredOption(parsed, "work") };
|
|
2413
|
+
if (subcommand === "baseline")
|
|
2414
|
+
return (wave === "1" ? registerMemoryRepairBaselineFromStage : registerMemorySecondRepairBaselineFromStage)(context, work);
|
|
2415
|
+
if (subcommand === "copy-reserve")
|
|
2416
|
+
return (wave === "1" ? reserveMemoryRepairWriterCopyFromStage : reserveMemorySecondRepairCopyFromStage)(context, work);
|
|
2417
|
+
if (subcommand === "copy-materialize")
|
|
2418
|
+
return (wave === "1" ? materializeMemoryRepairWriterCopyFromStage : materializeMemorySecondRepairCopyFromStage)(context, work);
|
|
2419
|
+
if (subcommand === "copy-dispatch")
|
|
2420
|
+
return (wave === "1" ? prepareMemoryRepairDispatchFromStage : prepareMemorySecondRepairDispatchFromStage)(context, work);
|
|
2421
|
+
const workspaceRoot = requiredOption(parsed, "workspace-root");
|
|
2422
|
+
if (wave === "2") {
|
|
2423
|
+
const bundle = readFlowRunExecutionBundle(context, work);
|
|
2424
|
+
if (!bundle || bundle.descriptor.descriptor.id !== "mb-init" || bundle.execution.snapshot().scope.workspace !== workspaceRoot)
|
|
2425
|
+
throw new AppError("memory_repair_scope_invalid", "Repair workspace does not match its frozen memory RUN", 2, { phase: "prepare", effect: "no_effect" });
|
|
2426
|
+
}
|
|
2427
|
+
if (subcommand === "current-view")
|
|
2428
|
+
return wave === "1"
|
|
2429
|
+
? registerMemoryRepairCurrentViewFromStage(context, { ...work, workspaceRoot })
|
|
2430
|
+
: registerMemorySecondRepairCurrentViewFromStage(context, work);
|
|
2431
|
+
const output = { ...work, workspaceRoot, workSessionId: requiredOption(parsed, "work-session") };
|
|
2432
|
+
if (subcommand === "publication-source" && wave === "1")
|
|
2433
|
+
return registerMemoryRepairPublicationSourceFromStage(context, output);
|
|
2434
|
+
if (subcommand === "publication-reserve") {
|
|
2435
|
+
if (!prepared.memoryOperationBytes)
|
|
2436
|
+
throw new AppError("cli_input_unprepared", "Memory repair output bytes were not prepared", 1);
|
|
2437
|
+
return (wave === "1" ? reserveMemoryRepairPublicationAgainstSourceFromStage : reserveMemorySecondRepairPublicationFromStage)(context, { ...output, bytes: prepared.memoryOperationBytes });
|
|
2438
|
+
}
|
|
2439
|
+
if (subcommand === "publication-apply")
|
|
2440
|
+
return (wave === "1" ? applyMemoryRepairPublicationFromStage : applyMemorySecondRepairPublicationFromStage)(context, output);
|
|
2441
|
+
if (subcommand === "publication-finish")
|
|
2442
|
+
return (wave === "1" ? finishMemoryRepairPublicationFromStage : finishMemorySecondRepairPublicationFromStage)(context, output);
|
|
2443
|
+
}
|
|
2444
|
+
if (command === "compose" && subcommand === "register") {
|
|
2445
|
+
if (!prepared.memoryOperationBytes)
|
|
2446
|
+
throw new AppError("cli_input_unprepared", "Memory composition bytes were not prepared", 1);
|
|
2447
|
+
try {
|
|
2448
|
+
return registerMemoryCompositionFromStage(context, { ...scope(), requestKey: requiredOption(parsed, "request-key"), bytes: prepared.memoryOperationBytes });
|
|
2449
|
+
}
|
|
2450
|
+
catch (error) {
|
|
2451
|
+
if (error instanceof AppError && (error.code === "memory_stage_result_invalid"
|
|
2452
|
+
|| error.code === "memory_preflight_handler_invalid" && ["unselected_preflight_source", "proposed_source_sha256_mismatch"].includes(String(error.details.reason))) && error.details.phase === "prepare"
|
|
2453
|
+
&& error.details.effect === "no_effect" && error.details.recoverable === true) {
|
|
2454
|
+
error.details.retry_command = runtimeCommand(context, ["memory", "compose", "register", "--run", requiredOption(parsed, "run"),
|
|
2455
|
+
"--project-root", requiredOption(parsed, "project-root"), "--request-key", requiredOption(parsed, "request-key"),
|
|
2456
|
+
"--result-file", requiredOption(parsed, "result-file"), "--json", "--progress-jsonl"]);
|
|
2457
|
+
error.details.retry_instruction = "Correct only the rejected composition proposal, then execute retry_command in this same Session. No Work graph was registered by this rejected call; do not dispatch children or finish the Stage until registration succeeds.";
|
|
2458
|
+
}
|
|
2459
|
+
throw error;
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
if (command === "verify" && subcommand === "checks")
|
|
2463
|
+
return runMemoryVerificationChecks(context, scope());
|
|
2464
|
+
if (command === "review" && subcommand === "register")
|
|
2465
|
+
return registerMemoryReviewFromStage(context, scope());
|
|
2466
|
+
if (command === "review" && subcommand === "collect") {
|
|
2467
|
+
const wave = collectMemoryInitialReviewFromStage(context, scope());
|
|
2468
|
+
const selected = scope(), bundle = readFlowRunExecutionBundle(context, selected);
|
|
2469
|
+
if (!bundle)
|
|
2470
|
+
throw new AppError("memory_review_handler_invalid", "Registered Memory bundle required", 2);
|
|
2471
|
+
const project = requireProjectByRoot(context, resolveProjectRoot(selected.projectRoot));
|
|
2472
|
+
const retained = PreparedRetainedMemoryReviewResults.prepare(context, PreparedRetainedMemoryReviewAuthority.prepare(context, { projectId: project.id, runId: selected.runId }, bundle));
|
|
2473
|
+
return { references: wave.references(), projection: wave.resultProjection(),
|
|
2474
|
+
correction_plan_binding: { schema_id: "dd-flow/memory-review-correction-plan@1", run_id: selected.runId, wave: 1, review_sha256: retained.sha256 } };
|
|
2475
|
+
}
|
|
2476
|
+
if (command === "finish" && subcommand === "evidence")
|
|
2477
|
+
return registerMemoryFinishEvidenceFromStage(context, scope());
|
|
2478
|
+
if (command === "finish" && subcommand === "integrate")
|
|
2479
|
+
return integrateMemoryFinishFromStage(context, scope());
|
|
2480
|
+
if (command === "corrections" || command === "review" && ["selective-register", "selective-collect"].includes(subcommand)) {
|
|
2481
|
+
const wave = requiredOption(parsed, "wave");
|
|
2482
|
+
if (wave !== "1" && wave !== "2")
|
|
2483
|
+
throw new AppError("usage", "Memory corrections support only waves 1 and 2", 2);
|
|
2484
|
+
if (command === "corrections" && subcommand === "register") {
|
|
2485
|
+
if (!prepared.memoryOperationBytes)
|
|
2486
|
+
throw new AppError("cli_input_unprepared", "Memory correction plan bytes were not prepared", 1);
|
|
2487
|
+
const register = wave === "1" ? registerMemoryCorrectionsFromStage : registerMemorySecondCorrectionsFromStage;
|
|
2488
|
+
return register(context, { ...scope(), bytes: prepared.memoryOperationBytes });
|
|
2489
|
+
}
|
|
2490
|
+
if (command === "corrections" && subcommand === "checks")
|
|
2491
|
+
return (wave === "1" ? runMemoryCorrectionChecksFromStage : runMemorySecondCorrectionChecksFromStage)(context, scope());
|
|
2492
|
+
if (command === "review" && subcommand === "selective-register")
|
|
2493
|
+
return (wave === "1" ? registerCorrectedMemoryReviewFromStage : registerSecondCorrectedMemoryReviewFromStage)(context, scope());
|
|
2494
|
+
if (command === "review" && subcommand === "selective-collect") {
|
|
2495
|
+
const accepted = (wave === "1" ? collectCorrectedMemoryReviewFromStage : collectSecondCorrectedMemoryReviewFromStage)(context, scope());
|
|
2496
|
+
return { wave: Number(wave), references: accepted.references(), projection: accepted.resultProjection(),
|
|
2497
|
+
...(wave === "1" ? { correction_plan_binding: { schema_id: "dd-flow/memory-review-correction-plan@1", run_id: scope().runId, wave: 2, review_sha256: accepted.sha256 } } : {}) };
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2382
2500
|
throw new AppError("usage", `Unknown memory command: ${["memory", command, subcommand].filter(Boolean).join(" ")}`, 2);
|
|
2383
2501
|
}
|
|
2384
2502
|
function completedCommandExitCode(payload) {
|
|
@@ -2504,7 +2622,8 @@ function dispatchRun(context, command, parsed, prepared = {}) {
|
|
|
2504
2622
|
if (bootstrapAction === "create")
|
|
2505
2623
|
return createEvalBootstrapSnapshot(context, {
|
|
2506
2624
|
projectRoot: requiredOption(parsed, "project-root"),
|
|
2507
|
-
output: requiredOption(parsed, "output")
|
|
2625
|
+
output: requiredOption(parsed, "output"),
|
|
2626
|
+
flow: optionalOption(parsed, "flow")
|
|
2508
2627
|
});
|
|
2509
2628
|
if (bootstrapAction === "restore")
|
|
2510
2629
|
return restoreEvalBootstrapSnapshot(context, snapshotRestoreInput(parsed), prepared.bootstrapRestore);
|
|
@@ -2600,7 +2719,8 @@ function dispatchRun(context, command, parsed, prepared = {}) {
|
|
|
2600
2719
|
return attachFlowRunStage(context, stageAttachmentInput(parsed));
|
|
2601
2720
|
}
|
|
2602
2721
|
if (command === "complete-stage") {
|
|
2603
|
-
|
|
2722
|
+
const input = stageCompletionInput(parsed);
|
|
2723
|
+
return completeFlowRunStage(context, input, prepareRawFlowRunStageCompletion(context, input));
|
|
2604
2724
|
}
|
|
2605
2725
|
if (command === "complete") {
|
|
2606
2726
|
throw new AppError("usage", "run complete is retired; only an operator may use run override", 2);
|
|
@@ -3184,7 +3304,7 @@ function parseArgs(args) {
|
|
|
3184
3304
|
function requiredPosition(parsed, index, label) {
|
|
3185
3305
|
const value = parsed.positional[index];
|
|
3186
3306
|
if (!value) {
|
|
3187
|
-
throw new AppError("usage", `Missing required argument: ${label}`, 2);
|
|
3307
|
+
throw new AppError("usage", `Missing required argument: ${label}`, 2, { parameter: label, reason: "missing_required_argument" });
|
|
3188
3308
|
}
|
|
3189
3309
|
return value;
|
|
3190
3310
|
}
|
|
@@ -3194,7 +3314,7 @@ function allOptions(parsed, key) {
|
|
|
3194
3314
|
function requiredScopeProjectRoot(root, operation) {
|
|
3195
3315
|
if (root)
|
|
3196
3316
|
return root;
|
|
3197
|
-
throw new AppError("usage", `${operation} requires --project-root or a unique protocol context`, 2);
|
|
3317
|
+
throw new AppError("usage", `${operation} requires --project-root or a unique protocol context`, 2, { parameter: "project-root", reason: "missing_required_option" });
|
|
3198
3318
|
}
|
|
3199
3319
|
function requiredOptionOrScope(parsed, root, key) {
|
|
3200
3320
|
return root ?? requiredOption(parsed, key);
|
|
@@ -3213,7 +3333,7 @@ function requiredOptionAlias(parsed, keys) {
|
|
|
3213
3333
|
if (value)
|
|
3214
3334
|
return value;
|
|
3215
3335
|
}
|
|
3216
|
-
throw new AppError("usage", `Missing required option: ${keys.map((key) => `--${key}`).join(" or ")}`, 2);
|
|
3336
|
+
throw new AppError("usage", `Missing required option: ${keys.map((key) => `--${key}`).join(" or ")}`, 2, { parameter: [...keys].sort(), reason: "missing_required_option" });
|
|
3217
3337
|
}
|
|
3218
3338
|
function hasOption(parsed, key) {
|
|
3219
3339
|
return parsed.options.has(key);
|
|
@@ -3243,11 +3363,13 @@ function parseWorktreePolicy(value) {
|
|
|
3243
3363
|
}
|
|
3244
3364
|
throw new AppError("validation", "--worktree must be keep or remove", 2);
|
|
3245
3365
|
}
|
|
3246
|
-
async function readStdin(stream) {
|
|
3366
|
+
async function readStdin(stream, maxBytes) {
|
|
3247
3367
|
if (!stream) {
|
|
3248
3368
|
return "";
|
|
3249
3369
|
}
|
|
3250
3370
|
let data = "";
|
|
3371
|
+
if (maxBytes !== undefined)
|
|
3372
|
+
return readBoundedUtf8Stream(stream, maxBytes);
|
|
3251
3373
|
stream.setEncoding("utf8");
|
|
3252
3374
|
for await (const chunk of stream) {
|
|
3253
3375
|
data += chunk;
|
|
@@ -3263,7 +3385,8 @@ function refreshDashboardsAfterMutation(context, args, result, resolvedScope) {
|
|
|
3263
3385
|
const projectRoot = projectRootForMutation(context, args, result, resolvedScope);
|
|
3264
3386
|
if (!projectRoot)
|
|
3265
3387
|
return [];
|
|
3266
|
-
|
|
3388
|
+
const runId = result && typeof result === "object" && "run_id" in result && typeof result.run_id === "string" ? result.run_id : undefined;
|
|
3389
|
+
autoRefreshDashboards(context, { projectRoot, ...(runId ? { runId } : {}) });
|
|
3267
3390
|
return [];
|
|
3268
3391
|
}
|
|
3269
3392
|
catch (error) {
|