@deksden-com/dd-flow-cli 0.9.0-beta.143 → 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 +65 -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 +74 -9
- 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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AppError } from "../shared/errors.js";
|
|
2
2
|
import { hybridDigest } from "./hybrid-contracts.js";
|
|
3
3
|
import { PreparedCompletedMemoryCorrectionWave } from "./memory-completed-correction-wave.js";
|
|
4
|
+
import { isCompletedMemoryRepairClaim } from "./memory-repair-work-results.js";
|
|
4
5
|
import { ObservedMemorySources } from "./memory-source-observations.js";
|
|
5
6
|
import { memorySourceKey } from "./memory-stage-results.js";
|
|
6
7
|
import { assertPreparedRunBundleSqlAuthority } from "./runs.js";
|
|
@@ -9,6 +10,7 @@ import { RetainedExecutionBundle } from "./execution-bundles.js";
|
|
|
9
10
|
import { PreparedRetainedMemoryReviewAuthority } from "./memory-retained-review-authority.js";
|
|
10
11
|
import { PreparedRetainedMemoryReviewResults } from "./memory-retained-review-results.js";
|
|
11
12
|
import { PreparedRegisteredMemoryCorrections } from "./memory-repair-registration.js";
|
|
13
|
+
import { memoryReviewViewWithinLimit } from "./memory-review-limits.js";
|
|
12
14
|
const token = Symbol("corrected-memory-review-inputs");
|
|
13
15
|
function refuse(reason) {
|
|
14
16
|
throw new AppError("memory_corrected_review_input_invalid", "Re-review inputs lack settled corrections and current source custody", 2, { reason, effect: "no_effect" });
|
|
@@ -46,9 +48,8 @@ export function correctedMemoryReviewAssignments(input) {
|
|
|
46
48
|
const finalProof = new Map();
|
|
47
49
|
for (const repair of input.repairs) {
|
|
48
50
|
reference(repair.reference.path, repair.reference.sha256, "run");
|
|
49
|
-
if (repair.result
|
|
50
|
-
|| repair.unit_ids.some((id) => !input.units.some(unit => unit.id === id && unit.applicability === "applicable"))
|
|
51
|
-
|| !Array.isArray(repair.result.changes) || !repair.result.changes.length)
|
|
51
|
+
if (!isCompletedMemoryRepairClaim(repair.result) || !Array.isArray(repair.unit_ids) || !repair.unit_ids.length
|
|
52
|
+
|| repair.unit_ids.some((id) => !input.units.some(unit => unit.id === id && unit.applicability === "applicable")))
|
|
52
53
|
refuse("invalid_repair_projection");
|
|
53
54
|
for (const change of repair.result.changes) {
|
|
54
55
|
reference(change.path, change.after_sha256 ?? change.before_sha256);
|
|
@@ -97,6 +98,9 @@ export function correctedMemoryReviewAssignments(input) {
|
|
|
97
98
|
unit.artifacts.push({ ...current });
|
|
98
99
|
}
|
|
99
100
|
const inputs = new Map();
|
|
101
|
+
for (const ref of input.initialAssignments?.find(item => item.unit.id === original.id)?.inputs ?? [])
|
|
102
|
+
if (ref.root === "run" && /^upgrade-baseline-[a-f0-9]{64}\.bin$/.test(ref.path))
|
|
103
|
+
inputs.set(memorySourceKey(ref.root, ref.path), { ...ref });
|
|
100
104
|
for (const ref of [...unit.evidence, ...unit.artifacts, ...input.repairs.map(repair => reference(repair.reference.path, repair.reference.sha256, "run"))]) {
|
|
101
105
|
const physical = reference(ref.root === "canon" ? `.memory-bank/${ref.path}` : ref.path, ref.sha256, ref.root === "run" ? "run" : "workspace");
|
|
102
106
|
const key = memorySourceKey(physical.root, physical.path), prior = inputs.get(key);
|
|
@@ -151,7 +155,7 @@ export class PreparedCorrectedMemoryReviewInputs {
|
|
|
151
155
|
return prepared;
|
|
152
156
|
}
|
|
153
157
|
static prepareFromBundle(context, input) {
|
|
154
|
-
if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id
|
|
158
|
+
if (!(input.bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(input.bundle.descriptor.descriptor.id))
|
|
155
159
|
refuse("registered_memory_bundle_required");
|
|
156
160
|
const original = PreparedRetainedMemoryReviewAuthority.prepare(context, input.scope, input.bundle);
|
|
157
161
|
const review = PreparedRetainedMemoryReviewResults.prepare(context, original);
|
|
@@ -203,8 +207,9 @@ function prepareView(wave) {
|
|
|
203
207
|
completed_correction_sha256: wave.sha256, original_review_sha256: review.sha256,
|
|
204
208
|
source_policy: "review-inputs@1", source_sha256: source, base: original.base, run_inputs: runInputs,
|
|
205
209
|
unit_inventory: structuredClone(original.unit_inventory), affected_unit_ids: wave.affectedUnitIds(), assignments,
|
|
210
|
+
...(original.upgrade_baseline ? { upgrade_baseline: structuredClone(original.upgrade_baseline), preservation_invariants: structuredClone(original.preservation_invariants ?? []) } : {}),
|
|
206
211
|
instruction: structuredClone(original.instruction), repairs: repairs.map(repair => ({ work_id: repair.work_id, authority_sha256: repair.authority_sha256, result: repair.reference })) };
|
|
207
|
-
if (
|
|
212
|
+
if (!memoryReviewViewWithinLimit(view))
|
|
208
213
|
refuse("unbounded_corrected_view");
|
|
209
214
|
return view;
|
|
210
215
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertMemorySqlCustody } from "./memory-custody-snapshot.js";
|
|
1
2
|
import { AppError } from "../shared/errors.js";
|
|
2
3
|
import { appendAudit } from "./audit.js";
|
|
3
4
|
import { hybridDigest } from "./hybrid-contracts.js";
|
|
@@ -81,7 +82,7 @@ export class PreparedMemoryCorrectedReviewReceipt {
|
|
|
81
82
|
refuse("receipt_readback_failed");
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
|
-
function acceptedReceipt(context, scope) {
|
|
85
|
+
function acceptedReceipt(context, scope, flowId) {
|
|
85
86
|
const data = readAcceptedStageData(context, { ...scope, stage: "review" }), rows = records(context, scope);
|
|
86
87
|
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 2 * 1024 * 1024)
|
|
87
88
|
refuse("accepted_receipt_missing");
|
|
@@ -99,7 +100,7 @@ function acceptedReceipt(context, scope) {
|
|
|
99
100
|
|| !/^[a-f0-9]{64}$/.test(retained.first_review_proof_sha256)))
|
|
100
101
|
|| typeof retained.corrected_input_sha256 !== "string" || !/^[a-f0-9]{64}$/.test(retained.corrected_input_sha256)
|
|
101
102
|
|| typeof retained.check_receipt_sha256 !== "string" || !/^[a-f0-9]{64}$/.test(retained.check_receipt_sha256)
|
|
102
|
-
|| data.data_schema_id !== "dd-flow/mb-init-review-result@1" || retained.result_sha256 !== data.result.sha256
|
|
103
|
+
|| data.data_schema_id !== (flowId === "mb-upgrade" ? "dd-flow/mb-upgrade-stage-result@1" : "dd-flow/mb-init-review-result@1") || retained.result_sha256 !== data.result.sha256
|
|
103
104
|
|| retained.input_sha256 !== data.input_sha256)
|
|
104
105
|
refuse("accepted_receipt_changed");
|
|
105
106
|
return { data, retained, authority: hybridDigest({ data: data.authority_sha256, receipt: retained }) };
|
|
@@ -109,24 +110,27 @@ function acceptedReceipt(context, scope) {
|
|
|
109
110
|
* commit: generic settlement restores it; reviewers/checks/repairs may not be
|
|
110
111
|
* substituted or re-admitted from today's project policy or documents. */
|
|
111
112
|
export class PreparedAcceptedMemoryCorrectedReview {
|
|
113
|
+
#custodyKey = {};
|
|
112
114
|
#scope;
|
|
113
115
|
#authority;
|
|
114
116
|
#history;
|
|
115
|
-
|
|
117
|
+
#flowId;
|
|
118
|
+
constructor(key, scope, authority, history, flowId) {
|
|
116
119
|
if (key !== token)
|
|
117
120
|
refuse("receipt_token_required");
|
|
118
121
|
this.#scope = { ...scope };
|
|
119
122
|
this.#authority = authority;
|
|
120
123
|
this.#history = history;
|
|
124
|
+
this.#flowId = flowId;
|
|
121
125
|
Object.freeze(this);
|
|
122
126
|
}
|
|
123
127
|
static prepare(context, input) {
|
|
124
|
-
if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id
|
|
128
|
+
if (!(input.bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(input.bundle.descriptor.descriptor.id)
|
|
125
129
|
|| !(input.bytes instanceof Uint8Array) || !input.bytes.length || input.bytes.length > 1024 * 1024)
|
|
126
130
|
refuse("registered_memory_result_required");
|
|
127
131
|
if (context.db.isOwnedWriteTransaction?.())
|
|
128
132
|
refuse("preparation_outside_writer_required");
|
|
129
|
-
const accepted = context.db.readSnapshot(() => acceptedReceipt(context, input.scope));
|
|
133
|
+
const accepted = context.db.readSnapshot(() => acceptedReceipt(context, input.scope, input.bundle.descriptor.descriptor.id));
|
|
130
134
|
if (!accepted.data.bytes.equals(Buffer.from(input.bytes)))
|
|
131
135
|
refuse("accepted_result_bytes_changed");
|
|
132
136
|
const hashes = { correctedInputSha256: accepted.retained.corrected_input_sha256, checkReceiptSha256: accepted.retained.check_receipt_sha256 };
|
|
@@ -151,20 +155,24 @@ export class PreparedAcceptedMemoryCorrectedReview {
|
|
|
151
155
|
const schema = JSON.parse(input.bundle.descriptor.stageBlob("review", "result_schema").toString("utf8"));
|
|
152
156
|
if (!new Ajv2020({ strict: true, strictRequired: false, validateFormats: false }).compile(schema)(value))
|
|
153
157
|
refuse("accepted_result_schema_changed");
|
|
154
|
-
const prepared = new PreparedAcceptedMemoryCorrectedReview(token, input.scope, accepted.authority, history);
|
|
158
|
+
const prepared = new PreparedAcceptedMemoryCorrectedReview(token, input.scope, accepted.authority, history, input.bundle.descriptor.descriptor.id);
|
|
155
159
|
prepared.revalidate(context);
|
|
156
160
|
return prepared;
|
|
157
161
|
}
|
|
158
162
|
assertCustody(context) {
|
|
159
|
-
this.#history
|
|
160
|
-
|
|
161
|
-
|
|
163
|
+
const history = this.#history;
|
|
164
|
+
assertMemorySqlCustody(context, this.#custodyKey, () => {
|
|
165
|
+
history.assertCustody(context);
|
|
166
|
+
if (acceptedReceipt(context, this.#scope, this.#flowId).authority !== this.#authority)
|
|
167
|
+
refuse("accepted_review_custody_changed");
|
|
168
|
+
});
|
|
162
169
|
}
|
|
163
170
|
/** Final wave inputs selected by the independently accepted receipt. */
|
|
164
171
|
reviewedSources(context) {
|
|
165
172
|
this.assertCustody(context);
|
|
166
173
|
return this.#history.retainedInputView().run_inputs;
|
|
167
174
|
}
|
|
175
|
+
settledDocumentBaseline(context) { this.assertCustody(context); return this.#history.settledDocumentBaseline(); }
|
|
168
176
|
finalChecks(context) { this.assertCustody(context); return this.#history.finalChecks(context); }
|
|
169
177
|
revalidate(context) { this.#history.revalidate(context); this.assertCustody(context); }
|
|
170
178
|
}
|
|
@@ -6,6 +6,7 @@ import { isMemoryCorrectionInputOwner } from "./memory-correction-input-owner.js
|
|
|
6
6
|
import { PreparedMemoryCorrectionCheckReceipt } from "./memory-correction-check-receipt.js";
|
|
7
7
|
import { memoryCorrectedReviewBatch } from "./memory-corrected-review-batch.js";
|
|
8
8
|
import { addWorkBatch, prepareWorkBatch, readWorkBatchCustody } from "./work-registry.js";
|
|
9
|
+
import { memoryReviewRegistrationByteLimit } from "./memory-review-limits.js";
|
|
9
10
|
const token = Symbol("registered-corrected-memory-review");
|
|
10
11
|
const event = "memory.corrected_review_registration";
|
|
11
12
|
function refuse(reason) {
|
|
@@ -40,7 +41,7 @@ function readRetainedRegistration(context, scope, inputSha256, checkReceiptSha25
|
|
|
40
41
|
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]);
|
|
41
42
|
if (!rows.length)
|
|
42
43
|
return null;
|
|
43
|
-
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) >
|
|
44
|
+
if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > memoryReviewRegistrationByteLimit)
|
|
44
45
|
refuse("ambiguous_or_unbounded_registration");
|
|
45
46
|
let receipt;
|
|
46
47
|
try {
|
|
@@ -171,7 +172,7 @@ export function registerCorrectedMemoryReview(context, inputs, checks) {
|
|
|
171
172
|
refuse("review_registration_missing");
|
|
172
173
|
const receipt = { schema_id: "dd-flow/memory-corrected-review-registration@1", run_id: scope.run_id, scope: view.scope, wave: view.wave,
|
|
173
174
|
input_sha256: inputs.sha256, view, check_receipt_sha256: checks.sha256, batch_sha256: hybridDigest(batch.works), work_ids: ids };
|
|
174
|
-
if (Buffer.byteLength(JSON.stringify(receipt)) >
|
|
175
|
+
if (Buffer.byteLength(JSON.stringify(receipt)) > memoryReviewRegistrationByteLimit)
|
|
175
176
|
refuse("unbounded_registration");
|
|
176
177
|
appendAudit(context, { projectId: scope.project_id, eventType: event, payload: receipt });
|
|
177
178
|
}
|
|
@@ -65,7 +65,7 @@ export class PreparedMemoryCorrectionCheckReceipt {
|
|
|
65
65
|
evidence.assertOwner({ projectId: view.scope.project_id, runId: view.scope.run_id, scope: "aggregate" });
|
|
66
66
|
const receipt = { schema_id: "dd-flow/memory-correction-checks@1", project_id: view.scope.project_id, run_id: view.scope.run_id,
|
|
67
67
|
wave: view.wave, review_input_sha256: view.scope.input_sha256, corrected_input_sha256: corrected.sha256,
|
|
68
|
-
completed_correction_sha256: view.completed_correction_sha256, profile_sha256:
|
|
68
|
+
completed_correction_sha256: view.completed_correction_sha256, profile_sha256: policy.profileHash(),
|
|
69
69
|
declarations_sha256: hybridDigest(policy.declarations()), checks: evidence.retainedReferences(context) };
|
|
70
70
|
if (!receipt.checks.length || receipt.checks.length > 4096 || Buffer.byteLength(JSON.stringify(receipt)) > 2 * 1024 * 1024)
|
|
71
71
|
refuse("unbounded_check_receipt");
|
|
@@ -81,7 +81,8 @@ export class PreparedMemoryCorrectionCheckReceipt {
|
|
|
81
81
|
refuse("prepared_check_owners_required");
|
|
82
82
|
if (context.db.isOwnedWriteTransaction?.())
|
|
83
83
|
refuse("preparation_outside_writer_required");
|
|
84
|
-
|
|
84
|
+
const existing = context.db.readSnapshot(() => stored(context, corrected));
|
|
85
|
+
if (!existing) {
|
|
85
86
|
const view = corrected.value(), projectRoot = corrected.bundle().execution.snapshot().scope.projectRoot;
|
|
86
87
|
const args = ["--run", view.scope.run_id, "--project-root", projectRoot, "--wave", String(view.wave), "--json"];
|
|
87
88
|
throw new AppError("memory_correction_checks_invalid", "Correction checks have not been registered for the settled corrected view", 2, { reason: "registered_check_receipt_required", phase: "prepare", effect: "no_effect", recoverable: true,
|
|
@@ -90,7 +91,22 @@ export class PreparedMemoryCorrectionCheckReceipt {
|
|
|
90
91
|
const bundle = corrected.bundle(), scope = corrected.value().scope;
|
|
91
92
|
const policy = PreparedMemoryVerificationChecks.prepare(context, { projectId: scope.project_id, runId: scope.run_id,
|
|
92
93
|
execution: bundle.execution, flow: bundle.descriptor, corrected });
|
|
93
|
-
|
|
94
|
+
// Registered execution belongs to its original environment, not the
|
|
95
|
+
// controller/reviewer's current shell. Keep exact current document and
|
|
96
|
+
// policy custody, then restore the sealed execution instead of selecting
|
|
97
|
+
// fresh evidence using the observer's environment.
|
|
98
|
+
const view = corrected.value(), receipt = historicalReceipt(context, { projectId: scope.project_id, runId: scope.run_id,
|
|
99
|
+
wave: view.wave, receiptSha256: hybridDigest(existing), correctedInputSha256: corrected.sha256 });
|
|
100
|
+
const expected = { schema_id: "dd-flow/memory-correction-checks@1", project_id: scope.project_id, run_id: scope.run_id,
|
|
101
|
+
wave: view.wave, review_input_sha256: scope.input_sha256, corrected_input_sha256: corrected.sha256,
|
|
102
|
+
completed_correction_sha256: view.completed_correction_sha256, profile_sha256: policy.profileHash(),
|
|
103
|
+
declarations_sha256: hybridDigest(policy.declarations()), checks: receipt.checks };
|
|
104
|
+
if (hybridDigest(receipt) !== hybridDigest(expected))
|
|
105
|
+
refuse("registered_check_receipt_changed");
|
|
106
|
+
const evidence = PreparedRetainedCheckEvidence.prepare(context, { projectId: scope.project_id, runId: scope.run_id, references: receipt.checks });
|
|
107
|
+
const prepared = new PreparedMemoryCorrectionCheckReceipt(token, corrected, policy, evidence, receipt, true);
|
|
108
|
+
prepared.revalidate(context);
|
|
109
|
+
return prepared;
|
|
94
110
|
}
|
|
95
111
|
value() {
|
|
96
112
|
return structuredClone(this.#receipt);
|
|
@@ -111,7 +127,7 @@ export class PreparedMemoryCorrectionCheckReceipt {
|
|
|
111
127
|
const existing = stored(context, this.#corrected);
|
|
112
128
|
if ((this.#registered && !existing) || (existing && hybridDigest(existing) !== this.sha256))
|
|
113
129
|
refuse("registered_check_receipt_changed");
|
|
114
|
-
if (hybridDigest(this.#evidence.retainedReferences(context)) !== hybridDigest(this.#receipt.checks))
|
|
130
|
+
if ("retainedReferences" in this.#evidence && hybridDigest(this.#evidence.retainedReferences(context)) !== hybridDigest(this.#receipt.checks))
|
|
115
131
|
refuse("selected_check_evidence_changed");
|
|
116
132
|
}
|
|
117
133
|
revalidate(context) {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { AppError } from "../shared/errors.js";
|
|
2
|
+
const snapshots = new WeakMap();
|
|
3
|
+
function synchronous(read) {
|
|
4
|
+
const value = read();
|
|
5
|
+
if (value && typeof value.then === "function") {
|
|
6
|
+
void Promise.resolve(value).catch(() => { });
|
|
7
|
+
throw new AppError("read_snapshot_async", "Memory custody traversal must be synchronous", 1);
|
|
8
|
+
}
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
export function withMemoryCustodySnapshot(context, read) {
|
|
12
|
+
if (snapshots.has(context))
|
|
13
|
+
return synchronous(read);
|
|
14
|
+
return context.db.readSnapshot(() => {
|
|
15
|
+
snapshots.set(context, new Set());
|
|
16
|
+
try {
|
|
17
|
+
return synchronous(read);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
snapshots.delete(context);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/** Only SQL custody may share a completed proof within this synchronous
|
|
25
|
+
* snapshot. Physical revalidation stays outside this memo, and the next
|
|
26
|
+
* traversal always rereads SQL. Failed checks never become reusable proof.
|
|
27
|
+
* Prepared owners supply private keys, never their externally visible object. */
|
|
28
|
+
export function assertMemorySqlCustody(context, owner, validate) {
|
|
29
|
+
withMemoryCustodySnapshot(context, () => {
|
|
30
|
+
const checked = snapshots.get(context);
|
|
31
|
+
if (checked.has(owner))
|
|
32
|
+
return;
|
|
33
|
+
synchronous(validate);
|
|
34
|
+
checked.add(owner);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -13,14 +13,23 @@ import { ObservedMemorySources } from "./memory-source-observations.js";
|
|
|
13
13
|
import { memorySourceKey, PreparedMemoryStageResult } from "./memory-stage-results.js";
|
|
14
14
|
import { PreparedDescriptorStageSettlement } from "./descriptor-stage-settlement.js";
|
|
15
15
|
import { assertPreparedRunBundleSqlAuthority } from "./runs.js";
|
|
16
|
-
import { readMemoryInitBootstrapReadiness } from "./memory-init-bootstrap-readiness.js";
|
|
17
|
-
import { readMemoryInitGitPolicy } from "./memory-init-git-policy.js";
|
|
18
16
|
import { reviewedMemoryGitFiles } from "./memory-git-integration.js";
|
|
17
|
+
import { readMemoryFinishGitSelection, readMemoryUpgradeFinishInventory } from "./memory-finish-integration.js";
|
|
19
18
|
const token = Symbol("memory-finish-evidence"), event = "memory.finish_evidence";
|
|
20
19
|
const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
|
21
20
|
function refuse(reason) {
|
|
22
21
|
throw new AppError("memory_finish_evidence_invalid", "Finish evidence lacks independently prepared acceptance custody", 2, { reason, effect: "no_effect" });
|
|
23
22
|
}
|
|
23
|
+
export function parseMemoryFinishProposal(bytes) {
|
|
24
|
+
if (!(bytes instanceof Uint8Array) || !bytes.length || bytes.length > 1024 * 1024)
|
|
25
|
+
refuse("invalid_result_bytes");
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
throw new AppError("memory_finish_evidence_invalid", "Finish proposal must be valid UTF-8 JSON. Correct only the proposal syntax, then use retry_command; do not rerun integration or settled checks", 2, { reason: "invalid_result_json", phase: "prepare", effect: "no_effect", recoverable: true, result_sha256: hash(bytes) });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
24
33
|
/** Terminal inventory and receipts belong to the accepted review/evidence
|
|
25
34
|
* owners. Optional echoes cannot introduce new references or semantic claims. */
|
|
26
35
|
export function projectMemoryFinishResult(value, owner, resultSha256) {
|
|
@@ -77,11 +86,24 @@ function acceptance(context, scope) {
|
|
|
77
86
|
refuse("ambiguous_finish_acceptance");
|
|
78
87
|
return rows[0] ? JSON.parse(rows[0].payload_json) : null;
|
|
79
88
|
}
|
|
89
|
+
/** Terminal parsing inherits the accepted scope and named old-data criteria;
|
|
90
|
+
* no fresh version inference or mutable project sources are consulted. */
|
|
91
|
+
function upgradeBinding(context, scope, bundle) {
|
|
92
|
+
if (bundle.descriptor.descriptor.id !== "mb-upgrade")
|
|
93
|
+
refuse("upgrade_preservation_binding_changed");
|
|
94
|
+
const preflight = readAcceptedStageData(context, { ...scope, stage: "preflight" });
|
|
95
|
+
const diff = readAcceptedStageData(context, { ...scope, stage: "diff-analysis" });
|
|
96
|
+
const preservationInvariants = JSON.parse(preflight.bytes.toString("utf8")).details.preservation_invariants;
|
|
97
|
+
const minimumMode = JSON.parse(diff.bytes.toString("utf8")).details.mode;
|
|
98
|
+
if (!["patch", "targeted_minor", "full_migration"].includes(minimumMode) || !Array.isArray(preservationInvariants))
|
|
99
|
+
refuse("upgrade_preservation_binding_changed");
|
|
100
|
+
return { minimumMode, preservationInvariants };
|
|
101
|
+
}
|
|
80
102
|
/** SQL-only historical byte/projection custody. Callers must independently
|
|
81
103
|
* prepare the genuine accepted review owner outside their writer. This does
|
|
82
104
|
* not re-observe today's integration checkout or grant RUN closure. */
|
|
83
105
|
export function readAcceptedMemoryFinishEvidence(context, input) {
|
|
84
|
-
if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id
|
|
106
|
+
if (!(input.bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(input.bundle.descriptor.descriptor.id)
|
|
85
107
|
|| !PreparedMemoryFinishReview.isPrepared(input.review))
|
|
86
108
|
refuse("registered_memory_review_required");
|
|
87
109
|
const scope = { ...input.scope, stage: "finish" };
|
|
@@ -96,7 +118,7 @@ export function readAcceptedMemoryFinishEvidence(context, input) {
|
|
|
96
118
|
|| evidence.attempt !== stage.attempt || evidence.input_sha256 !== stage.input_sha256
|
|
97
119
|
|| evidence.bundle_sha256 !== input.bundle.sha256 || evidence.review_sha256 !== reviewData.result.sha256
|
|
98
120
|
|| !input.review.bytes().equals(reviewData.bytes)
|
|
99
|
-
|| data.data_schema_id !== "dd-flow/mb-init-finish-result@1" || data.input_sha256 !== stage.input_sha256
|
|
121
|
+
|| data.data_schema_id !== (input.bundle.descriptor.descriptor.id === "mb-upgrade" ? "dd-flow/mb-upgrade-stage-result@1" : "dd-flow/mb-init-finish-result@1") || data.input_sha256 !== stage.input_sha256
|
|
100
122
|
|| hybridDigest(evidence.checks) !== hybridDigest(input.review.finalChecks(context)))
|
|
101
123
|
refuse("accepted_finish_evidence_changed");
|
|
102
124
|
const expectedAcceptance = { schema_id: "dd-flow/memory-finish-acceptance@1", project_id: scope.projectId, run_id: scope.runId,
|
|
@@ -134,16 +156,18 @@ export function readAcceptedMemoryFinishEvidence(context, input) {
|
|
|
134
156
|
refuse("historical_evidence_projection_changed");
|
|
135
157
|
const frozen = input.bundle.execution.snapshot().scope;
|
|
136
158
|
const request = { requestId: frozen.requestId, projectRoot: frozen.projectRoot, workspaceRoot: frozen.workspace };
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
||
|
|
141
|
-
|| policy.target_sha256 !== hybridDigest(bootstrap.authority.binding.target)
|
|
142
|
-
|| readiness.value.bootstrap_authority_sha256 !== hybridDigest(bootstrap.authority)
|
|
143
|
-
|| readiness.value.pack_sha256 !== bootstrap.authority.binding.pack_sha256)
|
|
159
|
+
const selected = readMemoryFinishGitSelection(context, scope, input.bundle), policy = selected.policy;
|
|
160
|
+
const packSha256 = selected.kind === "init" ? selected.readiness.authority.binding.pack_sha256 : selected.readiness.authority.receipt.upgrade_target.pack_sha256;
|
|
161
|
+
if (readiness.value.bootstrap_authority_sha256 !== hybridDigest(selected.readiness.authority)
|
|
162
|
+
|| readiness.value.pack_sha256 !== packSha256)
|
|
144
163
|
refuse("historical_terminal_bootstrap_policy_changed");
|
|
145
164
|
const integrated = integration.value;
|
|
146
|
-
const
|
|
165
|
+
const upgrade = selected.kind === "upgrade" ? readMemoryUpgradeFinishInventory(context, scope, input.bundle, input.review) : null;
|
|
166
|
+
const reviewedFiles = upgrade?.references ?? reviewedMemoryGitFiles(input.review.reviewedSources(context));
|
|
167
|
+
if (upgrade && (integrated.upgrade_inventory_sha256 !== hybridDigest(upgrade)
|
|
168
|
+
|| integrated.removed_files_sha256 !== (upgrade.removals.length ? hybridDigest(upgrade.removals) : undefined)
|
|
169
|
+
|| hybridDigest([readiness.value.migration_record]) !== hybridDigest([upgrade.migrationRecord])))
|
|
170
|
+
refuse("historical_upgrade_inventory_changed");
|
|
147
171
|
if (integrated.schema_id !== "dd-flow/memory-git-integration-observation@1"
|
|
148
172
|
|| integrated.project_root !== request.projectRoot || integrated.workspace_root !== request.workspaceRoot
|
|
149
173
|
|| integrated.repository !== policy.repository || integrated.workspace_branch !== policy.workspace_branch
|
|
@@ -167,11 +191,13 @@ export function readAcceptedMemoryFinishEvidence(context, input) {
|
|
|
167
191
|
runId: scope.runId, stage: "finish", inputSha256: stage.input_sha256,
|
|
168
192
|
predecessors: [{ stage: "review", result: reviewData.result, input_sha256: reviewData.input_sha256 }],
|
|
169
193
|
unitIds: reviewed.units.map((unit) => unit.id), sources,
|
|
194
|
+
...(upgrade ? { upgrade: upgradeBinding(context, scope, input.bundle) } : {}),
|
|
170
195
|
historicalEvidence: new Set(reviewed.units.flatMap((unit) => unit.evidence.map(ref => `${memorySourceKey(ref.root, ref.path)}\0${ref.sha256}`)))
|
|
171
196
|
});
|
|
172
197
|
const value = result.value(), references = { coverage: evidence.coverage,
|
|
173
198
|
checks: evidence.checks.map(({ path, sha256 }) => ({ path, sha256 })),
|
|
174
|
-
integration: evidence.integration, normal_flow_readiness: evidence.normal_flow_readiness
|
|
199
|
+
integration: evidence.integration, normal_flow_readiness: evidence.normal_flow_readiness,
|
|
200
|
+
...(upgrade ? { migration_record: upgrade.migrationRecord } : {}) };
|
|
175
201
|
if (value.outcome !== "accepted" || hybridDigest(value.units) !== hybridDigest(reviewed.units)
|
|
176
202
|
|| hybridDigest(value.findings) !== hybridDigest(reviewed.findings) || hybridDigest(value.details) !== hybridDigest(references))
|
|
177
203
|
refuse("historical_finish_result_projection_changed");
|
|
@@ -209,7 +235,7 @@ export class PreparedMemoryFinishEvidence {
|
|
|
209
235
|
Object.freeze(this);
|
|
210
236
|
}
|
|
211
237
|
static prepare(context, input) {
|
|
212
|
-
if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id
|
|
238
|
+
if (!(input.bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(input.bundle.descriptor.descriptor.id))
|
|
213
239
|
refuse("registered_memory_bundle_required");
|
|
214
240
|
if (context.db.isOwnedWriteTransaction?.())
|
|
215
241
|
refuse("preparation_outside_writer_required");
|
|
@@ -258,7 +284,8 @@ export class PreparedMemoryFinishEvidence {
|
|
|
258
284
|
references() {
|
|
259
285
|
const value = this.#receipt;
|
|
260
286
|
return { coverage: { ...value.coverage }, checks: value.checks.map(({ path, sha256 }) => ({ path, sha256 })),
|
|
261
|
-
integration: { ...value.integration }, normal_flow_readiness: { ...value.normal_flow_readiness }
|
|
287
|
+
integration: { ...value.integration }, normal_flow_readiness: { ...value.normal_flow_readiness },
|
|
288
|
+
...(this.#bundle.descriptor.descriptor.id === "mb-upgrade" ? { migration_record: this.#readiness.value().migration_record } : {}) };
|
|
262
289
|
}
|
|
263
290
|
/** Fresh terminal result preparation, never a historical replay reader.
|
|
264
291
|
* The proposal cannot replace accepted review coverage or CLI evidence. */
|
|
@@ -274,18 +301,13 @@ export class PreparedMemoryFinishEvidence {
|
|
|
274
301
|
if (typeof review.input_sha256 !== "string")
|
|
275
302
|
refuse("accepted_review_input_missing");
|
|
276
303
|
const reviewed = JSON.parse(this.#review.bytes().toString("utf8"));
|
|
277
|
-
|
|
278
|
-
try {
|
|
279
|
-
proposal = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
280
|
-
}
|
|
281
|
-
catch {
|
|
282
|
-
refuse("invalid_result_bytes");
|
|
283
|
-
}
|
|
304
|
+
const proposal = parseMemoryFinishProposal(bytes);
|
|
284
305
|
const canonical = projectMemoryFinishResult(proposal, { units: reviewed.units, findings: reviewed.findings, details: this.references() }, hash(bytes));
|
|
285
306
|
const result = PreparedMemoryStageResult.prepare(Buffer.from(JSON.stringify(canonical)), bundle.descriptor, {
|
|
286
307
|
runId: this.#scope.runId, stage: "finish", inputSha256: this.#input.inputSha256,
|
|
287
308
|
predecessors: [{ stage: "review", result: review.result, input_sha256: review.input_sha256 }],
|
|
288
309
|
unitIds: reviewed.units.map((unit) => unit.id), sources: sources.hashes(),
|
|
310
|
+
...(bundle.descriptor.descriptor.id === "mb-upgrade" ? { upgrade: upgradeBinding(context, this.#scope, bundle) } : {}),
|
|
289
311
|
historicalEvidence: new Set(reviewed.units.flatMap((unit) => unit.evidence.map(ref => `${memorySourceKey(ref.root, ref.path)}\0${ref.sha256}`)))
|
|
290
312
|
});
|
|
291
313
|
const value = result.value();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertMemorySqlCustody, withMemoryCustodySnapshot } from "./memory-custody-snapshot.js";
|
|
1
2
|
import { AppError } from "../shared/errors.js";
|
|
2
3
|
import { RetainedExecutionBundle } from "./execution-bundles.js";
|
|
3
4
|
import { readAcceptedStageData } from "./stage-report-renderer.js";
|
|
@@ -32,6 +33,7 @@ function selected(context, scope) {
|
|
|
32
33
|
/** Closed review predecessor proof only. It does not establish integration,
|
|
33
34
|
* normal-flow readiness, terminal Stage acceptance or RUN completion. */
|
|
34
35
|
export class PreparedMemoryFinishReview {
|
|
36
|
+
#custodyKey = {};
|
|
35
37
|
static isPrepared(value) {
|
|
36
38
|
return typeof value === "object" && value !== null && #review in value;
|
|
37
39
|
}
|
|
@@ -51,40 +53,52 @@ export class PreparedMemoryFinishReview {
|
|
|
51
53
|
Object.freeze(this);
|
|
52
54
|
}
|
|
53
55
|
static prepare(context, input) {
|
|
54
|
-
if (!(input.bundle instanceof RetainedExecutionBundle) || input.bundle.descriptor.descriptor.id
|
|
56
|
+
if (!(input.bundle instanceof RetainedExecutionBundle) || !["mb-init", "mb-upgrade"].includes(input.bundle.descriptor.descriptor.id)
|
|
55
57
|
|| input.bundle.descriptor.successor("review", "accepted") !== "finish")
|
|
56
58
|
refuse("registered_memory_bundle_required");
|
|
57
59
|
if (context.db.isOwnedWriteTransaction?.())
|
|
58
60
|
refuse("preparation_outside_writer_required");
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
return withMemoryCustodySnapshot(context, () => {
|
|
62
|
+
assertPreparedRunBundleSqlAuthority(context, input.scope, input.bundle);
|
|
63
|
+
const data = context.db.readSnapshot(() => selected(context, input.scope));
|
|
64
|
+
const review = data.corrected
|
|
65
|
+
? PreparedAcceptedMemoryCorrectedReview.prepare(context, { ...input, bytes: data.data.bytes })
|
|
66
|
+
: PreparedAcceptedMemoryInitialReview.prepare(context, { ...input, bytes: data.data.bytes });
|
|
67
|
+
const prepared = new PreparedMemoryFinishReview(token, input.scope, review, data);
|
|
68
|
+
prepared.revalidate(context);
|
|
69
|
+
return prepared;
|
|
70
|
+
});
|
|
67
71
|
}
|
|
68
72
|
bytes() { return Buffer.from(this.#bytes); }
|
|
69
73
|
reviewedSources(context) { this.assertCustody(context); return this.#review.reviewedSources(context); }
|
|
74
|
+
reviewedDocumentInventory(context) {
|
|
75
|
+
this.assertCustody(context);
|
|
76
|
+
return this.#review instanceof PreparedAcceptedMemoryCorrectedReview ? this.#review.settledDocumentBaseline(context).entries() : null;
|
|
77
|
+
}
|
|
70
78
|
finalChecks(context) { this.assertCustody(context); return this.#review.finalChecks(context); }
|
|
71
79
|
assertCustody(context) {
|
|
72
|
-
this.#review
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
const review = this.#review;
|
|
81
|
+
assertMemorySqlCustody(context, this.#custodyKey, () => {
|
|
82
|
+
review.assertCustody(context);
|
|
83
|
+
const data = selected(context, this.#scope);
|
|
84
|
+
if (data.corrected !== this.#corrected || data.data.authority_sha256 !== this.#authority
|
|
85
|
+
|| !data.data.bytes.equals(this.#bytes))
|
|
86
|
+
refuse("accepted_review_changed");
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
revalidate(context) {
|
|
90
|
+
const review = this.#review;
|
|
91
|
+
withMemoryCustodySnapshot(context, () => { review.revalidate(context); this.assertCustody(context); });
|
|
77
92
|
}
|
|
78
|
-
revalidate(context) { this.#review.revalidate(context); this.assertCustody(context); }
|
|
79
93
|
}
|
|
80
|
-
/**
|
|
81
|
-
*
|
|
94
|
+
/** Shared terminal entry for registered Memory flows. Opens only after
|
|
95
|
+
* historical review proof; no provider dispatch or Git mutation.
|
|
82
96
|
* Terminal settlement must separately prove integration and readiness. */
|
|
83
97
|
export function startMemoryFinish(context, input) {
|
|
84
98
|
if (!(input.bytes instanceof Uint8Array) || input.bytes.length > 1024 * 1024)
|
|
85
99
|
refuse("invalid_input_bytes");
|
|
86
100
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
87
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
101
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id) || !bundle.descriptor.descriptor.terminal_stages.includes("finish")
|
|
88
102
|
|| bundle.descriptor.successor("review", "accepted") !== "finish")
|
|
89
103
|
refuse("registered_memory_bundle_required");
|
|
90
104
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
|
|
@@ -107,7 +121,7 @@ export function replayAcceptedMemoryFinish(context, input) {
|
|
|
107
121
|
if (context.db.isOwnedWriteTransaction?.())
|
|
108
122
|
refuse("preparation_outside_writer_required");
|
|
109
123
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
110
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
124
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
111
125
|
refuse("registered_memory_bundle_required");
|
|
112
126
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
|
|
113
127
|
const review = PreparedMemoryFinishReview.prepare(context, { scope, bundle });
|
|
@@ -149,7 +163,7 @@ export function settleAcceptedMemoryRun(context, input) {
|
|
|
149
163
|
if (context.db.isOwnedWriteTransaction?.())
|
|
150
164
|
refuse("preparation_outside_writer_required");
|
|
151
165
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
152
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
166
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id)
|
|
153
167
|
|| !bundle.descriptor.descriptor.terminal_stages.includes("finish"))
|
|
154
168
|
refuse("registered_memory_bundle_required");
|
|
155
169
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
|
|
@@ -175,14 +189,14 @@ export function settleAcceptedMemoryRun(context, input) {
|
|
|
175
189
|
* Publication has its own exact receipt and does not accept the Stage. */
|
|
176
190
|
export function registerMemoryFinishEvidenceFromStage(context, input) {
|
|
177
191
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
178
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
192
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
179
193
|
refuse("registered_memory_bundle_required");
|
|
180
194
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
181
195
|
return PreparedMemoryFinishEvidence.prepare(context, { scope: { projectId: project.id, runId: input.runId }, bundle }).register(context);
|
|
182
196
|
}
|
|
183
197
|
export function integrateMemoryFinishFromStage(context, input) {
|
|
184
198
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
185
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
199
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
186
200
|
refuse("registered_memory_bundle_required");
|
|
187
201
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot));
|
|
188
202
|
return integrateMemoryFinish(context, { scope: { projectId: project.id, runId: input.runId }, bundle });
|
|
@@ -196,7 +210,7 @@ export function finishMemoryFinish(context, input) {
|
|
|
196
210
|
if (context.db.isOwnedWriteTransaction?.())
|
|
197
211
|
refuse("preparation_outside_writer_required");
|
|
198
212
|
const bundle = readFlowRunExecutionBundle(context, input);
|
|
199
|
-
if (!bundle || bundle.descriptor.descriptor.id
|
|
213
|
+
if (!bundle || !["mb-init", "mb-upgrade"].includes(bundle.descriptor.descriptor.id))
|
|
200
214
|
refuse("registered_memory_bundle_required");
|
|
201
215
|
const project = requireProjectByRoot(context, resolveProjectRoot(input.projectRoot)), scope = { projectId: project.id, runId: input.runId };
|
|
202
216
|
const run = assertPreparedRunBundleSqlAuthority(context, scope, bundle);
|