@deksden-com/dd-flow-cli 0.9.0-beta.136 → 0.9.0-beta.138

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +9 -0
  3. package/dist/build-info.json +6 -6
  4. package/dist/cli/argument-values.js +5 -5
  5. package/dist/cli/command-inputs.js +89 -20
  6. package/dist/cli/command-metadata.js +56 -3
  7. package/dist/cli/command-option-descriptions.js +5 -0
  8. package/dist/cli/executor-onboarding.js +8 -3
  9. package/dist/cli/flows.js +29 -0
  10. package/dist/cli/help.js +240 -6
  11. package/dist/cli/input-preparation.js +54 -5
  12. package/dist/cli/memory-flow-admission.js +44 -0
  13. package/dist/cli/memory-init-invocation.js +78 -0
  14. package/dist/cli/memory-init.js +240 -0
  15. package/dist/cli/memory-storage-admission.js +53 -0
  16. package/dist/cli/native-hook-ingress.js +1 -1
  17. package/dist/cli/response-file.js +2 -0
  18. package/dist/cli/run-cli.js +283 -160
  19. package/dist/cli/setup.js +9 -7
  20. package/dist/cli.js +54 -2
  21. package/dist/domain/stage-handler-identities.js +20 -0
  22. package/dist/harness-runtime/DD-ZCODE.md +13 -0
  23. package/dist/harness-runtime/bin/dd-opencode.mjs +3 -3
  24. package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
  25. package/dist/harness-runtime/lib/daemon-operations.mjs +4 -3
  26. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +4 -2
  27. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +11 -5
  28. package/dist/harness-runtime/lib/dd-codex.mjs +22 -10
  29. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +2 -1
  30. package/dist/harness-runtime/lib/dd-droid.mjs +2 -1
  31. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +4 -2
  32. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +20 -5
  33. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +45 -10
  34. package/dist/harness-runtime/lib/dd-zcode.mjs +7 -3
  35. package/dist/harness-runtime/lib/delegation-instructions.mjs +5 -3
  36. package/dist/harness-runtime/lib/lifecycle-command.mjs +1 -0
  37. package/dist/harness-runtime/lib/managed-daemon.d.mts +1 -0
  38. package/dist/harness-runtime/lib/managed-daemon.mjs +50 -15
  39. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  40. package/dist/harness-runtime/lib/native-hook-command.mjs +1 -1
  41. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  42. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  43. package/dist/harness-runtime/lib/opencode-plugin.mjs +5 -1
  44. package/dist/harness-runtime/lib/operation-progress.mjs +3 -1
  45. package/dist/runtime/context.js +1 -1
  46. package/dist/schemas/discovery-result.schema.json +184 -0
  47. package/dist/schemas/execution-bundle.schema.json +205 -0
  48. package/dist/schemas/execution-settings.schema.json +162 -0
  49. package/dist/schemas/flow-descriptor.schema.json +54 -0
  50. package/dist/schemas/flow-run.schema.json +22 -0
  51. package/dist/schemas/harness-catalog.schema.json +80 -0
  52. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  53. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  54. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  55. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  56. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  57. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  58. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  59. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  60. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  61. package/dist/schemas/memory-repair-work-result.schema.json +49 -0
  62. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  63. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  64. package/dist/schemas/model-catalog.schema.json +153 -0
  65. package/dist/schemas/profile-settings.schema.json +122 -0
  66. package/dist/schemas/release-manifest.schema.json +291 -0
  67. package/dist/schemas/run-engine-binding.schema.json +1 -1
  68. package/dist/services/check-runner-evidence.js +51 -4
  69. package/dist/services/cli-operation-classifier.js +8 -47
  70. package/dist/services/code-checks.js +387 -34
  71. package/dist/services/controller-child-observer.js +99 -0
  72. package/dist/services/controller-execution.js +88 -0
  73. package/dist/services/controller-fanout.js +79 -13
  74. package/dist/services/dashboard.js +8 -2
  75. package/dist/services/descriptor-coordinator-session.js +35 -0
  76. package/dist/services/descriptor-root-work.js +53 -0
  77. package/dist/services/descriptor-run-settlement.js +105 -0
  78. package/dist/services/descriptor-run-start.js +449 -0
  79. package/dist/services/descriptor-stage-coordinator.js +197 -0
  80. package/dist/services/descriptor-stage-settlement.js +222 -0
  81. package/dist/services/descriptor-stage-start.js +139 -0
  82. package/dist/services/engines.js +39 -22
  83. package/dist/services/eval-snapshots.js +83 -25
  84. package/dist/services/execution-bundles.js +263 -0
  85. package/dist/services/execution-policy.js +20 -16
  86. package/dist/services/external-work-launch.js +91 -11
  87. package/dist/services/flow-catalog.js +21 -0
  88. package/dist/services/flow-descriptors.js +82 -0
  89. package/dist/services/frozen-engine.js +242 -0
  90. package/dist/services/generic-execution.js +164 -0
  91. package/dist/services/harness-adapter.js +28 -2
  92. package/dist/services/hooks.js +24 -6
  93. package/dist/services/hybrid-contracts.js +31 -3
  94. package/dist/services/ids.js +29 -1
  95. package/dist/services/installation-lock.js +7 -4
  96. package/dist/services/installed-flow-source.js +183 -0
  97. package/dist/services/lifecycle-invocations.js +257 -78
  98. package/dist/services/memory-accepted-composition.js +77 -0
  99. package/dist/services/memory-baseline-preservation.js +65 -0
  100. package/dist/services/memory-completed-correction-wave.js +320 -0
  101. package/dist/services/memory-compose-handler.js +258 -0
  102. package/dist/services/memory-composition-acceptance.js +199 -0
  103. package/dist/services/memory-composition-graph.js +134 -0
  104. package/dist/services/memory-composition-registration.js +146 -0
  105. package/dist/services/memory-composition-work-custody.js +151 -0
  106. package/dist/services/memory-composition-work-results.js +96 -0
  107. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  108. package/dist/services/memory-corrected-review-batch.js +30 -0
  109. package/dist/services/memory-corrected-review-findings.js +106 -0
  110. package/dist/services/memory-corrected-review-inputs.js +210 -0
  111. package/dist/services/memory-corrected-review-projection.js +78 -0
  112. package/dist/services/memory-corrected-review-receipt.js +170 -0
  113. package/dist/services/memory-corrected-review-registration.js +191 -0
  114. package/dist/services/memory-correction-check-receipt.js +219 -0
  115. package/dist/services/memory-correction-input-owner.js +6 -0
  116. package/dist/services/memory-discover-handler.js +104 -0
  117. package/dist/services/memory-finish-evidence.js +435 -0
  118. package/dist/services/memory-finish-handler.js +215 -0
  119. package/dist/services/memory-finish-integration.js +280 -0
  120. package/dist/services/memory-finish-readiness.js +122 -0
  121. package/dist/services/memory-git-integration.js +151 -0
  122. package/dist/services/memory-historical-corrected-review.js +206 -0
  123. package/dist/services/memory-historical-original-review.js +130 -0
  124. package/dist/services/memory-historical-repair-registration.js +99 -0
  125. package/dist/services/memory-historical-second-review.js +128 -0
  126. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  127. package/dist/services/memory-init-contexts.js +89 -0
  128. package/dist/services/memory-init-controller-start.js +84 -0
  129. package/dist/services/memory-init-engine-release.js +223 -0
  130. package/dist/services/memory-init-git-policy.js +136 -0
  131. package/dist/services/memory-init-lint-capability.js +185 -0
  132. package/dist/services/memory-init-native-capacity.js +241 -0
  133. package/dist/services/memory-init-preflight.js +312 -0
  134. package/dist/services/memory-init-project-bootstrap.js +599 -0
  135. package/dist/services/memory-init-request-candidate.js +157 -0
  136. package/dist/services/memory-init-request-input.js +66 -0
  137. package/dist/services/memory-init-resource-storage.js +125 -0
  138. package/dist/services/memory-init-run-allocation.js +81 -0
  139. package/dist/services/memory-init-run-bundle.js +98 -0
  140. package/dist/services/memory-init-start.js +175 -0
  141. package/dist/services/memory-init-startup-custody.js +80 -0
  142. package/dist/services/memory-init-startup-input.js +240 -0
  143. package/dist/services/memory-init-storage.js +81 -0
  144. package/dist/services/memory-init-stores.js +359 -0
  145. package/dist/services/memory-init-worktrunk-capability.js +172 -0
  146. package/dist/services/memory-layer-publication.js +611 -0
  147. package/dist/services/memory-layer.js +156 -0
  148. package/dist/services/memory-lint-config.js +85 -0
  149. package/dist/services/memory-native-review-copy.js +165 -0
  150. package/dist/services/memory-normal-flow-entry.js +75 -0
  151. package/dist/services/memory-ordinary-defaults.js +112 -0
  152. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  153. package/dist/services/memory-preflight-handler.js +259 -0
  154. package/dist/services/memory-repair-current-view.js +299 -0
  155. package/dist/services/memory-repair-document-delta.js +451 -0
  156. package/dist/services/memory-repair-history.js +491 -0
  157. package/dist/services/memory-repair-physical-binding.js +312 -0
  158. package/dist/services/memory-repair-publication-files.js +152 -0
  159. package/dist/services/memory-repair-publication-intent.js +27 -0
  160. package/dist/services/memory-repair-publication-plan.js +160 -0
  161. package/dist/services/memory-repair-publication-source.js +225 -0
  162. package/dist/services/memory-repair-publication.js +794 -0
  163. package/dist/services/memory-repair-registration.js +239 -0
  164. package/dist/services/memory-repair-work-baseline.js +413 -0
  165. package/dist/services/memory-repair-work-completion.js +97 -0
  166. package/dist/services/memory-repair-work-custody.js +73 -0
  167. package/dist/services/memory-repair-work-results.js +89 -0
  168. package/dist/services/memory-repair-workspace.js +252 -0
  169. package/dist/services/memory-repair-writer-copy.js +735 -0
  170. package/dist/services/memory-result-binding.js +173 -0
  171. package/dist/services/memory-retained-review-authority.js +129 -0
  172. package/dist/services/memory-retained-review-results.js +70 -0
  173. package/dist/services/memory-retained-second-baseline.js +102 -0
  174. package/dist/services/memory-retained-second-repairs.js +156 -0
  175. package/dist/services/memory-review-acceptance.js +214 -0
  176. package/dist/services/memory-review-correction-plan.js +171 -0
  177. package/dist/services/memory-review-handler.js +585 -0
  178. package/dist/services/memory-review-inputs.js +200 -0
  179. package/dist/services/memory-review-receipt.js +180 -0
  180. package/dist/services/memory-review-registration.js +108 -0
  181. package/dist/services/memory-review-work-custody.js +124 -0
  182. package/dist/services/memory-review-work-input.js +72 -0
  183. package/dist/services/memory-review-work-results.js +73 -0
  184. package/dist/services/memory-second-corrected-review-inputs.js +165 -0
  185. package/dist/services/memory-second-correction-plan.js +76 -0
  186. package/dist/services/memory-second-repair-baseline.js +91 -0
  187. package/dist/services/memory-second-repair-launch.js +614 -0
  188. package/dist/services/memory-second-repair-registration.js +88 -0
  189. package/dist/services/memory-second-repair-source.js +187 -0
  190. package/dist/services/memory-second-review-acceptance.js +115 -0
  191. package/dist/services/memory-source-observations.js +117 -0
  192. package/dist/services/memory-stage-dispatch.js +28 -0
  193. package/dist/services/memory-stage-results.js +199 -0
  194. package/dist/services/memory-verification-acceptance.js +135 -0
  195. package/dist/services/memory-verification-checks.js +252 -0
  196. package/dist/services/memory-verification-receipt.js +159 -0
  197. package/dist/services/memory-verify-handler.js +135 -0
  198. package/dist/services/memory-work-result-preparation.js +63 -0
  199. package/dist/services/projects.js +17 -2
  200. package/dist/services/recovery-snapshot-database.js +416 -1
  201. package/dist/services/repair-intents.js +1 -1
  202. package/dist/services/review-copy.js +10 -2
  203. package/dist/services/run-control.js +80 -9
  204. package/dist/services/run-controller-capture.js +10 -3
  205. package/dist/services/run-controller-process.js +21 -0
  206. package/dist/services/run-controller-recovery.js +3 -1
  207. package/dist/services/run-controller-state.js +1 -1
  208. package/dist/services/run-controller.js +184 -48
  209. package/dist/services/run-recovery-guard.js +2 -0
  210. package/dist/services/run-recovery.js +145 -5
  211. package/dist/services/run-start-custody.js +177 -0
  212. package/dist/services/runs.js +319 -25
  213. package/dist/services/stage-context.js +9 -1
  214. package/dist/services/stage-handlers.js +74 -0
  215. package/dist/services/stage-lifecycle.js +2 -1
  216. package/dist/services/stage-report-renderer.js +76 -0
  217. package/dist/services/stage-work-graph.js +17 -0
  218. package/dist/services/vnext-code.js +3 -3
  219. package/dist/services/vnext-execution-profile.js +2 -2
  220. package/dist/services/vnext-fanout.js +136 -10
  221. package/dist/services/vnext-merge.js +8 -3
  222. package/dist/services/vnext-plan-review.js +6 -4
  223. package/dist/services/vnext-protocolize.js +60 -2
  224. package/dist/services/work-registry.js +616 -71
  225. package/dist/services/workspace-files.js +1 -1
  226. package/dist/storage/database.js +84 -6
  227. package/dist/storage/writer-contract.js +11 -7
  228. package/package.json +13 -3
  229. package/tools/create-canon-release.mjs +33 -0
  230. package/tools/produce-hybrid-release.mjs +41 -0
@@ -0,0 +1,239 @@
1
+ import { createHash } from "node:crypto";
2
+ import { AppError } from "../shared/errors.js";
3
+ import { appendAudit } from "./audit.js";
4
+ import { hybridDigest } from "./hybrid-contracts.js";
5
+ import { PreparedMemoryInitialCorrectionPlan, validateMemoryReviewCorrectionPlan } from "./memory-review-correction-plan.js";
6
+ import { PreparedRetainedMemoryReviewResults } from "./memory-retained-review-results.js";
7
+ import { memoryReviewWaveProjection } from "./memory-review-acceptance.js";
8
+ import { addWorkBatch, prepareWorkBatch, readWorkBatchCustody } from "./work-registry.js";
9
+ export const memoryRepairWorkerSchema = "dd-flow/memory-repair-work-result@1";
10
+ const event = "memory.repair_registration";
11
+ const registrationToken = Symbol("registered-memory-corrections");
12
+ const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
13
+ function refuse(reason) {
14
+ throw new AppError("memory_repair_registration_invalid", "Correction Work lacks independently retained plan and review custody", 2, { reason, effect: "no_effect" });
15
+ }
16
+ /** Deterministic allocation projection, not source-byte/write admission. The
17
+ * task is retained exactly as admitted; profile selection stays in the generic
18
+ * frozen execution route rather than in a new repair-specific dispatcher.
19
+ */
20
+ export function memoryRepairBatch(input) {
21
+ let total = 0;
22
+ const batch = { works: input.plan.works.map(work => {
23
+ const packet = { schema_id: "dd-flow/memory-repair-work-packet@1", run_id: input.scope.run_id,
24
+ stage: "review", wave: input.plan.wave, key: work.key, plan_sha256: input.planSha256,
25
+ review_sha256: input.plan.review_sha256, original_registration_sha256: input.originalRegistrationSha256,
26
+ unit_ids: [...work.unit_ids], findings: structuredClone(input.findings.filter(finding => work.finding_ids.includes(finding.id))),
27
+ write_paths: [...work.write_paths], read_inputs: structuredClone(input.references), result_schema: memoryRepairWorkerSchema };
28
+ const item = { key: work.key, task: work.task, depends_on: [...work.depends_on], launch_policy: "fresh_agent_required",
29
+ result_schema: memoryRepairWorkerSchema, payload: { kind: "memory-repair", read_only: false,
30
+ ...(work.profile_id === null ? {} : { execution_override: { agent_profile_id: work.profile_id } }),
31
+ memory_repair: { ...packet, packet_sha256: hybridDigest(packet) } } };
32
+ const size = Buffer.byteLength(JSON.stringify(item));
33
+ total += size;
34
+ if (size > 1024 * 1024 || total > 64 * 1024 * 1024)
35
+ refuse("unbounded_repair_batch");
36
+ return item;
37
+ }) };
38
+ return batch;
39
+ }
40
+ function batchScope(scope) {
41
+ return { project_id: scope.project_id, run_id: scope.run_id, stage: "review", attempt: scope.attempt,
42
+ cycle: "", parent_work_id: scope.parent_work_id, request_key: "memory-repair-wave-1" };
43
+ }
44
+ function selected(context, scope) {
45
+ 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')=1 LIMIT 2", [scope.project_id, event, scope.run_id, scope.attempt, scope.parent_work_id]);
46
+ if (!rows.length)
47
+ return null;
48
+ try {
49
+ if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 2 * 1024 * 1024)
50
+ refuse("ambiguous_or_unbounded_registration");
51
+ const receipt = JSON.parse(rows[0].payload_json);
52
+ if (receipt.schema_id !== "dd-flow/memory-repair-registration@1" || receipt.run_id !== scope.run_id || receipt.wave !== 1
53
+ || hybridDigest(receipt.scope) !== hybridDigest(scope)
54
+ || [receipt.original_registration_sha256, receipt.review_sha256, receipt.plan_sha256, receipt.batch_sha256].some(value => typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value))
55
+ || typeof receipt.plan_base64 !== "string" || !receipt.work_ids || typeof receipt.work_ids !== "object" || Array.isArray(receipt.work_ids)
56
+ || !Object.keys(receipt.work_ids).length || Object.keys(receipt.work_ids).length > 256
57
+ || Object.values(receipt.work_ids).some(id => typeof id !== "string" || !id)
58
+ || new Set(Object.values(receipt.work_ids)).size !== Object.keys(receipt.work_ids).length)
59
+ refuse("changed_registration");
60
+ const bytes = Buffer.from(receipt.plan_base64, "base64");
61
+ if (!bytes.length || bytes.length > 1024 * 1024 || bytes.toString("base64") !== receipt.plan_base64 || hash(bytes) !== receipt.plan_sha256)
62
+ refuse("changed_plan_bytes");
63
+ return structuredClone(receipt);
64
+ }
65
+ catch (error) {
66
+ if (error instanceof AppError && error.code === "memory_repair_registration_invalid")
67
+ throw error;
68
+ return refuse("invalid_registration");
69
+ }
70
+ }
71
+ function project(review, plan, planSha256) {
72
+ const original = review.original().registration();
73
+ return memoryRepairBatch({ scope: original.scope, plan, planSha256, originalRegistrationSha256: hybridDigest(original),
74
+ references: [...original.view.run_inputs, ...review.references().map(ref => ({ root: "run", ...ref.result }))],
75
+ findings: memoryReviewWaveProjection(review.results(), original.view.diagnostic_findings).findings });
76
+ }
77
+ function assertAllocation(context, receipt, batch) {
78
+ if (hybridDigest(batch.works) !== receipt.batch_sha256 || batch.works.length !== Object.keys(receipt.work_ids).length)
79
+ refuse("changed_repair_batch");
80
+ for (const item of batch.works) {
81
+ if (!Object.hasOwn(receipt.work_ids, item.key) || !receipt.work_ids[item.key])
82
+ refuse("missing_repair_work");
83
+ const custody = readWorkBatchCustody(context, receipt.work_ids[item.key]);
84
+ if (custody.item_key !== item.key || custody.batch_sha256 !== receipt.batch_sha256
85
+ || hybridDigest(custody.scope) !== hybridDigest(batchScope(receipt.scope))
86
+ || hybridDigest(custody.work_ids) !== hybridDigest(receipt.work_ids))
87
+ refuse("changed_work_custody");
88
+ const work = context.db.get("SELECT parent_work_id,task,launch_policy,result_schema,payload_json,depends_on_json FROM works WHERE project_id=? AND run_id=? AND work_id=?", [receipt.scope.project_id, receipt.run_id, receipt.work_ids[item.key]]);
89
+ let payload, dependencies;
90
+ try {
91
+ payload = JSON.parse(work?.payload_json ?? "null");
92
+ dependencies = JSON.parse(work?.depends_on_json ?? "null");
93
+ }
94
+ catch {
95
+ return refuse("invalid_repair_work");
96
+ }
97
+ if (!work || work.parent_work_id !== receipt.scope.parent_work_id || work.task !== item.task
98
+ || work.launch_policy !== item.launch_policy || work.result_schema !== item.result_schema
99
+ || hybridDigest(dependencies) !== hybridDigest(item.depends_on.map(key => receipt.work_ids[key]))
100
+ || hybridDigest(payload) !== hybridDigest({ ...item.payload, _dd_flow_batch_request: {
101
+ request_sha256: custody.request_sha256, batch_sha256: custody.batch_sha256, item_key: item.key
102
+ } }))
103
+ refuse("changed_repair_work");
104
+ }
105
+ }
106
+ /** Retained metadata/allocation readers only, not current repair admission. */
107
+ export function readRetainedMemoryRepairRegistration(context, scope) {
108
+ const receipt = selected(context, scope);
109
+ if (!receipt)
110
+ refuse("repair_registration_missing");
111
+ return receipt;
112
+ }
113
+ export function assertRetainedMemoryRepairAllocation(context, receipt, batch) {
114
+ const retained = readRetainedMemoryRepairRegistration(context, receipt.scope);
115
+ if (hybridDigest(retained) !== hybridDigest(receipt))
116
+ refuse("repair_registration_changed");
117
+ assertAllocation(context, retained, batch);
118
+ }
119
+ /** Historical registered-plan authority. Restore deliberately does not require
120
+ * today's documents to match the pre-correction hashes. It proves exact plan
121
+ * and Work identity only: current bytes, repair success and delta re-review
122
+ * require separate settlement owners. No Work or provider is allocated here.
123
+ */
124
+ export class PreparedRegisteredMemoryCorrections {
125
+ static isPrepared(value) {
126
+ return typeof value === "object" && value !== null && #receipt in value;
127
+ }
128
+ sha256;
129
+ #review;
130
+ #receipt;
131
+ #plan;
132
+ #batch;
133
+ constructor(token, review, receipt, plan, batch) {
134
+ if (token !== registrationToken)
135
+ refuse("registration_token_required");
136
+ this.#review = review;
137
+ this.#receipt = structuredClone(receipt);
138
+ this.#plan = structuredClone(plan);
139
+ this.#batch = structuredClone(batch);
140
+ this.sha256 = hybridDigest(receipt);
141
+ Object.freeze(this);
142
+ }
143
+ static restore(context, review, expectedBytes) {
144
+ if (!(review instanceof PreparedRetainedMemoryReviewResults))
145
+ refuse("prepared_review_results_required");
146
+ review.revalidate(context);
147
+ const original = review.original().registration(), bundle = review.original().bundle();
148
+ const receipt = context.db.readSnapshot(() => selected(context, original.scope));
149
+ if (!receipt)
150
+ refuse("repair_registration_missing");
151
+ if (receipt.original_registration_sha256 !== hybridDigest(original) || receipt.review_sha256 !== review.sha256
152
+ || review.results().some(result => result.outcome === "blocked"))
153
+ refuse("foreign_original_review");
154
+ const bytes = Buffer.from(receipt.plan_base64, "base64");
155
+ if (expectedBytes !== undefined && (!(expectedBytes instanceof Uint8Array) || !bytes.equals(Buffer.from(expectedBytes))))
156
+ refuse("plan_replay_conflict");
157
+ const plan = validateMemoryReviewCorrectionPlan(bytes, bundle.engine(), { runId: original.run_id, wave: 1,
158
+ reviewSha256: review.sha256, units: original.view.unit_inventory, findings: memoryReviewWaveProjection(review.results(), original.view.diagnostic_findings).findings });
159
+ for (const work of plan.works)
160
+ bundle.execution.work("review", work.profile_id ?? undefined);
161
+ const schema = JSON.parse(bundle.engine().schema("memory-repair-work-result").toString("utf8"));
162
+ if (schema.$id !== memoryRepairWorkerSchema)
163
+ refuse("frozen_repair_worker_schema_required");
164
+ const batch = project(review, plan, receipt.plan_sha256);
165
+ const prepared = new PreparedRegisteredMemoryCorrections(registrationToken, review, receipt, plan, batch);
166
+ prepared.assertCustody(context);
167
+ return prepared;
168
+ }
169
+ receipt() { return structuredClone(this.#receipt); }
170
+ plan() { return structuredClone(this.#plan); }
171
+ batch() { return structuredClone(this.#batch); }
172
+ review() { return this.#review; }
173
+ bytes() { return Buffer.from(this.#receipt.plan_base64, "base64"); }
174
+ assertCustody(context) {
175
+ this.#review.assertCustody(context);
176
+ const receipt = selected(context, this.#receipt.scope);
177
+ if (!receipt || hybridDigest(receipt) !== this.sha256)
178
+ refuse("repair_registration_changed");
179
+ assertAllocation(context, receipt, this.#batch);
180
+ }
181
+ revalidate(context) { this.#review.revalidate(context); this.assertCustody(context); }
182
+ replay(context) {
183
+ this.revalidate(context);
184
+ const scope = batchScope(this.#receipt.scope), batchInput = { parentWorkId: scope.parent_work_id,
185
+ requestKey: scope.request_key, stage: "review", value: this.#batch };
186
+ const prepared = prepareWorkBatch(context, batchInput);
187
+ return context.db.writeTransaction(() => {
188
+ this.assertCustody(context);
189
+ const allocation = addWorkBatch(context, { ...batchInput, prepared });
190
+ if (!allocation.replayed || hybridDigest(allocation.work_ids) !== hybridDigest(this.#receipt.work_ids))
191
+ refuse("changed_replay_allocation");
192
+ return { wave: 1, plan_sha256: this.#receipt.plan_sha256, work_ids: { ...this.#receipt.work_ids }, replayed: true };
193
+ });
194
+ }
195
+ }
196
+ /** First correction allocation. All source and frozen-schema/profile reads
197
+ * precede the writer; SQL-only review custody, generic allocation and the
198
+ * independent plan receipt commit together. Lost receipts cannot be adopted.
199
+ */
200
+ export function registerMemoryInitialCorrections(context, plan) {
201
+ if (!(plan instanceof PreparedMemoryInitialCorrectionPlan))
202
+ refuse("prepared_initial_plan_required");
203
+ const review = plan.review(), original = review.original().registration(), bundle = review.original().bundle();
204
+ const schema = JSON.parse(bundle.engine().schema("memory-repair-work-result").toString("utf8"));
205
+ if (schema.$id !== memoryRepairWorkerSchema)
206
+ refuse("frozen_repair_worker_schema_required");
207
+ const batch = project(review, plan.value(), plan.sha256), scope = batchScope(original.scope);
208
+ const batchInput = { parentWorkId: scope.parent_work_id, requestKey: scope.request_key, stage: "review", value: batch };
209
+ const prepared = prepareWorkBatch(context, batchInput);
210
+ plan.revalidate(context);
211
+ return context.db.writeTransaction(() => {
212
+ plan.assertCustody(context);
213
+ const prior = selected(context, original.scope);
214
+ if (prior) {
215
+ if (prior.plan_sha256 !== plan.sha256 || prior.review_sha256 !== review.sha256
216
+ || prior.original_registration_sha256 !== hybridDigest(original))
217
+ refuse("plan_replay_conflict");
218
+ assertAllocation(context, prior, batch);
219
+ const allocated = addWorkBatch(context, { ...batchInput, prepared });
220
+ if (!allocated.replayed || hybridDigest(allocated.work_ids) !== hybridDigest(prior.work_ids))
221
+ refuse("changed_replay_allocation");
222
+ return { wave: 1, plan_sha256: prior.plan_sha256, work_ids: { ...prior.work_ids }, replayed: true };
223
+ }
224
+ if (context.db.get("SELECT 1 FROM works w JOIN stage_work_memberships m ON m.work_id=w.work_id AND m.project_id=w.project_id AND m.run_id=w.run_id WHERE w.project_id=? AND w.run_id=? AND w.parent_work_id=? AND m.stage='review' AND m.attempt=? AND (w.result_schema=? OR json_extract(w.payload_json,'$.kind')='memory-repair') AND (json_extract(w.payload_json,'$.memory_repair.wave')=1 OR json_extract(w.payload_json,'$.memory_repair.wave') IS NULL) LIMIT 1", [scope.project_id, scope.run_id, scope.parent_work_id, scope.attempt, memoryRepairWorkerSchema]))
225
+ refuse("repair_registration_missing");
226
+ const allocated = addWorkBatch(context, { ...batchInput, prepared });
227
+ if (allocated.replayed)
228
+ refuse("repair_registration_missing");
229
+ const receipt = { schema_id: "dd-flow/memory-repair-registration@1", run_id: scope.run_id, scope: original.scope, wave: 1,
230
+ original_registration_sha256: hybridDigest(original), review_sha256: review.sha256, plan_sha256: plan.sha256,
231
+ plan_base64: plan.bytes().toString("base64"), batch_sha256: hybridDigest(batch.works), work_ids: allocated.work_ids };
232
+ appendAudit(context, { projectId: scope.project_id, eventType: event, payload: receipt });
233
+ const retained = selected(context, original.scope);
234
+ if (!retained)
235
+ refuse("repair_registration_missing");
236
+ assertAllocation(context, retained, batch);
237
+ return { wave: 1, plan_sha256: retained.plan_sha256, work_ids: { ...retained.work_ids }, replayed: false };
238
+ });
239
+ }