@deksden-com/dd-flow-cli 0.9.0-beta.137 → 0.9.0-beta.139

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 (283) hide show
  1. package/CHANGELOG.md +19 -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 +197 -0
  7. package/dist/cli/command-option-descriptions.js +191 -0
  8. package/dist/cli/completion-cli.js +70 -0
  9. package/dist/cli/completion.js +57 -0
  10. package/dist/cli/error-output.js +52 -0
  11. package/dist/cli/executor-onboarding.js +76 -0
  12. package/dist/cli/flows.js +29 -0
  13. package/dist/cli/harnesses.js +84 -0
  14. package/dist/cli/help.js +240 -6
  15. package/dist/cli/input-preparation.js +54 -5
  16. package/dist/cli/memory-flow-admission.js +44 -0
  17. package/dist/cli/memory-init-invocation.js +78 -0
  18. package/dist/cli/memory-init.js +240 -0
  19. package/dist/cli/memory-storage-admission.js +53 -0
  20. package/dist/cli/models.js +39 -0
  21. package/dist/cli/native-hook-ingress.js +1 -1
  22. package/dist/cli/operator-profiles.js +61 -0
  23. package/dist/cli/output-options.js +35 -0
  24. package/dist/cli/response-file.js +71 -0
  25. package/dist/cli/run-cli.js +283 -160
  26. package/dist/cli/runtime-process.js +1 -1
  27. package/dist/cli/setup.js +149 -0
  28. package/dist/cli.js +56 -2
  29. package/dist/domain/stage-handler-identities.js +20 -0
  30. package/dist/harness-runtime/lib/daemon-operations.d.mts +1 -0
  31. package/dist/harness-runtime/lib/daemon-operations.mjs +4 -3
  32. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +53 -22
  33. package/dist/harness-runtime/lib/dd-agy.mjs +16 -5
  34. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +12 -6
  35. package/dist/harness-runtime/lib/dd-codex.mjs +24 -12
  36. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +2 -1
  37. package/dist/harness-runtime/lib/dd-droid.mjs +32 -9
  38. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +11 -3
  39. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +100 -15
  40. package/dist/harness-runtime/lib/dd-opencode.mjs +51 -20
  41. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +22 -10
  42. package/dist/harness-runtime/lib/dd-zcode.mjs +17 -4
  43. package/dist/harness-runtime/lib/delegation-instructions.d.mts +1 -0
  44. package/dist/harness-runtime/lib/delegation-instructions.mjs +16 -3
  45. package/dist/harness-runtime/lib/lease-renewal.mjs +2 -1
  46. package/dist/harness-runtime/lib/lifecycle-command.mjs +1 -0
  47. package/dist/harness-runtime/lib/managed-daemon.d.mts +1 -0
  48. package/dist/harness-runtime/lib/managed-daemon.mjs +50 -15
  49. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  50. package/dist/harness-runtime/lib/native-children.d.mts +2 -0
  51. package/dist/harness-runtime/lib/native-children.mjs +20 -1
  52. package/dist/harness-runtime/lib/native-hook-command.mjs +1 -1
  53. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  54. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  55. package/dist/harness-runtime/lib/opencode-plugin.mjs +32 -9
  56. package/dist/harness-runtime/lib/operation-progress.mjs +3 -1
  57. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +13 -0
  58. package/dist/harness-runtime/lib/provider-overload-policy.mjs +138 -0
  59. package/dist/runtime/context.js +1 -1
  60. package/dist/schemas/discovery-result.schema.json +184 -0
  61. package/dist/schemas/execution-bundle.schema.json +205 -0
  62. package/dist/schemas/execution-settings.schema.json +162 -0
  63. package/dist/schemas/flow-descriptor.schema.json +54 -0
  64. package/dist/schemas/flow-run.schema.json +26 -0
  65. package/dist/schemas/harness-catalog.schema.json +80 -0
  66. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  67. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  68. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  69. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  70. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  71. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  72. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  73. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  74. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  75. package/dist/schemas/memory-repair-work-result.schema.json +49 -0
  76. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  77. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  78. package/dist/schemas/model-catalog.schema.json +153 -0
  79. package/dist/schemas/profile-settings.schema.json +122 -0
  80. package/dist/schemas/release-manifest.schema.json +291 -0
  81. package/dist/schemas/run-engine-binding.schema.json +1 -1
  82. package/dist/services/check-runner-evidence.js +51 -4
  83. package/dist/services/cli-operation-classifier.js +8 -47
  84. package/dist/services/cli-upgrade-allowlist.js +27 -0
  85. package/dist/services/code-checks.js +387 -34
  86. package/dist/services/controller-child-capacity.js +13 -0
  87. package/dist/services/controller-child-observer.js +18 -2
  88. package/dist/services/controller-execution.js +88 -0
  89. package/dist/services/controller-fanout.js +71 -12
  90. package/dist/services/dashboard.js +8 -2
  91. package/dist/services/descriptor-coordinator-session.js +35 -0
  92. package/dist/services/descriptor-root-work.js +53 -0
  93. package/dist/services/descriptor-run-settlement.js +105 -0
  94. package/dist/services/descriptor-run-start.js +449 -0
  95. package/dist/services/descriptor-stage-coordinator.js +197 -0
  96. package/dist/services/descriptor-stage-settlement.js +222 -0
  97. package/dist/services/descriptor-stage-start.js +139 -0
  98. package/dist/services/discovery/agy-discovery.js +2 -0
  99. package/dist/services/discovery/codex-discovery.js +2 -0
  100. package/dist/services/discovery/droid-discovery.js +2 -0
  101. package/dist/services/discovery/grok-discovery.js +2 -0
  102. package/dist/services/discovery/opencode-discovery.js +2 -0
  103. package/dist/services/discovery/static.js +31 -0
  104. package/dist/services/discovery/zcode-discovery.js +2 -0
  105. package/dist/services/engines.js +39 -22
  106. package/dist/services/eval-snapshots.js +83 -25
  107. package/dist/services/execution-bundles.js +263 -0
  108. package/dist/services/execution-policy.js +20 -16
  109. package/dist/services/executor-onboarding.js +56 -0
  110. package/dist/services/external-work-launch.js +93 -15
  111. package/dist/services/flow-catalog.js +21 -0
  112. package/dist/services/flow-descriptors.js +82 -0
  113. package/dist/services/frozen-engine.js +250 -0
  114. package/dist/services/generic-execution.js +164 -0
  115. package/dist/services/harness-adapter.js +28 -2
  116. package/dist/services/harness-discovery.js +29 -0
  117. package/dist/services/harness-doctor.js +75 -0
  118. package/dist/services/harness-probe-effects.js +51 -0
  119. package/dist/services/harness-version-probe.js +100 -0
  120. package/dist/services/hooks.js +24 -6
  121. package/dist/services/hybrid-contracts.js +483 -0
  122. package/dist/services/ids.js +29 -1
  123. package/dist/services/installation-lock.js +95 -0
  124. package/dist/services/installed-flow-source.js +183 -0
  125. package/dist/services/lifecycle-invocations.js +257 -78
  126. package/dist/services/managed-processes.js +31 -10
  127. package/dist/services/memory-accepted-composition.js +77 -0
  128. package/dist/services/memory-baseline-preservation.js +65 -0
  129. package/dist/services/memory-completed-correction-wave.js +320 -0
  130. package/dist/services/memory-compose-handler.js +258 -0
  131. package/dist/services/memory-composition-acceptance.js +199 -0
  132. package/dist/services/memory-composition-graph.js +134 -0
  133. package/dist/services/memory-composition-registration.js +146 -0
  134. package/dist/services/memory-composition-work-custody.js +151 -0
  135. package/dist/services/memory-composition-work-results.js +96 -0
  136. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  137. package/dist/services/memory-corrected-review-batch.js +30 -0
  138. package/dist/services/memory-corrected-review-findings.js +106 -0
  139. package/dist/services/memory-corrected-review-inputs.js +210 -0
  140. package/dist/services/memory-corrected-review-projection.js +78 -0
  141. package/dist/services/memory-corrected-review-receipt.js +170 -0
  142. package/dist/services/memory-corrected-review-registration.js +191 -0
  143. package/dist/services/memory-correction-check-receipt.js +219 -0
  144. package/dist/services/memory-correction-input-owner.js +6 -0
  145. package/dist/services/memory-discover-handler.js +104 -0
  146. package/dist/services/memory-finish-evidence.js +435 -0
  147. package/dist/services/memory-finish-handler.js +215 -0
  148. package/dist/services/memory-finish-integration.js +280 -0
  149. package/dist/services/memory-finish-readiness.js +122 -0
  150. package/dist/services/memory-git-integration.js +151 -0
  151. package/dist/services/memory-historical-corrected-review.js +206 -0
  152. package/dist/services/memory-historical-original-review.js +130 -0
  153. package/dist/services/memory-historical-repair-registration.js +99 -0
  154. package/dist/services/memory-historical-second-review.js +128 -0
  155. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  156. package/dist/services/memory-init-contexts.js +89 -0
  157. package/dist/services/memory-init-controller-start.js +84 -0
  158. package/dist/services/memory-init-engine-release.js +223 -0
  159. package/dist/services/memory-init-git-policy.js +136 -0
  160. package/dist/services/memory-init-lint-capability.js +185 -0
  161. package/dist/services/memory-init-native-capacity.js +296 -0
  162. package/dist/services/memory-init-preflight.js +330 -0
  163. package/dist/services/memory-init-project-bootstrap.js +599 -0
  164. package/dist/services/memory-init-request-candidate.js +157 -0
  165. package/dist/services/memory-init-request-input.js +66 -0
  166. package/dist/services/memory-init-resource-storage.js +125 -0
  167. package/dist/services/memory-init-run-allocation.js +81 -0
  168. package/dist/services/memory-init-run-bundle.js +98 -0
  169. package/dist/services/memory-init-start.js +181 -0
  170. package/dist/services/memory-init-startup-custody.js +80 -0
  171. package/dist/services/memory-init-startup-input.js +240 -0
  172. package/dist/services/memory-init-storage.js +81 -0
  173. package/dist/services/memory-init-stores.js +359 -0
  174. package/dist/services/memory-init-worktrunk-capability.js +178 -0
  175. package/dist/services/memory-layer-publication.js +611 -0
  176. package/dist/services/memory-layer.js +156 -0
  177. package/dist/services/memory-lint-config.js +85 -0
  178. package/dist/services/memory-native-review-copy.js +165 -0
  179. package/dist/services/memory-normal-flow-entry.js +75 -0
  180. package/dist/services/memory-ordinary-defaults.js +112 -0
  181. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  182. package/dist/services/memory-preflight-handler.js +259 -0
  183. package/dist/services/memory-repair-current-view.js +299 -0
  184. package/dist/services/memory-repair-document-delta.js +451 -0
  185. package/dist/services/memory-repair-history.js +491 -0
  186. package/dist/services/memory-repair-physical-binding.js +312 -0
  187. package/dist/services/memory-repair-publication-files.js +152 -0
  188. package/dist/services/memory-repair-publication-intent.js +27 -0
  189. package/dist/services/memory-repair-publication-plan.js +160 -0
  190. package/dist/services/memory-repair-publication-source.js +225 -0
  191. package/dist/services/memory-repair-publication.js +794 -0
  192. package/dist/services/memory-repair-registration.js +239 -0
  193. package/dist/services/memory-repair-work-baseline.js +413 -0
  194. package/dist/services/memory-repair-work-completion.js +97 -0
  195. package/dist/services/memory-repair-work-custody.js +73 -0
  196. package/dist/services/memory-repair-work-results.js +89 -0
  197. package/dist/services/memory-repair-workspace.js +252 -0
  198. package/dist/services/memory-repair-writer-copy.js +735 -0
  199. package/dist/services/memory-result-binding.js +173 -0
  200. package/dist/services/memory-retained-review-authority.js +129 -0
  201. package/dist/services/memory-retained-review-results.js +70 -0
  202. package/dist/services/memory-retained-second-baseline.js +102 -0
  203. package/dist/services/memory-retained-second-repairs.js +156 -0
  204. package/dist/services/memory-review-acceptance.js +214 -0
  205. package/dist/services/memory-review-correction-plan.js +171 -0
  206. package/dist/services/memory-review-handler.js +585 -0
  207. package/dist/services/memory-review-inputs.js +200 -0
  208. package/dist/services/memory-review-receipt.js +180 -0
  209. package/dist/services/memory-review-registration.js +108 -0
  210. package/dist/services/memory-review-work-custody.js +124 -0
  211. package/dist/services/memory-review-work-input.js +72 -0
  212. package/dist/services/memory-review-work-results.js +73 -0
  213. package/dist/services/memory-second-corrected-review-inputs.js +165 -0
  214. package/dist/services/memory-second-correction-plan.js +76 -0
  215. package/dist/services/memory-second-repair-baseline.js +91 -0
  216. package/dist/services/memory-second-repair-launch.js +614 -0
  217. package/dist/services/memory-second-repair-registration.js +88 -0
  218. package/dist/services/memory-second-repair-source.js +187 -0
  219. package/dist/services/memory-second-review-acceptance.js +115 -0
  220. package/dist/services/memory-source-observations.js +117 -0
  221. package/dist/services/memory-stage-dispatch.js +28 -0
  222. package/dist/services/memory-stage-results.js +199 -0
  223. package/dist/services/memory-verification-acceptance.js +135 -0
  224. package/dist/services/memory-verification-checks.js +252 -0
  225. package/dist/services/memory-verification-receipt.js +159 -0
  226. package/dist/services/memory-verify-handler.js +135 -0
  227. package/dist/services/memory-work-result-preparation.js +63 -0
  228. package/dist/services/merge-server.js +2 -4
  229. package/dist/services/model-catalog.js +109 -0
  230. package/dist/services/model-discovery.js +46 -0
  231. package/dist/services/operator-profiles.js +236 -0
  232. package/dist/services/projects.js +17 -2
  233. package/dist/services/{codex-capacity.js → provider-capacity.js} +34 -16
  234. package/dist/services/recovery-snapshot-database.js +417 -2
  235. package/dist/services/release-archive-producer.js +52 -0
  236. package/dist/services/release-archive.js +143 -0
  237. package/dist/services/release-cache.js +142 -0
  238. package/dist/services/release-compatibility.js +18 -0
  239. package/dist/services/release-download.js +67 -0
  240. package/dist/services/release-envelope.js +104 -0
  241. package/dist/services/release-manifest.js +45 -0
  242. package/dist/services/release-payload.js +114 -0
  243. package/dist/services/release-producer.js +63 -0
  244. package/dist/services/release-provenance.js +160 -0
  245. package/dist/services/release-registry.js +66 -0
  246. package/dist/services/release-source.js +194 -0
  247. package/dist/services/repair-intents.js +1 -1
  248. package/dist/services/review-copy.js +10 -2
  249. package/dist/services/run-control.js +80 -9
  250. package/dist/services/run-controller-adapter.js +1 -1
  251. package/dist/services/run-controller-capture.js +10 -3
  252. package/dist/services/run-controller-process.js +21 -0
  253. package/dist/services/run-controller-recovery.js +5 -5
  254. package/dist/services/run-controller-state.js +1 -1
  255. package/dist/services/run-controller.js +158 -64
  256. package/dist/services/run-recovery-guard.js +5 -3
  257. package/dist/services/run-recovery-runtime.js +3 -3
  258. package/dist/services/run-recovery.js +145 -5
  259. package/dist/services/run-start-custody.js +177 -0
  260. package/dist/services/runs.js +413 -30
  261. package/dist/services/setup.js +377 -0
  262. package/dist/services/stage-context.js +9 -1
  263. package/dist/services/stage-handlers.js +74 -0
  264. package/dist/services/stage-report-renderer.js +63 -0
  265. package/dist/services/stage-work-graph.js +17 -0
  266. package/dist/services/vnext-code-review.js +1 -1
  267. package/dist/services/vnext-code.js +6 -6
  268. package/dist/services/vnext-execution-profile.js +2 -2
  269. package/dist/services/vnext-fanout.js +73 -11
  270. package/dist/services/vnext-merge.js +8 -3
  271. package/dist/services/vnext-plan-review.js +7 -5
  272. package/dist/services/vnext-plan.js +3 -3
  273. package/dist/services/vnext-protocolize.js +20 -6
  274. package/dist/services/vnext-workspace-policy.js +7 -2
  275. package/dist/services/work-registry.js +616 -71
  276. package/dist/services/workspace-files.js +1 -1
  277. package/dist/storage/database.js +84 -6
  278. package/dist/storage/writer-contract.js +11 -7
  279. package/package.json +13 -3
  280. package/tools/create-canon-release.mjs +33 -0
  281. package/tools/produce-hybrid-release.mjs +41 -0
  282. package/dist/harness-runtime/lib/codex-capacity-policy.d.mts +0 -10
  283. package/dist/harness-runtime/lib/codex-capacity-policy.mjs +0 -102
@@ -5,6 +5,10 @@ import { AppError, errorRecord } from "../shared/errors.js";
5
5
  import { registerStoreWriter } from "../storage/writer-contract.js";
6
6
  import { managedProcessRuntimeHome } from "./managed-processes.js";
7
7
  import { cleanupScopeWriters } from "./scope-writer-cleanup.js";
8
+ import { hybridDigest } from "./hybrid-contracts.js";
9
+ import { readRunStartRequest } from "./run-start-custody.js";
10
+ import { readMemoryInitRunAllocation } from "./memory-init-run-allocation.js";
11
+ import { readMemoryInitStartupInput } from "./memory-init-startup-custody.js";
8
12
  /** Export one RUN's relational evidence, never mutate the live authority. */
9
13
  export function captureRecoveryDatabase(source, output, projectId, runId, protocolIds = []) {
10
14
  source.exec(`VACUUM INTO '${output.replace(/'/g, "''")}'`);
@@ -21,6 +25,8 @@ export function captureRecoveryDatabase(source, output, projectId, runId, protoc
21
25
  db.prepare("INSERT INTO capture_protocols VALUES (?)").run(id);
22
26
  if (!db.prepare("SELECT 1 FROM runs WHERE (project_id, id) IN (SELECT * FROM capture_scope)").get())
23
27
  throw new AppError("snapshot_run_missing", "Recovery export requires the selected RUN", 1);
28
+ assertCapturedBundleAuthority(db, projectId, runId);
29
+ assertCapturedStartAuthority(db, projectId, runId);
24
30
  const ownRun = "(project_id, run_id) IN (SELECT * FROM capture_scope)";
25
31
  const ownProject = "project_id IN (SELECT project_id FROM capture_scope)";
26
32
  const works = `SELECT work_id FROM works WHERE ${ownRun}`;
@@ -52,13 +58,354 @@ export function captureRecoveryDatabase(source, output, projectId, runId, protoc
52
58
  merge_servers: "0", merge_sessions: "0", merge_queue: "0", lanes: "0", lane_locks: "0", lane_waiters: "0",
53
59
  sqlite_sequence: "0"
54
60
  };
55
- for (const table of ["works", "stage_work_memberships", "repair_intents", "check_receipts", "merge_requests", "flow_run_flag_mutations", "usage", "flow_session_segments", "flow_jobs", "run_recovery_guards", "run_controllers", "run_controls"])
61
+ for (const table of ["works", "stage_work_memberships", "repair_intents", "check_receipts", "merge_requests", "flow_run_flag_mutations", "usage", "flow_session_segments", "flow_jobs", "run_recovery_guards", "run_controllers", "run_controls", "run_bundle_authorities", "run_start_requests"])
56
62
  rules[table] = ownRun;
57
63
  for (const table of ["plan_bindings", "plan_progress", "worktree_records", "audit_events"])
58
64
  rules[table] = `${ownProject} AND protocol_id IN (${protocols})`;
59
65
  // Relocation proofs are RUN-owned provenance needed to map unchanged context
60
66
  // bytes through subsequent recovery generations, not portable live authority.
61
- rules.audit_events = `${ownProject} AND (protocol_id IN (${protocols}) OR (event_type = 'flow_run.publication_relocation' AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)))`;
67
+ rules.audit_events = `${ownProject} AND (protocol_id IN (${protocols}) OR (event_type IN ('flow_run.publication_relocation', 'flow_run.workspace_rebound') AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)))`;
68
+ // Bootstrap precedes RUN/project allocation: some owning receipts have
69
+ // NULL project_id. Select only the captured MB bundle's independently
70
+ // anchored request/roots, never all bootstrap receipts for this project.
71
+ // This preserves bytes; the bootstrap readers still validate the complete
72
+ // release/target/policy/engine/readiness chain before admitting recovery.
73
+ if (db.prepare("SELECT 1 FROM sqlite_schema WHERE type='table' AND name='run_bundle_authorities'").get()) {
74
+ const bootstrapReceipts = `EXISTS (SELECT 1 FROM run_bundle_authorities b JOIN runs r
75
+ ON r.project_id=b.project_id AND r.id=b.run_id
76
+ WHERE (b.project_id,b.run_id) IN (SELECT * FROM capture_scope)
77
+ AND json_extract(r.index_json,'$.execution_bundle.flow_id')='mb-init'
78
+ AND (audit_events.project_id IS NULL OR audit_events.project_id=b.project_id)
79
+ AND (
80
+ (event_type IN ('memory.init_git_policy','memory.init_release_selection','memory.init_startup_input','memory.init_startup_input_intent','memory.init_project_bootstrap_intent',
81
+ 'memory.init_project_bootstrap','memory.init_engine_admission','memory.init_engine_bootstrap')
82
+ AND json_extract(payload_json,'$.scope.requestId')=json_extract(b.admission_json,'$.executionScope.requestId')
83
+ AND json_extract(payload_json,'$.scope.projectRoot')=json_extract(b.admission_json,'$.executionScope.projectRoot')
84
+ AND json_extract(payload_json,'$.scope.workspaceRoot')=json_extract(b.admission_json,'$.executionScope.workspace')
85
+ AND (
86
+ (event_type='memory.init_git_policy' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-git-policy@1')
87
+ OR (event_type='memory.init_release_selection' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-release-selection@1')
88
+ OR (audit_events.project_id IS NULL AND event_type='memory.init_startup_input' AND json_extract(payload_json,'$.schema_id') IN ('dd-flow/memory-init-startup-input@1','dd-flow/memory-init-startup-input@2','dd-flow/memory-init-startup-input@3'))
89
+ OR (audit_events.project_id IS NULL AND event_type='memory.init_startup_input_intent' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-startup-input-intent@1')
90
+ OR (event_type='memory.init_project_bootstrap_intent' AND json_extract(payload_json,'$.schema_id') IN
91
+ ('dd-flow/memory-init-project-bootstrap-intent@1','dd-flow/memory-init-project-bootstrap-intent@2','dd-flow/memory-init-project-bootstrap-intent@3','dd-flow/memory-init-project-bootstrap-intent@4'))
92
+ OR (event_type='memory.init_project_bootstrap' AND json_extract(payload_json,'$.receipt.schema_id') IN
93
+ ('dd-flow/memory-init-project-bootstrap@1','dd-flow/memory-init-project-bootstrap@2','dd-flow/memory-init-project-bootstrap@3','dd-flow/memory-init-project-bootstrap@4'))
94
+ OR (event_type='memory.init_engine_admission' AND json_extract(payload_json,'$.schema_id') IN
95
+ ('dd-flow/memory-init-engine-admission@1','dd-flow/memory-init-engine-admission@2'))
96
+ OR (event_type='memory.init_engine_bootstrap' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-engine-bootstrap@1')))
97
+ OR (audit_events.project_id=b.project_id
98
+ AND event_type IN ('memory.init_run_allocation','memory.init_run_allocation_intent')
99
+ AND json_extract(payload_json,'$.run_id')=b.run_id
100
+ AND json_extract(payload_json,'$.scope.requestId')=json_extract(b.admission_json,'$.executionScope.requestId')
101
+ AND json_extract(payload_json,'$.scope.projectRoot')=json_extract(b.admission_json,'$.executionScope.projectRoot')
102
+ AND json_extract(payload_json,'$.scope.workspaceRoot')=json_extract(b.admission_json,'$.executionScope.workspace')
103
+ AND ((event_type='memory.init_run_allocation' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-run-allocation@1')
104
+ OR (event_type='memory.init_run_allocation_intent' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-init-run-allocation-intent@1')))
105
+ OR (event_type IN ('memory.bootstrap_ready','memory.bootstrap_readiness_intent')
106
+ AND json_extract(payload_json,'$.request_id')=json_extract(b.admission_json,'$.executionScope.requestId')
107
+ AND json_extract(payload_json,'$.project_root')=json_extract(b.admission_json,'$.executionScope.projectRoot')
108
+ AND json_extract(payload_json,'$.workspace_root')=json_extract(b.admission_json,'$.executionScope.workspace')
109
+ AND ((event_type='memory.bootstrap_ready' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-bootstrap-authority@1')
110
+ OR (event_type='memory.bootstrap_readiness_intent' AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-bootstrap-readiness-intent@1')))))`;
111
+ rules.audit_events = `(${rules.audit_events}) OR (${bootstrapReceipts})`;
112
+ }
113
+ // Batch and composition registration are portable RUN evidence, not a host lease. Keep their
114
+ // independent receipt alongside the selected Works, never a neighboring
115
+ // RUN's receipt merely because it shares the project or names this RUN.
116
+ const batchReceipt = `event_type IN ('work.batch_registration', 'memory.composition_registration', 'memory.review_registration', 'memory.repair_registration', 'memory.second_repair_registration', 'memory.corrected_review_registration')
117
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
118
+ AND json_extract(payload_json, '$.scope.run_id') IN (SELECT run_id FROM capture_scope)
119
+ AND json_extract(payload_json, '$.scope.project_id') IN (SELECT project_id FROM capture_scope)
120
+ AND json_extract(payload_json, '$.scope.parent_work_id') IN (${works})
121
+ AND json_type(payload_json, '$.work_ids') = 'object'
122
+ AND NOT EXISTS (SELECT 1 FROM json_each(payload_json, '$.work_ids') WHERE value NOT IN (${works}))`;
123
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${batchReceipt}))`;
124
+ // Preserve independently admitted repair baselines by actual assigned
125
+ // Work/packet identity. Preservation never substitutes for owner admission.
126
+ const repairBaselineReceipt = `event_type = 'memory.repair_work_baseline'
127
+ AND json_extract(payload_json, '$.schema_id') IN ('dd-flow/memory-repair-work-baseline@2', 'dd-flow/memory-repair-work-baseline@3', 'dd-flow/memory-repair-work-baseline@4', 'dd-flow/memory-repair-work-baseline@5')
128
+ AND json_extract(payload_json, '$.project_id') = project_id
129
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
130
+ AND EXISTS (SELECT 1 FROM works w WHERE w.project_id=audit_events.project_id
131
+ AND w.run_id=json_extract(audit_events.payload_json, '$.run_id')
132
+ AND w.work_id=json_extract(audit_events.payload_json, '$.work_id')
133
+ AND json_extract(w.payload_json, '$.kind')='memory-repair'
134
+ AND json_extract(w.payload_json, '$.memory_repair.packet_sha256')=json_extract(audit_events.payload_json, '$.packet_sha256'))`;
135
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairBaselineReceipt}))`;
136
+ // A consumed dependency/peer view is part of the baseline's history. It
137
+ // predates WorkSession start, so do not require a start receipt here.
138
+ const repairCurrentViewReceipt = `event_type='memory.repair_current_view'
139
+ AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-repair-current-view@1'
140
+ AND json_extract(payload_json,'$.project_id')=project_id
141
+ AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
142
+ AND EXISTS (SELECT 1 FROM audit_events b WHERE (${repairBaselineReceipt.replaceAll("audit_events.", "b.")})
143
+ AND b.project_id=audit_events.project_id
144
+ AND json_extract(b.payload_json,'$.schema_id') IN ('dd-flow/memory-repair-work-baseline@3', 'dd-flow/memory-repair-work-baseline@5')
145
+ AND json_extract(b.payload_json,'$.run_id')=json_extract(audit_events.payload_json,'$.run_id')
146
+ AND json_extract(b.payload_json,'$.work_id')=json_extract(audit_events.payload_json,'$.work_id')
147
+ AND json_extract(b.payload_json,'$.generation')=json_extract(audit_events.payload_json,'$.generation')
148
+ AND json_extract(b.payload_json,'$.registration_sha256')=json_extract(audit_events.payload_json,'$.registration_sha256')
149
+ AND json_extract(b.payload_json,'$.current_view_sha256')=json_extract(audit_events.payload_json,'$.view_sha256'))`;
150
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairCurrentViewReceipt}))`;
151
+ const repairCopyReceipt = `event_type IN ('memory.repair_writer_copy_intent', 'memory.repair_writer_copy_build', 'memory.repair_writer_copy_ready')
152
+ AND json_extract(payload_json, '$.schema_id')='dd-flow/memory-repair-writer-copy-intent@1'
153
+ AND json_extract(payload_json, '$.project_id')=project_id
154
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
155
+ AND json_extract(payload_json, '$.work_id') IN (${works})
156
+ AND EXISTS (SELECT 1 FROM audit_events b JOIN works w
157
+ ON w.project_id=b.project_id AND w.run_id=json_extract(b.payload_json, '$.run_id')
158
+ AND w.work_id=json_extract(b.payload_json, '$.work_id')
159
+ WHERE b.project_id=audit_events.project_id AND b.event_type='memory.repair_work_baseline'
160
+ AND json_extract(b.payload_json, '$.schema_id') IN ('dd-flow/memory-repair-work-baseline@2', 'dd-flow/memory-repair-work-baseline@3', 'dd-flow/memory-repair-work-baseline@4', 'dd-flow/memory-repair-work-baseline@5')
161
+ AND json_extract(b.payload_json, '$.project_id')=b.project_id
162
+ AND json_extract(b.payload_json, '$.run_id')=json_extract(audit_events.payload_json, '$.run_id')
163
+ AND json_extract(b.payload_json, '$.work_id')=json_extract(audit_events.payload_json, '$.work_id')
164
+ AND json_extract(b.payload_json, '$.generation')=json_extract(audit_events.payload_json, '$.generation')
165
+ AND json_extract(b.payload_json, '$.workspace_root')=json_extract(audit_events.payload_json, '$.source_root')
166
+ AND json_extract(w.payload_json, '$.kind')='memory-repair'
167
+ AND json_extract(w.payload_json, '$.memory_repair.packet_sha256')=json_extract(b.payload_json, '$.packet_sha256'))`;
168
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairCopyReceipt}))`;
169
+ // Retain start evidence by relational WorkSession/physical Session and
170
+ // baseline generation. Export is preservation, never start admission.
171
+ const repairStartReceipt = `event_type='memory.repair_work_start'
172
+ AND json_extract(payload_json, '$.schema_id')='dd-flow/memory-repair-start@1'
173
+ AND json_extract(payload_json, '$.project_id')=project_id
174
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
175
+ AND EXISTS (SELECT 1 FROM works w JOIN work_sessions ws ON ws.work_id=w.work_id
176
+ JOIN sessions s ON s.project_id=w.project_id AND s.session_id=ws.session_id
177
+ JOIN audit_events b ON b.project_id=w.project_id AND b.event_type='memory.repair_work_baseline'
178
+ WHERE w.project_id=audit_events.project_id AND w.run_id=json_extract(audit_events.payload_json, '$.run_id')
179
+ AND w.work_id=json_extract(audit_events.payload_json, '$.work_id')
180
+ AND json_extract(w.payload_json, '$.kind')='memory-repair'
181
+ AND ws.id=json_extract(audit_events.payload_json, '$.work_session_id')
182
+ AND ws.session_id=json_extract(audit_events.payload_json, '$.session_id')
183
+ AND ws.hook_event_id=json_extract(audit_events.payload_json, '$.hook_event_id')
184
+ AND s.harness=json_extract(audit_events.payload_json, '$.harness')
185
+ AND s.provider_session_id=json_extract(audit_events.payload_json, '$.provider_session_id')
186
+ AND json_extract(b.payload_json, '$.schema_id') IN ('dd-flow/memory-repair-work-baseline@2', 'dd-flow/memory-repair-work-baseline@3', 'dd-flow/memory-repair-work-baseline@4', 'dd-flow/memory-repair-work-baseline@5')
187
+ AND json_extract(b.payload_json, '$.project_id')=w.project_id
188
+ AND json_extract(b.payload_json, '$.run_id')=w.run_id
189
+ AND json_extract(b.payload_json, '$.work_id')=w.work_id
190
+ AND json_extract(b.payload_json, '$.generation')=json_extract(audit_events.payload_json, '$.generation')
191
+ AND json_extract(b.payload_json, '$.packet_sha256')=json_extract(w.payload_json, '$.memory_repair.packet_sha256'))`;
192
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairStartReceipt}))`;
193
+ const nativeRepairBinding = `event_type='memory.repair_native_binding'
194
+ AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-repair-native-binding@1'
195
+ AND json_extract(payload_json,'$.project_id')=project_id
196
+ AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
197
+ AND EXISTS (SELECT 1 FROM works w JOIN work_sessions ws ON ws.work_id=w.work_id
198
+ JOIN sessions s ON s.project_id=w.project_id AND s.session_id=ws.session_id
199
+ JOIN hook_events he ON he.project_id=w.project_id AND he.event_key=ws.hook_event_id
200
+ WHERE w.project_id=audit_events.project_id AND w.run_id=json_extract(audit_events.payload_json,'$.run_id')
201
+ AND w.work_id=json_extract(audit_events.payload_json,'$.work_id')
202
+ AND json_extract(w.payload_json,'$.kind')='memory-repair'
203
+ AND ws.id=json_extract(audit_events.payload_json,'$.work_session_id')
204
+ AND he.event_key=json_extract(audit_events.payload_json,'$.hook_event_key') AND he.status='claimed'
205
+ AND he.session_id=ws.session_id AND s.provider_session_id=json_extract(audit_events.payload_json,'$.binding.provider_session_id')
206
+ AND he.parent_session_id=json_extract(audit_events.payload_json,'$.parent_session_id'))`;
207
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${nativeRepairBinding}))`;
208
+ const nativeReviewCopy = `event_type IN ('memory.native_review_copy_intent','memory.native_review_copy_ready')
209
+ AND COALESCE(json_extract(payload_json,'$.run_id'),json_extract(payload_json,'$.intent.run_id')) IN (SELECT run_id FROM capture_scope)
210
+ AND EXISTS (SELECT 1 FROM works w WHERE w.project_id=audit_events.project_id
211
+ AND w.run_id=COALESCE(json_extract(audit_events.payload_json,'$.run_id'),json_extract(audit_events.payload_json,'$.intent.run_id'))
212
+ AND w.work_id=COALESCE(json_extract(audit_events.payload_json,'$.work_id'),json_extract(audit_events.payload_json,'$.intent.work_id'))
213
+ AND json_extract(w.payload_json,'$.kind')='memory-review')`;
214
+ const nativeReviewBinding = `event_type='memory.native_review_binding'
215
+ AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
216
+ AND EXISTS (SELECT 1 FROM works w JOIN work_sessions ws ON ws.work_id=w.work_id
217
+ JOIN sessions s ON s.project_id=w.project_id AND s.session_id=ws.session_id
218
+ JOIN hook_events he ON he.project_id=w.project_id AND he.event_key=ws.hook_event_id
219
+ WHERE w.project_id=audit_events.project_id AND w.run_id=json_extract(audit_events.payload_json,'$.run_id')
220
+ AND w.work_id=json_extract(audit_events.payload_json,'$.work_id') AND json_extract(w.payload_json,'$.kind')='memory-review'
221
+ AND ws.id=json_extract(audit_events.payload_json,'$.work_session_id') AND he.status='claimed'
222
+ AND he.event_key=json_extract(audit_events.payload_json,'$.hook_event_key') AND he.session_id=ws.session_id
223
+ AND s.provider_session_id=json_extract(audit_events.payload_json,'$.provider_session_id'))`;
224
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND ((${nativeReviewCopy}) OR (${nativeReviewBinding})))`;
225
+ // Keep publication/settlement evidence only with the selected relational
226
+ // start and baseline. Export preserves bytes, never admits their hashes,
227
+ // physical effects or semantic correctness on restoration.
228
+ const repairPublicationSchemas = [
229
+ ["memory.repair_publication_source", "dd-flow/memory-repair-publication-source@1"],
230
+ ["memory.repair_publication_intent", "dd-flow/memory-repair-publication-intent@1"],
231
+ ["memory.repair_publication_intent", "dd-flow/memory-repair-publication-intent@2"],
232
+ ["memory.repair_publication_action_intent", "dd-flow/memory-repair-publication-action-intent@1"],
233
+ ["memory.repair_publication_staging_build", "dd-flow/memory-repair-publication-staging@1"],
234
+ ["memory.repair_publication_staging_ready", "dd-flow/memory-repair-publication-staging@1"],
235
+ ["memory.repair_publication_file_ready", "dd-flow/memory-repair-publication-file-ready@1"],
236
+ ["memory.repair_publication_directory_ready", "dd-flow/memory-repair-publication-directory-ready@1"],
237
+ ["memory.repair_publication_action_complete", "dd-flow/memory-repair-publication-action-complete@1"],
238
+ ["memory.repair_publication_complete", "dd-flow/memory-repair-publication-complete@1"],
239
+ ["memory.repair_work_settlement", "dd-flow/memory-repair-work-settlement@1"],
240
+ ];
241
+ const repairPublicationReceipt = `(${repairPublicationSchemas.map(([event, schema]) => `(event_type='${event}' AND json_extract(payload_json,'$.schema_id')='${schema}')`).join(" OR ")})
242
+ AND json_extract(payload_json,'$.project_id')=project_id
243
+ AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
244
+ AND EXISTS (SELECT 1 FROM audit_events a WHERE (${repairStartReceipt.replaceAll("audit_events.", "a.")})
245
+ AND a.project_id=audit_events.project_id
246
+ AND json_extract(a.payload_json,'$.run_id')=json_extract(audit_events.payload_json,'$.run_id')
247
+ AND json_extract(a.payload_json,'$.work_id')=json_extract(audit_events.payload_json,'$.work_id')
248
+ AND json_extract(a.payload_json,'$.generation')=json_extract(audit_events.payload_json,'$.generation')
249
+ AND json_extract(a.payload_json,'$.work_session_id')=json_extract(audit_events.payload_json,'$.work_session_id'))`;
250
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${repairPublicationReceipt}))`;
251
+ const coordinatorReceipt = `event_type = 'stage.coordinator_binding'
252
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
253
+ AND json_extract(payload_json, '$.scope.run_id') = json_extract(payload_json, '$.run_id')
254
+ AND json_extract(payload_json, '$.scope.project_id') = project_id
255
+ AND json_extract(payload_json, '$.work_id') IN (${works})
256
+ AND EXISTS (SELECT 1 FROM work_sessions ws WHERE ws.id = json_extract(payload_json, '$.work_session_id')
257
+ AND ws.work_id = json_extract(payload_json, '$.work_id') AND ws.session_id = json_extract(payload_json, '$.session_id'))
258
+ AND json_extract(payload_json, '$.session_id') IN (${sessions})`;
259
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${coordinatorReceipt}))`;
260
+ const descriptorRootReceipt = `event_type = 'flow_run.descriptor_root_work'
261
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
262
+ AND json_extract(payload_json, '$.binding.runId') = json_extract(payload_json, '$.run_id')
263
+ AND json_extract(payload_json, '$.binding.projectId') = project_id
264
+ AND json_extract(payload_json, '$.work_id') IN (${works})
265
+ AND EXISTS (SELECT 1 FROM runs r JOIN works w ON w.project_id=r.project_id AND w.run_id=r.id
266
+ WHERE r.project_id=audit_events.project_id AND r.id=json_extract(audit_events.payload_json, '$.run_id')
267
+ AND w.work_id=json_extract(audit_events.payload_json, '$.work_id') AND w.parent_work_id IS NULL
268
+ AND json_extract(r.index_json, '$.root_work_id')=w.work_id)`;
269
+ const descriptorCoordinatorReceipt = `event_type = 'flow_run.descriptor_coordinator'
270
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
271
+ AND json_extract(payload_json, '$.binding.runId') = json_extract(payload_json, '$.run_id')
272
+ AND json_extract(payload_json, '$.binding.projectId') = project_id
273
+ AND json_extract(payload_json, '$.work_id') IN (${works})
274
+ AND EXISTS (SELECT 1 FROM stage_work_memberships m WHERE m.project_id=audit_events.project_id
275
+ AND m.run_id=json_extract(audit_events.payload_json, '$.run_id') AND m.work_id=json_extract(audit_events.payload_json, '$.work_id')
276
+ AND m.stage=json_extract(audit_events.payload_json, '$.stage') AND m.attempt=json_extract(audit_events.payload_json, '$.binding.attempt'))`;
277
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND ((${descriptorRootReceipt}) OR (${descriptorCoordinatorReceipt})))`;
278
+ const descriptorSettlementReceipt = `event_type = 'flow_run.descriptor_stage_settlement'
279
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
280
+ AND json_extract(payload_json, '$.work_id') IN (${works})
281
+ AND EXISTS (SELECT 1 FROM stage_work_memberships m JOIN work_sessions ws ON ws.work_id=m.work_id
282
+ WHERE m.project_id=audit_events.project_id AND m.run_id=json_extract(audit_events.payload_json, '$.run_id')
283
+ AND m.work_id=json_extract(audit_events.payload_json, '$.work_id') AND m.stage=json_extract(audit_events.payload_json, '$.stage')
284
+ AND m.attempt=json_extract(audit_events.payload_json, '$.binding.attempt')
285
+ AND ws.id=json_extract(audit_events.payload_json, '$.work_session_id'))`;
286
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${descriptorSettlementReceipt}))`;
287
+ const memoryVerificationReceipt = `event_type = 'memory.verification_acceptance'
288
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
289
+ AND json_extract(payload_json, '$.project_id') = project_id
290
+ AND json_extract(payload_json, '$.schema_id') = 'dd-flow/memory-verification-acceptance@1'
291
+ AND json_extract(payload_json, '$.stage') = 'verify'
292
+ AND EXISTS (SELECT 1 FROM runs r, json_each(r.index_json, '$.stage_runs') s
293
+ WHERE r.project_id=audit_events.project_id AND r.id=json_extract(payload_json, '$.run_id')
294
+ AND json_extract(s.value, '$.stage')='verify' AND json_extract(s.value, '$.status')='done'
295
+ AND json_extract(s.value, '$.attempt')=json_extract(payload_json, '$.attempt')
296
+ AND json_extract(s.value, '$.input_sha256')=json_extract(payload_json, '$.input_sha256')
297
+ AND json_extract(s.value, '$.data_sha256')=json_extract(payload_json, '$.result_sha256'))`;
298
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryVerificationReceipt}))`;
299
+ // Preservation only, not admission: reconnect independently restores the
300
+ // corrected view, owning policy and exact passed check rows.
301
+ const memoryCorrectionCheckReceipt = `event_type = 'memory.correction_checks'
302
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
303
+ AND json_extract(payload_json, '$.project_id') = project_id
304
+ AND json_extract(payload_json, '$.schema_id') = 'dd-flow/memory-correction-checks@1'
305
+ AND json_extract(payload_json, '$.wave') IN (1, 2)
306
+ AND json_type(payload_json, '$.checks') = 'array'
307
+ AND json_array_length(payload_json, '$.checks') BETWEEN 1 AND 4096
308
+ AND EXISTS (SELECT 1 FROM runs r, json_each(r.index_json, '$.stage_runs') s
309
+ WHERE r.project_id=audit_events.project_id AND r.id=json_extract(payload_json, '$.run_id')
310
+ AND json_extract(s.value, '$.stage')='review'
311
+ AND json_extract(s.value, '$.input_sha256')=json_extract(payload_json, '$.review_input_sha256'))
312
+ AND NOT EXISTS (SELECT 1 FROM json_each(payload_json, '$.checks') c
313
+ WHERE NOT EXISTS (SELECT 1 FROM check_receipts cr WHERE cr.project_id=audit_events.project_id
314
+ AND cr.run_id=json_extract(audit_events.payload_json, '$.run_id') AND cr.id=json_extract(c.value, '$.id')))`;
315
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryCorrectionCheckReceipt}))`;
316
+ // Retain independently accepted review receipts only for the exact closed
317
+ // Stage and allocated reviewers. This is preservation, not replay admission.
318
+ const memoryReviewReceipt = `((event_type = 'memory.review_acceptance'
319
+ AND json_extract(payload_json, '$.schema_id') = 'dd-flow/memory-review-acceptance@1'
320
+ AND json_extract(payload_json, '$.wave') = 0)
321
+ OR (event_type = 'memory.corrected_review_acceptance'
322
+ AND json_extract(payload_json, '$.schema_id') = 'dd-flow/memory-corrected-review-acceptance@1'
323
+ AND (json_extract(payload_json, '$.wave') = 1
324
+ OR (json_extract(payload_json, '$.wave') = 2
325
+ AND json_type(payload_json, '$.first_review_proof_sha256') = 'text'
326
+ AND length(json_extract(payload_json, '$.first_review_proof_sha256')) = 64
327
+ AND json_extract(payload_json, '$.first_review_proof_sha256') NOT GLOB '*[^0-9a-f]*'))))
328
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
329
+ AND json_extract(payload_json, '$.project_id') = project_id
330
+ AND json_extract(payload_json, '$.stage') = 'review'
331
+ AND json_extract(payload_json, '$.registration_scope.project_id') = project_id
332
+ AND json_extract(payload_json, '$.registration_scope.run_id') = json_extract(payload_json, '$.run_id')
333
+ AND json_extract(payload_json, '$.registration_scope.stage') = 'review'
334
+ AND json_extract(payload_json, '$.registration_scope.attempt') = json_extract(payload_json, '$.attempt')
335
+ AND json_extract(payload_json, '$.registration_scope.input_sha256') = json_extract(payload_json, '$.input_sha256')
336
+ AND json_extract(payload_json, '$.registration_scope.parent_work_id') IN (${works})
337
+ AND json_type(payload_json, '$.workers') = 'array'
338
+ AND json_array_length(payload_json, '$.workers') BETWEEN 0 AND 256
339
+ AND (json_extract(payload_json, '$.wave') = 0 OR json_array_length(payload_json, '$.workers') > 0)
340
+ AND NOT EXISTS (SELECT 1 FROM json_each(payload_json, '$.workers') worker
341
+ WHERE NOT EXISTS (SELECT 1 FROM works w WHERE w.project_id=audit_events.project_id
342
+ AND w.run_id=json_extract(audit_events.payload_json, '$.run_id')
343
+ AND w.work_id=json_extract(worker.value, '$.work_id')))
344
+ AND EXISTS (SELECT 1 FROM runs r, json_each(r.index_json, '$.stage_runs') s
345
+ WHERE r.project_id=audit_events.project_id AND r.id=json_extract(payload_json, '$.run_id')
346
+ AND json_extract(s.value, '$.stage')='review' AND json_extract(s.value, '$.status')='done'
347
+ AND json_extract(s.value, '$.attempt')=json_extract(payload_json, '$.attempt')
348
+ AND json_extract(s.value, '$.input_sha256')=json_extract(payload_json, '$.input_sha256')
349
+ AND json_extract(s.value, '$.data_sha256')=json_extract(payload_json, '$.result_sha256'))`;
350
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryReviewReceipt}))`;
351
+ // Terminal evidence precedes Stage/RUN acceptance. Preserve only the
352
+ // selected MB bundle, exact finish input and independently closed review.
353
+ // Packet bytes remain under the existing Stage packet preservation rule.
354
+ const memoryFinishEvidence = `event_type='memory.finish_evidence'
355
+ AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-finish-evidence@1'
356
+ AND json_extract(payload_json,'$.project_id')=project_id
357
+ AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
358
+ AND json_extract(payload_json,'$.stage')='finish'
359
+ AND json_type(payload_json,'$.readiness_sha256')='text'
360
+ AND length(json_extract(payload_json,'$.readiness_sha256'))=64
361
+ AND json_extract(payload_json,'$.readiness_sha256') NOT GLOB '*[^0-9a-f]*'
362
+ AND EXISTS (SELECT 1 FROM runs r,json_each(r.index_json,'$.stage_runs') f,json_each(r.index_json,'$.stage_runs') v
363
+ WHERE r.project_id=audit_events.project_id AND r.id=json_extract(audit_events.payload_json,'$.run_id')
364
+ AND json_extract(r.index_json,'$.execution_bundle.flow_id')='mb-init'
365
+ AND json_extract(r.index_json,'$.execution_bundle.manifest_sha256')=json_extract(audit_events.payload_json,'$.bundle_sha256')
366
+ AND json_extract(f.value,'$.stage')='finish'
367
+ AND json_extract(f.value,'$.attempt')=json_extract(audit_events.payload_json,'$.attempt')
368
+ AND json_extract(f.value,'$.input_sha256')=json_extract(audit_events.payload_json,'$.input_sha256')
369
+ AND json_extract(v.value,'$.stage')='review' AND json_extract(v.value,'$.status')='done'
370
+ AND json_extract(v.value,'$.data_sha256')=json_extract(audit_events.payload_json,'$.review_sha256'))`;
371
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryFinishEvidence}))`;
372
+ const memoryFinishAcceptance = `event_type='memory.finish_acceptance'
373
+ AND json_extract(payload_json,'$.schema_id')='dd-flow/memory-finish-acceptance@1'
374
+ AND json_extract(payload_json,'$.project_id')=project_id
375
+ AND json_extract(payload_json,'$.run_id') IN (SELECT run_id FROM capture_scope)
376
+ AND json_extract(payload_json,'$.stage')='finish'
377
+ AND json_type(payload_json,'$.evidence_sha256')='text'
378
+ AND length(json_extract(payload_json,'$.evidence_sha256'))=64
379
+ AND json_extract(payload_json,'$.evidence_sha256') NOT GLOB '*[^0-9a-f]*'
380
+ AND EXISTS (SELECT 1 FROM runs r,json_each(r.index_json,'$.stage_runs') f
381
+ WHERE r.project_id=audit_events.project_id AND r.id=json_extract(audit_events.payload_json,'$.run_id')
382
+ AND json_extract(r.index_json,'$.execution_bundle.flow_id')='mb-init'
383
+ AND json_extract(r.index_json,'$.execution_bundle.manifest_sha256')=json_extract(audit_events.payload_json,'$.bundle_sha256')
384
+ AND json_extract(f.value,'$.stage')='finish' AND json_extract(f.value,'$.status')='done'
385
+ AND json_extract(f.value,'$.attempt')=json_extract(audit_events.payload_json,'$.attempt')
386
+ AND json_extract(f.value,'$.input_sha256')=json_extract(audit_events.payload_json,'$.input_sha256')
387
+ AND json_extract(f.value,'$.data_schema_id')='dd-flow/mb-init-finish-result@1'
388
+ AND json_extract(f.value,'$.data_sha256')=json_extract(audit_events.payload_json,'$.result_sha256'))`;
389
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${memoryFinishAcceptance}))`;
390
+ const descriptorRunSettlementReceipt = `event_type = 'flow_run.descriptor_run_settlement'
391
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
392
+ AND EXISTS (SELECT 1 FROM works w WHERE w.project_id=audit_events.project_id
393
+ AND w.run_id=json_extract(audit_events.payload_json, '$.run_id')
394
+ AND w.work_id=json_extract(audit_events.payload_json, '$.work_id') AND w.parent_work_id IS NULL)`;
395
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${descriptorRunSettlementReceipt}))`;
396
+ // Exact packet/report bytes remain predecessor and restart custody. A
397
+ // selected RUN's receipts have no protocol_id and must not be discarded.
398
+ const stageReceipt = `event_type IN ('flow_run.stage_packet', 'flow_run.stage_report', 'flow_run.descriptor_stage_start')
399
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
400
+ AND EXISTS (SELECT 1 FROM runs r, json_each(r.index_json, '$.stage_runs') s
401
+ WHERE r.project_id = audit_events.project_id AND r.id = json_extract(payload_json, '$.run_id')
402
+ AND json_extract(s.value, '$.stage') = json_extract(payload_json, '$.stage'))`;
403
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${stageReceipt}))`;
404
+ const startReceipt = `event_type IN ('flow_run.start_request', 'flow_run.start_root_owned', 'flow_run.start_published')
405
+ AND json_extract(payload_json, '$.run_id') IN (SELECT run_id FROM capture_scope)
406
+ AND EXISTS (SELECT 1 FROM runs r WHERE r.project_id = audit_events.project_id AND r.id = json_extract(payload_json, '$.run_id')
407
+ AND json_extract(r.index_json, '$.start_request.request_id') = json_extract(payload_json, '$.request_id'))`;
408
+ rules.audit_events = `(${rules.audit_events}) OR (${ownProject} AND (${startReceipt}))`;
62
409
  for (const table of ["run_controller_events", "run_controller_operations"])
63
410
  rules[table] = `controller_id IN (SELECT controller_id FROM run_controllers WHERE ${ownRun})`;
64
411
  for (const table of ["run_control_admissions", "run_control_stage_admissions", "run_control_operations", "run_control_workers"])
@@ -104,6 +451,74 @@ export function captureRecoveryDatabase(source, output, projectId, runId, protoc
104
451
  throw new AppError("snapshot_database_failed", primary instanceof Error ? primary.message : "Snapshot database cleanup failed", 1, { ...(failed ? { cause: errorRecord(primary) } : {}), snapshot_cleanup_errors: cleanup });
105
452
  }
106
453
  }
454
+ /** Validate retained allocation against the same consistent SQL copy. This
455
+ * preserves evidence only; absolute filesystem/engine paths are not relocated.
456
+ */
457
+ function assertCapturedStartAuthority(db, projectId, runId) {
458
+ const marker = JSON.parse(db.prepare("SELECT index_json FROM runs WHERE project_id = ? AND id = ?").get(projectId, runId).index_json)?.start_request;
459
+ const hasTable = db.prepare("SELECT 1 FROM sqlite_schema WHERE type = 'table' AND name = 'run_start_requests'").get();
460
+ const row = hasTable ? db.prepare("SELECT request_id FROM run_start_requests WHERE project_id = ? AND run_id = ?").get(projectId, runId) : undefined;
461
+ const audit = db.prepare("SELECT json_extract(payload_json, '$.request_id') AS request_id FROM audit_events WHERE project_id = ? AND event_type = 'flow_run.start_request' AND json_extract(payload_json, '$.run_id') = ? LIMIT 1").get(projectId, runId);
462
+ if (!marker && !row && !audit)
463
+ return;
464
+ if (!marker || !row || !audit || marker.request_id !== row.request_id || row.request_id !== audit.request_id)
465
+ throw new AppError("snapshot_start_authority_invalid", "Captured RUN is missing its independent allocation evidence", 1);
466
+ // Adapt the read-only query surface, never open or migrate another store.
467
+ const context = { db: {
468
+ readSnapshot: (operation) => operation(), // The copied database writer already pins this snapshot.
469
+ get: (sql, parameters = []) => db.prepare(sql).get(...parameters),
470
+ all: (sql, parameters = []) => db.prepare(sql).all(...parameters)
471
+ } };
472
+ const retained = readRunStartRequest(context, projectId, row.request_id);
473
+ if (retained?.payload.initial_index.execution_bundle?.flow_id === "mb-init") {
474
+ const p = retained.payload;
475
+ // This adapter supplies only SQL reads; the reservation/readiness readers
476
+ // must not access a host home or physical engine during capture.
477
+ const allocation = readMemoryInitRunAllocation(context, { requestId: p.request_id, projectRoot: p.project_root, workspaceRoot: p.workspace_root });
478
+ if (!allocation || allocation.project_id !== projectId || allocation.run_id !== runId)
479
+ throw new AppError("snapshot_start_authority_invalid", "Captured memory RUN is missing its request-bound identity reservation", 1);
480
+ if (db.prepare(`SELECT 1 FROM audit_events WHERE event_type IN ('memory.init_startup_input','memory.init_startup_input_intent')
481
+ AND json_extract(payload_json,'$.scope.requestId')=? AND json_extract(payload_json,'$.scope.projectRoot')=? LIMIT 1`).get(p.request_id, p.project_root)) {
482
+ readMemoryInitStartupInput(context, { requestId: p.request_id, projectRoot: p.project_root, workspaceRoot: p.workspace_root });
483
+ }
484
+ }
485
+ }
486
+ /** Check the consistent copied database, not a racy earlier read of the live
487
+ * store. Legacy evidence gains no descriptor or filesystem admission here.
488
+ */
489
+ function assertCapturedBundleAuthority(db, projectId, runId) {
490
+ const run = db.prepare("SELECT index_json FROM runs WHERE project_id = ? AND id = ?").get(projectId, runId);
491
+ const hasTable = db.prepare("SELECT 1 FROM sqlite_schema WHERE type = 'table' AND name = 'run_bundle_authorities'").get();
492
+ const row = hasTable ? db.prepare("SELECT manifest_sha256, admission_json FROM run_bundle_authorities WHERE project_id = ? AND run_id = ?").get(projectId, runId) : undefined;
493
+ const invalid = () => { throw new AppError("snapshot_bundle_authority_invalid", "Captured RUN bundle anchor and independent authority disagree", 1); };
494
+ let anchor;
495
+ try {
496
+ anchor = JSON.parse(run.index_json)?.execution_bundle;
497
+ }
498
+ catch {
499
+ if (row)
500
+ invalid();
501
+ return;
502
+ }
503
+ if (anchor === undefined) {
504
+ if (row)
505
+ invalid();
506
+ return;
507
+ }
508
+ if (!anchor || anchor.schema_id !== "dd-flow/run-execution-bundle@1" || !row
509
+ || [anchor.manifest_sha256, anchor.descriptor_sha256, anchor.admission_sha256].some(value => typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value))
510
+ || typeof anchor.flow_id !== "string" || !anchor.flow_id || row.manifest_sha256 !== anchor.manifest_sha256
511
+ || Buffer.byteLength(row.admission_json, "utf8") > 1024 * 1024)
512
+ invalid();
513
+ try {
514
+ const retained = JSON.parse(row.admission_json);
515
+ if (retained.runId !== runId || hybridDigest(retained) !== anchor.admission_sha256)
516
+ invalid();
517
+ }
518
+ catch {
519
+ invalid();
520
+ }
521
+ }
107
522
  /** Physical leases are evidence, not authority to resurrect on another host. */
108
523
  export function readRecoveryResourceEvidence(resourceHome, projectId, runId, authority) {
109
524
  const file = path.join(resourceHome, "runtime.sqlite");
@@ -0,0 +1,52 @@
1
+ import { gzipSync } from "node:zlib";
2
+ import { createHash } from "node:crypto";
3
+ import { AppError } from "../shared/errors.js";
4
+ import { inspectReleaseArchive } from "./release-archive.js";
5
+ /** Deterministic regular-file-only tar/gzip. Extraction admission is also applied
6
+ * to producer output; producing bytes never grants them installation authority.
7
+ */
8
+ export function produceReleaseArchive(files) {
9
+ const refuse = () => { throw new AppError("release_producer", "Archive production refused", 1, { reason: "invalid_archive_input", effect: "no_effect" }); };
10
+ if (!files.length || files.length > 100_000)
11
+ refuse();
12
+ const chunks = [];
13
+ let expanded = 1024;
14
+ const append = (name, bytes, mode, type) => {
15
+ expanded += 512 + Math.ceil(bytes.length / 512) * 512;
16
+ if (expanded > 512 * 1024 * 1024)
17
+ refuse();
18
+ const header = Buffer.alloc(512);
19
+ header.write(name);
20
+ header.write(mode.toString(8).padStart(7, "0") + "\0", 100);
21
+ header.write("0000000\0", 108);
22
+ header.write("0000000\0", 116);
23
+ header.write(bytes.length.toString(8).padStart(11, "0") + "\0", 124);
24
+ header.write("00000000000\0", 136);
25
+ header.fill(32, 148, 156);
26
+ header[156] = type;
27
+ header.write("ustar\0", 257);
28
+ header.write("00", 263);
29
+ header.write(header.reduce((sum, byte) => sum + byte, 0).toString(8).padStart(6, "0") + "\0 ", 148);
30
+ chunks.push(header, bytes, Buffer.alloc((512 - bytes.length % 512) % 512));
31
+ };
32
+ let index = 0;
33
+ for (const file of [...files].sort((a, b) => Buffer.compare(Buffer.from(a.path), Buffer.from(b.path)))) {
34
+ const length = Buffer.byteLength(file.path);
35
+ if (!length || length > 4096 || !Buffer.isBuffer(file.bytes) || typeof file.executable !== "boolean")
36
+ refuse();
37
+ let name = file.path;
38
+ if (length > 100) {
39
+ const record = `path=${file.path}\n`;
40
+ let size = Buffer.byteLength(record) + 2;
41
+ while (size !== Buffer.byteLength(record) + String(size).length + 1)
42
+ size = Buffer.byteLength(record) + String(size).length + 1;
43
+ append(`PaxHeaders/${index}`, Buffer.from(`${size} ${record}`), 0o644, 120);
44
+ name = `entries/${index}`;
45
+ }
46
+ append(name, file.bytes, file.executable ? 0o755 : 0o644, 48);
47
+ index++;
48
+ }
49
+ const bytes = gzipSync(Buffer.concat([...chunks, Buffer.alloc(1024)]), { level: 9 });
50
+ inspectReleaseArchive({ url: "https://producer.invalid/archive", bytes: bytes.length, sha256: createHash("sha256").update(bytes).digest("hex") }, bytes);
51
+ return bytes;
52
+ }