@fitlab-ai/agent-infra 0.12.1 → 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 (303) 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 +18 -10
  21. package/dist/lib/internal/task-create.js +1 -1
  22. package/dist/lib/internal/task-event.js +1 -8
  23. package/dist/lib/internal/task-finalization.js +0 -1
  24. package/dist/lib/internal/task-lifecycle.js +2 -2
  25. package/dist/lib/internal/task-operation-registry.js +4 -20
  26. package/dist/lib/internal/task-review.js +4 -4
  27. package/dist/lib/platform/comment-safety.js +1 -7
  28. package/dist/lib/platform/in-label-sync.js +1 -14
  29. package/dist/lib/platform/issue-comments.js +1 -16
  30. package/dist/lib/platform/issues.js +1 -1
  31. package/dist/lib/platform/operation-coordinator.js +4 -2
  32. package/dist/lib/platform/pr-change-report.js +1 -4
  33. package/dist/lib/platform/pr-checks.js +2 -8
  34. package/dist/lib/platform/provider-validation.js +0 -20
  35. package/dist/lib/platform/pull-requests.js +73 -84
  36. package/dist/lib/platform/releases.js +1 -43
  37. package/dist/lib/platform/verification-required.js +0 -2
  38. package/dist/lib/platform/verification-sync.js +1 -79
  39. package/dist/lib/process-data/normalize.js +1 -185
  40. package/dist/lib/process-data/privacy.js +1 -16
  41. package/dist/lib/process-data/sources.js +2 -279
  42. package/dist/lib/render.js +0 -12
  43. package/dist/lib/run/index.js +15 -10
  44. package/dist/lib/run/skills.js +0 -3
  45. package/dist/lib/sandbox/commands/create.js +40 -53
  46. package/dist/lib/sandbox/commands/list-running.js +0 -18
  47. package/dist/lib/sandbox/commands/start.js +7 -8
  48. package/dist/lib/sandbox/constants.js +0 -6
  49. package/dist/lib/sandbox/control/client.js +0 -1
  50. package/dist/lib/sandbox/control/container-identity.js +1 -16
  51. package/dist/lib/sandbox/control/executor.js +0 -4
  52. package/dist/lib/sandbox/control/identity-sentinel.js +0 -7
  53. package/dist/lib/sandbox/control/lifecycle.js +21 -37
  54. package/dist/lib/sandbox/control/native-file-lock.js +0 -3
  55. package/dist/lib/sandbox/control/server.js +18 -38
  56. package/dist/lib/sandbox/control/state.js +1 -9
  57. package/dist/lib/sandbox/dockerfile.js +0 -6
  58. package/dist/lib/sandbox/engine.js +0 -14
  59. package/dist/lib/sandbox/engines/docker-exact-discovery.js +1 -4
  60. package/dist/lib/sandbox/engines/wsl2-paths.js +0 -3
  61. package/dist/lib/sandbox/recovery.js +24 -26
  62. package/dist/lib/sandbox/removal.js +11 -519
  63. package/dist/lib/sandbox/task-resolver.js +0 -41
  64. package/dist/lib/sandbox/tools.js +1 -4
  65. package/dist/lib/sandbox/workspace-view.js +1 -2
  66. package/dist/lib/server/display.js +0 -6
  67. package/dist/lib/task/activity-intent.js +45 -40
  68. package/dist/lib/task/activity-log.js +9 -16
  69. package/dist/lib/task/artifact-command.js +1 -1
  70. package/dist/lib/task/artifact-lifecycle.js +61 -63
  71. package/dist/lib/task/artifact-name.js +0 -6
  72. package/dist/lib/task/artifact-operations.js +3 -3
  73. package/dist/lib/task/capabilities.js +4 -5
  74. package/dist/lib/task/commands/log.js +0 -6
  75. package/dist/lib/task/commands/status.js +17 -60
  76. package/dist/lib/task/commit-operation.js +28 -39
  77. package/dist/lib/task/completion-facts.js +56 -43
  78. package/dist/lib/task/control-authority.js +23 -256
  79. package/dist/lib/task/control-recovery.js +3 -5
  80. package/dist/lib/task/create.js +2 -4
  81. package/dist/lib/task/decision-intents.js +8 -9
  82. package/dist/lib/task/delivery-target.js +1 -40
  83. package/dist/lib/task/events.js +84 -107
  84. package/dist/lib/task/finalization.js +44 -8
  85. package/dist/lib/task/ledger-intents.js +1 -1
  86. package/dist/lib/task/lifecycle-execution.js +38 -33
  87. package/dist/lib/task/lifecycle.js +49 -41
  88. package/dist/lib/task/local-artifact-finalization.js +1 -4
  89. package/dist/lib/task/manual-validation-evidence.js +1 -37
  90. package/dist/lib/task/platform-operation-recovery.js +67 -24
  91. package/dist/lib/task/pr-delivery-fact.js +2 -5
  92. package/dist/lib/task/qualification-confirmation.js +5 -7
  93. package/dist/lib/task/resolve-ref.js +1 -25
  94. package/dist/lib/task/review-command.js +2 -2
  95. package/dist/lib/task/review-finalization.js +1 -21
  96. package/dist/lib/task/review-fingerprint.js +0 -4
  97. package/dist/lib/task/secure-fs.js +0 -56
  98. package/dist/lib/task/short-id.js +1 -39
  99. package/dist/lib/task/skill-scope.js +0 -1
  100. package/dist/lib/task/verification-engine.js +58 -282
  101. package/dist/lib/task/verification.js +6 -3
  102. package/dist/lib/task/write.js +11 -1
  103. package/lib/agent-clients/adapter.ts +0 -76
  104. package/lib/agent-clients/adapters/antigravity-cli.ts +0 -5
  105. package/lib/agent-clients/adapters/claude-code-credentials.ts +0 -19
  106. package/lib/agent-clients/adapters/claude-code.ts +0 -9
  107. package/lib/agent-clients/adapters/codex.ts +0 -56
  108. package/lib/agent-clients/adapters/opencode.ts +0 -5
  109. package/lib/agent-clients/adapters/traecli.ts +0 -5
  110. package/lib/agent-clients/config.ts +20 -61
  111. package/lib/agent-clients/registry.ts +1 -34
  112. package/lib/agent-clients/schema.ts +0 -18
  113. package/lib/agent-clients/tokens.ts +1 -2
  114. package/lib/agent-clients/types.ts +0 -15
  115. package/lib/decide.ts +1 -0
  116. package/lib/git/worktree-identity.ts +0 -10
  117. package/lib/internal/agent-client.ts +2 -70
  118. package/lib/internal/cli-route-inventory.ts +1 -4
  119. package/lib/internal/manual-validation.ts +16 -9
  120. package/lib/internal/task-create.ts +0 -1
  121. package/lib/internal/task-event.ts +1 -5
  122. package/lib/internal/task-finalization.ts +0 -1
  123. package/lib/internal/task-lifecycle.ts +3 -5
  124. package/lib/internal/task-operation-registry.ts +3 -19
  125. package/lib/internal/task-review.ts +4 -4
  126. package/lib/platform/comment-safety.ts +0 -10
  127. package/lib/platform/github-provider.ts +0 -2
  128. package/lib/platform/in-label-sync.ts +0 -16
  129. package/lib/platform/issue-comments.ts +0 -21
  130. package/lib/platform/issues.ts +0 -2
  131. package/lib/platform/operation-coordinator.ts +4 -2
  132. package/lib/platform/pr-change-report.ts +0 -5
  133. package/lib/platform/pr-checks.ts +1 -10
  134. package/lib/platform/pr-review.ts +1 -1
  135. package/lib/platform/provider-bridge.ts +0 -1
  136. package/lib/platform/provider-loader.ts +1 -5
  137. package/lib/platform/provider-validation.ts +1 -49
  138. package/lib/platform/pull-requests.ts +64 -99
  139. package/lib/platform/releases.ts +1 -40
  140. package/lib/platform/verification-required.ts +0 -2
  141. package/lib/platform/verification-sync.ts +0 -94
  142. package/lib/process-data/normalize.ts +1 -186
  143. package/lib/process-data/privacy.ts +2 -19
  144. package/lib/process-data/sources.ts +3 -283
  145. package/lib/render.ts +0 -15
  146. package/lib/run/index.ts +13 -7
  147. package/lib/run/skills.ts +0 -4
  148. package/lib/sandbox/commands/create.ts +37 -74
  149. package/lib/sandbox/commands/list-running.ts +0 -19
  150. package/lib/sandbox/commands/start.ts +7 -10
  151. package/lib/sandbox/constants.ts +0 -8
  152. package/lib/sandbox/control/client.ts +0 -1
  153. package/lib/sandbox/control/container-identity.ts +1 -16
  154. package/lib/sandbox/control/executor.ts +1 -5
  155. package/lib/sandbox/control/identity-sentinel.ts +0 -8
  156. package/lib/sandbox/control/lifecycle.ts +18 -51
  157. package/lib/sandbox/control/native-file-lock.ts +0 -8
  158. package/lib/sandbox/control/protocol.ts +0 -2
  159. package/lib/sandbox/control/server.ts +13 -39
  160. package/lib/sandbox/control/state.ts +1 -10
  161. package/lib/sandbox/dockerfile.ts +0 -11
  162. package/lib/sandbox/engine.ts +0 -17
  163. package/lib/sandbox/engines/docker-exact-discovery.ts +1 -5
  164. package/lib/sandbox/engines/wsl2-paths.ts +0 -4
  165. package/lib/sandbox/recovery.ts +24 -26
  166. package/lib/sandbox/removal.ts +11 -696
  167. package/lib/sandbox/shell.ts +1 -1
  168. package/lib/sandbox/task-resolver.ts +0 -48
  169. package/lib/sandbox/tools.ts +1 -5
  170. package/lib/sandbox/workspace-view.ts +2 -4
  171. package/lib/server/display.ts +0 -14
  172. package/lib/server/process-control.ts +1 -1
  173. package/lib/task/activity-intent.ts +36 -44
  174. package/lib/task/activity-log.ts +9 -22
  175. package/lib/task/artifact-command.ts +1 -1
  176. package/lib/task/artifact-lifecycle.ts +58 -67
  177. package/lib/task/artifact-name.ts +0 -7
  178. package/lib/task/artifact-operations.ts +3 -3
  179. package/lib/task/capabilities.ts +5 -6
  180. package/lib/task/commands/log.ts +0 -7
  181. package/lib/task/commands/status.ts +14 -79
  182. package/lib/task/commit-operation.ts +29 -51
  183. package/lib/task/completion-facts.ts +45 -42
  184. package/lib/task/control-authority.ts +27 -317
  185. package/lib/task/control-recovery.ts +2 -5
  186. package/lib/task/create.ts +2 -5
  187. package/lib/task/decision-intents.ts +5 -5
  188. package/lib/task/delivery-target.ts +0 -40
  189. package/lib/task/events.ts +89 -123
  190. package/lib/task/finalization.ts +41 -9
  191. package/lib/task/ledger-intents.ts +1 -1
  192. package/lib/task/lifecycle-execution.ts +37 -89
  193. package/lib/task/lifecycle.ts +48 -44
  194. package/lib/task/local-artifact-finalization.ts +0 -7
  195. package/lib/task/manual-validation-evidence.ts +1 -47
  196. package/lib/task/platform-operation-recovery.ts +50 -26
  197. package/lib/task/pr-delivery-fact.ts +2 -11
  198. package/lib/task/qualification-confirmation.ts +6 -6
  199. package/lib/task/resolve-ref.ts +0 -23
  200. package/lib/task/review-command.ts +2 -2
  201. package/lib/task/review-finalization.ts +1 -27
  202. package/lib/task/review-fingerprint.ts +0 -8
  203. package/lib/task/secure-fs.ts +0 -42
  204. package/lib/task/short-id.ts +0 -43
  205. package/lib/task/skill-scope.ts +0 -1
  206. package/lib/task/verification-engine.ts +56 -287
  207. package/lib/task/verification.ts +5 -5
  208. package/lib/task/write.ts +12 -1
  209. package/package.json +2 -2
  210. package/templates/.agents/README.en.md +1 -3
  211. package/templates/.agents/README.zh-CN.md +0 -2
  212. package/templates/.agents/rules/README.en.md +0 -1
  213. package/templates/.agents/rules/README.zh-CN.md +0 -1
  214. package/templates/.agents/rules/commit-and-pr.en.md +1 -1
  215. package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -1
  216. package/templates/.agents/rules/no-mid-flow-questions.en.md +0 -10
  217. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +0 -10
  218. package/templates/.agents/rules/pr-sync.en.md +1 -1
  219. package/templates/.agents/rules/pr-sync.zh-CN.md +1 -1
  220. package/templates/.agents/rules/task-management.en.md +3 -3
  221. package/templates/.agents/rules/task-management.zh-CN.md +3 -3
  222. package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
  223. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
  224. package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
  225. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
  226. package/templates/.agents/skills/code-task/SKILL.en.md +2 -2
  227. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +4 -4
  228. package/templates/.agents/skills/commit/SKILL.en.md +2 -2
  229. package/templates/.agents/skills/commit/SKILL.zh-CN.md +2 -2
  230. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +6 -6
  231. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +6 -6
  232. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
  233. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
  234. package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
  235. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
  236. package/templates/.agents/skills/review-code/SKILL.en.md +5 -5
  237. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -5
  238. package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
  239. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
  240. package/templates/.agents/skills/review-pr/SKILL.en.md +4 -4
  241. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +4 -4
  242. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
  243. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
  244. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -75
  245. package/templates/.agents/templates/task.en.md +1 -0
  246. package/templates/.agents/templates/task.zh-CN.md +1 -0
  247. package/templates/.claude/settings.json +0 -24
  248. package/templates/.codex/hooks.json +0 -50
  249. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +0 -582
  250. package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +0 -114
  251. package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +0 -237
  252. package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +0 -443
  253. package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +0 -236
  254. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +0 -292
  255. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +0 -267
  256. package/dist/lib/agent-clients/adapters/codex-orchestration.js +0 -466
  257. package/dist/lib/internal/task-orchestration.js +0 -71
  258. package/dist/lib/platform/verification.js +0 -6
  259. package/dist/lib/run/prompt.js +0 -2
  260. package/dist/lib/sandbox/engines/authority.js +0 -289
  261. package/dist/lib/task/delegation-receipts.js +0 -410
  262. package/dist/lib/task/orchestration.js +0 -1233
  263. package/dist/lib/task/verification-checks.js +0 -9
  264. package/dist/lib/task/workspace-snapshot.js +0 -121
  265. package/dist/lifecycle-build-manifest.json +0 -6
  266. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +0 -688
  267. package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +0 -147
  268. package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +0 -349
  269. package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +0 -506
  270. package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +0 -385
  271. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -41
  272. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +0 -418
  273. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +0 -354
  274. package/lib/agent-clients/adapters/codex-orchestration.ts +0 -630
  275. package/lib/internal/task-orchestration.ts +0 -74
  276. package/lib/platform/verification.ts +0 -11
  277. package/lib/run/prompt.ts +0 -1
  278. package/lib/sandbox/engines/authority.ts +0 -365
  279. package/lib/task/delegation-receipts.ts +0 -547
  280. package/lib/task/orchestration.ts +0 -1651
  281. package/lib/task/verification-checks.ts +0 -10
  282. package/lib/task/workspace-snapshot.ts +0 -144
  283. package/templates/.agents/hooks/lifecycle-delegation.js +0 -140
  284. package/templates/.agents/rules/lifecycle-orchestration.en.md +0 -44
  285. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +0 -44
  286. package/templates/.agents/skills/run-task/SKILL.en.md +0 -29
  287. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +0 -29
  288. package/templates/.agents/skills/run-task/config/verify.en.json +0 -10
  289. package/templates/.agents/skills/run-task/config/verify.zh-CN.json +0 -10
  290. package/templates/.agents/skills/run-task/reference/host-validation.en.md +0 -24
  291. package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +0 -24
  292. package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +0 -6
  293. package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +0 -6
  294. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +0 -6
  295. package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +0 -6
  296. package/templates/.claude/commands/run-task.en.md +0 -8
  297. package/templates/.claude/commands/run-task.zh-CN.md +0 -8
  298. package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +0 -3
  299. package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +0 -3
  300. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +0 -3
  301. package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +0 -3
  302. package/templates/.opencode/commands/run-task.en.md +0 -11
  303. package/templates/.opencode/commands/run-task.zh-CN.md +0 -11
@@ -2,27 +2,7 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
 
4
4
  import { normalizeAgentToken } from '../agent-clients/tokens.ts';
5
- import { isAgentClientId } from '../agent-clients/types.ts';
6
- import type { AgentClientId } from '../agent-clients/types.ts';
7
5
  import { sandboxControlPaths } from '../sandbox/workspace-view.ts';
8
- import { getAgentClientAdapter } from '../agent-clients/registry.ts';
9
- import {
10
- activateMatchingOrchestrationDelegation,
11
- activateOrchestrationDelegation,
12
- advanceOrchestration,
13
- awaitOrchestrationDelegationActivation,
14
- beginOrResumeOrchestration,
15
- dispatchOrchestrationDelegation,
16
- OrchestrationStateError,
17
- pauseOrchestration,
18
- prepareOrchestrationDelegation,
19
- recoverPreparedOrchestrationDelegation,
20
- routeOrchestration,
21
- sealMatchingOrchestrationDelegation,
22
- sealOrchestrationDelegation,
23
- statusOrchestration
24
- } from './orchestration.ts';
25
- import type { OrchestrationOptions, OrchestrationResult } from './orchestration.ts';
26
6
  import {
27
7
  applyTaskFinalization,
28
8
  type TaskFinalizationRequest,
@@ -33,11 +13,7 @@ import {
33
13
  type TaskLifecycleRequest,
34
14
  type TaskLifecycleResult
35
15
  } from './lifecycle.ts';
36
- import type {
37
- AgentClientLifecycleRecoveryRequest as LifecycleRecoveryRequest,
38
- AgentClientLifecycleRecoveryResult as LifecycleRecoveryResult
39
- } from '../agent-clients/adapter.ts';
40
- import { resolveTaskContext, resolveTaskRef, TASK_ID_RE } from './resolve-ref.ts';
16
+ import { resolveTaskRef, TASK_ID_RE } from './resolve-ref.ts';
41
17
  import { verifyTaskEvent } from './verification.ts';
42
18
  import { releaseStaleShortIdRegistry } from './short-id.ts';
43
19
 
@@ -62,39 +38,11 @@ export type TaskControlExecutionContext =
62
38
  requestId: string;
63
39
  }>;
64
40
 
65
- export type TaskControlOrchestrationIntent =
66
- | 'begin-or-resume'
67
- | 'route'
68
- | 'prepare'
69
- | 'dispatch'
70
- | 'await-activation'
71
- | 'recover-prepared'
72
- | 'hook-start'
73
- | 'hook-stop'
74
- | 'advance'
75
- | 'pause'
76
- | 'status';
77
-
78
41
  export type TaskControlOperation =
79
42
  | Readonly<{ family: 'task-lifecycle'; request: TaskLifecycleControlRequest }>
80
- | Readonly<{ family: 'task-finalization'; request: TaskFinalizationRequest }>
81
- | Readonly<{
82
- family: 'task-orchestration';
83
- taskRef: string;
84
- intent: TaskControlOrchestrationIntent;
85
- input: Readonly<Record<string, unknown>>;
86
- options?: Omit<OrchestrationOptions, 'repoRoot'>;
87
- }>;
43
+ | Readonly<{ family: 'task-finalization'; request: TaskFinalizationRequest }>;
88
44
 
89
- export type TaskControlDispatchResult = TaskLifecycleResult | LifecycleRecoveryResult | TaskFinalizationResult | OrchestrationResult;
90
-
91
- export function taskControlOperationKey(operation: TaskControlOperation): string {
92
- if (operation.family === 'task-finalization') return 'complete';
93
- if (operation.family === 'task-lifecycle') return operation.request.intent;
94
- return operation.intent === 'route'
95
- ? operation.input && operation.input.completed === true ? 'route.clean-completion' : 'route.read'
96
- : operation.intent;
97
- }
45
+ export type TaskControlDispatchResult = TaskLifecycleResult | TaskFinalizationResult;
98
46
 
99
47
  export type TaskLifecycleControlRequest = TaskLifecycleRequest;
100
48
 
@@ -178,26 +126,6 @@ function boundTaskRef(context: TaskControlExecutionContext, taskRef: string): st
178
126
  return context.source === 'sandbox-executor' ? context.taskId : taskRef;
179
127
  }
180
128
 
181
- function autoTaskOptions(
182
- context: TaskControlExecutionContext,
183
- options: OrchestrationOptions
184
- ): OrchestrationOptions {
185
- if (context.source === 'sandbox-executor') return { ...options, taskId: context.taskId };
186
- const resolved = resolveTaskContext(undefined, { repoRoot: context.repoRoot });
187
- if (!resolved.ok) throw new Error(`${resolved.code}: ${resolved.message}`);
188
- return { ...options, taskId: resolved.taskId };
189
- }
190
-
191
- function domainOptions(
192
- context: TaskControlExecutionContext,
193
- options: Omit<OrchestrationOptions, 'repoRoot'> | undefined
194
- ): OrchestrationOptions {
195
- return {
196
- ...options,
197
- repoRoot: context.repoRoot
198
- };
199
- }
200
-
201
129
  function lifecycleTaskId(request: TaskLifecycleControlRequest, repoRoot: string): string | null {
202
130
  if (request.intent === 'restore') return TASK_ID_RE.test(request.taskRef) ? request.taskRef : null;
203
131
  try {
@@ -211,23 +139,10 @@ function lifecycleTaskId(request: TaskLifecycleControlRequest, repoRoot: string)
211
139
  async function applyLifecycleWithAuthority(
212
140
  context: TaskControlExecutionContext,
213
141
  request: TaskLifecycleControlRequest
214
- ): Promise<TaskLifecycleResult | LifecycleRecoveryResult> {
142
+ ): Promise<TaskLifecycleResult> {
215
143
  const taskId = lifecycleTaskId(request, context.repoRoot);
216
144
  const controlRoot = taskId ? controlRootForTask(context, taskId) : undefined;
217
- const execute = async (): Promise<TaskLifecycleResult | LifecycleRecoveryResult> => {
218
- if (request.intent === 'recover-started') {
219
- const adapter = isAgentClientId(request.agent)
220
- ? getAgentClientAdapter(request.agent).orchestrationAdapter
221
- : undefined;
222
- if (!adapter?.recoverStarted) {
223
- return {
224
- status: 'no-op', changed: false, targetState: 'active',
225
- requestRef: request.taskRef, intent: 'recover-started', taskId: null,
226
- receiptId: null, childId: null, error: null
227
- };
228
- }
229
- return adapter.recoverStarted(request as LifecycleRecoveryRequest, { repoRoot: context.repoRoot });
230
- }
145
+ const execute = async (): Promise<TaskLifecycleResult> => {
231
146
  return applyTaskLifecycle(request, {
232
147
  repoRoot: context.repoRoot,
233
148
  ...(controlRoot ? { controlRoot } : {}),
@@ -248,94 +163,14 @@ function controlRootForTask(context: TaskControlExecutionContext, taskId: string
248
163
  }).root;
249
164
  }
250
165
 
251
- function orchestration(
252
- context: TaskControlExecutionContext,
253
- operation: Extract<TaskControlOperation, { family: 'task-orchestration' }>
254
- ): OrchestrationResult | Promise<OrchestrationResult> {
255
- const taskRef = boundTaskRef(context, operation.taskRef);
256
- const input = operation.input;
257
- const options = domainOptions(context, operation.options);
258
- switch (operation.intent) {
259
- case 'begin-or-resume':
260
- return beginOrResumeOrchestration(taskRef, {
261
- ...options,
262
- client: input.client as AgentClientId,
263
- maxSteps: input.maxSteps as number | undefined,
264
- modelPolicy: input.modelPolicy as OrchestrationOptions['modelPolicy']
265
- });
266
- case 'route': return routeOrchestration(taskRef, options);
267
- case 'status': return statusOrchestration(taskRef, options);
268
- case 'prepare': return prepareTaskOrchestration(context, { ...operation, taskRef }, options);
269
- case 'dispatch': return dispatchOrchestrationDelegation(taskRef, options);
270
- case 'await-activation':
271
- return awaitOrchestrationDelegationActivation(taskRef, input.event as never, options);
272
- case 'recover-prepared': return recoverPreparedOrchestrationDelegation(taskRef, options);
273
- case 'hook-start':
274
- return input.auto === true
275
- ? activateMatchingOrchestrationDelegation(
276
- input.client as AgentClientId, input.event as never, autoTaskOptions(context, options)
277
- )
278
- : activateOrchestrationDelegation(taskRef, input.event as never, options);
279
- case 'hook-stop':
280
- return input.auto === true
281
- ? sealMatchingOrchestrationDelegation(
282
- input.client as AgentClientId, input.event as never, autoTaskOptions(context, options)
283
- )
284
- : sealOrchestrationDelegation(taskRef, input.event as never, undefined, options);
285
- case 'advance': return advanceOrchestration(taskRef, options);
286
- case 'pause':
287
- return pauseOrchestration(
288
- taskRef,
289
- input.code as string,
290
- input.message as string,
291
- input.recoverable as boolean,
292
- options
293
- );
294
- }
295
- }
296
-
297
- function prepareTaskOrchestration(
298
- context: TaskControlExecutionContext,
299
- operation: Extract<TaskControlOperation, { family: 'task-orchestration' }>,
300
- options: OrchestrationOptions
301
- ): OrchestrationResult | Promise<OrchestrationResult> {
302
- const input = operation.input;
303
- const prepareInput = {
304
- client: input.client as AgentClientId,
305
- requestedModel: input.requestedModel as string | undefined,
306
- requestedReasoningEffort: input.requestedReasoningEffort as string | undefined,
307
- };
308
- const prepareDelegation = getAgentClientAdapter(prepareInput.client).orchestrationAdapter?.prepareDelegation;
309
- return prepareDelegation
310
- ? prepareDelegation(operation.taskRef, prepareInput, {
311
- repoRoot: context.repoRoot,
312
- orchestrationOptions: options,
313
- })
314
- : prepareOrchestrationDelegation(operation.taskRef, prepareInput, options);
315
- }
316
-
317
- function orchestrationFailure(error: unknown): OrchestrationResult {
318
- if (error instanceof OrchestrationStateError) {
319
- return {
320
- status: 'failed', changed: false, taskId: error.taskId, run: null, next: null,
321
- error: { code: error.code, message: error.message }
322
- };
323
- }
324
- throw error;
325
- }
326
-
327
166
  export function dispatchTaskControlOperation(
328
167
  context: TaskControlExecutionContext,
329
168
  operation: Extract<TaskControlOperation, { family: 'task-lifecycle' }>
330
- ): Promise<TaskLifecycleResult | LifecycleRecoveryResult>;
169
+ ): Promise<TaskLifecycleResult>;
331
170
  export function dispatchTaskControlOperation(
332
171
  context: TaskControlExecutionContext,
333
172
  operation: Extract<TaskControlOperation, { family: 'task-finalization' }>
334
173
  ): Promise<TaskFinalizationResult>;
335
- export function dispatchTaskControlOperation(
336
- context: TaskControlExecutionContext,
337
- operation: Extract<TaskControlOperation, { family: 'task-orchestration' }>
338
- ): OrchestrationResult | Promise<OrchestrationResult>;
339
174
  export function dispatchTaskControlOperation(
340
175
  context: TaskControlExecutionContext,
341
176
  operation: TaskControlOperation
@@ -389,12 +224,7 @@ export function dispatchTaskControlOperation(
389
224
  }
390
225
  });
391
226
  }
392
- try {
393
- const result = orchestration(context, operation);
394
- return result instanceof Promise ? result.catch(orchestrationFailure) : result;
395
- } catch (error) {
396
- return orchestrationFailure(error);
397
- }
227
+ throw new Error('TASK_CONTROL_OPERATION_INVALID: unsupported operation family');
398
228
  }
399
229
 
400
230
  export function assertTaskControlOperation(operation: TaskControlOperation): void {
@@ -410,9 +240,6 @@ export function assertTaskControlOperation(operation: TaskControlOperation): voi
410
240
  }
411
241
  return;
412
242
  }
413
- if (!operation.taskRef || !operation.intent || !operation.input || typeof operation.input !== 'object' || Array.isArray(operation.input)) {
414
- throw new Error('TASK_CONTROL_OPERATION_INVALID: orchestration operation is invalid');
415
- }
416
243
  }
417
244
 
418
245
  function operationInvalid(message: string): never {
@@ -421,20 +248,11 @@ function operationInvalid(message: string): never {
421
248
 
422
249
  const LIFECYCLE_FLAGS = new Set([
423
250
  '--agent', '--reason', '--unblock-condition', '--note', '--alert-number', '--staging-dir', '--issue-number',
424
- '--auto', '--dry-run'
251
+ '--dry-run'
425
252
  ]);
426
253
 
427
254
  const FINALIZATION_FLAGS = new Set(['--agent']);
428
255
 
429
- const ORCHESTRATION_FLAGS = new Set([
430
- '--agent', '--max-steps', '--executor-model', '--executor-reasoning-effort', '--reviewer-model',
431
- '--reviewer-reasoning-effort', '--client', '--requested-model', '--requested-reasoning-effort',
432
- '--parent-id', '--before-fingerprint', '--stage', '--round', '--artifact', '--role',
433
- '--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
434
- '--model-fallback-reason', '--reasoning-effort-fallback-reason', '--exit-code', '--after-fingerprint',
435
- '--changed-paths', '--code', '--message', '--recoverable'
436
- ]);
437
-
438
256
  function parseValues(
439
257
  args: readonly string[],
440
258
  start: number,
@@ -443,7 +261,7 @@ function parseValues(
443
261
  const values: Record<string, string | boolean> = {};
444
262
  for (let index = start; index < args.length; index += 1) {
445
263
  const flag = args[index]!;
446
- if (flag === '--dry-run' || flag === '--auto') {
264
+ if (flag === '--dry-run') {
447
265
  if (!flags.has(flag)) operationInvalid(`unknown option '${flag}'`);
448
266
  if (values[flag] !== undefined) operationInvalid(`duplicate option '${flag}'`);
449
267
  values[flag] = true;
@@ -463,13 +281,8 @@ function value(values: Record<string, string | boolean>, flag: string): string |
463
281
  return typeof current === 'string' ? current : undefined;
464
282
  }
465
283
 
466
- function required(values: Record<string, string | boolean>, flags: readonly string[]): void {
467
- const missing = flags.find((flag) => value(values, flag) === undefined);
468
- if (missing) operationInvalid(`option '${missing}' is required`);
469
- }
470
-
471
284
  export function parseTaskControlOperation(
472
- family: 'task-lifecycle' | 'task-orchestration' | 'task-finalization',
285
+ family: 'task-lifecycle' | 'task-finalization',
473
286
  args: readonly string[]
474
287
  ): TaskControlOperation {
475
288
  if (family === 'task-finalization') {
@@ -484,124 +297,21 @@ export function parseTaskControlOperation(
484
297
  if (args.length < 2) operationInvalid('task ref and intent are required');
485
298
  const taskRef = args[0]!;
486
299
  const intent = args[1]!;
487
- if (family === 'task-lifecycle') {
488
- if (intent === 'complete') operationInvalid('complete must use task-finalization');
489
- const values = parseValues(args, 2, LIFECYCLE_FLAGS);
490
- const agent = normalizeAgentToken(value(values, '--agent') ?? '');
491
- if (!agent) operationInvalid('lifecycle agent is invalid');
492
- const input: Record<string, unknown> = {
493
- taskRef,
494
- intent,
495
- agent,
496
- ...(value(values, '--reason') ? { reason: value(values, '--reason') } : {}),
497
- ...(value(values, '--unblock-condition') ? { unblockCondition: value(values, '--unblock-condition') } : {}),
498
- ...(value(values, '--note') ? { note: value(values, '--note') } : {}),
499
- ...(value(values, '--staging-dir') ? { stagingDir: value(values, '--staging-dir') } : {}),
500
- ...(value(values, '--alert-number') ? { alertNumber: Number(value(values, '--alert-number')) } : {}),
501
- ...(value(values, '--issue-number') ? { issueNumber: Number(value(values, '--issue-number')) } : {}),
502
- ...(values['--auto'] === true ? { auto: true } : {}),
503
- ...(values['--dry-run'] === true ? { dryRun: true } : {})
504
- };
505
- if (intent === 'recover-started') {
506
- const recoveryFlags = new Set(['--agent', '--auto']);
507
- for (const flag of Object.keys(values)) {
508
- if (!recoveryFlags.has(flag)) operationInvalid(`option '${flag}' is not supported for recover-started`);
509
- }
510
- if (values['--auto'] !== true) operationInvalid('--auto is required for recover-started');
511
- return { family, request: input as unknown as TaskLifecycleControlRequest };
512
- } else if (values['--auto'] !== undefined) {
513
- operationInvalid('--auto is only supported for recover-started');
514
- }
515
- return { family, request: input as unknown as TaskLifecycleControlRequest };
516
- }
517
-
518
- const values = parseValues(args, 2, ORCHESTRATION_FLAGS);
519
- const orchestrationIntents = new Set<TaskControlOrchestrationIntent>([
520
- 'begin-or-resume', 'route', 'prepare', 'dispatch', 'await-activation', 'recover-prepared',
521
- 'hook-start', 'hook-stop', 'advance', 'pause', 'status'
522
- ]);
523
- if (!orchestrationIntents.has(intent as TaskControlOrchestrationIntent)) {
524
- operationInvalid(`unknown orchestration intent '${intent}'`);
525
- }
526
- const client = value(values, '--client');
527
- if (client !== undefined && !isAgentClientId(client)) operationInvalid(`unknown client '${client}'`);
528
- const parsedIntent = intent as TaskControlOrchestrationIntent;
529
- const input: Record<string, unknown> = {};
530
- if (parsedIntent === 'begin-or-resume' || parsedIntent === 'prepare') {
531
- required(values, ['--client']);
532
- if (!client || !isAgentClientId(client)) operationInvalid(`unknown client '${client ?? ''}'`);
533
- input.client = client;
534
- }
535
- if (parsedIntent === 'begin-or-resume') {
536
- const maxSteps = value(values, '--max-steps');
537
- if (maxSteps !== undefined) {
538
- const parsed = Number(maxSteps);
539
- if (!Number.isInteger(parsed) || parsed < 1) operationInvalid('--max-steps must be a positive integer');
540
- input.maxSteps = parsed;
541
- }
542
- const policyFlags = ['--executor-model', '--executor-reasoning-effort', '--reviewer-model', '--reviewer-reasoning-effort'];
543
- const hasPolicy = policyFlags.some((flag) => value(values, flag) !== undefined);
544
- if (hasPolicy && policyFlags.some((flag) => value(values, flag) === undefined)) {
545
- operationInvalid('explicit model policy requires executor/reviewer model and reasoning effort');
546
- }
547
- if (hasPolicy) {
548
- input.modelPolicy = {
549
- executor: { model: value(values, '--executor-model'), reasoningEffort: value(values, '--executor-reasoning-effort') },
550
- reviewer: { model: value(values, '--reviewer-model'), reasoningEffort: value(values, '--reviewer-reasoning-effort') }
551
- };
552
- }
553
- }
554
- if (parsedIntent === 'prepare') {
555
- input.requestedModel = value(values, '--requested-model');
556
- input.requestedReasoningEffort = value(values, '--requested-reasoning-effort');
557
- }
558
- if (parsedIntent === 'await-activation') {
559
- required(values, ['--stage', '--round', '--artifact', '--role']);
560
- const round = Number(value(values, '--round'));
561
- if (!Number.isSafeInteger(round) || round < 1) operationInvalid('--round must be a positive integer');
562
- const role = value(values, '--role');
563
- if (role !== 'executor' && role !== 'reviewer') operationInvalid('--role must be executor or reviewer');
564
- input.event = { stage: value(values, '--stage'), round, artifact: value(values, '--artifact'), role };
565
- }
566
- if (parsedIntent === 'hook-start') {
567
- required(values, ['--native-agent', '--child-id', '--parent-id']);
568
- if (taskRef === 'auto') required(values, ['--client']);
569
- input.auto = taskRef === 'auto';
570
- input.client = value(values, '--client');
571
- input.event = {
572
- nativeAgent: value(values, '--native-agent'), childId: value(values, '--child-id'), parentId: value(values, '--parent-id'),
573
- spawnMode: value(values, '--spawn-mode'), actualModel: value(values, '--actual-model'),
574
- actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
575
- reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
576
- };
577
- }
578
- if (parsedIntent === 'hook-stop') {
579
- input.auto = taskRef === 'auto';
580
- if (input.auto) {
581
- required(values, ['--client', '--native-agent', '--child-id']);
582
- input.client = value(values, '--client');
583
- input.event = {
584
- nativeAgent: value(values, '--native-agent'), childId: value(values, '--child-id'), actualModel: value(values, '--actual-model'),
585
- actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
586
- reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
587
- };
588
- } else {
589
- required(values, ['--child-id', '--exit-code', '--after-fingerprint']);
590
- const exitCode = Number(value(values, '--exit-code'));
591
- if (!Number.isInteger(exitCode)) operationInvalid('--exit-code must be an integer');
592
- input.event = {
593
- childId: value(values, '--child-id'), exitCode, afterFingerprint: value(values, '--after-fingerprint'),
594
- changedPaths: value(values, '--changed-paths')?.split(',').filter(Boolean) ?? [], actualModel: value(values, '--actual-model'),
595
- actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
596
- reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
597
- };
598
- }
599
- }
600
- if (parsedIntent === 'pause') {
601
- required(values, ['--code', '--message', '--recoverable']);
602
- const recoverable = value(values, '--recoverable');
603
- if (recoverable !== 'true' && recoverable !== 'false') operationInvalid('--recoverable must be true or false');
604
- input.code = value(values, '--code'); input.message = value(values, '--message'); input.recoverable = recoverable === 'true';
605
- }
606
- return { family, taskRef, intent: parsedIntent, input };
300
+ if (intent === 'complete') operationInvalid('complete must use task-finalization');
301
+ const values = parseValues(args, 2, LIFECYCLE_FLAGS);
302
+ const agent = normalizeAgentToken(value(values, '--agent') ?? '');
303
+ if (!agent) operationInvalid('lifecycle agent is invalid');
304
+ const request: Record<string, unknown> = {
305
+ taskRef,
306
+ intent,
307
+ agent,
308
+ ...(value(values, '--reason') ? { reason: value(values, '--reason') } : {}),
309
+ ...(value(values, '--unblock-condition') ? { unblockCondition: value(values, '--unblock-condition') } : {}),
310
+ ...(value(values, '--note') ? { note: value(values, '--note') } : {}),
311
+ ...(value(values, '--staging-dir') ? { stagingDir: value(values, '--staging-dir') } : {}),
312
+ ...(value(values, '--alert-number') ? { alertNumber: Number(value(values, '--alert-number')) } : {}),
313
+ ...(value(values, '--issue-number') ? { issueNumber: Number(value(values, '--issue-number')) } : {}),
314
+ ...(values['--dry-run'] === true ? { dryRun: true } : {})
315
+ };
316
+ return { family, request: request as unknown as TaskLifecycleControlRequest };
607
317
  }
@@ -51,7 +51,7 @@ export type ControlRecoveryDecision = Readonly<{
51
51
  reasonCode: string;
52
52
  }>;
53
53
 
54
- const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'close-codescan', 'close-dependabot', 'restore', 'recover-started'] as const;
54
+ const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'close-codescan', 'close-dependabot', 'restore'] as const;
55
55
  export const SANDBOX_CONTROL_RECOVERY_OPERATIONS: readonly ControlRecoveryOperation[] = Object.freeze([
56
56
  ...LIFECYCLE_INTENTS.map((intent) => ({ family: 'task-lifecycle' as const, intent, class: 'lifecycle-mutation' })),
57
57
  { family: 'task-create', intent: 'create', class: 'task-create' }
@@ -73,13 +73,10 @@ function bindingMatchesResult(binding: ControlRecoveryBinding, result: Readonly<
73
73
  }
74
74
 
75
75
  function domainEvidenceMatches(
76
- operation: ControlRecoveryOperation,
77
- result: Readonly<Record<string, unknown>>,
78
76
  domain: Readonly<Record<string, unknown>> | null | undefined
79
77
  ): boolean {
80
78
  if (!domain) return false;
81
79
  if (domain.consistent !== true) return false;
82
- if (operation.family === 'task-lifecycle' && operation.intent === 'recover-started') return false;
83
80
  return true;
84
81
  }
85
82
 
@@ -110,7 +107,7 @@ export function classifySandboxControlRecovery(input: ControlRecoveryInput): Con
110
107
  if (result.changed === null) {
111
108
  return { outcome: 'unknown', responseReconstructable: false, reasonCode: 'RECOVERY_RESULT_CHANGE_FLAG_MISSING' };
112
109
  }
113
- if (!domainEvidenceMatches(input.operation, result, input.domain)) {
110
+ if (!domainEvidenceMatches(input.domain)) {
114
111
  if (input.journal?.exists && (input.journal.completedSteps?.length ?? 0) > 0) {
115
112
  return { outcome: 'in-progress', responseReconstructable: false, reasonCode: 'RECOVERY_DOMAIN_EVIDENCE_INCOMPLETE' };
116
113
  }
@@ -9,6 +9,7 @@ import { readDeliveryDefaults, validateBaseRef, validateRemote } from './deliver
9
9
  import { buildUnboundFact, encodePrDeliveryFact } from './pr-delivery-fact.ts';
10
10
  import { CANDIDATE_COLUMNS, CONSTRAINT_COLUMNS, parseTaskQualification } from './qualification-audit.ts';
11
11
  import { enumerateAllTaskDirs } from './resolve-ref.ts';
12
+ import { serializeLifecycleExecution } from './lifecycle-execution.ts';
12
13
  import { parseTaskFrontmatter } from './frontmatter.ts';
13
14
  import { AGENT_TOKEN_VALUES, type AgentToken } from '../agent-clients/tokens.ts';
14
15
  import { resolveProjectTaskWorkspaceRoot } from './workspace-root.ts';
@@ -59,7 +60,6 @@ function payloadError(message: string): never {
59
60
 
60
61
  function exactKeys(value: Record<string, unknown>, expected: readonly string[], label: string, optional: readonly string[] = []): void {
61
62
  const actual = Object.keys(value).sort();
62
- const wanted = [...expected].sort();
63
63
  const allowed = new Set([...expected, ...optional]);
64
64
  if (actual.some((key) => !allowed.has(key))) {
65
65
  payloadError(`${label} has unknown or missing fields`);
@@ -170,10 +170,6 @@ function taskIdFor(date: Date): string {
170
170
  return `TASK-${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`;
171
171
  }
172
172
 
173
- function yamlString(value: string): string {
174
- return JSON.stringify(value);
175
- }
176
-
177
173
  function markdownBlock(value: string): string {
178
174
  return value.split(/\r?\n/).map((line) => /^(?:#{1,6}\s|```)/.test(line) ? `\\${line}` : line).join('\n');
179
175
  }
@@ -289,6 +285,7 @@ function renderTask(params: Readonly<{
289
285
  'target_date:',
290
286
  'current_step: requirement-analysis',
291
287
  `assigned_to: ${candidate.agent}`,
288
+ `lifecycle_execution: ${JSON.stringify(serializeLifecycleExecution([]))}`,
292
289
  `pr_delivery_fact: ${JSON.stringify(encodePrDeliveryFact(buildUnboundFact()))}`,
293
290
  `delivery_remote: ${candidate.deliveryRemote ?? params.delivery.remote}`,
294
291
  `delivery_base_ref: ${candidate.deliveryBaseRef ?? params.delivery.baseRef}`,
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
 
3
- import { appendActivityEntry, locateActivityLog } from './activity-log.ts';
3
+ import { activityWarnings, appendActivityEntry, locateActivityLog } from './activity-log.ts';
4
4
  import { isDecisionItem, listDecisionItems, selectDecisionItem } from './decision-items.ts';
5
5
  import {
6
6
  createImplementationInput,
@@ -31,6 +31,7 @@ type HumanDecisionResult = {
31
31
  taskId: string | null; ledgerId: string | null; recordId: string | null;
32
32
  implementationInputId: string | null; operations: readonly TaskOperationSummary[];
33
33
  error: { code: string; message: string } | null;
34
+ warnings?: readonly { code: string; message: string }[];
34
35
  };
35
36
 
36
37
  const DECISION_ALIASES = ['人工裁决', 'Human Rulings', 'Human Decisions', 'Human Decision'] as const;
@@ -102,7 +103,7 @@ function applyHumanDecision(request: HumanDecisionRequest, options: TaskWriteOpt
102
103
  try {
103
104
  const replay = existingDecision(content, direct[0]!, request.decision.trim(), request.needsImplementation);
104
105
  if ('conflict' in replay) return failed('DECISION_CONFLICT', replay.conflict, resolved.taskId, direct[0]!.id);
105
- return { status: 'no-op', changed: false, taskId: resolved.taskId, ledgerId: direct[0]!.id, recordId: replay.recordId, implementationInputId: replay.implementationInputId, operations: [], error: null };
106
+ return { status: 'no-op', changed: false, taskId: resolved.taskId, ledgerId: direct[0]!.id, recordId: replay.recordId, implementationInputId: replay.implementationInputId, operations: [], error: null, warnings: activityWarnings(content) };
106
107
  } catch (error) { return failed('DECISION_DOCUMENT_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId, direct[0]!.id); }
107
108
  }
108
109
 
@@ -144,7 +145,6 @@ function applyHumanDecision(request: HumanDecisionRequest, options: TaskWriteOpt
144
145
  const decision = request.decision.trim();
145
146
  const record = `### ${recordId}\n\n- **原账本 ID**:${row.id}\n- **裁决时间**:${metadata.timestamp}\n- **裁决结果**:${decision}`;
146
147
  const activity = locateActivityLog(content);
147
- if (!activity) return failed('DECISION_ACTIVITY_MISSING', 'activity log section is missing or ambiguous', resolved.taskId, row.id);
148
148
  const mutations: TaskMutation[] = [
149
149
  {
150
150
  kind: 'table-row', action: 'upsert', sectionAliases: LEDGER_HEADINGS, columns: LEDGER_COLUMNS,
@@ -172,7 +172,7 @@ function applyHumanDecision(request: HumanDecisionRequest, options: TaskWriteOpt
172
172
  body: renderImplementationInputs(nextInputs)
173
173
  });
174
174
  }
175
- mutations.push({
175
+ if (activity) mutations.push({
176
176
  kind: 'section', aliases: ACTIVITY_ALIASES, heading: activity.heading,
177
177
  body: appendActivityEntry(activity, { time: metadata.timestamp, step: 'Human Decision', agent: 'human', note: `${row.id} decided → ${recordId}` })
178
178
  });
@@ -190,7 +190,7 @@ function applyHumanDecision(request: HumanDecisionRequest, options: TaskWriteOpt
190
190
  metadataProvider: () => metadata
191
191
  });
192
192
  if (writeResult.status === 'failed') return failed(writeResult.error.code, writeResult.error.message, writeResult.taskId, row.id);
193
- return { status: writeResult.status, changed: writeResult.changed, taskId: writeResult.taskId, ledgerId: row.id, recordId, implementationInputId, operations: writeResult.operations, error: null };
193
+ return { status: writeResult.status, changed: writeResult.changed, taskId: writeResult.taskId, ledgerId: row.id, recordId, implementationInputId, operations: writeResult.operations, error: null, warnings: activityWarnings(content) };
194
194
  }
195
195
 
196
196
  export { applyHumanDecision };
@@ -1,6 +1,5 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { execFileSync } from 'node:child_process';
4
3
 
5
4
  export type DeliveryTarget = Readonly<{
6
5
  remote: string;
@@ -82,49 +81,10 @@ function resolveDeliveryTarget(
82
81
  return bindDeliveryTarget({ defaults: defaults.value, existing, explicit });
83
82
  }
84
83
 
85
- function gitText(repoRoot: string, args: readonly string[]): string {
86
- return execFileSync('git', [...args], {
87
- cwd: repoRoot,
88
- encoding: 'utf8',
89
- stdio: ['ignore', 'pipe', 'pipe']
90
- }).trim();
91
- }
92
-
93
- function resolveTargetHead(repoRoot: string, target: DeliveryTarget): DeliveryTargetResult & { head?: string } {
94
- try {
95
- const output = gitText(repoRoot, ['ls-remote', '--refs', target.remote, `refs/heads/${target.baseRef}`]);
96
- const head = output.split(/\s+/)[0] ?? '';
97
- if (!/^[a-f0-9]{40}$/i.test(head)) {
98
- return { ok: false, code: 'DELIVERY_TARGET_UNAVAILABLE', message: `Delivery target ${target.remote}/${target.baseRef} is unavailable` };
99
- }
100
- try { gitText(repoRoot, ['cat-file', '-e', `${head}^{commit}`]); }
101
- catch {
102
- return { ok: false, code: 'DELIVERY_TARGET_OBJECT_MISSING', message: `Delivery target commit ${head} is not available locally` };
103
- }
104
- return { ok: true, value: target, head };
105
- } catch (error) {
106
- return { ok: false, code: 'DELIVERY_TARGET_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) };
107
- }
108
- }
109
-
110
- function resolveDiffBase(repoRoot: string, reviewedHead: string, targetHead: string): DiffBaseResult {
111
- try {
112
- const diffBase = gitText(repoRoot, ['merge-base', reviewedHead, targetHead]);
113
- if (!/^[a-f0-9]{40}$/i.test(diffBase)) {
114
- return { ok: false, code: 'DELIVERY_DIFF_BASE_UNAVAILABLE', message: 'Git returned an invalid diff base' };
115
- }
116
- return { ok: true, diffBase };
117
- } catch (error) {
118
- return { ok: false, code: 'DELIVERY_DIFF_BASE_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) };
119
- }
120
- }
121
-
122
84
  export {
123
85
  bindDeliveryTarget,
124
86
  readDeliveryDefaults,
125
87
  resolveDeliveryTarget,
126
- resolveTargetHead,
127
- resolveDiffBase,
128
88
  validateBaseRef,
129
89
  validateRemote
130
90
  };