@fitlab-ai/agent-infra 0.11.4 → 0.11.6
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.
- package/dist/bin/internal-cli.js +0 -5
- package/dist/lib/decide.js +4 -41
- package/dist/lib/git/branch-worktree.js +45 -0
- package/dist/lib/internal/cli-route-inventory.js +0 -3
- package/dist/lib/internal/task-activity.js +7 -40
- package/dist/lib/internal/task-event.js +4 -37
- package/dist/lib/internal/task-finalization.js +9 -2
- package/dist/lib/internal/task-ledger.js +5 -43
- package/dist/lib/internal/task-lifecycle.js +1 -1
- package/dist/lib/internal/task-operation-registry.js +1 -4
- package/dist/lib/internal/task-review.js +5 -37
- package/dist/lib/internal/task-verify.js +3 -47
- package/dist/lib/internal/task-warning.js +4 -40
- package/dist/lib/merge.js +62 -10
- package/dist/lib/platform/github-provider.js +9 -14
- package/dist/lib/platform/github-release-notes.js +80 -11
- package/dist/lib/platform/none-provider.js +1 -1
- package/dist/lib/platform/pr-summary.js +4 -23
- package/dist/lib/platform/provider-contract.d.ts +39 -16
- package/dist/lib/platform/provider-contract.js +1 -1
- package/dist/lib/platform/provider-validation.js +83 -13
- package/dist/lib/platform/release-notes.js +7 -8
- package/dist/lib/platform/verification-sync.js +12 -49
- package/dist/lib/sandbox/capture.js +1 -1
- package/dist/lib/sandbox/commands/create.js +46 -1
- package/dist/lib/sandbox/commands/enter.js +1 -1
- package/dist/lib/sandbox/commands/start.js +1 -1
- package/dist/lib/sandbox/config.js +10 -0
- package/dist/lib/sandbox/control/client.js +4 -1
- package/dist/lib/sandbox/control/executor.js +12 -4
- package/dist/lib/sandbox/control/lifecycle.js +18 -13
- package/dist/lib/sandbox/control/protocol.js +2 -1
- package/dist/lib/sandbox/removal.js +15 -8
- package/dist/lib/sandbox/task-resolver.js +62 -2
- package/dist/lib/task/activity-intent.js +1 -2
- package/dist/lib/task/artifact-operations.js +36 -2
- package/dist/lib/task/artifact-schema.js +7 -7
- package/dist/lib/task/control-authority.js +9 -166
- package/dist/lib/task/decision-intents.js +2 -4
- package/dist/lib/task/events.js +7 -28
- package/dist/lib/task/finalization-handoff.js +92 -0
- package/dist/lib/task/finalization.js +123 -12
- package/dist/lib/task/intermediate-cleanup.js +9 -148
- package/dist/lib/task/ledger-intents.js +3 -6
- package/dist/lib/task/lifecycle.js +50 -11
- package/dist/lib/task/local-artifact-finalization.js +13 -28
- package/dist/lib/task/resolve-ref.js +3 -3
- package/dist/lib/task/review-command.js +1 -2
- package/dist/lib/task/review-finalization.js +1 -2
- package/dist/lib/task/snapshot.js +6 -6
- package/dist/lib/task/verification-engine.js +16 -11
- package/dist/lib/task/verification.js +1 -13
- package/dist/lib/task/workflow-warning-intents.js +2 -4
- package/dist/lib/task/write.js +122 -3
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/decide.ts +5 -35
- package/lib/git/branch-worktree.ts +41 -0
- package/lib/internal/cli-route-inventory.ts +0 -2
- package/lib/internal/task-activity.ts +6 -34
- package/lib/internal/task-event.ts +4 -37
- package/lib/internal/task-finalization.ts +9 -2
- package/lib/internal/task-ledger.ts +5 -38
- package/lib/internal/task-lifecycle.ts +2 -2
- package/lib/internal/task-operation-registry.ts +1 -4
- package/lib/internal/task-review.ts +5 -31
- package/lib/internal/task-verify.ts +3 -39
- package/lib/internal/task-warning.ts +3 -32
- package/lib/merge.ts +59 -10
- package/lib/platform/github-provider.ts +11 -18
- package/lib/platform/github-release-notes.ts +89 -14
- package/lib/platform/none-provider.ts +1 -1
- package/lib/platform/pr-summary.ts +4 -25
- package/lib/platform/provider-contract.ts +38 -12
- package/lib/platform/provider-validation.ts +83 -12
- package/lib/platform/release-notes.ts +11 -12
- package/lib/platform/verification-sync.ts +13 -53
- package/lib/sandbox/capture.ts +1 -1
- package/lib/sandbox/commands/create.ts +52 -1
- package/lib/sandbox/commands/enter.ts +1 -1
- package/lib/sandbox/commands/start.ts +1 -1
- package/lib/sandbox/config.ts +12 -0
- package/lib/sandbox/control/client.ts +5 -1
- package/lib/sandbox/control/executor.ts +13 -4
- package/lib/sandbox/control/lifecycle.ts +22 -13
- package/lib/sandbox/control/protocol.ts +3 -2
- package/lib/sandbox/removal.ts +23 -7
- package/lib/sandbox/task-resolver.ts +51 -2
- package/lib/task/activity-intent.ts +1 -2
- package/lib/task/artifact-operations.ts +58 -2
- package/lib/task/artifact-schema.ts +9 -7
- package/lib/task/control-authority.ts +14 -188
- package/lib/task/decision-intents.ts +2 -4
- package/lib/task/events.ts +8 -27
- package/lib/task/finalization-handoff.ts +104 -0
- package/lib/task/finalization.ts +120 -12
- package/lib/task/intermediate-cleanup.ts +9 -125
- package/lib/task/ledger-intents.ts +3 -6
- package/lib/task/lifecycle.ts +45 -13
- package/lib/task/local-artifact-finalization.ts +16 -35
- package/lib/task/resolve-ref.ts +3 -3
- package/lib/task/review-command.ts +2 -5
- package/lib/task/review-finalization.ts +1 -4
- package/lib/task/snapshot.ts +6 -6
- package/lib/task/verification-engine.ts +20 -10
- package/lib/task/verification.ts +1 -15
- package/lib/task/workflow-warning-intents.ts +2 -4
- package/lib/task/write.ts +116 -5
- package/package.json +1 -1
- package/templates/.agents/rules/evidence-reporting.en.md +1 -2
- package/templates/.agents/rules/evidence-reporting.zh-CN.md +1 -2
- package/templates/.agents/skills/analyze-task/SKILL.en.md +11 -2
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -2
- package/templates/.agents/skills/archive-tasks/SKILL.en.md +2 -2
- package/templates/.agents/skills/archive-tasks/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/archive-tasks/scripts/archive-tasks.sh +109 -6
- package/templates/.agents/skills/code-task/reference/report-template.en.md +6 -6
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +6 -6
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +2 -2
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +2 -2
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +1 -3
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +1 -3
- package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
- package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -11
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -11
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +3 -3
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +3 -3
- package/templates/.agents/skills/review-code/reference/report-template.en.md +3 -3
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +3 -3
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +3 -3
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +3 -3
- package/templates/.agents/skills/review-pr/config/verify.en.json +3 -1
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +3 -1
- package/templates/.agents/skills/review-pr/reference/report-template.en.md +3 -3
- package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +3 -3
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +2 -2
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +2 -2
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
- package/dist/lib/internal/task-override.js +0 -138
- package/dist/lib/task/artifact-recovery.js +0 -476
- package/dist/lib/task/artifact-repair-intent.js +0 -181
- package/dist/lib/task/guard-override.js +0 -31
- package/dist/lib/task/human-override.js +0 -1259
- package/lib/internal/task-override.ts +0 -144
- package/lib/task/artifact-recovery.ts +0 -572
- package/lib/task/artifact-repair-intent.ts +0 -227
- package/lib/task/guard-override.ts +0 -50
- package/lib/task/human-override.ts +0 -1522
package/dist/bin/internal-cli.js
CHANGED
|
@@ -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));
|
package/dist/lib/decide.js
CHANGED
|
@@ -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
|
|
26
|
-
|
|
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
|
|
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'
|
|
28
|
-
'pr-review-complete': new Set(['kind', 'taskRef', 'agent', 'artifact', 'head', 'verdict', 'blockers', 'major', 'minor', 'dryRun'
|
|
29
|
-
'pr-review-terminate': new Set(['kind', 'taskRef', 'agent', 'artifact', 'head', 'outcome', 'reason', 'dryRun'
|
|
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(
|
|
158
|
-
|
|
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(
|
|
139
|
-
|
|
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({
|
|
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
|
|
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(
|
|
199
|
-
|
|
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\
|
|
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-
|
|
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]
|
|
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
|
|
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
|
-
|
|
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(
|
|
85
|
-
|
|
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]
|
|
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'
|
|
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
|
}
|