@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,299 @@
1
+ import { AppError } from "../shared/errors.js";
2
+ import { hybridDigest } from "./hybrid-contracts.js";
3
+ import { PreparedRegisteredMemoryCorrections } from "./memory-repair-registration.js";
4
+ import { PreparedRetainedSecondMemoryRepairs } from "./memory-retained-second-repairs.js";
5
+ import { PreparedSettledMemoryRepair } from "./memory-repair-history.js";
6
+ import { MemoryRepairDocumentBaseline } from "./memory-repair-document-delta.js";
7
+ import { PreparedMemoryRepairWorkspace } from "./memory-repair-workspace.js";
8
+ import { reviewSourceHash, reviewSourcePaths } from "./review-copy.js";
9
+ import { assertRunMutationAllowed } from "./run-recovery-guard.js";
10
+ import { appendAudit } from "./audit.js";
11
+ const token = Symbol("memory-repair-current-view");
12
+ const event = "memory.repair_current_view";
13
+ const nonMemory = (entry) => entry.path !== ".memory-bank" && !entry.path.startsWith(".memory-bank/");
14
+ function isRegistration(value) {
15
+ return PreparedRegisteredMemoryCorrections.isPrepared(value) || PreparedRetainedSecondMemoryRepairs.isPrepared(value);
16
+ }
17
+ function inputView(registration) {
18
+ return PreparedRetainedSecondMemoryRepairs.isPrepared(registration) ? registration.initialInputView()
19
+ : registration.review().original().registration().view;
20
+ }
21
+ function bundle(registration) {
22
+ return PreparedRetainedSecondMemoryRepairs.isPrepared(registration) ? registration.bundle()
23
+ : registration.review().original().bundle();
24
+ }
25
+ function refuse(reason) {
26
+ throw new AppError("memory_repair_current_view_invalid", "Current repair inputs lack settled graph and document custody", 1, { reason, effect: "no_effect" });
27
+ }
28
+ /** SQL-only graph selection. This record is not a current-view/start owner. */
29
+ export function selectMemoryRepairGraph(context, registration, workId, phase, retainedStates) {
30
+ if (!isRegistration(registration))
31
+ refuse("registered_corrections_required");
32
+ if (phase !== "created" && phase !== "running")
33
+ refuse("invalid_graph_phase");
34
+ registration.assertCustody(context);
35
+ const receipt = registration.receipt(), batch = registration.batch();
36
+ const target = batch.works.find(item => receipt.work_ids[item.key] === workId);
37
+ if (!target)
38
+ refuse("foreign_repair_work");
39
+ const generation = assertRunMutationAllowed(context, receipt.scope.project_id, receipt.run_id);
40
+ const states = batch.works.map((item, index) => {
41
+ const id = receipt.work_ids[item.key];
42
+ const row = context.db.get("SELECT status FROM works WHERE project_id=? AND run_id=? AND work_id=?", [receipt.scope.project_id, receipt.run_id, id]);
43
+ if (!row)
44
+ refuse("missing_registered_work");
45
+ const retained = retainedStates?.[index];
46
+ if (retainedStates && (!retained || retained.key !== item.key || retained.work_id !== id || !["created", "running", "paused", "completed", "failed", "cancelled"].includes(retained.status)))
47
+ refuse("retained_graph_changed");
48
+ return { key: item.key, work_id: id, status: retained?.status ?? row.status };
49
+ });
50
+ if (retainedStates && retainedStates.length !== states.length)
51
+ refuse("retained_graph_changed");
52
+ if (states.find(item => item.work_id === workId)?.status !== phase)
53
+ refuse(phase === "created" ? "unstarted_target_required" : "running_target_required");
54
+ const completed = new Set(states.filter(item => item.status === "completed").map(item => item.key));
55
+ for (const item of batch.works) {
56
+ if ((item.key === target.key || completed.has(item.key)) && item.depends_on.some(key => !completed.has(key)))
57
+ refuse("unsettled_dependency");
58
+ }
59
+ const ids = new Set(states.filter(item => item.status === "completed").map(item => item.work_id));
60
+ if (!ids.size) {
61
+ if (phase === "created")
62
+ refuse("settled_history_required");
63
+ return { generation, states, settlements: [], target };
64
+ }
65
+ const rows = context.db.all(`SELECT a.id,json_extract(a.payload_json,'$.work_id') AS work_id FROM audit_events a JOIN works w ON w.work_id=json_extract(a.payload_json,'$.work_id') AND w.project_id=a.project_id AND w.run_id=json_extract(a.payload_json,'$.run_id') WHERE a.project_id=? AND a.event_type='memory.repair_work_settlement' AND w.run_id=? AND w.parent_work_id=? AND w.work_id IN (${[...ids].map(() => "?").join(",")}) ORDER BY a.id LIMIT 257`, [receipt.scope.project_id, receipt.run_id, receipt.scope.parent_work_id, ...ids]);
66
+ const settlements = rows.filter(row => ids.has(row.work_id));
67
+ if (rows.length > 256 || !settlements.length || settlements.length !== ids.size || new Set(settlements.map(item => item.work_id)).size !== ids.size)
68
+ refuse("settled_history_required");
69
+ return { generation, states, settlements, target };
70
+ }
71
+ function selection(context, registration, workId, retainedStates) {
72
+ return selectMemoryRepairGraph(context, registration, workId, "created", retainedStates);
73
+ }
74
+ function registered(context, registration, workId) {
75
+ const scope = registration.receipt().scope;
76
+ 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,'$.work_id')=? LIMIT 2", [scope.project_id, event, scope.run_id, workId]);
77
+ if (!rows.length)
78
+ return null;
79
+ if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 40 * 1024 * 1024)
80
+ refuse("ambiguous_or_unbounded_view_receipt");
81
+ try {
82
+ const value = JSON.parse(rows[0].payload_json);
83
+ if (!value || typeof value !== "object" || Array.isArray(value))
84
+ refuse("invalid_view_receipt");
85
+ return value;
86
+ }
87
+ catch (error) {
88
+ if (error instanceof AppError)
89
+ throw error;
90
+ return refuse("invalid_view_receipt");
91
+ }
92
+ }
93
+ /** SQL-only retained selection. A returned record is not prepared authority;
94
+ * consumers must check their independent baseline/start/receipt binding.
95
+ */
96
+ export function readMemoryRepairCurrentViewReceipt(context, registration, workId) {
97
+ registration.assertCustody(context);
98
+ const value = registered(context, registration, workId);
99
+ if (!value)
100
+ refuse("registered_view_required");
101
+ return structuredClone(value);
102
+ }
103
+ function retainedBytes(value) {
104
+ if (typeof value !== "string" || value.length > Math.ceil(8 * 1024 * 1024 / 3) * 4)
105
+ refuse("unbounded_view_bytes");
106
+ const bytes = Buffer.from(value, "base64");
107
+ if (bytes.length > 8 * 1024 * 1024 || bytes.toString("base64") !== value)
108
+ refuse("changed_view_bytes");
109
+ return bytes;
110
+ }
111
+ function compose(histories, paths, registration) {
112
+ let baseline = (PreparedRetainedSecondMemoryRepairs.isPrepared(registration)
113
+ ? registration.initialDocumentBaseline() : histories[0].before()).withWritePaths(paths);
114
+ const versions = new Set([hybridDigest(baseline.entries())]);
115
+ for (const history of histories) {
116
+ if (!versions.has(hybridDigest(history.before().entries())))
117
+ refuse("unexplained_historical_input_view");
118
+ baseline = baseline.composeSettledDelta(history.before(), history.after());
119
+ versions.add(hybridDigest(baseline.entries()));
120
+ }
121
+ return baseline;
122
+ }
123
+ /** Current-view preparation/restoration is read-only. Explicit registration
124
+ * owns only the bounded view audit, never a provider, copy or shared document.
125
+ * Registering a baseline and binding its launch/publication remain separate
126
+ * operations; this owner cannot bypass them.
127
+ */
128
+ export class PreparedMemoryRepairCurrentView {
129
+ static isPrepared(value) {
130
+ return typeof value === "object" && value !== null && #selection in value;
131
+ }
132
+ sha256;
133
+ workId;
134
+ #registration;
135
+ #selection;
136
+ #histories;
137
+ #baseline;
138
+ #exported;
139
+ #workspace;
140
+ #input;
141
+ #registered = false;
142
+ constructor(key, registration, workId, selected, histories, baseline, exported, workspace, input) {
143
+ if (key !== token)
144
+ refuse("current_view_token_required");
145
+ this.#registration = registration;
146
+ this.workId = workId;
147
+ this.#selection = structuredClone(selected);
148
+ this.#histories = histories;
149
+ this.#baseline = baseline;
150
+ this.#exported = exported;
151
+ this.#workspace = workspace;
152
+ this.#input = structuredClone(input);
153
+ this.sha256 = hybridDigest({ registration: registration.sha256, work_id: workId, selected, histories: histories.map(item => item.sha256),
154
+ baseline_sha256: baseline.sha256, exported_sha256: exported.sha256, workspace_sha256: workspace.sha256, input });
155
+ Object.freeze(this);
156
+ }
157
+ static prepare(context, registration, workId) {
158
+ if (!isRegistration(registration))
159
+ refuse("registered_corrections_required");
160
+ if (context.db.isOwnedWriteTransaction?.())
161
+ refuse("preparation_outside_writer_required");
162
+ const selected = context.db.readSnapshot(() => selection(context, registration, workId));
163
+ const histories = selected.settlements.map(item => PreparedSettledMemoryRepair.prepare(context, registration, item.work_id));
164
+ const paths = selected.target.payload.memory_repair.write_paths;
165
+ const baseline = compose(histories, paths, registration);
166
+ const view = inputView(registration);
167
+ const workspaceRoot = bundle(registration).execution.snapshot().scope.workspace;
168
+ const input = { base: view.base, explicit_inputs: view.run_inputs.filter(ref => ref.root === "workspace").map(ref => ref.path) };
169
+ baseline.revalidate(workspaceRoot);
170
+ const candidates = reviewSourcePaths(workspaceRoot, input.explicit_inputs, input.base);
171
+ if (!candidates)
172
+ refuse("source_inventory_unavailable");
173
+ const available = new Set(baseline.entries().filter(entry => entry.kind === "file").map(entry => entry.path));
174
+ const exported = baseline.exported(candidates.filter(logical => logical.startsWith(".memory-bank/") && available.has(logical)));
175
+ const workspace = PreparedMemoryRepairWorkspace.capture(workspaceRoot, input, exported);
176
+ const nonMemorySha256 = hybridDigest(workspace.entries().filter(nonMemory));
177
+ for (const history of histories) {
178
+ if (hybridDigest(history.workspaceManifest().entries().filter(nonMemory)) !== nonMemorySha256)
179
+ refuse("non_memory_source_changed");
180
+ }
181
+ const copyInput = { ...input, source_sha256: reviewSourceHash(workspaceRoot, input.explicit_inputs, input.base) };
182
+ const prepared = new PreparedMemoryRepairCurrentView(token, registration, workId, selected, histories, baseline, exported, workspace, copyInput);
183
+ prepared.revalidate(context);
184
+ return prepared;
185
+ }
186
+ /** Restore admitted bytes and graph evidence, not today's documents. A
187
+ * later caller must separately establish launch/Session/publication scope.
188
+ */
189
+ static restore(context, registration, workId) {
190
+ if (!isRegistration(registration))
191
+ refuse("registered_corrections_required");
192
+ if (context.db.isOwnedWriteTransaction?.())
193
+ refuse("preparation_outside_writer_required");
194
+ registration.assertCustody(context);
195
+ const value = registered(context, registration, workId);
196
+ if (!value)
197
+ refuse("registered_view_required");
198
+ const rawSelection = value.selected;
199
+ if (!rawSelection || !Array.isArray(rawSelection.states))
200
+ refuse("invalid_view_receipt");
201
+ const selected = context.db.readSnapshot(() => selection(context, registration, workId, rawSelection.states));
202
+ if (hybridDigest(selected) !== hybridDigest(rawSelection))
203
+ refuse("retained_graph_changed");
204
+ const histories = selected.settlements.map(item => PreparedSettledMemoryRepair.prepare(context, registration, item.work_id));
205
+ const baseline = MemoryRepairDocumentBaseline.restore(retainedBytes(value.baseline_base64), value.baseline_sha256);
206
+ if (compose(histories, selected.target.payload.memory_repair.write_paths, registration).sha256 !== baseline.sha256)
207
+ refuse("retained_document_view_changed");
208
+ const exported = MemoryRepairDocumentBaseline.restore(retainedBytes(value.exported_baseline_base64), value.exported_baseline_sha256);
209
+ if (baseline.exported(exported.entries().filter(entry => entry.kind === "file").map(entry => entry.path)).sha256 !== exported.sha256)
210
+ refuse("retained_export_changed");
211
+ const workspace = PreparedMemoryRepairWorkspace.restore(retainedBytes(value.workspace_manifest_base64), value.workspace_manifest_sha256, exported);
212
+ const view = inputView(registration);
213
+ const input = value.input;
214
+ if (!input || typeof input.source_sha256 !== "string" || !/^[a-f0-9]{64}$/.test(input.source_sha256)
215
+ || input.base !== view.base || hybridDigest(input.explicit_inputs) !== hybridDigest(view.run_inputs.filter(ref => ref.root === "workspace").map(ref => ref.path)))
216
+ refuse("retained_source_input_changed");
217
+ const nonMemorySha256 = hybridDigest(workspace.entries().filter(nonMemory));
218
+ if (histories.some(history => hybridDigest(history.workspaceManifest().entries().filter(nonMemory)) !== nonMemorySha256))
219
+ refuse("retained_non_memory_changed");
220
+ const prepared = new PreparedMemoryRepairCurrentView(token, registration, workId, selected, histories, baseline, exported, workspace, input);
221
+ if (hybridDigest(prepared.receipt()) !== hybridDigest(value))
222
+ refuse("registered_view_changed");
223
+ prepared.#registered = true;
224
+ prepared.assertCustody(context);
225
+ return prepared;
226
+ }
227
+ receipt() {
228
+ const scope = this.#registration.receipt().scope;
229
+ const receipt = { schema_id: "dd-flow/memory-repair-current-view@1", project_id: scope.project_id, run_id: scope.run_id,
230
+ work_id: this.workId, generation: this.#selection.generation, registration_sha256: this.#registration.sha256,
231
+ view_sha256: this.sha256, selected: structuredClone(this.#selection),
232
+ histories: this.#histories.map(history => ({ work_id: history.workId, sha256: history.sha256 })), input: this.copyInput(),
233
+ baseline_sha256: this.#baseline.sha256, baseline_base64: this.#baseline.bytes().toString("base64"),
234
+ exported_baseline_sha256: this.#exported.sha256, exported_baseline_base64: this.#exported.bytes().toString("base64"),
235
+ workspace_manifest_sha256: this.#workspace.sha256, workspace_manifest_base64: this.#workspace.bytes().toString("base64") };
236
+ if (Buffer.byteLength(JSON.stringify(receipt)) > 40 * 1024 * 1024)
237
+ refuse("unbounded_view_receipt");
238
+ return receipt;
239
+ }
240
+ register(context) {
241
+ this.revalidate(context);
242
+ const receipt = this.receipt(), expected = hybridDigest(receipt);
243
+ const result = context.db.writeTransaction(() => {
244
+ if (!context.db.isOwnedWriteTransaction?.())
245
+ refuse("owned_view_writer_required");
246
+ this.assertCustody(context);
247
+ if (!context.db.get("SELECT 1 FROM works WHERE project_id=? AND run_id=? AND work_id=? AND status='created'", [receipt.project_id, receipt.run_id, this.workId])
248
+ || context.db.get("SELECT 1 FROM work_sessions WHERE work_id=? LIMIT 1", [this.workId])
249
+ || (context.db.get("SELECT 1 FROM sqlite_schema WHERE type='table' AND name='work_launches'")
250
+ && context.db.get("SELECT 1 FROM work_launches WHERE work_id=? LIMIT 1", [this.workId])))
251
+ refuse("unstarted_target_required");
252
+ const prior = registered(context, this.#registration, this.workId);
253
+ if (prior && hybridDigest(prior) !== expected)
254
+ refuse("registered_view_changed");
255
+ if (!prior)
256
+ appendAudit(context, { projectId: receipt.project_id, eventType: event, payload: receipt });
257
+ if (hybridDigest(registered(context, this.#registration, this.workId)) !== expected)
258
+ refuse("view_receipt_readback_failed");
259
+ return { work_id: this.workId, view_sha256: this.sha256, receipt_sha256: expected, replayed: Boolean(prior) };
260
+ });
261
+ this.#registered = true;
262
+ try {
263
+ this.revalidate(context);
264
+ }
265
+ catch (error) {
266
+ throw new AppError("memory_repair_current_view_pending", "Current view committed but custody changed before baseline consumption", 1, { effect: "committed", view_sha256: this.sha256, cause: error instanceof Error ? error.message : String(error) });
267
+ }
268
+ return result;
269
+ }
270
+ baseline() { return this.#baseline; }
271
+ exportedBaseline() { return this.#exported; }
272
+ workspaceManifest() { return this.#workspace; }
273
+ copyInput() { return structuredClone(this.#input); }
274
+ assertCustody(context) {
275
+ if (hybridDigest(selection(context, this.#registration, this.workId, this.#registered ? this.#selection.states : undefined)) !== hybridDigest(this.#selection))
276
+ refuse("current_view_graph_changed");
277
+ for (const history of this.#histories)
278
+ history.assertCustody(context);
279
+ if (this.#registered && hybridDigest(registered(context, this.#registration, this.workId)) !== hybridDigest(this.receipt()))
280
+ refuse("registered_view_changed");
281
+ }
282
+ revalidate(context) {
283
+ if (context.db.isOwnedWriteTransaction?.())
284
+ refuse("preparation_outside_writer_required");
285
+ this.assertCustody(context);
286
+ const root = bundle(this.#registration).execution.snapshot().scope.workspace;
287
+ this.#baseline.revalidate(root);
288
+ const view = inputView(this.#registration);
289
+ const fresh = PreparedMemoryRepairWorkspace.capture(root, { base: view.base,
290
+ explicit_inputs: view.run_inputs.filter(ref => ref.root === "workspace").map(ref => ref.path) }, this.#exported);
291
+ if (fresh.sha256 !== this.#workspace.sha256)
292
+ refuse("selected_source_inventory_changed");
293
+ if (reviewSourceHash(root, this.#input.explicit_inputs, this.#input.base) !== this.#input.source_sha256)
294
+ refuse("selected_source_hash_changed");
295
+ for (const history of this.#histories)
296
+ history.revalidate(context);
297
+ this.assertCustody(context);
298
+ }
299
+ }