@fitlab-ai/agent-infra 0.12.0 → 0.12.2

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 (331) hide show
  1. package/README.md +0 -2
  2. package/README.zh-CN.md +0 -2
  3. package/dist/bin/internal-cli.js +2 -17
  4. package/dist/lib/agent-clients/adapter.js +0 -13
  5. package/dist/lib/agent-clients/adapters/antigravity-cli.js +0 -5
  6. package/dist/lib/agent-clients/adapters/claude-code-credentials.js +0 -17
  7. package/dist/lib/agent-clients/adapters/claude-code.js +0 -9
  8. package/dist/lib/agent-clients/adapters/codex.js +0 -52
  9. package/dist/lib/agent-clients/adapters/opencode.js +0 -5
  10. package/dist/lib/agent-clients/adapters/traecli.js +0 -5
  11. package/dist/lib/agent-clients/config.js +19 -54
  12. package/dist/lib/agent-clients/registry.js +1 -12
  13. package/dist/lib/agent-clients/schema.js +0 -18
  14. package/dist/lib/agent-clients/tokens.js +1 -2
  15. package/dist/lib/agent-clients/types.js +0 -1
  16. package/dist/lib/decide.js +2 -0
  17. package/dist/lib/git/worktree-identity.js +1 -9
  18. package/dist/lib/internal/agent-client.js +2 -62
  19. package/dist/lib/internal/cli-route-inventory.js +1 -5
  20. package/dist/lib/internal/manual-validation.js +29 -27
  21. package/dist/lib/internal/platform-comment.js +56 -7
  22. package/dist/lib/internal/task-create.js +1 -1
  23. package/dist/lib/internal/task-event.js +1 -8
  24. package/dist/lib/internal/task-finalization.js +0 -1
  25. package/dist/lib/internal/task-lifecycle.js +2 -2
  26. package/dist/lib/internal/task-operation-registry.js +4 -20
  27. package/dist/lib/internal/task-review.js +4 -4
  28. package/dist/lib/platform/comment-safety.js +1 -7
  29. package/dist/lib/platform/in-label-sync.js +1 -14
  30. package/dist/lib/platform/issue-comments.js +373 -282
  31. package/dist/lib/platform/issue-summary-content.js +112 -0
  32. package/dist/lib/platform/issues.js +1 -1
  33. package/dist/lib/platform/operation-coordinator.js +4 -2
  34. package/dist/lib/platform/pr-change-report.js +176 -30
  35. package/dist/lib/platform/pr-checks.js +2 -8
  36. package/dist/lib/platform/pr-summary-content.js +54 -0
  37. package/dist/lib/platform/pr-summary.js +318 -284
  38. package/dist/lib/platform/provider-validation.js +0 -20
  39. package/dist/lib/platform/pull-requests.js +73 -84
  40. package/dist/lib/platform/releases.js +1 -43
  41. package/dist/lib/platform/summary-content-pipeline.js +18 -0
  42. package/dist/lib/platform/verification-required.js +0 -2
  43. package/dist/lib/platform/verification-sync.js +1 -79
  44. package/dist/lib/process-data/normalize.js +1 -185
  45. package/dist/lib/process-data/privacy.js +1 -16
  46. package/dist/lib/process-data/sources.js +2 -279
  47. package/dist/lib/render.js +0 -12
  48. package/dist/lib/run/index.js +15 -10
  49. package/dist/lib/run/skills.js +0 -3
  50. package/dist/lib/sandbox/commands/create.js +40 -53
  51. package/dist/lib/sandbox/commands/list-running.js +0 -18
  52. package/dist/lib/sandbox/commands/start.js +7 -8
  53. package/dist/lib/sandbox/constants.js +0 -6
  54. package/dist/lib/sandbox/control/client.js +0 -1
  55. package/dist/lib/sandbox/control/container-identity.js +1 -16
  56. package/dist/lib/sandbox/control/executor.js +0 -4
  57. package/dist/lib/sandbox/control/identity-sentinel.js +0 -7
  58. package/dist/lib/sandbox/control/lifecycle.js +21 -37
  59. package/dist/lib/sandbox/control/native-file-lock.js +0 -3
  60. package/dist/lib/sandbox/control/server.js +18 -38
  61. package/dist/lib/sandbox/control/state.js +1 -9
  62. package/dist/lib/sandbox/dockerfile.js +0 -6
  63. package/dist/lib/sandbox/engine.js +0 -14
  64. package/dist/lib/sandbox/engines/docker-exact-discovery.js +1 -4
  65. package/dist/lib/sandbox/engines/wsl2-paths.js +0 -3
  66. package/dist/lib/sandbox/recovery.js +24 -26
  67. package/dist/lib/sandbox/removal.js +67 -518
  68. package/dist/lib/sandbox/task-resolver.js +0 -41
  69. package/dist/lib/sandbox/tools.js +1 -4
  70. package/dist/lib/sandbox/workspace-view.js +1 -2
  71. package/dist/lib/server/display.js +0 -6
  72. package/dist/lib/task/activity-intent.js +45 -40
  73. package/dist/lib/task/activity-log.js +9 -16
  74. package/dist/lib/task/artifact-command.js +1 -1
  75. package/dist/lib/task/artifact-lifecycle.js +61 -63
  76. package/dist/lib/task/artifact-name.js +0 -6
  77. package/dist/lib/task/artifact-operations.js +3 -3
  78. package/dist/lib/task/capabilities.js +4 -5
  79. package/dist/lib/task/commands/log.js +0 -6
  80. package/dist/lib/task/commands/status.js +17 -60
  81. package/dist/lib/task/commit-operation.js +28 -39
  82. package/dist/lib/task/completion-facts.js +56 -43
  83. package/dist/lib/task/control-authority.js +23 -256
  84. package/dist/lib/task/control-recovery.js +3 -5
  85. package/dist/lib/task/create.js +2 -4
  86. package/dist/lib/task/decision-intents.js +8 -9
  87. package/dist/lib/task/delivery-target.js +1 -40
  88. package/dist/lib/task/events.js +84 -107
  89. package/dist/lib/task/finalization.js +60 -15
  90. package/dist/lib/task/ledger-intents.js +1 -1
  91. package/dist/lib/task/lifecycle-execution.js +38 -33
  92. package/dist/lib/task/lifecycle.js +49 -41
  93. package/dist/lib/task/local-artifact-finalization.js +1 -4
  94. package/dist/lib/task/manual-validation-evidence.js +1 -37
  95. package/dist/lib/task/platform-operation-recovery.js +151 -108
  96. package/dist/lib/task/pr-delivery-fact.js +2 -5
  97. package/dist/lib/task/qualification-confirmation.js +5 -7
  98. package/dist/lib/task/resolve-ref.js +1 -25
  99. package/dist/lib/task/review-command.js +2 -2
  100. package/dist/lib/task/review-finalization.js +1 -21
  101. package/dist/lib/task/review-fingerprint.js +0 -4
  102. package/dist/lib/task/secure-fs.js +0 -56
  103. package/dist/lib/task/short-id.js +1 -39
  104. package/dist/lib/task/skill-scope.js +0 -1
  105. package/dist/lib/task/verification-engine.js +58 -282
  106. package/dist/lib/task/verification.js +6 -3
  107. package/dist/lib/task/write.js +11 -1
  108. package/lib/agent-clients/adapter.ts +0 -76
  109. package/lib/agent-clients/adapters/antigravity-cli.ts +0 -5
  110. package/lib/agent-clients/adapters/claude-code-credentials.ts +0 -19
  111. package/lib/agent-clients/adapters/claude-code.ts +0 -9
  112. package/lib/agent-clients/adapters/codex.ts +0 -56
  113. package/lib/agent-clients/adapters/opencode.ts +0 -5
  114. package/lib/agent-clients/adapters/traecli.ts +0 -5
  115. package/lib/agent-clients/config.ts +20 -61
  116. package/lib/agent-clients/registry.ts +1 -34
  117. package/lib/agent-clients/schema.ts +0 -18
  118. package/lib/agent-clients/tokens.ts +1 -2
  119. package/lib/agent-clients/types.ts +0 -15
  120. package/lib/decide.ts +1 -0
  121. package/lib/git/worktree-identity.ts +0 -10
  122. package/lib/internal/agent-client.ts +2 -70
  123. package/lib/internal/cli-route-inventory.ts +1 -4
  124. package/lib/internal/manual-validation.ts +28 -27
  125. package/lib/internal/platform-comment.ts +46 -4
  126. package/lib/internal/task-create.ts +0 -1
  127. package/lib/internal/task-event.ts +1 -5
  128. package/lib/internal/task-finalization.ts +0 -1
  129. package/lib/internal/task-lifecycle.ts +3 -5
  130. package/lib/internal/task-operation-registry.ts +3 -19
  131. package/lib/internal/task-review.ts +4 -4
  132. package/lib/platform/comment-safety.ts +0 -10
  133. package/lib/platform/github-provider.ts +0 -2
  134. package/lib/platform/in-label-sync.ts +0 -16
  135. package/lib/platform/issue-comments.ts +478 -301
  136. package/lib/platform/issue-summary-content.ts +132 -0
  137. package/lib/platform/issues.ts +0 -2
  138. package/lib/platform/operation-coordinator.ts +4 -2
  139. package/lib/platform/pr-change-report.ts +165 -25
  140. package/lib/platform/pr-checks.ts +1 -10
  141. package/lib/platform/pr-review.ts +1 -1
  142. package/lib/platform/pr-summary-content.ts +60 -0
  143. package/lib/platform/pr-summary.ts +364 -257
  144. package/lib/platform/provider-bridge.ts +0 -1
  145. package/lib/platform/provider-loader.ts +1 -5
  146. package/lib/platform/provider-validation.ts +1 -49
  147. package/lib/platform/pull-requests.ts +64 -99
  148. package/lib/platform/releases.ts +1 -40
  149. package/lib/platform/summary-content-pipeline.ts +23 -0
  150. package/lib/platform/verification-required.ts +0 -2
  151. package/lib/platform/verification-sync.ts +0 -94
  152. package/lib/process-data/normalize.ts +1 -186
  153. package/lib/process-data/privacy.ts +2 -19
  154. package/lib/process-data/sources.ts +3 -283
  155. package/lib/render.ts +0 -15
  156. package/lib/run/index.ts +13 -7
  157. package/lib/run/skills.ts +0 -4
  158. package/lib/sandbox/commands/create.ts +37 -74
  159. package/lib/sandbox/commands/list-running.ts +0 -19
  160. package/lib/sandbox/commands/start.ts +7 -10
  161. package/lib/sandbox/constants.ts +0 -8
  162. package/lib/sandbox/control/client.ts +0 -1
  163. package/lib/sandbox/control/container-identity.ts +1 -16
  164. package/lib/sandbox/control/executor.ts +1 -5
  165. package/lib/sandbox/control/identity-sentinel.ts +0 -8
  166. package/lib/sandbox/control/lifecycle.ts +18 -51
  167. package/lib/sandbox/control/native-file-lock.ts +0 -8
  168. package/lib/sandbox/control/protocol.ts +0 -2
  169. package/lib/sandbox/control/server.ts +13 -39
  170. package/lib/sandbox/control/state.ts +1 -10
  171. package/lib/sandbox/dockerfile.ts +0 -11
  172. package/lib/sandbox/engine.ts +0 -17
  173. package/lib/sandbox/engines/docker-exact-discovery.ts +1 -5
  174. package/lib/sandbox/engines/wsl2-paths.ts +0 -4
  175. package/lib/sandbox/recovery.ts +24 -26
  176. package/lib/sandbox/removal.ts +58 -687
  177. package/lib/sandbox/shell.ts +1 -1
  178. package/lib/sandbox/task-resolver.ts +0 -48
  179. package/lib/sandbox/tools.ts +1 -5
  180. package/lib/sandbox/workspace-view.ts +2 -4
  181. package/lib/server/display.ts +0 -14
  182. package/lib/server/process-control.ts +1 -1
  183. package/lib/task/activity-intent.ts +36 -44
  184. package/lib/task/activity-log.ts +9 -22
  185. package/lib/task/artifact-command.ts +1 -1
  186. package/lib/task/artifact-lifecycle.ts +58 -67
  187. package/lib/task/artifact-name.ts +0 -7
  188. package/lib/task/artifact-operations.ts +3 -3
  189. package/lib/task/capabilities.ts +5 -6
  190. package/lib/task/commands/log.ts +0 -7
  191. package/lib/task/commands/status.ts +14 -79
  192. package/lib/task/commit-operation.ts +29 -51
  193. package/lib/task/completion-facts.ts +45 -42
  194. package/lib/task/control-authority.ts +27 -317
  195. package/lib/task/control-recovery.ts +2 -5
  196. package/lib/task/create.ts +2 -5
  197. package/lib/task/decision-intents.ts +5 -5
  198. package/lib/task/delivery-target.ts +0 -40
  199. package/lib/task/events.ts +89 -123
  200. package/lib/task/finalization.ts +52 -15
  201. package/lib/task/ledger-intents.ts +1 -1
  202. package/lib/task/lifecycle-execution.ts +37 -89
  203. package/lib/task/lifecycle.ts +48 -44
  204. package/lib/task/local-artifact-finalization.ts +0 -7
  205. package/lib/task/manual-validation-evidence.ts +1 -47
  206. package/lib/task/platform-operation-recovery.ts +117 -104
  207. package/lib/task/pr-delivery-fact.ts +2 -11
  208. package/lib/task/qualification-confirmation.ts +6 -6
  209. package/lib/task/resolve-ref.ts +0 -23
  210. package/lib/task/review-command.ts +2 -2
  211. package/lib/task/review-finalization.ts +1 -27
  212. package/lib/task/review-fingerprint.ts +0 -8
  213. package/lib/task/secure-fs.ts +0 -42
  214. package/lib/task/short-id.ts +0 -43
  215. package/lib/task/skill-scope.ts +0 -1
  216. package/lib/task/verification-engine.ts +56 -287
  217. package/lib/task/verification.ts +5 -5
  218. package/lib/task/write.ts +12 -1
  219. package/package.json +2 -2
  220. package/templates/.agents/README.en.md +1 -3
  221. package/templates/.agents/README.zh-CN.md +0 -2
  222. package/templates/.agents/rules/README.en.md +0 -1
  223. package/templates/.agents/rules/README.zh-CN.md +0 -1
  224. package/templates/.agents/rules/commit-and-pr.en.md +1 -1
  225. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -1
  226. package/templates/.agents/rules/no-mid-flow-questions.en.md +0 -10
  227. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +0 -10
  228. package/templates/.agents/rules/pr-sync.en.md +4 -2
  229. package/templates/.agents/rules/pr-sync.zh-CN.md +6 -9
  230. package/templates/.agents/rules/task-management.en.md +3 -3
  231. package/templates/.agents/rules/task-management.zh-CN.md +3 -3
  232. package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
  233. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
  234. package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
  235. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
  236. package/templates/.agents/skills/code-task/SKILL.en.md +2 -2
  237. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +4 -4
  238. package/templates/.agents/skills/commit/SKILL.en.md +2 -2
  239. package/templates/.agents/skills/commit/SKILL.zh-CN.md +2 -2
  240. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +6 -6
  241. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +6 -6
  242. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
  243. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
  244. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +2 -2
  245. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +2 -2
  246. package/templates/.agents/skills/complete-task/SKILL.en.md +10 -25
  247. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +11 -26
  248. package/templates/.agents/skills/create-pr/SKILL.en.md +1 -1
  249. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +1 -1
  250. package/templates/.agents/skills/create-pr/reference/change-report.en.md +9 -2
  251. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +9 -2
  252. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +2 -2
  253. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +2 -2
  254. package/templates/.agents/skills/create-task/SKILL.en.md +0 -18
  255. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +0 -18
  256. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
  257. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
  258. package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
  259. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
  260. package/templates/.agents/skills/review-code/SKILL.en.md +5 -5
  261. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -5
  262. package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
  263. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
  264. package/templates/.agents/skills/review-pr/SKILL.en.md +4 -4
  265. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +4 -4
  266. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
  267. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
  268. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -75
  269. package/templates/.agents/skills/watch-pr/SKILL.en.md +1 -1
  270. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +1 -1
  271. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +3 -3
  272. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +3 -3
  273. package/templates/.agents/templates/task.en.md +1 -0
  274. package/templates/.agents/templates/task.zh-CN.md +1 -0
  275. package/templates/.claude/settings.json +0 -24
  276. package/templates/.codex/hooks.json +0 -50
  277. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +0 -582
  278. package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +0 -114
  279. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +0 -237
  280. package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +0 -443
  281. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +0 -236
  282. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +0 -292
  283. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +0 -267
  284. package/dist/lib/agent-clients/adapters/codex-orchestration.js +0 -466
  285. package/dist/lib/internal/task-orchestration.js +0 -71
  286. package/dist/lib/platform/verification.js +0 -6
  287. package/dist/lib/run/prompt.js +0 -2
  288. package/dist/lib/sandbox/engines/authority.js +0 -289
  289. package/dist/lib/task/delegation-receipts.js +0 -410
  290. package/dist/lib/task/orchestration.js +0 -1233
  291. package/dist/lib/task/verification-checks.js +0 -9
  292. package/dist/lib/task/workspace-snapshot.js +0 -121
  293. package/dist/lifecycle-build-manifest.json +0 -6
  294. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +0 -688
  295. package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +0 -147
  296. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +0 -349
  297. package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +0 -506
  298. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +0 -385
  299. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -41
  300. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +0 -418
  301. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +0 -354
  302. package/lib/agent-clients/adapters/codex-orchestration.ts +0 -630
  303. package/lib/internal/task-orchestration.ts +0 -74
  304. package/lib/platform/verification.ts +0 -11
  305. package/lib/run/prompt.ts +0 -1
  306. package/lib/sandbox/engines/authority.ts +0 -365
  307. package/lib/task/delegation-receipts.ts +0 -547
  308. package/lib/task/orchestration.ts +0 -1651
  309. package/lib/task/verification-checks.ts +0 -10
  310. package/lib/task/workspace-snapshot.ts +0 -144
  311. package/templates/.agents/hooks/lifecycle-delegation.js +0 -140
  312. package/templates/.agents/rules/lifecycle-orchestration.en.md +0 -44
  313. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +0 -44
  314. package/templates/.agents/skills/run-task/SKILL.en.md +0 -29
  315. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +0 -29
  316. package/templates/.agents/skills/run-task/config/verify.en.json +0 -10
  317. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +0 -10
  318. package/templates/.agents/skills/run-task/reference/host-validation.en.md +0 -24
  319. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +0 -24
  320. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +0 -6
  321. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +0 -6
  322. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +0 -6
  323. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +0 -6
  324. package/templates/.claude/commands/run-task.en.md +0 -8
  325. package/templates/.claude/commands/run-task.zh-CN.md +0 -8
  326. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +0 -3
  327. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +0 -3
  328. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +0 -3
  329. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +0 -3
  330. package/templates/.opencode/commands/run-task.en.md +0 -11
  331. package/templates/.opencode/commands/run-task.zh-CN.md +0 -11
@@ -1,547 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
-
3
- import { isAgentClientId } from '../agent-clients/types.ts';
4
- import type { AgentClientId } from '../agent-clients/types.ts';
5
- import { normalizeAgentToken } from '../agent-clients/tokens.ts';
6
-
7
- type DelegationRole = 'executor' | 'reviewer';
8
- type DelegationStage = 'analysis' | 'review-analysis' | 'plan' | 'review-plan' | 'code' | 'review-code' | 'commit';
9
- type DelegationStatus = 'prepared' | 'activated' | 'stage-completed' | 'sealed' | 'consumed' | 'aborted' | 'expired';
10
- type DelegationReceipt = Readonly<{
11
- id: string;
12
- taskId: string;
13
- runId: string;
14
- role: DelegationRole;
15
- stage: DelegationStage;
16
- round: number;
17
- artifact: string;
18
- client: AgentClientId;
19
- requestedModel: string | null;
20
- requestedReasoningEffort: string | null;
21
- actualModel: string | null;
22
- actualReasoningEffort: string | null;
23
- modelFallbackReason: string | null;
24
- reasoningEffortFallbackReason: string | null;
25
- parentId: string | null;
26
- childId: string | null;
27
- spawnMode: string | null;
28
- agent: string | null;
29
- status: DelegationStatus;
30
- workspaceSnapshotScope?: 'task';
31
- adapterEvidence?: Readonly<Record<string, unknown>>;
32
- beforeFingerprint: string;
33
- afterFingerprint: string | null;
34
- changedPaths: readonly string[];
35
- createdAt: string;
36
- preparedMonotonicMs: number;
37
- spawnDispatchMonotonicMs: number | null;
38
- activationDeadlineMonotonicMs: number | null;
39
- spawnDispatchedAt: string | null;
40
- activationDeadlineAt: string | null;
41
- startEvidenceMonotonicMs: number | null;
42
- activatedMonotonicMs: number | null;
43
- activatedAt: string | null;
44
- sealedAt: string | null;
45
- consumedAt: string | null;
46
- }>;
47
-
48
- type ReceiptFailure = Readonly<{ ok: false; code: string; message: string; receipt?: never }>;
49
- type ReceiptSuccess = Readonly<{ ok: true; receipt: DelegationReceipt; code?: never; message?: never }>;
50
- type ReceiptResult = ReceiptSuccess | ReceiptFailure;
51
-
52
- function isRecord(value: unknown): value is Record<string, unknown> {
53
- return typeof value === 'object' && value !== null && !Array.isArray(value);
54
- }
55
-
56
- function hasExactKeys(
57
- value: unknown,
58
- required: readonly string[],
59
- optional: readonly string[] = []
60
- ): value is Record<string, unknown> {
61
- if (!isRecord(value)) return false;
62
- const keys = Object.keys(value);
63
- const allowed = new Set([...required, ...optional]);
64
- return required.every((key) => Object.prototype.hasOwnProperty.call(value, key))
65
- && keys.every((key) => allowed.has(key));
66
- }
67
-
68
- function exactText(value: unknown): value is string {
69
- return typeof value === 'string' && value.length > 0 && value.trim() === value;
70
- }
71
-
72
- function nullableText(value: unknown): value is string | null {
73
- return value === null || exactText(value);
74
- }
75
-
76
- function nullableSafeInteger(value: unknown): value is number | null {
77
- return value === null || (Number.isSafeInteger(value) && (value as number) >= 0);
78
- }
79
-
80
- const RECEIPT_KEYS = [
81
- 'id', 'taskId', 'runId', 'role', 'stage', 'round', 'artifact', 'client',
82
- 'requestedModel', 'requestedReasoningEffort', 'actualModel', 'actualReasoningEffort',
83
- 'modelFallbackReason', 'reasoningEffortFallbackReason', 'parentId', 'childId',
84
- 'spawnMode', 'agent', 'status', 'workspaceSnapshotScope',
85
- 'beforeFingerprint', 'afterFingerprint', 'changedPaths', 'createdAt',
86
- 'preparedMonotonicMs', 'spawnDispatchMonotonicMs', 'activationDeadlineMonotonicMs',
87
- 'spawnDispatchedAt', 'activationDeadlineAt', 'startEvidenceMonotonicMs',
88
- 'activatedMonotonicMs', 'activatedAt', 'sealedAt', 'consumedAt'
89
- ] as const;
90
- const RECEIPT_OPTIONAL_KEYS = ['adapterEvidence'] as const;
91
-
92
- function isJsonRecord(value: unknown): value is Readonly<Record<string, unknown>> {
93
- if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
94
- try {
95
- return JSON.parse(JSON.stringify(value)) !== null;
96
- } catch {
97
- return false;
98
- }
99
- }
100
-
101
- function withClientEvidence(receipt: DelegationReceipt, evidence: unknown): Readonly<Record<string, unknown>> | null {
102
- if (evidence === undefined) return receipt.adapterEvidence ?? Object.freeze({});
103
- if (!isJsonRecord(evidence)) return null;
104
- return Object.freeze({
105
- ...(receipt.adapterEvidence ?? {}),
106
- [receipt.client]: JSON.parse(JSON.stringify(evidence)) as unknown
107
- });
108
- }
109
-
110
- function hasStatusBoundEvidence(receipt: DelegationReceipt): boolean {
111
- const dispatchFields = [
112
- receipt.spawnDispatchMonotonicMs,
113
- receipt.activationDeadlineMonotonicMs,
114
- receipt.spawnDispatchedAt,
115
- receipt.activationDeadlineAt
116
- ];
117
- const dispatchEmpty = dispatchFields.every((field) => field === null);
118
- const dispatchComplete = dispatchFields.every((field) => field !== null);
119
- if (!dispatchEmpty && !dispatchComplete) return false;
120
-
121
- const beforeActivation = ['prepared', 'expired'].includes(receipt.status)
122
- || (receipt.status === 'aborted' && receipt.activatedAt === null);
123
- if (beforeActivation) {
124
- return receipt.parentId === null
125
- && receipt.childId === null
126
- && receipt.spawnMode === null
127
- && receipt.actualModel === null
128
- && receipt.actualReasoningEffort === null
129
- && receipt.modelFallbackReason === null
130
- && receipt.reasoningEffortFallbackReason === null
131
- && receipt.agent === null
132
- && receipt.startEvidenceMonotonicMs === null
133
- && receipt.activatedMonotonicMs === null
134
- && receipt.activatedAt === null
135
- && receipt.afterFingerprint === null
136
- && receipt.changedPaths.length === 0
137
- && receipt.sealedAt === null
138
- && receipt.consumedAt === null;
139
- }
140
-
141
- if (
142
- !dispatchComplete
143
- || !exactText(receipt.parentId)
144
- || !exactText(receipt.childId)
145
- || receipt.parentId === receipt.childId
146
- || receipt.startEvidenceMonotonicMs === null
147
- || receipt.activatedMonotonicMs === null
148
- || !exactText(receipt.activatedAt)
149
- ) return false;
150
-
151
- if (receipt.status === 'activated') {
152
- return receipt.agent === null
153
- && receipt.afterFingerprint === null
154
- && receipt.changedPaths.length === 0
155
- && receipt.sealedAt === null
156
- && receipt.consumedAt === null;
157
- }
158
-
159
- if (receipt.status === 'aborted') {
160
- return receipt.agent === null
161
- && receipt.afterFingerprint === null
162
- && receipt.changedPaths.length === 0
163
- && receipt.sealedAt === null
164
- && receipt.consumedAt === null
165
- && receipt.childId !== null;
166
- }
167
-
168
- if (
169
- !exactText(receipt.agent)
170
- || normalizeAgentToken(receipt.agent) !== normalizeAgentToken(receipt.client)
171
- ) return false;
172
-
173
- if (receipt.status === 'stage-completed') {
174
- return receipt.afterFingerprint === null
175
- && receipt.changedPaths.length === 0
176
- && receipt.sealedAt === null
177
- && receipt.consumedAt === null;
178
- }
179
-
180
- if (!exactText(receipt.afterFingerprint) || !exactText(receipt.sealedAt)) return false;
181
- return receipt.status === 'sealed'
182
- ? receipt.consumedAt === null
183
- : receipt.status === 'consumed' && exactText(receipt.consumedAt);
184
- }
185
-
186
- function isDelegationReceipt(value: unknown): value is DelegationReceipt {
187
- if (!hasExactKeys(value, RECEIPT_KEYS, RECEIPT_OPTIONAL_KEYS)) return false;
188
- const structurallyValid = exactText(value.id)
189
- && exactText(value.taskId)
190
- && exactText(value.runId)
191
- && ['executor', 'reviewer'].includes(value.role as string)
192
- && ['analysis', 'review-analysis', 'plan', 'review-plan', 'code', 'review-code', 'commit'].includes(value.stage as string)
193
- && Number.isSafeInteger(value.round)
194
- && (value.round as number) > 0
195
- && exactText(value.artifact)
196
- && isAgentClientId(value.client)
197
- && exactText(value.requestedModel)
198
- && exactText(value.requestedReasoningEffort)
199
- && nullableText(value.actualModel)
200
- && nullableText(value.actualReasoningEffort)
201
- && nullableText(value.modelFallbackReason)
202
- && nullableText(value.reasoningEffortFallbackReason)
203
- && nullableText(value.parentId)
204
- && nullableText(value.childId)
205
- && nullableText(value.spawnMode)
206
- && nullableText(value.agent)
207
- && ['prepared', 'activated', 'stage-completed', 'sealed', 'consumed', 'aborted', 'expired'].includes(value.status as string)
208
- && value.workspaceSnapshotScope === 'task'
209
- && (value.adapterEvidence === undefined || isJsonRecord(value.adapterEvidence))
210
- && exactText(value.beforeFingerprint)
211
- && nullableText(value.afterFingerprint)
212
- && Array.isArray(value.changedPaths)
213
- && value.changedPaths.every(exactText)
214
- && exactText(value.createdAt)
215
- && nullableSafeInteger(value.preparedMonotonicMs)
216
- && value.preparedMonotonicMs !== null
217
- && nullableSafeInteger(value.spawnDispatchMonotonicMs)
218
- && nullableSafeInteger(value.activationDeadlineMonotonicMs)
219
- && nullableText(value.spawnDispatchedAt)
220
- && nullableText(value.activationDeadlineAt)
221
- && nullableSafeInteger(value.startEvidenceMonotonicMs)
222
- && nullableSafeInteger(value.activatedMonotonicMs)
223
- && nullableText(value.activatedAt)
224
- && nullableText(value.sealedAt)
225
- && nullableText(value.consumedAt);
226
- if (!structurallyValid) return false;
227
- const receipt = value as unknown as DelegationReceipt;
228
- if (!hasStatusBoundEvidence(receipt)) return false;
229
- return true;
230
- }
231
-
232
- const MANAGED_AGENTS = {
233
- 'agent-infra-lifecycle-executor': 'executor',
234
- 'agent-infra-lifecycle-reviewer': 'reviewer'
235
- } as const;
236
-
237
- function managedDelegationRole(nativeAgent: string): DelegationRole | null {
238
- return MANAGED_AGENTS[nativeAgent as keyof typeof MANAGED_AGENTS] ?? null;
239
- }
240
-
241
- function fail(code: string, message: string): ReceiptFailure {
242
- return { ok: false, code, message };
243
- }
244
-
245
- // 空白串折叠为 null,保持"缺失即 null"的单一表示(Start/Stop 两处共用,避免任一入口把 " " 当成已观察到的值入账)
246
- function foldBlankToNull(value: string | undefined): string | null {
247
- return value?.trim() ? value : null;
248
- }
249
-
250
- function validateSealRequest(
251
- receipt: DelegationReceipt,
252
- event: Parameters<typeof sealDelegation>[1]
253
- ): ReceiptFailure | null {
254
- if (receipt.status !== 'stage-completed') {
255
- return fail('DELEGATION_STATE_INVALID', `delegation ${receipt.id} is ${receipt.status}, expected stage-completed`);
256
- }
257
- if (event.childId !== receipt.childId || event.exitCode !== 0) {
258
- return fail('DELEGATION_STOP_INVALID', 'native stop identity or exit status is invalid');
259
- }
260
- const reviewerPathFailure = validateReviewerSealPaths(receipt, event.changedPaths);
261
- return reviewerPathFailure;
262
- }
263
-
264
- function validateReviewerSealPaths(receipt: DelegationReceipt, changedPaths: readonly string[]): ReceiptFailure | null {
265
- if (receipt.role !== 'reviewer') return null;
266
- const taskRoot = `task-workspace/active/${receipt.taskId}/`;
267
- const allowed = new Set([
268
- `${taskRoot}${receipt.artifact}`,
269
- `${taskRoot}task.md`,
270
- `${taskRoot}.runtime/orchestration.json`
271
- ]);
272
- const disallowed = changedPaths.find((entry) => !allowed.has(entry));
273
- return disallowed
274
- ? fail('DELEGATION_REVIEWER_WRITE_FORBIDDEN', `reviewer changed forbidden path '${disallowed}'`)
275
- : null;
276
- }
277
-
278
- function prepareDelegation(
279
- input: Omit<DelegationReceipt, 'id' | 'requestedModel' | 'requestedReasoningEffort' | 'actualModel' | 'actualReasoningEffort' | 'modelFallbackReason' | 'reasoningEffortFallbackReason' | 'parentId' | 'childId' | 'spawnMode' | 'agent' | 'status' | 'afterFingerprint' | 'changedPaths' | 'createdAt' | 'preparedMonotonicMs' | 'spawnDispatchMonotonicMs' | 'activationDeadlineMonotonicMs' | 'spawnDispatchedAt' | 'activationDeadlineAt' | 'startEvidenceMonotonicMs' | 'activatedMonotonicMs' | 'activatedAt' | 'sealedAt' | 'consumedAt'> & Readonly<{ requestedModel: string; requestedReasoningEffort: string }>,
280
- options: { id?: () => string; now?: () => string; monotonicNow?: () => number } = {}
281
- ): DelegationReceipt {
282
- const monotonic = (options.monotonicNow ?? (() => Number(process.hrtime.bigint() / 1_000_000n)))();
283
- return Object.freeze({
284
- ...input,
285
- adapterEvidence: Object.freeze({ ...(input.adapterEvidence ?? {}) }),
286
- id: (options.id ?? randomUUID)(),
287
- actualModel: null,
288
- actualReasoningEffort: null,
289
- modelFallbackReason: null,
290
- reasoningEffortFallbackReason: null,
291
- parentId: null,
292
- childId: null,
293
- spawnMode: null,
294
- agent: null,
295
- status: 'prepared' as const,
296
- afterFingerprint: null,
297
- changedPaths: Object.freeze([]),
298
- createdAt: (options.now ?? (() => new Date().toISOString()))(),
299
- preparedMonotonicMs: monotonic,
300
- spawnDispatchMonotonicMs: null,
301
- activationDeadlineMonotonicMs: null,
302
- spawnDispatchedAt: null,
303
- activationDeadlineAt: null,
304
- startEvidenceMonotonicMs: null,
305
- activatedMonotonicMs: null,
306
- activatedAt: null,
307
- sealedAt: null,
308
- consumedAt: null
309
- });
310
- }
311
-
312
- function dispatchDelegation(
313
- receipt: DelegationReceipt,
314
- options: { now?: () => string; monotonicNow?: () => number; activationWindowMs?: number } = {}
315
- ): ReceiptResult {
316
- if (receipt.status !== 'prepared') {
317
- return fail('DELEGATION_STATE_INVALID', `delegation ${receipt.id} is ${receipt.status}, expected prepared`);
318
- }
319
- if (receipt.spawnDispatchMonotonicMs != null || receipt.spawnDispatchedAt != null) {
320
- return fail('DELEGATION_DISPATCH_REPLAY', `delegation ${receipt.id} was already dispatched`);
321
- }
322
- const monotonic = (options.monotonicNow ?? (() => Number(process.hrtime.bigint() / 1_000_000n)))();
323
- const dispatchedAt = (options.now ?? (() => new Date().toISOString()))();
324
- const window = options.activationWindowMs ?? 60_000;
325
- return { ok: true, receipt: Object.freeze({
326
- ...receipt,
327
- spawnDispatchMonotonicMs: monotonic,
328
- activationDeadlineMonotonicMs: monotonic + window,
329
- spawnDispatchedAt: dispatchedAt,
330
- activationDeadlineAt: new Date(Date.parse(dispatchedAt) + window).toISOString()
331
- }) };
332
- }
333
-
334
- function activateDelegation(
335
- receipt: DelegationReceipt,
336
- event: Readonly<{
337
- nativeAgent: string;
338
- childId: string;
339
- parentId: string;
340
- spawnMode?: string;
341
- actualModel?: string;
342
- actualReasoningEffort?: string;
343
- modelFallbackReason?: string;
344
- reasoningEffortFallbackReason?: string;
345
- clientEvidence?: unknown;
346
- }>,
347
- options: {
348
- now?: () => string;
349
- monotonicNow?: () => number;
350
- evidencePolicy?: Readonly<{
351
- spawnModeRequired?: boolean;
352
- actualModelRequired?: boolean;
353
- actualReasoningEffortRequired?: boolean;
354
- fallbackReasonRequired?: boolean;
355
- }>;
356
- } = {}
357
- ): ReceiptResult {
358
- const managedRole = managedDelegationRole(event.nativeAgent);
359
- if (!managedRole) return fail('DELEGATION_IGNORED', `subagent '${event.nativeAgent}' is not lifecycle-managed`);
360
- if (receipt.status !== 'prepared') return fail('DELEGATION_STATE_INVALID', `delegation ${receipt.id} is ${receipt.status}, expected prepared`);
361
- if (
362
- receipt.spawnDispatchMonotonicMs == null
363
- || receipt.spawnDispatchedAt == null
364
- || receipt.activationDeadlineAt == null
365
- || receipt.activationDeadlineMonotonicMs == null
366
- || !Number.isFinite(Date.parse(receipt.spawnDispatchedAt))
367
- || !Number.isFinite(Date.parse(receipt.activationDeadlineAt))
368
- ) {
369
- return fail('DELEGATION_NOT_DISPATCHED', `delegation ${receipt.id} has not reached the native spawn dispatch boundary`);
370
- }
371
- const monotonic = (options.monotonicNow ?? (() => Number(process.hrtime.bigint() / 1_000_000n)))();
372
- const wallNow = Date.parse((options.now ?? (() => new Date().toISOString()))());
373
- if (wallNow > Date.parse(receipt.activationDeadlineAt)) {
374
- return fail('DELEGATION_ACTIVATION_TIMEOUT', `delegation ${receipt.id} activation evidence arrived after its deadline`);
375
- }
376
- if (managedRole !== receipt.role) return fail('DELEGATION_ROLE_MISMATCH', `managed role ${managedRole} does not match ${receipt.role}`);
377
- if (!event.parentId || (receipt.parentId !== null && event.parentId !== receipt.parentId) || !event.childId || event.childId === event.parentId) {
378
- return fail('DELEGATION_IDENTITY_INVALID', 'native parent/child identity does not match the prepared delegation');
379
- }
380
- const evidencePolicy = options.evidencePolicy ?? {};
381
- if (evidencePolicy.spawnModeRequired !== false && event.spawnMode !== 'fresh') {
382
- return fail('DELEGATION_FORK_FORBIDDEN', `spawn mode '${event.spawnMode}' is not fresh`);
383
- }
384
- const actualModel = foldBlankToNull(event.actualModel);
385
- const actualReasoningEffort = foldBlankToNull(event.actualReasoningEffort);
386
- if (evidencePolicy.actualModelRequired !== false) {
387
- if (!actualModel || actualModel.trim() !== actualModel) {
388
- return fail('DELEGATION_MODEL_IDENTITY_MISSING', 'native start event must provide a non-empty actual model identity');
389
- }
390
- }
391
- if (actualModel !== null && actualModel !== receipt.requestedModel) {
392
- if (evidencePolicy.fallbackReasonRequired !== false && (!event.modelFallbackReason || event.modelFallbackReason.trim() === '')) {
393
- return fail('DELEGATION_MODEL_FALLBACK_UNRECORDED', 'actual model differs from requested model without a fallback reason');
394
- }
395
- }
396
- if (evidencePolicy.actualReasoningEffortRequired !== false) {
397
- if (!actualReasoningEffort || actualReasoningEffort.trim() !== actualReasoningEffort) {
398
- return fail('DELEGATION_REASONING_EFFORT_MISSING', 'native start event must provide a non-empty actual reasoning effort');
399
- }
400
- }
401
- if (actualReasoningEffort !== null && actualReasoningEffort !== receipt.requestedReasoningEffort) {
402
- if (evidencePolicy.fallbackReasonRequired !== false && (!event.reasoningEffortFallbackReason || event.reasoningEffortFallbackReason.trim() === '')) {
403
- return fail('DELEGATION_REASONING_EFFORT_FALLBACK_UNRECORDED', 'actual reasoning effort differs from requested effort without a fallback reason');
404
- }
405
- }
406
- // "无关 fallback 理由"检查对所有 client 保持不变——防止编造理由的红线,不属于 HDR-2 放宽范围
407
- // actualModel/actualReasoningEffort 为 null(未观察到)时同样没有"实际不同"这回事,理由一样是无关的
408
- if ((actualModel === null || actualModel === receipt.requestedModel) && event.modelFallbackReason) {
409
- return fail('DELEGATION_MODEL_FALLBACK_INVALID', 'model fallback reason is only valid when actual model differs');
410
- }
411
- if (
412
- (actualReasoningEffort === null || actualReasoningEffort === receipt.requestedReasoningEffort)
413
- && event.reasoningEffortFallbackReason
414
- ) {
415
- return fail('DELEGATION_REASONING_EFFORT_FALLBACK_INVALID', 'reasoning-effort fallback reason is only valid when actual effort differs');
416
- }
417
- const adapterEvidence = withClientEvidence(receipt, event.clientEvidence);
418
- if (!adapterEvidence) return fail('DELEGATION_ADAPTER_EVIDENCE_INVALID', 'adapter evidence must be a JSON object');
419
- return { ok: true, receipt: Object.freeze({
420
- ...receipt,
421
- status: 'activated',
422
- parentId: event.parentId,
423
- childId: event.childId,
424
- spawnMode: event.spawnMode ?? null,
425
- actualModel,
426
- actualReasoningEffort,
427
- modelFallbackReason: event.modelFallbackReason ?? null,
428
- reasoningEffortFallbackReason: event.reasoningEffortFallbackReason ?? null,
429
- adapterEvidence,
430
- startEvidenceMonotonicMs: monotonic,
431
- activatedMonotonicMs: (options.monotonicNow ?? (() => Number(process.hrtime.bigint() / 1_000_000n)))(),
432
- activatedAt: new Date(wallNow).toISOString()
433
- }) };
434
- }
435
-
436
- function abortPreparedDelegation(receipt: DelegationReceipt): ReceiptResult {
437
- if (receipt.status !== 'prepared') {
438
- return fail('DELEGATION_STATE_INVALID', `delegation ${receipt.id} is ${receipt.status}, expected prepared`);
439
- }
440
- return {
441
- ok: true,
442
- receipt: Object.freeze({ ...receipt, status: 'aborted' as const })
443
- };
444
- }
445
-
446
- function abortActivatedDelegation(
447
- receipt: DelegationReceipt,
448
- event: Readonly<{ childId: string; clientEvidence?: unknown }>
449
- ): ReceiptResult {
450
- if (receipt.status !== 'activated') {
451
- return fail('DELEGATION_STATE_INVALID', `delegation ${receipt.id} is ${receipt.status}, expected activated`);
452
- }
453
- if (event.childId !== receipt.childId) return fail('DELEGATION_RECOVERY_EVIDENCE_INVALID', 'recovery child does not match the activated delegation');
454
- const adapterEvidence = withClientEvidence(receipt, event.clientEvidence);
455
- if (!adapterEvidence) return fail('DELEGATION_ADAPTER_EVIDENCE_INVALID', 'adapter evidence must be a JSON object');
456
- return {
457
- ok: true,
458
- receipt: Object.freeze({
459
- ...receipt,
460
- status: 'aborted' as const,
461
- agent: null,
462
- afterFingerprint: null,
463
- changedPaths: Object.freeze([]),
464
- sealedAt: null,
465
- consumedAt: null,
466
- adapterEvidence
467
- })
468
- };
469
- }
470
-
471
- function completeDelegationStage(
472
- receipt: DelegationReceipt,
473
- event: Readonly<{ stage: DelegationStage; round: number; artifact: string; agent: string }>
474
- ): ReceiptResult {
475
- if (receipt.status !== 'activated') return fail('DELEGATION_STATE_INVALID', `delegation ${receipt.id} is ${receipt.status}, expected activated`);
476
- if (event.stage !== receipt.stage || event.round !== receipt.round || event.artifact !== receipt.artifact) {
477
- return fail('DELEGATION_STAGE_MISMATCH', 'stage completion identity does not match the active delegation');
478
- }
479
- if (normalizeAgentToken(event.agent) !== normalizeAgentToken(receipt.client)) {
480
- return fail('DELEGATION_AGENT_MISMATCH', `stage agent '${event.agent}' does not match client '${receipt.client}'`);
481
- }
482
- return { ok: true, receipt: Object.freeze({ ...receipt, status: 'stage-completed', agent: event.agent }) };
483
- }
484
-
485
- function sealDelegation(
486
- receipt: DelegationReceipt,
487
- event: Readonly<{
488
- childId: string;
489
- exitCode: number;
490
- afterFingerprint: string;
491
- changedPaths: readonly string[];
492
- actualModel?: string;
493
- actualReasoningEffort?: string;
494
- modelFallbackReason?: string;
495
- reasoningEffortFallbackReason?: string;
496
- clientEvidence?: unknown;
497
- }>,
498
- options: { now?: () => string } = {}
499
- ): ReceiptResult {
500
- const validationFailure = validateSealRequest(receipt, event);
501
- if (validationFailure) return validationFailure;
502
- const adapterEvidence = withClientEvidence(receipt, event.clientEvidence);
503
- if (!adapterEvidence) return fail('DELEGATION_ADAPTER_EVIDENCE_INVALID', 'adapter evidence must be a JSON object');
504
- return { ok: true, receipt: Object.freeze({
505
- ...receipt,
506
- status: 'sealed',
507
- afterFingerprint: event.afterFingerprint,
508
- changedPaths: Object.freeze([...event.changedPaths]),
509
- actualModel: receipt.actualModel ?? foldBlankToNull(event.actualModel),
510
- actualReasoningEffort: receipt.actualReasoningEffort ?? foldBlankToNull(event.actualReasoningEffort),
511
- modelFallbackReason: receipt.modelFallbackReason ?? event.modelFallbackReason ?? null,
512
- reasoningEffortFallbackReason: receipt.reasoningEffortFallbackReason ?? event.reasoningEffortFallbackReason ?? null,
513
- adapterEvidence,
514
- sealedAt: (options.now ?? (() => new Date().toISOString()))()
515
- }) };
516
- }
517
-
518
- function consumeDelegation(receipt: DelegationReceipt, options: { now?: () => string } = {}): ReceiptResult {
519
- if (receipt.status === 'consumed') return fail('DELEGATION_REPLAY', `delegation ${receipt.id} was already consumed`);
520
- if (receipt.status !== 'sealed') return fail('DELEGATION_STATE_INVALID', `delegation ${receipt.id} is ${receipt.status}, expected sealed`);
521
- return { ok: true, receipt: Object.freeze({
522
- ...receipt,
523
- status: 'consumed',
524
- consumedAt: (options.now ?? (() => new Date().toISOString()))()
525
- }) };
526
- }
527
-
528
- export {
529
- activateDelegation,
530
- abortActivatedDelegation,
531
- abortPreparedDelegation,
532
- completeDelegationStage,
533
- consumeDelegation,
534
- dispatchDelegation,
535
- foldBlankToNull,
536
- isDelegationReceipt,
537
- managedDelegationRole,
538
- prepareDelegation,
539
- sealDelegation
540
- };
541
- export type {
542
- DelegationReceipt,
543
- DelegationRole,
544
- DelegationStage,
545
- DelegationStatus,
546
- ReceiptResult
547
- };