@fitlab-ai/agent-infra 0.11.4 → 0.11.5

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 (111) hide show
  1. package/dist/bin/internal-cli.js +0 -5
  2. package/dist/lib/decide.js +4 -41
  3. package/dist/lib/git/branch-worktree.js +45 -0
  4. package/dist/lib/internal/cli-route-inventory.js +0 -3
  5. package/dist/lib/internal/task-activity.js +7 -40
  6. package/dist/lib/internal/task-event.js +4 -37
  7. package/dist/lib/internal/task-finalization.js +9 -2
  8. package/dist/lib/internal/task-ledger.js +5 -43
  9. package/dist/lib/internal/task-lifecycle.js +1 -1
  10. package/dist/lib/internal/task-operation-registry.js +1 -4
  11. package/dist/lib/internal/task-review.js +5 -37
  12. package/dist/lib/internal/task-verify.js +3 -47
  13. package/dist/lib/internal/task-warning.js +4 -40
  14. package/dist/lib/platform/pr-summary.js +4 -23
  15. package/dist/lib/platform/verification-sync.js +12 -49
  16. package/dist/lib/sandbox/control/client.js +4 -1
  17. package/dist/lib/sandbox/control/executor.js +12 -4
  18. package/dist/lib/sandbox/control/protocol.js +2 -1
  19. package/dist/lib/sandbox/removal.js +15 -8
  20. package/dist/lib/task/activity-intent.js +1 -2
  21. package/dist/lib/task/artifact-operations.js +36 -2
  22. package/dist/lib/task/artifact-schema.js +7 -7
  23. package/dist/lib/task/control-authority.js +9 -166
  24. package/dist/lib/task/decision-intents.js +2 -4
  25. package/dist/lib/task/events.js +7 -28
  26. package/dist/lib/task/finalization-handoff.js +92 -0
  27. package/dist/lib/task/finalization.js +123 -12
  28. package/dist/lib/task/intermediate-cleanup.js +9 -148
  29. package/dist/lib/task/ledger-intents.js +3 -6
  30. package/dist/lib/task/lifecycle.js +50 -11
  31. package/dist/lib/task/local-artifact-finalization.js +13 -28
  32. package/dist/lib/task/review-command.js +1 -2
  33. package/dist/lib/task/review-finalization.js +1 -2
  34. package/dist/lib/task/snapshot.js +6 -6
  35. package/dist/lib/task/verification-engine.js +16 -11
  36. package/dist/lib/task/verification.js +1 -13
  37. package/dist/lib/task/workflow-warning-intents.js +2 -4
  38. package/dist/lib/task/write.js +1 -2
  39. package/dist/lifecycle-build-manifest.json +3 -3
  40. package/lib/decide.ts +5 -35
  41. package/lib/git/branch-worktree.ts +41 -0
  42. package/lib/internal/cli-route-inventory.ts +0 -2
  43. package/lib/internal/task-activity.ts +6 -34
  44. package/lib/internal/task-event.ts +4 -37
  45. package/lib/internal/task-finalization.ts +9 -2
  46. package/lib/internal/task-ledger.ts +5 -38
  47. package/lib/internal/task-lifecycle.ts +2 -2
  48. package/lib/internal/task-operation-registry.ts +1 -4
  49. package/lib/internal/task-review.ts +5 -31
  50. package/lib/internal/task-verify.ts +3 -39
  51. package/lib/internal/task-warning.ts +3 -32
  52. package/lib/platform/pr-summary.ts +4 -25
  53. package/lib/platform/verification-sync.ts +13 -53
  54. package/lib/sandbox/control/client.ts +5 -1
  55. package/lib/sandbox/control/executor.ts +13 -4
  56. package/lib/sandbox/control/protocol.ts +3 -2
  57. package/lib/sandbox/removal.ts +23 -7
  58. package/lib/task/activity-intent.ts +1 -2
  59. package/lib/task/artifact-operations.ts +58 -2
  60. package/lib/task/artifact-schema.ts +9 -7
  61. package/lib/task/control-authority.ts +14 -188
  62. package/lib/task/decision-intents.ts +2 -4
  63. package/lib/task/events.ts +8 -27
  64. package/lib/task/finalization-handoff.ts +104 -0
  65. package/lib/task/finalization.ts +120 -12
  66. package/lib/task/intermediate-cleanup.ts +9 -125
  67. package/lib/task/ledger-intents.ts +3 -6
  68. package/lib/task/lifecycle.ts +45 -13
  69. package/lib/task/local-artifact-finalization.ts +16 -35
  70. package/lib/task/review-command.ts +2 -5
  71. package/lib/task/review-finalization.ts +1 -4
  72. package/lib/task/snapshot.ts +6 -6
  73. package/lib/task/verification-engine.ts +20 -10
  74. package/lib/task/verification.ts +1 -15
  75. package/lib/task/workflow-warning-intents.ts +2 -4
  76. package/lib/task/write.ts +1 -4
  77. package/package.json +1 -1
  78. package/templates/.agents/skills/analyze-task/SKILL.en.md +11 -2
  79. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -2
  80. package/templates/.agents/skills/code-task/reference/report-template.en.md +6 -6
  81. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +6 -6
  82. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +2 -2
  83. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +2 -2
  84. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +1 -3
  85. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +1 -3
  86. package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
  87. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
  88. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +3 -3
  89. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +3 -3
  90. package/templates/.agents/skills/review-code/reference/report-template.en.md +3 -3
  91. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +3 -3
  92. package/templates/.agents/skills/review-plan/reference/report-template.en.md +3 -3
  93. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +3 -3
  94. package/templates/.agents/skills/review-pr/config/verify.en.json +3 -1
  95. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +3 -1
  96. package/templates/.agents/skills/review-pr/reference/report-template.en.md +3 -3
  97. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +3 -3
  98. package/templates/.agents/skills/run-manual-validation/config/verify.en.json +2 -2
  99. package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +2 -2
  100. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
  101. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
  102. package/dist/lib/internal/task-override.js +0 -138
  103. package/dist/lib/task/artifact-recovery.js +0 -476
  104. package/dist/lib/task/artifact-repair-intent.js +0 -181
  105. package/dist/lib/task/guard-override.js +0 -31
  106. package/dist/lib/task/human-override.js +0 -1259
  107. package/lib/internal/task-override.ts +0 -144
  108. package/lib/task/artifact-recovery.ts +0 -572
  109. package/lib/task/artifact-repair-intent.ts +0 -227
  110. package/lib/task/guard-override.ts +0 -50
  111. package/lib/task/human-override.ts +0 -1522
@@ -240,11 +240,6 @@ if (!controlRouted && !taskViewGuardFailed && internalRouteRegistered)
240
240
  await taskFinalization(process.argv.slice(3));
241
241
  break;
242
242
  }
243
- case 'task-override': {
244
- const { taskOverride } = await import('../lib/internal/task-override.js');
245
- await taskOverride(process.argv.slice(3));
246
- break;
247
- }
248
243
  case 'task-short-id': {
249
244
  const { taskShortId } = await import('../lib/internal/task-short-id.js');
250
245
  taskShortId(process.argv.slice(3));
@@ -2,15 +2,11 @@ import { VERSION } from './version.js';
2
2
  import { parseTaskScope } from './task/command-options.js';
3
3
  import { applyHumanDecision } from './task/decision-intents.js';
4
4
  import { canonicalTimestamp } from './task/write.js';
5
- import { consumeHumanOverride, failureId } from './task/human-override.js';
6
5
  import { resolveTaskContext } from './task/resolve-ref.js';
7
6
  import { TaskExecutionLockError, withTaskExecutionLock } from './task/task-execution-lock.js';
8
7
  function parseDecisionParts(parts) {
9
8
  const decision = [];
10
9
  let needsImplementation;
11
- let overrideTicket;
12
- let overrideTarget;
13
- let overrideScope;
14
10
  for (let index = 0; index < parts.length; index += 1) {
15
11
  const part = parts[index];
16
12
  if (part === '--needs-implementation') {
@@ -22,16 +18,8 @@ function parseDecisionParts(parts) {
22
18
  }
23
19
  needsImplementation = value === 'true';
24
20
  }
25
- else if (part === '--override-ticket' || part === '--override-target' || part === '--override-scope') {
26
- const value = parts[++index];
27
- if (!value)
28
- throw new Error(`${part} requires a value`);
29
- if (part === '--override-ticket')
30
- overrideTicket = value;
31
- else if (part === '--override-target')
32
- overrideTarget = value;
33
- else
34
- overrideScope = value;
21
+ else if (part?.startsWith('--')) {
22
+ throw new Error(`unknown option '${part}'`);
35
23
  }
36
24
  else {
37
25
  decision.push(parts[index]);
@@ -39,7 +27,7 @@ function parseDecisionParts(parts) {
39
27
  }
40
28
  if (decision.length === 0)
41
29
  throw new Error('decision content is required');
42
- return { decision: decision.join(' '), needsImplementation, overrideTicket, overrideTarget, overrideScope };
30
+ return { decision: decision.join(' '), needsImplementation };
43
31
  }
44
32
  export async function decide(args, options = {}) {
45
33
  let scope;
@@ -94,32 +82,7 @@ export async function decide(args, options = {}) {
94
82
  metadataProvider: () => ({ timestamp: now, agentInfraVersion: options.version ?? VERSION })
95
83
  };
96
84
  let result;
97
- const execute = async () => {
98
- let current = applyHumanDecision(request, writeOptions);
99
- if (current.status !== 'failed' || !parsedDecision.overrideTicket)
100
- return current;
101
- if (!parsedDecision.overrideTarget || !parsedDecision.overrideScope)
102
- throw new Error('override ticket requires --override-target and --override-scope');
103
- const consumed = await consumeHumanOverride({
104
- taskRef: resolved.taskId,
105
- ticketId: parsedDecision.overrideTicket,
106
- failureId: failureId('decision-intent', current.error?.code ?? 'TASK_STATE_MISMATCH'),
107
- target: parsedDecision.overrideTarget,
108
- scope: parsedDecision.overrideScope
109
- }, {
110
- ...writeOptions,
111
- effectExecutor: (capability) => {
112
- const retried = applyHumanDecision(request, { ...writeOptions, manualOverride: capability });
113
- current = retried;
114
- return retried.status === 'failed' || retried.status === 'planned'
115
- ? { code: 'OVERRIDE_EFFECT_FAILED', message: retried.status === 'planned' ? 'producer returned planned; no decision effect was committed' : `${retried.error?.code ?? 'DECISION_FAILED'}: ${retried.error?.message ?? 'manual decision effect failed'}` }
116
- : null;
117
- }
118
- });
119
- if (consumed.status === 'failed')
120
- throw new Error(consumed.error.message);
121
- return current;
122
- };
85
+ const execute = async () => applyHumanDecision(request, writeOptions);
123
86
  result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-decision', execute);
124
87
  if (result.error)
125
88
  throw new Error(result.error.message);
@@ -0,0 +1,45 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ function gitText(repositoryRoot, args) {
3
+ try {
4
+ return execFileSync('git', ['-C', repositoryRoot, ...args], {
5
+ encoding: 'utf8',
6
+ stdio: ['ignore', 'pipe', 'pipe']
7
+ }).trim();
8
+ }
9
+ catch {
10
+ return null;
11
+ }
12
+ }
13
+ function verifiedWorktreeRoot(candidate, expectedBranch, expectedCommonDirectory) {
14
+ const commonDirectory = gitText(candidate, ['rev-parse', '--path-format=absolute', '--git-common-dir']);
15
+ if (commonDirectory !== expectedCommonDirectory)
16
+ return null;
17
+ const root = gitText(candidate, ['rev-parse', '--show-toplevel']);
18
+ if (!root)
19
+ return null;
20
+ const branch = gitText(root, ['symbolic-ref', '--short', 'HEAD']);
21
+ return branch === expectedBranch ? root : null;
22
+ }
23
+ export function resolveBranchWorktree(repositoryRoot, expectedBranch) {
24
+ const commonDirectory = gitText(repositoryRoot, ['rev-parse', '--path-format=absolute', '--git-common-dir']);
25
+ if (!commonDirectory)
26
+ return null;
27
+ const currentRoot = verifiedWorktreeRoot(repositoryRoot, expectedBranch, commonDirectory);
28
+ if (currentRoot)
29
+ return currentRoot;
30
+ const records = gitText(repositoryRoot, ['worktree', 'list', '--porcelain']);
31
+ if (!records)
32
+ return null;
33
+ const expectedRef = `refs/heads/${expectedBranch}`;
34
+ for (const record of records.split(/\r?\n\r?\n/)) {
35
+ const candidate = /^worktree (.+)$/m.exec(record)?.[1];
36
+ const branch = /^branch (.+)$/m.exec(record)?.[1];
37
+ if (candidate && branch === expectedRef) {
38
+ const verifiedRoot = verifiedWorktreeRoot(candidate, expectedBranch, commonDirectory);
39
+ if (verifiedRoot)
40
+ return verifiedRoot;
41
+ }
42
+ }
43
+ return null;
44
+ }
45
+ //# sourceMappingURL=branch-worktree.js.map
@@ -58,7 +58,6 @@ export const INTERNAL_HANDLER_ROUTE_SELECTORS = Object.freeze({
58
58
  'task-review': ['preflight', 'finalize-summary'],
59
59
  'task-event': ['event'],
60
60
  'task-invalidation': ['reconcile'],
61
- 'task-override': ['diagnose', 'issue', 'consume'],
62
61
  'task-lifecycle': ['intent'],
63
62
  'task-finalization': ['complete'],
64
63
  'task-short-id': ['list', 'list-verify', 'alloc', 'release', 'resolve'],
@@ -105,8 +104,6 @@ export function internalRouteSelector(command, args) {
105
104
  return args[1] ?? '';
106
105
  if (command === 'task-invalidation')
107
106
  return args[1] ?? '';
108
- if (command === 'task-override')
109
- return args[1] ?? '';
110
107
  if (command === 'task-artifact')
111
108
  return args[1] ?? '';
112
109
  if (command === 'platform-pr-review' && first(args) === 'publish') {
@@ -1,5 +1,4 @@
1
1
  import { applyPrReviewActivityIntent, inspectPrReviewActivity } from '../task/activity-intent.js';
2
- import { consumeHumanOverride, failureId, overrideDryRunConflict } from '../task/human-override.js';
3
2
  import { resolveTaskRef } from '../task/resolve-ref.js';
4
3
  import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.js';
5
4
  import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
@@ -18,15 +17,14 @@ const FLAGS = {
18
17
  '--major': 'major',
19
18
  '--minor': 'minor',
20
19
  '--outcome': 'outcome',
21
- '--reason': 'reason',
22
- '--override-ticket': 'overrideTicket', '--override-target': 'overrideTarget', '--override-scope': 'overrideScope'
20
+ '--reason': 'reason'
23
21
  };
24
22
  const COMMON = ['agent', 'artifact', 'head'];
25
23
  const ALLOWED = {
26
24
  'pr-review-inspect': new Set(['kind', 'taskRef']),
27
- 'pr-review-start': new Set(['kind', 'taskRef', 'agent', 'artifact', 'head', 'dryRun', 'overrideTicket', 'overrideTarget', 'overrideScope']),
28
- 'pr-review-complete': new Set(['kind', 'taskRef', 'agent', 'artifact', 'head', 'verdict', 'blockers', 'major', 'minor', 'dryRun', 'overrideTicket', 'overrideTarget', 'overrideScope']),
29
- 'pr-review-terminate': new Set(['kind', 'taskRef', 'agent', 'artifact', 'head', 'outcome', 'reason', 'dryRun', 'overrideTicket', 'overrideTarget', 'overrideScope'])
25
+ 'pr-review-start': new Set(['kind', 'taskRef', 'agent', 'artifact', 'head', 'dryRun']),
26
+ 'pr-review-complete': new Set(['kind', 'taskRef', 'agent', 'artifact', 'head', 'verdict', 'blockers', 'major', 'minor', 'dryRun']),
27
+ 'pr-review-terminate': new Set(['kind', 'taskRef', 'agent', 'artifact', 'head', 'outcome', 'reason', 'dryRun'])
30
28
  };
31
29
  function usageFailure(message) {
32
30
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'ACTIVITY_PAYLOAD_INVALID', message } })}\n`);
@@ -109,43 +107,14 @@ async function taskActivity(args = []) {
109
107
  return;
110
108
  }
111
109
  }
112
- const dryRunConflict = overrideDryRunConflict(values);
113
- if (dryRunConflict) {
114
- usageFailure(dryRunConflict.message);
115
- return;
116
- }
117
110
  const resolved = resolveTaskRef(taskRef);
118
111
  if (!resolved.ok) {
119
112
  usageFailure(resolved.message);
120
113
  return;
121
114
  }
122
115
  let result;
123
- let humanOverride = null;
124
116
  try {
125
- result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-activity.${kind}`, async () => {
126
- let current = applyPrReviewActivityIntent(values, { lockAlreadyHeld: true });
127
- if (current.status !== 'failed' || !values.overrideTicket)
128
- return current;
129
- if (!values.overrideTarget || !values.overrideScope) {
130
- usageFailure('override ticket requires target and scope');
131
- return current;
132
- }
133
- const consumed = await consumeHumanOverride({
134
- taskRef, ticketId: String(values.overrideTicket),
135
- failureId: failureId('activity-intent', current.error?.code ?? 'TASK_STATE_MISMATCH'),
136
- target: String(values.overrideTarget), scope: String(values.overrideScope)
137
- }, {
138
- effectExecutor: (capability) => {
139
- const retried = applyPrReviewActivityIntent(values, { lockAlreadyHeld: true, manualOverride: capability });
140
- current = retried;
141
- return retried.status === 'failed' || retried.status === 'planned'
142
- ? { code: 'OVERRIDE_EFFECT_FAILED', message: retried.status === 'planned' ? 'producer returned planned; no activity effect was committed' : `${retried.error?.code ?? 'ACTIVITY_FAILED'}: ${retried.error?.message ?? 'manual activity effect failed'}` }
143
- : null;
144
- }
145
- });
146
- humanOverride = consumed;
147
- return current;
148
- });
117
+ result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-activity.${kind}`, async () => applyPrReviewActivityIntent(values, { lockAlreadyHeld: true }));
149
118
  }
150
119
  catch (error) {
151
120
  if (!(error instanceof TaskExecutionLockError))
@@ -154,10 +123,8 @@ async function taskActivity(args = []) {
154
123
  process.exitCode = 1;
155
124
  return;
156
125
  }
157
- process.stdout.write(`${JSON.stringify(humanOverride ? { ...result, humanOverride } : result)}\n`);
158
- const overrideFailed = Boolean(humanOverride && typeof humanOverride === 'object' &&
159
- humanOverride.status === 'failed');
160
- if (result.status === 'failed' || overrideFailed)
126
+ process.stdout.write(`${JSON.stringify(result)}\n`);
127
+ if (result.status === 'failed')
161
128
  process.exitCode = 1;
162
129
  }
163
130
  export { taskActivity };
@@ -1,6 +1,5 @@
1
1
  import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.js';
2
2
  import { applyTaskEvent, eventCatalog } from '../task/events.js';
3
- import { consumeHumanOverride, failureId, overrideDryRunConflict } from '../task/human-override.js';
4
3
  import { resolveTaskRef } from '../task/resolve-ref.js';
5
4
  import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.js';
6
5
  import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
@@ -18,8 +17,7 @@ const FLAGS = {
18
17
  '--verdict': 'verdict', '--blockers': 'blockers', '--major': 'major',
19
18
  '--minor': 'minor', '--manual-validation': 'manualValidation', '--files-modified': 'filesModified',
20
19
  '--tests-passed': 'testsPassed', '--summary-result': 'summaryResult',
21
- '--transaction-id': 'transactionId', '--receipt-digest': 'receiptDigest', '--pr-head-sha': 'prHeadSha',
22
- '--override-ticket': 'overrideTicket', '--override-target': 'overrideTarget', '--override-scope': 'overrideScope'
20
+ '--transaction-id': 'transactionId', '--receipt-digest': 'receiptDigest', '--pr-head-sha': 'prHeadSha'
23
21
  };
24
22
  const NUMERIC = new Set(['round', 'question', 'blockers', 'major', 'minor', 'manualValidation', 'filesModified', 'testsPassed']);
25
23
  function usageFailure(message) {
@@ -68,9 +66,6 @@ export function parseTaskEventRequest(args) {
68
66
  if (!agent)
69
67
  throw new Error(`invalid --agent '${request.agent}': ${AGENT_USAGE_HINT}`);
70
68
  request.agent = agent;
71
- const dryRunConflict = overrideDryRunConflict(request);
72
- if (dryRunConflict)
73
- throw new Error(dryRunConflict.message);
74
69
  return request;
75
70
  }
76
71
  async function taskEvent(args = []) {
@@ -99,34 +94,8 @@ async function taskEvent(args = []) {
99
94
  return;
100
95
  }
101
96
  let result;
102
- let humanOverride = null;
103
97
  try {
104
- result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-event.${request.event}`, async () => {
105
- let current = applyTaskEvent(request, { lockAlreadyHeld: true });
106
- const values = request;
107
- if (current.status !== 'failed' || !values.overrideTicket)
108
- return current;
109
- if (!values.overrideTarget || !values.overrideScope) {
110
- return { ...current, humanOverride: { status: 'failed', error: { code: 'OVERRIDE_PAYLOAD_INVALID', message: 'override ticket requires target and scope' } } };
111
- }
112
- const consumed = await consumeHumanOverride({
113
- taskRef: request.taskRef,
114
- ticketId: String(values.overrideTicket),
115
- failureId: failureId('task-event', current.error?.code ?? 'EVENT_TRANSITION_INVALID'),
116
- target: String(values.overrideTarget),
117
- scope: String(values.overrideScope)
118
- }, {
119
- effectExecutor: (capability) => {
120
- const retried = applyTaskEvent(request, { lockAlreadyHeld: true, manualOverride: capability });
121
- current = retried;
122
- return retried.status === 'failed' || retried.status === 'planned'
123
- ? { code: 'OVERRIDE_EFFECT_FAILED', message: retried.status === 'planned' ? 'producer returned planned; no task event was committed' : `${retried.error?.code ?? 'EVENT_FAILED'}: ${retried.error?.message ?? 'manual task event effect failed'}` }
124
- : null;
125
- }
126
- });
127
- humanOverride = consumed;
128
- return current;
129
- });
98
+ result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-event.${request.event}`, async () => applyTaskEvent(request, { lockAlreadyHeld: true }));
130
99
  }
131
100
  catch (error) {
132
101
  if (!(error instanceof TaskExecutionLockError))
@@ -135,10 +104,8 @@ async function taskEvent(args = []) {
135
104
  process.exitCode = 1;
136
105
  return;
137
106
  }
138
- process.stdout.write(`${JSON.stringify(humanOverride ? { ...result, humanOverride } : result)}\n`);
139
- const overrideFailed = Boolean(humanOverride && typeof humanOverride === 'object' &&
140
- humanOverride.status === 'failed');
141
- if (result.status === 'failed' || overrideFailed)
107
+ process.stdout.write(`${JSON.stringify(result)}\n`);
108
+ if (result.status === 'failed')
142
109
  process.exitCode = 1;
143
110
  }
144
111
  export { taskEvent };
@@ -1,5 +1,6 @@
1
1
  import { createDirectHostExecutionContext, dispatchTaskControlOperation, parseTaskControlOperation } from '../task/control-authority.js';
2
- import { applyTaskFinalization, prepareTaskFinalization } from '../task/finalization.js';
2
+ import { applyTaskFinalization, bindTaskFinalizationReceipt, prepareTaskFinalization } from '../task/finalization.js';
3
+ import { publishTaskFinalizationHandoff } from '../task/finalization-handoff.js';
3
4
  import { detectRepoRoot, resolveTaskRef } from '../task/resolve-ref.js';
4
5
  import { verifyTaskEvent } from '../task/verification.js';
5
6
  import { resolveSandboxControlTransport } from './task-operation-registry.js';
@@ -74,7 +75,13 @@ async function taskFinalization(args = []) {
74
75
  return;
75
76
  }
76
77
  try {
77
- const response = requestSandboxTaskFinalization({ agent: boundOperation.request.agent });
78
+ const response = requestSandboxTaskFinalization({
79
+ agent: boundOperation.request.agent,
80
+ prepareHandoff: (binding) => {
81
+ const receipt = bindTaskFinalizationReceipt(repoRoot, boundOperation.request.taskRef, binding);
82
+ return publishTaskFinalizationHandoff('/share/branch', receipt, binding);
83
+ }
84
+ });
78
85
  process.stdout.write(response.stdout);
79
86
  process.stderr.write(response.stderr);
80
87
  process.exitCode = response.exitCode ?? 1;
@@ -1,6 +1,5 @@
1
1
  import fs from 'node:fs';
2
2
  import { applyLedgerIntent } from '../task/ledger-intents.js';
3
- import { consumeHumanOverride, failureId, overrideDryRunConflict } from '../task/human-override.js';
4
3
  import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, isReviewStage, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from '../task/ledger.js';
5
4
  import { resolveTaskRef } from '../task/resolve-ref.js';
6
5
  import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.js';
@@ -11,8 +10,7 @@ const FLAGS = {
11
10
  '--severity': 'severity', '--evidence': 'evidence', '--id': 'id', '--round': 'round',
12
11
  '--status': 'status', '--artifact': 'artifact', '--needs-implementation': 'needsImplementation',
13
12
  '--intent-id': 'intentId', '--finding-id': 'findingId', '--source-artifact': 'sourceArtifact',
14
- '--source-sha256': 'sourceSha256', '--classification': 'classification',
15
- '--override-ticket': 'overrideTicket', '--override-target': 'overrideTarget', '--override-scope': 'overrideScope'
13
+ '--source-sha256': 'sourceSha256', '--classification': 'classification'
16
14
  };
17
15
  const NUMERIC = new Set(['ordinal', 'round']);
18
16
  const BOOLEAN = new Set(['needsImplementation']);
@@ -96,10 +94,7 @@ async function taskLedger(args = []) {
96
94
  'decision-upsert': ['needsImplementation'],
97
95
  'rework-intent-rebuild': ['findingId', 'sourceArtifact', 'sourceSha256', 'classification']
98
96
  };
99
- const overrideFields = kind === 'stage-status' || kind === 'decision-next-id' || kind === 'rework-intent-upsert' || kind === 'rework-intent-rebuild'
100
- ? []
101
- : ['overrideTicket', 'overrideTarget', 'overrideScope'];
102
- const allowed = new Set(['kind', 'taskRef', 'dryRun', ...required[kind], ...(optional[kind] ?? []), ...overrideFields]);
97
+ const allowed = new Set(['kind', 'taskRef', 'dryRun', ...required[kind], ...(optional[kind] ?? [])]);
103
98
  const unexpected = Object.keys(values).find((key) => !allowed.has(key));
104
99
  const missing = required[kind].find((key) => values[key] === undefined);
105
100
  if (unexpected) {
@@ -110,11 +105,6 @@ async function taskLedger(args = []) {
110
105
  usageFailure(`${kind} requires '${missing}'`);
111
106
  return;
112
107
  }
113
- const dryRunConflict = overrideDryRunConflict(values);
114
- if (dryRunConflict) {
115
- usageFailure(dryRunConflict.message);
116
- return;
117
- }
118
108
  if (values.classification !== undefined && !REWORK_CLASSIFICATIONS.has(String(values.classification))) {
119
109
  usageFailure(`invalid rework classification '${values.classification}'`);
120
110
  return;
@@ -159,34 +149,8 @@ async function taskLedger(args = []) {
159
149
  return;
160
150
  }
161
151
  let result;
162
- let humanOverride = null;
163
152
  try {
164
- result = await withTaskExecutionLock(lockResolved.repoRoot, lockResolved.taskId, `task-ledger.${kind}`, async () => {
165
- let current = applyLedgerIntent(values);
166
- if (current.status !== 'failed' || !values.overrideTicket)
167
- return current;
168
- if (!values.overrideTarget || !values.overrideScope) {
169
- usageFailure('override ticket requires target and scope');
170
- return current;
171
- }
172
- const consumed = await consumeHumanOverride({
173
- taskRef,
174
- ticketId: String(values.overrideTicket),
175
- failureId: failureId('ledger-intent', current.error?.code ?? 'TASK_STATE_MISMATCH'),
176
- target: String(values.overrideTarget),
177
- scope: String(values.overrideScope)
178
- }, {
179
- effectExecutor: (capability) => {
180
- const retried = applyLedgerIntent(values, { manualOverride: capability });
181
- current = retried;
182
- return retried.status === 'failed'
183
- ? { code: 'OVERRIDE_EFFECT_FAILED', message: `${retried.error?.code ?? 'LEDGER_FAILED'}: ${retried.error?.message ?? 'manual ledger effect failed'}` }
184
- : null;
185
- }
186
- });
187
- humanOverride = consumed;
188
- return current;
189
- });
153
+ result = await withTaskExecutionLock(lockResolved.repoRoot, lockResolved.taskId, `task-ledger.${kind}`, async () => applyLedgerIntent(values));
190
154
  }
191
155
  catch (error) {
192
156
  if (!(error instanceof TaskExecutionLockError))
@@ -195,10 +159,8 @@ async function taskLedger(args = []) {
195
159
  process.exitCode = 1;
196
160
  return;
197
161
  }
198
- process.stdout.write(`${JSON.stringify(humanOverride ? { ...result, humanOverride } : result)}\n`);
199
- const overrideFailed = Boolean(humanOverride && typeof humanOverride === 'object' &&
200
- humanOverride.status === 'failed');
201
- if (result.status === 'failed' || overrideFailed)
162
+ process.stdout.write(`${JSON.stringify(result)}\n`);
163
+ if (result.status === 'failed')
202
164
  process.exitCode = 1;
203
165
  }
204
166
  export { taskLedger };
@@ -2,7 +2,7 @@ import { createDirectHostExecutionContext, dispatchTaskControlOperation, parseTa
2
2
  import { lifecycleIntentCatalog } from '../task/lifecycle.js';
3
3
  import { detectRepoRoot, resolveTaskRef } from '../task/resolve-ref.js';
4
4
  import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
5
- const USAGE = `Usage: agent-infra-internal task-lifecycle <N | TASK-id> <intent> --agent <agent> [intent flags] [--dry-run]\n\nIntents: ${lifecycleIntentCatalog.join(', ')}\nrecover-started: --auto\nOverride: --override-ticket <ticket> --override-target <target> --override-scope <scope>\n`;
5
+ const USAGE = `Usage: agent-infra-internal task-lifecycle <N | TASK-id> <intent> --agent <agent> [intent flags] [--dry-run]\n\nIntents: ${lifecycleIntentCatalog.join(', ')}\nrecover-started: --auto\n`;
6
6
  function usageFailure(message) {
7
7
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'LIFECYCLE_PAYLOAD_INVALID', message } })}\n`);
8
8
  process.stderr.write(USAGE);
@@ -103,9 +103,6 @@ function internalTaskRoutes() {
103
103
  descriptor('internal', 'task-review', 'finalize-summary', 'task-bound', 'progress'),
104
104
  descriptor('internal', 'task-event', 'event', 'task-bound', 'progress'),
105
105
  descriptor('internal', 'task-invalidation', 'reconcile', 'task-bound', 'progress'),
106
- descriptor('internal', 'task-override', 'diagnose', 'task-bound', 'diagnostic'),
107
- descriptor('internal', 'task-override', 'issue', 'task-bound', 'progress'),
108
- descriptor('internal', 'task-override', 'consume', 'task-bound', 'progress'),
109
106
  descriptor('internal', 'task-lifecycle', 'intent', 'task-bound', 'progress'),
110
107
  descriptor('internal', 'task-finalization', 'complete', 'task-bound', 'progress'),
111
108
  descriptor('internal', 'task-short-id', 'list', 'conditional', 'diagnostic'),
@@ -181,7 +178,7 @@ export const INTERNAL_DISPATCHER_ROUTES = Object.freeze([
181
178
  'platform-comment', 'platform-issue', 'platform-pr', 'platform-pr-review', 'pr-review-grade',
182
179
  'platform-checks', 'task-context', 'task-ledger', 'task-warning', 'task-activity', 'task-artifact',
183
180
  'task-orchestration', 'task-review', 'task-event', 'task-invalidation', 'task-lifecycle',
184
- 'task-finalization', 'task-override', 'task-short-id', 'task-snapshot', 'task-verify', 'task-validate', 'manual-validation'
181
+ 'task-finalization', 'task-short-id', 'task-snapshot', 'task-verify', 'task-validate', 'manual-validation'
185
182
  ]);
186
183
  export const PUBLIC_DISPATCHER_ROUTES = Object.freeze([
187
184
  'agent-client', 'cp', 'data', 'decide', 'help', 'init', 'merge', 'run', 'sandbox', 'server', 'task', 'sync', 'update', 'version'
@@ -1,10 +1,9 @@
1
1
  import { parseReviewCommand } from '../task/review-command.js';
2
2
  import { finalizeReviewSummary, preflightReviewSummary } from '../task/review-finalization.js';
3
- import { consumeHumanOverride, failureId, overrideDryRunConflict } from '../task/human-override.js';
4
3
  import { resolveTaskRef } from '../task/resolve-ref.js';
5
4
  import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.js';
6
5
  import { ensureInternalHandlerRoute } from './cli-route-inventory.js';
7
- const USAGE = 'Usage: agent-infra-internal task-review <task-ref> <preflight|finalize-summary> --stage <analysis|plan|code> --artifact <review-*.md> [--orchestrated] [--dry-run] [--override-ticket <ticket> --override-target <target> --override-scope <scope>]\n';
6
+ const USAGE = 'Usage: agent-infra-internal task-review <task-ref> <preflight|finalize-summary> --stage <analysis|plan|code> --artifact <review-*.md> [--orchestrated] [--dry-run]\n';
8
7
  function failUsage(message) {
9
8
  process.stdout.write(`${JSON.stringify({
10
9
  status: 'failed',
@@ -30,48 +29,19 @@ async function taskReview(args = []) {
30
29
  failUsage(error instanceof Error ? error.message : String(error));
31
30
  return;
32
31
  }
33
- const { stage, artifact, dryRun, orchestrated, overrideTicket, overrideTarget, overrideScope } = request;
32
+ const { stage, artifact, dryRun, orchestrated } = request;
34
33
  const operation = args[1];
35
- const dryRunConflict = overrideDryRunConflict({ dryRun, overrideTicket, overrideTarget, overrideScope });
36
- if (dryRunConflict) {
37
- failUsage(dryRunConflict.message);
38
- return;
39
- }
40
34
  const resolved = resolveTaskRef(args[0]);
41
35
  if (!resolved.ok) {
42
36
  failUsage(resolved.message);
43
37
  return;
44
38
  }
45
39
  let result;
46
- let humanOverride = null;
47
40
  try {
48
41
  result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-review.${operation}`, async () => {
49
- let current = operation === 'preflight'
42
+ return operation === 'preflight'
50
43
  ? preflightReviewSummary({ taskRef: args[0], stage, artifact, orchestrated, dryRun }, { lockAlreadyHeld: true })
51
44
  : finalizeReviewSummary({ taskRef: args[0], stage, artifact, orchestrated, dryRun }, { lockAlreadyHeld: true });
52
- if (operation === 'preflight')
53
- return current;
54
- if (current.status !== 'failed' || !overrideTicket)
55
- return current;
56
- if (!overrideTarget || !overrideScope) {
57
- failUsage('override ticket requires target and scope');
58
- return current;
59
- }
60
- const consumed = await consumeHumanOverride({
61
- taskRef: args[0], ticketId: overrideTicket,
62
- failureId: failureId('review-finalization', current.error?.code ?? 'TASK_STATE_MISMATCH'),
63
- target: overrideTarget, scope: overrideScope
64
- }, {
65
- effectExecutor: (capability) => {
66
- const retried = finalizeReviewSummary({ taskRef: args[0], stage, artifact, orchestrated, dryRun }, { lockAlreadyHeld: true, manualOverride: capability });
67
- current = retried;
68
- return retried.status === 'failed' || retried.status === 'planned'
69
- ? { code: 'OVERRIDE_EFFECT_FAILED', message: retried.status === 'planned' ? 'producer returned planned; no review effect was committed' : `${retried.error?.code ?? 'REVIEW_FAILED'}: ${retried.error?.message ?? 'manual review effect failed'}` }
70
- : null;
71
- }
72
- });
73
- humanOverride = consumed;
74
- return current;
75
45
  });
76
46
  }
77
47
  catch (error) {
@@ -81,10 +51,8 @@ async function taskReview(args = []) {
81
51
  process.exitCode = 1;
82
52
  return;
83
53
  }
84
- process.stdout.write(`${JSON.stringify(humanOverride ? { ...result, humanOverride } : result)}\n`);
85
- const overrideFailed = Boolean(humanOverride && typeof humanOverride === 'object' &&
86
- humanOverride.status === 'failed');
87
- if (result.status === 'failed' || overrideFailed)
54
+ process.stdout.write(`${JSON.stringify(result)}\n`);
55
+ if (result.status === 'failed')
88
56
  process.exitCode = 1;
89
57
  }
90
58
  export { taskReview };
@@ -1,9 +1,8 @@
1
1
  import { renderTaskVerification, verifyTaskEvent } from '../task/verification.js';
2
- import { consumeHumanOverride, failureId } from '../task/human-override.js';
3
2
  import { resolveTaskRef } from '../task/resolve-ref.js';
4
3
  import { TaskExecutionLockError, withTaskExecutionLock } from '../task/task-execution-lock.js';
5
4
  import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
6
- const USAGE = 'Usage: agent-infra-internal task-verify <N | TASK-id> <verification-event> [--artifact <canonical.md>] [--format json|text] [--override-ticket <ticket> --override-target <target> --override-scope <scope>]\n';
5
+ const USAGE = 'Usage: agent-infra-internal task-verify <N | TASK-id> <verification-event> [--artifact <canonical.md>] [--format json|text]\n';
7
6
  function fail(message) {
8
7
  process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'VERIFY_PAYLOAD_INVALID', message } })}\n`);
9
8
  process.stderr.write(USAGE);
@@ -25,13 +24,10 @@ async function taskVerify(args = []) {
25
24
  const event = args[1];
26
25
  let artifact;
27
26
  let format = 'json';
28
- let overrideTicket;
29
- let overrideTarget;
30
- let overrideScope;
31
27
  const seen = new Set();
32
28
  for (let index = 2; index < args.length; index += 1) {
33
29
  const flag = args[index];
34
- if (!['--artifact', '--format', '--override-ticket', '--override-target', '--override-scope'].includes(flag)) {
30
+ if (!['--artifact', '--format'].includes(flag)) {
35
31
  fail(`unknown option '${flag}'`);
36
32
  return;
37
33
  }
@@ -47,12 +43,6 @@ async function taskVerify(args = []) {
47
43
  seen.add(flag);
48
44
  if (flag === '--artifact')
49
45
  artifact = value;
50
- else if (flag === '--override-ticket')
51
- overrideTicket = value;
52
- else if (flag === '--override-target')
53
- overrideTarget = value;
54
- else if (flag === '--override-scope')
55
- overrideScope = value;
56
46
  else if (value === 'json' || value === 'text')
57
47
  format = value;
58
48
  else {
@@ -66,40 +56,8 @@ async function taskVerify(args = []) {
66
56
  return;
67
57
  }
68
58
  let result;
69
- let humanOverride = null;
70
59
  try {
71
- result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-verify.${event}`, async () => {
72
- let current = await verifyTaskEvent({ taskRef, event, ...(artifact ? { artifact } : {}) });
73
- if (current.status === 'pass' || !overrideTicket)
74
- return current;
75
- if (!overrideTarget || !overrideScope) {
76
- fail('override ticket requires target and scope');
77
- return current;
78
- }
79
- const failureProducer = current.status === 'blocked' || current.status === 'fail'
80
- ? 'verification-engine'
81
- : 'task-verify';
82
- const failureCode = current.status === 'blocked'
83
- ? 'CHECK_BLOCKED'
84
- : current.status === 'fail'
85
- ? 'CHECK_FAILED'
86
- : current.error?.code ?? 'VERIFY_TASK_STATE_MISMATCH';
87
- const consumed = await consumeHumanOverride({
88
- taskRef, ticketId: overrideTicket,
89
- failureId: failureId(failureProducer, failureCode),
90
- target: overrideTarget, scope: overrideScope
91
- }, {
92
- effectExecutor: async (capability) => {
93
- const retried = await verifyTaskEvent({ taskRef, event, ...(artifact ? { artifact } : {}) }, { manualOverride: capability });
94
- current = retried;
95
- return retried.status !== 'pass'
96
- ? { code: 'OVERRIDE_EFFECT_FAILED', message: `${retried.error?.code ?? 'VERIFY_FAILED'}: ${retried.error?.message ?? 'manual verification effect failed'}` }
97
- : null;
98
- }
99
- });
100
- humanOverride = consumed;
101
- return current;
102
- });
60
+ result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-verify.${event}`, async () => verifyTaskEvent({ taskRef, event, ...(artifact ? { artifact } : {}) }));
103
61
  }
104
62
  catch (error) {
105
63
  if (!(error instanceof TaskExecutionLockError))
@@ -107,8 +65,6 @@ async function taskVerify(args = []) {
107
65
  fail(`${error.code}: ${error.message}`);
108
66
  return;
109
67
  }
110
- if (humanOverride)
111
- result = { ...result, humanOverride };
112
68
  process.stdout.write(format === 'text' ? renderTaskVerification(result) : `${JSON.stringify(result)}\n`);
113
69
  process.exitCode = result.status === 'pass' ? 0 : result.status === 'blocked' ? 2 : 1;
114
70
  }