@deksden-com/dd-flow-cli 0.9.0-beta.15 → 0.9.0-beta.151

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 (560) hide show
  1. package/CHANGELOG.md +907 -0
  2. package/README.md +139 -10
  3. package/dist/build-info.json +8 -8
  4. package/dist/cli/argument-values.js +38 -0
  5. package/dist/cli/command-inputs.js +386 -0
  6. package/dist/cli/command-metadata.js +232 -0
  7. package/dist/cli/command-option-descriptions.js +192 -0
  8. package/dist/cli/completion-cli.js +70 -0
  9. package/dist/cli/completion.js +57 -0
  10. package/dist/cli/diagnostic-invocation.js +46 -0
  11. package/dist/cli/diagnostic.js +120 -0
  12. package/dist/cli/error-output.js +52 -0
  13. package/dist/cli/executor-onboarding.js +76 -0
  14. package/dist/cli/flows.js +29 -0
  15. package/dist/cli/harnesses.js +84 -0
  16. package/dist/cli/help.js +396 -19
  17. package/dist/cli/hook-ingress.js +102 -0
  18. package/dist/cli/input-preparation.js +165 -0
  19. package/dist/cli/memory-flow-admission.js +50 -0
  20. package/dist/cli/memory-init-invocation.js +85 -0
  21. package/dist/cli/memory-init.js +249 -0
  22. package/dist/cli/memory-storage-admission.js +54 -0
  23. package/dist/cli/memory-storage-qualification.js +105 -0
  24. package/dist/cli/memory-storage-transition.js +123 -0
  25. package/dist/cli/memory-upgrade.js +189 -0
  26. package/dist/cli/models.js +39 -0
  27. package/dist/cli/native-hook-ingress.js +90 -0
  28. package/dist/cli/native-hook-preparation.js +55 -0
  29. package/dist/cli/operator-profiles.js +61 -0
  30. package/dist/cli/output-options.js +35 -0
  31. package/dist/cli/response-file.js +72 -0
  32. package/dist/cli/run-cli.js +1734 -550
  33. package/dist/cli/runtime-maintenance-diagnostics.js +46 -0
  34. package/dist/cli/runtime-maintenance-ingress.js +52 -0
  35. package/dist/cli/runtime-process.js +153 -0
  36. package/dist/cli/setup.js +150 -0
  37. package/dist/cli.js +89 -2
  38. package/dist/domain/diagnostic-aspects.js +103 -0
  39. package/dist/domain/diagnostic-flows.js +8 -0
  40. package/dist/domain/stage-catalog.js +1 -1
  41. package/dist/domain/stage-handler-identities.js +28 -0
  42. package/dist/harness-runtime/DD-ZCODE.md +112 -0
  43. package/dist/harness-runtime/OPENCODE-LICENSE.txt +24 -0
  44. package/dist/harness-runtime/bin/dd-agy.mjs +56 -0
  45. package/dist/harness-runtime/bin/dd-codex.mjs +27 -0
  46. package/dist/harness-runtime/bin/dd-droid.mjs +34 -0
  47. package/dist/harness-runtime/bin/dd-grok.mjs +40 -0
  48. package/dist/harness-runtime/bin/dd-opencode.mjs +22 -0
  49. package/dist/harness-runtime/bin/dd-zcode.mjs +87 -0
  50. package/dist/harness-runtime/lib/adapter-timeouts.d.mts +5 -0
  51. package/dist/harness-runtime/lib/adapter-timeouts.mjs +34 -0
  52. package/dist/harness-runtime/lib/agy-error-boundary.mjs +79 -0
  53. package/dist/harness-runtime/lib/agy-hooks.d.mts +1 -0
  54. package/dist/harness-runtime/lib/agy-hooks.mjs +9 -0
  55. package/dist/harness-runtime/lib/agy-native-inspection.mjs +216 -0
  56. package/dist/harness-runtime/lib/agy-native_pb.js +117 -0
  57. package/dist/harness-runtime/lib/agy-terminal-envelope.mjs +67 -0
  58. package/dist/harness-runtime/lib/daemon-observation.d.mts +2 -0
  59. package/dist/harness-runtime/lib/daemon-observation.mjs +163 -0
  60. package/dist/harness-runtime/lib/daemon-operations.d.mts +2 -0
  61. package/dist/harness-runtime/lib/daemon-operations.mjs +462 -0
  62. package/dist/harness-runtime/lib/dd-agy-daemon.d.mts +6 -0
  63. package/dist/harness-runtime/lib/dd-agy-daemon.mjs +1092 -0
  64. package/dist/harness-runtime/lib/dd-agy.mjs +86 -0
  65. package/dist/harness-runtime/lib/dd-codex-daemon.d.mts +1 -0
  66. package/dist/harness-runtime/lib/dd-codex-daemon.mjs +231 -0
  67. package/dist/harness-runtime/lib/dd-codex.d.mts +1 -0
  68. package/dist/harness-runtime/lib/dd-codex.mjs +954 -0
  69. package/dist/harness-runtime/lib/dd-droid-daemon.mjs +141 -0
  70. package/dist/harness-runtime/lib/dd-droid.mjs +626 -0
  71. package/dist/harness-runtime/lib/dd-grok-daemon.mjs +555 -0
  72. package/dist/harness-runtime/lib/dd-grok.mjs +180 -0
  73. package/dist/harness-runtime/lib/dd-opencode-daemon.mjs +627 -0
  74. package/dist/harness-runtime/lib/dd-opencode.mjs +390 -0
  75. package/dist/harness-runtime/lib/dd-zcode-daemon.mjs +752 -0
  76. package/dist/harness-runtime/lib/dd-zcode.mjs +1200 -0
  77. package/dist/harness-runtime/lib/delegation-instructions.d.mts +14 -0
  78. package/dist/harness-runtime/lib/delegation-instructions.mjs +166 -0
  79. package/dist/harness-runtime/lib/dispatch-fence.mjs +14 -0
  80. package/dist/harness-runtime/lib/driver-recovery.mjs +140 -0
  81. package/dist/harness-runtime/lib/droid-observation.mjs +66 -0
  82. package/dist/harness-runtime/lib/entity-references.d.mts +2 -0
  83. package/dist/harness-runtime/lib/entity-references.mjs +9 -0
  84. package/dist/harness-runtime/lib/lease-renewal.d.mts +8 -0
  85. package/dist/harness-runtime/lib/lease-renewal.mjs +37 -0
  86. package/dist/harness-runtime/lib/lifecycle-command.d.mts +20 -0
  87. package/dist/harness-runtime/lib/lifecycle-command.mjs +273 -0
  88. package/dist/harness-runtime/lib/lifecycle-contract.d.mts +10 -0
  89. package/dist/harness-runtime/lib/lifecycle-contract.mjs +19 -0
  90. package/dist/harness-runtime/lib/managed-daemon.d.mts +16 -0
  91. package/dist/harness-runtime/lib/managed-daemon.mjs +698 -0
  92. package/dist/harness-runtime/lib/managed-flow-env.mjs +15 -0
  93. package/dist/harness-runtime/lib/model-observations.mjs +113 -0
  94. package/dist/harness-runtime/lib/native-children.d.mts +34 -0
  95. package/dist/harness-runtime/lib/native-children.mjs +265 -0
  96. package/dist/harness-runtime/lib/native-hook-command.d.mts +7 -0
  97. package/dist/harness-runtime/lib/native-hook-command.mjs +251 -0
  98. package/dist/harness-runtime/lib/native-request-proof.d.mts +2 -0
  99. package/dist/harness-runtime/lib/native-request-proof.mjs +65 -0
  100. package/dist/harness-runtime/lib/native-streams.mjs +45 -0
  101. package/dist/harness-runtime/lib/observation-clock.d.mts +18 -0
  102. package/dist/harness-runtime/lib/observation-clock.mjs +95 -0
  103. package/dist/harness-runtime/lib/opencode-plugin.mjs +85 -0
  104. package/dist/harness-runtime/lib/operation-context.mjs +5 -0
  105. package/dist/harness-runtime/lib/operation-errors.d.mts +16 -0
  106. package/dist/harness-runtime/lib/operation-errors.mjs +127 -0
  107. package/dist/harness-runtime/lib/operation-progress.d.mts +7 -0
  108. package/dist/harness-runtime/lib/operation-progress.mjs +114 -0
  109. package/dist/harness-runtime/lib/process-json.d.mts +5 -0
  110. package/dist/harness-runtime/lib/process-json.mjs +201 -0
  111. package/dist/harness-runtime/lib/process-snapshot.mjs +10 -0
  112. package/dist/harness-runtime/lib/provider-overload-policy.d.mts +23 -0
  113. package/dist/harness-runtime/lib/provider-overload-policy.mjs +242 -0
  114. package/dist/harness-runtime/lib/runner-events.mjs +202 -0
  115. package/dist/harness-runtime/lib/runner-lock.mjs +42 -0
  116. package/dist/harness-runtime/lib/session-settlement.mjs +30 -0
  117. package/dist/harness-runtime/lib/setup-progress.d.mts +9 -0
  118. package/dist/harness-runtime/lib/setup-progress.mjs +53 -0
  119. package/dist/harness-runtime/lib/tool-observations.d.mts +21 -0
  120. package/dist/harness-runtime/lib/tool-observations.mjs +228 -0
  121. package/dist/harness-runtime/lib/zcode-usage.mjs +55 -0
  122. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-1y4a697q.js +81 -0
  123. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-2ny4vxct.js +92 -0
  124. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-6mptkzbc.js +0 -0
  125. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-7x67cf1q.js +52 -0
  126. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9rqn6x4v.js +16 -0
  127. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-9vdz0zwn.js +1661 -0
  128. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ecs5ftka.js +1466 -0
  129. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-frbwqjmf.js +145 -0
  130. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gne7h7mq.js +50 -0
  131. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-gx9wnkzr.js +105 -0
  132. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-m2eywc8w.js +0 -0
  133. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-nwcpakzx.js +12 -0
  134. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-q4g3afnw.js +623 -0
  135. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-qav6mfdz.js +0 -0
  136. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-sxt88q69.js +12 -0
  137. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-t1xa31vm.js +39 -0
  138. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ve4aws36.js +103 -0
  139. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vmytr4q8.js +4 -0
  140. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vt9jbch8.js +36 -0
  141. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-vyas3vgt.js +0 -0
  142. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-wjyeq25y.js +30 -0
  143. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-xgnj2w4v.js +20 -0
  144. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-y2etg5bs.js +9 -0
  145. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-ydhz1zrh.js +238 -0
  146. package/dist/harness-runtime/vendor/opencode-client/chunks/service-probe-z6qdwcsf.js +62 -0
  147. package/dist/harness-runtime/vendor/opencode-client/contract.d.ts +1 -0
  148. package/dist/harness-runtime/vendor/opencode-client/contract.js +12 -0
  149. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.d.ts +2806 -0
  150. package/dist/harness-runtime/vendor/opencode-client/effect/api/api.js +0 -0
  151. package/dist/harness-runtime/vendor/opencode-client/effect/api.d.ts +4 -0
  152. package/dist/harness-runtime/vendor/opencode-client/effect/api.js +0 -0
  153. package/dist/harness-runtime/vendor/opencode-client/effect/client.d.ts +2530 -0
  154. package/dist/harness-runtime/vendor/opencode-client/effect/client.js +15 -0
  155. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.d.ts +7 -0
  156. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client-error.js +6 -0
  157. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.d.ts +2529 -0
  158. package/dist/harness-runtime/vendor/opencode-client/effect/generated/client.js +8 -0
  159. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.d.ts +2 -0
  160. package/dist/harness-runtime/vendor/opencode-client/effect/generated/index.js +12 -0
  161. package/dist/harness-runtime/vendor/opencode-client/effect/index.d.ts +35 -0
  162. package/dist/harness-runtime/vendor/opencode-client/effect/index.js +75 -0
  163. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.d.ts +20 -0
  164. package/dist/harness-runtime/vendor/opencode-client/effect/rpc.js +11 -0
  165. package/dist/harness-runtime/vendor/opencode-client/effect/service.d.ts +90 -0
  166. package/dist/harness-runtime/vendor/opencode-client/effect/service.js +187 -0
  167. package/dist/harness-runtime/vendor/opencode-client/package.json +84 -0
  168. package/dist/harness-runtime/vendor/opencode-client/promise/api.d.ts +21 -0
  169. package/dist/harness-runtime/vendor/opencode-client/promise/api.js +0 -0
  170. package/dist/harness-runtime/vendor/opencode-client/promise/client.d.ts +252 -0
  171. package/dist/harness-runtime/vendor/opencode-client/promise/client.js +14 -0
  172. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.d.ts +8 -0
  173. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client-error.js +6 -0
  174. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.d.ts +259 -0
  175. package/dist/harness-runtime/vendor/opencode-client/promise/generated/client.js +7 -0
  176. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.d.ts +3 -0
  177. package/dist/harness-runtime/vendor/opencode-client/promise/generated/index.js +79 -0
  178. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.d.ts +8932 -0
  179. package/dist/harness-runtime/vendor/opencode-client/promise/generated/types.js +70 -0
  180. package/dist/harness-runtime/vendor/opencode-client/promise/index.d.ts +6 -0
  181. package/dist/harness-runtime/vendor/opencode-client/promise/index.js +83 -0
  182. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.d.ts +32 -0
  183. package/dist/harness-runtime/vendor/opencode-client/promise/rpc.js +7 -0
  184. package/dist/harness-runtime/vendor/opencode-client/promise/service.d.ts +24 -0
  185. package/dist/harness-runtime/vendor/opencode-client/promise/service.js +187 -0
  186. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.d.ts +12 -0
  187. package/dist/harness-runtime/vendor/opencode-client/pty-handoff.js +14 -0
  188. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.d.ts +20 -0
  189. package/dist/harness-runtime/vendor/opencode-client/rpc-runtime.js +14 -0
  190. package/dist/harness-runtime/vendor/opencode-client/service-contender.d.ts +37 -0
  191. package/dist/harness-runtime/vendor/opencode-client/service-contender.js +10 -0
  192. package/dist/harness-runtime/vendor/opencode-client/service-probe.d.ts +70 -0
  193. package/dist/harness-runtime/vendor/opencode-client/service-probe.js +16 -0
  194. package/dist/harness-runtime/vendor/opencode-client/service-timing.d.ts +12 -0
  195. package/dist/harness-runtime/vendor/opencode-client/service-timing.js +10 -0
  196. package/dist/harness-runtime/vendor/opencode-client/service-version.d.ts +2 -0
  197. package/dist/harness-runtime/vendor/opencode-client/service-version.js +6 -0
  198. package/dist/harness-runtime/vendor/opencode-client/service.d.ts +52 -0
  199. package/dist/harness-runtime/vendor/opencode-client/service.js +1 -0
  200. package/dist/harness-runtime/vendor/opencode-client/shared-events.d.ts +11 -0
  201. package/dist/harness-runtime/vendor/opencode-client/shared-events.js +8 -0
  202. package/dist/harness-runtime/vendor/opencode-client/solid/connection.d.ts +37 -0
  203. package/dist/harness-runtime/vendor/opencode-client/solid/connection.js +10 -0
  204. package/dist/harness-runtime/vendor/opencode-client/solid/data.d.ts +211 -0
  205. package/dist/harness-runtime/vendor/opencode-client/solid/data.js +18 -0
  206. package/dist/harness-runtime/vendor/opencode-client/solid/index.d.ts +3 -0
  207. package/dist/harness-runtime/vendor/opencode-client/solid/index.js +32 -0
  208. package/dist/harness-runtime/vendor/opencode-client/solid/pty.d.ts +22 -0
  209. package/dist/harness-runtime/vendor/opencode-client/solid/pty.js +8 -0
  210. package/dist/harness-runtime/vendor/opencode-plugin.mjs +3 -0
  211. package/dist/protocol/local-files.js +18 -9
  212. package/dist/runtime/context.js +8 -4
  213. package/dist/schemas/agent-profile.schema.json +1 -1
  214. package/dist/schemas/code-review-decision.schema.json +9 -0
  215. package/dist/schemas/code-review-result.schema.json +1 -1
  216. package/dist/schemas/code-verification.schema.json +7 -5
  217. package/dist/schemas/code-work-batch.schema.json +2 -2
  218. package/dist/schemas/diagnostic-stage-result.schema.json +354 -0
  219. package/dist/schemas/diagnostic-work-result.schema.json +296 -0
  220. package/dist/schemas/discovery-result.schema.json +184 -0
  221. package/dist/schemas/execution-bundle.schema.json +211 -0
  222. package/dist/schemas/execution-settings.schema.json +162 -0
  223. package/dist/schemas/flow-descriptor.schema.json +54 -0
  224. package/dist/schemas/flow-run.schema.json +29 -0
  225. package/dist/schemas/harness-catalog.schema.json +80 -0
  226. package/dist/schemas/mb-init-compose-result.schema.json +457 -0
  227. package/dist/schemas/mb-init-discover-result.schema.json +500 -0
  228. package/dist/schemas/mb-init-finish-result.schema.json +422 -0
  229. package/dist/schemas/mb-init-preflight-result.schema.json +367 -0
  230. package/dist/schemas/mb-init-review-result.schema.json +396 -0
  231. package/dist/schemas/mb-init-verify-result.schema.json +391 -0
  232. package/dist/schemas/mb-upgrade-stage-result.schema.json +863 -0
  233. package/dist/schemas/memory-bootstrap-receipt-v2.schema.json +67 -0
  234. package/dist/schemas/memory-bootstrap-receipt.schema.json +354 -0
  235. package/dist/schemas/memory-composition-work-result.schema.json +38 -0
  236. package/dist/schemas/memory-repair-work-result.schema.json +56 -0
  237. package/dist/schemas/memory-review-correction-plan.schema.json +30 -0
  238. package/dist/schemas/memory-review-work-result.schema.json +43 -0
  239. package/dist/schemas/model-catalog.schema.json +153 -0
  240. package/dist/schemas/plan-review-decision.schema.json +12 -3
  241. package/dist/schemas/plan-review-result.schema.json +2 -2
  242. package/dist/schemas/profile-settings.schema.json +122 -0
  243. package/dist/schemas/project-flow-pack-manifest.schema.json +1 -1
  244. package/dist/schemas/release-impact.schema.json +3 -3
  245. package/dist/schemas/release-manifest.schema.json +291 -0
  246. package/dist/schemas/run-control-receipt.schema.json +118 -0
  247. package/dist/schemas/run-control-request.schema.json +36 -0
  248. package/dist/schemas/run-engine-binding.schema.json +1 -1
  249. package/dist/schemas/stage-start-response.schema.json +4 -0
  250. package/dist/schemas/vnext-protocol-plan.schema.json +2 -2
  251. package/dist/services/accepted-intent.js +139 -0
  252. package/dist/services/branch-context.js +3 -3
  253. package/dist/services/canon.js +54 -15
  254. package/dist/services/check-environment.js +21 -0
  255. package/dist/services/check-runner-evidence.js +277 -0
  256. package/dist/services/check-runner-proof.js +305 -0
  257. package/dist/services/cleanup.js +133 -40
  258. package/dist/services/cli-operation-classifier.js +26 -63
  259. package/dist/services/cli-upgrade-allowlist.js +27 -0
  260. package/dist/services/code-checks.js +1401 -119
  261. package/dist/services/codex-hook-delivery.js +32 -0
  262. package/dist/services/command-context.js +80 -0
  263. package/dist/services/compatibility-preflight.js +16 -3
  264. package/dist/services/config.js +11 -8
  265. package/dist/services/continuation-outcome.js +20 -0
  266. package/dist/services/controller-child-capacity.js +71 -0
  267. package/dist/services/controller-child-observer.js +121 -0
  268. package/dist/services/controller-execution.js +94 -0
  269. package/dist/services/controller-fanout.js +226 -0
  270. package/dist/services/controller-memory-task.js +45 -0
  271. package/dist/services/controller-memory-worker.js +49 -0
  272. package/dist/services/dashboard.js +143 -58
  273. package/dist/services/descriptor-coordinator-session.js +35 -0
  274. package/dist/services/descriptor-root-work.js +53 -0
  275. package/dist/services/descriptor-run-settlement.js +107 -0
  276. package/dist/services/descriptor-run-start.js +475 -0
  277. package/dist/services/descriptor-stage-coordinator.js +250 -0
  278. package/dist/services/descriptor-stage-settlement.js +223 -0
  279. package/dist/services/descriptor-stage-start.js +175 -0
  280. package/dist/services/diagnostic-evidence.js +73 -0
  281. package/dist/services/diagnostic-report-publication.js +72 -0
  282. package/dist/services/diagnostic-report.js +67 -0
  283. package/dist/services/diagnostic-run-bundle.js +74 -0
  284. package/dist/services/diagnostic-snapshot.js +159 -0
  285. package/dist/services/diagnostic-stage-handlers.js +108 -0
  286. package/dist/services/diagnostic-stage-results.js +132 -0
  287. package/dist/services/diagnostic-start.js +84 -0
  288. package/dist/services/diagnostic-work-batch.js +34 -0
  289. package/dist/services/diagnostic-work-collection.js +97 -0
  290. package/dist/services/diagnostic-work-registration.js +101 -0
  291. package/dist/services/diagnostic-work-results.js +93 -0
  292. package/dist/services/discovery/agy-discovery.js +2 -0
  293. package/dist/services/discovery/codex-discovery.js +2 -0
  294. package/dist/services/discovery/droid-discovery.js +2 -0
  295. package/dist/services/discovery/grok-discovery.js +2 -0
  296. package/dist/services/discovery/opencode-discovery.js +2 -0
  297. package/dist/services/discovery/static.js +31 -0
  298. package/dist/services/discovery/zcode-discovery.js +2 -0
  299. package/dist/services/engines.js +354 -163
  300. package/dist/services/eval-snapshots.js +1316 -150
  301. package/dist/services/execution-bundles.js +275 -0
  302. package/dist/services/execution-policy.js +185 -0
  303. package/dist/services/executor-onboarding.js +56 -0
  304. package/dist/services/external-work-launch.js +310 -0
  305. package/dist/services/flow-catalog.js +30 -0
  306. package/dist/services/flow-descriptors.js +82 -0
  307. package/dist/services/frozen-engine.js +387 -0
  308. package/dist/services/generic-execution.js +164 -0
  309. package/dist/services/harness-adapter.js +355 -36
  310. package/dist/services/harness-config.js +2 -0
  311. package/dist/services/harness-discovery.js +29 -0
  312. package/dist/services/harness-doctor.js +75 -0
  313. package/dist/services/harness-probe-effects.js +51 -0
  314. package/dist/services/harness-version-probe.js +100 -0
  315. package/dist/services/hook-memory-routing.js +188 -0
  316. package/dist/services/hook-recovery-guard.js +14 -0
  317. package/dist/services/hook-session-observation.js +24 -0
  318. package/dist/services/hooks.js +791 -326
  319. package/dist/services/hybrid-contracts.js +474 -0
  320. package/dist/services/hybrid-digest.js +14 -0
  321. package/dist/services/ids.js +29 -1
  322. package/dist/services/installation-lock.js +95 -0
  323. package/dist/services/installed-flow-source.js +226 -0
  324. package/dist/services/lanes.js +78 -65
  325. package/dist/services/lifecycle-command.js +1 -288
  326. package/dist/services/lifecycle-contract.js +1 -0
  327. package/dist/services/lifecycle-invocations.js +2148 -0
  328. package/dist/services/managed-daemon-binding.js +38 -0
  329. package/dist/services/managed-lease-monitor.js +133 -0
  330. package/dist/services/managed-processes.js +449 -69
  331. package/dist/services/memory-accepted-composition.js +78 -0
  332. package/dist/services/memory-baseline-preservation.js +65 -0
  333. package/dist/services/memory-completed-correction-wave.js +328 -0
  334. package/dist/services/memory-compose-handler.js +400 -0
  335. package/dist/services/memory-composition-acceptance.js +375 -0
  336. package/dist/services/memory-composition-graph.js +165 -0
  337. package/dist/services/memory-composition-registration.js +161 -0
  338. package/dist/services/memory-composition-work-custody.js +156 -0
  339. package/dist/services/memory-composition-work-results.js +108 -0
  340. package/dist/services/memory-corrected-review-acceptance.js +129 -0
  341. package/dist/services/memory-corrected-review-batch.js +37 -0
  342. package/dist/services/memory-corrected-review-findings.js +108 -0
  343. package/dist/services/memory-corrected-review-inputs.js +215 -0
  344. package/dist/services/memory-corrected-review-projection.js +78 -0
  345. package/dist/services/memory-corrected-review-receipt.js +178 -0
  346. package/dist/services/memory-corrected-review-registration.js +192 -0
  347. package/dist/services/memory-correction-check-receipt.js +235 -0
  348. package/dist/services/memory-correction-input-owner.js +6 -0
  349. package/dist/services/memory-custody-snapshot.js +36 -0
  350. package/dist/services/memory-discover-handler.js +104 -0
  351. package/dist/services/memory-finish-evidence.js +457 -0
  352. package/dist/services/memory-finish-handler.js +229 -0
  353. package/dist/services/memory-finish-integration.js +450 -0
  354. package/dist/services/memory-finish-readiness.js +169 -0
  355. package/dist/services/memory-git-integration.js +220 -0
  356. package/dist/services/memory-historical-corrected-review.js +212 -0
  357. package/dist/services/memory-historical-original-review.js +143 -0
  358. package/dist/services/memory-historical-repair-registration.js +105 -0
  359. package/dist/services/memory-historical-second-review.js +147 -0
  360. package/dist/services/memory-init-bootstrap-readiness.js +210 -0
  361. package/dist/services/memory-init-contexts.js +131 -0
  362. package/dist/services/memory-init-controller-start.js +103 -0
  363. package/dist/services/memory-init-engine-release.js +223 -0
  364. package/dist/services/memory-init-git-policy.js +165 -0
  365. package/dist/services/memory-init-lint-capability.js +203 -0
  366. package/dist/services/memory-init-native-capacity.js +309 -0
  367. package/dist/services/memory-init-preflight.js +334 -0
  368. package/dist/services/memory-init-project-bootstrap.js +599 -0
  369. package/dist/services/memory-init-request-candidate.js +213 -0
  370. package/dist/services/memory-init-request-input.js +82 -0
  371. package/dist/services/memory-init-resource-storage.js +125 -0
  372. package/dist/services/memory-init-run-allocation.js +81 -0
  373. package/dist/services/memory-init-run-bundle.js +135 -0
  374. package/dist/services/memory-init-start.js +181 -0
  375. package/dist/services/memory-init-startup-custody.js +80 -0
  376. package/dist/services/memory-init-startup-input.js +240 -0
  377. package/dist/services/memory-init-storage.js +91 -0
  378. package/dist/services/memory-init-stores.js +359 -0
  379. package/dist/services/memory-init-worktrunk-capability.js +174 -0
  380. package/dist/services/memory-layer-publication.js +611 -0
  381. package/dist/services/memory-layer.js +221 -0
  382. package/dist/services/memory-lint-config.js +194 -0
  383. package/dist/services/memory-native-review-copy.js +103 -0
  384. package/dist/services/memory-normal-flow-entry.js +87 -0
  385. package/dist/services/memory-ordinary-defaults.js +129 -0
  386. package/dist/services/memory-preflight-bootstrap-custody.js +115 -0
  387. package/dist/services/memory-preflight-handler.js +274 -0
  388. package/dist/services/memory-repair-current-view.js +299 -0
  389. package/dist/services/memory-repair-document-delta.js +488 -0
  390. package/dist/services/memory-repair-history.js +496 -0
  391. package/dist/services/memory-repair-physical-binding.js +194 -0
  392. package/dist/services/memory-repair-publication-files.js +152 -0
  393. package/dist/services/memory-repair-publication-intent.js +27 -0
  394. package/dist/services/memory-repair-publication-plan.js +162 -0
  395. package/dist/services/memory-repair-publication-source.js +225 -0
  396. package/dist/services/memory-repair-publication.js +795 -0
  397. package/dist/services/memory-repair-registration.js +240 -0
  398. package/dist/services/memory-repair-work-baseline.js +415 -0
  399. package/dist/services/memory-repair-work-completion.js +117 -0
  400. package/dist/services/memory-repair-work-custody.js +73 -0
  401. package/dist/services/memory-repair-work-results.js +108 -0
  402. package/dist/services/memory-repair-workspace.js +261 -0
  403. package/dist/services/memory-repair-writer-copy.js +736 -0
  404. package/dist/services/memory-result-binding.js +239 -0
  405. package/dist/services/memory-retained-review-authority.js +138 -0
  406. package/dist/services/memory-retained-review-results.js +70 -0
  407. package/dist/services/memory-retained-second-baseline.js +102 -0
  408. package/dist/services/memory-retained-second-repairs.js +162 -0
  409. package/dist/services/memory-review-acceptance.js +214 -0
  410. package/dist/services/memory-review-correction-plan.js +206 -0
  411. package/dist/services/memory-review-handler.js +585 -0
  412. package/dist/services/memory-review-inputs.js +246 -0
  413. package/dist/services/memory-review-limits.js +10 -0
  414. package/dist/services/memory-review-receipt.js +180 -0
  415. package/dist/services/memory-review-registration.js +117 -0
  416. package/dist/services/memory-review-work-custody.js +126 -0
  417. package/dist/services/memory-review-work-input.js +91 -0
  418. package/dist/services/memory-review-work-results.js +95 -0
  419. package/dist/services/memory-second-corrected-review-inputs.js +167 -0
  420. package/dist/services/memory-second-correction-plan.js +77 -0
  421. package/dist/services/memory-second-repair-baseline.js +91 -0
  422. package/dist/services/memory-second-repair-launch.js +614 -0
  423. package/dist/services/memory-second-repair-registration.js +88 -0
  424. package/dist/services/memory-second-repair-source.js +187 -0
  425. package/dist/services/memory-second-review-acceptance.js +115 -0
  426. package/dist/services/memory-source-observations.js +117 -0
  427. package/dist/services/memory-stage-dispatch.js +65 -0
  428. package/dist/services/memory-stage-results.js +290 -0
  429. package/dist/services/memory-tool-probe.js +25 -0
  430. package/dist/services/memory-upgrade-analysis-handler.js +243 -0
  431. package/dist/services/memory-upgrade-bootstrap-readiness.js +251 -0
  432. package/dist/services/memory-upgrade-evidence.js +100 -0
  433. package/dist/services/memory-upgrade-inventory.js +442 -0
  434. package/dist/services/memory-upgrade-publication-custody.js +73 -0
  435. package/dist/services/memory-upgrade-publication.js +413 -0
  436. package/dist/services/memory-upgrade-selection.js +430 -0
  437. package/dist/services/memory-upgrade-start.js +60 -0
  438. package/dist/services/memory-upgrade-storage-readiness.js +340 -0
  439. package/dist/services/memory-verification-acceptance.js +156 -0
  440. package/dist/services/memory-verification-checks.js +317 -0
  441. package/dist/services/memory-verification-receipt.js +160 -0
  442. package/dist/services/memory-verify-handler.js +137 -0
  443. package/dist/services/memory-work-result-json.js +12 -0
  444. package/dist/services/memory-work-result-preparation.js +64 -0
  445. package/dist/services/merge-queue.js +228 -149
  446. package/dist/services/merge-server.js +163 -35
  447. package/dist/services/migrations.js +164 -114
  448. package/dist/services/model-catalog.js +109 -0
  449. package/dist/services/model-discovery.js +46 -0
  450. package/dist/services/native-daemon-history.js +50 -0
  451. package/dist/services/native-session-control.js +39 -0
  452. package/dist/services/operator-profiles.js +236 -0
  453. package/dist/services/physical-startup.js +45 -0
  454. package/dist/services/plan-runtime.js +26 -11
  455. package/dist/services/plans.js +28 -25
  456. package/dist/services/project-registry.js +97 -0
  457. package/dist/services/project-summary.js +1 -1
  458. package/dist/services/projects.js +17 -87
  459. package/dist/services/prompt-delivery.js +71 -0
  460. package/dist/services/prompts.js +28 -17
  461. package/dist/services/protocols.js +163 -87
  462. package/dist/services/provider-capacity.js +463 -0
  463. package/dist/services/recovery-observation-budget.js +121 -0
  464. package/dist/services/recovery-snapshot-database.js +588 -0
  465. package/dist/services/release-archive-producer.js +52 -0
  466. package/dist/services/release-archive.js +143 -0
  467. package/dist/services/release-cache.js +150 -0
  468. package/dist/services/release-compatibility.js +18 -0
  469. package/dist/services/release-download.js +67 -0
  470. package/dist/services/release-envelope.js +104 -0
  471. package/dist/services/release-manifest.js +45 -0
  472. package/dist/services/release-payload.js +114 -0
  473. package/dist/services/release-producer.js +63 -0
  474. package/dist/services/release-provenance.js +160 -0
  475. package/dist/services/release-registry.js +66 -0
  476. package/dist/services/release-source.js +194 -0
  477. package/dist/services/repair-intents.js +31 -0
  478. package/dist/services/repair-receipt.js +13 -0
  479. package/dist/services/review-copy.js +165 -0
  480. package/dist/services/review-deferral.js +23 -0
  481. package/dist/services/run-control-receipt.js +56 -0
  482. package/dist/services/run-control-worker.js +428 -0
  483. package/dist/services/run-control.js +1092 -0
  484. package/dist/services/run-controller-adapter.js +400 -0
  485. package/dist/services/run-controller-capture.js +186 -0
  486. package/dist/services/run-controller-process.js +205 -0
  487. package/dist/services/run-controller-recovery.js +295 -0
  488. package/dist/services/run-controller-state.js +97 -0
  489. package/dist/services/run-controller.js +1395 -0
  490. package/dist/services/run-engine-bindings.js +1 -1
  491. package/dist/services/run-fork.js +147 -0
  492. package/dist/services/run-health.js +149 -0
  493. package/dist/services/run-observations.js +152 -0
  494. package/dist/services/run-projection.js +22 -64
  495. package/dist/services/run-recovery-guard.js +107 -0
  496. package/dist/services/run-recovery-runtime.js +112 -0
  497. package/dist/services/run-recovery.js +456 -0
  498. package/dist/services/run-start-custody.js +189 -0
  499. package/dist/services/runs.js +1023 -246
  500. package/dist/services/runtime-budget.js +446 -0
  501. package/dist/services/runtime-command.js +43 -0
  502. package/dist/services/runtime-scope-capture.js +52 -0
  503. package/dist/services/runtime-scope-control.js +468 -0
  504. package/dist/services/runtime-scope-resume.js +605 -0
  505. package/dist/services/runtime-scope-stop.js +211 -0
  506. package/dist/services/runtime-scope-worker.js +314 -0
  507. package/dist/services/runtime-service.js +19 -14
  508. package/dist/services/schema-validation.js +10 -8
  509. package/dist/services/scope-writer-cleanup.js +27 -0
  510. package/dist/services/sessions.js +36 -91
  511. package/dist/services/setup.js +427 -0
  512. package/dist/services/stage-blocker.js +17 -7
  513. package/dist/services/stage-context.js +240 -18
  514. package/dist/services/stage-handlers.js +89 -0
  515. package/dist/services/stage-lifecycle.js +152 -116
  516. package/dist/services/stage-pause.js +202 -91
  517. package/dist/services/stage-report-renderer.js +234 -6
  518. package/dist/services/stage-work-graph.js +52 -0
  519. package/dist/services/tooling.js +41 -30
  520. package/dist/services/usage.js +49 -101
  521. package/dist/services/verification-matrix.js +393 -0
  522. package/dist/services/version-status.js +1 -1
  523. package/dist/services/vnext-code-review.js +235 -88
  524. package/dist/services/vnext-code.js +327 -226
  525. package/dist/services/vnext-contracts.js +10 -1
  526. package/dist/services/vnext-execution-profile.js +80 -5
  527. package/dist/services/vnext-fanout.js +355 -21
  528. package/dist/services/vnext-merge.js +332 -111
  529. package/dist/services/vnext-plan-review.js +287 -132
  530. package/dist/services/vnext-plan.js +228 -104
  531. package/dist/services/vnext-protocolize.js +533 -95
  532. package/dist/services/vnext-specify.js +123 -81
  533. package/dist/services/vnext-workspace-policy.js +7 -2
  534. package/dist/services/work-registry.js +1706 -200
  535. package/dist/services/workspace-bootstrap.js +53 -15
  536. package/dist/services/workspace-files.js +85 -0
  537. package/dist/services/worktrees.js +105 -48
  538. package/dist/shared/entity-references.js +1 -0
  539. package/dist/shared/errors.js +27 -0
  540. package/dist/storage/agent-output.js +26 -0
  541. package/dist/storage/data-preservation.js +65 -0
  542. package/dist/storage/database.js +930 -40
  543. package/dist/storage/foreign-key-transaction.js +39 -0
  544. package/dist/storage/immutable-input.js +45 -0
  545. package/dist/storage/import-guard.js +159 -0
  546. package/dist/storage/memory-upgrade-schema-bootstrap.js +38 -0
  547. package/dist/storage/native-cleanup.js +52 -0
  548. package/dist/storage/paired-writer-migration.js +424 -0
  549. package/dist/storage/paths.js +17 -4
  550. package/dist/storage/projection-lock.js +73 -0
  551. package/dist/storage/work-references.js +23 -0
  552. package/dist/storage/writer-contract.js +96 -0
  553. package/dist/storage/writer-migration.js +346 -0
  554. package/dist/storage/writer-restore.js +217 -0
  555. package/dist/verification-components.json +299 -0
  556. package/package.json +51 -13
  557. package/tools/create-canon-release.mjs +33 -0
  558. package/tools/probe-codex-history.mjs +37 -0
  559. package/tools/produce-hybrid-release.mjs +41 -0
  560. package/tools/repair-paused-run-status.mjs +84 -0
@@ -0,0 +1,221 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ import { Ajv } from "ajv/dist/ajv.js";
5
+ import semver from "semver";
6
+ import { AppError } from "../shared/errors.js";
7
+ import { hybridDigest } from "./hybrid-contracts.js";
8
+ import { readSetupStatus, readCommittedCanonRelease } from "./setup.js";
9
+ import { readBoundedReleaseFile } from "./release-source.js";
10
+ import { normalizeFlowContract } from "../domain/flow-contract.js";
11
+ import { inspectReleaseArchive } from "./release-archive.js";
12
+ import { canonicalOnlyFlowNames } from "./version-status.js";
13
+ export function isCanonicalOnlyMemoryPath(logical) {
14
+ return logical.startsWith("dd-flow/project-review/")
15
+ || canonicalOnlyFlowNames.some(name => logical === `dd-flow/${name}` || logical.startsWith(`dd-flow/${name.slice(0, -3)}/`));
16
+ }
17
+ const rootFiles = ["README.md", "index.md", "compatibility.json", "flow-contract.json", "go.md", "f.md", "prime.md", "protocol.md",
18
+ "protocol-implement.md", "plan.md", "code.md", "merge.md", "merge-start.md", "merge-stop.md", "release.md", "deploy.md", "publish.md",
19
+ "review-fix.md", "mb-fix.md", "mb-lint.md", "interactive.md", "finish.md", "fix-def.md"];
20
+ const supportDirectories = ["common", "prime", "mb-sdlc", "aspects", "def", "workers", "schemas", "vnext", "specify", "stage-reports", "dashboard", "plan", "code", "merge"];
21
+ const required = ["README.md", "index.md", "flow-contract.json", "compatibility.json", "prime.md", "go.md",
22
+ "common/style.md", "common/runtime-contract.md", "common/lifecycle-guards.md", "common/workspace-bootstrap.md", "common/worker-session.md",
23
+ "vnext/start.md", "vnext/specify.md", "vnext/protocolize.md", "vnext/plan.md", "vnext/plan-review.md", "vnext/code.md", "vnext/code-review.md", "vnext/merge.md",
24
+ "schemas/flow-run.schema.json", "schemas/project-flow-pack-manifest.schema.json"];
25
+ const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
26
+ function refuse(reason) {
27
+ throw new AppError("memory_layer_invalid", "Selected Memory Bank layer cannot be prepared", 1, { reason, phase: "prepare", effect: "no_effect" });
28
+ }
29
+ function directory(file) { if (!fs.lstatSync(file).isDirectory())
30
+ refuse("unsafe_source_directory"); }
31
+ /** Canonical-layer bytes only, not project facts, a productive bootstrap receipt or qualification.
32
+ * The source must be the independently selected, verified installed release cache.
33
+ */
34
+ export class PreparedMemoryLayer {
35
+ sha256;
36
+ packSha256;
37
+ installationSha256;
38
+ #files;
39
+ constructor(files, installationSha256) {
40
+ this.#files = files;
41
+ this.installationSha256 = installationSha256;
42
+ const inventory = [...files].map(([logical, bytes]) => ({ path: logical, sha256: hash(bytes) }));
43
+ this.sha256 = hybridDigest(inventory);
44
+ this.packSha256 = hybridDigest(inventory.filter(item => item.path.startsWith("dd-flow/")));
45
+ Object.freeze(this);
46
+ }
47
+ static fromInstalledRelease(home, expectedInstallationSha256, installedAt) {
48
+ try {
49
+ if (!path.isAbsolute(home) || !/^[a-f0-9]{64}$/.test(expectedInstallationSha256)
50
+ || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(installedAt) || !Number.isFinite(Date.parse(installedAt)))
51
+ refuse("invalid_selection");
52
+ const selection = readSetupStatus(home);
53
+ if (!selection.installation || selection.installation_readiness !== "installed")
54
+ refuse("installed_release_unavailable");
55
+ const installation = selection.installation;
56
+ if (installation.manifest_sha256 !== expectedInstallationSha256)
57
+ refuse("installation_selection_changed");
58
+ directory(installation.canon_root);
59
+ const roots = fs.readdirSync(installation.canon_root);
60
+ if (roots.length !== 1)
61
+ refuse("ambiguous_archive_root");
62
+ const canonRoot = path.join(installation.canon_root, roots[0]);
63
+ directory(canonRoot);
64
+ const dotRoot = path.join(canonRoot, ".memory-bank");
65
+ const memoryRoot = fs.existsSync(dotRoot) ? dotRoot : canonRoot;
66
+ directory(memoryRoot);
67
+ const files = new Map(), folded = new Set();
68
+ let total = 0;
69
+ const put = (logical, bytes) => {
70
+ if (bytes.length < 1 || bytes.length > 1024 * 1024 || !/^[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/.test(logical) || logical.split("/").some(part => [".", ".."].includes(part))
71
+ || folded.has(logical.toLowerCase()) || (total += bytes.length) > 64 * 1024 * 1024)
72
+ refuse("unsafe_or_unbounded_inventory");
73
+ folded.add(logical.toLowerCase());
74
+ files.set(logical, Buffer.from(bytes));
75
+ };
76
+ const collect = (source, logical) => {
77
+ directory(source);
78
+ for (const name of fs.readdirSync(source).sort()) {
79
+ const file = path.join(source, name), target = `${logical}/${name}`, stat = fs.lstatSync(file);
80
+ if (stat.isDirectory())
81
+ collect(file, target);
82
+ else if (stat.isFile())
83
+ put(target, readBoundedReleaseFile(file, 1024 * 1024));
84
+ else
85
+ refuse("unsafe_source_file");
86
+ }
87
+ };
88
+ collect(path.join(memoryRoot, "mbb"), "mbb");
89
+ if (!files.has("mbb/index.md"))
90
+ refuse("missing_mbb_entrypoint");
91
+ const flowRoot = path.join(memoryRoot, "dd-flow");
92
+ directory(flowRoot);
93
+ for (const name of rootFiles)
94
+ if (fs.existsSync(path.join(flowRoot, name)))
95
+ put(`dd-flow/${name}`, readBoundedReleaseFile(path.join(flowRoot, name), 1024 * 1024));
96
+ for (const name of supportDirectories)
97
+ if (fs.existsSync(path.join(flowRoot, name)))
98
+ collect(path.join(flowRoot, name), `dd-flow/${name}`);
99
+ if (required.some(logical => !files.has(`dd-flow/${logical}`)))
100
+ refuse("incomplete_project_pack");
101
+ const contract = normalizeFlowContract(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(files.get("dd-flow/flow-contract.json"))));
102
+ const compatibility = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(files.get("dd-flow/compatibility.json")));
103
+ const compatibilitySchema = JSON.parse(fs.readFileSync(new URL("../schemas/compatibility.schema.json", import.meta.url), "utf8"));
104
+ if (!new Ajv({ strict: false, validateFormats: false }).compile(compatibilitySchema)(compatibility))
105
+ refuse("invalid_compatibility");
106
+ if (compatibility.memory_bank_version !== installation.manifest.canon.version
107
+ || compatibility.dd_flow_cli.flow_contract !== contract.id
108
+ || compatibility.dd_flow_cli.package_name !== installation.manifest.engine.package
109
+ || compatibility.engine.package_name !== installation.manifest.engine.package
110
+ || !semver.validRange(compatibility.engine.version_range)
111
+ || !semver.satisfies(installation.manifest.engine.version, compatibility.engine.version_range, { includePrerelease: true })
112
+ || !semver.valid(compatibility.dd_flow_cli.min_version)
113
+ || semver.lt(installation.manifest.engine.version, compatibility.dd_flow_cli.min_version))
114
+ refuse("incompatible_selected_release");
115
+ const included = [...files.keys()].filter(logical => logical.startsWith("dd-flow/")).map(logical => logical.slice(8)).sort();
116
+ const manifest = { schema_id: "dd-flow/project-flow-pack-manifest@2", pack_version: installation.manifest.canon.version,
117
+ flow_origin_policy: "project_local_pack", canon_root: canonRoot, canon_memory_bank_root: memoryRoot, canon_flow_root: flowRoot,
118
+ source_commit: installation.manifest.canon.commit, canon_version_at_source_commit: installation.manifest.canon.version,
119
+ flow_contract: contract.id, installed_at: installedAt, included_files: included,
120
+ file_hashes: Object.fromEntries(included.map(logical => [logical, hash(files.get(`dd-flow/${logical}`))])),
121
+ excluded_canonical_only_flows: canonicalOnlyFlowNames, generated_allow_patterns: [".generated/**"] };
122
+ const schema = JSON.parse(fs.readFileSync(new URL("../schemas/project-flow-pack-manifest.schema.json", import.meta.url), "utf8"));
123
+ if (!new Ajv({ strict: false, validateFormats: false }).compile(schema)(manifest))
124
+ refuse("invalid_pack_manifest");
125
+ const retainedSchema = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(files.get("dd-flow/schemas/project-flow-pack-manifest.schema.json")));
126
+ if (retainedSchema.$id !== "dd-flow/project-flow-pack-manifest@2"
127
+ || !new Ajv({ strict: false, validateFormats: false }).compile(retainedSchema)(manifest))
128
+ refuse("invalid_retained_manifest_schema");
129
+ put("dd-flow/manifest.json", Buffer.from(`${JSON.stringify(manifest, null, 2)}\n`));
130
+ return new PreparedMemoryLayer(new Map([...files].sort(([left], [right]) => left.localeCompare(right, "en"))), expectedInstallationSha256);
131
+ }
132
+ catch (error) {
133
+ if (error instanceof AppError && error.code === "memory_layer_invalid")
134
+ throw error;
135
+ return refuse("source_unavailable_or_changed");
136
+ }
137
+ }
138
+ files() { return new Map([...this.#files].map(([logical, bytes]) => [logical, Buffer.from(bytes)])); }
139
+ /** Historical content baseline, not an executable target layer. Project
140
+ * paths select a subset; every byte/provenance fact comes from the committed
141
+ * setup canon. Old runtime compatibility and current installation defaults
142
+ * are irrelevant, and no release is activated or downloaded here.
143
+ */
144
+ static fromCommittedCanon(home, current, expectedInstallationSha256) {
145
+ if (!path.isAbsolute(home) || !current || !Array.isArray(current.included_files) || current.included_files.length > 20_000
146
+ || typeof current.installed_at !== "string" || !current.installed_at || current.installed_at.length > 256)
147
+ refuse("invalid_baseline_selection");
148
+ const installation = readCommittedCanonRelease(home, current.canon_version_at_source_commit, current.source_commit, expectedInstallationSha256);
149
+ if (!installation)
150
+ return null;
151
+ const archive = inspectReleaseArchive(installation.manifest.canon.archive, readBoundedReleaseFile(path.join(path.dirname(installation.canon_root), "archive.tgz"), installation.manifest.canon.archive.bytes));
152
+ const roots = [...new Set(archive.map(entry => entry.path.split("/")[0]))];
153
+ if (roots.length !== 1)
154
+ refuse("ambiguous_archive_root");
155
+ const prefix = archive.some(entry => entry.path.startsWith(`${roots[0]}/.memory-bank/`)) ? `${roots[0]}/.memory-bank` : roots[0];
156
+ const canonRoot = path.join(installation.canon_root, roots[0]), memoryRoot = path.join(installation.canon_root, prefix);
157
+ const sourceFiles = new Map(archive.filter(entry => entry.kind === "file").map(entry => [entry.path, entry.bytes]));
158
+ const files = new Map(), folded = new Set();
159
+ let total = 0;
160
+ const put = (logical, content) => {
161
+ if (!/^(?:dd-flow|mbb)\/[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/.test(logical)
162
+ || content.length > 1024 * 1024 || files.size >= 20_000 || (total += content.length) > 64 * 1024 * 1024
163
+ || folded.has(logical.toLowerCase()))
164
+ refuse("unsafe_or_unbounded_baseline");
165
+ folded.add(logical.toLowerCase());
166
+ files.set(logical, Buffer.from(content));
167
+ };
168
+ const flowRoot = path.join(memoryRoot, "dd-flow");
169
+ for (const logical of [...new Set(current.included_files)].sort()) {
170
+ if (typeof logical !== "string" || !/^[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/.test(logical)
171
+ || logical.split("/").some(part => [".", ".."].includes(part)))
172
+ refuse("unsafe_baseline_path");
173
+ if (logical === "manifest.json")
174
+ continue;
175
+ const content = sourceFiles.get(`${prefix}/dd-flow/${logical}`);
176
+ if (content)
177
+ put(`dd-flow/${logical}`, content);
178
+ }
179
+ const included = [...files.keys()].map(logical => logical.slice("dd-flow/".length));
180
+ if (!included.length)
181
+ return null;
182
+ for (const [logical, content] of sourceFiles) {
183
+ const relative = logical.slice(prefix.length + 1);
184
+ if (logical.startsWith(`${prefix}/`) && (relative.startsWith("mbb/") || isCanonicalOnlyMemoryPath(relative)))
185
+ put(relative, content);
186
+ }
187
+ const manifestBytes = Buffer.from(JSON.stringify({ schema_id: "dd-flow/project-flow-pack-manifest@1",
188
+ pack_version: installation.manifest.canon.version, flow_origin_policy: "project_local_pack", canon_root: canonRoot,
189
+ canon_memory_bank_root: memoryRoot, canon_flow_root: flowRoot, source_commit: installation.manifest.canon.commit,
190
+ canon_version_at_source_commit: installation.manifest.canon.version, installed_at: current.installed_at,
191
+ included_files: included, file_hashes: Object.fromEntries(included.map(logical => [logical, hash(files.get(`dd-flow/${logical}`))])),
192
+ excluded_canonical_only_flows: canonicalOnlyFlowNames }));
193
+ if (files.size >= 20_000 || manifestBytes.length > 1024 * 1024 || total + manifestBytes.length > 64 * 1024 * 1024)
194
+ refuse("unsafe_or_unbounded_baseline");
195
+ files.set("dd-flow/manifest.json", manifestBytes);
196
+ return new PreparedMemoryLayer(new Map([...files].sort(([left], [right]) => left.localeCompare(right, "en"))), installation.manifest_sha256);
197
+ }
198
+ /** Restore only with an independently retained hash of an already admitted layer.
199
+ * SHA admission proves the original verified bytes; mutable installation sources are not read.
200
+ */
201
+ static restoreRetained(files, expectedSha256, installationSha256, allowEmpty = false) {
202
+ if (!/^[a-f0-9]{64}$/.test(expectedSha256) || !/^[a-f0-9]{64}$/.test(installationSha256)
203
+ || files.size < 1 || files.size > 20_000)
204
+ refuse("invalid_retained_selection");
205
+ let total = 0;
206
+ const folded = new Set(), retained = new Map();
207
+ for (const [logical, content] of files) {
208
+ if (!/^(?:mbb|dd-flow)\/[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/.test(logical)
209
+ || logical.split("/").some(segment => segment === "." || segment === "..")
210
+ || folded.has(logical.toLowerCase()) || !allowEmpty && content.length < 1 || content.length > 1024 * 1024
211
+ || (total += content.length) > 64 * 1024 * 1024)
212
+ refuse("unsafe_or_unbounded_inventory");
213
+ folded.add(logical.toLowerCase());
214
+ retained.set(logical, Buffer.from(content));
215
+ }
216
+ const result = new PreparedMemoryLayer(new Map([...retained].sort(([left], [right]) => left.localeCompare(right, "en"))), installationSha256);
217
+ if (result.sha256 !== expectedSha256)
218
+ refuse("retained_layer_changed");
219
+ return result;
220
+ }
221
+ }
@@ -0,0 +1,194 @@
1
+ import { AppError } from "../shared/errors.js";
2
+ import { createHash } from "node:crypto";
3
+ import { parseDocument } from "yaml";
4
+ /** Source templates are assets, not instantiated project documents. A known
5
+ * canonical asset may retain customized placement or a fixed example date;
6
+ * its header must still be a template. A directory name grants no exemption. */
7
+ export function memoryCanonicalTemplatePaths(entries, files, current) {
8
+ const result = new Set();
9
+ const placeholder = (value) => typeof value === "string" && /<[^>]+>/.test(value);
10
+ const header = (bytes) => {
11
+ const match = new TextDecoder("utf-8", { fatal: true }).decode(bytes).match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
12
+ if (!match)
13
+ return null;
14
+ const document = parseDocument(match[1]);
15
+ return document.errors.length ? null : document.toJS();
16
+ };
17
+ for (const entry of entries) {
18
+ if (!/^mbb\/templates\/.+\.(?:md|markdown)$/.test(entry.path) || !entry.target || !["canonical", "local-customized"].includes(entry.ownership))
19
+ continue;
20
+ const target = files.get(entry.path);
21
+ if (!target || createHash("sha256").update(target).digest("hex") !== entry.target.sha256)
22
+ refuse("canonical_template_source_changed");
23
+ const bytes = current.get(entry.path);
24
+ if (!bytes)
25
+ continue;
26
+ try {
27
+ const source = header(target), observed = header(bytes);
28
+ if (source && observed && typeof observed.date === "string" && /^(?:YYYY-MM-DD|\d{4}-\d{2}-\d{2})$/.test(observed.date)
29
+ && ["file", "description", "purpose"].some(key => placeholder(source[key]) && placeholder(observed[key])))
30
+ result.add(`.memory-bank/${entry.path}`);
31
+ }
32
+ catch { /* Malformed headers remain active and are linted. */ }
33
+ }
34
+ return result;
35
+ }
36
+ /** A copied canonical guide may name its source repository's specs/protocols.
37
+ * Only those exact frozen relations are foreign provenance, not a promise that
38
+ * the consumer contains them. New project targets and body links stay checked. */
39
+ export function memoryCanonicalLintExceptions(entries, files, selected) {
40
+ const result = [];
41
+ for (const file of new Set(selected)) {
42
+ if (!/^\.memory-bank\/(?:dd-flow|mbb)\/.+\.(?:md|markdown)$/.test(file))
43
+ continue;
44
+ if (["*", "?", "[", "]", "{", "}", "!", "(", ")", "\\"].some(character => file.includes(character)))
45
+ continue;
46
+ const logical = file.slice(13), entry = entries.find(entry => entry.path === logical);
47
+ if (!entry?.target || !["canonical", "local-customized"].includes(entry.ownership))
48
+ continue;
49
+ const bytes = files.get(logical);
50
+ if (!bytes || createHash("sha256").update(bytes).digest("hex") !== entry.target.sha256)
51
+ refuse("canonical_guidance_source_changed");
52
+ let header;
53
+ try {
54
+ const match = new TextDecoder("utf-8", { fatal: true }).decode(bytes).match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
55
+ if (!match)
56
+ continue;
57
+ const document = parseDocument(match[1]);
58
+ if (document.errors.length)
59
+ continue;
60
+ const value = document.toJS();
61
+ if (!value || typeof value !== "object" || Array.isArray(value) || value.file !== file)
62
+ continue;
63
+ header = value;
64
+ }
65
+ catch {
66
+ continue;
67
+ }
68
+ const targets = new Set(["related_specs", "related_protocols"].flatMap(key => Array.isArray(header[key]) ? header[key] : [])
69
+ .filter((target) => typeof target === "string" && /^\.memory-bank\/(?:spec|protocol)\//.test(target)
70
+ && !["*", "?", "[", "]", "{", "}", "!", "(", ")"].some(character => target.includes(character))
71
+ && !target.includes("\\") && !target.includes("\0") && target.split("/").every(part => part && part !== "." && part !== "..")));
72
+ for (const target of targets)
73
+ result.push({ ruleId: "links/frontmatter-target-exists", file, target,
74
+ reason: "Source-canon spec/protocol provenance, not a required consumer-owned document; source resolution is not claimed." });
75
+ }
76
+ return result;
77
+ }
78
+ /** Pure ownership projection from retained inventory and accepted diff. Exact
79
+ * retained-only bytes keep their existing lint policy; they are preservation
80
+ * artifacts, not new authoring. Changed or semantic-work files stay protected.
81
+ * Mechanical canonical references remain verified by their publication owner. */
82
+ export function memoryUpgradeLintGuidance(entries, changes) {
83
+ const authored = new Set(changes.filter(change => change.action === "semantic-work").map(change => change.to));
84
+ const retained = new Set(changes.filter(change => change.action === "retain" && change.from === change.to).map(change => change.from));
85
+ const preserved = entries.filter(entry => entry.current?.kind === "file" && /\.(?:md|markdown)$/.test(entry.path)
86
+ && retained.has(`.memory-bank/${entry.path}`) && !authored.has(`.memory-bank/${entry.path}`))
87
+ .map(entry => [`.memory-bank/${entry.path}`, entry.current.sha256]);
88
+ return new Map([...preserved, ...entries.filter(entry => entry.ownership === "canonical" && entry.target
89
+ && /^(?:dd-flow|mbb)\//.test(entry.path) && !authored.has(`.memory-bank/${entry.path}`))
90
+ .map(entry => [`.memory-bank/${entry.path}`, entry.target.sha256])]);
91
+ }
92
+ /** Review inputs also contain immutable guidance; only accepted current unit
93
+ * artifacts are project output that lint configuration must not suppress. */
94
+ export function memoryVerificationActivePaths(units, assignments = [], guidance, templates) {
95
+ return [".memory-bank/index.md", ".memory-bank/structure.md", ".memory-bank/project-policy.md",
96
+ ...units.flatMap(unit => (assignments.find(assignment => assignment.unit.id === unit.id)?.unit ?? unit).artifacts
97
+ .filter(artifact => artifact.root === "workspace" && !templates?.has(artifact.path) && !(typeof artifact.sha256 === "string" && guidance?.get(artifact.path) === artifact.sha256))
98
+ .map(artifact => artifact.path))];
99
+ }
100
+ /** Bootstrap-owned policy for immutable guidance, never project knowledge or
101
+ * the two project-owned JSON defaults beside the canonical flow pack. */
102
+ export function defaultMemoryLintConfiguration() {
103
+ return Buffer.from(`${JSON.stringify({
104
+ ignorePaths: [".memory-bank/dd-flow/*.md", ".memory-bank/dd-flow/**/*.md", ".memory-bank/mbb/templates/**"],
105
+ ignoreFindings: [{ ruleId: "def/required-fields", file: ".memory-bank/mbb/named-deferrals-guide.md",
106
+ target: "DEF-UI-PROTECTED-BROWSER-PROOF", reason: "Illustrative DEF in immutable canonical guidance, not a project deferral." }]
107
+ }, null, 2)}\n`);
108
+ }
109
+ function refuse(reason) {
110
+ throw new AppError("memory_lint_config_invalid", "Lint configuration cannot suppress active memory verification", 2, { reason, effect: "no_effect" });
111
+ }
112
+ function record(value) {
113
+ if (!value || typeof value !== "object" || Array.isArray(value))
114
+ refuse("invalid_config_object");
115
+ return value;
116
+ }
117
+ function patterns(value) {
118
+ if (value === undefined)
119
+ return [];
120
+ if (!Array.isArray(value) || value.some(pattern => typeof pattern !== "string" || !pattern.trim() || pattern.includes("\0")))
121
+ refuse("invalid_ignore_paths");
122
+ return value;
123
+ }
124
+ // mb-lint's documented matcher uses literal characters plus * and **, not
125
+ // shell/extglob semantics. Backslashes are normalized to portable separators.
126
+ function matches(pattern, file) {
127
+ const portable = pattern.replaceAll("\\", "/");
128
+ if (["?", "[", "]", "{", "}", "!", "(", ")"].some(character => portable.includes(character)) || portable.split("/").some(segment => !segment || segment === "." || segment === ".."))
129
+ refuse("unsupported_ignore_pattern");
130
+ const chunks = portable.split(/(\*\*|\*)/);
131
+ const source = chunks.map(chunk => chunk === "**" ? ".*" : chunk === "*" ? "[^/]*" : chunk.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&")).join("");
132
+ return new RegExp(`^${source}$`).test(file.replaceAll("\\", "/"));
133
+ }
134
+ /** Pure admission, no writes or inference of semantic completeness. Protected
135
+ * paths come from accepted composition plus required active root documents.
136
+ * Existing config bytes remain user-owned; exclusion repair is not automatic.
137
+ */
138
+ export function validateMemoryLintConfig(bytes, activePaths) {
139
+ if (!(bytes instanceof Uint8Array) || !bytes.length || bytes.length > 1024 * 1024)
140
+ refuse("invalid_config_bytes");
141
+ let parsed;
142
+ try {
143
+ parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
144
+ }
145
+ catch {
146
+ return refuse("invalid_config_json");
147
+ }
148
+ const config = record(parsed), allowed = new Set(["ignorePaths", "ignoreFindings", "ignore", "git"]);
149
+ if (Object.keys(config).some(key => !allowed.has(key)))
150
+ refuse("unsupported_config_field");
151
+ const nested = config.ignore === undefined ? {} : record(config.ignore);
152
+ if (Object.keys(nested).some(key => !['files', 'findings'].includes(key)))
153
+ refuse("unsupported_ignore_field");
154
+ const paths = [...patterns(config.ignorePaths), ...patterns(nested.files)];
155
+ if (paths.some(pattern => activePaths.some(file => matches(pattern, file))))
156
+ refuse("active_document_ignored");
157
+ for (const list of [config.ignoreFindings, nested.findings]) {
158
+ if (list === undefined)
159
+ continue;
160
+ if (!Array.isArray(list))
161
+ refuse("invalid_ignore_findings");
162
+ for (const item of list) {
163
+ const finding = record(item);
164
+ if (Object.keys(finding).some(key => !['ruleId', 'file', 'target', 'reason'].includes(key))
165
+ || Object.values(finding).some(value => typeof value !== "string" || !value.trim() || value.includes("\0")))
166
+ refuse("invalid_ignore_finding");
167
+ if (typeof finding.file !== "string" || activePaths.some(file => matches(finding.file, file)))
168
+ refuse("active_finding_suppressed");
169
+ }
170
+ }
171
+ if (config.git !== undefined) {
172
+ const git = record(config.git);
173
+ if (Object.keys(git).some(key => key !== "respectIgnore") || git.respectIgnore !== undefined && typeof git.respectIgnore !== "boolean")
174
+ refuse("invalid_git_config");
175
+ }
176
+ }
177
+ /** Preserve project lint policy, but independently check every active Markdown
178
+ * document it suppresses. JSON artifacts belong to their schema owners, not
179
+ * mb-lint's Markdown scanner. Invalid policy still refuses instead of fallback. */
180
+ export function memoryVerificationSupplementalLintFiles(bytes, activePaths) {
181
+ validateMemoryLintConfig(bytes, []);
182
+ return [...new Set(activePaths)].filter(file => file.startsWith(".memory-bank/") && /\.(?:md|markdown)$/.test(file)).filter(file => {
183
+ try {
184
+ validateMemoryLintConfig(bytes, [file]);
185
+ return false;
186
+ }
187
+ catch (error) {
188
+ if (error instanceof AppError && error.code === "memory_lint_config_invalid"
189
+ && ["active_document_ignored", "active_finding_suppressed"].includes(String(error.details.reason)))
190
+ return true;
191
+ throw error;
192
+ }
193
+ });
194
+ }
@@ -0,0 +1,103 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { AppError } from "../shared/errors.js";
4
+ import { appendAudit } from "./audit.js";
5
+ import { hybridDigest } from "./hybrid-contracts.js";
6
+ import { prepareMemoryReviewWorkInput, assertPreparedMemoryReviewWorkInput } from "./memory-review-work-input.js";
7
+ import { assertRunMutationAllowed } from "./run-recovery-guard.js";
8
+ import { reviewSourceFilter, reviewSourceHash, reviewExecutionCopyHash } from "./review-copy.js";
9
+ import { writeReviewGitEvidence } from "./external-work-launch.js";
10
+ import { memoryReviewPhysicalDestination } from "./hook-memory-routing.js";
11
+ function refuse(reason) { throw new AppError("memory_native_review_copy_invalid", "Native Memory review requires an independently owned immutable execution copy", 1, { reason, effect: "no_effect" }); }
12
+ export { memoryNativeReviewAssignedHookCwd } from "./hook-memory-routing.js";
13
+ /** Existing source/copy policy, separate native physical custody: no external
14
+ * launch row is invented. An interrupted allocation is never overwritten. */
15
+ export function prepareMemoryNativeReviewCopy(context, workId, allocate = false, preparedOwner) {
16
+ const work = context.db.get("SELECT * FROM works WHERE work_id=?", [workId]);
17
+ if (!work)
18
+ refuse("owned_work_required");
19
+ const run = context.db.get("SELECT * FROM runs WHERE project_id=? AND id=?", [work.project_id, work.run_id]);
20
+ if (!run)
21
+ refuse("owned_run_required");
22
+ const generation = assertRunMutationAllowed(context, work.project_id, work.run_id);
23
+ const owner = preparedOwner ?? prepareMemoryReviewWorkInput(context, work, run, generation);
24
+ assertPreparedMemoryReviewWorkInput(context, owner, work, run, generation);
25
+ const route = owner.bundle.execution.work("review");
26
+ if (route.delegation.mode !== "native")
27
+ refuse("native_route_required");
28
+ const relative = `works/${workId}/native-review-workspaces/generation-${generation}`;
29
+ const runRoot = run.run_root ?? run.run_dir, root = path.join(runRoot, relative);
30
+ memoryReviewPhysicalDestination(runRoot, relative);
31
+ const inputs = owner.input.run_inputs.filter(ref => ref.root === "workspace").map(ref => ref.path);
32
+ const selectedBase = JSON.parse(run.index_json).workspace?.base;
33
+ const base = selectedBase && selectedBase !== "unknown" ? selectedBase : "HEAD";
34
+ const intent = { schema_id: "dd-flow/memory-native-review-copy@1", project_id: work.project_id, run_id: work.run_id,
35
+ work_id: workId, generation, root: relative, input_sha256: hybridDigest(owner.input), source_sha256: reviewSourceHash(run.workspace_root, inputs, base) };
36
+ // A recovery generation gets a new owned copy; never adopt the previous
37
+ // generation's journal or overwrite its physical evidence.
38
+ const retained = (event, reader = context) => reader.db.all("SELECT payload_json FROM audit_events WHERE project_id=? AND event_type=? AND COALESCE(json_extract(payload_json,'$.run_id'),json_extract(payload_json,'$.intent.run_id'))=? AND COALESCE(json_extract(payload_json,'$.work_id'),json_extract(payload_json,'$.intent.work_id'))=? AND COALESCE(json_extract(payload_json,'$.generation'),json_extract(payload_json,'$.intent.generation'))=? LIMIT 2", [work.project_id, event, work.run_id, workId, generation]);
39
+ const ready = retained("memory.native_review_copy_ready");
40
+ let copy;
41
+ if (ready.length) {
42
+ if (ready.length !== 1)
43
+ refuse("ambiguous_copy");
44
+ const intents = retained("memory.native_review_copy_intent");
45
+ if (intents.length !== 1 || hybridDigest(JSON.parse(intents[0].payload_json)) !== hybridDigest(intent))
46
+ refuse("copy_custody_changed");
47
+ const value = JSON.parse(ready[0].payload_json);
48
+ if (hybridDigest(value.intent) !== hybridDigest(intent) || !/^[a-f0-9]{64}$/.test(value.sha256))
49
+ refuse("copy_or_source_changed");
50
+ copy = { root: relative, sha256: value.sha256, source_sha256: intent.source_sha256 };
51
+ }
52
+ else {
53
+ if (!allocate)
54
+ refuse("ready_copy_required");
55
+ if (retained("memory.native_review_copy_intent").length || fs.lstatSync(root, { throwIfNoEntry: false }))
56
+ refuse("copy_allocation_unsettled");
57
+ owner.revalidate(context);
58
+ context.db.writeTransaction(() => {
59
+ owner.assertCustody(context);
60
+ if (retained("memory.native_review_copy_intent").length)
61
+ refuse("copy_allocation_unsettled");
62
+ appendAudit(context, { projectId: work.project_id, eventType: "memory.native_review_copy_intent", payload: intent });
63
+ });
64
+ try {
65
+ fs.mkdirSync(path.dirname(root), { recursive: true, mode: 0o700 });
66
+ memoryReviewPhysicalDestination(runRoot, relative);
67
+ fs.mkdirSync(root, { mode: 0o700 }); // Exclusive: never adopt an existing or partial destination.
68
+ memoryReviewPhysicalDestination(runRoot, relative);
69
+ fs.cpSync(run.workspace_root, root, { recursive: true, verbatimSymlinks: true, force: false, errorOnExist: true, filter: reviewSourceFilter(run.workspace_root, inputs, base) });
70
+ if (reviewSourceHash(run.workspace_root, inputs, base) !== intent.source_sha256
71
+ || reviewExecutionCopyHash(root, run.workspace_root, false, inputs, base) !== intent.source_sha256)
72
+ refuse("copy_or_source_changed");
73
+ writeReviewGitEvidence(run.workspace_root, root, base, inputs);
74
+ owner.revalidate(context);
75
+ if (reviewSourceHash(run.workspace_root, inputs, base) !== intent.source_sha256
76
+ || reviewExecutionCopyHash(root, run.workspace_root, false, inputs, base) !== intent.source_sha256)
77
+ refuse("copy_or_source_changed");
78
+ copy = { root: relative, source_sha256: intent.source_sha256, sha256: reviewExecutionCopyHash(root, run.workspace_root, true, inputs, base) };
79
+ context.db.writeTransaction(() => {
80
+ owner.assertCustody(context);
81
+ if (retained("memory.native_review_copy_ready").length)
82
+ refuse("copy_allocation_unsettled");
83
+ appendAudit(context, { projectId: work.project_id, eventType: "memory.native_review_copy_ready", payload: { intent, sha256: copy.sha256 } });
84
+ });
85
+ }
86
+ catch (error) {
87
+ throw new AppError("memory_native_review_copy_pending", "Native review copy allocation is retained and cannot be replayed or overwritten", 1, { effect: "partial", recoverable: false, work_id: workId, copy_root: root, next_action: "Inspect the exact retained copy intent and private destination; do not relaunch or adopt partial files.",
88
+ cause: error instanceof Error ? error.message : String(error) });
89
+ }
90
+ }
91
+ if (reviewExecutionCopyHash(root, run.workspace_root, true, inputs, base) !== copy.sha256)
92
+ refuse("copy_changed");
93
+ const assertCustody = (writer) => {
94
+ owner.assertCustody(writer);
95
+ assertRunMutationAllowed(writer, work.project_id, work.run_id, generation);
96
+ const rows = retained("memory.native_review_copy_ready", writer);
97
+ const intents = retained("memory.native_review_copy_intent", writer);
98
+ if (intents.length !== 1 || hybridDigest(JSON.parse(intents[0].payload_json)) !== hybridDigest(intent)
99
+ || rows.length !== 1 || hybridDigest(JSON.parse(rows[0].payload_json)) !== hybridDigest({ intent, sha256: copy.sha256 }))
100
+ refuse("copy_custody_changed");
101
+ };
102
+ return { root, copy, route, assertCustody };
103
+ }
@@ -0,0 +1,87 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ import { parse as parseYaml } from "yaml";
5
+ import { AppError } from "../shared/errors.js";
6
+ import { ObservedMemorySources } from "./memory-source-observations.js";
7
+ import { memorySourceKey } from "./memory-stage-results.js";
8
+ import { prepareVnextSpecifyStart } from "./vnext-specify.js";
9
+ import { loadVnextWorkspacePolicy } from "./vnext-workspace-policy.js";
10
+ import { hybridDigest } from "./hybrid-contracts.js";
11
+ const identity = [".memory-bank/index.md", ".memory-bank/structure.md", ".memory-bank/project-policy.md"];
12
+ /** VERIFY diagnostics must remain reviewable when preparation fails. Neither
13
+ * outcome creates a future task or establishes provider access. */
14
+ export function observeMemoryNormalFlowEntryDiagnostic(context, projectRoot) {
15
+ try {
16
+ return { status: "prepared", observation: observeMemoryNormalFlowEntry(context, projectRoot) };
17
+ }
18
+ catch (error) {
19
+ if (!(error instanceof AppError))
20
+ throw error;
21
+ return { status: "unavailable", error: { code: error.code, reason: error.details?.reason ?? null } };
22
+ }
23
+ }
24
+ function refuse(reason) {
25
+ throw new AppError("memory_normal_flow_entry_invalid", "Ordinary SDLC entry cannot be prepared from initialized memory", 2, { reason, effect: "no_effect" });
26
+ }
27
+ /** Real ordinary-entry preparation only. No launch, protocol, Work, Session,
28
+ * provider, command execution or runtime receipt is created. Callers still
29
+ * need independent semantic review, selected pack/tools and integration. */
30
+ export function observeMemoryNormalFlowEntry(context, projectRoot) {
31
+ if (context.db.isOwnedWriteTransaction?.())
32
+ refuse("preparation_outside_writer_required");
33
+ if (typeof projectRoot !== "string" || !path.isAbsolute(projectRoot))
34
+ refuse("absolute_project_root_required");
35
+ const root = fs.realpathSync(projectRoot);
36
+ const paths = [...identity, ".memory-bank/mbb/index.md", ".memory-bank/dd-flow/flow-contract.json",
37
+ ".memory-bank/dd-flow/project-execution.json", ".memory-bank/dd-flow/project-workspace.json",
38
+ ".memory-bank/dd-flow/vnext/specify.md"];
39
+ for (const name of ["mb-sdlc-vnext-specify.json", "mb-sdlc-vnext-protocolize.json"]) {
40
+ const logical = `.memory-bank/dd-flow/vnext/${name}`;
41
+ try {
42
+ fs.lstatSync(path.join(root, logical));
43
+ paths.push(logical);
44
+ }
45
+ catch (error) {
46
+ if (error.code !== "ENOENT")
47
+ throw error;
48
+ }
49
+ }
50
+ const observe = (selected) => ObservedMemorySources.capture({ project: root }, selected.map(path => ({ root: "project", path })));
51
+ const before = observe(paths);
52
+ for (const logical of identity) {
53
+ const text = before.bytes({ root: "project", path: logical }).toString("utf8");
54
+ if (!text.startsWith("---\n") && !text.startsWith("---\r\n"))
55
+ refuse("identity_frontmatter_required");
56
+ const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
57
+ if (!match)
58
+ refuse("identity_frontmatter_required");
59
+ const header = parseYaml(match[1]);
60
+ if (!header || typeof header !== "object" || Array.isArray(header))
61
+ refuse("identity_frontmatter_required");
62
+ }
63
+ // This diagnostic intake is never persisted or dispatched as a user task.
64
+ const prepared = prepareVnextSpecifyStart(context, { projectRoot: root,
65
+ intakeMarkdown: "Internal ordinary-entry readiness preparation; do not launch a RUN.", slug: "memory-readiness" });
66
+ const policy = loadVnextWorkspacePolicy(root), profile = prepared.start?.executionProfile;
67
+ if (!profile || prepared.preflight.ok !== true || prepared.start?.projectRoot !== root)
68
+ refuse("ordinary_preparation_incomplete");
69
+ const policyPath = profile.settings.code_bootstrap?.policy_ref;
70
+ if (policyPath !== undefined && (typeof policyPath !== "string" || !policyPath.startsWith(".memory-bank/") || policyPath.includes("\\")
71
+ || policyPath.includes("\0") || policyPath.split("/").some(segment => !segment || segment === "." || segment === "..")))
72
+ refuse("bootstrap_policy_reference_required");
73
+ const selected = [...new Set([...paths, ...(policyPath === undefined ? [] : [policyPath]), ...prepared.grounding.map(item => item.source)])].sort();
74
+ const observed = observe(selected), hashes = observed.hashes();
75
+ before.revalidate();
76
+ if (hashes.get(memorySourceKey("project", ".memory-bank/dd-flow/project-execution.json")) !== profile.source_checksum)
77
+ refuse("ordinary_profile_changed");
78
+ observed.revalidate();
79
+ return { schema_id: "dd-flow/memory-normal-flow-entry-observation@1", project_root: root,
80
+ operation: "stage.start.bootstrap.specify", runtime_state: "not_created", model_access: "unknown",
81
+ source_sha256: observed.sha256, sources: selected.map(path => ({ root: "project", path,
82
+ sha256: hashes.get(memorySourceKey("project", path)) })),
83
+ profile_sha256: profile.source_checksum, execution_sha256: hybridDigest({ settings: profile.settings,
84
+ profiles: profile.agent_profiles ?? null, operational_decision: profile.operational_decision ?? null }),
85
+ template_sha256: createHash("sha256").update(prepared.template).digest("hex"),
86
+ workspace_policy: policy, handoff: prepared.handoff };
87
+ }