@deksden-com/dd-flow-cli 0.9.0-beta.144 → 0.9.0-beta.145
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 +59 -0
- package/README.md +13 -8
- package/dist/build-info.json +7 -7
- package/dist/cli/command-inputs.js +9 -3
- package/dist/cli/command-metadata.js +33 -14
- package/dist/cli/help.js +32 -1
- package/dist/cli/hook-ingress.js +27 -3
- package/dist/cli/memory-flow-admission.js +7 -3
- package/dist/cli/memory-init-invocation.js +10 -3
- package/dist/cli/memory-init.js +74 -68
- package/dist/cli/memory-storage-admission.js +3 -2
- package/dist/cli/memory-storage-qualification.js +105 -0
- package/dist/cli/memory-storage-transition.js +123 -0
- package/dist/cli/memory-upgrade.js +189 -0
- package/dist/cli/native-hook-ingress.js +14 -4
- package/dist/cli/native-hook-preparation.js +55 -0
- package/dist/cli/response-file.js +2 -1
- package/dist/cli/run-cli.js +70 -32
- package/dist/cli/setup.js +2 -1
- package/dist/cli.js +12 -0
- package/dist/domain/stage-handler-identities.js +8 -0
- package/dist/harness-runtime/bin/dd-agy.mjs +3 -3
- package/dist/harness-runtime/bin/dd-grok.mjs +3 -3
- package/dist/harness-runtime/bin/dd-zcode.mjs +5 -5
- package/dist/harness-runtime/lib/agy-error-boundary.mjs +58 -0
- package/dist/harness-runtime/lib/dd-agy-daemon.mjs +62 -20
- package/dist/harness-runtime/lib/dd-agy.mjs +17 -3
- package/dist/harness-runtime/lib/dd-droid.mjs +1 -1
- package/dist/harness-runtime/lib/dd-grok-daemon.mjs +70 -13
- package/dist/harness-runtime/lib/dd-grok.mjs +6 -3
- package/dist/harness-runtime/lib/dd-zcode.mjs +44 -14
- package/dist/harness-runtime/lib/delegation-instructions.mjs +1 -1
- package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
- package/dist/harness-runtime/lib/entity-references.mjs +9 -0
- package/dist/harness-runtime/lib/managed-daemon.mjs +13 -6
- package/dist/harness-runtime/lib/native-hook-command.mjs +4 -4
- package/dist/harness-runtime/lib/opencode-plugin.mjs +3 -3
- package/dist/harness-runtime/lib/operation-errors.mjs +1 -1
- package/dist/harness-runtime/lib/provider-overload-policy.d.mts +4 -2
- package/dist/harness-runtime/lib/provider-overload-policy.mjs +19 -6
- package/dist/harness-runtime/lib/runner-events.mjs +3 -1
- package/dist/harness-runtime/lib/setup-progress.mjs +8 -6
- package/dist/schemas/mb-upgrade-stage-result.schema.json +863 -0
- package/dist/schemas/memory-repair-work-result.schema.json +9 -2
- package/dist/schemas/release-impact.schema.json +3 -3
- package/dist/schemas/stage-start-response.schema.json +4 -0
- package/dist/services/accepted-intent.js +13 -1
- package/dist/services/canon.js +43 -7
- package/dist/services/cli-operation-classifier.js +1 -1
- package/dist/services/cli-upgrade-allowlist.js +1 -1
- package/dist/services/code-checks.js +11 -4
- package/dist/services/compatibility-preflight.js +5 -2
- package/dist/services/controller-fanout.js +21 -4
- package/dist/services/controller-memory-task.js +45 -0
- package/dist/services/controller-memory-worker.js +48 -0
- package/dist/services/dashboard.js +2 -2
- package/dist/services/descriptor-run-start.js +26 -19
- package/dist/services/descriptor-stage-coordinator.js +30 -10
- package/dist/services/descriptor-stage-start.js +40 -4
- package/dist/services/engines.js +64 -14
- package/dist/services/eval-snapshots.js +104 -93
- package/dist/services/external-work-launch.js +5 -3
- package/dist/services/flow-catalog.js +8 -4
- package/dist/services/frozen-engine.js +113 -11
- package/dist/services/hook-memory-routing.js +188 -0
- package/dist/services/hook-recovery-guard.js +14 -0
- package/dist/services/hook-session-observation.js +24 -0
- package/dist/services/hooks.js +27 -8
- package/dist/services/hybrid-contracts.js +2 -13
- package/dist/services/hybrid-digest.js +14 -0
- package/dist/services/installed-flow-source.js +25 -4
- package/dist/services/lifecycle-invocations.js +33 -5
- package/dist/services/memory-accepted-composition.js +5 -4
- package/dist/services/memory-completed-correction-wave.js +23 -15
- package/dist/services/memory-compose-handler.js +163 -21
- package/dist/services/memory-composition-acceptance.js +186 -10
- package/dist/services/memory-composition-graph.js +42 -11
- package/dist/services/memory-composition-registration.js +23 -8
- package/dist/services/memory-composition-work-custody.js +14 -9
- package/dist/services/memory-composition-work-results.js +15 -3
- package/dist/services/memory-corrected-review-batch.js +10 -3
- package/dist/services/memory-corrected-review-findings.js +4 -2
- package/dist/services/memory-corrected-review-inputs.js +10 -5
- package/dist/services/memory-corrected-review-receipt.js +17 -9
- package/dist/services/memory-corrected-review-registration.js +3 -2
- package/dist/services/memory-correction-check-receipt.js +20 -4
- package/dist/services/memory-custody-snapshot.js +36 -0
- package/dist/services/memory-finish-evidence.js +44 -22
- package/dist/services/memory-finish-handler.js +37 -23
- package/dist/services/memory-finish-integration.js +218 -48
- package/dist/services/memory-finish-readiness.js +66 -19
- package/dist/services/memory-git-integration.js +87 -18
- package/dist/services/memory-historical-corrected-review.js +21 -15
- package/dist/services/memory-historical-original-review.js +22 -9
- package/dist/services/memory-historical-repair-registration.js +14 -8
- package/dist/services/memory-historical-second-review.js +30 -11
- package/dist/services/memory-init-contexts.js +28 -2
- package/dist/services/memory-init-controller-start.js +19 -8
- package/dist/services/memory-init-git-policy.js +50 -21
- package/dist/services/memory-init-lint-capability.js +21 -3
- package/dist/services/memory-init-native-capacity.js +13 -0
- package/dist/services/memory-init-preflight.js +11 -1
- package/dist/services/memory-init-request-candidate.js +73 -17
- package/dist/services/memory-init-request-input.js +23 -7
- package/dist/services/memory-init-run-bundle.js +49 -12
- package/dist/services/memory-init-storage.js +17 -7
- package/dist/services/memory-layer.js +68 -4
- package/dist/services/memory-lint-config.js +111 -2
- package/dist/services/memory-native-review-copy.js +5 -67
- package/dist/services/memory-normal-flow-entry.js +12 -0
- package/dist/services/memory-ordinary-defaults.js +22 -5
- package/dist/services/memory-preflight-handler.js +15 -0
- package/dist/services/memory-repair-current-view.js +1 -1
- package/dist/services/memory-repair-document-delta.js +70 -33
- package/dist/services/memory-repair-history.js +12 -7
- package/dist/services/memory-repair-physical-binding.js +1 -119
- package/dist/services/memory-repair-publication-plan.js +5 -3
- package/dist/services/memory-repair-publication-source.js +1 -1
- package/dist/services/memory-repair-publication.js +3 -2
- package/dist/services/memory-repair-registration.js +2 -1
- package/dist/services/memory-repair-work-baseline.js +4 -2
- package/dist/services/memory-repair-work-completion.js +32 -12
- package/dist/services/memory-repair-work-results.js +21 -2
- package/dist/services/memory-repair-workspace.js +11 -2
- package/dist/services/memory-repair-writer-copy.js +2 -1
- package/dist/services/memory-result-binding.js +78 -12
- package/dist/services/memory-retained-review-authority.js +17 -8
- package/dist/services/memory-retained-second-baseline.js +1 -1
- package/dist/services/memory-retained-second-repairs.js +12 -6
- package/dist/services/memory-review-correction-plan.js +47 -12
- package/dist/services/memory-review-handler.js +17 -17
- package/dist/services/memory-review-inputs.js +55 -9
- package/dist/services/memory-review-limits.js +10 -0
- package/dist/services/memory-review-receipt.js +2 -2
- package/dist/services/memory-review-registration.js +13 -4
- package/dist/services/memory-review-work-custody.js +3 -1
- package/dist/services/memory-review-work-input.js +26 -7
- package/dist/services/memory-review-work-results.js +26 -4
- package/dist/services/memory-second-corrected-review-inputs.js +5 -3
- package/dist/services/memory-second-correction-plan.js +2 -1
- package/dist/services/memory-second-repair-launch.js +4 -4
- package/dist/services/memory-second-repair-source.js +1 -1
- package/dist/services/memory-stage-dispatch.js +38 -1
- package/dist/services/memory-stage-results.js +113 -22
- package/dist/services/memory-upgrade-analysis-handler.js +243 -0
- package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
- package/dist/services/memory-upgrade-evidence.js +100 -0
- package/dist/services/memory-upgrade-inventory.js +442 -0
- package/dist/services/memory-upgrade-publication-custody.js +73 -0
- package/dist/services/memory-upgrade-publication.js +413 -0
- package/dist/services/memory-upgrade-selection.js +430 -0
- package/dist/services/memory-upgrade-start.js +60 -0
- package/dist/services/memory-upgrade-storage-readiness.js +340 -0
- package/dist/services/memory-verification-acceptance.js +38 -17
- package/dist/services/memory-verification-checks.js +77 -23
- package/dist/services/memory-verification-receipt.js +6 -5
- package/dist/services/memory-verify-handler.js +15 -13
- package/dist/services/memory-work-result-json.js +12 -0
- package/dist/services/memory-work-result-preparation.js +5 -4
- package/dist/services/merge-server.js +4 -2
- package/dist/services/migrations.js +127 -98
- package/dist/services/physical-startup.js +45 -0
- package/dist/services/project-registry.js +97 -0
- package/dist/services/project-summary.js +1 -1
- package/dist/services/projects.js +3 -93
- package/dist/services/prompt-delivery.js +71 -0
- package/dist/services/provider-capacity.js +69 -8
- package/dist/services/recovery-snapshot-database.js +32 -4
- package/dist/services/repair-intents.js +1 -12
- package/dist/services/repair-receipt.js +13 -0
- package/dist/services/run-control-worker.js +35 -18
- package/dist/services/run-controller-process.js +2 -6
- package/dist/services/run-controller-recovery.js +6 -1
- package/dist/services/run-controller.js +131 -80
- package/dist/services/run-recovery-guard.js +30 -0
- package/dist/services/run-recovery.js +11 -44
- package/dist/services/run-start-custody.js +17 -5
- package/dist/services/runtime-scope-worker.js +46 -19
- package/dist/services/sessions.js +3 -24
- package/dist/services/setup.js +63 -13
- package/dist/services/stage-handlers.js +9 -7
- package/dist/services/stage-pause.js +108 -44
- package/dist/services/version-status.js +1 -1
- package/dist/services/vnext-fanout.js +21 -9
- package/dist/services/vnext-plan-review.js +3 -5
- package/dist/services/work-registry.js +80 -33
- package/dist/services/workspace-files.js +1 -1
- package/dist/shared/entity-references.js +1 -8
- package/dist/storage/data-preservation.js +65 -0
- package/dist/storage/database.js +53 -19
- package/dist/storage/import-guard.js +84 -27
- package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
- package/dist/storage/paired-writer-migration.js +424 -0
- package/dist/storage/writer-contract.js +11 -4
- package/dist/storage/writer-migration.js +313 -52
- package/dist/storage/writer-restore.js +217 -0
- package/package.json +8 -4
|
@@ -57,15 +57,15 @@ export function startMemoryReview(context, input) {
|
|
|
57
57
|
if (!(input.bytes instanceof Uint8Array) || input.bytes.length > 1024 * 1024)
|
|
58
58
|
refuse("invalid_input_bytes");
|
|
59
59
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
60
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
60
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id) || bundle.descriptor.successor("verify", "accepted") !== "review"
|
|
61
61
|
|| bundle.descriptor.successor("review", "accepted") !== "finish")
|
|
62
62
|
refuse("registered_memory_bundle_required");
|
|
63
63
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
|
|
64
64
|
const run = assertPreparedRunBundleSqlAuthority(context, scope, bundle), index = JSON.parse(run.index_json);
|
|
65
65
|
if (index.stage_runs.find((stage) => stage.stage === "review")?.status === "done")
|
|
66
66
|
refuse("use_accepted_finish_replay");
|
|
67
|
-
const preservation = PreparedMemoryBaselinePreservation.prepare(context, bundle.execution);
|
|
68
67
|
const composition = PreparedAcceptedMemoryComposition.prepare(context, { scope, bundle });
|
|
68
|
+
const preservation = bundle.descriptor.descriptor.id === "mb-upgrade" ? composition : PreparedMemoryBaselinePreservation.prepare(context, bundle.execution);
|
|
69
69
|
const data = readAcceptedStageData(context, { ...scope, stage: "verify" });
|
|
70
70
|
const verification = PreparedAcceptedMemoryVerification.prepare(context, { ...scope, bytes: data.bytes });
|
|
71
71
|
const fence = (writer) => { preservation.assertCustody(writer); composition.assertCustody(writer); verification.assertCustody(writer); };
|
|
@@ -82,7 +82,7 @@ export function startMemoryReview(context, input) {
|
|
|
82
82
|
*/
|
|
83
83
|
export function registerMemoryReviewFromStage(context, input) {
|
|
84
84
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
85
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
85
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
86
86
|
refuse("registered_memory_bundle_required");
|
|
87
87
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
88
88
|
const inputs = PreparedMemoryInitialReviewInputs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -94,7 +94,7 @@ export function registerMemoryReviewFromStage(context, input) {
|
|
|
94
94
|
*/
|
|
95
95
|
export function collectMemoryInitialReviewFromStage(context, input) {
|
|
96
96
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
97
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
97
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
98
98
|
refuse("registered_memory_bundle_required");
|
|
99
99
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
100
100
|
const inputs = PreparedMemoryInitialReviewInputs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -107,7 +107,7 @@ export function finishMemoryReview(context, input) {
|
|
|
107
107
|
if (!(input.bytes instanceof Uint8Array) || !input.bytes.length || input.bytes.length > 1024 * 1024)
|
|
108
108
|
refuse("invalid_result_bytes");
|
|
109
109
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
110
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
110
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id) || bundle.descriptor.successor("verify", "accepted") !== "review"
|
|
111
111
|
|| bundle.descriptor.successor("review", "accepted") !== "finish")
|
|
112
112
|
refuse("registered_memory_bundle_required");
|
|
113
113
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
|
|
@@ -170,7 +170,7 @@ export function registerMemoryCorrectionsFromStage(context, input) {
|
|
|
170
170
|
if (!(input.bytes instanceof Uint8Array) || !input.bytes.length || input.bytes.length > 1024 * 1024)
|
|
171
171
|
refuse("invalid_input_bytes");
|
|
172
172
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
173
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
173
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
174
174
|
refuse("registered_memory_bundle_required");
|
|
175
175
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
176
176
|
const original = PreparedRetainedMemoryReviewAuthority.prepare(context, { projectId: project.id, runId: input.runId }, bundle);
|
|
@@ -222,7 +222,7 @@ function prepareMemoryRepairBaselineFromStage(context, input) {
|
|
|
222
222
|
}
|
|
223
223
|
function prepareMemoryRepairRegistrationFromStage(context, input) {
|
|
224
224
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
225
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
225
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
226
226
|
refuse("registered_memory_bundle_required");
|
|
227
227
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
228
228
|
const original = PreparedRetainedMemoryReviewAuthority.prepare(context, { projectId: project.id, runId: input.runId }, bundle);
|
|
@@ -264,7 +264,7 @@ export function registerMemorySecondCorrectionsFromStage(context, input) {
|
|
|
264
264
|
if (!(input.bytes instanceof Uint8Array) || !input.bytes.length || input.bytes.length > 1024 * 1024)
|
|
265
265
|
refuse("invalid_input_bytes");
|
|
266
266
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
267
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
267
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
268
268
|
refuse("registered_memory_bundle_required");
|
|
269
269
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
270
270
|
try {
|
|
@@ -281,7 +281,7 @@ export function registerMemorySecondCorrectionsFromStage(context, input) {
|
|
|
281
281
|
}
|
|
282
282
|
export function prepareMemorySecondRepairSourceFromStage(context, input) {
|
|
283
283
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
284
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
284
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
285
285
|
refuse("registered_memory_bundle_required");
|
|
286
286
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
287
287
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -295,7 +295,7 @@ export function prepareMemorySecondRepairSourceFromStage(context, input) {
|
|
|
295
295
|
* only; consuming it as a dependent baseline/start requires separate owners. */
|
|
296
296
|
export function prepareMemorySecondRepairCurrentViewFromStage(context, input) {
|
|
297
297
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
298
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
298
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
299
299
|
refuse("registered_memory_bundle_required");
|
|
300
300
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
301
301
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -306,7 +306,7 @@ export function registerMemorySecondRepairCurrentViewFromStage(context, input) {
|
|
|
306
306
|
}
|
|
307
307
|
export function restoreMemorySecondRepairCurrentViewFromStage(context, input) {
|
|
308
308
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
309
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
309
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
310
310
|
refuse("registered_memory_bundle_required");
|
|
311
311
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
312
312
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -314,7 +314,7 @@ export function restoreMemorySecondRepairCurrentViewFromStage(context, input) {
|
|
|
314
314
|
}
|
|
315
315
|
export function prepareMemorySecondRepairCurrentSourceFromStage(context, input) {
|
|
316
316
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
317
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
317
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
318
318
|
refuse("registered_memory_bundle_required");
|
|
319
319
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
320
320
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -342,7 +342,7 @@ export function prepareMemorySecondRepairDispatchFromStage(context, input) {
|
|
|
342
342
|
}
|
|
343
343
|
export function restoreMemorySecondRepairBaselineFromStage(context, input) {
|
|
344
344
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
345
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
345
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
346
346
|
refuse("registered_memory_bundle_required");
|
|
347
347
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
348
348
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -350,7 +350,7 @@ export function restoreMemorySecondRepairBaselineFromStage(context, input) {
|
|
|
350
350
|
}
|
|
351
351
|
export function prepareMemorySecondRepairLaunchFromStage(context, input) {
|
|
352
352
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
353
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
353
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
354
354
|
refuse("registered_memory_bundle_required");
|
|
355
355
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
356
356
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -359,7 +359,7 @@ export function prepareMemorySecondRepairLaunchFromStage(context, input) {
|
|
|
359
359
|
}
|
|
360
360
|
export function restoreStartedMemorySecondRepairLaunchFromStage(context, input) {
|
|
361
361
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
362
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
362
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
363
363
|
refuse("registered_memory_bundle_required");
|
|
364
364
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
365
365
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -386,7 +386,7 @@ export function finishMemorySecondRepairPublicationFromStage(context, input) {
|
|
|
386
386
|
* The whole independent start/publication/SDK settlement chain is required. */
|
|
387
387
|
export function prepareSettledMemorySecondRepairFromStage(context, input) {
|
|
388
388
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
389
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
389
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
390
390
|
refuse("registered_memory_bundle_required");
|
|
391
391
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
392
392
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -396,7 +396,7 @@ export function prepareSettledMemorySecondRepairFromStage(context, input) {
|
|
|
396
396
|
* semantic re-review acceptance and does not close the review Stage. */
|
|
397
397
|
export function prepareCompletedMemorySecondCorrectionsFromStage(context, input) {
|
|
398
398
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
399
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
399
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
400
400
|
refuse("registered_memory_bundle_required");
|
|
401
401
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
402
402
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -14,6 +14,8 @@ import { assertRunMutationAllowed } from "./run-recovery-guard.js";
|
|
|
14
14
|
import { PreparedDescriptorStageCoordinator } from "./descriptor-stage-coordinator.js";
|
|
15
15
|
import { readDescriptorCoordinatorSession } from "./descriptor-coordinator-session.js";
|
|
16
16
|
import { readMemoryInitBootstrapReadiness } from "./memory-init-bootstrap-readiness.js";
|
|
17
|
+
import { readMemoryUpgradeEvidence } from "./memory-upgrade-evidence.js";
|
|
18
|
+
import { memoryReviewViewWithinLimit } from "./memory-review-limits.js";
|
|
17
19
|
/** Exact inherited evidence only; current artifact bytes remain independently observed. */
|
|
18
20
|
export function memoryReviewEvidenceTriples(units) {
|
|
19
21
|
return new Set(units.flatMap(unit => unit.evidence.map(ref => `${memorySourceKey(ref.root, ref.path)}\0${ref.sha256}`)));
|
|
@@ -25,7 +27,7 @@ function refuse(reason) {
|
|
|
25
27
|
* are read through the assigned workspace, whose baseline is independently
|
|
26
28
|
* preserved. This function alone supplies neither acceptance nor SQL authority.
|
|
27
29
|
*/
|
|
28
|
-
export function memoryReviewUnitAssignments(units, historicalEvidence = new Set()) {
|
|
30
|
+
export function memoryReviewUnitAssignments(units, historicalEvidence = new Set(), retainedEvidence = new Map()) {
|
|
29
31
|
if (!Array.isArray(units) || !units.length || units.length > 256
|
|
30
32
|
|| units.some(unit => !unit || typeof unit.id !== "string" || !unit.id || typeof unit.aspect !== "string" || !unit.aspect)
|
|
31
33
|
|| new Set(units.map(unit => unit.id)).size !== units.length)
|
|
@@ -46,7 +48,8 @@ export function memoryReviewUnitAssignments(units, historicalEvidence = new Set(
|
|
|
46
48
|
|| ref.path.split("/").some((part) => !part || part === "." || part === "..")
|
|
47
49
|
|| typeof ref.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(ref.sha256))
|
|
48
50
|
refuse("invalid_unit_source");
|
|
49
|
-
const
|
|
51
|
+
const historical = role === "evidence" ? retainedEvidence.get(`${memorySourceKey(ref.root, ref.path)}\0${ref.sha256}`) : undefined;
|
|
52
|
+
const input = historical ?? { root: ref.root === "run" ? "run" : "workspace",
|
|
50
53
|
path: ref.root === "canon" ? `.memory-bank/${ref.path}` : ref.path, sha256: ref.sha256 };
|
|
51
54
|
if (role === "evidence" && historicalEvidence.has(`${memorySourceKey(ref.root, ref.path)}\0${ref.sha256}`)
|
|
52
55
|
&& units.flatMap(item => item.artifacts).some(artifact => (artifact.root === "run" ? "run" : "workspace") === input.root
|
|
@@ -57,6 +60,12 @@ export function memoryReviewUnitAssignments(units, historicalEvidence = new Set(
|
|
|
57
60
|
refuse("conflicting_unit_sources");
|
|
58
61
|
references.set(key, input);
|
|
59
62
|
}
|
|
63
|
+
// The author cannot hide a semantic loss by omitting the previous version
|
|
64
|
+
// from unit.evidence. Every rewritten output brings its old bytes to review.
|
|
65
|
+
const outputPaths = new Set(unit.artifacts.map((ref) => memorySourceKey(ref.root === "run" ? "run" : "workspace", ref.root === "canon" ? `.memory-bank/${ref.path}` : ref.path)));
|
|
66
|
+
for (const [source, retained] of retainedEvidence)
|
|
67
|
+
if (outputPaths.has(source.slice(0, source.lastIndexOf("\0"))))
|
|
68
|
+
references.set(memorySourceKey(retained.root, retained.path), retained);
|
|
60
69
|
if (references.size > 4096)
|
|
61
70
|
refuse("unbounded_unit_sources");
|
|
62
71
|
return { unit: structuredClone(unit), inputs: [...references.values()].sort((a, b) => a.path.localeCompare(b.path, "en")) };
|
|
@@ -109,7 +118,7 @@ export class PreparedMemoryInitialReviewInputs {
|
|
|
109
118
|
}
|
|
110
119
|
static prepare(context, input) {
|
|
111
120
|
const { scope, bundle } = input;
|
|
112
|
-
if (!(bundle instanceof RetainedExecutionBundle) || bundle.descriptor.descriptor.id
|
|
121
|
+
if (!(bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
113
122
|
refuse("registered_memory_bundle_required");
|
|
114
123
|
const generation = assertRunMutationAllowed(context, scope.projectId, scope.runId);
|
|
115
124
|
const workerSchema = JSON.parse(bundle.engine().schema("memory-review-work-result").toString("utf8"));
|
|
@@ -119,13 +128,50 @@ export class PreparedMemoryInitialReviewInputs {
|
|
|
119
128
|
const coordinator = PreparedDescriptorStageCoordinator.prepare(context, { projectRoot: bundle.execution.snapshot().scope.projectRoot, runId: scope.runId, stage: "review" });
|
|
120
129
|
coordinator.assertAllocatedCustody(context);
|
|
121
130
|
const coordinatorSession = readDescriptorCoordinatorSession(context, { scope: { ...scope, stage: "review" }, bundle, workId: selected.parent_work_id }, refuse);
|
|
122
|
-
const preservation = PreparedMemoryBaselinePreservation.prepare(context, bundle.execution);
|
|
123
131
|
const composition = PreparedAcceptedMemoryComposition.prepare(context, { scope, bundle });
|
|
124
|
-
const
|
|
132
|
+
const upgrade = bundle.descriptor.descriptor.id === "mb-upgrade", frozenScope = bundle.execution.snapshot().scope;
|
|
133
|
+
const preservation = upgrade ? composition : PreparedMemoryBaselinePreservation.prepare(context, bundle.execution);
|
|
134
|
+
const old = upgrade ? readMemoryUpgradeEvidence(context, { requestId: frozenScope.requestId, projectRoot: frozenScope.projectRoot, workspaceRoot: frozenScope.workspace }) : null;
|
|
135
|
+
const retainedEvidence = new Map();
|
|
136
|
+
for (const entry of old?.index.entries ?? []) {
|
|
137
|
+
retainedEvidence.set(`${memorySourceKey(entry.source.root, entry.source.path)}\0${entry.source.sha256}`, entry.retained);
|
|
138
|
+
if (frozenScope.workspace === frozenScope.projectRoot)
|
|
139
|
+
retainedEvidence.set(`${memorySourceKey("project", entry.source.path)}\0${entry.source.sha256}`, entry.retained);
|
|
140
|
+
}
|
|
141
|
+
const compose = readAcceptedStageData(context, { ...scope, stage: upgrade ? "upgrade" : "compose" });
|
|
125
142
|
const verify = readAcceptedStageData(context, { ...scope, stage: "verify" });
|
|
126
143
|
const verification = PreparedAcceptedMemoryVerification.prepare(context, { ...scope, bytes: verify.bytes });
|
|
127
144
|
const unitInventory = composition.result().value().units;
|
|
128
|
-
const assignments = memoryReviewUnitAssignments(unitInventory, composition.historicalEvidence());
|
|
145
|
+
const assignments = memoryReviewUnitAssignments(unitInventory, composition.historicalEvidence(), retainedEvidence);
|
|
146
|
+
if (upgrade && typeof verify.input_sha256 === "string") {
|
|
147
|
+
const reference = { root: "run", path: `${bundle.descriptor.stage("verify").directory}/stage-input.json`, sha256: verify.input_sha256 };
|
|
148
|
+
for (const assignment of assignments)
|
|
149
|
+
if (!assignment.inputs.some(ref => ref.root === reference.root && ref.path === reference.path))
|
|
150
|
+
assignment.inputs.push(reference);
|
|
151
|
+
}
|
|
152
|
+
if (old) {
|
|
153
|
+
const diff = JSON.parse(readAcceptedStageData(context, { ...scope, stage: "diff-analysis" }).bytes.toString("utf8"));
|
|
154
|
+
for (const change of diff.details.path_map) {
|
|
155
|
+
const assigned = assignments.find(item => item.unit.id === change.unit_id);
|
|
156
|
+
const before = old.index.entries.find(entry => entry.source.path === change.from)?.retained;
|
|
157
|
+
if (assigned && before && !assigned.inputs.some(ref => ref.root === before.root && ref.path === before.path))
|
|
158
|
+
assigned.inputs.push(before);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Every named preservation criterion is supplied independently of which
|
|
162
|
+
// historical references the author chose to repeat in its final unit.
|
|
163
|
+
const invariants = composition.result().preservationInvariants();
|
|
164
|
+
for (const invariant of invariants) {
|
|
165
|
+
const assigned = assignments.find(item => item.unit.id === invariant.unit_id);
|
|
166
|
+
if (!assigned)
|
|
167
|
+
refuse("preservation_invariant_without_reviewer");
|
|
168
|
+
for (const ref of invariant.evidence) {
|
|
169
|
+
const retained = retainedEvidence.get(`${memorySourceKey(ref.root, ref.path)}\0${ref.sha256}`)
|
|
170
|
+
?? { root: ref.root === "run" ? "run" : "workspace", path: ref.root === "canon" ? `.memory-bank/${ref.path}` : ref.path, sha256: ref.sha256 };
|
|
171
|
+
if (!assigned.inputs.some(input => input.root === retained.root && input.path === retained.path && input.sha256 === retained.sha256))
|
|
172
|
+
assigned.inputs.push(retained);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
129
175
|
const diagnosticFindings = verification.qualityPassed(context) ? [] : verification.diagnosticFindings(context).filter(finding => finding.status === "open" && finding.severity !== "minor");
|
|
130
176
|
for (const finding of diagnosticFindings) {
|
|
131
177
|
const assignment = assignments.find(item => item.unit.id === finding.unit_id);
|
|
@@ -136,8 +182,7 @@ export class PreparedMemoryInitialReviewInputs {
|
|
|
136
182
|
assignment.inputs.push({ ...ref, root: "run" });
|
|
137
183
|
}
|
|
138
184
|
const inputs = new Map();
|
|
139
|
-
const
|
|
140
|
-
const bootstrap = readMemoryInitBootstrapReadiness(context, { requestId: frozenScope.requestId,
|
|
185
|
+
const bootstrap = upgrade ? null : readMemoryInitBootstrapReadiness(context, { requestId: frozenScope.requestId,
|
|
141
186
|
projectRoot: frozenScope.projectRoot, workspaceRoot: frozenScope.workspace });
|
|
142
187
|
const lintSha256 = bootstrap?.authority.binding.target.generated_lint_config_sha256;
|
|
143
188
|
if (lintSha256)
|
|
@@ -168,8 +213,9 @@ export class PreparedMemoryInitialReviewInputs {
|
|
|
168
213
|
source_policy: "review-inputs@1", source_sha256: reviewSourceHash(roots.workspace, paths, base), base,
|
|
169
214
|
run_inputs: runInputs, unit_inventory: structuredClone(unitInventory), assignments,
|
|
170
215
|
...(diagnosticFindings.length ? { diagnostic_findings: diagnosticFindings } : {}),
|
|
216
|
+
...(old ? { upgrade_baseline: { ...old.index, entries: old.index.entries.filter(entry => runInputs.some(ref => ref.root === entry.retained.root && ref.path === entry.retained.path)) }, preservation_invariants: invariants } : {}),
|
|
171
217
|
instruction: { sha256: bundle.descriptor.stage("review").instruction.sha256, base64: instruction.toString("base64") } };
|
|
172
|
-
if (
|
|
218
|
+
if (!memoryReviewViewWithinLimit(view))
|
|
173
219
|
refuse("unbounded_review_input");
|
|
174
220
|
const prepared = new PreparedMemoryInitialReviewInputs(scope, bundle, selected, composition, verification, preservation, observed, view, generation, coordinator, coordinatorSession);
|
|
175
221
|
prepared.assertCustody(context);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** A prepared wave aggregates independently bounded units and retained before
|
|
2
|
+
* references. It is not one untrusted agent response (still capped at 1 MiB).
|
|
3
|
+
* Use the existing complete reviewer-batch budget for all three wave views;
|
|
4
|
+
* leave room for allocation identities in their retained SQL receipts.
|
|
5
|
+
*/
|
|
6
|
+
export const memoryReviewWaveByteLimit = 64 * 1024 * 1024;
|
|
7
|
+
export const memoryReviewRegistrationByteLimit = memoryReviewWaveByteLimit + 1024 * 1024;
|
|
8
|
+
export function memoryReviewViewWithinLimit(view) {
|
|
9
|
+
return Buffer.byteLength(JSON.stringify(view)) <= memoryReviewWaveByteLimit;
|
|
10
|
+
}
|
|
@@ -100,7 +100,7 @@ function accepted(context, scope, bundle) {
|
|
|
100
100
|
}
|
|
101
101
|
if (!receipt || typeof receipt !== "object" || Array.isArray(receipt) || !receipt.registration_scope
|
|
102
102
|
|| receipt.registration_scope.bundle_sha256 !== bundle.sha256 || receipt.registration_scope.execution_sha256 !== bundle.execution.sha256
|
|
103
|
-
|| receipt.wave !== 0 || data.data_schema_id !== "dd-flow/mb-init-review-result@1" || data.input_sha256 !== selected.input_sha256)
|
|
103
|
+
|| receipt.wave !== 0 || data.data_schema_id !== (bundle.descriptor.descriptor.id === "mb-upgrade" ? "dd-flow/mb-upgrade-stage-result@1" : "dd-flow/mb-init-review-result@1") || data.input_sha256 !== selected.input_sha256)
|
|
104
104
|
refuse("accepted_review_changed");
|
|
105
105
|
const registration = readRegisteredMemoryReview(context, receipt.registration_scope, 0);
|
|
106
106
|
const batch = memoryReviewBatch(registration.view), harness = runtimeHarness(bundle.execution.work("review").worker);
|
|
@@ -136,7 +136,7 @@ export class PreparedAcceptedMemoryInitialReview {
|
|
|
136
136
|
Object.freeze(this);
|
|
137
137
|
}
|
|
138
138
|
static prepare(context, input) {
|
|
139
|
-
if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id
|
|
139
|
+
if (!(input.bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(input.bundle.descriptor.descriptor.id)
|
|
140
140
|
|| !(input.bytes instanceof Uint8Array) || !input.bytes.length || input.bytes.length > 1024 * 1024)
|
|
141
141
|
refuse("registered_memory_result_required");
|
|
142
142
|
if (context.db.isOwnedWriteTransaction?.())
|
|
@@ -3,6 +3,7 @@ import { appendAudit } from "./audit.js";
|
|
|
3
3
|
import { hybridDigest } from "./hybrid-contracts.js";
|
|
4
4
|
import { PreparedMemoryInitialReviewInputs } from "./memory-review-inputs.js";
|
|
5
5
|
import { addWorkBatch, prepareWorkBatch, readWorkBatchCustody } from "./work-registry.js";
|
|
6
|
+
import { memoryReviewRegistrationByteLimit } from "./memory-review-limits.js";
|
|
6
7
|
export const memoryReviewWorkerSchema = "dd-flow/memory-review-work-result@1";
|
|
7
8
|
const event = "memory.review_registration";
|
|
8
9
|
function refuse(reason) {
|
|
@@ -16,7 +17,7 @@ function selected(context, scope, wave) {
|
|
|
16
17
|
const rows = context.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type=? AND json_extract(payload_json,'$.run_id')=? AND json_extract(payload_json,'$.scope.attempt')=? AND json_extract(payload_json,'$.scope.parent_work_id')=? AND json_extract(payload_json,'$.wave')=? LIMIT 2", [scope.project_id, event, scope.run_id, scope.attempt, scope.parent_work_id, wave]);
|
|
17
18
|
if (!rows.length)
|
|
18
19
|
return null;
|
|
19
|
-
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) >
|
|
20
|
+
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > memoryReviewRegistrationByteLimit)
|
|
20
21
|
refuse("ambiguous_or_unbounded_registration");
|
|
21
22
|
try {
|
|
22
23
|
const receipt = JSON.parse(rows[0].payload_json);
|
|
@@ -56,13 +57,19 @@ function batchScope(view) {
|
|
|
56
57
|
* frozen Stage instruction is context, not coordinator authority for a worker.
|
|
57
58
|
*/
|
|
58
59
|
export function memoryReviewBatch(view) {
|
|
60
|
+
const inputSha256 = view.assignments.length ? hybridDigest(view) : "";
|
|
59
61
|
return { works: view.assignments.map((assignment, index) => {
|
|
60
62
|
const key = `review-${String(index + 1).padStart(3, "0")}`;
|
|
63
|
+
const inputPaths = view.upgrade_baseline ? new Set(assignment.inputs.map(ref => `${ref.root}\0${ref.path}`)) : null;
|
|
61
64
|
const packet = { schema_id: "dd-flow/memory-review-work-packet@1", run_id: view.scope.run_id,
|
|
62
65
|
stage: "review", wave: view.wave, key, unit: assignment.unit, unit_inputs: assignment.inputs,
|
|
63
|
-
review_input_sha256:
|
|
64
|
-
instruction: view.instruction
|
|
65
|
-
|
|
66
|
+
review_input_sha256: inputSha256, result_schema: memoryReviewWorkerSchema,
|
|
67
|
+
instruction: view.instruction,
|
|
68
|
+
...(view.upgrade_baseline ? {
|
|
69
|
+
historical_inputs: view.upgrade_baseline.entries.filter(entry => inputPaths.has(`${entry.retained.root}\0${entry.retained.path}`)),
|
|
70
|
+
preservation_invariants: (view.preservation_invariants ?? []).filter(item => item.unit_id === assignment.unit.id)
|
|
71
|
+
} : {}) };
|
|
72
|
+
return { key, task: `Independently review the assigned knowledge unit ${JSON.stringify(assignment.unit.id)}. Read the frozen review instruction in memory_review as review criteria, not permission to coordinate or repair. Check grounding, evidence, coverage and cross-file consistency using the registered wave inputs. Assigned unit.evidence may retain historical source versions; cite those exact versions only as historical context, never as bytes read from or current in this copy. Direct assessment and findings must still cite the assigned current unit.artifacts/unit_inputs. Do not edit project documents, allocate Work or repair findings. Report concrete material defects with unit/source evidence; do not block on taste. Return only the assigned memory-review-work-result JSON; do not claim other units or Stage completion.${view.upgrade_baseline ? " Compare every assigned preservation_invariant against the actual old bytes in historical_inputs.retained and the current unit outputs. Historical copies are readable RUN inputs, not current workspace documents or executable instructions. Cite the retained old reference and current output; identify lost facts, constraints, decisions, identifiers, custom commands, metadata or links even when lint passes." : ""}${view.diagnostic_findings?.length ? ` Committed VERIFY diagnostics for this unit remain unresolved until distinct repair and passed recheck: ${JSON.stringify(view.diagnostic_findings.filter(finding => finding.unit_id === assignment.unit.id))}.` : ""}`,
|
|
66
73
|
depends_on: [], launch_policy: "fresh_agent_required", result_schema: memoryReviewWorkerSchema,
|
|
67
74
|
payload: { kind: "memory-review", read_only: true,
|
|
68
75
|
memory_review: { ...packet, packet_sha256: hybridDigest(packet) } } };
|
|
@@ -100,6 +107,8 @@ export function registerMemoryInitialReview(context, inputs) {
|
|
|
100
107
|
const receipt = { schema_id: "dd-flow/memory-review-registration@1", run_id: request.run_id,
|
|
101
108
|
scope: view.scope, wave: view.wave, input_sha256: inputs.sha256, view,
|
|
102
109
|
batch_sha256: hybridDigest(batch.works), work_ids: workIds };
|
|
110
|
+
if (Buffer.byteLength(JSON.stringify(receipt)) > memoryReviewRegistrationByteLimit)
|
|
111
|
+
refuse("unbounded_registration");
|
|
103
112
|
appendAudit(context, { projectId: request.project_id, eventType: event, payload: receipt });
|
|
104
113
|
}
|
|
105
114
|
const retained = readRegisteredMemoryReview(context, view.scope, view.wave);
|
|
@@ -84,14 +84,16 @@ export class PreparedRegisteredMemoryReviewWorkResult {
|
|
|
84
84
|
if (!run)
|
|
85
85
|
refuse("owned_run_required");
|
|
86
86
|
const generation = recoveryGuard(context, work.project_id, work.run_id)?.generation ?? 0;
|
|
87
|
-
const owner = prepareMemoryReviewWorkInput(context, work, run, generation);
|
|
87
|
+
const owner = prepareMemoryReviewWorkInput(context, work, run, generation, input.progress);
|
|
88
88
|
const bytes = Buffer.from(input.bytes), value = validateMemoryReviewWorkResult(bytes, owner.bundle.engine(), {
|
|
89
89
|
workId: work.work_id, packet: owner.packet(), references: owner.input.run_inputs
|
|
90
90
|
});
|
|
91
|
+
input.progress?.(`Memory review ${work.work_id}: result validated`);
|
|
91
92
|
const harness = runtimeHarness(owner.bundle.execution.work("review").worker);
|
|
92
93
|
const allocation = readWorkBatchCustody(context, work.work_id), selected = physical(context, work, owner, harness);
|
|
93
94
|
const prepared = new PreparedRegisteredMemoryReviewWorkResult(bytes, value, work, owner, allocation, selected, harness);
|
|
94
95
|
prepared.assertCustody(context);
|
|
96
|
+
input.progress?.(`Memory review ${work.work_id}: result custody verified`);
|
|
95
97
|
return prepared;
|
|
96
98
|
}
|
|
97
99
|
bytes() { return Buffer.from(this.#bytes); }
|
|
@@ -21,10 +21,11 @@ function refuse(reason) {
|
|
|
21
21
|
/** Physical preparation outside a writer. The SQL-only closure must also be
|
|
22
22
|
* consumed by Work claim, not just by an external launch/copy precheck.
|
|
23
23
|
*/
|
|
24
|
-
export function prepareMemoryReviewWorkInput(context, work, run, generation) {
|
|
24
|
+
export function prepareMemoryReviewWorkInput(context, work, run, generation, progress) {
|
|
25
25
|
const bundle = readFlowRunExecutionBundle(context, { projectRoot: run.project_root, runId: work.run_id });
|
|
26
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
26
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
27
27
|
refuse("registered_memory_bundle_required");
|
|
28
|
+
progress?.(`Memory review ${work.work_id}: bundle verified`);
|
|
28
29
|
let payload;
|
|
29
30
|
try {
|
|
30
31
|
payload = JSON.parse(work.payload_json ?? "null");
|
|
@@ -40,8 +41,14 @@ export function prepareMemoryReviewWorkInput(context, work, run, generation) {
|
|
|
40
41
|
const scope = { projectId: work.project_id, runId: work.run_id };
|
|
41
42
|
const corrected = packet.wave === 2 ? PreparedSecondCorrectedMemoryReviewInputs.prepareFromBundle(context, { scope, bundle })
|
|
42
43
|
: packet.wave === 1 ? PreparedCorrectedMemoryReviewInputs.prepareFromBundle(context, { scope, bundle }) : null;
|
|
43
|
-
const registration = corrected ? PreparedRegisteredCorrectedMemoryReview.restore(context, corrected, PreparedMemoryCorrectionCheckReceipt.restore(context, corrected)) : null;
|
|
44
44
|
const owner = corrected ?? PreparedMemoryInitialReviewInputs.prepare(context, { scope, bundle });
|
|
45
|
+
progress?.(`Memory review ${work.work_id}: inputs prepared`);
|
|
46
|
+
const checks = corrected ? PreparedMemoryCorrectionCheckReceipt.restore(context, corrected) : null;
|
|
47
|
+
if (checks)
|
|
48
|
+
progress?.(`Memory review ${work.work_id}: checks restored`);
|
|
49
|
+
const registration = corrected && checks ? PreparedRegisteredCorrectedMemoryReview.restore(context, corrected, checks) : null;
|
|
50
|
+
if (registration)
|
|
51
|
+
progress?.(`Memory review ${work.work_id}: registration restored`);
|
|
45
52
|
const view = owner.value(), receipt = registration ? registration.receipt() : readRegisteredMemoryReview(context, view.scope, view.wave);
|
|
46
53
|
if (receipt.input_sha256 !== owner.sha256 || work.parent_work_id !== view.scope.parent_work_id
|
|
47
54
|
|| work.result_schema !== memoryReviewWorkerSchema || work.launch_policy !== "fresh_agent_required")
|
|
@@ -53,20 +60,32 @@ export function prepareMemoryReviewWorkInput(context, work, run, generation) {
|
|
|
53
60
|
refuse("changed_review_assignment");
|
|
54
61
|
const receiptSha256 = hybridDigest(receipt);
|
|
55
62
|
const assertCustody = (writer) => {
|
|
56
|
-
owner.assertCustody(writer);
|
|
57
63
|
if (registration)
|
|
58
64
|
registration.assertCustody(writer);
|
|
59
|
-
else
|
|
60
|
-
|
|
65
|
+
else {
|
|
66
|
+
owner.assertCustody(writer);
|
|
67
|
+
if (hybridDigest(readRegisteredMemoryReview(writer, view.scope, view.wave)) !== receiptSha256)
|
|
68
|
+
refuse("review_registration_changed");
|
|
69
|
+
}
|
|
61
70
|
};
|
|
62
71
|
assertCustody(context);
|
|
72
|
+
progress?.(`Memory review ${work.work_id}: assignment verified`);
|
|
63
73
|
const input = { schema_id: "dd-flow/review-input@3", parent_work_id: view.scope.parent_work_id,
|
|
64
74
|
kind: "memory-review", cycle: `memory-review-wave-${view.wave}`, generation,
|
|
65
75
|
workspace_fingerprint: view.source_sha256, source_policy: "review-inputs@1",
|
|
66
76
|
source_sha256: view.source_sha256, run_inputs: structuredClone(view.run_inputs) };
|
|
67
77
|
const prepared = Object.freeze({ input, assertCustody, bundle,
|
|
68
78
|
registration: () => structuredClone(receipt), packet: () => structuredClone(assigned.payload.memory_review),
|
|
69
|
-
|
|
79
|
+
// The registered owner already revalidates corrected inputs, checks and
|
|
80
|
+
// its allocation. Repeating those traversals here adds no new boundary.
|
|
81
|
+
revalidate: (reader) => {
|
|
82
|
+
if (registration)
|
|
83
|
+
registration.revalidate(reader);
|
|
84
|
+
else {
|
|
85
|
+
owner.revalidate(reader);
|
|
86
|
+
assertCustody(reader);
|
|
87
|
+
}
|
|
88
|
+
} });
|
|
70
89
|
preparedOwners.set(prepared, { store: context.db, work: workScope(work), root: run.project_root, generation, input: hybridDigest(input) });
|
|
71
90
|
return prepared;
|
|
72
91
|
}
|
|
@@ -3,6 +3,7 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import { AppError } from "../shared/errors.js";
|
|
4
4
|
import { AdmittedFrozenEngine } from "./frozen-engine.js";
|
|
5
5
|
import { memorySourceKey } from "./memory-stage-results.js";
|
|
6
|
+
import { parseMemoryWorkResultProposal } from "./memory-work-result-json.js";
|
|
6
7
|
import { memoryReviewWorkerSchema } from "./memory-review-registration.js";
|
|
7
8
|
function refuse(reason) {
|
|
8
9
|
throw new AppError("memory_review_work_result_invalid", "Reviewer result lacks assigned unit and retained input evidence", 2, { reason, effect: "no_effect" });
|
|
@@ -16,12 +17,16 @@ export function validateMemoryReviewWorkResult(input, engine, binding) {
|
|
|
16
17
|
if (!(input instanceof Uint8Array) || !input.byteLength || input.byteLength > 1024 * 1024
|
|
17
18
|
|| !(engine instanceof AdmittedFrozenEngine) || !binding.workId || binding.packet?.result_schema !== memoryReviewWorkerSchema)
|
|
18
19
|
refuse("invalid_preparation_binding");
|
|
19
|
-
const value =
|
|
20
|
+
const value = parseMemoryWorkResultProposal(input, "memory_review_work_result_invalid");
|
|
20
21
|
const schema = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(engine.schema("memory-review-work-result")));
|
|
21
22
|
if (schema.$id !== memoryReviewWorkerSchema)
|
|
22
23
|
refuse("invalid_result_schema");
|
|
23
24
|
const packet = binding.packet;
|
|
24
|
-
|
|
25
|
+
// A malformed checksum is a correctable proposal shape, not proof that a
|
|
26
|
+
// valid foreign packet was selected. Never accept either mismatch.
|
|
27
|
+
const foreignPacket = typeof value.packet_sha256 === "string" && /^[a-f0-9]{64}$/.test(value.packet_sha256)
|
|
28
|
+
&& value.packet_sha256 !== packet.packet_sha256;
|
|
29
|
+
if (value.schema_id !== memoryReviewWorkerSchema || value.run_id !== packet.run_id || value.work_id !== binding.workId || foreignPacket
|
|
25
30
|
|| value.unit_id !== packet.unit.id || value.wave !== packet.wave)
|
|
26
31
|
refuse("foreign_result_identity");
|
|
27
32
|
const validate = new Ajv2020({ strict: true, validateFormats: false }).compile(schema);
|
|
@@ -33,14 +38,31 @@ export function validateMemoryReviewWorkResult(input, engine, binding) {
|
|
|
33
38
|
const evidence = (refs) => {
|
|
34
39
|
for (const ref of refs) {
|
|
35
40
|
if (!sources.has(`${memorySourceKey(ref.root, ref.path)}\0${ref.sha256}`))
|
|
36
|
-
|
|
41
|
+
throw new AppError("memory_review_work_result_invalid", "Cite only the retained references assigned to this reviewer", 2, { reason: "unregistered_or_duplicate_evidence", phase: "prepare", effect: "no_effect", recoverable: true,
|
|
42
|
+
unit_id: packet.unit.id, reference: structuredClone(ref),
|
|
43
|
+
hint: "Correct this citation using assigned packet references, or remove the extra citation. Do not change the packet, accepted inputs or assigned scope.",
|
|
44
|
+
result_sha256: createHash("sha256").update(input).digest("hex") });
|
|
37
45
|
}
|
|
38
46
|
};
|
|
39
47
|
const nonblank = (text) => Boolean(text.trim()) && !text.includes("\0");
|
|
40
48
|
if (!nonblank(value.summary))
|
|
41
49
|
refuse("missing_assessment");
|
|
42
50
|
evidence(value.evidence);
|
|
43
|
-
|
|
51
|
+
if ("preservation_invariants" in packet && packet.preservation_invariants) {
|
|
52
|
+
for (const invariant of packet.preservation_invariants) {
|
|
53
|
+
const old = invariant.evidence;
|
|
54
|
+
const refs = old.flatMap(source => {
|
|
55
|
+
const path = source.root === "canon" ? `.memory-bank/${source.path}` : source.path;
|
|
56
|
+
const retained = packet.historical_inputs?.filter(entry => entry.source.path === path && entry.source.sha256 === source.sha256).map(entry => entry.retained) ?? [];
|
|
57
|
+
return retained.length ? retained : packet.unit_inputs.filter(ref => ref.path === path && ref.sha256 === source.sha256);
|
|
58
|
+
});
|
|
59
|
+
if (!refs.length || !value.evidence.some(ref => refs.some(old => old.root === ref.root && old.path === ref.path && old.sha256 === ref.sha256)))
|
|
60
|
+
throw new AppError("memory_review_work_result_invalid", "Examine and cite the assigned old document evidence as well as current outputs", 2, { reason: "preservation_review_without_old_evidence", phase: "prepare", effect: "no_effect", recoverable: true,
|
|
61
|
+
invariant_id: invariant.id, old_references: structuredClone(refs), result_sha256: createHash("sha256").update(input).digest("hex") });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const outputs = packet.unit.artifacts.map(ref => ({ root: ref.root === "run" ? "run" : "workspace",
|
|
65
|
+
path: ref.root === "canon" ? `.memory-bank/${ref.path}` : ref.path, sha256: ref.sha256 }));
|
|
44
66
|
if (!value.evidence.some(ref => outputs.some(output => ref.root === output.root && ref.path === output.path && ref.sha256 === output.sha256))) {
|
|
45
67
|
const corrected = "deleted_references" in packet;
|
|
46
68
|
if (!corrected || packet.schema_id !== "dd-flow/memory-review-work-packet@2" || ![1, 2].includes(packet.wave)
|
|
@@ -8,6 +8,7 @@ import { memorySourceKey } from "./memory-stage-results.js";
|
|
|
8
8
|
import { assertPreparedRunBundleSqlAuthority } from "./runs.js";
|
|
9
9
|
import { reviewSourceHash } from "./review-copy.js";
|
|
10
10
|
import { RetainedExecutionBundle } from "./execution-bundles.js";
|
|
11
|
+
import { memoryReviewViewWithinLimit } from "./memory-review-limits.js";
|
|
11
12
|
const token = Symbol("second-corrected-memory-review-inputs");
|
|
12
13
|
function refuse(reason) {
|
|
13
14
|
throw new AppError("memory_second_corrected_review_input_invalid", "Final re-review lacks settled second repairs and independent first-review custody", 2, { reason, effect: "no_effect" });
|
|
@@ -22,7 +23,7 @@ export function secondCorrectedMemoryReviewAssignments(input) {
|
|
|
22
23
|
refuse("invalid_first_unit_projection");
|
|
23
24
|
const firstAssignments = new Map(input.first.assignments.map(assignment => [assignment.unit.id, assignment]));
|
|
24
25
|
const units = memoryCorrectionCurrentUnits(input.first.unit_inventory, input.first.assignments);
|
|
25
|
-
const assignments = correctedMemoryReviewAssignments({ units, affected: input.affected, files: input.files, repairs: input.repairs });
|
|
26
|
+
const assignments = correctedMemoryReviewAssignments({ units, initialAssignments: input.first.assignments, affected: input.affected, files: input.files, repairs: input.repairs });
|
|
26
27
|
const available = new Map(input.files.map(file => [file.path, file]));
|
|
27
28
|
for (const assignment of assignments) {
|
|
28
29
|
for (const deleted of firstAssignments.get(assignment.unit.id)?.deleted_references ?? []) {
|
|
@@ -121,7 +122,7 @@ export class PreparedSecondCorrectedMemoryReviewInputs {
|
|
|
121
122
|
return prepared;
|
|
122
123
|
}
|
|
123
124
|
static prepareFromBundle(context, input) {
|
|
124
|
-
if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id
|
|
125
|
+
if (!(input.bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(input.bundle.descriptor.descriptor.id))
|
|
125
126
|
refuse("registered_memory_bundle_required");
|
|
126
127
|
const registration = PreparedRetainedSecondMemoryRepairs.prepare(context, input);
|
|
127
128
|
return this.prepare(context, PreparedCompletedMemoryCorrectionWave.prepare(context, registration));
|
|
@@ -158,8 +159,9 @@ function prepareView(context, wave) {
|
|
|
158
159
|
first_review_registration_sha256: receipt.first_review_registration_sha256,
|
|
159
160
|
source_policy: "review-inputs@1", source_sha256: reviewSourceHash(workspace, runInputs.filter(ref => ref.root === "workspace").map(ref => ref.path), first.base),
|
|
160
161
|
base: first.base, run_inputs: runInputs, unit_inventory: units, affected_unit_ids: wave.affectedUnitIds(), assignments,
|
|
162
|
+
...(first.upgrade_baseline ? { upgrade_baseline: structuredClone(first.upgrade_baseline), preservation_invariants: structuredClone(first.preservation_invariants ?? []) } : {}),
|
|
161
163
|
instruction: structuredClone(first.instruction), repairs: repairs.map(repair => ({ work_id: repair.work_id, authority_sha256: repair.authority_sha256, result: repair.reference })) };
|
|
162
|
-
if (
|
|
164
|
+
if (!memoryReviewViewWithinLimit(view))
|
|
163
165
|
refuse("unbounded_second_view");
|
|
164
166
|
return view;
|
|
165
167
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { AppError } from "../shared/errors.js";
|
|
3
3
|
import { PreparedCorrectedMemoryReviewAcceptance } from "./memory-corrected-review-acceptance.js";
|
|
4
|
-
import { validateMemoryReviewCorrectionPlan } from "./memory-review-correction-plan.js";
|
|
4
|
+
import { validateMemoryReviewCorrectionPlan, memoryRepairCanonicalPaths } from "./memory-review-correction-plan.js";
|
|
5
5
|
import { PreparedHistoricalOriginalMemoryReview } from "./memory-historical-original-review.js";
|
|
6
6
|
import { PreparedHistoricalCorrectedMemoryReview } from "./memory-historical-corrected-review.js";
|
|
7
7
|
import { hybridDigest } from "./hybrid-contracts.js";
|
|
@@ -45,6 +45,7 @@ export class PreparedMemorySecondCorrectionPlan {
|
|
|
45
45
|
const units = view.unit_inventory.map(unit => assignments.get(unit.id) ?? unit);
|
|
46
46
|
const bundle = registration.inputs().bundle();
|
|
47
47
|
const value = validateMemoryReviewCorrectionPlan(bytes, bundle.engine(), { runId: view.scope.run_id, wave: 2,
|
|
48
|
+
canonicalPaths: memoryRepairCanonicalPaths(context, bundle),
|
|
48
49
|
reviewSha256: review.sha256, units, findings: projection.findings });
|
|
49
50
|
for (const work of value.works)
|
|
50
51
|
bundle.execution.work("review", work.profile_id ?? undefined);
|
|
@@ -11,7 +11,7 @@ import { readDescriptorCoordinatorSession } from "./descriptor-coordinator-sessi
|
|
|
11
11
|
import { reviewSourceHash } from "./review-copy.js";
|
|
12
12
|
import { runtimeHarness } from "./execution-policy.js";
|
|
13
13
|
import { appendAudit } from "./audit.js";
|
|
14
|
-
import { memoryRepairCurrentReferences, validateMemoryRepairWorkResult } from "./memory-repair-work-results.js";
|
|
14
|
+
import { isCompletedMemoryRepairClaim, memoryRepairCurrentReferences, validateMemoryRepairWorkResult } from "./memory-repair-work-results.js";
|
|
15
15
|
import { RetainedMemoryRepairPublicationPlan } from "./memory-repair-publication-plan.js";
|
|
16
16
|
import { retainedMemoryRepairPublicationPlans } from "./memory-repair-publication-intent.js";
|
|
17
17
|
import { deriveRetainedMemoryRepairViews } from "./memory-repair-publication.js";
|
|
@@ -97,7 +97,7 @@ export class PreparedSecondMemoryRepairLaunch {
|
|
|
97
97
|
static #prepare(context, input, workSessionId) {
|
|
98
98
|
if (!PreparedRetainedSecondMemoryRepairs.isPrepared(input.registration) || !PreparedRetainedSecondMemoryBaseline.isPrepared(input.baseline))
|
|
99
99
|
refuse("retained_second_owners_required");
|
|
100
|
-
if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id
|
|
100
|
+
if (!(input.bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(input.bundle.descriptor.descriptor.id))
|
|
101
101
|
refuse("registered_memory_bundle_required");
|
|
102
102
|
if (context.db.isOwnedWriteTransaction?.())
|
|
103
103
|
refuse("preparation_outside_writer_required");
|
|
@@ -204,7 +204,7 @@ export class PreparedSecondMemoryRepairLaunch {
|
|
|
204
204
|
* settled peer views and partial publication recovery require other owners. */
|
|
205
205
|
reservePublication(context, bytes) {
|
|
206
206
|
const observed = this.observeOutput(context, bytes), receipt = this.#baseline.receipt();
|
|
207
|
-
if (observed.result
|
|
207
|
+
if (!isCompletedMemoryRepairClaim(observed.result))
|
|
208
208
|
refuse("accepted_private_output_required");
|
|
209
209
|
const before = this.#baseline.baseline(), exported = this.#baseline.exportedBaseline();
|
|
210
210
|
this.#workspace.verifySelectedSourceInputs(receipt.workspace_root, this.#baseline.copyInput(), before);
|
|
@@ -294,7 +294,7 @@ export class PreparedSecondMemoryRepairLaunch {
|
|
|
294
294
|
const packet = assigned.payload.memory_repair;
|
|
295
295
|
const result = validateMemoryRepairWorkResult(bytes, this.#bundle.engine(), { workId: receipt.work_id, packet,
|
|
296
296
|
effectiveInputs: memoryRepairCurrentReferences(packet, this.#workspace) });
|
|
297
|
-
if (result
|
|
297
|
+
if (!isCompletedMemoryRepairClaim(result))
|
|
298
298
|
refuse("accepted_reserved_result_required");
|
|
299
299
|
const views = deriveRetainedMemoryRepairViews(this.#baseline.baseline(), this.#baseline.exportedBaseline(), plan, result, privatePlan);
|
|
300
300
|
const outputSha256 = hybridDigest({ input: this.input(), start_receipt_sha256: value.start_receipt_sha256,
|
|
@@ -56,7 +56,7 @@ export class PreparedSecondMemoryRepairSource {
|
|
|
56
56
|
static #prepare(context, input, current) {
|
|
57
57
|
if (!PreparedRetainedSecondMemoryRepairs.isPrepared(input.registration))
|
|
58
58
|
refuse("retained_second_registration_required");
|
|
59
|
-
if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id
|
|
59
|
+
if (!(input.bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(input.bundle.descriptor.descriptor.id))
|
|
60
60
|
refuse("registered_memory_bundle_required");
|
|
61
61
|
if (context.db.isOwnedWriteTransaction?.())
|
|
62
62
|
refuse("preparation_outside_writer_required");
|