@fitlab-ai/agent-infra 0.11.9 → 0.11.10

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 (124) hide show
  1. package/dist/bin/internal-cli.js +0 -6
  2. package/dist/lib/git/workflow.js +1 -1
  3. package/dist/lib/internal/cli-route-inventory.js +0 -3
  4. package/dist/lib/internal/sandbox-control.js +30 -5
  5. package/dist/lib/internal/task-finalization.js +14 -23
  6. package/dist/lib/internal/task-operation-registry.js +2 -3
  7. package/dist/lib/internal/task-platform-recovery.js +9 -4
  8. package/dist/lib/platform/completion-backfill.js +2 -1
  9. package/dist/lib/platform/context.js +4 -2
  10. package/dist/lib/platform/github-client.js +20 -17
  11. package/dist/lib/platform/github-provider.js +42 -22
  12. package/dist/lib/platform/github-release-notes.js +4 -2
  13. package/dist/lib/platform/in-label-sync.js +2 -1
  14. package/dist/lib/platform/issue-comments.js +13 -9
  15. package/dist/lib/platform/operation-coordinator.js +1 -1
  16. package/dist/lib/platform/pr-review.js +2 -1
  17. package/dist/lib/platform/provider-bridge.js +4 -5
  18. package/dist/lib/platform/provider-contract.d.ts +3 -6
  19. package/dist/lib/platform/provider-contract.js +3 -15
  20. package/dist/lib/platform/provider-validation.js +9 -4
  21. package/dist/lib/platform/pull-requests.js +4 -2
  22. package/dist/lib/sandbox/control/client.js +54 -6
  23. package/dist/lib/sandbox/control/executor.js +8 -3
  24. package/dist/lib/sandbox/removal.js +0 -1
  25. package/dist/lib/task/artifact-command.js +11 -1
  26. package/dist/lib/task/artifact-lifecycle.js +119 -62
  27. package/dist/lib/task/artifact-selection.js +1 -1
  28. package/dist/lib/task/capabilities.js +55 -21
  29. package/dist/lib/task/commands/status.js +0 -27
  30. package/dist/lib/task/commit-identity.js +22 -7
  31. package/dist/lib/task/commit-intent.js +67 -26
  32. package/dist/lib/task/commit-operation.js +19 -8
  33. package/dist/lib/task/completion-facts.js +32 -10
  34. package/dist/lib/task/control-authority.js +2 -4
  35. package/dist/lib/task/current-contract.js +1 -5
  36. package/dist/lib/task/events.js +8 -274
  37. package/dist/lib/task/execution-inputs.js +14 -0
  38. package/dist/lib/task/finalization-envelope.js +4 -0
  39. package/dist/lib/task/finalization.js +10 -36
  40. package/dist/lib/task/frontmatter.js +1 -1
  41. package/dist/lib/task/ledger-intents.js +4 -7
  42. package/dist/lib/task/orchestration.js +11 -10
  43. package/dist/lib/task/platform-operation-journal.js +17 -10
  44. package/dist/lib/task/platform-operation-recovery.js +95 -28
  45. package/dist/lib/task/review-fingerprint.js +4 -26
  46. package/dist/lib/task/verification-engine.js +95 -6
  47. package/dist/lib/task/write.js +0 -11
  48. package/dist/lifecycle-build-manifest.json +3 -3
  49. package/lib/git/workflow.ts +1 -1
  50. package/lib/internal/cli-route-inventory.ts +0 -2
  51. package/lib/internal/sandbox-control.ts +39 -6
  52. package/lib/internal/task-finalization.ts +16 -24
  53. package/lib/internal/task-operation-registry.ts +2 -3
  54. package/lib/internal/task-platform-recovery.ts +9 -4
  55. package/lib/platform/completion-backfill.ts +2 -1
  56. package/lib/platform/context.ts +8 -4
  57. package/lib/platform/github-client.ts +24 -20
  58. package/lib/platform/github-provider.ts +47 -26
  59. package/lib/platform/github-release-notes.ts +5 -3
  60. package/lib/platform/in-label-sync.ts +2 -1
  61. package/lib/platform/issue-comments.ts +14 -9
  62. package/lib/platform/operation-coordinator.ts +1 -1
  63. package/lib/platform/pr-review.ts +2 -1
  64. package/lib/platform/provider-bridge.ts +10 -9
  65. package/lib/platform/provider-contract.ts +6 -21
  66. package/lib/platform/provider-loader.ts +7 -6
  67. package/lib/platform/provider-validation.ts +30 -8
  68. package/lib/platform/pull-requests.ts +4 -2
  69. package/lib/platform/repository-metadata.ts +3 -2
  70. package/lib/platform/security-alerts.ts +1 -1
  71. package/lib/platform/types.ts +2 -0
  72. package/lib/sandbox/control/client.ts +57 -6
  73. package/lib/sandbox/control/executor.ts +8 -3
  74. package/lib/sandbox/removal.ts +2 -10
  75. package/lib/task/artifact-command.ts +10 -1
  76. package/lib/task/artifact-lifecycle.ts +100 -52
  77. package/lib/task/artifact-selection.ts +1 -1
  78. package/lib/task/capabilities.ts +47 -24
  79. package/lib/task/commands/status.ts +0 -31
  80. package/lib/task/commit-identity.ts +24 -7
  81. package/lib/task/commit-intent.ts +58 -24
  82. package/lib/task/commit-operation.ts +17 -8
  83. package/lib/task/completion-facts.ts +31 -9
  84. package/lib/task/control-authority.ts +1 -4
  85. package/lib/task/current-contract.ts +1 -6
  86. package/lib/task/events.ts +8 -247
  87. package/lib/task/execution-inputs.ts +25 -0
  88. package/lib/task/finalization-envelope.ts +21 -0
  89. package/lib/task/finalization.ts +10 -35
  90. package/lib/task/frontmatter.ts +1 -1
  91. package/lib/task/ledger-intents.ts +4 -7
  92. package/lib/task/orchestration.ts +11 -17
  93. package/lib/task/platform-operation-journal.ts +18 -11
  94. package/lib/task/platform-operation-recovery.ts +90 -31
  95. package/lib/task/review-fingerprint.ts +4 -26
  96. package/lib/task/verification-engine.ts +103 -9
  97. package/lib/task/write.ts +0 -19
  98. package/package.json +1 -1
  99. package/templates/.agents/rules/commit-and-pr.en.md +5 -5
  100. package/templates/.agents/rules/commit-and-pr.zh-CN.md +5 -5
  101. package/templates/.agents/rules/decision-qualification.en.md +1 -1
  102. package/templates/.agents/rules/decision-qualification.zh-CN.md +1 -1
  103. package/templates/.agents/skills/code-task/SKILL.en.md +25 -9
  104. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +26 -9
  105. package/templates/.agents/skills/code-task/reference/code-rules.en.md +1 -1
  106. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +1 -1
  107. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +5 -16
  108. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +5 -16
  109. package/templates/.agents/skills/code-task/reference/report-template.en.md +1 -1
  110. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +1 -1
  111. package/templates/.agents/skills/complete-task/SKILL.en.md +15 -12
  112. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +11 -10
  113. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +1 -1
  114. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +1 -1
  115. package/templates/.agents/templates/task.zh-CN.md +0 -12
  116. package/templates/.github/workflows/pr-label.yml +1 -2
  117. package/dist/lib/internal/task-invalidation.js +0 -63
  118. package/dist/lib/task/intermediate-cleanup.js +0 -327
  119. package/dist/lib/task/invalidation-command.js +0 -88
  120. package/dist/lib/task/invalidation.js +0 -242
  121. package/lib/internal/task-invalidation.ts +0 -41
  122. package/lib/task/intermediate-cleanup.ts +0 -393
  123. package/lib/task/invalidation-command.ts +0 -88
  124. package/lib/task/invalidation.ts +0 -313
@@ -1,11 +1,18 @@
1
- import { createHash } from 'node:crypto';
1
+ import { createHash, randomBytes } from 'node:crypto';
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
- function intentRoot(repoRoot) {
5
- return path.join(repoRoot, '.agents', 'workspace', '.task-commit-intents');
4
+ const MAX_INTENT_SIZE = 1024 * 1024;
5
+ const TASK_ID_PATTERN = /^TASK-\d{8}-\d{6}$/;
6
+ function intentPath(taskDir) {
7
+ return path.join(taskDir, '.checkpoint-intent.json');
6
8
  }
7
- function intentPath(repoRoot, taskId) {
8
- return path.join(intentRoot(repoRoot), `${taskId}.json`);
9
+ function assertTaskDirectory(taskDir, taskId) {
10
+ if (!TASK_ID_PATTERN.test(taskId) || path.basename(path.resolve(taskDir)) !== taskId) {
11
+ throw new Error('COMMIT_INTENT_INVALID: task directory does not match task ID');
12
+ }
13
+ const stat = fs.statSync(taskDir);
14
+ if (!stat.isDirectory())
15
+ throw new Error('COMMIT_INTENT_INVALID: task directory is not a directory');
9
16
  }
10
17
  function checkpointIntentDigest(identity) {
11
18
  return createHash('sha256').update(JSON.stringify({
@@ -23,8 +30,13 @@ function isIntent(value) {
23
30
  if (!value || typeof value !== 'object' || Array.isArray(value))
24
31
  return false;
25
32
  const intent = value;
33
+ const validState = ['prepared', 'committed', 'synced'].includes(String(intent.state));
34
+ const validHead = intent.committedHead === null
35
+ ? intent.state === 'prepared'
36
+ : typeof intent.committedHead === 'string' && /^[a-f0-9]{40,64}$/.test(intent.committedHead)
37
+ && intent.state !== 'prepared';
26
38
  return intent.version === 1
27
- && typeof intent.taskId === 'string' && intent.taskId.length > 0
39
+ && typeof intent.taskId === 'string' && TASK_ID_PATTERN.test(intent.taskId)
28
40
  && typeof intent.branch === 'string' && intent.branch.length > 0
29
41
  && intent.mode === 'local'
30
42
  && typeof intent.expectedHead === 'string' && /^[a-f0-9]{40,64}$/.test(intent.expectedHead)
@@ -33,28 +45,57 @@ function isIntent(value) {
33
45
  && typeof intent.message === 'string' && intent.message.length > 0
34
46
  && Number.isSafeInteger(intent.round) && Number(intent.round) > 0
35
47
  && typeof intent.digest === 'string' && /^[a-f0-9]{64}$/.test(intent.digest)
36
- && ['prepared', 'committed', 'synced'].includes(String(intent.state))
37
- && (intent.committedHead === null || (typeof intent.committedHead === 'string' && /^[a-f0-9]{40,64}$/.test(intent.committedHead)))
48
+ && validState && validHead
38
49
  && typeof intent.createdAt === 'string' && intent.createdAt.length > 0
39
50
  && typeof intent.updatedAt === 'string' && intent.updatedAt.length > 0
40
51
  && intent.digest === checkpointIntentDigest(intent);
41
52
  }
42
- function readCheckpointIntent(repoRoot, taskId) {
43
- const target = intentPath(repoRoot, taskId);
44
- if (!fs.existsSync(target))
45
- return null;
46
- const value = JSON.parse(fs.readFileSync(target, 'utf8'));
47
- if (!isIntent(value))
48
- throw new Error('COMMIT_INTENT_INVALID: checkpoint intent schema is invalid');
49
- return value;
53
+ function invalidIntent() {
54
+ throw new Error('COMMIT_INTENT_INVALID: checkpoint intent schema is invalid');
55
+ }
56
+ function readCheckpointIntent(taskDir, taskId) {
57
+ assertTaskDirectory(taskDir, taskId);
58
+ const target = intentPath(taskDir);
59
+ let before;
60
+ try {
61
+ before = fs.lstatSync(target);
62
+ }
63
+ catch (error) {
64
+ if (error.code === 'ENOENT')
65
+ return null;
66
+ throw error;
67
+ }
68
+ if (!before.isFile() || before.isSymbolicLink() || before.size > MAX_INTENT_SIZE)
69
+ return invalidIntent();
70
+ let descriptor;
71
+ try {
72
+ const noFollow = typeof fs.constants.O_NOFOLLOW === 'number' ? fs.constants.O_NOFOLLOW : 0;
73
+ descriptor = fs.openSync(target, fs.constants.O_RDONLY | noFollow);
74
+ const opened = fs.fstatSync(descriptor);
75
+ if (!opened.isFile() || opened.dev !== before.dev || opened.ino !== before.ino
76
+ || opened.size !== before.size || opened.size > MAX_INTENT_SIZE)
77
+ return invalidIntent();
78
+ const value = JSON.parse(fs.readFileSync(descriptor, 'utf8'));
79
+ if (!isIntent(value) || value.taskId !== taskId)
80
+ return invalidIntent();
81
+ return value;
82
+ }
83
+ catch (error) {
84
+ if (error instanceof Error && error.message.startsWith('COMMIT_INTENT_INVALID:'))
85
+ throw error;
86
+ return invalidIntent();
87
+ }
88
+ finally {
89
+ if (descriptor !== undefined)
90
+ fs.closeSync(descriptor);
91
+ }
50
92
  }
51
- function writeCheckpointIntent(repoRoot, value) {
93
+ function writeCheckpointIntent(taskDir, value) {
94
+ assertTaskDirectory(taskDir, value.taskId);
52
95
  if (!isIntent(value))
53
- throw new Error('COMMIT_INTENT_INVALID: checkpoint intent schema is invalid');
54
- const directory = intentRoot(repoRoot);
55
- fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
56
- const target = intentPath(repoRoot, value.taskId);
57
- const temporary = `${target}.${process.pid}.${Date.now()}.tmp`;
96
+ return invalidIntent();
97
+ const target = intentPath(taskDir);
98
+ const temporary = `${target}.${process.pid}.${randomBytes(8).toString('hex')}.tmp`;
58
99
  fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
59
100
  try {
60
101
  fs.renameSync(temporary, target);
@@ -75,10 +116,10 @@ function updateCheckpointIntent(value, patch) {
75
116
  throw new Error('COMMIT_INTENT_INVALID: committed intent requires a committed head');
76
117
  return next;
77
118
  }
78
- function removeCheckpointIntent(repoRoot, taskId) {
79
- const target = intentPath(repoRoot, taskId);
119
+ function removeCheckpointIntent(taskDir, taskId) {
120
+ assertTaskDirectory(taskDir, taskId);
80
121
  try {
81
- fs.unlinkSync(target);
122
+ fs.unlinkSync(intentPath(taskDir));
82
123
  }
83
124
  catch (error) {
84
125
  if (error.code !== 'ENOENT')
@@ -96,5 +137,5 @@ function sameCheckpointIntent(left, right) {
96
137
  && left.round === right.round
97
138
  && JSON.stringify(left.paths) === JSON.stringify(right.paths);
98
139
  }
99
- export { checkpointIntentDigest, intentPath, intentRoot, isIntent, readCheckpointIntent, removeCheckpointIntent, sameCheckpointIntent, updateCheckpointIntent, writeCheckpointIntent };
140
+ export { checkpointIntentDigest, intentPath, isIntent, readCheckpointIntent, removeCheckpointIntent, sameCheckpointIntent, updateCheckpointIntent, writeCheckpointIntent };
100
141
  //# sourceMappingURL=commit-intent.js.map
@@ -206,7 +206,7 @@ function executeUnlocked(input, task, mode) {
206
206
  ? (() => {
207
207
  const identity = checkpointIdentity(input, task, delivery);
208
208
  try {
209
- pendingIntent = readCheckpointIntent(task.repoRoot, task.taskId);
209
+ pendingIntent = readCheckpointIntent(task.taskDir, task.taskId);
210
210
  }
211
211
  catch (error) {
212
212
  return {
@@ -215,6 +215,11 @@ function executeUnlocked(input, task, mode) {
215
215
  };
216
216
  }
217
217
  if (pendingIntent && !sameCheckpointIntent(pendingIntent, identity)) {
218
+ if (pendingIntent.state !== 'prepared')
219
+ return {
220
+ status: 'failed', changed: false, snapshot: inspected.snapshot, operations: [],
221
+ error: { code: 'COMMIT_INTENT_INVALID', message: 'A committed checkpoint intent must be recovered with its original request' }
222
+ };
218
223
  const timestamp = checkpointTimestamp();
219
224
  pendingIntent = {
220
225
  version: 1, ...identity,
@@ -222,7 +227,7 @@ function executeUnlocked(input, task, mode) {
222
227
  state: 'prepared', committedHead: null, createdAt: timestamp, updatedAt: timestamp
223
228
  };
224
229
  try {
225
- writeCheckpointIntent(task.repoRoot, pendingIntent);
230
+ writeCheckpointIntent(task.taskDir, pendingIntent);
226
231
  }
227
232
  catch (error) {
228
233
  return {
@@ -231,6 +236,12 @@ function executeUnlocked(input, task, mode) {
231
236
  };
232
237
  }
233
238
  }
239
+ if (pendingIntent && pendingIntent.state !== 'prepared'
240
+ && !checkpointCommitMatches(task.repoRoot, pendingIntent, pendingIntent.committedHead))
241
+ return {
242
+ status: 'failed', changed: false, snapshot: inspected.snapshot, operations: [],
243
+ error: { code: 'COMMIT_INTENT_INVALID', message: 'Committed checkpoint intent does not match its Git commit' }
244
+ };
234
245
  if (!pendingIntent) {
235
246
  const timestamp = checkpointTimestamp();
236
247
  pendingIntent = {
@@ -238,7 +249,7 @@ function executeUnlocked(input, task, mode) {
238
249
  committedHead: null, createdAt: timestamp, updatedAt: timestamp
239
250
  };
240
251
  try {
241
- writeCheckpointIntent(task.repoRoot, pendingIntent);
252
+ writeCheckpointIntent(task.taskDir, pendingIntent);
242
253
  }
243
254
  catch (error) {
244
255
  return {
@@ -264,7 +275,7 @@ function executeUnlocked(input, task, mode) {
264
275
  pendingIntent = updateCheckpointIntent(pendingIntent, {
265
276
  state: 'committed', committedHead: checkpointCommittedHead, updatedAt: checkpointTimestamp()
266
277
  });
267
- writeCheckpointIntent(task.repoRoot, pendingIntent);
278
+ writeCheckpointIntent(task.taskDir, pendingIntent);
268
279
  return {
269
280
  status: 'no-op', changed: false, snapshot: inspected.snapshot,
270
281
  operations: [{ name: 'commit', status: 'no-op' }], error: null
@@ -284,10 +295,10 @@ function executeUnlocked(input, task, mode) {
284
295
  pendingIntent = updateCheckpointIntent(pendingIntent, {
285
296
  state: 'committed', committedHead: checkpointCommittedHead, updatedAt: checkpointTimestamp()
286
297
  });
287
- writeCheckpointIntent(task.repoRoot, pendingIntent);
298
+ writeCheckpointIntent(task.taskDir, pendingIntent);
288
299
  }
289
300
  else if (created.status === 'no-op') {
290
- removeCheckpointIntent(task.repoRoot, task.taskId);
301
+ removeCheckpointIntent(task.taskDir, task.taskId);
291
302
  pendingIntent = null;
292
303
  }
293
304
  return created;
@@ -377,8 +388,8 @@ function executeUnlocked(input, task, mode) {
377
388
  const synced = updateCheckpointIntent(pendingIntent, {
378
389
  state: 'synced', committedHead: checkpointCommittedHead, updatedAt: checkpointTimestamp()
379
390
  });
380
- writeCheckpointIntent(task.repoRoot, synced);
381
- removeCheckpointIntent(task.repoRoot, task.taskId);
391
+ writeCheckpointIntent(task.taskDir, synced);
392
+ removeCheckpointIntent(task.taskDir, task.taskId);
382
393
  }
383
394
  }
384
395
  return {
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import { canonicalSemanticDigest } from './artifact-operations.js';
3
- import { inspectActivityLog } from './activity-log.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';
@@ -39,18 +39,40 @@ export function hasArtifactCompletionFact(taskContent, artifactPath, event) {
39
39
  }
40
40
  }
41
41
  export function hasArtifactCompletionLog(taskContent, artifact, event) {
42
+ return artifactCompletionOrder(taskContent, artifact, event) !== null;
43
+ }
44
+ /** Returns the stable Activity Log position of a paired completion row. */
45
+ export function artifactCompletionOrder(taskContent, artifact, event) {
42
46
  const identity = parseArtifactName(artifact);
43
47
  if (!identity)
44
- return false;
45
- const action = event === 'review-code.completed' ? 'Review Code'
46
- : event === 'review-plan.completed' ? 'Review Plan'
47
- : event === 'review-analysis.completed' ? 'Review Analysis' : null;
48
- if (!action)
49
- return false;
48
+ 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';
50
62
  const { section, invalidEntries } = inspectActivityLog(taskContent);
51
63
  if (!section || invalidEntries.length > 0)
52
- return false;
53
- const expected = `${action} (Round ${identity.round})`;
54
- return section.entries.some((entry) => entry.step === expected && entry.note.includes(`→ ${artifact}`));
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;
55
77
  }
56
78
  //# sourceMappingURL=completion-facts.js.map
@@ -4,7 +4,7 @@ import { normalizeAgentToken } from '../agent-clients/tokens.js';
4
4
  import { isAgentClientId } from '../agent-clients/types.js';
5
5
  import { getAgentClientAdapter } from '../agent-clients/registry.js';
6
6
  import { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, advanceOrchestration, awaitOrchestrationDelegationActivation, beginOrResumeOrchestration, dispatchOrchestrationDelegation, OrchestrationStateError, pauseOrchestration, prepareOrchestrationDelegation, recoverPreparedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealOrchestrationDelegation, statusOrchestration } from './orchestration.js';
7
- import { applyTaskFinalization, commitPreparedTaskFinalization } from './finalization.js';
7
+ import { applyTaskFinalization } from './finalization.js';
8
8
  import { applyTaskLifecycle, taskLifecycleFailure } from './lifecycle.js';
9
9
  import { resolveTaskRef, TASK_ID_RE } from './resolve-ref.js';
10
10
  import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
@@ -434,12 +434,10 @@ export function dispatchTaskControlOperation(context, operation) {
434
434
  }
435
435
  if (operation.family === 'task-finalization') {
436
436
  operationTaskId(context, operation.request.taskRef);
437
- const finalize = context.source === 'sandbox-executor' ? commitPreparedTaskFinalization : applyTaskFinalization;
438
- return finalize(operation.request, {
437
+ return applyTaskFinalization(operation.request, {
439
438
  repoRoot: context.repoRoot,
440
439
  ...(context.source === 'sandbox-executor' ? {
441
440
  controlBinding: { generation: context.generation, requestId: context.requestId },
442
- handoffDirectory: context.handoffDirectory,
443
441
  manifestPath: context.manifestPath
444
442
  } : {}),
445
443
  preflight: (request, options) => verifyTaskEvent({ ...request, event: 'complete-task.hard-preflight' }, options)
@@ -1,7 +1,6 @@
1
1
  import { isValidAgentInfraVersion } from '../version.js';
2
2
  import { parseTypedTaskFrontmatter } from './frontmatter.js';
3
3
  import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, validateLedgerRows } from './ledger.js';
4
- import { parseInvalidationDocument } from './invalidation.js';
5
4
  function validateCurrentTaskContract(content) {
6
5
  let metadata;
7
6
  try {
@@ -30,10 +29,7 @@ function validateCurrentTaskContract(content) {
30
29
  const invalid = validateLedgerRows(ledger.rows);
31
30
  if (invalid)
32
31
  return { ok: false, code: 'TASK_CURRENT_CONTRACT_INVALID', message: `${invalid.code}: ${invalid.message}` };
33
- const invalidation = parseInvalidationDocument(content);
34
- if (!invalidation.ok)
35
- return { ok: false, code: 'TASK_CURRENT_CONTRACT_INVALID', message: `${invalidation.code}: ${invalidation.message}` };
36
- return { ok: true, metadata, ledger, invalidation: invalidation.document };
32
+ return { ok: true, metadata, ledger };
37
33
  }
38
34
  export { validateCurrentTaskContract };
39
35
  //# sourceMappingURL=current-contract.js.map