@devflow-tools/delivery-line 0.18.8

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 (259) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -0
  3. package/dist/__tests__/artifact-generation.test.d.ts +2 -0
  4. package/dist/__tests__/artifact-generation.test.d.ts.map +1 -0
  5. package/dist/__tests__/artifact-generation.test.js +16 -0
  6. package/dist/__tests__/artifact-generation.test.js.map +1 -0
  7. package/dist/__tests__/backend-scenario.e2e.test.d.ts +2 -0
  8. package/dist/__tests__/backend-scenario.e2e.test.d.ts.map +1 -0
  9. package/dist/__tests__/backend-scenario.e2e.test.js +25 -0
  10. package/dist/__tests__/backend-scenario.e2e.test.js.map +1 -0
  11. package/dist/__tests__/claude-events.test.d.ts +2 -0
  12. package/dist/__tests__/claude-events.test.d.ts.map +1 -0
  13. package/dist/__tests__/claude-events.test.js +28 -0
  14. package/dist/__tests__/claude-events.test.js.map +1 -0
  15. package/dist/__tests__/facade-e2e.test.d.ts +2 -0
  16. package/dist/__tests__/facade-e2e.test.d.ts.map +1 -0
  17. package/dist/__tests__/facade-e2e.test.js +167 -0
  18. package/dist/__tests__/facade-e2e.test.js.map +1 -0
  19. package/dist/__tests__/frontend-scenario.e2e.test.d.ts +2 -0
  20. package/dist/__tests__/frontend-scenario.e2e.test.d.ts.map +1 -0
  21. package/dist/__tests__/frontend-scenario.e2e.test.js +35 -0
  22. package/dist/__tests__/frontend-scenario.e2e.test.js.map +1 -0
  23. package/dist/__tests__/git-artifact-store.test.d.ts +2 -0
  24. package/dist/__tests__/git-artifact-store.test.d.ts.map +1 -0
  25. package/dist/__tests__/git-artifact-store.test.js +44 -0
  26. package/dist/__tests__/git-artifact-store.test.js.map +1 -0
  27. package/dist/__tests__/governance-adapters.test.d.ts +2 -0
  28. package/dist/__tests__/governance-adapters.test.d.ts.map +1 -0
  29. package/dist/__tests__/governance-adapters.test.js +51 -0
  30. package/dist/__tests__/governance-adapters.test.js.map +1 -0
  31. package/dist/__tests__/handoff-validator.test.d.ts +2 -0
  32. package/dist/__tests__/handoff-validator.test.d.ts.map +1 -0
  33. package/dist/__tests__/handoff-validator.test.js +13 -0
  34. package/dist/__tests__/handoff-validator.test.js.map +1 -0
  35. package/dist/__tests__/interaction-session.test.d.ts +2 -0
  36. package/dist/__tests__/interaction-session.test.d.ts.map +1 -0
  37. package/dist/__tests__/interaction-session.test.js +13 -0
  38. package/dist/__tests__/interaction-session.test.js.map +1 -0
  39. package/dist/__tests__/interaction.test.d.ts +2 -0
  40. package/dist/__tests__/interaction.test.d.ts.map +1 -0
  41. package/dist/__tests__/interaction.test.js +27 -0
  42. package/dist/__tests__/interaction.test.js.map +1 -0
  43. package/dist/__tests__/persistence.test.d.ts +2 -0
  44. package/dist/__tests__/persistence.test.d.ts.map +1 -0
  45. package/dist/__tests__/persistence.test.js +41 -0
  46. package/dist/__tests__/persistence.test.js.map +1 -0
  47. package/dist/__tests__/recovery-spike.test.d.ts +2 -0
  48. package/dist/__tests__/recovery-spike.test.d.ts.map +1 -0
  49. package/dist/__tests__/recovery-spike.test.js +20 -0
  50. package/dist/__tests__/recovery-spike.test.js.map +1 -0
  51. package/dist/__tests__/sqlite-recovery.test.d.ts +2 -0
  52. package/dist/__tests__/sqlite-recovery.test.d.ts.map +1 -0
  53. package/dist/__tests__/sqlite-recovery.test.js +90 -0
  54. package/dist/__tests__/sqlite-recovery.test.js.map +1 -0
  55. package/dist/__tests__/state-machine.test.d.ts +2 -0
  56. package/dist/__tests__/state-machine.test.d.ts.map +1 -0
  57. package/dist/__tests__/state-machine.test.js +49 -0
  58. package/dist/__tests__/state-machine.test.js.map +1 -0
  59. package/dist/__tests__/subagent-orchestrator.test.d.ts +2 -0
  60. package/dist/__tests__/subagent-orchestrator.test.d.ts.map +1 -0
  61. package/dist/__tests__/subagent-orchestrator.test.js +33 -0
  62. package/dist/__tests__/subagent-orchestrator.test.js.map +1 -0
  63. package/dist/__tests__/subagent-recovery.e2e.test.d.ts +2 -0
  64. package/dist/__tests__/subagent-recovery.e2e.test.d.ts.map +1 -0
  65. package/dist/__tests__/subagent-recovery.e2e.test.js +35 -0
  66. package/dist/__tests__/subagent-recovery.e2e.test.js.map +1 -0
  67. package/dist/__tests__/task-dag.test.d.ts +2 -0
  68. package/dist/__tests__/task-dag.test.d.ts.map +1 -0
  69. package/dist/__tests__/task-dag.test.js +31 -0
  70. package/dist/__tests__/task-dag.test.js.map +1 -0
  71. package/dist/__tests__/worker-integration.test.d.ts +2 -0
  72. package/dist/__tests__/worker-integration.test.d.ts.map +1 -0
  73. package/dist/__tests__/worker-integration.test.js +217 -0
  74. package/dist/__tests__/worker-integration.test.js.map +1 -0
  75. package/dist/adapters/approval.d.ts +40 -0
  76. package/dist/adapters/approval.d.ts.map +1 -0
  77. package/dist/adapters/approval.js +100 -0
  78. package/dist/adapters/approval.js.map +1 -0
  79. package/dist/adapters/delivery-package.d.ts +23 -0
  80. package/dist/adapters/delivery-package.d.ts.map +1 -0
  81. package/dist/adapters/delivery-package.js +37 -0
  82. package/dist/adapters/delivery-package.js.map +1 -0
  83. package/dist/adapters/integration.d.ts +37 -0
  84. package/dist/adapters/integration.d.ts.map +1 -0
  85. package/dist/adapters/integration.js +84 -0
  86. package/dist/adapters/integration.js.map +1 -0
  87. package/dist/adapters/review.d.ts +12 -0
  88. package/dist/adapters/review.d.ts.map +1 -0
  89. package/dist/adapters/review.js +33 -0
  90. package/dist/adapters/review.js.map +1 -0
  91. package/dist/adapters/verification.d.ts +25 -0
  92. package/dist/adapters/verification.d.ts.map +1 -0
  93. package/dist/adapters/verification.js +57 -0
  94. package/dist/adapters/verification.js.map +1 -0
  95. package/dist/adapters/workflow-execution.d.ts +130 -0
  96. package/dist/adapters/workflow-execution.d.ts.map +1 -0
  97. package/dist/adapters/workflow-execution.js +135 -0
  98. package/dist/adapters/workflow-execution.js.map +1 -0
  99. package/dist/artifact-generation.test.d.ts +2 -0
  100. package/dist/artifact-generation.test.d.ts.map +1 -0
  101. package/dist/artifact-generation.test.js +11 -0
  102. package/dist/artifact-generation.test.js.map +1 -0
  103. package/dist/artifacts/context-manifest.d.ts +20 -0
  104. package/dist/artifacts/context-manifest.d.ts.map +1 -0
  105. package/dist/artifacts/context-manifest.js +24 -0
  106. package/dist/artifacts/context-manifest.js.map +1 -0
  107. package/dist/artifacts/generation-guard.d.ts +13 -0
  108. package/dist/artifacts/generation-guard.d.ts.map +1 -0
  109. package/dist/artifacts/generation-guard.js +16 -0
  110. package/dist/artifacts/generation-guard.js.map +1 -0
  111. package/dist/artifacts/git-artifact-store.d.ts +16 -0
  112. package/dist/artifacts/git-artifact-store.d.ts.map +1 -0
  113. package/dist/artifacts/git-artifact-store.js +47 -0
  114. package/dist/artifacts/git-artifact-store.js.map +1 -0
  115. package/dist/claude-events.test.d.ts +2 -0
  116. package/dist/claude-events.test.d.ts.map +1 -0
  117. package/dist/claude-events.test.js +14 -0
  118. package/dist/claude-events.test.js.map +1 -0
  119. package/dist/composition.d.ts +13 -0
  120. package/dist/composition.d.ts.map +1 -0
  121. package/dist/composition.js +47 -0
  122. package/dist/composition.js.map +1 -0
  123. package/dist/domain/interaction.d.ts +23 -0
  124. package/dist/domain/interaction.d.ts.map +1 -0
  125. package/dist/domain/interaction.js +60 -0
  126. package/dist/domain/interaction.js.map +1 -0
  127. package/dist/domain/state-machine.d.ts +26 -0
  128. package/dist/domain/state-machine.d.ts.map +1 -0
  129. package/dist/domain/state-machine.js +67 -0
  130. package/dist/domain/state-machine.js.map +1 -0
  131. package/dist/domain/task-dag.d.ts +5 -0
  132. package/dist/domain/task-dag.d.ts.map +1 -0
  133. package/dist/domain/task-dag.js +78 -0
  134. package/dist/domain/task-dag.js.map +1 -0
  135. package/dist/domain/types.d.ts +320 -0
  136. package/dist/domain/types.d.ts.map +1 -0
  137. package/dist/domain/types.js +9 -0
  138. package/dist/domain/types.js.map +1 -0
  139. package/dist/facade/delivery-line-facade.d.ts +77 -0
  140. package/dist/facade/delivery-line-facade.d.ts.map +1 -0
  141. package/dist/facade/delivery-line-facade.js +417 -0
  142. package/dist/facade/delivery-line-facade.js.map +1 -0
  143. package/dist/git-artifact-store.test.d.ts +2 -0
  144. package/dist/git-artifact-store.test.d.ts.map +1 -0
  145. package/dist/git-artifact-store.test.js +27 -0
  146. package/dist/git-artifact-store.test.js.map +1 -0
  147. package/dist/governance-adapters.test.d.ts +2 -0
  148. package/dist/governance-adapters.test.d.ts.map +1 -0
  149. package/dist/governance-adapters.test.js +14 -0
  150. package/dist/governance-adapters.test.js.map +1 -0
  151. package/dist/handoff-validator.test.d.ts +2 -0
  152. package/dist/handoff-validator.test.d.ts.map +1 -0
  153. package/dist/handoff-validator.test.js +10 -0
  154. package/dist/handoff-validator.test.js.map +1 -0
  155. package/dist/index.d.ts +37 -0
  156. package/dist/index.d.ts.map +1 -0
  157. package/dist/index.js +37 -0
  158. package/dist/index.js.map +1 -0
  159. package/dist/interaction-session.d.ts +12 -0
  160. package/dist/interaction-session.d.ts.map +1 -0
  161. package/dist/interaction-session.js +21 -0
  162. package/dist/interaction-session.js.map +1 -0
  163. package/dist/interaction-session.test.d.ts +2 -0
  164. package/dist/interaction-session.test.d.ts.map +1 -0
  165. package/dist/interaction-session.test.js +13 -0
  166. package/dist/interaction-session.test.js.map +1 -0
  167. package/dist/persistence/cas.d.ts +4 -0
  168. package/dist/persistence/cas.d.ts.map +1 -0
  169. package/dist/persistence/cas.js +7 -0
  170. package/dist/persistence/cas.js.map +1 -0
  171. package/dist/persistence/event-ledger.d.ts +10 -0
  172. package/dist/persistence/event-ledger.d.ts.map +1 -0
  173. package/dist/persistence/event-ledger.js +6 -0
  174. package/dist/persistence/event-ledger.js.map +1 -0
  175. package/dist/persistence/memory-store.d.ts +51 -0
  176. package/dist/persistence/memory-store.d.ts.map +1 -0
  177. package/dist/persistence/memory-store.js +99 -0
  178. package/dist/persistence/memory-store.js.map +1 -0
  179. package/dist/persistence/schema.d.ts +2 -0
  180. package/dist/persistence/schema.d.ts.map +1 -0
  181. package/dist/persistence/schema.js +107 -0
  182. package/dist/persistence/schema.js.map +1 -0
  183. package/dist/persistence/sqlite-store.d.ts +59 -0
  184. package/dist/persistence/sqlite-store.d.ts.map +1 -0
  185. package/dist/persistence/sqlite-store.js +133 -0
  186. package/dist/persistence/sqlite-store.js.map +1 -0
  187. package/dist/persistence.test.d.ts +2 -0
  188. package/dist/persistence.test.d.ts.map +1 -0
  189. package/dist/persistence.test.js +28 -0
  190. package/dist/persistence.test.js.map +1 -0
  191. package/dist/ports/index.d.ts +248 -0
  192. package/dist/ports/index.d.ts.map +1 -0
  193. package/dist/ports/index.js +2 -0
  194. package/dist/ports/index.js.map +1 -0
  195. package/dist/recovery-spike.d.ts +22 -0
  196. package/dist/recovery-spike.d.ts.map +1 -0
  197. package/dist/recovery-spike.js +28 -0
  198. package/dist/recovery-spike.js.map +1 -0
  199. package/dist/recovery-spike.test.d.ts +2 -0
  200. package/dist/recovery-spike.test.d.ts.map +1 -0
  201. package/dist/recovery-spike.test.js +20 -0
  202. package/dist/recovery-spike.test.js.map +1 -0
  203. package/dist/runtime/claude-host-adapter.d.ts +28 -0
  204. package/dist/runtime/claude-host-adapter.d.ts.map +1 -0
  205. package/dist/runtime/claude-host-adapter.js +43 -0
  206. package/dist/runtime/claude-host-adapter.js.map +1 -0
  207. package/dist/runtime/context-binder.d.ts +61 -0
  208. package/dist/runtime/context-binder.d.ts.map +1 -0
  209. package/dist/runtime/context-binder.js +26 -0
  210. package/dist/runtime/context-binder.js.map +1 -0
  211. package/dist/runtime/execution-coordinator.d.ts +32 -0
  212. package/dist/runtime/execution-coordinator.d.ts.map +1 -0
  213. package/dist/runtime/execution-coordinator.js +243 -0
  214. package/dist/runtime/execution-coordinator.js.map +1 -0
  215. package/dist/runtime/gate-queue.d.ts +17 -0
  216. package/dist/runtime/gate-queue.d.ts.map +1 -0
  217. package/dist/runtime/gate-queue.js +33 -0
  218. package/dist/runtime/gate-queue.js.map +1 -0
  219. package/dist/runtime/host-conformance.d.ts +47 -0
  220. package/dist/runtime/host-conformance.d.ts.map +1 -0
  221. package/dist/runtime/host-conformance.js +61 -0
  222. package/dist/runtime/host-conformance.js.map +1 -0
  223. package/dist/runtime/host-routing.d.ts +5 -0
  224. package/dist/runtime/host-routing.d.ts.map +1 -0
  225. package/dist/runtime/host-routing.js +42 -0
  226. package/dist/runtime/host-routing.js.map +1 -0
  227. package/dist/runtime/memory-writeback.d.ts +18 -0
  228. package/dist/runtime/memory-writeback.d.ts.map +1 -0
  229. package/dist/runtime/memory-writeback.js +23 -0
  230. package/dist/runtime/memory-writeback.js.map +1 -0
  231. package/dist/runtime/operation-journal.d.ts +13 -0
  232. package/dist/runtime/operation-journal.d.ts.map +1 -0
  233. package/dist/runtime/operation-journal.js +38 -0
  234. package/dist/runtime/operation-journal.js.map +1 -0
  235. package/dist/runtime/plan-compiler.d.ts +37 -0
  236. package/dist/runtime/plan-compiler.d.ts.map +1 -0
  237. package/dist/runtime/plan-compiler.js +62 -0
  238. package/dist/runtime/plan-compiler.js.map +1 -0
  239. package/dist/runtime/project-runtime-factory.d.ts +15 -0
  240. package/dist/runtime/project-runtime-factory.d.ts.map +1 -0
  241. package/dist/runtime/project-runtime-factory.js +11 -0
  242. package/dist/runtime/project-runtime-factory.js.map +1 -0
  243. package/dist/runtime/review-coordinator.d.ts +25 -0
  244. package/dist/runtime/review-coordinator.d.ts.map +1 -0
  245. package/dist/runtime/review-coordinator.js +22 -0
  246. package/dist/runtime/review-coordinator.js.map +1 -0
  247. package/dist/subagents/claude-events.d.ts +59 -0
  248. package/dist/subagents/claude-events.d.ts.map +1 -0
  249. package/dist/subagents/claude-events.js +60 -0
  250. package/dist/subagents/claude-events.js.map +1 -0
  251. package/dist/subagents/handoff-validator.d.ts +8 -0
  252. package/dist/subagents/handoff-validator.d.ts.map +1 -0
  253. package/dist/subagents/handoff-validator.js +20 -0
  254. package/dist/subagents/handoff-validator.js.map +1 -0
  255. package/dist/subagents/orchestrator.d.ts +47 -0
  256. package/dist/subagents/orchestrator.d.ts.map +1 -0
  257. package/dist/subagents/orchestrator.js +85 -0
  258. package/dist/subagents/orchestrator.js.map +1 -0
  259. package/package.json +45 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 shilongfeicool
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # @devflow-tools/delivery-line
2
+
3
+ > 从需求澄清到受控 `integrationRef` 与可审计交付包的宿主中立交付编排。
4
+
5
+ [![npm version](https://img.shields.io/npm/v/%40devflow-tools%2Fdelivery-line.svg)](https://www.npmjs.com/package/@devflow-tools/delivery-line)
6
+
7
+ ## 安装
8
+
9
+ ```bash
10
+ npm install @devflow-tools/delivery-line
11
+ ```
12
+
13
+ ## 快速开始
14
+
15
+ ```typescript
16
+ import { ProjectRuntimeFactory } from '@devflow-tools/delivery-line';
17
+
18
+ const runtime = await ProjectRuntimeFactory.create({ projectRoot: process.cwd() });
19
+ const status = await runtime.facade.createCase({
20
+ actor: { id: 'owner', kind: 'human' },
21
+ sessionId: 'session-1',
22
+ executionId: 'execution-1',
23
+ idempotencyKey: 'create-1',
24
+ contextReceipt: 'context-receipt-1',
25
+ projectRoot: runtime.projectRoot,
26
+ baseRef: 'HEAD',
27
+ targetRef: 'main',
28
+ title: 'Implement and verify a scoped change',
29
+ });
30
+ ```
31
+
32
+ ## 运行边界
33
+
34
+ - Delivery Line 只更新案件专属 `integrationRef`,不会写入受保护的 `targetRef`。
35
+ - Worker、Verification、Review、Approval 与 Package 都通过显式 Port/Adapter 接入。
36
+ - 宿主能力必须先通过 conformance probe;缺失能力会使案件进入 `held`,不会伪造成功。
37
+ - 代码、Memory 与 Knowledge 只以带来源哈希的 Context Receipt 进入交付链。
38
+
39
+ ## 公共 API
40
+
41
+ 主要入口包括 `ProjectRuntimeFactory`、`DeliveryLineFacade`、`ContextBinder`、`PlanCompiler`、`ExecutionCoordinator`、`ReviewCoordinator` 与宿主 conformance 契约。
42
+
43
+ ## 相关链接
44
+
45
+ - [DevFlow 仓库](https://github.com/shilongfeicool/dev-flow)
46
+ - [问题反馈](https://github.com/shilongfeicool/dev-flow/issues)
47
+
48
+ ## License
49
+
50
+ MIT
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=artifact-generation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-generation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/artifact-generation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { validateArtifactGeneration } from '../artifacts/generation-guard.js';
3
+ import { assertContextArtifactBinding } from '../artifacts/context-manifest.js';
4
+ const context = { id: 'ctx', caseId: 'case', receipt: 'receipt', refs: [{ path: 'src/a.ts', hash: 'hash', classification: 'internal', untrusted: true }], artifactRefs: [{ id: 'artifact-1', ref: 'refs/devflow/delivery-artifacts/case', commit: 'commit-1', path: 'spec.md', blobHash: 'blob-1', contentHash: 'parent' }], omitted: [], compressed: false };
5
+ const base = { type: 'spec', parentHash: 'parent', context, generator: { id: 'agent', kind: 'agent', role: 'designer' }, content: '# spec' };
6
+ describe('artifact generation guard', () => {
7
+ it('accepts a bounded artifact and rejects secret-like content', () => {
8
+ expect(() => validateArtifactGeneration(base)).not.toThrow();
9
+ expect(() => validateArtifactGeneration({ ...base, content: 'api_key: leaked' })).toThrow('secret-like');
10
+ expect(() => assertContextArtifactBinding(context, context.artifactRefs[0])).not.toThrow();
11
+ expect(() => assertContextArtifactBinding(context, { ...context.artifactRefs[0], contentHash: 'other' })).toThrow('not bound');
12
+ expect(() => validateArtifactGeneration({ ...base, context: { ...context, compressed: true, compactionMarker: 'compact-1' } })).toThrow('source hashes');
13
+ expect(() => validateArtifactGeneration({ ...base, context: { ...context, compressed: true, compactionMarker: 'compact-1', retainedSourceHashes: ['hash'] } })).not.toThrow();
14
+ });
15
+ });
16
+ //# sourceMappingURL=artifact-generation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-generation.test.js","sourceRoot":"","sources":["../../src/__tests__/artifact-generation.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAEhF,MAAM,OAAO,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,UAAmB,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,sCAAsC,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACvW,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,MAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAgB,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAE/J,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,CAAC,GAAG,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC7D,MAAM,CAAC,GAAG,EAAE,CAAC,0BAA0B,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACzG,MAAM,CAAC,GAAG,EAAE,CAAC,4BAA4B,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC3F,MAAM,CAAC,GAAG,EAAE,CAAC,4BAA4B,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC/H,MAAM,CAAC,GAAG,EAAE,CAAC,0BAA0B,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACzJ,MAAM,CAAC,GAAG,EAAE,CAAC,0BAA0B,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAChL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=backend-scenario.e2e.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-scenario.e2e.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/backend-scenario.e2e.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { DeliveryLineError } from '../domain/types.js';
3
+ import { assertIntegrationTarget } from '../adapters/integration.js';
4
+ import { assertReviewPasses } from '../adapters/review.js';
5
+ import { assertNonBypassableGates } from '../adapters/approval.js';
6
+ describe('backend developer journey', () => {
7
+ it('rejects target ref writes and requires all security gates', () => {
8
+ const bugInput = 'Workflow Run 详情接口必须绑定请求中的 project scope;跨项目的 runId 返回 403,且不能改变任何状态。先补充能稳定复现问题的测试,再做最小修复。';
9
+ expect(bugInput).toContain('403');
10
+ expect(() => assertIntegrationTarget({ integrationRef: 'refs/devflow/delivery/case', targetRef: 'main', candidateRevision: 'candidate' })).not.toThrow();
11
+ expect(() => assertIntegrationTarget({ integrationRef: 'main', targetRef: 'main', candidateRevision: 'candidate' })).toThrow(DeliveryLineError);
12
+ const passed = ['bugs', 'security', 'compliance'].map(kind => ({ id: kind, kind, artifactHash: 'h', findings: [], passed: true, createdAt: 1 }));
13
+ expect(() => assertReviewPasses(passed, 'h')).not.toThrow();
14
+ expect(() => assertReviewPasses(passed.map(receipt => receipt.kind === 'security' ? { ...receipt, passed: false } : receipt), 'h')).toThrow('security');
15
+ const state = { role: 'user', balance: 100 };
16
+ const before = structuredClone(state);
17
+ const request = { role: 'user', resource: 'admin/balance' };
18
+ expect(request.resource.startsWith('admin/')).toBe(true);
19
+ expect(() => { if (request.resource.startsWith('admin/'))
20
+ throw new DeliveryLineError('MISSING_PREREQUISITE', '403'); }).toThrow('403');
21
+ expect(state).toEqual(before);
22
+ expect(() => assertNonBypassableGates({ auth: true, dataIntegrity: true, redTest: false })).toThrow('safety');
23
+ });
24
+ });
25
+ //# sourceMappingURL=backend-scenario.e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-scenario.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/backend-scenario.e2e.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,QAAQ,GAAG,2FAA2F,CAAC;QAC7G,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,EAAE,CAAC,uBAAuB,CAAC,EAAE,cAAc,EAAE,4BAA4B,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACzJ,MAAM,CAAC,GAAG,EAAE,CAAC,uBAAuB,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAChJ,MAAM,MAAM,GAAI,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,CAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5J,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC5D,MAAM,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACxJ,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;QAC5D,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,MAAM,IAAI,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxI,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=claude-events.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-events.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/claude-events.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { consumeClaudeSession, createClaudeSessionState, mapClaudeEvent, replayClaudeHistory, shouldBreak } from '../subagents/claude-events.js';
3
+ describe('Claude event contract', () => {
4
+ it('deduplicates replayed events while preserving terminal idle semantics', () => {
5
+ const state = createClaudeSessionState();
6
+ expect(mapClaudeEvent({ id: 'm1', type: 'agent.message', text: 'ok' }, state)).toMatchObject({ type: 'message' });
7
+ expect(mapClaudeEvent({ id: 'm1', type: 'agent.message', text: 'ok' }, state)).toBeUndefined();
8
+ const waiting = mapClaudeEvent({ id: 'i1', type: 'session.status_idle', stop_reason: { type: 'requires_action' } }, state);
9
+ expect(shouldBreak(waiting)).toBe(false);
10
+ const done = mapClaudeEvent({ id: 'i2', type: 'session.status_idle', stop_reason: { type: 'end_turn' } }, state);
11
+ expect(shouldBreak(done)).toBe(true);
12
+ const history = replayClaudeHistory([{ id: 'u1', type: 'user.message' }, { id: 'u1', type: 'user.message' }, { id: 'c1', type: 'compaction', marker: 'compact-1' }]);
13
+ expect(history.map(event => event.type)).toEqual(['user_event_queued', 'compaction']);
14
+ expect(mapClaudeEvent({ id: 'tool-1', type: 'agent.custom_tool_use', name: 'secret-tool', input: { apiKey: 'secret' } }, state)).toMatchObject({ type: 'custom_tool_required', input: { apiKey: '[REDACTED]' } });
15
+ });
16
+ it('opens the stream before kickoff and replays history with processed markers', async () => {
17
+ const order = [];
18
+ const stream = async function* () { yield { id: 'stream-1', type: 'agent.message', text: 'live' }; };
19
+ const events = await consumeClaudeSession({
20
+ openStream: async () => { order.push('open'); return stream(); },
21
+ kickoff: async () => { order.push('kickoff'); },
22
+ history: async () => [{ id: 'history-1', type: 'user.message', processed_at: '2026-08-28T00:00:00Z' }, { id: 'stream-1', type: 'agent.message', text: 'replayed' }],
23
+ });
24
+ expect(order).toEqual(['open', 'kickoff']);
25
+ expect(events.map(event => event.type)).toEqual(['user_event_processed', 'message']);
26
+ });
27
+ });
28
+ //# sourceMappingURL=claude-events.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-events.test.js","sourceRoot":"","sources":["../../src/__tests__/claude-events.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,cAAc,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjJ,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,uEAAuE,EAAE,GAAG,EAAE;QAC/E,MAAM,KAAK,GAAG,wBAAwB,EAAE,CAAC;QACzC,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAClH,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC/F,MAAM,OAAO,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,qBAAqB,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,KAAK,CAAE,CAAC;QAC5H,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,qBAAqB,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,CAAE,CAAC;QAClH,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QACrK,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC,CAAC;QACtF,MAAM,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;IACpN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,KAAK,SAAS,CAAC,MAAM,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;QACrG,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC;YACxC,UAAU,EAAE,KAAK,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAAC,CAAC,CAAC;YAChE,OAAO,EAAE,KAAK,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC/C,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,sBAAsB,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;SACpK,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,sBAAsB,EAAE,SAAS,CAAC,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=facade-e2e.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facade-e2e.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/facade-e2e.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,167 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { DeliveryLineFacade } from '../facade/delivery-line-facade.js';
3
+ import { MemoryCaseStore } from '../persistence/memory-store.js';
4
+ const identity = (key) => ({ actor: { id: 'owner', kind: 'human', role: 'owner' }, sessionId: 'session-1', executionId: 'execution-1', idempotencyKey: key, contextReceipt: 'ctx-1', turn: 1 });
5
+ describe('delivery line facade', () => {
6
+ it('drives a gated case from clarification to a delivered package', async () => {
7
+ const store = new MemoryCaseStore();
8
+ const calls = [];
9
+ const verificationInputs = [];
10
+ const facade = new DeliveryLineFacade({
11
+ store,
12
+ execution: { startTask: async (raw) => { const input = raw; calls.push(`execute:${input.taskId}`); return { taskId: input.taskId, status: 'started' }; }, cancelTask: async () => { } },
13
+ verification: { verify: async (raw) => { verificationInputs.push(raw); const input = raw; return { id: `verification:${input.taskId ?? 'plan'}`, taskId: input.taskId, commit: 'candidate', lockfileHash: 'lock', runtime: 'node', toolVersion: 'vitest', environment: 'test', commands: [], passed: true, createdAt: Date.now() }; } },
14
+ integration: { integrate: async (raw) => { calls.push(`integrate:${raw.taskId}`); return { candidateRevision: 'candidate-integrated' }; } },
15
+ review: { review: async (raw) => { const input = raw; return { id: `review:${input.kind}`, kind: input.kind, artifactHash: 'review', findings: [], passed: true, createdAt: Date.now() }; } },
16
+ package: { prepare: async () => ({ packageHash: 'package-hash', path: '/tmp/delivery.json' }) }, approval: { approve: async (input) => input, reject: async (input) => input },
17
+ });
18
+ let status = await facade.createCase({ ...identity('create'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'Add feature' });
19
+ expect(status.stage).toBe('clarifying');
20
+ status = await facade.answer(status.caseId, { ...identity('answer'), turn: 1, value: 'Feature with tests' });
21
+ status = await facade.approve(status.caseId, { ...identity('approve-intent'), stage: 'intent' });
22
+ expect(status.stage).toBe('designing');
23
+ status = await facade.compareOptions(status.caseId, { ...identity('compare'), option: 'bounded design' });
24
+ status = await facade.approve(status.caseId, { ...identity('approve-spec'), stage: 'spec' });
25
+ status = await facade.approve(status.caseId, { ...identity('approve-plan'), stage: 'plan' });
26
+ status = await facade.resume(status.caseId, identity('resume'));
27
+ expect(status.stage).toBe('reviewed');
28
+ status = await facade.approve(status.caseId, { ...identity('approve-release'), stage: 'release' });
29
+ status = await facade.export(status.caseId, { ...identity('export'), path: '/tmp/delivery.json' });
30
+ expect(status.stage).toBe('delivered');
31
+ const delivered = await store.get(status.caseId);
32
+ expect(delivered.evidence.some(item => item.hash === 'package-hash')).toBe(true);
33
+ expect(delivered.artifacts.at(-1)).toMatchObject({ type: 'delivery-package', contentHash: expect.any(String) });
34
+ expect(calls).toEqual([`execute:${status.caseId}:task-1`, `integrate:${status.caseId}:task-1`]);
35
+ expect(status.artifactRefs.map(artifact => artifact.type)).toEqual(['intent', 'spec', 'plan', 'delivery-package']);
36
+ expect(status.evidenceRefs.length).toBeGreaterThan(0);
37
+ expect((await store.get(status.caseId)).interaction.summaries?.[0]).toMatchObject({ question: expect.any(String), answer: 'Feature with tests', contextReceipt: 'ctx-1' });
38
+ expect(status.taskSummaries[0]).toMatchObject({ status: 'integrated', attempt: 1 });
39
+ expect(verificationInputs.at(-1)).toMatchObject({ planLevel: true, integrationRef: status.caseId.replace(status.caseId, `refs/devflow/delivery/${status.caseId}`) });
40
+ });
41
+ it('does not replay a running task after recovery and rejects stale approval hashes', async () => {
42
+ const store = new MemoryCaseStore();
43
+ const facade = new DeliveryLineFacade({ store });
44
+ let status = await facade.createCase({ ...identity('create-recovery'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'Recovery task' });
45
+ status = await facade.answer(status.caseId, { ...identity('answer-recovery'), turn: 1, value: 'criteria' });
46
+ await expect(facade.approve(status.caseId, { ...identity('approve-old-turn'), turn: 0, stage: 'intent' })).rejects.toMatchObject({ code: 'STALE_INTERACTION_TURN' });
47
+ await expect(facade.approve(status.caseId, { ...identity('approve-stale'), stage: 'intent', artifactHash: 'stale' })).rejects.toMatchObject({ code: 'ARTIFACT_HASH_MISMATCH' });
48
+ status = await facade.approve(status.caseId, { ...identity('approve-recovery-intent'), stage: 'intent' });
49
+ status = await facade.compareOptions(status.caseId, { ...identity('compare-recovery'), option: 'design' });
50
+ status = await facade.approve(status.caseId, { ...identity('approve-recovery-spec'), stage: 'spec' });
51
+ status = await facade.approve(status.caseId, { ...identity('approve-recovery-plan'), stage: 'plan' });
52
+ const record = await store.get(status.caseId);
53
+ record.tasks[0].status = 'running';
54
+ await store.save(record, record.version);
55
+ const resumed = await facade.resume(status.caseId, identity('resume-recovery'));
56
+ expect(resumed.stage).toBe('held');
57
+ expect(resumed.taskSummaries[0].attempt).toBe(0);
58
+ });
59
+ it('rejects create idempotency reuse with a different request payload', async () => {
60
+ const store = new MemoryCaseStore();
61
+ const facade = new DeliveryLineFacade({ store });
62
+ const first = await facade.createCase({ ...identity('same-create'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'first' });
63
+ await expect(facade.createCase({ ...identity('same-create'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'different' })).rejects.toMatchObject({ code: 'IDEMPOTENCY_CONFLICT' });
64
+ await expect(facade.createCase({ ...identity('same-create'), caseId: first.caseId, projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'first' })).resolves.toMatchObject({ caseId: first.caseId });
65
+ });
66
+ it('routes integration conflicts to a resumable blocked case', async () => {
67
+ const store = new MemoryCaseStore();
68
+ const facade = new DeliveryLineFacade({
69
+ store,
70
+ execution: { startTask: async (input) => ({ taskId: input.taskId, status: 'started' }), cancelTask: async () => { } },
71
+ verification: { verify: async (input) => ({ id: 'v', taskId: input.taskId, commit: 'candidate', lockfileHash: 'lock', runtime: 'node', toolVersion: 'test', environment: 'test', commands: [], passed: true, createdAt: 1 }) },
72
+ integration: { integrate: async () => ({ candidateRevision: '' }) },
73
+ });
74
+ let status = await facade.createCase({ ...identity('create-conflict'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'Conflict' });
75
+ status = await facade.answer(status.caseId, { ...identity('answer-conflict'), turn: 1, value: 'criteria' });
76
+ status = await facade.approve(status.caseId, { ...identity('approve-conflict-intent'), stage: 'intent' });
77
+ status = await facade.compareOptions(status.caseId, { ...identity('compare-conflict'), option: 'design' });
78
+ status = await facade.approve(status.caseId, { ...identity('approve-conflict-spec'), stage: 'spec' });
79
+ status = await facade.approve(status.caseId, { ...identity('approve-conflict-plan'), stage: 'plan' });
80
+ status = await facade.resume(status.caseId, identity('resume-conflict'));
81
+ expect(status.stage).toBe('blocked');
82
+ expect(status.blockers[0]).toMatchObject({ code: 'BLOCKED', taskId: `${status.caseId}:task-1` });
83
+ expect(status.nextActions).toContain('resume');
84
+ });
85
+ it('holds a case when interaction or wall-time budgets are exhausted', async () => {
86
+ const store = new MemoryCaseStore();
87
+ const facade = new DeliveryLineFacade({ store });
88
+ let status = await facade.createCase({ ...identity('create-budget'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'Budget', budgets: { maxInteractionTurns: 1 } });
89
+ status = await facade.answer(status.caseId, { ...identity('answer-budget'), turn: 1, value: 'criteria' });
90
+ expect(status.stage).toBe('held');
91
+ expect(status.blockers[0]?.code).toBe('HELD');
92
+ });
93
+ it('cancels running tasks and protects terminal cases from later writes', async () => {
94
+ const store = new MemoryCaseStore();
95
+ const cancelled = [];
96
+ const facade = new DeliveryLineFacade({ store, execution: { startTask: async (input) => ({ taskId: input.taskId, status: 'started' }), cancelTask: async (input) => { cancelled.push(input.taskId); } } });
97
+ let status = await facade.createCase({ ...identity('create-cancel'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'Cancel' });
98
+ const record = await store.get(status.caseId);
99
+ record.tasks = [{ id: `${status.caseId}:task`, caseId: status.caseId, title: 'task', attempt: 1, version: 0, baseRevision: 'main', dependsOn: [], allowedFiles: [], expectedChanges: [], verificationCommands: [], status: 'running', evidence: [] }];
100
+ record.stage = 'executing';
101
+ await store.save(record, record.version);
102
+ status = await facade.cancel(status.caseId, { ...identity('cancel'), reason: 'stop' });
103
+ expect(status.stage).toBe('cancelled');
104
+ expect(cancelled).toEqual([`${status.caseId}:task`]);
105
+ expect(status.taskSummaries[0].status).toBe('cancelled');
106
+ await expect(facade.answer(status.caseId, { ...identity('late-answer'), turn: 1, value: 'late' })).rejects.toMatchObject({ code: 'CASE_CANCELLED' });
107
+ await expect(facade.cancel(status.caseId, { ...identity('late-cancel'), reason: 'again' })).rejects.toMatchObject({ code: 'CASE_CANCELLED' });
108
+ });
109
+ it('binds every write to the case context receipt and makes retry resumable', async () => {
110
+ const store = new MemoryCaseStore();
111
+ const facade = new DeliveryLineFacade({ store });
112
+ const created = await facade.createCase({ ...identity('create-context'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'Context bound' });
113
+ await expect(facade.answer(created.caseId, { ...identity('wrong-context'), contextReceipt: 'other', turn: 1, value: 'nope' })).rejects.toMatchObject({ code: 'MISSING_PREREQUISITE' });
114
+ await expect(facade.answer(created.caseId, { ...identity('wrong-execution'), executionId: 'other-execution', turn: 1, value: 'nope' })).rejects.toMatchObject({ code: 'MISSING_PREREQUISITE' });
115
+ await expect(facade.answer(created.caseId, { ...identity('wrong-actor'), actor: { id: 'other', kind: 'human' }, turn: 1, value: 'nope' })).rejects.toMatchObject({ code: 'UNAUTHORIZED_ROLE' });
116
+ const record = await store.get(created.caseId);
117
+ record.stage = 'failed';
118
+ record.tasks = [{ id: `${created.caseId}:task`, caseId: created.caseId, title: 'retry', attempt: 1, version: 0, baseRevision: 'main', dependsOn: [], allowedFiles: [], expectedChanges: [], verificationCommands: [], status: 'failed', evidence: [] }];
119
+ await store.save(record, record.version);
120
+ const retried = await facade.retryTask(created.caseId, { ...identity('retry-context'), taskId: `${created.caseId}:task` });
121
+ expect(retried.stage).toBe('executing');
122
+ expect(retried.taskSummaries[0].status).toBe('pending');
123
+ });
124
+ it('promotes security-sensitive cases to high risk and records approval receipts', async () => {
125
+ const store = new MemoryCaseStore();
126
+ const facade = new DeliveryLineFacade({ store, approval: { approve: async (input) => input, reject: async (input) => input } });
127
+ const status = await facade.createCase({ ...identity('create-risk'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'scope guard', riskSignals: ['authorization scope'] });
128
+ expect((await store.get(status.caseId)).riskTier).toBe('high');
129
+ await facade.answer(status.caseId, { ...identity('risk-answer'), turn: 1, value: 'criteria' });
130
+ const approved = await facade.approve(status.caseId, { ...identity('risk-intent'), stage: 'intent' });
131
+ expect(approved.evidenceRefs.some(item => item.kind === 'approval')).toBe(true);
132
+ expect((await store.get(status.caseId)).evidence.some(item => item.kind === 'approval')).toBe(true);
133
+ });
134
+ it('routes execution adapter failures to a failed task without losing the case state', async () => {
135
+ const store = new MemoryCaseStore();
136
+ const facade = new DeliveryLineFacade({ store, execution: { startTask: async () => { throw new Error('worker unavailable'); }, cancelTask: async () => { } }, verification: { verify: async () => { throw new Error('must not run'); } }, integration: { integrate: async () => ({ candidateRevision: 'never' }) } });
137
+ let view = await facade.createCase({ ...identity('create-exec-failure'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'worker failure' });
138
+ view = await facade.answer(view.caseId, { ...identity('answer-exec-failure'), turn: 1, value: 'criteria' });
139
+ view = await facade.approve(view.caseId, { ...identity('intent-exec-failure'), stage: 'intent' });
140
+ view = await facade.compareOptions(view.caseId, { ...identity('compare-exec-failure'), option: 'design' });
141
+ view = await facade.approve(view.caseId, { ...identity('spec-exec-failure'), stage: 'spec' });
142
+ view = await facade.approve(view.caseId, { ...identity('plan-exec-failure'), stage: 'plan' });
143
+ view = await facade.resume(view.caseId, identity('resume-exec-failure'));
144
+ expect(view.stage).toBe('failed');
145
+ expect(view.taskSummaries[0].status).toBe('failed');
146
+ expect(view.nextActions).toContain('retry_task');
147
+ });
148
+ it('keeps high-risk gates open until each required approval role is present', async () => {
149
+ const store = new MemoryCaseStore();
150
+ const roles = { intent: ['product_owner'], spec: ['product_owner', 'tech_lead', 'security_owner'], plan: ['tech_lead', 'security_owner'], release: ['code_owner', 'security_owner'] };
151
+ const approval = { requiredRoles: ({ stage }) => roles[stage] ?? [], approve: async (input) => input, reject: async (input) => input };
152
+ const facade = new DeliveryLineFacade({ store, approval });
153
+ const owner = (role, key) => ({ ...identity(key), actor: { id: role, kind: 'human', role } });
154
+ let view = await facade.createCase({ ...owner('product_owner', 'create-high'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: 'high risk', riskTier: 'high' });
155
+ view = await facade.answer(view.caseId, { ...owner('product_owner', 'answer-high'), turn: 1, value: 'criteria' });
156
+ view = await facade.approve(view.caseId, { ...owner('product_owner', 'intent-high'), stage: 'intent' });
157
+ view = await facade.compareOptions(view.caseId, { ...owner('product_owner', 'compare-high'), option: 'safe' });
158
+ view = await facade.approve(view.caseId, { ...owner('product_owner', 'spec-product'), stage: 'spec' });
159
+ expect(view.stage).toBe('spec_ready');
160
+ expect(view.nextActions).toContain('approve');
161
+ view = await facade.approve(view.caseId, { ...owner('tech_lead', 'spec-tech'), stage: 'spec' });
162
+ expect(view.stage).toBe('spec_ready');
163
+ view = await facade.approve(view.caseId, { ...owner('security_owner', 'spec-security'), stage: 'spec' });
164
+ expect(view.stage).toBe('plan_ready');
165
+ });
166
+ });
167
+ //# sourceMappingURL=facade-e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facade-e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/facade-e2e.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEjE,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAgB,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAEjN,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,kBAAkB,GAAc,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC;YACpC,KAAK;YACL,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,GAAY,EAAE,EAAE,GAAG,MAAM,KAAK,GAAG,GAAyB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE;YACrN,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAY,EAAE,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,GAA0B,CAAC,CAAC,OAAO,EAAE,EAAE,EAAE,gBAAgB,KAAK,CAAC,MAAM,IAAI,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;YACvW,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,GAA6G,EAAE,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,CAAC,CAAC,CAAC,EAAE;YACrP,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAY,EAAE,EAAE,GAAG,MAAM,KAAK,GAAG,GAAmD,CAAC,CAAC,OAAO,EAAE,EAAE,EAAE,UAAU,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;YACtP,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,CAAC,KAAc,EAAE,MAAM,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,CAAC,KAAc,EAAE;SAC7L,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;QAChJ,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACxC,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAC7G,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACjG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC1G,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7F,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7F,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACnG,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC,CAAC;QACnG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjF,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChH,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,MAAM,CAAC,MAAM,SAAS,EAAE,aAAa,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC;QAChG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;QACnH,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,oBAAoB,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3K,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QACpF,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAyB,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACvK,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QAC/F,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACjD,IAAI,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC3J,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QAC5G,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,CAAC,CAAC;QACrK,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAChL,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,yBAAyB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC1G,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3G,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,uBAAuB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACtG,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,uBAAuB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACtG,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC;QAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5H,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAChF,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAChJ,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACtM,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACnN,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC;YACpC,KAAK;YACL,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE;YAClH,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAG,KAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE;YACpP,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,iBAAiB,EAAE,EAAE,EAAE,CAAC,EAAE;SACpE,CAAC,CAAC;QACH,IAAI,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QACtJ,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QAC5G,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,yBAAyB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC1G,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3G,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,uBAAuB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACtG,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,uBAAuB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACtG,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACzE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC;QACjG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACjD,IAAI,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,mBAAmB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACvL,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1G,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QAAC,MAAM,SAAS,GAAa,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvM,IAAI,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClJ,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QAAC,MAAM,CAAC,KAAK,GAAG,WAAW,CAAC;QAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3W,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACvF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAAC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC;QAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACvJ,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;QACrJ,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAChJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,gBAAgB,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QAC7J,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACvL,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,WAAW,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC,CAAC;QAChM,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAChM,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC;QAAC,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QACjR,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC;QAC3H,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC5F,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,CAAC,KAAc,EAAE,MAAM,EAAE,KAAK,EAAC,KAAK,EAAC,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,CAAC;QAC9I,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;QAC7L,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/D,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QAC/F,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtG,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChF,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;QAChG,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACrT,IAAI,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,CAAC,qBAAqB,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC9J,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QAC5G,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClG,IAAI,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3G,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,mBAAmB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9F,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,QAAQ,CAAC,mBAAmB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9F,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACzE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAC3I,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,MAAM,KAAK,GAA6B,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,eAAe,EAAE,WAAW,EAAE,gBAAgB,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC,YAAY,EAAE,gBAAgB,CAAC,EAAE,CAAC;QAChN,MAAM,QAAQ,GAAG,EAAE,aAAa,EAAE,CAAC,EAAE,KAAK,EAA0D,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAc,EAAE,EAAE,CAAC,KAAc,EAAE,MAAM,EAAE,KAAK,EAAE,KAAc,EAAE,EAAE,CAAC,KAAc,EAAE,CAAC;QACnO,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,GAAW,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAgB,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QACvH,IAAI,IAAI,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,EAAE,GAAG,KAAK,CAAC,eAAe,EAAE,aAAa,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACjL,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,eAAe,EAAE,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QAClH,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,eAAe,EAAE,aAAa,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxG,IAAI,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/G,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACvG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACrF,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAChG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACtC,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,gBAAgB,EAAE,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACzG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=frontend-scenario.e2e.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontend-scenario.e2e.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/frontend-scenario.e2e.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { DeliveryLineFacade } from '../facade/delivery-line-facade.js';
3
+ import { MemoryCaseStore } from '../persistence/memory-store.js';
4
+ import { validateTaskDag } from '../domain/task-dag.js';
5
+ const id = (key) => ({ actor: { id: 'frontend-owner', kind: 'human' }, sessionId: 'frontend-session', executionId: 'frontend-execution', idempotencyKey: key, contextReceipt: 'frontend-ctx', turn: 1 });
6
+ describe('frontend developer journey', () => {
7
+ it('keeps scope and verification evidence visible through delivery', async () => {
8
+ const store = new MemoryCaseStore();
9
+ const facade = new DeliveryLineFacade({ store, execution: { startTask: async (input) => ({ taskId: input.taskId, status: 'started' }), cancelTask: async () => { } }, verification: { verify: async (input) => ({ id: 'v', taskId: input.taskId, commit: 'candidate', lockfileHash: 'lock', runtime: 'node', toolVersion: 'vitest', environment: 'dashboard', commands: [], passed: true, createdAt: Date.now() }) }, integration: { integrate: async (input) => ({ candidateRevision: input.candidateRevision }) }, review: { review: async (input) => ({ id: String(input.kind), kind: input.kind, artifactHash: 'review', findings: [], passed: true, createdAt: Date.now() }) }, package: { prepare: async () => ({ packageHash: 'hash', path: '/tmp/frontend-delivery.json' }) } });
10
+ const request = '在 apps/dashboard 的 Runs 页面增加按项目和运行状态筛选;筛选条件写入 URL,保留现有 API 客户端和页面的 loading/empty/error 体验;补充测试,不修改 Server。';
11
+ let view = await facade.createCase({ ...id('create'), projectRoot: '/repo', baseRef: 'main', targetRef: 'main', title: request });
12
+ expect(view.pendingDecisions[0]?.question).toContain('outcome');
13
+ view = await facade.answer(view.caseId, { ...id('answer'), turn: 1, value: 'Project list comes from the existing API; refresh and share preserve query.' });
14
+ view = await facade.approve(view.caseId, { ...id('intent'), stage: 'intent' });
15
+ view = await facade.compareOptions(view.caseId, { ...id('compare'), option: 'URL query state' });
16
+ view = await facade.approve(view.caseId, { ...id('spec'), stage: 'spec' });
17
+ view = await facade.approve(view.caseId, { ...id('plan'), stage: 'plan' });
18
+ view = await facade.resume(view.caseId, id('resume'));
19
+ expect(view.stage).toBe('reviewed');
20
+ expect(view.taskSummaries[0]).toMatchObject({ status: 'integrated', attempt: 1 });
21
+ expect(view.nextActions).toContain('approve');
22
+ const tasks = (await store.get(view.caseId)).tasks;
23
+ expect(tasks.every(task => !task.allowedFiles.some(file => file.startsWith('apps/server/')))).toBe(true);
24
+ const browserEvidence = { kind: 'verification', hash: 'browser-unavailable', id: 'browser-1', createdAt: Date.now(), metadata: { channel: 'browser', status: 'unavailable' } };
25
+ const record = await store.get(view.caseId);
26
+ record.evidence.push(browserEvidence);
27
+ await store.save(record, record.version);
28
+ expect((await store.get(view.caseId)).evidence.find(item => item.id === 'browser-1')?.metadata).toMatchObject({ status: 'unavailable' });
29
+ const manifestRecord = await store.get(view.caseId);
30
+ expect(manifestRecord.artifacts.map(item => item.type)).toEqual(['intent', 'spec', 'plan']);
31
+ expect(manifestRecord.tasks[0].allowedFiles.every(file => !file.startsWith('apps/server/'))).toBe(true);
32
+ expect(() => validateTaskDag([{ ...tasks[0], id: 'f1-task', allowedFiles: ['apps/dashboard/src/**'], status: 'pending' }])).not.toThrow();
33
+ });
34
+ });
35
+ //# sourceMappingURL=frontend-scenario.e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontend-scenario.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/frontend-scenario.e2e.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=git-artifact-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-artifact-store.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/git-artifact-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { execFileSync } from 'node:child_process';
3
+ import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { GitArtifactStore } from '../artifacts/git-artifact-store.js';
7
+ function git(root, args) { return execFileSync('git', ['-C', root, ...args], { encoding: 'utf8' }).trim(); }
8
+ describe('Git artifact store', () => {
9
+ it('writes immutable artifacts under a delivery-only ref without changing HEAD', async () => {
10
+ const root = mkdtempSync(join(tmpdir(), 'delivery-artifact-'));
11
+ git(root, ['init', '-q']);
12
+ git(root, ['config', 'user.email', 'test@example.com']);
13
+ git(root, ['config', 'user.name', 'Delivery Test']);
14
+ writeFileSync(join(root, 'README.md'), 'base\n');
15
+ git(root, ['add', 'README.md']);
16
+ git(root, ['commit', '-qm', 'base']);
17
+ const head = git(root, ['rev-parse', 'HEAD']);
18
+ const store = new GitArtifactStore();
19
+ const artifact = await store.create({ caseId: 'case-1', repoId: 'repo-1', repositoryPath: root, type: 'intent', path: 'intent.md', content: '# Intent\n', parentBlobHashes: [], createdBy: { id: 'u', kind: 'human' } });
20
+ expect(git(root, ['rev-parse', 'HEAD'])).toBe(head);
21
+ expect(git(root, ['rev-parse', artifact.ref])).toBe(artifact.commit);
22
+ expect(git(root, ['show', `${artifact.commit}:${artifact.path}`])).toBe('# Intent');
23
+ expect(() => readFileSync(join(root, 'intent.md'))).toThrow();
24
+ await expect(store.create({ caseId: 'case-1', repoId: 'repo-1', repositoryPath: root, type: 'spec', path: '../escape.md', content: 'bad', parentBlobHashes: [artifact.blobHash], createdBy: { id: 'agent', kind: 'agent', role: 'designer' } })).rejects.toThrow('escapes');
25
+ });
26
+ it('chains parent hashes, rejects dirty or mutable writes, and keeps code worktrees isolated', async () => {
27
+ const root = mkdtempSync(join(tmpdir(), 'delivery-artifact-chain-'));
28
+ git(root, ['init', '-q']);
29
+ git(root, ['config', 'user.email', 'test@example.com']);
30
+ git(root, ['config', 'user.name', 'Delivery Test']);
31
+ writeFileSync(join(root, 'README.md'), 'base\n');
32
+ git(root, ['add', 'README.md']);
33
+ git(root, ['commit', '-qm', 'base']);
34
+ const store = new GitArtifactStore();
35
+ const first = await store.create({ caseId: 'case-2', repoId: 'repo-2', repositoryPath: root, type: 'intent', path: 'intent.md', content: 'one', parentBlobHashes: [], createdBy: { id: 'u', kind: 'human' } });
36
+ const second = await store.create({ caseId: 'case-2', repoId: 'repo-2', repositoryPath: root, type: 'spec', path: 'spec.md', content: 'two', parentBlobHashes: [first.blobHash], createdBy: { id: 'u', kind: 'human' } });
37
+ expect(second.commit).not.toBe(first.commit);
38
+ expect(git(root, ['show', `${second.commit}:intent.md`])).toBe('one');
39
+ await expect(store.create({ caseId: 'case-2', repoId: 'repo-2', repositoryPath: root, type: 'plan', path: 'plan.md', content: 'three', parentBlobHashes: [], createdBy: { id: 'u', kind: 'human' } })).rejects.toThrow('parent blob');
40
+ writeFileSync(join(root, 'dirty.txt'), 'uncommitted');
41
+ await expect(store.create({ caseId: 'case-2', repoId: 'repo-2', repositoryPath: root, type: 'plan', path: 'plan.md', content: 'three', parentBlobHashes: [first.blobHash, second.blobHash], createdBy: { id: 'u', kind: 'human' } })).rejects.toThrow('clean');
42
+ });
43
+ });
44
+ //# sourceMappingURL=git-artifact-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-artifact-store.test.js","sourceRoot":"","sources":["../../src/__tests__/git-artifact-store.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=governance-adapters.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance-adapters.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/governance-adapters.test.ts"],"names":[],"mappings":""}