@fitlab-ai/agent-infra 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/internal/manual-validation.js +6 -2
- package/dist/lib/platform/issues.js +3 -4
- package/dist/lib/platform/verification-sync.js +142 -154
- package/dist/lib/sandbox/control/workflow-executor.js +7 -1
- package/dist/lib/task/artifact-lifecycle.js +15 -52
- package/dist/lib/task/artifact-operations.js +27 -1
- package/dist/lib/task/capabilities.js +0 -2
- package/dist/lib/task/events.js +60 -43
- package/dist/lib/task/gate-policy.js +94 -0
- package/dist/lib/task/local-artifact-finalization.js +7 -4
- package/dist/lib/task/orchestration.js +8 -6
- package/dist/lib/task/review-artifacts.js +12 -6
- package/dist/lib/task/review-finalization.js +3 -9
- package/dist/lib/task/verification-engine.js +28 -17
- package/dist/lib/task/verification.js +25 -9
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/internal/manual-validation.ts +6 -2
- package/lib/platform/issues.ts +3 -4
- package/lib/platform/verification-sync.ts +159 -177
- package/lib/sandbox/control/workflow-executor.ts +11 -1
- package/lib/task/artifact-lifecycle.ts +12 -49
- package/lib/task/artifact-operations.ts +27 -1
- package/lib/task/capabilities.ts +0 -1
- package/lib/task/events.ts +49 -32
- package/lib/task/gate-policy.ts +133 -0
- package/lib/task/local-artifact-finalization.ts +6 -4
- package/lib/task/orchestration.ts +12 -7
- package/lib/task/review-artifacts.ts +8 -2
- package/lib/task/review-finalization.ts +3 -9
- package/lib/task/verification-engine.ts +24 -14
- package/lib/task/verification-types.ts +7 -0
- package/lib/task/verification.ts +25 -9
- package/package.json +1 -1
- package/templates/.agents/rules/issue-sync.en.md +2 -0
- package/templates/.agents/rules/issue-sync.zh-CN.md +5 -8
- package/templates/.agents/rules/local-artifact-repair.en.md +11 -3
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +11 -3
- package/templates/.agents/skills/analyze-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -10
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/block-task/config/verify.json +1 -3
- package/templates/.agents/skills/cancel-task/config/verify.json +1 -4
- package/templates/.agents/skills/code-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/code-task/config/verify.en.json +1 -12
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -12
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +11 -0
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +11 -0
- package/templates/.agents/skills/commit/config/verify.json +1 -5
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +6 -6
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +6 -6
- package/templates/.agents/skills/complete-task/config/verify.en.json +3 -14
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +3 -14
- package/templates/.agents/skills/create-pr/config/verify.json +1 -10
- package/templates/.agents/skills/create-task/config/verify.json +1 -4
- package/templates/.agents/skills/import-issue/config/verify.json +1 -2
- package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/plan-task/config/verify.en.json +1 -10
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -10
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -10
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/review-code/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -10
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/review-pr/config/verify.en.json +1 -8
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -8
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +38 -13
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +38 -13
|
@@ -69,7 +69,6 @@ function preflightReviewSummaryUnlocked(request, options = {}) {
|
|
|
69
69
|
let taskContent;
|
|
70
70
|
let content;
|
|
71
71
|
let recovery;
|
|
72
|
-
let existingIntent;
|
|
73
72
|
try {
|
|
74
73
|
taskContent = fs.readFileSync(resolved.taskMdPath, 'utf8');
|
|
75
74
|
if (request.recoveryId) {
|
|
@@ -89,7 +88,6 @@ function preflightReviewSummaryUnlocked(request, options = {}) {
|
|
|
89
88
|
return preflightFailed(request, validated.error.code === 'ARTIFACT_NOT_REGULAR' ? 'REVIEW_ARTIFACT_NOT_REGULAR' : 'REVIEW_ARTIFACT_IDENTITY_INVALID', validated.error.message, resolved.taskId);
|
|
90
89
|
content = fs.readFileSync(validated.artifact.path, 'utf8');
|
|
91
90
|
const intent = readArtifactRecoveryIntent(resolved.repoRoot, resolved.taskId, spec.family, request.artifact);
|
|
92
|
-
existingIntent = intent;
|
|
93
91
|
if (intent?.state === 'preflight-ready')
|
|
94
92
|
recovery = recoveryContextFromIntent(resolved.repoRoot, resolved.taskDir, intent);
|
|
95
93
|
if (intent?.state === 'consumed')
|
|
@@ -143,12 +141,6 @@ function preflightReviewSummaryUnlocked(request, options = {}) {
|
|
|
143
141
|
...(recovery ? { recovery: recoveryInfo(recovery) } : {})
|
|
144
142
|
});
|
|
145
143
|
}
|
|
146
|
-
if (!recovery && existingIntent?.state === 'passed') {
|
|
147
|
-
return {
|
|
148
|
-
...preflightFailed(request, 'REVIEW_ARTIFACT_CONFLICT', '', resolved.taskId, { artifactSha256, semanticDigest }),
|
|
149
|
-
status: 'passed', changed: false, error: null
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
144
|
if (request.dryRun || recovery && readArtifactRecoveryIntent(resolved.repoRoot, resolved.taskId, spec.family, request.artifact)?.state === 'preflight-ready') {
|
|
153
145
|
return {
|
|
154
146
|
...preflightFailed(request, 'REVIEW_ARTIFACT_CONFLICT', '', resolved.taskId, { artifactSha256, semanticDigest, ...(recovery ? { recovery: recoveryInfo(recovery) } : {}) }),
|
|
@@ -316,7 +308,9 @@ function prepareReviewSummaryCandidate(request, artifactContent, options = {}) {
|
|
|
316
308
|
...(recovery ? { recovery } : {})
|
|
317
309
|
};
|
|
318
310
|
}
|
|
319
|
-
const transformed = finalizeReviewSummaryContent(artifactContent, stageStatus.unresolvedFindingCounts
|
|
311
|
+
const transformed = finalizeReviewSummaryContent(artifactContent, stageStatus.unresolvedFindingCounts, {
|
|
312
|
+
refreshNumericCounts: Boolean(request.recoveryId && recovery)
|
|
313
|
+
});
|
|
320
314
|
if (!transformed.ok)
|
|
321
315
|
return reject(transformed.code, transformed.message);
|
|
322
316
|
const finalDigests = { artifactSha256: sha256Content(transformed.content), semanticDigest: canonicalSemanticDigest(transformed.content) };
|
|
@@ -29,6 +29,7 @@ import { validateLocalArtifact } from "./local-artifact-finalization.js";
|
|
|
29
29
|
import { validateQualificationAudit } from "./qualification-audit.js";
|
|
30
30
|
import { getArtifactSchema } from "./artifact-schema.js";
|
|
31
31
|
import { inspectArtifactContract } from "./artifact-operations.js";
|
|
32
|
+
import { normalizeVerificationRecord } from './gate-policy.js';
|
|
32
33
|
import { manualValidationFinalSummaryProjectionMatches } from "./manual-validation-receipt.js";
|
|
33
34
|
import { readManualValidationCompletion } from "./manual-validation-completion.js";
|
|
34
35
|
import { sha256File } from "./artifact-receipts.js";
|
|
@@ -1198,19 +1199,19 @@ function interpolate(template, taskDir, artifactFile) {
|
|
|
1198
1199
|
.replace(/\{artifact-stem\}/g, artifactStem);
|
|
1199
1200
|
}
|
|
1200
1201
|
function summarizeGate(checks) {
|
|
1201
|
-
if (checks.some((check) => check.
|
|
1202
|
+
if (checks.some((check) => check.effectiveStatus === "blocked")) {
|
|
1202
1203
|
return "blocked";
|
|
1203
1204
|
}
|
|
1204
|
-
if (checks.some((check) => check.
|
|
1205
|
+
if (checks.some((check) => check.effectiveStatus === "fail")) {
|
|
1205
1206
|
return "fail";
|
|
1206
1207
|
}
|
|
1207
1208
|
return "pass";
|
|
1208
1209
|
}
|
|
1209
1210
|
function summarizeChecks(checks) {
|
|
1210
1211
|
const counts = {
|
|
1211
|
-
pass: checks.filter((check) => check.
|
|
1212
|
-
fail: checks.filter((check) => check.
|
|
1213
|
-
blocked: checks.filter((check) => check.
|
|
1212
|
+
pass: checks.filter((check) => check.effectiveStatus === "pass").length,
|
|
1213
|
+
fail: checks.filter((check) => check.effectiveStatus === "fail").length,
|
|
1214
|
+
blocked: checks.filter((check) => check.effectiveStatus === "blocked").length
|
|
1214
1215
|
};
|
|
1215
1216
|
if (counts.blocked > 0) {
|
|
1216
1217
|
return `${counts.pass} passed, ${counts.fail} failed, ${counts.blocked} blocked`;
|
|
@@ -1221,7 +1222,7 @@ function buildAction(gate, checks) {
|
|
|
1221
1222
|
if (gate === "pass") {
|
|
1222
1223
|
return "All declared checks passed";
|
|
1223
1224
|
}
|
|
1224
|
-
const firstFailure = checks.find((check) => check.
|
|
1225
|
+
const firstFailure = checks.find((check) => check.effectiveStatus !== "pass");
|
|
1225
1226
|
if (!firstFailure) {
|
|
1226
1227
|
return "Review validation output";
|
|
1227
1228
|
}
|
|
@@ -1277,16 +1278,16 @@ async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks:
|
|
|
1277
1278
|
for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {
|
|
1278
1279
|
if (checkConfig === null)
|
|
1279
1280
|
continue;
|
|
1280
|
-
const result = await runCheck(type, {
|
|
1281
|
+
const result = normalizeVerificationRecord(await runCheck(type, {
|
|
1281
1282
|
mode,
|
|
1282
1283
|
skillName,
|
|
1283
1284
|
taskDir: path.resolve(taskDir),
|
|
1284
1285
|
artifactFile,
|
|
1285
1286
|
repositoryRoot: repoRoot,
|
|
1286
1287
|
config: checkConfig
|
|
1287
|
-
}, shared);
|
|
1288
|
-
checks.push(result);
|
|
1289
|
-
if (
|
|
1288
|
+
}, shared));
|
|
1289
|
+
checks.push(...(result.subchecks?.map(normalizeVerificationRecord) ?? [result]));
|
|
1290
|
+
if (checks.at(-1)?.effectiveStatus === "blocked")
|
|
1290
1291
|
break;
|
|
1291
1292
|
}
|
|
1292
1293
|
const gate = summarizeGate(checks);
|
|
@@ -1298,15 +1299,25 @@ async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks:
|
|
|
1298
1299
|
return { skill: skillName, ...failResult(type, `Unknown check type '${type}' for skill '${skillName}'.`) };
|
|
1299
1300
|
if (config === null)
|
|
1300
1301
|
return { skill: skillName, ...passResult(type, `Check '${type}' is disabled for skill '${skillName}'.`) };
|
|
1302
|
+
const result = normalizeVerificationRecord(await runCheck(type, {
|
|
1303
|
+
skillName,
|
|
1304
|
+
taskDir: path.resolve(taskDir),
|
|
1305
|
+
artifactFile,
|
|
1306
|
+
repositoryRoot: repoRoot,
|
|
1307
|
+
config
|
|
1308
|
+
}, shared));
|
|
1309
|
+
if (!result.subchecks?.length)
|
|
1310
|
+
return { skill: skillName, ...result };
|
|
1311
|
+
const checks = result.subchecks.map(normalizeVerificationRecord);
|
|
1312
|
+
const gate = summarizeGate(checks);
|
|
1301
1313
|
return {
|
|
1302
1314
|
skill: skillName,
|
|
1303
|
-
...
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
}, shared)
|
|
1315
|
+
...result,
|
|
1316
|
+
status: gate,
|
|
1317
|
+
effectiveStatus: gate,
|
|
1318
|
+
reason: gate === 'pass' ? 'OK' : checks.find((check) => check.effectiveStatus !== 'pass')?.reason ?? 'CHECK_FAILED',
|
|
1319
|
+
action: buildAction(gate, checks),
|
|
1320
|
+
checks
|
|
1310
1321
|
};
|
|
1311
1322
|
}
|
|
1312
1323
|
export { verifyInProcess };
|
|
@@ -80,7 +80,7 @@ async function verifyTaskEvent(request, options = {}) {
|
|
|
80
80
|
else {
|
|
81
81
|
for (const check of spec.checks ?? []) {
|
|
82
82
|
const payload = await engine({ mode: 'checks', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [check], repositoryRoot: resolved.repoRoot });
|
|
83
|
-
const status = payload.status;
|
|
83
|
+
const status = (payload.effectiveStatus ?? payload.status);
|
|
84
84
|
if (status !== 'pass' && allowsManualOverride(options.manualOverride, 'verification-engine', status === 'blocked' ? 'CHECK_BLOCKED' : 'CHECK_FAILED')) {
|
|
85
85
|
invocations.push({ status: 'pass', exitCode: 0, payload: { ...payload, status: 'pass', humanOverride: 'human-approved', originalStatus: status } });
|
|
86
86
|
break;
|
|
@@ -103,19 +103,35 @@ function statusLabel(status) {
|
|
|
103
103
|
function renderPayload(payload) {
|
|
104
104
|
const lines = [];
|
|
105
105
|
if (Array.isArray(payload.checks)) {
|
|
106
|
-
|
|
106
|
+
const gateMode = typeof payload.gate === 'string';
|
|
107
|
+
lines.push(gateMode
|
|
108
|
+
? `Verification: ${payload.gate} | Skill: ${payload.skill}`
|
|
109
|
+
: `Check: ${payload.status} | Skill: ${payload.skill} | Type: ${payload.type}`, '');
|
|
107
110
|
for (const check of payload.checks) {
|
|
108
|
-
|
|
111
|
+
const raw = statusLabel(check.status);
|
|
112
|
+
const effective = statusLabel(check.effectiveStatus ?? check.status);
|
|
113
|
+
const reason = check.reason ?? 'CHECK_FAILED';
|
|
114
|
+
const message = check.message ?? reason;
|
|
115
|
+
lines.push(` [${effective}] ${check.checkId ?? check.type} (${check.classification ?? 'hard'}; raw ${raw}; reason ${reason}) - ${message}; ${check.action ?? 'Review validation output'}`);
|
|
109
116
|
}
|
|
110
|
-
|
|
117
|
+
const summary = payload.summary ?? (() => {
|
|
118
|
+
const checks = payload.checks;
|
|
119
|
+
const statuses = checks.map((check) => check.effectiveStatus ?? check.status);
|
|
120
|
+
return `${statuses.filter((status) => status === 'pass').length} passed, ${statuses.filter((status) => status === 'fail').length} failed${statuses.includes('blocked') ? `, ${statuses.filter((status) => status === 'blocked').length} blocked` : ''}`;
|
|
121
|
+
})();
|
|
122
|
+
lines.push('', `Result: ${summary} - ${payload.action}`);
|
|
111
123
|
}
|
|
112
124
|
else {
|
|
113
125
|
lines.push(`Check: ${payload.status} | Skill: ${payload.skill} | Type: ${payload.type}`, '');
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
126
|
+
const raw = statusLabel(payload.status);
|
|
127
|
+
const effective = statusLabel(payload.effectiveStatus ?? payload.status);
|
|
128
|
+
const reason = payload.reason ?? 'CHECK_FAILED';
|
|
129
|
+
lines.push(` [${effective}] ${payload.checkId ?? payload.type} (${payload.classification ?? 'hard'}; raw ${raw}; reason ${reason}) - ${payload.message ?? reason}; ${payload.action ?? 'Review validation output'}`);
|
|
130
|
+
const status = payload.effectiveStatus ?? payload.status;
|
|
131
|
+
const summary = status === 'pass' ? '1 passed, 0 failed'
|
|
132
|
+
: status === 'blocked' ? '0 passed, 0 failed, 1 blocked' : '0 passed, 1 failed';
|
|
133
|
+
const action = status === 'pass' ? 'Requested check passed'
|
|
134
|
+
: status === 'blocked' ? `Resolve blocked ${payload.type} check and re-run check`
|
|
119
135
|
: `Fix ${payload.type} issues and re-run check`;
|
|
120
136
|
lines.push('', `Result: ${summary} - ${action}`);
|
|
121
137
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"protocolVersion": 3,
|
|
3
|
-
"packageVersion": "0.11.
|
|
4
|
-
"sourceInputHash": "
|
|
5
|
-
"internalExecutableBuildHash": "
|
|
3
|
+
"packageVersion": "0.11.1",
|
|
4
|
+
"sourceInputHash": "0d66fb32bbdc0982d38a04b86b0278768bb6091eb945ebd90a432f9bae363712",
|
|
5
|
+
"internalExecutableBuildHash": "4b1edd20ed87d3d742e5e7975fd49b1ac1fb0ff14f837d52ee9ba3ab11318365"
|
|
6
6
|
}
|
|
@@ -44,6 +44,7 @@ function printFailure(format: OutputFormat, error: { code: string; message: stri
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const MANUAL_VALIDATION_STATUS_SECTION = /^###\s+(?:⚠️\s+(?:需人工校验|Manual Validation Required)|✅\s+(?:人工验证已通过|无需人工校验|Manual Validation Passed|No Manual Validation Required)|⏳\s+(?:人工验证待收尾|Manual Validation Pending))\s*$[\s\S]*?(?=^#{1,3}\s|(?![\s\S]))/gmu;
|
|
47
|
+
const TRAILING_CANONICAL_REPORT_PLACEHOLDER = /\n*<!--\s*canonical-pr-change-report\s*-->\s*$/u;
|
|
47
48
|
|
|
48
49
|
function manualSummaryBody(body: string, phase: 'pending' | 'final', transactionId: string, receiptDigest = '', evidenceDigest = '', prHeadSha = ''): string {
|
|
49
50
|
const chinese = /###\s+(?:⚠️\s+需人工校验|✅\s+(?:人工验证已通过|无需人工校验)|⏳\s+人工验证待收尾)\s*$/mu.test(body);
|
|
@@ -55,10 +56,13 @@ function manualSummaryBody(body: string, phase: 'pending' | 'final', transaction
|
|
|
55
56
|
? `### ✅ 人工验证已通过\n\n人工验证已通过;transaction=${transactionId}; receipt=${receiptDigest}; evidence=${evidenceDigest}; head=${prHeadSha}.`
|
|
56
57
|
: `### ✅ Manual Validation Passed\n\nManual validation passed; transaction=${transactionId}; receipt=${receiptDigest}; evidence=${evidenceDigest}; head=${prHeadSha}.`;
|
|
57
58
|
let inserted = false;
|
|
58
|
-
const updated = body.replace(MANUAL_VALIDATION_STATUS_SECTION, () => {
|
|
59
|
+
const updated = body.replace(MANUAL_VALIDATION_STATUS_SECTION, (matched) => {
|
|
59
60
|
if (inserted) return '';
|
|
60
61
|
inserted = true;
|
|
61
|
-
|
|
62
|
+
const trailingPlaceholder = TRAILING_CANONICAL_REPORT_PLACEHOLDER.exec(matched)?.[0];
|
|
63
|
+
return trailingPlaceholder
|
|
64
|
+
? `${trailingPlaceholder.trim()}\n\n${section}\n\n`
|
|
65
|
+
: `${section}\n\n`;
|
|
62
66
|
});
|
|
63
67
|
return inserted ? `${updated.replace(/\s+$/u, '')}\n` : `${body.replace(/\s+$/u, '')}\n\n${section}\n`;
|
|
64
68
|
}
|
package/lib/platform/issues.ts
CHANGED
|
@@ -574,9 +574,8 @@ async function syncPlatformIssue(taskRef: string, options: SyncOptions): Promise
|
|
|
574
574
|
const failure = plan.operations.find((operation) => operation.status === 'failed');
|
|
575
575
|
if (failure) return result('failed', base.resolved.taskId, base.issueNumber, { issue: snapshot, operations: plan.operations, error: { code: failure.reasonCode || 'ISSUE_SYNC_FAILED', message: `Operation ${failure.name} failed`, retryable: false } });
|
|
576
576
|
const planned = plan.operations.filter((operation) => operation.status === 'planned');
|
|
577
|
-
|
|
578
|
-
if (
|
|
579
|
-
if (planned.length === 0) return result(skipped ? 'degraded' : 'no-op', base.resolved.taskId, base.issueNumber, { issue: snapshot, operations: plan.operations, error: null });
|
|
577
|
+
if (options.dryRun) return result(planned.length ? 'planned' : 'no-op', base.resolved.taskId, base.issueNumber, { issue: snapshot, operations: plan.operations, error: null });
|
|
578
|
+
if (planned.length === 0) return result('no-op', base.resolved.taskId, base.issueNumber, { issue: snapshot, operations: plan.operations, error: null });
|
|
580
579
|
const payload = applyRestOperations(snapshot, planned) as Partial<{
|
|
581
580
|
title: string; body: string; labels: string[]; assignees: string[];
|
|
582
581
|
milestone: string | null; state: 'open' | 'closed'; fields: Record<string, string | number | null>;
|
|
@@ -611,7 +610,7 @@ async function syncPlatformIssue(taskRef: string, options: SyncOptions): Promise
|
|
|
611
610
|
error: { code: 'IN_LABEL_SYNC_PARTIAL', message: 'Issue labels did not converge after update', retryable: true }
|
|
612
611
|
});
|
|
613
612
|
}
|
|
614
|
-
return result(
|
|
613
|
+
return result('applied', base.resolved.taskId, base.issueNumber, {
|
|
615
614
|
changed: updated.value.changed, platform: base.context.platform, capabilities: base.context.capabilities,
|
|
616
615
|
resource: { kind: 'issue', number: base.issueNumber, identity: base.issueIdentity }, issue: finalIssue,
|
|
617
616
|
operations: plan.operations.map((operation) => operation.status === 'planned' ? { ...operation, status: 'applied' } : operation), error: null
|