@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
@@ -7,12 +7,12 @@ import { checkpointCommitMatches } from './commit-identity.js';
7
7
  import { resolveTaskContext, resolveTaskRef } from './resolve-ref.js';
8
8
  import { commitPushDecision } from './commit-policy.js';
9
9
  import { mergeOperationWarnings } from './operation-outcome.js';
10
- import { appendActivityEntry, locateActivityLog } from './activity-log.js';
10
+ import { activityWarnings, appendActivityEntry, locateActivityLog } from './activity-log.js';
11
11
  import { captureTaskWriteMetadata, writeTask } from './write.js';
12
12
  import { checkpointIntentDigest, readCheckpointIntent, removeCheckpointIntent, sameCheckpointIntent, updateCheckpointIntent, writeCheckpointIntent } from './commit-intent.js';
13
13
  const HEAD_REF = /^refs\/heads\/(.+)$/;
14
14
  function isCommitExecutionMode(value) {
15
- return value === 'direct' || value === 'orchestrated';
15
+ return value === 'direct';
16
16
  }
17
17
  function gitText(repoRoot, args) {
18
18
  return execFileSync('git', [...args], {
@@ -117,50 +117,43 @@ function validateCommon(input, branch) {
117
117
  }
118
118
  return null;
119
119
  }
120
- function syncTaskCommit(input, task, committedHead) {
120
+ // Log presentation only; checkpoint identity and recovery never depend on this projection.
121
+ function commitLogProjection(activity, timestamp, agent, commitNote) {
122
+ if (!activity)
123
+ return [];
124
+ let lastCommit = -1;
125
+ for (const [index, entry] of activity.entries.entries()) {
126
+ if (entry.step === 'Commit' && entry.note === commitNote)
127
+ lastCommit = index;
128
+ }
129
+ const reviewedAfter = activity.entries.slice(lastCommit + 1).some((entry) => /^Review Code \(Round \d+\)$/.test(entry.step));
130
+ if (lastCommit >= 0 && !reviewedAfter)
131
+ return [];
132
+ return [{ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: activity.heading,
133
+ body: appendActivityEntry(activity, { time: timestamp, step: 'Commit', agent, note: commitNote }) }];
134
+ }
135
+ function syncTaskCommit(input, task, committedHead, writeOptions = {}) {
121
136
  let content;
122
137
  try {
123
138
  content = fs.readFileSync(task.taskMdPath, 'utf8');
124
139
  const activity = locateActivityLog(content);
125
- if (!activity)
126
- return warning('TASK_STATUS_SYNC_FAILED', 'task has no unique Activity Log section', true, 'task', task.taskId, 'ACTION_REQUIRED');
127
140
  const metadata = captureTaskWriteMetadata();
128
141
  const commitNote = gitText(task.repoRoot, ['show', '-s', '--format=%h %s', committedHead]);
129
- let matchingCommitIndex = -1;
130
- for (let index = activity.entries.length - 1; index >= 0; index -= 1) {
131
- const entry = activity.entries[index];
132
- if (entry.step === 'Commit' && entry.note === commitNote) {
133
- matchingCommitIndex = index;
134
- break;
135
- }
136
- }
137
- const reviewedAfterCommit = matchingCommitIndex >= 0 && activity.entries
138
- .slice(matchingCommitIndex + 1)
139
- .some((entry) => /^Review Code \(Round \d+\)$/.test(entry.step));
140
- const alreadyLogged = matchingCommitIndex >= 0 && !reviewedAfterCommit;
141
- const mutations = [];
142
- if (!alreadyLogged)
143
- mutations.push({
144
- kind: 'section',
145
- aliases: ['活动日志', 'Activity Log'],
146
- heading: activity.heading,
147
- body: appendActivityEntry(activity, { time: metadata.timestamp, step: 'Commit', agent: input.agent, note: commitNote })
148
- });
142
+ const mutations = commitLogProjection(activity, metadata.timestamp, input.agent, commitNote);
149
143
  const frontmatter = {
150
144
  assigned_to: input.agent,
151
145
  checkpoint_commit: committedHead
152
146
  };
153
147
  mutations.push({ kind: 'frontmatter', set: frontmatter });
154
- if (mutations.length === 0)
155
- return null;
156
148
  const written = writeTask({
157
149
  taskRef: task.taskId,
158
150
  expectedState: 'active',
159
151
  mutations
160
- }, { repoRoot: task.repoRoot, metadataProvider: () => metadata });
152
+ }, { ...writeOptions, repoRoot: task.repoRoot, metadataProvider: () => metadata });
161
153
  if (written.status === 'failed')
162
154
  return warning('TASK_STATUS_SYNC_FAILED', written.error.message, true, 'task', task.taskId, 'ACTION_REQUIRED');
163
- return null;
155
+ const logWarning = activityWarnings(content)[0];
156
+ return logWarning ? warning(logWarning.code, logWarning.message, true, 'task', task.taskId, 'IMPORTANT') : null;
164
157
  }
165
158
  catch (error) {
166
159
  return warning('TASK_STATUS_SYNC_FAILED', error instanceof Error ? error.message : String(error), true, 'task', task.taskId, 'ACTION_REQUIRED');
@@ -183,12 +176,10 @@ function checkpointIdentity(input, task, delivery) {
183
176
  function checkpointTimestamp() {
184
177
  return new Date().toISOString();
185
178
  }
186
- function executeCommitOperationCore(input, task, mode) {
179
+ function executeCommitOperationCore(input, task, mode, writeOptions) {
187
180
  const inspected = inspectGitWorkflow(input.cwd);
188
181
  if (!inspected.snapshot)
189
182
  return failure(input, mode, task?.taskId ?? null, 'GIT_INSPECT_FAILED', 'Unable to inspect Git repository');
190
- if (mode === 'orchestrated')
191
- return failure(input, mode, task?.taskId ?? null, 'ORCHESTRATED_COMMIT_REMOVED', 'Orchestrated commit is no longer a lifecycle stage; use local checkpoint delivery from code-task', 'blocked', inspected.snapshot);
192
183
  const branch = inspected.snapshot.branch;
193
184
  const commonError = validateCommon(input, branch);
194
185
  if (commonError)
@@ -380,13 +371,13 @@ function executeCommitOperationCore(input, task, mode) {
380
371
  }
381
372
  if (task && (committed.status === 'applied' || committed.status === 'no-op')) {
382
373
  const committedHead = checkpointCommittedHead ?? committed.snapshot?.head ?? gitText(task.repoRoot, ['rev-parse', 'HEAD']);
383
- const taskWarning = syncTaskCommit(input, task, committedHead);
374
+ const taskWarning = syncTaskCommit(input, task, committedHead, writeOptions);
384
375
  if (taskWarning) {
385
376
  warnings.push(taskWarning);
386
377
  status = 'applied';
387
378
  result = 'committed_with_warnings';
388
379
  }
389
- if (delivery.mode === 'local' && !taskWarning && pendingIntent && checkpointCommittedHead) {
380
+ if (delivery.mode === 'local' && taskWarning?.code !== 'TASK_STATUS_SYNC_FAILED' && pendingIntent && checkpointCommittedHead) {
390
381
  const synced = updateCheckpointIntent(pendingIntent, {
391
382
  state: 'synced', committedHead: checkpointCommittedHead, updatedAt: checkpointTimestamp()
392
383
  });
@@ -406,7 +397,7 @@ function executeCommitOperationCore(input, task, mode) {
406
397
  error: null
407
398
  };
408
399
  }
409
- function executeCommitOperation(input) {
400
+ function executeCommitOperation(input, writeOptions = {}) {
410
401
  if (input.mode !== undefined && !isCommitExecutionMode(input.mode))
411
402
  return {
412
403
  status: 'blocked',
@@ -417,7 +408,7 @@ function executeCommitOperation(input) {
417
408
  warnings: [],
418
409
  snapshot: null,
419
410
  operations: [],
420
- error: { code: 'COMMIT_MODE_INVALID', message: 'commit mode must be direct or orchestrated' }
411
+ error: { code: 'COMMIT_MODE_INVALID', message: 'commit mode must be direct' }
421
412
  };
422
413
  const mode = input.mode ?? 'direct';
423
414
  let normalizedInput;
@@ -431,10 +422,8 @@ function executeCommitOperation(input) {
431
422
  if (resolved.kind === 'error')
432
423
  return resolved.result;
433
424
  const task = resolved.kind === 'bound' ? resolved.task : null;
434
- if (mode === 'orchestrated' && !task)
435
- return failure(normalizedInput, mode, null, 'ORCHESTRATION_TASK_REQUIRED', 'orchestrated commit requires a task context', 'blocked');
436
425
  try {
437
- return executeCommitOperationCore(normalizedInput, task, mode);
426
+ return executeCommitOperationCore(normalizedInput, task, mode, writeOptions);
438
427
  }
439
428
  catch (error) {
440
429
  const code = 'COMMIT_OPERATION_FAILED';
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
+ import path from 'node:path';
2
3
  import { canonicalSemanticDigest } from './artifact-operations.js';
3
- import { inspectActivityLog, pairEntries } from './activity-log.js';
4
4
  import { parseTypedTaskFrontmatter } from './frontmatter.js';
5
5
  import { parseArtifactName } from './artifact-name.js';
6
6
  import { sha256File } from './artifact-receipts.js';
@@ -23,56 +23,69 @@ export function parseCompletionFacts(value) {
23
23
  return [];
24
24
  }
25
25
  }
26
- export function hasArtifactCompletionFact(taskContent, artifactPath, event) {
26
+ function completionEvent(family) {
27
+ if (family === 'validation-run')
28
+ return 'validation-run.completed';
29
+ if (family === 'analysis')
30
+ return 'analyze.completed';
31
+ if (family === 'review-analysis')
32
+ return 'review-analysis.completed';
33
+ if (family === 'plan')
34
+ return 'plan.completed';
35
+ if (family === 'review-plan')
36
+ return 'review-plan.completed';
37
+ if (family === 'code')
38
+ return 'code.completed';
39
+ if (family === 'review-code')
40
+ return 'review-code.completed';
41
+ return null;
42
+ }
43
+ /** Validates an artifact's own completion fact and output evidence. */
44
+ export function hasValidArtifactCompletion(taskContent, taskDir, artifact, event) {
27
45
  try {
28
- const frontmatter = parseTypedTaskFrontmatter(taskContent);
29
- const output = artifactPath.split(/[\\/]/u).at(-1) ?? '';
30
- const content = fs.readFileSync(artifactPath, 'utf8');
31
- const outputSha256 = sha256File(artifactPath);
32
- const semanticDigest = canonicalSemanticDigest(content);
33
- return parseCompletionFacts(frontmatter.completion_facts).some((fact) => fact.event === event && fact.output === output
34
- && fact.outputSha256 === outputSha256 && fact.semanticDigest === semanticDigest
35
- && fact.requestId.length > 0);
46
+ const fact = findCompletionFact(taskContent, artifact, event);
47
+ return Boolean(fact && validateOutput(taskDir, artifact, fact));
36
48
  }
37
49
  catch {
38
50
  return false;
39
51
  }
40
52
  }
41
- export function hasArtifactCompletionLog(taskContent, artifact, event) {
42
- return artifactCompletionOrder(taskContent, artifact, event) !== null;
53
+ /** Distinguishes an invalidated completion fact from a round that has never completed. */
54
+ export function hasArtifactCompletionRecord(taskContent, artifact, event) {
55
+ try {
56
+ const raw = parseTypedTaskFrontmatter(taskContent).completion_facts;
57
+ if (raw === undefined)
58
+ return false;
59
+ if (typeof raw !== 'string')
60
+ return true;
61
+ if (raw.trim() === '')
62
+ return false;
63
+ const parsed = JSON.parse(raw);
64
+ if (!Array.isArray(parsed))
65
+ return true;
66
+ return parsed.some((fact) => fact && typeof fact === 'object' && !Array.isArray(fact)
67
+ && fact.event === event
68
+ && fact.output === artifact);
69
+ }
70
+ catch {
71
+ return true;
72
+ }
43
73
  }
44
- /** Returns the stable Activity Log position of a paired completion row. */
45
- export function artifactCompletionOrder(taskContent, artifact, event) {
74
+ function findCompletionFact(taskContent, artifact, event) {
46
75
  const identity = parseArtifactName(artifact);
47
- if (!identity)
76
+ if (!identity || completionEvent(identity.family) !== event)
48
77
  return null;
49
- const family = event === 'analysis.completed' || event === 'analyze.completed' ? 'analysis'
50
- : event === 'review-analysis.completed' ? 'review-analysis'
51
- : event === 'plan.completed' ? 'plan'
52
- : event === 'review-plan.completed' ? 'review-plan'
53
- : event === 'code.completed' ? 'code'
54
- : event === 'review-code.completed' ? 'review-code' : null;
55
- if (!family || family !== identity.family)
56
- return null;
57
- const action = family === 'analysis' ? 'Analyze Task'
58
- : family === 'review-analysis' ? 'Review Analysis'
59
- : family === 'plan' ? 'Plan Task'
60
- : family === 'review-plan' ? 'Review Plan'
61
- : family === 'code' ? 'Code Task' : 'Review Code';
62
- const { section, invalidEntries } = inspectActivityLog(taskContent);
63
- if (!section || invalidEntries.length > 0)
64
- return null;
65
- const ordered = section.entries.map((entry, sourceOrder) => ({ entry, sourceOrder }))
66
- .sort((left, right) => Date.parse(left.entry.time.replace(' ', 'T')) - Date.parse(right.entry.time.replace(' ', 'T')) || left.sourceOrder - right.sourceOrder);
67
- const entries = ordered.map(({ entry }) => entry);
68
- const roundPattern = new RegExp(`^${action} \\(Round ${identity.round}(?:, [^)]+)?\\)$`);
69
- const row = pairEntries(entries).find((candidate) => candidate.started !== ''
70
- && candidate.done !== '' && roundPattern.test(candidate.step)
71
- && candidate.note.includes(`→ ${artifact}`));
72
- if (!row)
73
- return null;
74
- const doneIndex = ordered.findIndex(({ entry }) => entry.time === row.done
75
- && entry.step === row.step && entry.note === row.note);
76
- return doneIndex < 0 ? null : doneIndex;
78
+ const fact = parseCompletionFacts(parseTypedTaskFrontmatter(taskContent).completion_facts)
79
+ .find((candidate) => candidate.event === event && candidate.output === artifact);
80
+ return fact && fact.requestId.length > 0 ? fact : null;
81
+ }
82
+ function validateOutput(taskDir, artifact, fact) {
83
+ const outputPath = path.join(taskDir, artifact);
84
+ const stat = fs.lstatSync(outputPath);
85
+ if (!stat.isFile() || stat.isSymbolicLink())
86
+ return false;
87
+ const content = fs.readFileSync(outputPath, 'utf8');
88
+ return sha256File(outputPath) === fact.outputSha256
89
+ && canonicalSemanticDigest(content) === fact.semanticDigest;
77
90
  }
78
91
  //# sourceMappingURL=completion-facts.js.map
@@ -1,24 +1,12 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { normalizeAgentToken } from '../agent-clients/tokens.js';
4
- import { isAgentClientId } from '../agent-clients/types.js';
5
4
  import { sandboxControlPaths } from '../sandbox/workspace-view.js';
6
- import { getAgentClientAdapter } from '../agent-clients/registry.js';
7
- import { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, advanceOrchestration, awaitOrchestrationDelegationActivation, beginOrResumeOrchestration, dispatchOrchestrationDelegation, OrchestrationStateError, pauseOrchestration, prepareOrchestrationDelegation, recoverPreparedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealOrchestrationDelegation, statusOrchestration } from './orchestration.js';
8
5
  import { applyTaskFinalization } from './finalization.js';
9
6
  import { applyTaskLifecycle } from './lifecycle.js';
10
- import { resolveTaskContext, resolveTaskRef, TASK_ID_RE } from './resolve-ref.js';
7
+ import { resolveTaskRef, TASK_ID_RE } from './resolve-ref.js';
11
8
  import { verifyTaskEvent } from './verification.js';
12
9
  import { releaseStaleShortIdRegistry } from './short-id.js';
13
- export function taskControlOperationKey(operation) {
14
- if (operation.family === 'task-finalization')
15
- return 'complete';
16
- if (operation.family === 'task-lifecycle')
17
- return operation.request.intent;
18
- return operation.intent === 'route'
19
- ? operation.input && operation.input.completed === true ? 'route.clean-completion' : 'route.read'
20
- : operation.intent;
21
- }
22
10
  function invalidContext(message) {
23
11
  throw new Error(`TASK_CONTROL_CONTEXT_INVALID: ${message}`);
24
12
  }
@@ -85,20 +73,6 @@ export function assertTaskControlExecutionContext(context) {
85
73
  function boundTaskRef(context, taskRef) {
86
74
  return context.source === 'sandbox-executor' ? context.taskId : taskRef;
87
75
  }
88
- function autoTaskOptions(context, options) {
89
- if (context.source === 'sandbox-executor')
90
- return { ...options, taskId: context.taskId };
91
- const resolved = resolveTaskContext(undefined, { repoRoot: context.repoRoot });
92
- if (!resolved.ok)
93
- throw new Error(`${resolved.code}: ${resolved.message}`);
94
- return { ...options, taskId: resolved.taskId };
95
- }
96
- function domainOptions(context, options) {
97
- return {
98
- ...options,
99
- repoRoot: context.repoRoot
100
- };
101
- }
102
76
  function lifecycleTaskId(request, repoRoot) {
103
77
  if (request.intent === 'restore')
104
78
  return TASK_ID_RE.test(request.taskRef) ? request.taskRef : null;
@@ -114,19 +88,6 @@ async function applyLifecycleWithAuthority(context, request) {
114
88
  const taskId = lifecycleTaskId(request, context.repoRoot);
115
89
  const controlRoot = taskId ? controlRootForTask(context, taskId) : undefined;
116
90
  const execute = async () => {
117
- if (request.intent === 'recover-started') {
118
- const adapter = isAgentClientId(request.agent)
119
- ? getAgentClientAdapter(request.agent).orchestrationAdapter
120
- : undefined;
121
- if (!adapter?.recoverStarted) {
122
- return {
123
- status: 'no-op', changed: false, targetState: 'active',
124
- requestRef: request.taskRef, intent: 'recover-started', taskId: null,
125
- receiptId: null, childId: null, error: null
126
- };
127
- }
128
- return adapter.recoverStarted(request, { repoRoot: context.repoRoot });
129
- }
130
91
  return applyTaskLifecycle(request, {
131
92
  repoRoot: context.repoRoot,
132
93
  ...(controlRoot ? { controlRoot } : {}),
@@ -147,62 +108,6 @@ function controlRootForTask(context, taskId) {
147
108
  identity: { mode: 'task-bound', taskId }
148
109
  }).root;
149
110
  }
150
- function orchestration(context, operation) {
151
- const taskRef = boundTaskRef(context, operation.taskRef);
152
- const input = operation.input;
153
- const options = domainOptions(context, operation.options);
154
- switch (operation.intent) {
155
- case 'begin-or-resume':
156
- return beginOrResumeOrchestration(taskRef, {
157
- ...options,
158
- client: input.client,
159
- maxSteps: input.maxSteps,
160
- modelPolicy: input.modelPolicy
161
- });
162
- case 'route': return routeOrchestration(taskRef, options);
163
- case 'status': return statusOrchestration(taskRef, options);
164
- case 'prepare': return prepareTaskOrchestration(context, { ...operation, taskRef }, options);
165
- case 'dispatch': return dispatchOrchestrationDelegation(taskRef, options);
166
- case 'await-activation':
167
- return awaitOrchestrationDelegationActivation(taskRef, input.event, options);
168
- case 'recover-prepared': return recoverPreparedOrchestrationDelegation(taskRef, options);
169
- case 'hook-start':
170
- return input.auto === true
171
- ? activateMatchingOrchestrationDelegation(input.client, input.event, autoTaskOptions(context, options))
172
- : activateOrchestrationDelegation(taskRef, input.event, options);
173
- case 'hook-stop':
174
- return input.auto === true
175
- ? sealMatchingOrchestrationDelegation(input.client, input.event, autoTaskOptions(context, options))
176
- : sealOrchestrationDelegation(taskRef, input.event, undefined, options);
177
- case 'advance': return advanceOrchestration(taskRef, options);
178
- case 'pause':
179
- return pauseOrchestration(taskRef, input.code, input.message, input.recoverable, options);
180
- }
181
- }
182
- function prepareTaskOrchestration(context, operation, options) {
183
- const input = operation.input;
184
- const prepareInput = {
185
- client: input.client,
186
- requestedModel: input.requestedModel,
187
- requestedReasoningEffort: input.requestedReasoningEffort,
188
- };
189
- const prepareDelegation = getAgentClientAdapter(prepareInput.client).orchestrationAdapter?.prepareDelegation;
190
- return prepareDelegation
191
- ? prepareDelegation(operation.taskRef, prepareInput, {
192
- repoRoot: context.repoRoot,
193
- orchestrationOptions: options,
194
- })
195
- : prepareOrchestrationDelegation(operation.taskRef, prepareInput, options);
196
- }
197
- function orchestrationFailure(error) {
198
- if (error instanceof OrchestrationStateError) {
199
- return {
200
- status: 'failed', changed: false, taskId: error.taskId, run: null, next: null,
201
- error: { code: error.code, message: error.message }
202
- };
203
- }
204
- throw error;
205
- }
206
111
  export function dispatchTaskControlOperation(context, operation) {
207
112
  assertTaskControlExecutionContext(context);
208
113
  assertTaskControlOperation(operation);
@@ -253,13 +158,7 @@ export function dispatchTaskControlOperation(context, operation) {
253
158
  }
254
159
  });
255
160
  }
256
- try {
257
- const result = orchestration(context, operation);
258
- return result instanceof Promise ? result.catch(orchestrationFailure) : result;
259
- }
260
- catch (error) {
261
- return orchestrationFailure(error);
262
- }
161
+ throw new Error('TASK_CONTROL_OPERATION_INVALID: unsupported operation family');
263
162
  }
264
163
  export function assertTaskControlOperation(operation) {
265
164
  if (operation.family === 'task-lifecycle') {
@@ -274,31 +173,20 @@ export function assertTaskControlOperation(operation) {
274
173
  }
275
174
  return;
276
175
  }
277
- if (!operation.taskRef || !operation.intent || !operation.input || typeof operation.input !== 'object' || Array.isArray(operation.input)) {
278
- throw new Error('TASK_CONTROL_OPERATION_INVALID: orchestration operation is invalid');
279
- }
280
176
  }
281
177
  function operationInvalid(message) {
282
178
  throw new Error(`TASK_CONTROL_OPERATION_INVALID: ${message}`);
283
179
  }
284
180
  const LIFECYCLE_FLAGS = new Set([
285
181
  '--agent', '--reason', '--unblock-condition', '--note', '--alert-number', '--staging-dir', '--issue-number',
286
- '--auto', '--dry-run'
182
+ '--dry-run'
287
183
  ]);
288
184
  const FINALIZATION_FLAGS = new Set(['--agent']);
289
- const ORCHESTRATION_FLAGS = new Set([
290
- '--agent', '--max-steps', '--executor-model', '--executor-reasoning-effort', '--reviewer-model',
291
- '--reviewer-reasoning-effort', '--client', '--requested-model', '--requested-reasoning-effort',
292
- '--parent-id', '--before-fingerprint', '--stage', '--round', '--artifact', '--role',
293
- '--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
294
- '--model-fallback-reason', '--reasoning-effort-fallback-reason', '--exit-code', '--after-fingerprint',
295
- '--changed-paths', '--code', '--message', '--recoverable'
296
- ]);
297
185
  function parseValues(args, start, flags) {
298
186
  const values = {};
299
187
  for (let index = start; index < args.length; index += 1) {
300
188
  const flag = args[index];
301
- if (flag === '--dry-run' || flag === '--auto') {
189
+ if (flag === '--dry-run') {
302
190
  if (!flags.has(flag))
303
191
  operationInvalid(`unknown option '${flag}'`);
304
192
  if (values[flag] !== undefined)
@@ -321,11 +209,6 @@ function value(values, flag) {
321
209
  const current = values[flag];
322
210
  return typeof current === 'string' ? current : undefined;
323
211
  }
324
- function required(values, flags) {
325
- const missing = flags.find((flag) => value(values, flag) === undefined);
326
- if (missing)
327
- operationInvalid(`option '${missing}' is required`);
328
- }
329
212
  export function parseTaskControlOperation(family, args) {
330
213
  if (family === 'task-finalization') {
331
214
  if (args.length !== 4 || args[1] !== 'complete' || args[2] !== '--agent' || !args[0] || !args[3]) {
@@ -341,140 +224,24 @@ export function parseTaskControlOperation(family, args) {
341
224
  operationInvalid('task ref and intent are required');
342
225
  const taskRef = args[0];
343
226
  const intent = args[1];
344
- if (family === 'task-lifecycle') {
345
- if (intent === 'complete')
346
- operationInvalid('complete must use task-finalization');
347
- const values = parseValues(args, 2, LIFECYCLE_FLAGS);
348
- const agent = normalizeAgentToken(value(values, '--agent') ?? '');
349
- if (!agent)
350
- operationInvalid('lifecycle agent is invalid');
351
- const input = {
352
- taskRef,
353
- intent,
354
- agent,
355
- ...(value(values, '--reason') ? { reason: value(values, '--reason') } : {}),
356
- ...(value(values, '--unblock-condition') ? { unblockCondition: value(values, '--unblock-condition') } : {}),
357
- ...(value(values, '--note') ? { note: value(values, '--note') } : {}),
358
- ...(value(values, '--staging-dir') ? { stagingDir: value(values, '--staging-dir') } : {}),
359
- ...(value(values, '--alert-number') ? { alertNumber: Number(value(values, '--alert-number')) } : {}),
360
- ...(value(values, '--issue-number') ? { issueNumber: Number(value(values, '--issue-number')) } : {}),
361
- ...(values['--auto'] === true ? { auto: true } : {}),
362
- ...(values['--dry-run'] === true ? { dryRun: true } : {})
363
- };
364
- if (intent === 'recover-started') {
365
- const recoveryFlags = new Set(['--agent', '--auto']);
366
- for (const flag of Object.keys(values)) {
367
- if (!recoveryFlags.has(flag))
368
- operationInvalid(`option '${flag}' is not supported for recover-started`);
369
- }
370
- if (values['--auto'] !== true)
371
- operationInvalid('--auto is required for recover-started');
372
- return { family, request: input };
373
- }
374
- else if (values['--auto'] !== undefined) {
375
- operationInvalid('--auto is only supported for recover-started');
376
- }
377
- return { family, request: input };
378
- }
379
- const values = parseValues(args, 2, ORCHESTRATION_FLAGS);
380
- const orchestrationIntents = new Set([
381
- 'begin-or-resume', 'route', 'prepare', 'dispatch', 'await-activation', 'recover-prepared',
382
- 'hook-start', 'hook-stop', 'advance', 'pause', 'status'
383
- ]);
384
- if (!orchestrationIntents.has(intent)) {
385
- operationInvalid(`unknown orchestration intent '${intent}'`);
386
- }
387
- const client = value(values, '--client');
388
- if (client !== undefined && !isAgentClientId(client))
389
- operationInvalid(`unknown client '${client}'`);
390
- const parsedIntent = intent;
391
- const input = {};
392
- if (parsedIntent === 'begin-or-resume' || parsedIntent === 'prepare') {
393
- required(values, ['--client']);
394
- if (!client || !isAgentClientId(client))
395
- operationInvalid(`unknown client '${client ?? ''}'`);
396
- input.client = client;
397
- }
398
- if (parsedIntent === 'begin-or-resume') {
399
- const maxSteps = value(values, '--max-steps');
400
- if (maxSteps !== undefined) {
401
- const parsed = Number(maxSteps);
402
- if (!Number.isInteger(parsed) || parsed < 1)
403
- operationInvalid('--max-steps must be a positive integer');
404
- input.maxSteps = parsed;
405
- }
406
- const policyFlags = ['--executor-model', '--executor-reasoning-effort', '--reviewer-model', '--reviewer-reasoning-effort'];
407
- const hasPolicy = policyFlags.some((flag) => value(values, flag) !== undefined);
408
- if (hasPolicy && policyFlags.some((flag) => value(values, flag) === undefined)) {
409
- operationInvalid('explicit model policy requires executor/reviewer model and reasoning effort');
410
- }
411
- if (hasPolicy) {
412
- input.modelPolicy = {
413
- executor: { model: value(values, '--executor-model'), reasoningEffort: value(values, '--executor-reasoning-effort') },
414
- reviewer: { model: value(values, '--reviewer-model'), reasoningEffort: value(values, '--reviewer-reasoning-effort') }
415
- };
416
- }
417
- }
418
- if (parsedIntent === 'prepare') {
419
- input.requestedModel = value(values, '--requested-model');
420
- input.requestedReasoningEffort = value(values, '--requested-reasoning-effort');
421
- }
422
- if (parsedIntent === 'await-activation') {
423
- required(values, ['--stage', '--round', '--artifact', '--role']);
424
- const round = Number(value(values, '--round'));
425
- if (!Number.isSafeInteger(round) || round < 1)
426
- operationInvalid('--round must be a positive integer');
427
- const role = value(values, '--role');
428
- if (role !== 'executor' && role !== 'reviewer')
429
- operationInvalid('--role must be executor or reviewer');
430
- input.event = { stage: value(values, '--stage'), round, artifact: value(values, '--artifact'), role };
431
- }
432
- if (parsedIntent === 'hook-start') {
433
- required(values, ['--native-agent', '--child-id', '--parent-id']);
434
- if (taskRef === 'auto')
435
- required(values, ['--client']);
436
- input.auto = taskRef === 'auto';
437
- input.client = value(values, '--client');
438
- input.event = {
439
- nativeAgent: value(values, '--native-agent'), childId: value(values, '--child-id'), parentId: value(values, '--parent-id'),
440
- spawnMode: value(values, '--spawn-mode'), actualModel: value(values, '--actual-model'),
441
- actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
442
- reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
443
- };
444
- }
445
- if (parsedIntent === 'hook-stop') {
446
- input.auto = taskRef === 'auto';
447
- if (input.auto) {
448
- required(values, ['--client', '--native-agent', '--child-id']);
449
- input.client = value(values, '--client');
450
- input.event = {
451
- nativeAgent: value(values, '--native-agent'), childId: value(values, '--child-id'), actualModel: value(values, '--actual-model'),
452
- actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
453
- reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
454
- };
455
- }
456
- else {
457
- required(values, ['--child-id', '--exit-code', '--after-fingerprint']);
458
- const exitCode = Number(value(values, '--exit-code'));
459
- if (!Number.isInteger(exitCode))
460
- operationInvalid('--exit-code must be an integer');
461
- input.event = {
462
- childId: value(values, '--child-id'), exitCode, afterFingerprint: value(values, '--after-fingerprint'),
463
- changedPaths: value(values, '--changed-paths')?.split(',').filter(Boolean) ?? [], actualModel: value(values, '--actual-model'),
464
- actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
465
- reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
466
- };
467
- }
468
- }
469
- if (parsedIntent === 'pause') {
470
- required(values, ['--code', '--message', '--recoverable']);
471
- const recoverable = value(values, '--recoverable');
472
- if (recoverable !== 'true' && recoverable !== 'false')
473
- operationInvalid('--recoverable must be true or false');
474
- input.code = value(values, '--code');
475
- input.message = value(values, '--message');
476
- input.recoverable = recoverable === 'true';
477
- }
478
- return { family, taskRef, intent: parsedIntent, input };
227
+ if (intent === 'complete')
228
+ operationInvalid('complete must use task-finalization');
229
+ const values = parseValues(args, 2, LIFECYCLE_FLAGS);
230
+ const agent = normalizeAgentToken(value(values, '--agent') ?? '');
231
+ if (!agent)
232
+ operationInvalid('lifecycle agent is invalid');
233
+ const request = {
234
+ taskRef,
235
+ intent,
236
+ agent,
237
+ ...(value(values, '--reason') ? { reason: value(values, '--reason') } : {}),
238
+ ...(value(values, '--unblock-condition') ? { unblockCondition: value(values, '--unblock-condition') } : {}),
239
+ ...(value(values, '--note') ? { note: value(values, '--note') } : {}),
240
+ ...(value(values, '--staging-dir') ? { stagingDir: value(values, '--staging-dir') } : {}),
241
+ ...(value(values, '--alert-number') ? { alertNumber: Number(value(values, '--alert-number')) } : {}),
242
+ ...(value(values, '--issue-number') ? { issueNumber: Number(value(values, '--issue-number')) } : {}),
243
+ ...(values['--dry-run'] === true ? { dryRun: true } : {})
244
+ };
245
+ return { family, request: request };
479
246
  }
480
247
  //# sourceMappingURL=control-authority.js.map
@@ -16,7 +16,7 @@ export function parseControlOutput(output) {
16
16
  export const SANDBOX_CONTROL_REQUIRED_COMPLETION_PHASES = Object.freeze([
17
17
  'completed', 'evidence-written', 'publish-authorized'
18
18
  ]);
19
- const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'close-codescan', 'close-dependabot', 'restore', 'recover-started'];
19
+ const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'close-codescan', 'close-dependabot', 'restore'];
20
20
  export const SANDBOX_CONTROL_RECOVERY_OPERATIONS = Object.freeze([
21
21
  ...LIFECYCLE_INTENTS.map((intent) => ({ family: 'task-lifecycle', intent, class: 'lifecycle-mutation' })),
22
22
  { family: 'task-create', intent: 'create', class: 'task-create' }
@@ -33,13 +33,11 @@ function bindingMatchesResult(binding, result) {
33
33
  && (result.taskId === undefined || result.taskId === binding.taskId)
34
34
  && (result.intentDigest === undefined || result.intentDigest === binding.intentDigest);
35
35
  }
36
- function domainEvidenceMatches(operation, result, domain) {
36
+ function domainEvidenceMatches(domain) {
37
37
  if (!domain)
38
38
  return false;
39
39
  if (domain.consistent !== true)
40
40
  return false;
41
- if (operation.family === 'task-lifecycle' && operation.intent === 'recover-started')
42
- return false;
43
41
  return true;
44
42
  }
45
43
  export function classifySandboxControlRecovery(input) {
@@ -71,7 +69,7 @@ export function classifySandboxControlRecovery(input) {
71
69
  if (result.changed === null) {
72
70
  return { outcome: 'unknown', responseReconstructable: false, reasonCode: 'RECOVERY_RESULT_CHANGE_FLAG_MISSING' };
73
71
  }
74
- if (!domainEvidenceMatches(input.operation, result, input.domain)) {
72
+ if (!domainEvidenceMatches(input.domain)) {
75
73
  if (input.journal?.exists && (input.journal.completedSteps?.length ?? 0) > 0) {
76
74
  return { outcome: 'in-progress', responseReconstructable: false, reasonCode: 'RECOVERY_DOMAIN_EVIDENCE_INCOMPLETE' };
77
75
  }