@fitlab-ai/agent-infra 0.9.15 → 0.11.0

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 (224) hide show
  1. package/README.md +2 -6
  2. package/README.zh-CN.md +2 -6
  3. package/bin/internal-cli.sh +0 -13
  4. package/dist/bin/internal-cli.js +11 -49
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +6 -2
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +43 -3
  7. package/dist/lib/fs/durable-write.js +2 -0
  8. package/dist/lib/internal/cli-route-inventory.js +3 -4
  9. package/dist/lib/internal/manual-validation.js +17 -8
  10. package/dist/lib/internal/platform-comment.js +60 -2
  11. package/dist/lib/internal/task-artifact.js +1 -1
  12. package/dist/lib/internal/task-finalization.js +2 -2
  13. package/dist/lib/internal/task-lifecycle.js +4 -4
  14. package/dist/lib/internal/task-operation-registry.js +22 -13
  15. package/dist/lib/internal/task-orchestration.js +2 -2
  16. package/dist/lib/internal/task-review.js +12 -7
  17. package/dist/lib/platform/activity-recovery.js +159 -0
  18. package/dist/lib/platform/issue-comments.js +89 -31
  19. package/dist/lib/platform/issues.js +1 -1
  20. package/dist/lib/platform/pr-change-report.js +5 -4
  21. package/dist/lib/platform/pr-summary.js +64 -32
  22. package/dist/lib/platform/pull-requests.js +3 -3
  23. package/dist/lib/platform/task-comment-projection.js +70 -0
  24. package/dist/lib/platform/task-identities.js +2 -9
  25. package/dist/lib/platform/task-recovery.js +55 -0
  26. package/dist/lib/platform/verification-sync.js +45 -7
  27. package/dist/lib/pr-review/evidence-grading.js +4 -8
  28. package/dist/lib/sandbox/commands/rm.js +21 -2
  29. package/dist/lib/sandbox/control/executor.js +4 -2
  30. package/dist/lib/sandbox/control/server.js +29 -9
  31. package/dist/lib/sandbox/control/state.js +7 -1
  32. package/dist/lib/sandbox/control/task-workflow.js +1 -1
  33. package/dist/lib/sandbox/control/workflow-executor.js +87 -35
  34. package/dist/lib/sandbox/index.js +1 -2
  35. package/dist/lib/sandbox/removal.js +116 -1011
  36. package/dist/lib/sandbox/workspace-identity.js +17 -1
  37. package/dist/lib/server/process-state.js +17 -5
  38. package/dist/lib/task/artifact-command.js +11 -30
  39. package/dist/lib/task/artifact-operations.js +17 -231
  40. package/dist/lib/task/artifact-recovery.js +476 -0
  41. package/dist/lib/task/artifact-repair-intent.js +90 -39
  42. package/dist/lib/task/commit-operation.js +31 -4
  43. package/dist/lib/task/control-authority.js +39 -8
  44. package/dist/lib/task/control-recovery.js +14 -2
  45. package/dist/lib/task/create-service.js +1 -8
  46. package/dist/lib/task/delegation-receipts.js +64 -3
  47. package/dist/lib/task/events.js +165 -23
  48. package/dist/lib/task/human-override.js +5 -8
  49. package/dist/lib/task/intermediate-cleanup.js +91 -8
  50. package/dist/lib/task/lifecycle-recovery.js +549 -0
  51. package/dist/lib/task/lifecycle.js +12 -3
  52. package/dist/lib/task/local-artifact-finalization.js +212 -123
  53. package/dist/lib/task/manual-validation-receipt.js +5 -1
  54. package/dist/lib/task/orchestration.js +52 -2
  55. package/dist/lib/task/pr-delivery-fact.js +12 -56
  56. package/dist/lib/task/recovery-warning.js +19 -0
  57. package/dist/lib/task/review-command.js +3 -2
  58. package/dist/lib/task/review-finalization.js +294 -74
  59. package/dist/lib/{host-control → task}/secure-fs.js +8 -19
  60. package/dist/lib/task/short-id.js +15 -7
  61. package/dist/lib/task/task-execution-lock.js +1 -1
  62. package/dist/lib/task/verification-engine.js +3 -14
  63. package/dist/lib/task/workflow-command.js +2 -1
  64. package/dist/lib/task/workflow-dispatch.js +161 -0
  65. package/dist/lib/version.js +1 -11
  66. package/dist/lifecycle-build-manifest.json +3 -3
  67. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +7 -2
  68. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +55 -3
  69. package/lib/fs/durable-write.ts +1 -0
  70. package/lib/internal/cli-route-inventory.ts +3 -4
  71. package/lib/internal/manual-validation.ts +17 -8
  72. package/lib/internal/platform-comment.ts +53 -2
  73. package/lib/internal/task-artifact.ts +1 -1
  74. package/lib/internal/task-finalization.ts +1 -1
  75. package/lib/internal/task-lifecycle.ts +5 -4
  76. package/lib/internal/task-operation-registry.ts +22 -13
  77. package/lib/internal/task-orchestration.ts +1 -1
  78. package/lib/internal/task-review.ts +11 -7
  79. package/lib/platform/activity-recovery.ts +179 -0
  80. package/lib/platform/issue-comments.ts +105 -30
  81. package/lib/platform/issues.ts +1 -1
  82. package/lib/platform/pr-change-report.ts +7 -5
  83. package/lib/platform/pr-summary.ts +64 -32
  84. package/lib/platform/pull-requests.ts +3 -3
  85. package/lib/platform/task-comment-projection.ts +79 -0
  86. package/lib/platform/task-identities.ts +3 -14
  87. package/lib/platform/task-recovery.ts +54 -0
  88. package/lib/platform/verification-sync.ts +48 -11
  89. package/lib/pr-review/evidence-grading.ts +4 -9
  90. package/lib/sandbox/commands/rm.ts +34 -2
  91. package/lib/sandbox/control/executor.ts +4 -2
  92. package/lib/sandbox/control/protocol.ts +6 -1
  93. package/lib/sandbox/control/server.ts +30 -10
  94. package/lib/sandbox/control/state.ts +9 -1
  95. package/lib/sandbox/control/task-workflow.ts +1 -1
  96. package/lib/sandbox/control/workflow-executor.ts +106 -35
  97. package/lib/sandbox/index.ts +1 -2
  98. package/lib/sandbox/removal.ts +126 -1128
  99. package/lib/sandbox/workspace-identity.ts +19 -3
  100. package/lib/server/process-state.ts +26 -5
  101. package/lib/task/artifact-command.ts +12 -29
  102. package/lib/task/artifact-operations.ts +22 -252
  103. package/lib/task/artifact-recovery.ts +572 -0
  104. package/lib/task/artifact-repair-intent.ts +126 -51
  105. package/lib/task/commit-operation.ts +35 -4
  106. package/lib/task/control-authority.ts +48 -15
  107. package/lib/task/control-recovery.ts +13 -1
  108. package/lib/task/create-service.ts +1 -10
  109. package/lib/task/delegation-receipts.ts +73 -2
  110. package/lib/task/events.ts +188 -24
  111. package/lib/task/human-override.ts +5 -8
  112. package/lib/task/intermediate-cleanup.ts +66 -12
  113. package/lib/task/lifecycle-recovery.ts +691 -0
  114. package/lib/task/lifecycle.ts +13 -4
  115. package/lib/task/local-artifact-finalization.ts +249 -131
  116. package/lib/task/manual-validation-receipt.ts +5 -1
  117. package/lib/task/orchestration.ts +65 -0
  118. package/lib/task/pr-delivery-fact.ts +15 -62
  119. package/lib/task/recovery-warning.ts +21 -0
  120. package/lib/task/review-command.ts +2 -1
  121. package/lib/task/review-finalization.ts +298 -84
  122. package/lib/{host-control → task}/secure-fs.ts +10 -32
  123. package/lib/task/short-id.ts +27 -5
  124. package/lib/task/task-execution-lock.ts +1 -1
  125. package/lib/task/verification-engine.ts +3 -17
  126. package/lib/task/verification-types.ts +0 -2
  127. package/lib/task/workflow-command.ts +2 -1
  128. package/lib/task/workflow-dispatch.ts +171 -0
  129. package/lib/version.ts +1 -15
  130. package/package.json +1 -1
  131. package/templates/.agents/rules/create-issue.en.md +1 -1
  132. package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
  133. package/templates/.agents/rules/issue-sync.en.md +12 -2
  134. package/templates/.agents/rules/issue-sync.zh-CN.md +13 -5
  135. package/templates/.agents/rules/local-artifact-repair.en.md +47 -39
  136. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +45 -36
  137. package/templates/.agents/skills/analyze-task/SKILL.en.md +6 -6
  138. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +6 -6
  139. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -1
  140. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -1
  141. package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
  142. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
  143. package/templates/.agents/skills/block-task/config/verify.json +1 -1
  144. package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
  145. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
  146. package/templates/.agents/skills/cancel-task/config/verify.json +1 -1
  147. package/templates/.agents/skills/code-task/SKILL.en.md +7 -7
  148. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +8 -8
  149. package/templates/.agents/skills/code-task/config/verify.en.json +1 -1
  150. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -1
  151. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
  152. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
  153. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +1 -1
  154. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +1 -1
  155. package/templates/.agents/skills/complete-task/SKILL.en.md +2 -2
  156. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +2 -2
  157. package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
  158. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
  159. package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
  160. package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
  161. package/templates/.agents/skills/create-pr/SKILL.en.md +2 -2
  162. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +2 -2
  163. package/templates/.agents/skills/create-pr/config/verify.json +1 -1
  164. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +2 -2
  165. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +2 -2
  166. package/templates/.agents/skills/create-task/SKILL.en.md +5 -5
  167. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -5
  168. package/templates/.agents/skills/create-task/config/verify.json +1 -1
  169. package/templates/.agents/skills/import-issue/SKILL.en.md +8 -8
  170. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +8 -8
  171. package/templates/.agents/skills/import-issue/config/verify.json +2 -2
  172. package/templates/.agents/skills/plan-task/SKILL.en.md +4 -4
  173. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -4
  174. package/templates/.agents/skills/plan-task/config/verify.en.json +1 -1
  175. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -1
  176. package/templates/.agents/skills/restore-task/SKILL.en.md +11 -6
  177. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +11 -6
  178. package/templates/.agents/skills/restore-task/config/verify.json +1 -1
  179. package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
  180. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
  181. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -1
  182. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -1
  183. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +7 -7
  184. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +6 -6
  185. package/templates/.agents/skills/review-code/SKILL.en.md +5 -4
  186. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -4
  187. package/templates/.agents/skills/review-code/config/verify.en.json +1 -1
  188. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -1
  189. package/templates/.agents/skills/review-code/reference/report-template.en.md +12 -12
  190. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +12 -12
  191. package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
  192. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
  193. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -1
  194. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -1
  195. package/templates/.agents/skills/review-plan/reference/report-template.en.md +7 -7
  196. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +7 -7
  197. package/templates/.agents/skills/review-pr/config/verify.en.json +1 -1
  198. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -1
  199. package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +3 -3
  200. package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +3 -3
  201. package/templates/.agents/skills/run-manual-validation/config/verify.en.json +1 -1
  202. package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +1 -1
  203. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  204. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  205. package/templates/.agents/templates/task.en.md +1 -1
  206. package/templates/.agents/templates/task.zh-CN.md +1 -1
  207. package/templates/.claude/commands/import-issue.en.md +1 -1
  208. package/templates/.claude/commands/import-issue.zh-CN.md +1 -1
  209. package/templates/.claude/commands/restore-task.en.md +1 -1
  210. package/templates/.claude/commands/restore-task.zh-CN.md +1 -1
  211. package/dist/lib/host-control/audit.js +0 -19
  212. package/dist/lib/host-control/client.js +0 -142
  213. package/dist/lib/host-control/command.js +0 -49
  214. package/dist/lib/host-control/path.js +0 -160
  215. package/dist/lib/host-control/server.js +0 -159
  216. package/dist/lib/host-control/service.js +0 -112
  217. package/dist/lib/internal/host-control.js +0 -28
  218. package/lib/host-control/audit.ts +0 -22
  219. package/lib/host-control/client.ts +0 -172
  220. package/lib/host-control/command.ts +0 -60
  221. package/lib/host-control/path.ts +0 -167
  222. package/lib/host-control/server.ts +0 -180
  223. package/lib/host-control/service.ts +0 -133
  224. package/lib/internal/host-control.ts +0 -28
@@ -2,14 +2,15 @@ import { TASK_WORKFLOW_COMMANDS } from '../../task/workflow-command.ts';
2
2
 
3
3
  import { parseArtifactCommand, executeArtifactCommand } from '../../task/artifact-command.ts';
4
4
  import { parseReviewCommand } from '../../task/review-command.ts';
5
- import { prepareLocalArtifact, commitLocalArtifactProvenance } from '../../task/local-artifact-finalization.ts';
5
+ import { prepareLocalArtifact, preflightLocalArtifact, commitLocalArtifactProvenance } from '../../task/local-artifact-finalization.ts';
6
6
  import { prepareReviewSummaryCandidate, commitReviewSummaryProvenance } from '../../task/review-finalization.ts';
7
+ import { readArtifactRecoveryIntent } from '../../task/artifact-repair-intent.ts';
7
8
  import { withTaskExecutionLock } from '../../task/task-execution-lock.ts';
8
- import { dispatchHostControlCommand } from '../../host-control/command.ts';
9
+ import { dispatchWorkflowCommand } from '../../task/workflow-dispatch.ts';
9
10
  import { assertSandboxTaskSource } from '../workspace-view.ts';
10
11
  import { appendDiagnosticAudit } from './audit.ts';
11
12
  import {
12
- readTaskArtifact, writeTaskArtifact, type TaskWorkflowRequest
13
+ readTaskArtifact, type TaskWorkflowRequest
13
14
  } from './task-workflow.ts';
14
15
  import type { SandboxControlManifest } from './protocol.ts';
15
16
  import type { SandboxControlExecutionResult } from './executor.ts';
@@ -17,6 +18,17 @@ import type { LifecycleRecoveryAttestationV1 } from '../../task/control-authorit
17
18
  import { applyTaskEvent } from '../../task/events.ts';
18
19
  import { parseTaskEventRequest } from '../../internal/task-event.ts';
19
20
 
21
+ export type TaskWorkflowFaultWindow =
22
+ | 'before-call'
23
+ | 'before-domain-write'
24
+ | 'after-atomic-rename'
25
+ | 'before-result-return';
26
+
27
+ export type TaskWorkflowExecutionOptions = Readonly<{
28
+ /** Deterministic test seam; production callers leave this unset. */
29
+ faultWindow?: TaskWorkflowFaultWindow;
30
+ }>;
31
+
20
32
  function executionResult(result: Record<string, unknown>): SandboxControlExecutionResult {
21
33
  return { exitCode: result.status === 'failed' || result.status === 'refused' ? 1 : 0, stdout: `${JSON.stringify(result)}\n`, stderr: '' };
22
34
  }
@@ -25,10 +37,41 @@ function executionResult(result: Record<string, unknown>): SandboxControlExecuti
25
37
  export async function executeTaskWorkflow(
26
38
  manifest: SandboxControlManifest,
27
39
  request: TaskWorkflowRequest,
28
- lifecycleRecoveryAttestation: LifecycleRecoveryAttestationV1 | null = null
40
+ lifecycleRecoveryAttestation: LifecycleRecoveryAttestationV1 | null = null,
41
+ options: TaskWorkflowExecutionOptions = {}
29
42
  ): Promise<SandboxControlExecutionResult> {
30
- let publicationStarted = false;
43
+ let publicationCommitted = false;
44
+ let recoveryObservation: Readonly<{
45
+ family: 'analysis' | 'plan' | 'code' | 'review-analysis' | 'review-plan' | 'review-code';
46
+ artifact: string;
47
+ wasPassed: boolean;
48
+ }> | null = null;
49
+ const observeRecoveryPublication = (): void => {
50
+ if (!recoveryObservation || recoveryObservation.wasPassed) return;
51
+ const intent = readArtifactRecoveryIntent(
52
+ manifest.repoRoot,
53
+ request.taskId,
54
+ recoveryObservation.family,
55
+ recoveryObservation.artifact
56
+ );
57
+ publicationCommitted ||= intent?.state === 'preflight-ready'
58
+ || intent?.state === 'preflight-commit-started'
59
+ || intent?.state === 'preflight-passed'
60
+ || intent?.state === 'passed'
61
+ || intent?.state === 'commit-started';
62
+ };
63
+ let faultTriggered = false;
64
+ const fault = (window: TaskWorkflowFaultWindow): void => {
65
+ if (faultTriggered || options.faultWindow !== window) return;
66
+ faultTriggered = true;
67
+ throw new Error(`TASK_WORKFLOW_FAULT_INJECTED:${window}`);
68
+ };
69
+ const response = (result: Record<string, unknown>): SandboxControlExecutionResult => {
70
+ fault('before-result-return');
71
+ return executionResult(result);
72
+ };
31
73
  try {
74
+ fault('before-call');
32
75
  const taskDir = assertSandboxTaskSource(manifest.repoRoot, request.taskId);
33
76
  const [command] = TASK_WORKFLOW_COMMANDS[request.operation];
34
77
  if (request.operation === 'event') {
@@ -36,67 +79,95 @@ export async function executeTaskWorkflow(
36
79
  const boundEventRequest = lifecycleRecoveryAttestation && eventRequest.requestId === undefined
37
80
  ? { ...eventRequest, requestId: lifecycleRecoveryAttestation.lifecycleRequestId }
38
81
  : eventRequest;
82
+ fault('before-domain-write');
39
83
  const result = applyTaskEvent(boundEventRequest, {
40
84
  repoRoot: manifest.repoRoot,
41
85
  lifecycleRecoveryAttestation,
42
86
  deferLifecycleRecoveryConsumption: true
43
87
  });
44
- return executionResult(result);
88
+ publicationCommitted = result.changed;
89
+ fault('after-atomic-rename');
90
+ return response(result);
45
91
  }
46
92
  if (command !== 'task-artifact' && command !== 'task-review') {
47
- publicationStarted = true;
48
- // Inherit this executor's process group so its existing recovery owns the worker too.
49
- const result = await dispatchHostControlCommand({
50
- operation: command, payload: { workingDirectory: manifest.repoRoot, args: request.args }
51
- });
52
- return result;
93
+ // The broker owns this short-lived executor; no global service or worker
94
+ // credential participates in the command's authority or recovery path.
95
+ fault('before-domain-write');
96
+ const result = dispatchWorkflowCommand(manifest.repoRoot, request.operation, request.args);
97
+ publicationCommitted = result.changed === true;
98
+ fault('after-atomic-rename');
99
+ return response(result);
53
100
  }
54
101
  const input = command === 'task-artifact' ? parseArtifactCommand(request.args) : parseReviewCommand(request.args);
55
102
  if (command === 'task-artifact' && 'operation' in input && input.operation === 'inspect') {
56
- return executionResult(executeArtifactCommand(input, { repoRoot: manifest.repoRoot }));
103
+ fault('before-domain-write');
104
+ const result = executeArtifactCommand(input, { repoRoot: manifest.repoRoot });
105
+ publicationCommitted = result.changed === true;
106
+ fault('after-atomic-rename');
107
+ return response(result);
57
108
  }
58
- if ('operation' in input && (input.operation === 'init' || input.operation === 'repair')) {
59
- return executionResult(executeArtifactCommand(input, { repoRoot: manifest.repoRoot, artifactDir: taskDir }));
109
+ if ('operation' in input && input.operation === 'init') {
110
+ fault('before-domain-write');
111
+ const result = executeArtifactCommand(input, { repoRoot: manifest.repoRoot, artifactDir: taskDir });
112
+ publicationCommitted = result.changed === true;
113
+ fault('after-atomic-rename');
114
+ return response(result);
60
115
  }
61
116
  return await withTaskExecutionLock(manifest.repoRoot, request.taskId, `sandbox-control.${request.operation}`, async () => {
62
117
  const artifact = await readTaskArtifact(taskDir, { artifact: input.artifact });
63
118
  const content = artifact.bytes.toString('utf8');
119
+ fault('before-domain-write');
64
120
  let result: Record<string, unknown>;
65
121
  if ('operation' in input) {
66
122
  const { family } = input;
67
123
  if (family !== 'analysis' && family !== 'plan' && family !== 'code') throw new Error('ARTIFACT_IDENTITY_INVALID');
68
- const local = { taskRef: request.taskId, family, artifact: input.artifact, repoRoot: manifest.repoRoot } as const;
124
+ const local = { taskRef: request.taskId, family, artifact: input.artifact, repoRoot: manifest.repoRoot, recoveryId: input.recoveryId, lockAlreadyHeld: true } as const;
125
+ if (input.operation === 'preflight') {
126
+ // Preflight only seals a verified generation. It must not publish the
127
+ // formal artifact, set publicationStarted, or append finalizer audit.
128
+ const result = preflightLocalArtifact(local);
129
+ recoveryObservation = { family, artifact: input.artifact, wasPassed: false };
130
+ observeRecoveryPublication();
131
+ return response(result);
132
+ }
133
+ recoveryObservation = {
134
+ family,
135
+ artifact: input.artifact,
136
+ wasPassed: readArtifactRecoveryIntent(manifest.repoRoot, request.taskId, family, input.artifact)?.state === 'passed'
137
+ };
69
138
  const prepared = prepareLocalArtifact(local, content, lifecycleRecoveryAttestation ?? undefined);
70
- if (prepared.result.status === 'failed') return executionResult(commitLocalArtifactProvenance(prepared));
71
- publicationStarted = true;
72
- await writeTaskArtifact(taskDir, {
73
- artifact: artifact.artifact,
74
- bytes: artifact.bytes,
75
- expectedSha256: artifact.sha256
76
- });
77
- result = commitLocalArtifactProvenance(prepared);
139
+ observeRecoveryPublication();
140
+ const commitOptions = { afterPublish: () => fault('after-atomic-rename') };
141
+ if (prepared.result.status === 'failed') return executionResult(commitLocalArtifactProvenance(prepared, commitOptions));
142
+ result = commitLocalArtifactProvenance(prepared, commitOptions);
78
143
  } else {
79
144
  if (input.overrideTicket) throw new Error('TASK_WORKFLOW_OVERRIDE_UNSUPPORTED');
80
- const prepared = prepareReviewSummaryCandidate(input, content, { repoRoot: manifest.repoRoot });
81
- if (input.dryRun || prepared.result.status === 'planned') return executionResult(prepared.result);
82
- if (prepared.result.status === 'failed') return executionResult(commitReviewSummaryProvenance(prepared, manifest.repoRoot));
83
- publicationStarted = true;
84
- await writeTaskArtifact(taskDir, {
145
+ const family = `review-${input.stage}` as 'review-analysis' | 'review-plan' | 'review-code';
146
+ recoveryObservation = {
147
+ family,
85
148
  artifact: input.artifact,
86
- bytes: Buffer.from(prepared.content, 'utf8'),
87
- expectedSha256: artifact.sha256
88
- });
89
- result = commitReviewSummaryProvenance(prepared, manifest.repoRoot);
149
+ wasPassed: readArtifactRecoveryIntent(manifest.repoRoot, request.taskId, family, input.artifact)?.state === 'passed'
150
+ };
151
+ const prepared = prepareReviewSummaryCandidate(input, content, { repoRoot: manifest.repoRoot, lockAlreadyHeld: true, startRecovery: true });
152
+ observeRecoveryPublication();
153
+ if (input.dryRun || prepared.result.status === 'planned') return executionResult(prepared.result);
154
+ const commitOptions = { afterPublish: () => fault('after-atomic-rename') };
155
+ if (prepared.result.status === 'failed') return executionResult(commitReviewSummaryProvenance(prepared, manifest.repoRoot, commitOptions));
156
+ result = commitReviewSummaryProvenance(prepared, manifest.repoRoot, commitOptions);
90
157
  }
158
+ observeRecoveryPublication();
159
+ publicationCommitted ||= result.changed === true;
91
160
  if (result.status !== 'failed') appendDiagnosticAudit(manifest, 'task-workflow-artifact-finalized', {
92
161
  requestId: request.id, sandboxTaskId: request.taskId, workflowOperation: request.operation,
93
162
  artifact: input.artifact, sha256: result.artifactSha256 as string, semanticDigest: result.semanticDigest as string
94
163
  });
95
- return executionResult({ ...result, changed: true });
164
+ fault('after-atomic-rename');
165
+ return response(result);
96
166
  });
97
167
  } catch (error) {
168
+ observeRecoveryPublication();
98
169
  const message = error instanceof Error ? error.message : String(error);
99
170
  const code = (error as { code?: string })?.code ?? /^([A-Z][A-Z0-9_]+)/u.exec(message)?.[1] ?? 'TASK_WORKFLOW_REQUEST_INVALID';
100
- return executionResult({ status: 'failed', changed: publicationStarted ? null : false, error: { code, message } });
171
+ return executionResult({ status: 'failed', changed: publicationCommitted ? null : false, error: { code, message } });
101
172
  }
102
173
  }
@@ -20,8 +20,7 @@ Commands:
20
20
  rm <branch | TASK-id> | --unbound | --purge
21
21
  Remove one sandbox; use a full TASK-id for task-bound
22
22
  cleanup and a branch for branch-only cleanup. --unbound
23
- removes completed task-bound and branch-only sandboxes
24
- plus verified auxiliary state; active, blocked, and archive tasks are protected.
23
+ removes discovered task-bound and branch-only sandboxes.
25
24
  start [--recreate] <branch | TASK-id | N>
26
25
  Verify or recover an existing sandbox container;
27
26
  optionally replace only the container on failure