@fitlab-ai/agent-infra 0.11.15 → 0.12.1

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 (265) hide show
  1. package/bin/cli.ts +1 -1
  2. package/dist/bin/cli.js +1 -1
  3. package/dist/bin/internal-cli.js +6 -1
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +6 -6
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +8 -18
  6. package/dist/lib/agent-clients/adapters/codex-orchestration.js +1 -1
  7. package/dist/lib/decide.js +2 -7
  8. package/dist/lib/internal/cli-route-inventory.js +3 -0
  9. package/dist/lib/internal/manual-validation.js +19 -33
  10. package/dist/lib/internal/platform-comment.js +59 -9
  11. package/dist/lib/internal/task-activity.js +1 -12
  12. package/dist/lib/internal/task-event.js +1 -12
  13. package/dist/lib/internal/task-ledger.js +1 -12
  14. package/dist/lib/internal/task-operation-registry.js +2 -1
  15. package/dist/lib/internal/task-qualification.js +6 -15
  16. package/dist/lib/internal/task-review.js +3 -16
  17. package/dist/lib/internal/task-short-id.js +2 -1
  18. package/dist/lib/internal/task-verify.js +1 -11
  19. package/dist/lib/internal/task-warning.js +1 -12
  20. package/dist/lib/internal/task-workspace.js +43 -0
  21. package/dist/lib/merge.js +4 -3
  22. package/dist/lib/platform/issue-comments.js +373 -267
  23. package/dist/lib/platform/issue-summary-content.js +112 -0
  24. package/dist/lib/platform/pr-change-report.js +175 -26
  25. package/dist/lib/platform/pr-summary-content.js +54 -0
  26. package/dist/lib/platform/pr-summary.js +321 -296
  27. package/dist/lib/platform/pull-requests.js +3 -15
  28. package/dist/lib/platform/summary-content-pipeline.js +18 -0
  29. package/dist/lib/pr-review/evidence-grading.js +3 -2
  30. package/dist/lib/process-data/index.js +5 -4
  31. package/dist/lib/process-data/sources.js +6 -0
  32. package/dist/lib/run/index.js +3 -2
  33. package/dist/lib/sandbox/commands/create.js +5 -1
  34. package/dist/lib/sandbox/commands/enter.js +1 -1
  35. package/dist/lib/sandbox/commands/list-running.js +2 -1
  36. package/dist/lib/sandbox/control/client.js +8 -13
  37. package/dist/lib/sandbox/control/completed-reentry.js +2 -1
  38. package/dist/lib/sandbox/control/task-view.js +4 -2
  39. package/dist/lib/sandbox/mounts.js +4 -4
  40. package/dist/lib/sandbox/recovery.js +26 -16
  41. package/dist/lib/sandbox/removal.js +62 -12
  42. package/dist/lib/sandbox/task-resolver.js +9 -6
  43. package/dist/lib/sandbox/workspace-identity.js +6 -5
  44. package/dist/lib/sandbox/workspace-view.js +29 -22
  45. package/dist/lib/task/activity-intent.js +2 -12
  46. package/dist/lib/task/artifact-lifecycle.js +17 -11
  47. package/dist/lib/task/artifact-operations.js +41 -49
  48. package/dist/lib/task/capabilities.js +2 -2
  49. package/dist/lib/task/commands/ls.js +4 -3
  50. package/dist/lib/task/commands/status.js +1 -1
  51. package/dist/lib/task/commit-operation.js +6 -6
  52. package/dist/lib/task/control-authority.js +32 -32
  53. package/dist/lib/task/create-service.js +2 -4
  54. package/dist/lib/task/create.js +12 -65
  55. package/dist/lib/task/delegation-receipts.js +1 -1
  56. package/dist/lib/task/delivery.js +2 -8
  57. package/dist/lib/task/events.js +5 -31
  58. package/dist/lib/task/finalization.js +33 -29
  59. package/dist/lib/task/lifecycle.js +9 -48
  60. package/dist/lib/task/local-artifact-finalization.js +1 -2
  61. package/dist/lib/task/orchestration.js +24 -57
  62. package/dist/lib/task/platform-operation-recovery.js +87 -88
  63. package/dist/lib/task/resolve-ref.js +17 -12
  64. package/dist/lib/task/review-finalization.js +2 -35
  65. package/dist/lib/task/review-identity.js +3 -1
  66. package/dist/lib/task/short-id.js +10 -8
  67. package/dist/lib/task/verification-engine.js +19 -58
  68. package/dist/lib/task/workspace-root.js +59 -0
  69. package/dist/lib/task/workspace-snapshot.js +4 -3
  70. package/dist/lifecycle-build-manifest.json +3 -3
  71. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +6 -6
  72. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +8 -34
  73. package/lib/agent-clients/adapters/codex-orchestration.ts +1 -1
  74. package/lib/decide.ts +2 -7
  75. package/lib/internal/cli-route-inventory.ts +2 -0
  76. package/lib/internal/manual-validation.ts +20 -37
  77. package/lib/internal/platform-comment.ts +49 -6
  78. package/lib/internal/task-activity.ts +1 -10
  79. package/lib/internal/task-event.ts +1 -10
  80. package/lib/internal/task-ledger.ts +1 -10
  81. package/lib/internal/task-operation-registry.ts +2 -1
  82. package/lib/internal/task-qualification.ts +5 -11
  83. package/lib/internal/task-review.ts +3 -14
  84. package/lib/internal/task-short-id.ts +2 -1
  85. package/lib/internal/task-verify.ts +1 -9
  86. package/lib/internal/task-warning.ts +1 -10
  87. package/lib/internal/task-workspace.ts +39 -0
  88. package/lib/merge.ts +4 -3
  89. package/lib/platform/issue-comments.ts +478 -280
  90. package/lib/platform/issue-summary-content.ts +132 -0
  91. package/lib/platform/pr-change-report.ts +165 -20
  92. package/lib/platform/pr-summary-content.ts +60 -0
  93. package/lib/platform/pr-summary.ts +367 -269
  94. package/lib/platform/pull-requests.ts +3 -24
  95. package/lib/platform/summary-content-pipeline.ts +23 -0
  96. package/lib/pr-review/evidence-grading.ts +3 -2
  97. package/lib/process-data/index.ts +4 -3
  98. package/lib/process-data/sources.ts +6 -0
  99. package/lib/run/index.ts +3 -2
  100. package/lib/sandbox/commands/create.ts +5 -1
  101. package/lib/sandbox/commands/enter.ts +1 -1
  102. package/lib/sandbox/commands/list-running.ts +2 -1
  103. package/lib/sandbox/control/client.ts +7 -12
  104. package/lib/sandbox/control/completed-reentry.ts +2 -1
  105. package/lib/sandbox/control/task-view.ts +4 -2
  106. package/lib/sandbox/mounts.ts +4 -4
  107. package/lib/sandbox/recovery.ts +26 -18
  108. package/lib/sandbox/removal.ts +60 -27
  109. package/lib/sandbox/task-resolver.ts +9 -6
  110. package/lib/sandbox/workspace-identity.ts +6 -5
  111. package/lib/sandbox/workspace-view.ts +28 -20
  112. package/lib/task/activity-intent.ts +3 -17
  113. package/lib/task/artifact-lifecycle.ts +39 -11
  114. package/lib/task/artifact-operations.ts +28 -35
  115. package/lib/task/capabilities.ts +2 -2
  116. package/lib/task/commands/ls.ts +4 -3
  117. package/lib/task/commands/status.ts +1 -1
  118. package/lib/task/commit-operation.ts +5 -6
  119. package/lib/task/control-authority.ts +29 -35
  120. package/lib/task/create-service.ts +2 -4
  121. package/lib/task/create.ts +10 -51
  122. package/lib/task/delegation-receipts.ts +1 -1
  123. package/lib/task/delivery.ts +2 -10
  124. package/lib/task/events.ts +5 -32
  125. package/lib/task/finalization.ts +27 -30
  126. package/lib/task/lifecycle.ts +9 -50
  127. package/lib/task/local-artifact-finalization.ts +1 -4
  128. package/lib/task/orchestration.ts +31 -80
  129. package/lib/task/platform-operation-recovery.ts +70 -82
  130. package/lib/task/resolve-ref.ts +18 -12
  131. package/lib/task/review-finalization.ts +2 -52
  132. package/lib/task/review-identity.ts +3 -1
  133. package/lib/task/short-id.ts +10 -8
  134. package/lib/task/verification-engine.ts +20 -62
  135. package/lib/task/workspace-root.ts +78 -0
  136. package/lib/task/workspace-snapshot.ts +4 -3
  137. package/package.json +1 -1
  138. package/templates/.agents/QUICKSTART.en.md +19 -8
  139. package/templates/.agents/QUICKSTART.zh-CN.md +19 -8
  140. package/templates/.agents/README.en.md +10 -15
  141. package/templates/.agents/README.zh-CN.md +9 -13
  142. package/templates/.agents/rules/issue-sync.en.md +1 -1
  143. package/templates/.agents/rules/issue-sync.zh-CN.md +1 -1
  144. package/templates/.agents/rules/lifecycle-orchestration.en.md +1 -1
  145. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +1 -1
  146. package/templates/.agents/rules/next-step-output.en.md +2 -2
  147. package/templates/.agents/rules/next-step-output.zh-CN.md +2 -2
  148. package/templates/.agents/rules/pr-sync.en.md +5 -3
  149. package/templates/.agents/rules/pr-sync.zh-CN.md +7 -10
  150. package/templates/.agents/rules/release-commands.en.md +3 -0
  151. package/templates/.agents/rules/release-commands.zh-CN.md +3 -0
  152. package/templates/.agents/rules/task-management.en.md +0 -2
  153. package/templates/.agents/rules/task-management.zh-CN.md +0 -2
  154. package/templates/.agents/rules/task-short-id.en.md +2 -2
  155. package/templates/.agents/rules/task-short-id.zh-CN.md +2 -2
  156. package/templates/.agents/scripts/task-short-id.js +2 -8
  157. package/templates/.agents/skills/analyze-task/SKILL.en.md +6 -6
  158. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +6 -6
  159. package/templates/.agents/skills/analyze-task/config/verify.en.json +0 -1
  160. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +0 -1
  161. package/templates/.agents/skills/archive-tasks/SKILL.en.md +5 -5
  162. package/templates/.agents/skills/archive-tasks/SKILL.zh-CN.md +5 -5
  163. package/templates/.agents/skills/archive-tasks/scripts/archive-tasks.sh +10 -2
  164. package/templates/.agents/skills/block-task/SKILL.en.md +4 -4
  165. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +5 -5
  166. package/templates/.agents/skills/block-task/config/verify.json +0 -1
  167. package/templates/.agents/skills/cancel-task/SKILL.en.md +7 -7
  168. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +7 -7
  169. package/templates/.agents/skills/cancel-task/config/verify.json +0 -1
  170. package/templates/.agents/skills/code-task/SKILL.en.md +1 -1
  171. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +3 -3
  172. package/templates/.agents/skills/code-task/config/verify.en.json +0 -1
  173. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +0 -1
  174. package/templates/.agents/skills/code-task/reference/output-template.en.md +1 -1
  175. package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +1 -1
  176. package/templates/.agents/skills/commit/SKILL.en.md +1 -1
  177. package/templates/.agents/skills/commit/SKILL.zh-CN.md +1 -1
  178. package/templates/.agents/skills/commit/config/verify.json +0 -1
  179. package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +2 -2
  180. package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +2 -2
  181. package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +2 -2
  182. package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +2 -2
  183. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +2 -2
  184. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +2 -2
  185. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +0 -1
  186. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +0 -1
  187. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +3 -3
  188. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +3 -3
  189. package/templates/.agents/skills/complete-task/SKILL.en.md +15 -30
  190. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +17 -32
  191. package/templates/.agents/skills/complete-task/config/verify.en.json +0 -1
  192. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +0 -1
  193. package/templates/.agents/skills/create-pr/SKILL.en.md +3 -3
  194. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +3 -3
  195. package/templates/.agents/skills/create-pr/config/verify.json +0 -1
  196. package/templates/.agents/skills/create-pr/reference/change-report.en.md +10 -3
  197. package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +10 -3
  198. package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +3 -3
  199. package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +3 -3
  200. package/templates/.agents/skills/create-release-note/SKILL.en.md +2 -2
  201. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +2 -2
  202. package/templates/.agents/skills/create-task/SKILL.en.md +4 -22
  203. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +4 -22
  204. package/templates/.agents/skills/create-task/config/verify.json +0 -1
  205. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  206. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  207. package/templates/.agents/skills/import-codescan/config/verify.json +0 -1
  208. package/templates/.agents/skills/import-dependabot/SKILL.en.md +3 -3
  209. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +3 -3
  210. package/templates/.agents/skills/import-dependabot/config/verify.json +0 -1
  211. package/templates/.agents/skills/import-issue/SKILL.en.md +5 -5
  212. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +5 -5
  213. package/templates/.agents/skills/import-issue/config/verify.json +0 -1
  214. package/templates/.agents/skills/plan-task/SKILL.en.md +5 -5
  215. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -5
  216. package/templates/.agents/skills/plan-task/config/verify.en.json +0 -1
  217. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +0 -1
  218. package/templates/.agents/skills/restore-task/SKILL.en.md +2 -2
  219. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +3 -3
  220. package/templates/.agents/skills/restore-task/config/verify.json +0 -1
  221. package/templates/.agents/skills/review-analysis/SKILL.en.md +1 -1
  222. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
  223. package/templates/.agents/skills/review-analysis/config/verify.en.json +0 -1
  224. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +0 -1
  225. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +5 -5
  226. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +5 -5
  227. package/templates/.agents/skills/review-code/SKILL.en.md +2 -2
  228. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +2 -2
  229. package/templates/.agents/skills/review-code/reference/output-templates.en.md +4 -4
  230. package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +4 -4
  231. package/templates/.agents/skills/review-plan/SKILL.en.md +1 -1
  232. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
  233. package/templates/.agents/skills/review-plan/config/verify.en.json +0 -1
  234. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +0 -1
  235. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +5 -5
  236. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +5 -5
  237. package/templates/.agents/skills/review-pr/SKILL.en.md +2 -2
  238. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +2 -2
  239. package/templates/.agents/skills/review-pr/config/verify.en.json +0 -1
  240. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +0 -1
  241. package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +1 -1
  242. package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +1 -1
  243. package/templates/.agents/skills/run-manual-validation/config/verify.en.json +0 -1
  244. package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +0 -1
  245. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  246. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  247. package/templates/.agents/skills/test/SKILL.en.md +0 -3
  248. package/templates/.agents/skills/test/SKILL.zh-CN.md +0 -3
  249. package/templates/.agents/skills/test-integration/SKILL.en.md +0 -3
  250. package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +0 -3
  251. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +13 -6
  252. package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +0 -3
  253. package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +0 -3
  254. package/templates/.agents/skills/watch-pr/SKILL.en.md +4 -4
  255. package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +4 -4
  256. package/templates/.agents/skills/watch-pr/config/verify.json +0 -1
  257. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +3 -3
  258. package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +3 -3
  259. package/templates/.agents/templates/handoff.en.md +1 -1
  260. package/templates/.agents/templates/handoff.zh-CN.md +1 -1
  261. package/templates/.agents/workflows/bug-fix.en.yaml +1 -1
  262. package/templates/.agents/workflows/feature-development.en.yaml +1 -1
  263. package/templates/.agents/workflows/refactoring.en.yaml +1 -1
  264. package/dist/lib/task/task-execution-lock.js +0 -250
  265. package/lib/task/task-execution-lock.ts +0 -320
@@ -1,3 +1,4 @@
1
+ import fs from 'node:fs';
1
2
  import path from 'node:path';
2
3
 
3
4
  import { normalizeAgentToken } from '../agent-clients/tokens.ts';
@@ -29,8 +30,6 @@ import {
29
30
  } from './finalization.ts';
30
31
  import {
31
32
  applyTaskLifecycle,
32
- applyTaskLifecycleWithinTaskLock,
33
- taskLifecycleFailure,
34
33
  type TaskLifecycleRequest,
35
34
  type TaskLifecycleResult
36
35
  } from './lifecycle.ts';
@@ -39,8 +38,8 @@ import type {
39
38
  AgentClientLifecycleRecoveryResult as LifecycleRecoveryResult
40
39
  } from '../agent-clients/adapter.ts';
41
40
  import { resolveTaskContext, resolveTaskRef, TASK_ID_RE } from './resolve-ref.ts';
42
- import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.ts';
43
41
  import { verifyTaskEvent } from './verification.ts';
42
+ import { releaseStaleShortIdRegistry } from './short-id.ts';
44
43
 
45
44
  export type TaskControlExecutionContext =
46
45
  | Readonly<{
@@ -215,7 +214,7 @@ async function applyLifecycleWithAuthority(
215
214
  ): Promise<TaskLifecycleResult | LifecycleRecoveryResult> {
216
215
  const taskId = lifecycleTaskId(request, context.repoRoot);
217
216
  const controlRoot = taskId ? controlRootForTask(context, taskId) : undefined;
218
- const execute = async (underTaskLock = false): Promise<TaskLifecycleResult | LifecycleRecoveryResult> => {
217
+ const execute = async (): Promise<TaskLifecycleResult | LifecycleRecoveryResult> => {
219
218
  if (request.intent === 'recover-started') {
220
219
  const adapter = isAgentClientId(request.agent)
221
220
  ? getAgentClientAdapter(request.agent).orchestrationAdapter
@@ -229,38 +228,13 @@ async function applyLifecycleWithAuthority(
229
228
  }
230
229
  return adapter.recoverStarted(request as LifecycleRecoveryRequest, { repoRoot: context.repoRoot });
231
230
  }
232
- return underTaskLock
233
- ? applyTaskLifecycleWithinTaskLock(request, {
234
- repoRoot: context.repoRoot,
235
- ...(controlRoot ? { controlRoot } : {}),
236
- ...(context.source === 'direct-host' && context.project ? { controlProject: context.project } : {})
237
- }, taskId!)
238
- : applyTaskLifecycle(request, {
239
- repoRoot: context.repoRoot,
240
- ...(controlRoot ? { controlRoot } : {}),
241
- ...(context.source === 'direct-host' && context.project ? { controlProject: context.project } : {})
242
- });
231
+ return applyTaskLifecycle(request, {
232
+ repoRoot: context.repoRoot,
233
+ ...(controlRoot ? { controlRoot } : {}),
234
+ ...(context.source === 'direct-host' && context.project ? { controlProject: context.project } : {})
235
+ });
243
236
  };
244
- if (!taskId) return await execute();
245
- try {
246
- return await withTaskExecutionLock(
247
- context.repoRoot,
248
- taskId,
249
- `task-lifecycle.${request.intent}`,
250
- () => execute(true)
251
- );
252
- } catch (error) {
253
- if (!(error instanceof TaskExecutionLockError)) throw error;
254
- if (request.intent === 'recover-started') {
255
- return {
256
- status: 'owner-unknown', changed: false, targetState: 'active',
257
- requestRef: request.taskRef, intent: 'recover-started', taskId,
258
- receiptId: null, childId: null,
259
- error: { code: error.code, message: error.message }
260
- };
261
- }
262
- return taskLifecycleFailure(request, { code: error.code, message: error.message }, taskId);
263
- }
237
+ return await execute();
264
238
  }
265
239
 
266
240
  function controlRootForTask(context: TaskControlExecutionContext, taskId: string): string | undefined {
@@ -393,6 +367,26 @@ export function dispatchTaskControlOperation(
393
367
  preflight: (request, options) => verifyTaskEvent(
394
368
  { ...request, event: 'complete-task.hard-preflight' }, options
395
369
  )
370
+ }).then((result) => {
371
+ if (context.source !== 'direct-host' || !controlRoot || result.status !== 'completed' || !result.taskId) return result;
372
+ try {
373
+ if (fs.lstatSync(controlRoot, { throwIfNoEntry: false }) === undefined) {
374
+ const released = releaseStaleShortIdRegistry(context.repoRoot, result.taskId);
375
+ return { ...result, changed: result.changed || released.changed };
376
+ }
377
+ return result;
378
+ } catch (error) {
379
+ return {
380
+ ...result,
381
+ status: 'blocked',
382
+ result: 'blocked',
383
+ error: {
384
+ code: 'TASK_FINALIZATION_SHORT_ID_RELEASE_FAILED',
385
+ message: error instanceof Error ? error.message : String(error),
386
+ retryable: true
387
+ }
388
+ };
389
+ }
396
390
  });
397
391
  }
398
392
  try {
@@ -4,7 +4,6 @@ import type { PlatformResult } from '../platform/types.ts';
4
4
  import { VERSION } from '../version.ts';
5
5
  import { applyWorkflowWarningIntent } from './workflow-warning-intents.ts';
6
6
  import { createLocalTask, type TaskCreateCandidateV1 } from './create.ts';
7
- import { TaskExecutionLockError } from './task-execution-lock.ts';
8
7
  import { verifyTaskEvent } from './verification.ts';
9
8
 
10
9
  type TaskCreateStatus = 'applied' | 'no-op' | 'degraded' | 'failed' | 'blocked';
@@ -201,9 +200,8 @@ async function createTask(value: unknown, options: CreateTaskOptions): Promise<T
201
200
  });
202
201
  } catch (error) {
203
202
  const message = error instanceof Error ? error.message : String(error);
204
- const lockBusy = error instanceof TaskExecutionLockError && error.code === 'ORCHESTRATION_LOCK_BUSY';
205
- const code = lockBusy ? error.code : /^([A-Z][A-Z0-9_]+)/.exec(message)?.[1] ?? 'TASK_CREATE_FAILED';
206
- return taskCreateFailure({ code, message, retryable: lockBusy || code === 'TASK_CREATE_LOCK_TIMEOUT' });
203
+ const code = /^([A-Z][A-Z0-9_]+)/.exec(message)?.[1] ?? 'TASK_CREATE_FAILED';
204
+ return taskCreateFailure({ code, message, retryable: false });
207
205
  }
208
206
 
209
207
  const operations: TaskCreateOperation[] = [{
@@ -5,13 +5,13 @@ import path from 'node:path';
5
5
 
6
6
  import { isValidAgentInfraVersion, VERSION } from '../version.ts';
7
7
  import { loadShortIdByTaskId, mutateShortIdRegistry } from './short-id.ts';
8
- import { TaskExecutionLockError, withRepositoryMutationLock, withTaskExecutionLock } from './task-execution-lock.ts';
9
8
  import { readDeliveryDefaults, validateBaseRef, validateRemote } from './delivery-target.ts';
10
9
  import { buildUnboundFact, encodePrDeliveryFact } from './pr-delivery-fact.ts';
11
10
  import { CANDIDATE_COLUMNS, CONSTRAINT_COLUMNS, parseTaskQualification } from './qualification-audit.ts';
12
11
  import { enumerateAllTaskDirs } from './resolve-ref.ts';
13
12
  import { parseTaskFrontmatter } from './frontmatter.ts';
14
13
  import { AGENT_TOKEN_VALUES, type AgentToken } from '../agent-clients/tokens.ts';
14
+ import { resolveProjectTaskWorkspaceRoot } from './workspace-root.ts';
15
15
 
16
16
  const TYPES = ['feature', 'bugfix', 'refactor', 'docs', 'chore'] as const;
17
17
  const PRIORITIES = ['Urgent', 'High', 'Medium', 'Low'] as const;
@@ -348,42 +348,6 @@ function ensureRealDirectory(directory: string, code: string): void {
348
348
  fs.mkdirSync(directory, { mode: 0o700 });
349
349
  }
350
350
 
351
- function createLockRoot(project: string): string {
352
- const root = path.join(os.homedir(), '.agent-infra');
353
- const directories = [root, path.join(root, 'run'), path.join(root, 'run', project), path.join(root, 'run', project, 'task-create-locks')];
354
- for (const directory of directories) {
355
- if (fs.existsSync(directory)) {
356
- assertRealDirectory(directory, 'TASK_CREATE_LOCK_FAILED');
357
- continue;
358
- }
359
- try {
360
- fs.mkdirSync(directory, { mode: 0o700 });
361
- } catch (error) {
362
- if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
363
- assertRealDirectory(directory, 'TASK_CREATE_LOCK_FAILED');
364
- }
365
- }
366
- return directories.at(-1)!;
367
- }
368
-
369
- function withCreateLock<T>(repoRoot: string, project: string, operation: () => T): T {
370
- const lockRoot = createLockRoot(project);
371
- let callbackError: unknown;
372
- try {
373
- return withTaskExecutionLock(repoRoot, 'task-create', 'task-create', () => {
374
- try { return operation(); }
375
- catch (error) { callbackError = error; throw error; }
376
- }, { lockRoot, identityScope: `task-create\0${project}` });
377
- } catch (error) {
378
- if (callbackError !== undefined) throw callbackError;
379
- if (error instanceof TaskExecutionLockError && error.code === 'ORCHESTRATION_LOCK_BUSY') {
380
- throw new Error('TASK_CREATE_LOCK_TIMEOUT');
381
- }
382
- const message = error instanceof Error ? error.message : String(error);
383
- throw new Error(`TASK_CREATE_LOCK_FAILED: ${message}`);
384
- }
385
- }
386
-
387
351
  function recoverPublishedTask(repoRoot: string, keyDigest: string, candidateDigest: string): { taskId: string; shortId: string | null; state: 'active' | 'blocked' | 'completed' | 'archive' } | null {
388
352
  for (const task of enumerateAllTaskDirs(repoRoot)) {
389
353
  const taskMd = path.join(task.taskDir, 'task.md');
@@ -410,16 +374,22 @@ function createLocalTask(value: unknown, options: LocalTaskCreateOptions): Local
410
374
  throw new Error('TASK_CREATE_VERSION_INVALID: agentInfraVersion must be a valid v-prefixed semver');
411
375
  }
412
376
  const repoRoot = fs.realpathSync.native(options.repoRoot);
413
- const workspaceRoot = path.join(repoRoot, '.agents', 'workspace');
377
+ const workspaceRoot = resolveProjectTaskWorkspaceRoot(repoRoot);
414
378
  const activeRoot = path.join(workspaceRoot, 'active');
415
379
  ensureRealDirectory(path.join(repoRoot, '.agents'), 'TASK_CREATE_WORKSPACE_INVALID');
380
+ const home = path.resolve(process.env.HOME || os.homedir());
381
+ const managedRoots = [path.join(home, '.agent-infra'), path.join(home, '.agent-infra', 'task-workspaces')];
382
+ for (const root of managedRoots) {
383
+ if (fs.existsSync(root)) assertRealDirectory(root, 'TASK_CREATE_WORKSPACE_INVALID');
384
+ else fs.mkdirSync(root, { mode: 0o700 });
385
+ }
416
386
  ensureRealDirectory(workspaceRoot, 'TASK_CREATE_WORKSPACE_INVALID');
417
387
  ensureRealDirectory(activeRoot, 'TASK_CREATE_WORKSPACE_INVALID');
418
388
  const projectConfig = readProject(repoRoot);
419
389
  const canonical = canonicalTaskCreateCandidate(candidate);
420
390
  const candidateDigest = sha256(canonical);
421
391
  const keyDigest = sha256(candidate.idempotencyKey);
422
- function createUnderRepositoryLock(): LocalTaskCreateResult {
392
+ function createOnce(): LocalTaskCreateResult {
423
393
  const recovered = recoverPublishedTask(repoRoot, keyDigest, candidateDigest);
424
394
  if (recovered) {
425
395
  return { status: 'no-op', changed: false, task: { id: recovered.taskId, shortId: recovered.shortId, state: recovered.state } };
@@ -451,18 +421,7 @@ function createLocalTask(value: unknown, options: LocalTaskCreateOptions): Local
451
421
  return { status: 'applied', changed: true, task: { id: taskId, shortId: allocated.shortId, state: 'active' } };
452
422
  }
453
423
 
454
- return withCreateLock(repoRoot, projectConfig.project, () => {
455
- let callbackError: unknown;
456
- try {
457
- return withRepositoryMutationLock(repoRoot, () => {
458
- try { return createUnderRepositoryLock(); }
459
- catch (error) { callbackError = error; throw error; }
460
- });
461
- } catch (error) {
462
- if (callbackError !== undefined) throw callbackError;
463
- throw error;
464
- }
465
- });
424
+ return createOnce();
466
425
 
467
426
  }
468
427
 
@@ -263,7 +263,7 @@ function validateSealRequest(
263
263
 
264
264
  function validateReviewerSealPaths(receipt: DelegationReceipt, changedPaths: readonly string[]): ReceiptFailure | null {
265
265
  if (receipt.role !== 'reviewer') return null;
266
- const taskRoot = `.agents/workspace/active/${receipt.taskId}/`;
266
+ const taskRoot = `task-workspace/active/${receipt.taskId}/`;
267
267
  const allowed = new Set([
268
268
  `${taskRoot}${receipt.artifact}`,
269
269
  `${taskRoot}task.md`,
@@ -6,7 +6,6 @@ import { parseTaskFrontmatter } from './frontmatter.ts';
6
6
  import { resolveTaskRef } from './resolve-ref.ts';
7
7
  import { resolveDeliveryTarget, validateBaseRef, validateRemote } from './delivery-target.ts';
8
8
  import { captureTaskWriteMetadata, writeTask } from './write.ts';
9
- import { withRepositoryMutationLock, withTaskExecutionLock } from './task-execution-lock.ts';
10
9
 
11
10
  export type DeliveryState = 'absent' | 'same' | 'known-old' | 'unknown-drift';
12
11
 
@@ -50,7 +49,7 @@ function failure(taskId: string | null, code: string, message: string, retryable
50
49
  return { status, changed: false, taskId, remoteHead: null, localHead: null, state: null, error: { code, message, retryable } };
51
50
  }
52
51
 
53
- function deliverUnlocked(
52
+ function deliverTaskBranchCore(
54
53
  taskId: string,
55
54
  taskDir: string,
56
55
  repoRoot: string,
@@ -108,14 +107,7 @@ function deliverUnlocked(
108
107
  function deliverTaskBranch(taskRef: string, options: { repoRoot?: string; agent: string; remote?: string; baseRef?: string; dryRun?: boolean }): TaskBranchDeliveryResult {
109
108
  const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
110
109
  if (!resolved.ok) return failure(resolved.taskId, resolved.code, resolved.message);
111
- try {
112
- return withRepositoryMutationLock(resolved.repoRoot, () => withTaskExecutionLock(
113
- resolved.repoRoot, resolved.taskId, 'task-delivery',
114
- () => deliverUnlocked(resolved.taskId, resolved.taskDir, resolved.repoRoot, options)
115
- ));
116
- } catch (error) {
117
- return failure(resolved.taskId, 'DELIVERY_LOCK_FAILED', error instanceof Error ? error.message : String(error), true, 'blocked');
118
- }
110
+ return deliverTaskBranchCore(resolved.taskId, resolved.taskDir, resolved.repoRoot, options);
119
111
  }
120
112
 
121
113
  export { classifyDeliveryState, deliverTaskBranch };
@@ -31,7 +31,6 @@ import { findSectionHeading } from './sections.ts';
31
31
  import { validateLifecycleExecution } from './lifecycle-execution.ts';
32
32
  import { commitOrchestrationStageCompletion } from './orchestration.ts';
33
33
  import type { OrchestrationStageCompletion } from './orchestration.ts';
34
- import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.ts';
35
34
  import { captureTaskWriteMetadata, writeTask } from './write.ts';
36
35
  import type { TaskOperationSummary, TaskWriteErrorCode, TaskWriteOptions } from './write.ts';
37
36
  import { validateLocalArtifact } from './local-artifact-finalization.ts';
@@ -86,7 +85,6 @@ type TaskEventRequest = {
86
85
  type TaskEventError = { code: TaskEventErrorCode; message: string };
87
86
  type TaskEventOptions = TaskWriteOptions & {
88
87
  commitOrchestrationCompletion?: (plan: OrchestrationStageCompletion) => void;
89
- lockAlreadyHeld?: boolean;
90
88
  };
91
89
  type TaskEventResult = {
92
90
  status: 'planned' | 'applied' | 'no-op' | 'failed'; changed: boolean;
@@ -519,6 +517,7 @@ function reworkIntentMutationForCompletion(
519
517
  function buildCompletionReceipt(
520
518
  content: string,
521
519
  taskDir: string,
520
+ repositoryRoot: string | undefined,
522
521
  family: EventFamily,
523
522
  artifact: ArtifactIdentity,
524
523
  completedAt: string,
@@ -527,7 +526,7 @@ function buildCompletionReceipt(
527
526
  ): { ok: true; receipts: readonly ArtifactReceipt[] } | { ok: false; message: string } | null {
528
527
  if (!['analyze', 'plan', 'code'].includes(family) && !family.startsWith('review-')) return null;
529
528
  if (family === 'review-code') {
530
- const identity = inspectReviewIdentity(taskDir, fs.readFileSync(artifact.path, 'utf8'));
529
+ const identity = inspectReviewIdentity(taskDir, fs.readFileSync(artifact.path, 'utf8'), repositoryRoot);
531
530
  if (identity.status !== 'matched') return { ok: false, message: `review-code identity is ${identity.status}: ${identity.message}` };
532
531
  }
533
532
  const event = family === 'analyze' ? 'analysis.completed'
@@ -627,7 +626,7 @@ function replaceCompletionFact(facts: readonly CompletionFact[], next: Completio
627
626
  return [...facts.filter((fact) => !(fact.event === next.event && fact.output === next.output)), next];
628
627
  }
629
628
 
630
- function applyTaskEventUnlocked(request: TaskEventRequest, options: TaskEventOptions = {}): TaskEventResult {
629
+ function applyTaskEvent(request: TaskEventRequest, options: TaskEventOptions = {}): TaskEventResult {
631
630
  const invalid = validateTaskEventRequest(request);
632
631
  if (invalid) return failed(request, invalid);
633
632
  const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
@@ -757,7 +756,7 @@ function applyTaskEventUnlocked(request: TaskEventRequest, options: TaskEventOpt
757
756
  }
758
757
  if (eventIdentity.phase === 'started') {
759
758
  const trigger = eventTrigger(normalized, eventIdentity.family);
760
- const facts = buildLifecycleFacts(resolved.taskDir, content, resolved.state);
759
+ const facts = buildLifecycleFacts(resolved.taskDir, content, resolved.state, false, resolved.repoRoot);
761
760
  if (!facts.ok) return failed(normalized, { code: 'EVENT_TRANSITION_INVALID', message: `${facts.code}: ${facts.message}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
762
761
  const capability = canStart(lifecycleAction(eventIdentity.family), facts.facts, trigger);
763
762
  const safetyFailure = capability.reasonCode === 'TASK_NOT_ACTIVE'
@@ -804,7 +803,7 @@ function applyTaskEventUnlocked(request: TaskEventRequest, options: TaskEventOpt
804
803
  let currentFact: CompletionFact | null = null;
805
804
  let completionRework: ReturnType<typeof reworkIntentMutation> | null = null;
806
805
  if (eventIdentity.phase === 'completed' && completedArtifact) {
807
- const receipt = buildCompletionReceipt(content, resolved.taskDir, eventIdentity.family, completedArtifact, metadata.timestamp, frontmatter, normalized);
806
+ const receipt = buildCompletionReceipt(content, resolved.taskDir, resolved.repoRoot, eventIdentity.family, completedArtifact, metadata.timestamp, frontmatter, normalized);
808
807
  if (receipt && !receipt.ok) {
809
808
  return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: receipt.message }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
810
809
  }
@@ -978,32 +977,6 @@ function applyTaskEventUnlocked(request: TaskEventRequest, options: TaskEventOpt
978
977
  };
979
978
  }
980
979
 
981
- function applyTaskEvent(request: TaskEventRequest, options: TaskEventOptions = {}): TaskEventResult {
982
- const invalid = validateTaskEventRequest(request);
983
- if (invalid) return failed(request, invalid);
984
- const parts = eventParts(request.event);
985
- if (options.lockAlreadyHeld) return applyTaskEventUnlocked(request, options);
986
- if (request.dryRun || !['started', 'completed'].includes(parts.phase)) {
987
- return applyTaskEventUnlocked(request, options);
988
- }
989
- const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
990
- if (!resolved.ok) return applyTaskEventUnlocked(request, options);
991
- try {
992
- return withTaskExecutionLock(
993
- resolved.repoRoot,
994
- resolved.taskId,
995
- `task-event.${request.event}`,
996
- () => applyTaskEventUnlocked(request, { ...options, lockAlreadyHeld: true })
997
- );
998
- } catch (error) {
999
- if (!(error instanceof TaskExecutionLockError)) throw error;
1000
- return failed(request, {
1001
- code: 'EVENT_TRANSITION_INVALID',
1002
- message: `${error.code}: ${error.message}`
1003
- }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
1004
- }
1005
- }
1006
-
1007
980
  function successNoOp(
1008
981
  request: TaskEventRequest, taskId: string, taskMdPath: string, currentStep: string,
1009
982
  eventIdentity: ReturnType<typeof identity>, timestamp: string,
@@ -14,7 +14,6 @@ import { parseTaskFrontmatter } from './frontmatter.ts';
14
14
  import { recoverPlatformOperations } from './platform-operation-recovery.ts';
15
15
  import {
16
16
  applyTaskLifecycle,
17
- applyTaskLifecycleWithinTaskLock,
18
17
  inspectTaskLifecycleProgress,
19
18
  type TaskLifecycleOptions,
20
19
  type TaskLifecycleRequest,
@@ -24,7 +23,6 @@ import {
24
23
  } from './lifecycle.ts';
25
24
  import { enumerateAllTaskDirs, resolveTaskRef } from './resolve-ref.ts';
26
25
  import { inspectShortIdRegistry } from './short-id.ts';
27
- import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.ts';
28
26
  import { verifyTaskEvent } from './verification.ts';
29
27
  import type { TaskVerificationResult } from './verification.ts';
30
28
  import { projectFinalizationWarning } from './workflow-warning-intents.ts';
@@ -35,6 +33,7 @@ import {
35
33
  } from './operation-outcome.ts';
36
34
  import { readSandboxControlManifest } from '../sandbox/control/lifecycle.ts';
37
35
  import { validateSandboxControlIdentity } from '../sandbox/control/identity-sentinel.ts';
36
+ import { parseDeliverySummaryContent, renderDeliverySummaryContent } from '../platform/issue-summary-content.ts';
38
37
 
39
38
  const RECEIPT_VERSION = 4 as const;
40
39
  const FINALIZATION_STEPS = ['lifecycle', 'task-comment', 'verification', 'summary'] as const;
@@ -586,7 +585,7 @@ function mutationPatch(current: TaskFinalizationReceipt, mutation: FinalizationM
586
585
  : { warningProjection: 'pending', lastError: mutation.error };
587
586
  }
588
587
 
589
- function applyFinalizationReceiptMutationUnderLock(
588
+ function mutateFinalizationReceipt(
590
589
  repoRoot: string,
591
590
  receipt: TaskFinalizationReceipt,
592
591
  capability: FinalizationCapability,
@@ -615,9 +614,7 @@ function applyFinalizationReceiptMutation(
615
614
  if (!hasFinalizationTaskDocument(repoRoot, receipt.taskId)) {
616
615
  throw capabilityError('FINALIZATION_SCOPE_INVALID', 'finalization capability requires an active task or a completed task');
617
616
  }
618
- return withTaskExecutionLock(repoRoot, receipt.taskId, 'task-finalization.receipt-mutation', () =>
619
- applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, mutation, new Set<string>())
620
- );
617
+ return mutateFinalizationReceipt(repoRoot, receipt, capability, mutation, new Set<string>());
621
618
  }
622
619
 
623
620
  function warningKey(warning: Pick<FinalizationWarning, 'step' | 'code' | 'target'>): string {
@@ -640,20 +637,20 @@ function reconcileWarningProjection(repoRoot: string, taskId: string, receipt: T
640
637
  retryable: true
641
638
  };
642
639
  const capability = issueCapability(receipt, 'warning-projection');
643
- return applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'failed', error: detail }, consumed);
640
+ return mutateFinalizationReceipt(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'failed', error: detail }, consumed);
644
641
  }
645
642
  } catch (error) {
646
643
  const detail = errorOf(error, 'FINALIZATION_WARNING_PROJECTION_FAILED', true);
647
644
  try {
648
645
  const capability = issueCapability(receipt, 'warning-projection');
649
- return applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'failed', error: detail }, consumed);
646
+ return mutateFinalizationReceipt(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'failed', error: detail }, consumed);
650
647
  }
651
648
  catch { return receipt; }
652
649
  }
653
650
  }
654
651
  try {
655
652
  const capability = issueCapability(receipt, 'warning-projection');
656
- return applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'succeeded' }, consumed);
653
+ return mutateFinalizationReceipt(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'succeeded' }, consumed);
657
654
  }
658
655
  catch { return receipt; }
659
656
  }
@@ -692,7 +689,7 @@ async function syncPendingTaskComment(input: {
692
689
  if (result.status === 'applied' || result.status === 'no-op') {
693
690
  const skipped = result.error?.code === 'ISSUE_NOT_LINKED';
694
691
  const capability = issueCapability(receipt, 'task-comment');
695
- receipt = applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, {
692
+ receipt = mutateFinalizationReceipt(repoRoot, receipt, capability, {
696
693
  scope: 'task-comment', operation: 'succeeded', state: skipped ? 'skipped' : 'done'
697
694
  }, consumedCapabilities);
698
695
  receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
@@ -708,7 +705,7 @@ async function syncPendingTaskComment(input: {
708
705
  }
709
706
  const detail = step.error ?? { code: 'COMMENT_SYNC_FAILED', message: 'task comment synchronization failed', retryable: true };
710
707
  const capability = issueCapability(receipt, 'task-comment');
711
- receipt = applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, {
708
+ receipt = mutateFinalizationReceipt(repoRoot, receipt, capability, {
712
709
  scope: 'task-comment', operation: 'failed', error: detail
713
710
  }, consumedCapabilities);
714
711
  receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
@@ -717,7 +714,7 @@ async function syncPendingTaskComment(input: {
717
714
  const detail = errorOf(error, 'COMMENT_SYNC_FAILED', true);
718
715
  try {
719
716
  const capability = issueCapability(receipt, 'task-comment');
720
- receipt = applyFinalizationReceiptMutationUnderLock(repoRoot, receipt, capability, {
717
+ receipt = mutateFinalizationReceipt(repoRoot, receipt, capability, {
721
718
  scope: 'task-comment', operation: 'failed', error: detail
722
719
  }, consumedCapabilities);
723
720
  receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
@@ -734,16 +731,20 @@ function readDeliverySummary(taskDir: string, taskId: string): { body: string; s
734
731
  } catch {
735
732
  throw Object.assign(new Error('delivery summary staging record is unavailable'), { code: 'SUMMARY_STAGING_INVALID' });
736
733
  }
737
- if (value.taskId !== taskId || typeof value.body !== 'string' || typeof value.sha256 !== 'string') {
734
+ if (value.taskId !== taskId || !value.content || typeof value.contentSha256 !== 'string') {
738
735
  throw Object.assign(new Error('delivery summary staging record is invalid'), { code: 'SUMMARY_STAGING_INVALID' });
739
736
  }
740
- const canonical = canonicalizeSummaryBody(value.body);
741
- if (!canonical.ok || canonical.value !== value.body) {
742
- throw Object.assign(new Error('delivery summary staging body is not canonical'), { code: 'SUMMARY_STAGING_INVALID' });
737
+ let content;
738
+ try { content = parseDeliverySummaryContent(value.content); }
739
+ catch { throw Object.assign(new Error('delivery summary staging payload is invalid'), { code: 'SUMMARY_STAGING_INVALID' }); }
740
+ if (content.taskId !== taskId || createHash('sha256').update(JSON.stringify(content)).digest('hex') !== value.contentSha256) {
741
+ throw Object.assign(new Error('delivery summary staging digest does not match payload'), { code: 'SUMMARY_STAGING_INVALID' });
743
742
  }
743
+ const body = renderDeliverySummaryContent(content);
744
+ const canonical = canonicalizeSummaryBody(body);
745
+ if (!canonical.ok) throw Object.assign(new Error('delivery summary staging body is not canonical'), { code: 'SUMMARY_STAGING_INVALID' });
744
746
  const digest = createHash('sha256').update(canonical.value).digest('hex');
745
- if (digest !== value.sha256) throw Object.assign(new Error('delivery summary staging digest does not match body'), { code: 'SUMMARY_STAGING_INVALID' });
746
- return { body: canonical.value, sha256: value.sha256 };
747
+ return { body: canonical.value, sha256: digest };
747
748
  }
748
749
 
749
750
  async function syncPendingSummary(input: {
@@ -863,14 +864,14 @@ function preparedResult(
863
864
  };
864
865
  }
865
866
 
866
- async function prepareUnderLock(
867
+ async function prepareTaskFinalizationCore(
867
868
  request: TaskFinalizationRequest,
868
869
  taskId: string,
869
870
  options: TaskFinalizationOptions
870
871
  ): Promise<TaskFinalizationResult> {
871
872
  const repoRoot = path.resolve(options.repoRoot);
872
873
  const lifecycle = options.lifecycle ?? ((lifecycleRequest, lifecycleOptions) => (
873
- applyTaskLifecycleWithinTaskLock(lifecycleRequest, lifecycleOptions ?? { repoRoot }, taskId)
874
+ applyTaskLifecycle(lifecycleRequest, lifecycleOptions ?? { repoRoot })
874
875
  ));
875
876
  const backfill = options.backfill ?? backfillCompletionComments;
876
877
  const commentSync = options.commentSync ?? syncPlatformComment;
@@ -1142,11 +1143,9 @@ async function prepareTaskFinalization(request: TaskFinalizationRequest, options
1142
1143
  const resolved = resolveTaskRef(request.taskRef, { repoRoot });
1143
1144
  if (!resolved.ok) return failed(resolved.taskId, { code: resolved.code, message: resolved.message, retryable: false });
1144
1145
  try {
1145
- return await withTaskExecutionLock(repoRoot, resolved.taskId, 'task-finalization.prepare', () => prepareUnderLock(request, resolved.taskId, options));
1146
+ return await prepareTaskFinalizationCore(request, resolved.taskId, options);
1146
1147
  } catch (error) {
1147
- const detail = error instanceof TaskExecutionLockError
1148
- ? { code: error.code, message: error.message, retryable: error.code === 'ORCHESTRATION_LOCK_BUSY' }
1149
- : errorOf(error, 'TASK_FINALIZATION_FAILED');
1148
+ const detail = errorOf(error, 'TASK_FINALIZATION_FAILED');
1150
1149
  return failed(resolved.taskId, detail);
1151
1150
  }
1152
1151
  }
@@ -1159,7 +1158,7 @@ async function commitPreparedTaskFinalization(request: TaskFinalizationRequest,
1159
1158
  const resolved = resolveTaskRef(request.taskRef, { repoRoot });
1160
1159
  if (!resolved.ok) return failed(resolved.taskId, { code: resolved.code, message: resolved.message, retryable: false });
1161
1160
  try {
1162
- return await withTaskExecutionLock(repoRoot, resolved.taskId, 'task-finalization.commit', async () => {
1161
+ return await (async () => {
1163
1162
  if (options.controlBinding && options.manifestPath) {
1164
1163
  try {
1165
1164
  const manifest = readSandboxControlManifest(options.manifestPath);
@@ -1223,7 +1222,7 @@ async function commitPreparedTaskFinalization(request: TaskFinalizationRequest,
1223
1222
  };
1224
1223
  const result = options.lifecycle
1225
1224
  ? options.lifecycle(lifecycleRequest, lifecycleOptions)
1226
- : applyTaskLifecycleWithinTaskLock(lifecycleRequest, lifecycleOptions, resolved.taskId);
1225
+ : applyTaskLifecycle(lifecycleRequest, lifecycleOptions);
1227
1226
  const step = lifecycleStep(result);
1228
1227
  if (result.status !== 'applied' && result.status !== 'no-op') {
1229
1228
  const updated = updateReceipt(repoRoot, receipt, { lifecycle: 'pending', lastError: step.error });
@@ -1305,11 +1304,9 @@ async function commitPreparedTaskFinalization(request: TaskFinalizationRequest,
1305
1304
  });
1306
1305
  }
1307
1306
  return terminalResult(resolved.taskId, updated, { lifecycle: step, verification }, result.changed, detail);
1308
- });
1307
+ })();
1309
1308
  } catch (error) {
1310
- const detail = error instanceof TaskExecutionLockError
1311
- ? { code: error.code, message: error.message, retryable: error.code === 'ORCHESTRATION_LOCK_BUSY' }
1312
- : errorOf(error, 'TASK_FINALIZATION_FAILED');
1309
+ const detail = errorOf(error, 'TASK_FINALIZATION_FAILED');
1313
1310
  return failed(resolved.taskId, detail);
1314
1311
  }
1315
1312
  }