@deksden-com/dd-flow-cli 0.9.0-beta.144 → 0.9.0-beta.149

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 (254) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +13 -8
  3. package/dist/build-info.json +7 -7
  4. package/dist/cli/command-inputs.js +13 -3
  5. package/dist/cli/command-metadata.js +51 -16
  6. package/dist/cli/diagnostic-invocation.js +46 -0
  7. package/dist/cli/diagnostic.js +120 -0
  8. package/dist/cli/help.js +67 -1
  9. package/dist/cli/hook-ingress.js +27 -3
  10. package/dist/cli/memory-flow-admission.js +9 -3
  11. package/dist/cli/memory-init-invocation.js +10 -3
  12. package/dist/cli/memory-init.js +77 -68
  13. package/dist/cli/memory-storage-admission.js +3 -2
  14. package/dist/cli/memory-storage-qualification.js +105 -0
  15. package/dist/cli/memory-storage-transition.js +123 -0
  16. package/dist/cli/memory-upgrade.js +189 -0
  17. package/dist/cli/native-hook-ingress.js +14 -4
  18. package/dist/cli/native-hook-preparation.js +55 -0
  19. package/dist/cli/response-file.js +2 -1
  20. package/dist/cli/run-cli.js +79 -40
  21. package/dist/cli/setup.js +2 -1
  22. package/dist/cli.js +18 -0
  23. package/dist/domain/diagnostic-aspects.js +103 -0
  24. package/dist/domain/diagnostic-flows.js +8 -0
  25. package/dist/domain/stage-handler-identities.js +8 -0
  26. package/dist/harness-runtime/bin/dd-agy.mjs +3 -3
  27. package/dist/harness-runtime/bin/dd-grok.mjs +3 -3
  28. package/dist/harness-runtime/bin/dd-zcode.mjs +5 -5
  29. package/dist/harness-runtime/lib/agy-error-boundary.mjs +58 -0
  30. package/dist/harness-runtime/lib/agy-native-inspection.mjs +216 -0
  31. package/dist/harness-runtime/lib/agy-native_pb.js +117 -0
  32. package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
  33. package/dist/harness-runtime/lib/daemon-operations.mjs +84 -10
  34. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +366 -52
  35. package/dist/harness-runtime/lib/dd-agy.mjs +17 -3
  36. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +27 -13
  37. package/dist/harness-runtime/lib/dd-codex.mjs +4 -0
  38. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +4 -3
  39. package/dist/harness-runtime/lib/dd-droid.mjs +71 -29
  40. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +73 -16
  41. package/dist/harness-runtime/lib/dd-grok.mjs +6 -3
  42. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +66 -20
  43. package/dist/harness-runtime/lib/dd-opencode.mjs +30 -3
  44. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +7 -6
  45. package/dist/harness-runtime/lib/dd-zcode.mjs +44 -14
  46. package/dist/harness-runtime/lib/delegation-instructions.mjs +1 -1
  47. package/dist/harness-runtime/lib/driver-recovery.mjs +9 -8
  48. package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
  49. package/dist/harness-runtime/lib/entity-references.mjs +9 -0
  50. package/dist/harness-runtime/lib/managed-daemon.d.mts +1 -1
  51. package/dist/harness-runtime/lib/managed-daemon.mjs +24 -9
  52. package/dist/harness-runtime/lib/native-children.d.mts +8 -1
  53. package/dist/harness-runtime/lib/native-children.mjs +114 -8
  54. package/dist/harness-runtime/lib/native-hook-command.mjs +4 -4
  55. package/dist/harness-runtime/lib/native-request-proof.mjs +1 -1
  56. package/dist/harness-runtime/lib/observation-clock.d.mts +2 -2
  57. package/dist/harness-runtime/lib/observation-clock.mjs +7 -4
  58. package/dist/harness-runtime/lib/opencode-plugin.mjs +3 -3
  59. package/dist/harness-runtime/lib/operation-errors.mjs +1 -1
  60. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +5 -3
  61. package/dist/harness-runtime/lib/provider-overload-policy.mjs +20 -7
  62. package/dist/harness-runtime/lib/runner-events.mjs +3 -1
  63. package/dist/harness-runtime/lib/setup-progress.mjs +8 -6
  64. package/dist/harness-runtime/lib/tool-observations.mjs +1 -1
  65. package/dist/schemas/diagnostic-stage-result.schema.json +354 -0
  66. package/dist/schemas/diagnostic-work-result.schema.json +296 -0
  67. package/dist/schemas/execution-bundle.schema.json +7 -1
  68. package/dist/schemas/mb-upgrade-stage-result.schema.json +863 -0
  69. package/dist/schemas/memory-repair-work-result.schema.json +9 -2
  70. package/dist/schemas/project-flow-pack-manifest.schema.json +1 -1
  71. package/dist/schemas/release-impact.schema.json +3 -3
  72. package/dist/schemas/stage-start-response.schema.json +4 -0
  73. package/dist/services/accepted-intent.js +13 -1
  74. package/dist/services/canon.js +43 -7
  75. package/dist/services/check-environment.js +21 -0
  76. package/dist/services/check-runner-evidence.js +267 -15
  77. package/dist/services/cli-operation-classifier.js +1 -1
  78. package/dist/services/cli-upgrade-allowlist.js +1 -1
  79. package/dist/services/code-checks.js +34 -19
  80. package/dist/services/compatibility-preflight.js +5 -2
  81. package/dist/services/controller-execution.js +10 -4
  82. package/dist/services/controller-fanout.js +34 -10
  83. package/dist/services/controller-memory-task.js +45 -0
  84. package/dist/services/controller-memory-worker.js +49 -0
  85. package/dist/services/dashboard.js +2 -2
  86. package/dist/services/descriptor-run-settlement.js +5 -3
  87. package/dist/services/descriptor-run-start.js +46 -20
  88. package/dist/services/descriptor-stage-coordinator.js +66 -13
  89. package/dist/services/descriptor-stage-settlement.js +2 -1
  90. package/dist/services/descriptor-stage-start.js +40 -4
  91. package/dist/services/diagnostic-evidence.js +73 -0
  92. package/dist/services/diagnostic-report-publication.js +72 -0
  93. package/dist/services/diagnostic-report.js +67 -0
  94. package/dist/services/diagnostic-run-bundle.js +74 -0
  95. package/dist/services/diagnostic-snapshot.js +159 -0
  96. package/dist/services/diagnostic-stage-handlers.js +108 -0
  97. package/dist/services/diagnostic-stage-results.js +132 -0
  98. package/dist/services/diagnostic-start.js +84 -0
  99. package/dist/services/diagnostic-work-batch.js +34 -0
  100. package/dist/services/diagnostic-work-collection.js +97 -0
  101. package/dist/services/diagnostic-work-registration.js +101 -0
  102. package/dist/services/diagnostic-work-results.js +93 -0
  103. package/dist/services/engines.js +64 -14
  104. package/dist/services/eval-snapshots.js +186 -119
  105. package/dist/services/execution-bundles.js +19 -7
  106. package/dist/services/external-work-launch.js +5 -3
  107. package/dist/services/flow-catalog.js +13 -4
  108. package/dist/services/frozen-engine.js +148 -11
  109. package/dist/services/hook-memory-routing.js +188 -0
  110. package/dist/services/hook-recovery-guard.js +14 -0
  111. package/dist/services/hook-session-observation.js +24 -0
  112. package/dist/services/hooks.js +27 -8
  113. package/dist/services/hybrid-contracts.js +4 -13
  114. package/dist/services/hybrid-digest.js +14 -0
  115. package/dist/services/installed-flow-source.js +47 -4
  116. package/dist/services/lifecycle-invocations.js +179 -38
  117. package/dist/services/memory-accepted-composition.js +5 -4
  118. package/dist/services/memory-completed-correction-wave.js +23 -15
  119. package/dist/services/memory-compose-handler.js +163 -21
  120. package/dist/services/memory-composition-acceptance.js +186 -10
  121. package/dist/services/memory-composition-graph.js +42 -11
  122. package/dist/services/memory-composition-registration.js +23 -8
  123. package/dist/services/memory-composition-work-custody.js +14 -9
  124. package/dist/services/memory-composition-work-results.js +15 -3
  125. package/dist/services/memory-corrected-review-batch.js +10 -3
  126. package/dist/services/memory-corrected-review-findings.js +4 -2
  127. package/dist/services/memory-corrected-review-inputs.js +10 -5
  128. package/dist/services/memory-corrected-review-receipt.js +17 -9
  129. package/dist/services/memory-corrected-review-registration.js +3 -2
  130. package/dist/services/memory-correction-check-receipt.js +20 -4
  131. package/dist/services/memory-custody-snapshot.js +36 -0
  132. package/dist/services/memory-finish-evidence.js +44 -22
  133. package/dist/services/memory-finish-handler.js +37 -23
  134. package/dist/services/memory-finish-integration.js +218 -48
  135. package/dist/services/memory-finish-readiness.js +66 -19
  136. package/dist/services/memory-git-integration.js +87 -18
  137. package/dist/services/memory-historical-corrected-review.js +21 -15
  138. package/dist/services/memory-historical-original-review.js +22 -9
  139. package/dist/services/memory-historical-repair-registration.js +14 -8
  140. package/dist/services/memory-historical-second-review.js +30 -11
  141. package/dist/services/memory-init-contexts.js +44 -2
  142. package/dist/services/memory-init-controller-start.js +27 -8
  143. package/dist/services/memory-init-git-policy.js +50 -21
  144. package/dist/services/memory-init-lint-capability.js +24 -6
  145. package/dist/services/memory-init-native-capacity.js +17 -4
  146. package/dist/services/memory-init-preflight.js +21 -17
  147. package/dist/services/memory-init-request-candidate.js +73 -17
  148. package/dist/services/memory-init-request-input.js +23 -7
  149. package/dist/services/memory-init-run-bundle.js +49 -12
  150. package/dist/services/memory-init-storage.js +17 -7
  151. package/dist/services/memory-init-worktrunk-capability.js +3 -7
  152. package/dist/services/memory-layer.js +71 -6
  153. package/dist/services/memory-lint-config.js +111 -2
  154. package/dist/services/memory-native-review-copy.js +5 -67
  155. package/dist/services/memory-normal-flow-entry.js +12 -0
  156. package/dist/services/memory-ordinary-defaults.js +22 -5
  157. package/dist/services/memory-preflight-handler.js +15 -0
  158. package/dist/services/memory-repair-current-view.js +1 -1
  159. package/dist/services/memory-repair-document-delta.js +70 -33
  160. package/dist/services/memory-repair-history.js +12 -7
  161. package/dist/services/memory-repair-physical-binding.js +1 -119
  162. package/dist/services/memory-repair-publication-plan.js +5 -3
  163. package/dist/services/memory-repair-publication-source.js +1 -1
  164. package/dist/services/memory-repair-publication.js +3 -2
  165. package/dist/services/memory-repair-registration.js +2 -1
  166. package/dist/services/memory-repair-work-baseline.js +4 -2
  167. package/dist/services/memory-repair-work-completion.js +32 -12
  168. package/dist/services/memory-repair-work-results.js +21 -2
  169. package/dist/services/memory-repair-workspace.js +11 -2
  170. package/dist/services/memory-repair-writer-copy.js +2 -1
  171. package/dist/services/memory-result-binding.js +78 -12
  172. package/dist/services/memory-retained-review-authority.js +17 -8
  173. package/dist/services/memory-retained-second-baseline.js +1 -1
  174. package/dist/services/memory-retained-second-repairs.js +12 -6
  175. package/dist/services/memory-review-correction-plan.js +47 -12
  176. package/dist/services/memory-review-handler.js +17 -17
  177. package/dist/services/memory-review-inputs.js +55 -9
  178. package/dist/services/memory-review-limits.js +10 -0
  179. package/dist/services/memory-review-receipt.js +2 -2
  180. package/dist/services/memory-review-registration.js +13 -4
  181. package/dist/services/memory-review-work-custody.js +3 -1
  182. package/dist/services/memory-review-work-input.js +26 -7
  183. package/dist/services/memory-review-work-results.js +26 -4
  184. package/dist/services/memory-second-corrected-review-inputs.js +5 -3
  185. package/dist/services/memory-second-correction-plan.js +2 -1
  186. package/dist/services/memory-second-repair-launch.js +4 -4
  187. package/dist/services/memory-second-repair-source.js +1 -1
  188. package/dist/services/memory-stage-dispatch.js +38 -1
  189. package/dist/services/memory-stage-results.js +113 -22
  190. package/dist/services/memory-tool-probe.js +25 -0
  191. package/dist/services/memory-upgrade-analysis-handler.js +243 -0
  192. package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
  193. package/dist/services/memory-upgrade-evidence.js +100 -0
  194. package/dist/services/memory-upgrade-inventory.js +442 -0
  195. package/dist/services/memory-upgrade-publication-custody.js +73 -0
  196. package/dist/services/memory-upgrade-publication.js +413 -0
  197. package/dist/services/memory-upgrade-selection.js +430 -0
  198. package/dist/services/memory-upgrade-start.js +60 -0
  199. package/dist/services/memory-upgrade-storage-readiness.js +340 -0
  200. package/dist/services/memory-verification-acceptance.js +38 -17
  201. package/dist/services/memory-verification-checks.js +92 -27
  202. package/dist/services/memory-verification-receipt.js +6 -5
  203. package/dist/services/memory-verify-handler.js +15 -13
  204. package/dist/services/memory-work-result-json.js +12 -0
  205. package/dist/services/memory-work-result-preparation.js +5 -4
  206. package/dist/services/merge-server.js +4 -2
  207. package/dist/services/migrations.js +127 -98
  208. package/dist/services/native-daemon-history.js +2 -1
  209. package/dist/services/physical-startup.js +45 -0
  210. package/dist/services/project-registry.js +97 -0
  211. package/dist/services/project-summary.js +1 -1
  212. package/dist/services/projects.js +3 -93
  213. package/dist/services/prompt-delivery.js +71 -0
  214. package/dist/services/provider-capacity.js +112 -46
  215. package/dist/services/recovery-snapshot-database.js +32 -4
  216. package/dist/services/release-cache.js +8 -0
  217. package/dist/services/repair-intents.js +1 -12
  218. package/dist/services/repair-receipt.js +13 -0
  219. package/dist/services/run-control-worker.js +35 -18
  220. package/dist/services/run-control.js +2 -1
  221. package/dist/services/run-controller-adapter.js +2 -1
  222. package/dist/services/run-controller-process.js +4 -7
  223. package/dist/services/run-controller-recovery.js +8 -2
  224. package/dist/services/run-controller.js +215 -94
  225. package/dist/services/run-fork.js +1 -1
  226. package/dist/services/run-recovery-guard.js +30 -0
  227. package/dist/services/run-recovery.js +11 -44
  228. package/dist/services/run-start-custody.js +17 -5
  229. package/dist/services/runs.js +6 -1
  230. package/dist/services/runtime-scope-resume.js +12 -6
  231. package/dist/services/runtime-scope-stop.js +3 -2
  232. package/dist/services/runtime-scope-worker.js +46 -19
  233. package/dist/services/runtime-service.js +2 -1
  234. package/dist/services/sessions.js +3 -24
  235. package/dist/services/setup.js +63 -13
  236. package/dist/services/stage-handlers.js +22 -7
  237. package/dist/services/stage-pause.js +111 -44
  238. package/dist/services/version-status.js +1 -1
  239. package/dist/services/vnext-code.js +2 -2
  240. package/dist/services/vnext-fanout.js +51 -9
  241. package/dist/services/vnext-plan-review.js +3 -5
  242. package/dist/services/work-registry.js +117 -39
  243. package/dist/services/workspace-bootstrap.js +2 -1
  244. package/dist/services/workspace-files.js +1 -1
  245. package/dist/shared/entity-references.js +1 -8
  246. package/dist/storage/data-preservation.js +65 -0
  247. package/dist/storage/database.js +53 -19
  248. package/dist/storage/import-guard.js +84 -27
  249. package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
  250. package/dist/storage/paired-writer-migration.js +424 -0
  251. package/dist/storage/writer-contract.js +11 -4
  252. package/dist/storage/writer-migration.js +313 -52
  253. package/dist/storage/writer-restore.js +217 -0
  254. package/package.json +13 -6
@@ -0,0 +1,251 @@
1
+ import { createHash } from "node:crypto";
2
+ import { AppError } from "../shared/errors.js";
3
+ import { appendAudit } from "./audit.js";
4
+ import { hybridDigest, validateHybridContract } from "./hybrid-contracts.js";
5
+ import { prepareMemoryInitBootstrapSchema } from "./memory-init-bootstrap-readiness.js";
6
+ import { restoreMemoryUpgradeSelectionData } from "./memory-upgrade-selection.js";
7
+ import { PreparedUpgradeStorageReadiness, readUpgradeStorageReadiness, upgradeStorageMigration, resolveUpgradeHistoricalScope, assertUpgradeExecutionStorage } from "./memory-upgrade-storage-readiness.js";
8
+ import { RetainedExecutionBundle } from "./execution-bundles.js";
9
+ import { assertPreparedRunBundleSqlAuthority } from "./runs.js";
10
+ import { runContextRelocations } from "./stage-context.js";
11
+ import semver from "semver";
12
+ import { PreparedMemoryInitLintCapability, isMemoryInitLintCapabilityFacts } from "./memory-init-lint-capability.js";
13
+ import { inspectMemoryLintExecutable } from "./memory-init-preflight.js";
14
+ import { readBoundedReleaseFile } from "./release-source.js";
15
+ const eventType = "memory.bootstrap_ready";
16
+ const bytes = (value) => Buffer.from(JSON.stringify(value));
17
+ const hash = (value) => createHash("sha256").update(value).digest("hex");
18
+ function refuse(reason) {
19
+ throw new AppError("memory_upgrade_bootstrap_readiness_invalid", "Upgrade bootstrap requires its retained selection and accepted storage", 1, { reason, effect: "no_effect", next_action: "reconcile_exact_request" });
20
+ }
21
+ /** SQL-only construction. This receipt authorizes execution bootstrap, not
22
+ * semantic acceptance, canonical publication or a substitute handler registry. */
23
+ function material(context, binding) {
24
+ const retained = readUpgradeStorageReadiness(context, binding.scope);
25
+ if (!retained?.selection || retained.sha256 !== binding.storage_sha256
26
+ || retained.selection.sha256 !== binding.selection_sha256)
27
+ refuse("storage_selection_changed");
28
+ const p = retained.selection.payload, release = retained.selection.release;
29
+ if (binding.flow !== undefined) {
30
+ const facts = { schema_id: "dd-flow/memory-upgrade-engine-flow@1", flow_id: "mb-upgrade", source_sha256: p.source.sha256,
31
+ descriptor_sha256: p.execution.snapshot.settings.descriptor_sha256,
32
+ stages: ["preflight", "diff-analysis", "upgrade", "verify", "review", "finish"] };
33
+ if (hybridDigest(binding.flow) !== hybridDigest({ facts, sha256: hybridDigest(facts),
34
+ engine_manifest_sha256: p.engine.manifest_sha256, engine_sha256: p.engine.identity.integrity_checksum }))
35
+ refuse("selected_engine_flow_changed");
36
+ }
37
+ if (binding.lint !== undefined) {
38
+ if (!isMemoryInitLintCapabilityFacts(binding.lint))
39
+ refuse("invalid_lint_capability");
40
+ const compatibility = p.layer.files.find(file => file.path === "dd-flow/compatibility.json");
41
+ const minimum = compatibility ? JSON.parse(Buffer.from(compatibility.base64, "base64").toString("utf8")).mb_lint?.min_version : null;
42
+ if (typeof minimum !== "string" || !semver.valid(minimum) || semver.lt(binding.lint.version, minimum))
43
+ refuse("selected_linter_below_target_minimum");
44
+ }
45
+ const target = retained.receipt.proof.target;
46
+ if (!target || typeof target.pack_sha256 !== "string" || !/^[a-f0-9]{64}$/.test(target.pack_sha256))
47
+ refuse("invalid_target_pack");
48
+ if (binding.execution_sha256 !== p.execution.sha256 || typeof binding.engine_manifest_base64 !== "string"
49
+ || binding.engine_manifest_base64.length > 2 * 1024 * 1024)
50
+ refuse("execution_binding_changed");
51
+ const manifestBytes = Buffer.from(binding.engine_manifest_base64, "base64");
52
+ if (manifestBytes.toString("base64") !== binding.engine_manifest_base64 || hash(manifestBytes) !== p.engine.manifest_sha256)
53
+ refuse("engine_manifest_changed");
54
+ const manifest = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(manifestBytes));
55
+ if (manifest.integrity?.checksum !== p.engine.identity.integrity_checksum
56
+ || release.engine.package !== manifest.package_name || release.engine.version !== manifest.package_version)
57
+ refuse("foreign_engine");
58
+ const scope = binding.scope, fact = { requestId: scope.requestId, projectRoot: scope.projectRoot, workspace: scope.workspaceRoot };
59
+ const baseline = hybridDigest({ inventory_sha256: p.current.inventory.sha256, git: p.workspace });
60
+ const evidenceValue = { schema_id: "dd-flow/memory-upgrade-storage-evidence@1", scope,
61
+ storage_sha256: retained.sha256, proof: retained.receipt.proof };
62
+ const evidence = [{ kind: "storage-compatibility", path: "receipts/storage-compatibility.json",
63
+ sha256: hash(bytes(evidenceValue)), base64: bytes(evidenceValue).toString("base64") }];
64
+ const migration = retained.receipt.proof.route === "migration" ? upgradeStorageMigration(retained.receipt.proof.migration, retained.selection.sha256) : undefined;
65
+ if (migration)
66
+ evidence.push(...migration.proof.evidence);
67
+ const reference = (kind) => { const entry = evidence.find(entry => entry.kind === kind); return entry ? { path: entry.path, sha256: entry.sha256 } : null; };
68
+ const receipt = { schema_id: "dd-flow/memory-bootstrap-receipt@2", request_id: scope.requestId, flow_id: "mb-upgrade",
69
+ project_root: scope.projectRoot, workspace: { path: scope.workspaceRoot, repository: scope.projectRoot,
70
+ branch: p.workspace.branch, commit: p.workspace.head, git_state: p.workspace.head === null ? "unborn" : "committed" },
71
+ baseline_sha256: baseline,
72
+ project_current: { canon_version: p.current.canon_version, pack_sha256: hybridDigest(p.current.inventory.inventory.entries
73
+ .filter(entry => entry.path.startsWith("dd-flow/") && entry.current)
74
+ .map(entry => ({ path: entry.path, sha256: entry.current.sha256 }))) },
75
+ upgrade_target: { canon_version: release.canon.version, pack_sha256: target.pack_sha256 },
76
+ effective_execution: { engine_sha256: p.engine.identity.integrity_checksum, canon_sha256: release.canon.archive.sha256 },
77
+ readiness: "ready", storage: { route: migration ? "migration" : "verified-no-op", outcome: migration ? "applied" : "no-op",
78
+ compatibility_receipt: { path: evidence[0].path, sha256: evidence[0].sha256 },
79
+ drain_receipt: reference("writer-drain"), backup_receipt: reference("storage-backup"), plan_receipt: reference("storage-plan"),
80
+ apply_receipt: reference("storage-apply"), verification_receipt: reference("storage-verification") },
81
+ effects: migration ? [{ kind: "storage-apply", receipt: reference("storage-apply") }] : [] };
82
+ const admission = { receipts: new Map(evidence.map(entry => [entry.sha256, { kind: entry.kind, ...fact }])),
83
+ bootstrapIdentity: { ...fact, baselineSha256: baseline, engineSha256: p.engine.identity.integrity_checksum,
84
+ canonSha256: release.canon.archive.sha256,
85
+ workspaceGit: { repository: scope.projectRoot, branch: p.workspace.branch, commit: p.workspace.head } } };
86
+ const authority = { schema_id: "dd-flow/memory-bootstrap-authority@1", request_id: scope.requestId,
87
+ project_root: scope.projectRoot, workspace_root: scope.workspaceRoot, flow_id: "mb-upgrade", readiness: "ready",
88
+ model_access: "unknown", bootstrap_sha256: hash(bytes(receipt)), binding, receipt, evidence };
89
+ return { authority, admission, projectId: retained.receipt.project_id, hasPreservationBaseline: p.current.old_tree !== undefined,
90
+ hasLintCapability: binding.lint !== undefined, hasGitPolicy: p.git !== undefined, hasFlowCapability: binding.flow !== undefined };
91
+ }
92
+ /** Accepted storage is the independent input record. A lone bootstrap marker
93
+ * cannot manufacture its selection, execution or receipt bytes. No filesystem. */
94
+ export function readMemoryUpgradeBootstrapReadiness(context, scope) {
95
+ try {
96
+ return context.db.readSnapshot(() => {
97
+ const query = (logical) => context.db.all("SELECT project_id,payload_json,created_at FROM audit_events WHERE event_type=? AND json_extract(payload_json,'$.request_id')=? AND json_extract(payload_json,'$.project_root')=? AND json_extract(payload_json,'$.workspace_root')=? LIMIT 2", [eventType, logical.requestId, logical.projectRoot, logical.workspaceRoot]);
98
+ let logical = scope, rows = query(scope);
99
+ if (!rows.length) {
100
+ try {
101
+ logical = resolveUpgradeHistoricalScope(context, scope).scope;
102
+ }
103
+ catch (error) {
104
+ if (error instanceof AppError && error.details?.reason === 'project_not_active')
105
+ return null;
106
+ throw error;
107
+ }
108
+ rows = query(logical);
109
+ }
110
+ if (!rows.length)
111
+ return null;
112
+ if (rows.length !== 1 || Buffer.byteLength(rows[0].payload_json) > 4 * 1024 * 1024)
113
+ refuse("ambiguous_bootstrap_authority");
114
+ const value = JSON.parse(rows[0].payload_json), binding = value.binding;
115
+ if (!binding || Object.keys(binding).filter(key => key !== "lint" && key !== "flow").sort().join() !== "engine_manifest_base64,execution_sha256,scope,selection_sha256,storage_sha256"
116
+ || hybridDigest(binding.scope) !== hybridDigest(logical))
117
+ refuse("invalid_bootstrap_binding");
118
+ const selected = material(context, binding);
119
+ if (rows[0].project_id !== selected.projectId || hybridDigest(value) !== hybridDigest(selected.authority))
120
+ refuse("bootstrap_authority_changed");
121
+ return { ...selected, createdAt: rows[0].created_at };
122
+ });
123
+ }
124
+ catch (error) {
125
+ if (error instanceof AppError)
126
+ throw error;
127
+ return refuse("invalid_bootstrap_authority");
128
+ }
129
+ }
130
+ export class PreparedMemoryUpgradeBootstrapReadiness {
131
+ #binding;
132
+ #material;
133
+ #lint;
134
+ constructor(binding, selected, lint) {
135
+ this.#binding = structuredClone(binding);
136
+ this.#material = selected;
137
+ this.#lint = lint;
138
+ Object.freeze(this);
139
+ }
140
+ /** A relocated, already allocated RUN keeps original bootstrap/migration
141
+ * bytes. Admit its current stores without replaying the old cutover in the
142
+ * new Home. This never allocates a RUN or creates a new readiness receipt. */
143
+ static assertForRetainedRun(context, bundle) {
144
+ if (!(bundle instanceof RetainedExecutionBundle) || bundle.manifest.flow_id !== "mb-upgrade")
145
+ refuse("retained_upgrade_bundle_required");
146
+ const frozen = bundle.execution.snapshot().scope;
147
+ const scope = { requestId: frozen.requestId, projectRoot: frozen.projectRoot, workspaceRoot: frozen.workspace };
148
+ const { projectId } = resolveUpgradeHistoricalScope(context, scope);
149
+ assertPreparedRunBundleSqlAuthority(context, { projectId, runId: bundle.manifest.run_id }, bundle);
150
+ if (!runContextRelocations(context, projectId, bundle.manifest.run_id).length) {
151
+ this.prepare(context, scope);
152
+ return;
153
+ }
154
+ const ready = readMemoryUpgradeBootstrapReadiness(context, scope), reference = bundle.manifest.bootstrap_receipts[0];
155
+ if (!ready?.hasPreservationBaseline || !ready.hasLintCapability || !ready.hasFlowCapability
156
+ || ready.projectId !== projectId || ready.authority.binding.execution_sha256 !== bundle.execution.sha256
157
+ || bundle.manifest.bootstrap_receipts.length !== 1 || reference?.sha256 !== ready.authority.bootstrap_sha256
158
+ || !bundle.blob(reference.path).equals(bytes(ready.authority.receipt)))
159
+ refuse("retained_bootstrap_changed");
160
+ assertUpgradeExecutionStorage(context, bundle.engine());
161
+ }
162
+ /** Full productive prerequisite path; never install or repair global tools.
163
+ * Exact replay retains the first functional qualification instead of probing
164
+ * again after effects or choosing a different executable from today's PATH. */
165
+ static prepareForRun(context, scope) {
166
+ if (context.db.isOwnedWriteTransaction?.())
167
+ refuse("preparation_outside_writer_required");
168
+ const storage = readUpgradeStorageReadiness(context, scope), git = storage?.selection?.payload.git;
169
+ if (!git)
170
+ refuse("historical_selection_requires_new_request");
171
+ if (hash(readBoundedReleaseFile(git.executable, 64 * 1024 * 1024)) !== git.probe.executable_sha256)
172
+ refuse("selected_git_changed");
173
+ const prior = readMemoryUpgradeBootstrapReadiness(context, scope);
174
+ if (prior) {
175
+ const lint = prior.authority.binding.lint;
176
+ if (!lint || !prior.hasFlowCapability)
177
+ refuse("historical_bootstrap_requires_new_request");
178
+ if (hash(readBoundedReleaseFile(lint.executable, 64 * 1024 * 1024)) !== lint.executable_sha256)
179
+ refuse("selected_linter_changed");
180
+ return this.prepare(context, scope);
181
+ }
182
+ if (!storage?.receipt.selection)
183
+ refuse("accepted_storage_required");
184
+ const retained = storage.receipt.selection;
185
+ const restored = restoreMemoryUpgradeSelectionData(Buffer.from(retained.payload_json), retained.sha256, retained.request_input, scope);
186
+ const flow = restored.engine.admitMemoryUpgradeFlow(restored.source);
187
+ const selected = inspectMemoryLintExecutable(context.env);
188
+ return this.#prepare(context, scope, PreparedMemoryInitLintCapability.prepareExecutable(selected.executable, selected.probe, context.env, { temporaryConfiguration: true }), flow);
189
+ }
190
+ static prepare(context, scope, lint) {
191
+ if (context.db.isOwnedWriteTransaction?.())
192
+ refuse("preparation_outside_writer_required");
193
+ if (lint !== undefined && !(lint instanceof PreparedMemoryInitLintCapability))
194
+ refuse("prepared_lint_capability_required");
195
+ return this.#prepare(context, scope, lint, readMemoryUpgradeBootstrapReadiness(context, scope)?.authority.binding.flow);
196
+ }
197
+ static #prepare(context, scope, lint, flow) {
198
+ if (context.db.isOwnedWriteTransaction?.())
199
+ refuse("preparation_outside_writer_required");
200
+ if (lint !== undefined && !(lint instanceof PreparedMemoryInitLintCapability))
201
+ refuse("prepared_lint_capability_required");
202
+ lint?.revalidateExecutable();
203
+ const lintFacts = lint?.facts() ?? readMemoryUpgradeBootstrapReadiness(context, scope)?.authority.binding.lint;
204
+ // Re-observe physical admission and the original old-tree before issuing
205
+ // fresh execution authority, even if a historical storage receipt exists.
206
+ PreparedUpgradeStorageReadiness.prepareFromSelection(context, scope);
207
+ const storage = readUpgradeStorageReadiness(context, scope);
208
+ if (!storage?.selection || !storage.receipt.selection)
209
+ refuse("accepted_storage_required");
210
+ const retained = storage.receipt.selection;
211
+ const selected = restoreMemoryUpgradeSelectionData(Buffer.from(retained.payload_json, "utf8"), retained.sha256, retained.request_input, scope);
212
+ if (!selected.oldTree)
213
+ refuse("preservation_baseline_required");
214
+ const validate = prepareMemoryInitBootstrapSchema(selected.engine);
215
+ const binding = { scope: { ...scope }, storage_sha256: storage.sha256, selection_sha256: selected.sha256,
216
+ execution_sha256: selected.execution.sha256, engine_manifest_base64: selected.engine.manifestBytes().toString("base64"), ...(lintFacts ? { lint: lintFacts } : {}),
217
+ ...(flow ? { flow } : {}) };
218
+ const prepared = context.db.readSnapshot(() => material(context, binding));
219
+ if (!validate(prepared.authority.receipt)
220
+ || validateHybridContract("memory-bootstrap-receipt", prepared.authority.receipt, prepared.admission).length)
221
+ refuse("selected_engine_bootstrap_contract_invalid");
222
+ return new PreparedMemoryUpgradeBootstrapReadiness(binding, prepared, lint);
223
+ }
224
+ apply(context) {
225
+ const prior = readMemoryUpgradeBootstrapReadiness(context, this.#binding.scope);
226
+ if (prior) {
227
+ if (hybridDigest(prior.authority) !== hybridDigest(this.#material.authority))
228
+ refuse("bootstrap_request_changed");
229
+ return { ...prior, changed: false };
230
+ }
231
+ const current = PreparedMemoryUpgradeBootstrapReadiness.#prepare(context, this.#binding.scope, this.#lint, this.#binding.flow);
232
+ if (hybridDigest(current.#material.authority) !== hybridDigest(this.#material.authority))
233
+ refuse("bootstrap_changed_after_preparation");
234
+ return context.db.writeTransaction(() => {
235
+ const existing = readMemoryUpgradeBootstrapReadiness(context, this.#binding.scope);
236
+ if (existing) {
237
+ if (hybridDigest(existing.authority) !== hybridDigest(this.#material.authority))
238
+ refuse("bootstrap_request_changed");
239
+ return { ...existing, changed: false };
240
+ }
241
+ const selected = material(context, this.#binding);
242
+ if (hybridDigest(selected.authority) !== hybridDigest(this.#material.authority))
243
+ refuse("bootstrap_dependencies_changed");
244
+ appendAudit(context, { projectId: selected.projectId, eventType, payload: selected.authority });
245
+ const accepted = readMemoryUpgradeBootstrapReadiness(context, this.#binding.scope);
246
+ if (!accepted)
247
+ refuse("bootstrap_readback_failed");
248
+ return { ...accepted, changed: true };
249
+ }, "memoryUpgrade.bootstrapReadiness");
250
+ }
251
+ }
@@ -0,0 +1,100 @@
1
+ import { createHash } from "node:crypto";
2
+ import { AppError } from "../shared/errors.js";
3
+ import { readUpgradeStorageReadiness } from "./memory-upgrade-storage-readiness.js";
4
+ import { readUpgradePreservationBaseline, readUpgradeProjectFiles } from "./memory-upgrade-inventory.js";
5
+ import { localEnvironmentAllowed } from "./workspace-files.js";
6
+ import { PreparedMemoryLayer } from "./memory-layer.js";
7
+ import { readRunStartRequest } from "./run-start-custody.js";
8
+ export const upgradeEvidenceIndexPath = "upgrade-baseline.json";
9
+ const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
10
+ export const upgradeEvidenceFilePath = (sha256) => `upgrade-baseline-${sha256}.bin`;
11
+ export const upgradeTargetIndexPath = "upgrade-target.json";
12
+ export const upgradeTargetFilePath = (sha256) => `upgrade-target-${sha256}.bin`;
13
+ function refuse(reason) {
14
+ throw new AppError("memory_upgrade_evidence_invalid", "Old document evidence requires the retained upgrade selection", 2, { reason, effect: "no_effect" });
15
+ }
16
+ /** SQL-selected old bytes, not today's workspace or agent-proposed paths.
17
+ * RUN start publishes these using its existing retained artifact/replay owner.
18
+ * Equal content shares a copy; the index retains original paths and modes.
19
+ * Links are never followed; private/environment files are never materialized.
20
+ * Optional link identities are frozen literal metadata inside this regular index.
21
+ */
22
+ export function readMemoryUpgradeEvidence(context, scope) {
23
+ const selected = readUpgradeStorageReadiness(context, scope)?.selection;
24
+ if (!selected?.payload.current.old_tree)
25
+ refuse("retained_old_tree_required");
26
+ const files = readUpgradePreservationBaseline(selected.payload.current.old_tree, selected.payload.current.inventory);
27
+ const artifacts = new Map();
28
+ const entries = [];
29
+ const projectFiles = readUpgradeProjectFiles(selected.payload.current.project_files ?? []);
30
+ const sources = [...files].map(([logical, file]) => [`.memory-bank/${logical}`, file]);
31
+ const excluded = sources.filter(([logical, file]) => file.kind !== "file" || logical.split("/").some(part => [".git", "node_modules", ".dd-flow"].includes(part) || !localEnvironmentAllowed(part))).length;
32
+ for (const file of projectFiles)
33
+ sources.push([file.path, { kind: "file", bytes: Buffer.from(file.base64, "base64"), mode: file.mode, sha256: file.sha256 }]);
34
+ for (const [logical, file] of sources) {
35
+ if (file.kind !== "file" || logical.split("/").some(part => [".git", "node_modules", ".dd-flow"].includes(part) || !localEnvironmentAllowed(part)))
36
+ continue;
37
+ if (file.bytes.length > 16 * 1024 * 1024)
38
+ refuse("old_document_exceeds_read_bound");
39
+ const retained = { root: "run", path: upgradeEvidenceFilePath(file.sha256), sha256: file.sha256 };
40
+ artifacts.set(retained.path, file.bytes);
41
+ entries.push({ source: { root: "workspace", path: logical, sha256: file.sha256 }, retained, mode: file.mode });
42
+ }
43
+ const index = { schema_id: "dd-flow/memory-upgrade-evidence@1", selection_sha256: selected.sha256,
44
+ ...(selected.payload.current.project_links?.length ? { project_link_metadata: selected.payload.current.project_links } : {}),
45
+ entries, excluded_entries: excluded };
46
+ const bytes = Buffer.from(JSON.stringify(index));
47
+ if (bytes.length > 16 * 1024 * 1024)
48
+ refuse("evidence_index_exceeds_read_bound");
49
+ const reference = { root: "run", path: upgradeEvidenceIndexPath, sha256: hash(bytes) };
50
+ artifacts.set(reference.path, bytes);
51
+ // Custody readers need the index, not publication copies. Keep full source
52
+ // validation above, and encode the deduplicated artifacts only on demand.
53
+ let encoded;
54
+ return { index, reference, get artifacts() {
55
+ if (!encoded) {
56
+ encoded = [...artifacts].map(([path, bytes]) => ({ path, base64: bytes.toString("base64") }));
57
+ artifacts.clear();
58
+ }
59
+ return encoded;
60
+ } };
61
+ }
62
+ /** Target guidance is distinct from old project evidence. Only frozen canonical
63
+ * layer bytes are exported, never today's installation or a caller's files. */
64
+ export function readMemoryUpgradeTargetEvidence(context, scope) {
65
+ const selected = readUpgradeStorageReadiness(context, scope)?.selection;
66
+ if (!selected)
67
+ refuse("retained_target_required");
68
+ const payload = selected.payload, frozen = payload.layer;
69
+ const files = PreparedMemoryLayer.restoreRetained(new Map(frozen.files.map(file => [file.path, Buffer.from(file.base64, "base64")])), frozen.sha256, frozen.installation_sha256).files();
70
+ const artifacts = new Map();
71
+ const entries = [...files].map(([logical, bytes]) => {
72
+ const sha256 = hash(bytes), retained = { root: "run", path: upgradeTargetFilePath(sha256), sha256 };
73
+ artifacts.set(retained.path, { path: retained.path, base64: bytes.toString("base64") });
74
+ return { path: `.memory-bank/${logical}`, retained };
75
+ });
76
+ const index = { schema_id: "dd-flow/memory-upgrade-target@1", selection_sha256: selected.sha256,
77
+ source_version: payload.current.canon_version, target_version: selected.release.canon.version,
78
+ ...(payload.current.flow_pack_canon_version ? { source_flow_pack_version: payload.current.flow_pack_canon_version } : {}),
79
+ ...(payload.current.version_source ? { version_marker_update: { path: `.memory-bank/${payload.current.version_source}`,
80
+ field: "memory_bank_version", target_version: selected.release.canon.version, operation: "cli_marker_only" } } : {}),
81
+ layer_sha256: frozen.sha256, impact: payload.impact, inventory: payload.current.inventory, entries };
82
+ const bytes = Buffer.from(JSON.stringify(index));
83
+ if (bytes.length > 16 * 1024 * 1024)
84
+ refuse("target_index_exceeds_read_bound");
85
+ const reference = { root: "run", path: upgradeTargetIndexPath, sha256: hash(bytes) };
86
+ artifacts.set(reference.path, { path: reference.path, base64: bytes.toString("base64") });
87
+ return { index, reference, artifacts: [...artifacts.values()] };
88
+ }
89
+ /** Older RUNs keep their original packets; presence comes from allocated SQL
90
+ * custody, not a stray file or today's target selection. */
91
+ export function readIssuedMemoryUpgradeTarget(context, scope, projectId) {
92
+ const request = readRunStartRequest(context, projectId, scope.requestId);
93
+ const artifact = request?.payload.artifacts.find(file => file.path === upgradeTargetIndexPath);
94
+ if (!artifact)
95
+ return null;
96
+ const target = readMemoryUpgradeTargetEvidence(context, scope);
97
+ if (artifact.base64 !== target.artifacts.find(file => file.path === upgradeTargetIndexPath).base64)
98
+ refuse("target_allocation_changed");
99
+ return target;
100
+ }