@fitlab-ai/agent-infra 0.9.12 → 0.9.13
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/README.md +11 -11
- package/README.zh-CN.md +11 -11
- package/dist/bin/internal-cli.js +24 -19
- package/dist/lib/agent-clients/next-steps.js +6 -1
- package/dist/lib/decide.js +3 -3
- package/dist/lib/internal/platform-checks.js +3 -3
- package/dist/lib/internal/platform-comment.js +9 -9
- package/dist/lib/internal/platform-context.js +2 -2
- package/dist/lib/internal/platform-issue.js +8 -9
- package/dist/lib/internal/platform-pr-review.js +10 -10
- package/dist/lib/internal/platform-pr.js +63 -24
- package/dist/lib/internal/platform-release-notes.js +3 -3
- package/dist/lib/internal/pr-review-grade.js +11 -9
- package/dist/lib/internal/release-workflow.js +4 -4
- package/dist/lib/internal/sandbox-control.js +30 -4
- package/dist/lib/internal/task-activity.js +3 -3
- package/dist/lib/internal/task-artifact.js +76 -24
- package/dist/lib/internal/task-create.js +2 -2
- package/dist/lib/internal/task-event.js +6 -3
- package/dist/lib/internal/task-finalization.js +2 -2
- package/dist/lib/internal/task-invalidation.js +60 -0
- package/dist/lib/internal/task-ledger.js +9 -6
- package/dist/lib/internal/task-lifecycle.js +2 -2
- package/dist/lib/internal/task-override.js +4 -4
- package/dist/lib/internal/task-review.js +3 -3
- package/dist/lib/internal/task-verify.js +6 -6
- package/dist/lib/internal/task-warning.js +3 -3
- package/dist/lib/platform/adapters.js +1 -3
- package/dist/lib/platform/change-request-git-evidence.js +27 -7
- package/dist/lib/platform/completion-backfill.js +6 -5
- package/dist/lib/platform/context.js +70 -130
- package/dist/lib/platform/github-client.js +1 -1
- package/dist/lib/platform/github-provider.js +903 -0
- package/dist/lib/platform/in-label-sync.js +143 -0
- package/dist/lib/platform/issue-comments.js +94 -41
- package/dist/lib/platform/issues.js +335 -189
- package/dist/lib/platform/metadata-labels.js +6 -2
- package/dist/lib/platform/none-provider.js +28 -0
- package/dist/lib/platform/pr-change-report.js +551 -0
- package/dist/lib/platform/pr-checks.js +119 -104
- package/dist/lib/platform/pr-review.js +88 -72
- package/dist/lib/platform/pr-summary.js +520 -50
- package/dist/lib/platform/provider-bridge.js +45 -0
- package/dist/lib/platform/provider-contract.d.ts +487 -0
- package/dist/lib/platform/provider-contract.js +95 -0
- package/dist/lib/platform/provider-loader.js +251 -0
- package/dist/lib/platform/provider-validation.js +504 -0
- package/dist/lib/platform/pull-request-metadata.js +8 -6
- package/dist/lib/platform/pull-requests.js +783 -537
- package/dist/lib/platform/release-notes.js +78 -55
- package/dist/lib/platform/releases.js +79 -50
- package/dist/lib/platform/resource-identity.d.ts +26 -0
- package/dist/lib/platform/resource-identity.js +92 -0
- package/dist/lib/platform/task-identities.js +31 -0
- package/dist/lib/platform/verification-required.js +11 -12
- package/dist/lib/platform/verification-sync.js +112 -238
- package/dist/lib/pr-review/evidence-grading.js +19 -6
- package/dist/lib/run/index.js +63 -23
- package/dist/lib/sandbox/control/client.js +96 -15
- package/dist/lib/sandbox/control/executor.js +3 -3
- package/dist/lib/sandbox/control/protocol.js +77 -0
- package/dist/lib/sandbox/control/server.js +398 -25
- package/dist/lib/sandbox/control/state.js +204 -1
- package/dist/lib/server/protocol.js +38 -1
- package/dist/lib/task/activity-log.js +8 -1
- package/dist/lib/task/artifact-lifecycle.js +33 -5
- package/dist/lib/task/capabilities.js +239 -0
- package/dist/lib/task/commands/status.js +32 -0
- package/dist/lib/task/commit-operation.js +12 -1
- package/dist/lib/task/control-authority.js +8 -5
- package/dist/lib/task/create-service.js +8 -8
- package/dist/lib/task/current-contract.js +5 -1
- package/dist/lib/task/decision-details.js +1 -1
- package/dist/lib/task/events.js +297 -17
- package/dist/lib/task/finalization.js +37 -13
- package/dist/lib/task/human-override.js +58 -36
- package/dist/lib/task/invalidation-command.js +86 -0
- package/dist/lib/task/invalidation.js +260 -0
- package/dist/lib/task/ledger-intents.js +37 -0
- package/dist/lib/task/local-artifact-finalization.js +374 -0
- package/dist/lib/task/orchestration.js +49 -93
- package/dist/lib/task/pr-delivery-fact.js +102 -101
- package/dist/lib/task/review-fingerprint.js +24 -2
- package/dist/lib/task/rework-intent.js +138 -0
- package/dist/lib/task/skill-scope.js +23 -0
- package/dist/lib/task/task-execution-lock.js +27 -17
- package/dist/lib/task/verification-engine.js +43 -16
- package/dist/lib/task/verification.js +3 -3
- package/dist/lib/task/workflow-warning-intents.js +1 -1
- package/dist/lib/task/write.js +11 -0
- package/dist/lib/version.js +11 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/next-steps.ts +6 -1
- package/lib/decide.ts +3 -3
- package/lib/init.ts +1 -1
- package/lib/internal/platform-checks.ts +3 -3
- package/lib/internal/platform-comment.ts +8 -8
- package/lib/internal/platform-context.ts +2 -2
- package/lib/internal/platform-issue.ts +7 -8
- package/lib/internal/platform-pr-review.ts +9 -9
- package/lib/internal/platform-pr.ts +47 -22
- package/lib/internal/platform-release-notes.ts +3 -3
- package/lib/internal/pr-review-grade.ts +10 -8
- package/lib/internal/release-workflow.ts +4 -4
- package/lib/internal/sandbox-control.ts +27 -3
- package/lib/internal/task-activity.ts +3 -3
- package/lib/internal/task-artifact.ts +65 -22
- package/lib/internal/task-create.ts +2 -2
- package/lib/internal/task-event.ts +6 -3
- package/lib/internal/task-finalization.ts +3 -3
- package/lib/internal/task-invalidation.ts +39 -0
- package/lib/internal/task-ledger.ts +11 -8
- package/lib/internal/task-lifecycle.ts +2 -2
- package/lib/internal/task-override.ts +6 -6
- package/lib/internal/task-review.ts +3 -3
- package/lib/internal/task-verify.ts +6 -6
- package/lib/internal/task-warning.ts +3 -3
- package/lib/platform/adapters.ts +3 -2
- package/lib/platform/change-request-git-evidence.ts +36 -9
- package/lib/platform/completion-backfill.ts +9 -8
- package/lib/platform/context.ts +97 -134
- package/lib/platform/github-client.ts +2 -2
- package/lib/platform/github-provider.ts +910 -0
- package/lib/platform/in-label-sync.ts +208 -0
- package/lib/platform/issue-comments.ts +97 -47
- package/lib/platform/issues.ts +344 -174
- package/lib/platform/metadata-labels.ts +5 -2
- package/lib/platform/none-provider.ts +35 -0
- package/lib/platform/pr-change-report.ts +645 -0
- package/lib/platform/pr-checks.ts +126 -106
- package/lib/platform/pr-review.ts +88 -85
- package/lib/platform/pr-summary.ts +560 -53
- package/lib/platform/provider-bridge.ts +82 -0
- package/lib/platform/provider-contract.ts +536 -0
- package/lib/platform/provider-loader.ts +307 -0
- package/lib/platform/provider-validation.ts +529 -0
- package/lib/platform/pull-request-metadata.ts +10 -7
- package/lib/platform/pull-requests.ts +826 -543
- package/lib/platform/release-notes.ts +76 -59
- package/lib/platform/releases.ts +77 -43
- package/lib/platform/resource-identity.ts +121 -0
- package/lib/platform/task-identities.ts +40 -0
- package/lib/platform/types.ts +4 -2
- package/lib/platform/verification-required.ts +11 -13
- package/lib/platform/verification-sync.ts +112 -292
- package/lib/pr-review/evidence-grading.ts +25 -8
- package/lib/run/index.ts +57 -22
- package/lib/sandbox/control/client.ts +105 -15
- package/lib/sandbox/control/executor.ts +4 -4
- package/lib/sandbox/control/protocol.ts +113 -0
- package/lib/sandbox/control/server.ts +431 -23
- package/lib/sandbox/control/state.ts +251 -1
- package/lib/server/protocol.ts +36 -1
- package/lib/task/activity-log.ts +8 -0
- package/lib/task/artifact-lifecycle.ts +32 -6
- package/lib/task/capabilities.ts +262 -0
- package/lib/task/commands/status.ts +38 -0
- package/lib/task/commit-operation.ts +12 -1
- package/lib/task/control-authority.ts +11 -8
- package/lib/task/create-service.ts +8 -8
- package/lib/task/current-contract.ts +6 -1
- package/lib/task/decision-details.ts +6 -2
- package/lib/task/events.ts +296 -16
- package/lib/task/finalization.ts +50 -14
- package/lib/task/human-override.ts +70 -46
- package/lib/task/invalidation-command.ts +86 -0
- package/lib/task/invalidation.ts +332 -0
- package/lib/task/ledger-intents.ts +35 -1
- package/lib/task/local-artifact-finalization.ts +563 -0
- package/lib/task/orchestration.ts +52 -85
- package/lib/task/pr-delivery-fact.ts +131 -148
- package/lib/task/review-fingerprint.ts +23 -2
- package/lib/task/rework-intent.ts +165 -0
- package/lib/task/skill-scope.ts +24 -0
- package/lib/task/task-execution-lock.ts +23 -14
- package/lib/task/verification-engine.ts +52 -17
- package/lib/task/verification.ts +4 -4
- package/lib/task/workflow-warning-intents.ts +1 -1
- package/lib/task/write.ts +19 -0
- package/lib/update.ts +1 -1
- package/lib/version.ts +15 -1
- package/package.json +7 -1
- package/templates/.agents/rules/README.en.md +1 -1
- package/templates/.agents/rules/README.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +2 -0
- package/templates/.agents/rules/issue-sync.zh-CN.md +2 -0
- package/templates/.agents/rules/local-artifact-repair.en.md +9 -2
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +9 -2
- package/templates/.agents/rules/pr-sync.en.md +10 -4
- package/templates/.agents/rules/pr-sync.zh-CN.md +17 -4
- package/templates/.agents/rules/task-short-id.en.md +1 -4
- package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
- package/templates/.agents/skills/analyze-task/SKILL.en.md +13 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +10 -3
- package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
- package/templates/.agents/skills/code-task/SKILL.en.md +27 -8
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +29 -10
- package/templates/.agents/skills/code-task/config/verify.en.json +1 -0
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +2 -0
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +3 -3
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +3 -3
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -3
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +4 -3
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +4 -3
- package/templates/.agents/skills/complete-task/SKILL.en.md +21 -3
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +20 -3
- package/templates/.agents/skills/create-pr/SKILL.en.md +7 -6
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +7 -7
- package/templates/.agents/skills/create-pr/config/verify.json +1 -0
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
- package/templates/.agents/skills/plan-task/SKILL.en.md +13 -3
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +10 -3
- package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/review-code/SKILL.en.md +4 -4
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +4 -2
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +4 -2
- package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
- package/templates/.agents/templates/task.en.md +18 -1
- package/templates/.agents/templates/task.zh-CN.md +18 -1
- package/templates/.github/workflows/pr-label.yml +7 -26
|
@@ -21,6 +21,7 @@ import { snapshotReview } from "../git/review-snapshot.js";
|
|
|
21
21
|
import { OrchestrationStateError, readRun } from "./orchestration.js";
|
|
22
22
|
import { resolveDeliveryTarget } from "./delivery-target.js";
|
|
23
23
|
import { readPrDeliveryFact } from "./pr-delivery-fact.js";
|
|
24
|
+
import { validateLocalArtifact } from "./local-artifact-finalization.js";
|
|
24
25
|
const TASK_ENUMS = {
|
|
25
26
|
type: ["feature", "bugfix", "refactor", "docs", "chore"],
|
|
26
27
|
workflow: ["feature-development", "bug-fix", "refactoring"],
|
|
@@ -69,7 +70,7 @@ const scriptPath = fileURLToPath(import.meta.url);
|
|
|
69
70
|
let repoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
|
|
70
71
|
const PLATFORM_ADAPTERS = {
|
|
71
72
|
"platform-sync": checkPlatformSync,
|
|
72
|
-
"platform-sync-preflight": (context, shared) => ({ ...checkPlatformSync(context, shared), type: "platform-sync-preflight" }),
|
|
73
|
+
"platform-sync-preflight": async (context, shared) => ({ ...await checkPlatformSync(context, shared), type: "platform-sync-preflight" }),
|
|
73
74
|
"required-checks": checkRequiredChecks
|
|
74
75
|
};
|
|
75
76
|
const OPTIONAL_PLATFORM_CHECKS = new Set(["platform-sync"]);
|
|
@@ -86,7 +87,7 @@ const sharedUtils = {
|
|
|
86
87
|
parseIssueNumber,
|
|
87
88
|
parsePrNumber
|
|
88
89
|
};
|
|
89
|
-
function runCheck(type, context, shared) {
|
|
90
|
+
async function runCheck(type, context, shared) {
|
|
90
91
|
switch (type) {
|
|
91
92
|
case "task-meta":
|
|
92
93
|
return checkTaskMeta(context);
|
|
@@ -124,7 +125,7 @@ function runCheck(type, context, shared) {
|
|
|
124
125
|
}
|
|
125
126
|
return failResult(type, `Unsupported check type '${type}'.`);
|
|
126
127
|
}
|
|
127
|
-
return adapter(context, shared);
|
|
128
|
+
return await adapter(context, shared);
|
|
128
129
|
}
|
|
129
130
|
}
|
|
130
131
|
}
|
|
@@ -419,7 +420,7 @@ function checkTaskMeta({ taskDir, config }) {
|
|
|
419
420
|
const warningSuffix = warnings.length > 0 ? `; warnings: ${warnings.join("; ")}` : "";
|
|
420
421
|
return passResult("task-meta", `Task metadata valid (${requiredFields.length} required fields checked${warningSuffix})`, warnings);
|
|
421
422
|
}
|
|
422
|
-
function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
|
|
423
|
+
async function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
|
|
423
424
|
const task = loadTask(taskDir);
|
|
424
425
|
if (!task.ok)
|
|
425
426
|
return failResult('required-pr-delivery', task.message);
|
|
@@ -438,10 +439,11 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
|
|
|
438
439
|
return failResult('required-pr-delivery', factRead.error.message);
|
|
439
440
|
const fact = factRead.status === 'valid' ? factRead.fact : null;
|
|
440
441
|
const status = fact?.state || 'unbound';
|
|
441
|
-
const
|
|
442
|
+
const prIdentity = fact?.state === 'bound' ? fact.identity.resource : null;
|
|
443
|
+
const prNumber = prIdentity?.kind === 'number' ? prIdentity.value : null;
|
|
442
444
|
if (flow === 'disabled')
|
|
443
445
|
return passResult('required-pr-delivery', 'Pull request delivery is disabled by project policy');
|
|
444
|
-
if (flow === 'required' && (status !== 'bound' ||
|
|
446
|
+
if (flow === 'required' && (status !== 'bound' || !prIdentity)) {
|
|
445
447
|
return failResult('required-pr-delivery', 'Project policy requires a bound pull request before completion');
|
|
446
448
|
}
|
|
447
449
|
if (flow !== 'required' && status === 'unbound') {
|
|
@@ -451,7 +453,7 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
|
|
|
451
453
|
if (mode === 'gate') {
|
|
452
454
|
return passResult('required-pr-delivery', 'Bound pull request shape is valid; merged-state inspection is reserved for hard preflight');
|
|
453
455
|
}
|
|
454
|
-
const inspected = inspectPlatformPullRequest(task.metadata.id, { cwd: repositoryRoot });
|
|
456
|
+
const inspected = await inspectPlatformPullRequest(task.metadata.id, { cwd: repositoryRoot });
|
|
455
457
|
if (inspected.status === 'blocked') {
|
|
456
458
|
return blockedResult('required-pr-delivery', inspected.error?.message || 'Unable to inspect the required pull request', inspected.error?.code || 'PR_INSPECTION_BLOCKED');
|
|
457
459
|
}
|
|
@@ -459,7 +461,7 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
|
|
|
459
461
|
const repository = inspected.platform.repository?.toLowerCase() || '';
|
|
460
462
|
const taskBranch = String(task.metadata.branch || '').trim();
|
|
461
463
|
const deliveryBaseRef = String(task.metadata.delivery_base_ref || projectConfig.delivery?.baseRef || '').trim();
|
|
462
|
-
if (inspected.status !== 'no-op' || !pullRequest
|
|
464
|
+
if (inspected.status !== 'no-op' || !pullRequest) {
|
|
463
465
|
return failResult('required-pr-delivery', 'Bound pull request identity could not be verified');
|
|
464
466
|
}
|
|
465
467
|
if (!repository
|
|
@@ -472,7 +474,7 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
|
|
|
472
474
|
if (pullRequest.state !== 'closed' || !pullRequest.mergedAt || !pullRequest.mergeCommitSha) {
|
|
473
475
|
return failResult('required-pr-delivery', 'Project policy requires the bound pull request to be merged');
|
|
474
476
|
}
|
|
475
|
-
return passResult('required-pr-delivery', `Pull request delivery policy satisfied (merged PR
|
|
477
|
+
return passResult('required-pr-delivery', `Pull request delivery policy satisfied (merged PR ${prNumber === null ? 'identity' : `#${prNumber}`})`);
|
|
476
478
|
}
|
|
477
479
|
return passResult('required-pr-delivery', `Pull request delivery policy satisfied (${status})`);
|
|
478
480
|
}
|
|
@@ -504,7 +506,7 @@ function loadProjectName() {
|
|
|
504
506
|
return "";
|
|
505
507
|
}
|
|
506
508
|
}
|
|
507
|
-
function checkArtifact({ taskDir, config, artifactFile }) {
|
|
509
|
+
function checkArtifact({ taskDir, config, artifactFile, skillName }) {
|
|
508
510
|
const resolvedArtifact = resolveArtifactPath(taskDir, config.file_pattern, artifactFile);
|
|
509
511
|
if (!resolvedArtifact.ok) {
|
|
510
512
|
return failResult("artifact", resolvedArtifact.message);
|
|
@@ -519,6 +521,20 @@ function checkArtifact({ taskDir, config, artifactFile }) {
|
|
|
519
521
|
}
|
|
520
522
|
const content = fs.readFileSync(artifactPath, "utf8");
|
|
521
523
|
const requiredSections = config.required_sections || [];
|
|
524
|
+
const localFamily = skillName === "analyze-task"
|
|
525
|
+
? "analysis"
|
|
526
|
+
: skillName === "plan-task" ? "plan" : skillName === "code-task" ? "code" : null;
|
|
527
|
+
if (localFamily) {
|
|
528
|
+
const local = validateLocalArtifact(content, {
|
|
529
|
+
family: localFamily,
|
|
530
|
+
requiredSections: requiredSections.filter((section) => typeof section === "string"),
|
|
531
|
+
requiredPatterns: (config.required_patterns || []).filter((pattern) => typeof pattern === "string")
|
|
532
|
+
});
|
|
533
|
+
if (!local.ok) {
|
|
534
|
+
return failResult("artifact", `${path.basename(artifactPath)} has local structural errors: ${local.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')}`);
|
|
535
|
+
}
|
|
536
|
+
return passResult("artifact", `${path.basename(artifactPath)} passed (${requiredSections.length} sections)`);
|
|
537
|
+
}
|
|
522
538
|
const missingSections = requiredSections.filter((section) => !new RegExp(`^##\\s+${escapeRegExp(section)}\\s*$`, "m").test(content));
|
|
523
539
|
if (missingSections.length > 0) {
|
|
524
540
|
return failResult("artifact", `${path.basename(artifactPath)} is missing sections: ${missingSections.join(", ")}`);
|
|
@@ -902,6 +918,8 @@ function checkManualValidation({ taskDir }) {
|
|
|
902
918
|
// 1. Latest review-code artifact; none -> pass (no review, check not applicable).
|
|
903
919
|
const review = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
904
920
|
if (!review.ok) {
|
|
921
|
+
if (review.error)
|
|
922
|
+
return failResult("manual-validation", `Review-code artifact is unavailable: ${review.error}`);
|
|
905
923
|
return passResult("manual-validation", "No review-code artifact; manual validation not applicable");
|
|
906
924
|
}
|
|
907
925
|
// 2. Parse the numeric manual-validation count; unparseable/null -> fail closed
|
|
@@ -953,9 +971,11 @@ function checkManualValidation({ taskDir }) {
|
|
|
953
971
|
}
|
|
954
972
|
return passResult("manual-validation", `Manual validation completed → ${artifactName}`);
|
|
955
973
|
}
|
|
956
|
-
function checkPostReviewCommit({ taskDir, config }) {
|
|
974
|
+
async function checkPostReviewCommit({ taskDir, config }) {
|
|
957
975
|
const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
958
976
|
if (!reviewArtifact.ok) {
|
|
977
|
+
if (reviewArtifact.error)
|
|
978
|
+
return failResult("post-review-commit", `Review-code artifact is unavailable: ${reviewArtifact.error}`);
|
|
959
979
|
return passResult("post-review-commit", "No review-code artifact; check inactive");
|
|
960
980
|
}
|
|
961
981
|
let gitRoot;
|
|
@@ -977,7 +997,7 @@ function checkPostReviewCommit({ taskDir, config }) {
|
|
|
977
997
|
const hasPullRequest = fact?.state === 'bound';
|
|
978
998
|
let inspected = null;
|
|
979
999
|
if (hasPullRequest) {
|
|
980
|
-
inspected = inspectPlatformPullRequest(task.metadata.id, { cwd: gitRoot });
|
|
1000
|
+
inspected = await inspectPlatformPullRequest(task.metadata.id, { cwd: gitRoot });
|
|
981
1001
|
if (!inspected.pullRequest) {
|
|
982
1002
|
const message = inspected.error?.message || "PR merge snapshot is unavailable";
|
|
983
1003
|
const code = inspected.error?.code || "PR_INSPECTION_INVALID";
|
|
@@ -988,7 +1008,7 @@ function checkPostReviewCommit({ taskDir, config }) {
|
|
|
988
1008
|
if (inspected.pullRequest.state === "closed" &&
|
|
989
1009
|
inspected.pullRequest.mergedAt &&
|
|
990
1010
|
inspected.pullRequest.mergeCommitSha) {
|
|
991
|
-
const relation = resolveMaterializedReviewedHeadRelation({
|
|
1011
|
+
const relation = await resolveMaterializedReviewedHeadRelation({
|
|
992
1012
|
cwd: gitRoot,
|
|
993
1013
|
platformType: inspected.platform.type,
|
|
994
1014
|
lastReviewedCommit,
|
|
@@ -1124,6 +1144,13 @@ function checkReviewFact({ taskDir, artifactFile }) {
|
|
|
1124
1144
|
if (!resolvedArtifact.ok) {
|
|
1125
1145
|
return failResult("review-fact", resolvedArtifact.message);
|
|
1126
1146
|
}
|
|
1147
|
+
const authoritative = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
1148
|
+
if (!authoritative.ok) {
|
|
1149
|
+
return failResult("review-fact", authoritative.error ?? "No active review-code artifact is available");
|
|
1150
|
+
}
|
|
1151
|
+
if (path.basename(resolvedArtifact.path) !== authoritative.fileName) {
|
|
1152
|
+
return failResult("review-fact", `review-code artifact ${path.basename(resolvedArtifact.path)} is not the current active artifact ${authoritative.fileName}; re-run review-code`);
|
|
1153
|
+
}
|
|
1127
1154
|
const task = loadTask(taskDir);
|
|
1128
1155
|
if (!task.ok) {
|
|
1129
1156
|
return failResult("review-fact", task.message);
|
|
@@ -1401,7 +1428,7 @@ function escapeRegExp(value) {
|
|
|
1401
1428
|
function isBlank(value) {
|
|
1402
1429
|
return value === undefined || value === null || String(value).trim() === "";
|
|
1403
1430
|
}
|
|
1404
|
-
function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }) {
|
|
1431
|
+
async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }) {
|
|
1405
1432
|
if (repositoryRoot)
|
|
1406
1433
|
repoRoot = path.resolve(repositoryRoot);
|
|
1407
1434
|
else {
|
|
@@ -1418,7 +1445,7 @@ function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: reque
|
|
|
1418
1445
|
for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {
|
|
1419
1446
|
if (checkConfig === null)
|
|
1420
1447
|
continue;
|
|
1421
|
-
const result = runCheck(type, {
|
|
1448
|
+
const result = await runCheck(type, {
|
|
1422
1449
|
mode,
|
|
1423
1450
|
skillName,
|
|
1424
1451
|
taskDir: path.resolve(taskDir),
|
|
@@ -1441,7 +1468,7 @@ function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: reque
|
|
|
1441
1468
|
return { skill: skillName, ...passResult(type, `Check '${type}' is disabled for skill '${skillName}'.`) };
|
|
1442
1469
|
return {
|
|
1443
1470
|
skill: skillName,
|
|
1444
|
-
...runCheck(type, {
|
|
1471
|
+
...await runCheck(type, {
|
|
1445
1472
|
skillName,
|
|
1446
1473
|
taskDir: path.resolve(taskDir),
|
|
1447
1474
|
artifactFile,
|
|
@@ -41,7 +41,7 @@ function failure(request, code, message, extra = {}) {
|
|
|
41
41
|
artifact: request.artifact ?? null, invocations: [], error: { code, message }, ...extra
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
-
function verifyTaskEvent(request, options = {}) {
|
|
44
|
+
async function verifyTaskEvent(request, options = {}) {
|
|
45
45
|
const spec = VERIFICATION_CATALOG[request.event];
|
|
46
46
|
if (!spec)
|
|
47
47
|
return failure(request, 'VERIFY_EVENT_UNKNOWN', `unknown verification event '${request.event}'`);
|
|
@@ -66,7 +66,7 @@ function verifyTaskEvent(request, options = {}) {
|
|
|
66
66
|
const invocations = [];
|
|
67
67
|
const engine = options.engine ?? verifyInProcess;
|
|
68
68
|
if (spec.mode === 'gate') {
|
|
69
|
-
const payload = engine({ mode: 'gate', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [], repositoryRoot: resolved.repoRoot });
|
|
69
|
+
const payload = await engine({ mode: 'gate', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [], repositoryRoot: resolved.repoRoot });
|
|
70
70
|
const status = payload.gate;
|
|
71
71
|
if (status !== 'pass' && allowsManualOverride(options.manualOverride, 'verification-engine', status === 'blocked' ? 'CHECK_BLOCKED' : 'CHECK_FAILED')) {
|
|
72
72
|
invocations.push({ status: 'pass', exitCode: 0, payload: { ...payload, gate: 'pass', humanOverride: 'human-approved', originalGate: status } });
|
|
@@ -79,7 +79,7 @@ function verifyTaskEvent(request, options = {}) {
|
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
81
|
for (const check of spec.checks ?? []) {
|
|
82
|
-
const payload = engine({ mode: 'checks', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [check], repositoryRoot: resolved.repoRoot });
|
|
82
|
+
const payload = await engine({ mode: 'checks', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [check], repositoryRoot: resolved.repoRoot });
|
|
83
83
|
const status = 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 } });
|
|
@@ -38,7 +38,7 @@ function sectionMutation(content) {
|
|
|
38
38
|
const english = /^##\s+Activity Log\s*$/m.test(content);
|
|
39
39
|
return [{
|
|
40
40
|
kind: 'section', aliases: WORKFLOW_WARNING_HEADINGS, heading: english ? 'Workflow Warnings' : '工作流告警',
|
|
41
|
-
body: `| ${WORKFLOW_WARNING_COLUMNS.join(' | ')} |\n
|
|
41
|
+
body: `| ${WORKFLOW_WARNING_COLUMNS.join(' | ')} |\n|----|------|------|----------|------|--------|---------|--------|-------------|------------|------------|`
|
|
42
42
|
}];
|
|
43
43
|
}
|
|
44
44
|
function rowMutation(row) {
|
package/dist/lib/task/write.js
CHANGED
|
@@ -6,6 +6,7 @@ import { resolveTaskRef } from './resolve-ref.js';
|
|
|
6
6
|
import { allowsManualOverride } from './guard-override.js';
|
|
7
7
|
import { mutateTableRow, upsertSection } from './sections.js';
|
|
8
8
|
import { validateCurrentTaskContract } from './current-contract.js';
|
|
9
|
+
import { invalidationBlocks, parseInvalidationDocument } from './invalidation.js';
|
|
9
10
|
const DEFAULT_FILE_SYSTEM = {
|
|
10
11
|
readFileSync: (file) => fs.readFileSync(file, 'utf8'),
|
|
11
12
|
statModeSync: (file) => fs.statSync(file).mode,
|
|
@@ -90,6 +91,16 @@ function writeTask(request, options = {}) {
|
|
|
90
91
|
if (!contract.ok) {
|
|
91
92
|
return failure(request, identity, contract.code, contract.message);
|
|
92
93
|
}
|
|
94
|
+
if (invalidationBlocks(contract.invalidation)
|
|
95
|
+
&& options.invalidationContext !== 'source-completion'
|
|
96
|
+
&& options.invalidationContext !== 'reconcile') {
|
|
97
|
+
return failure(request, identity, 'TASK_INVALIDATION_BLOCKED', 'task has an incomplete artifact invalidation operation; reconcile it before writing downstream state');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const invalidation = parseInvalidationDocument(original);
|
|
102
|
+
if (!invalidation.ok)
|
|
103
|
+
return failure(request, identity, 'TASK_INVALIDATION_INVALID', invalidation.message);
|
|
93
104
|
}
|
|
94
105
|
let candidate = original;
|
|
95
106
|
const operations = [];
|
package/dist/lib/version.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import semver from 'semver';
|
|
2
3
|
const packageJsonUrl = [
|
|
3
4
|
new URL('../package.json', import.meta.url),
|
|
4
5
|
new URL('../../package.json', import.meta.url),
|
|
@@ -9,8 +10,17 @@ if (!packageJsonUrl) {
|
|
|
9
10
|
const { version } = JSON.parse(readFileSync(packageJsonUrl, 'utf8'));
|
|
10
11
|
const VERSION = `v${version}`;
|
|
11
12
|
const AGENT_INFRA_VERSION_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
13
|
+
const LEGACY_COMPATIBILITY_CUTOFF_VERSION = '1.0.0';
|
|
12
14
|
function isValidAgentInfraVersion(value) {
|
|
13
15
|
return typeof value === 'string' && AGENT_INFRA_VERSION_PATTERN.test(value);
|
|
14
16
|
}
|
|
15
|
-
|
|
17
|
+
function isLegacyCompatibilityEnabled(runtimeVersion = VERSION) {
|
|
18
|
+
const normalized = runtimeVersion.startsWith('v') ? runtimeVersion.slice(1) : runtimeVersion;
|
|
19
|
+
const parsed = semver.valid(normalized);
|
|
20
|
+
return parsed !== null && semver.lt(parsed, LEGACY_COMPATIBILITY_CUTOFF_VERSION);
|
|
21
|
+
}
|
|
22
|
+
function legacyCompatibilityError(resource, runtimeVersion = VERSION) {
|
|
23
|
+
return Object.assign(new Error(`PLATFORM_IDENTITY_LEGACY_UNSUPPORTED: ${resource} requires migration to the current schema before v${LEGACY_COMPATIBILITY_CUTOFF_VERSION} runtime ${runtimeVersion}`), { code: 'PLATFORM_IDENTITY_LEGACY_UNSUPPORTED' });
|
|
24
|
+
}
|
|
25
|
+
export { LEGACY_COMPATIBILITY_CUTOFF_VERSION, VERSION, isLegacyCompatibilityEnabled, isValidAgentInfraVersion, legacyCompatibilityError };
|
|
16
26
|
//# sourceMappingURL=version.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"protocolVersion": 3,
|
|
3
|
-
"packageVersion": "0.9.
|
|
4
|
-
"sourceInputHash": "
|
|
5
|
-
"internalExecutableBuildHash": "
|
|
3
|
+
"packageVersion": "0.9.13",
|
|
4
|
+
"sourceInputHash": "5e4d3ad1c1e7e3c909489ef59ff318ea9cffe5f538ae37d83923773946357afe",
|
|
5
|
+
"internalExecutableBuildHash": "c8cabf5c6bc776cdcb9621f712172ebda95ff9b12fb6f67213e18bc0159516fd"
|
|
6
6
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { listEnabledAgentClientAdapters } from './registry.ts';
|
|
2
2
|
import { renderAgentClientInvocation } from './invocation.ts';
|
|
3
3
|
import semver from 'semver';
|
|
4
|
+
import { isTaskScopeSkill } from '../task/skill-scope.ts';
|
|
4
5
|
import type { CustomTUI } from './custom-tuis.ts';
|
|
5
6
|
import type { AgentClientId, AgentClientState } from './types.ts';
|
|
6
7
|
|
|
@@ -45,7 +46,11 @@ function renderNextStepCommands(
|
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
const args = [
|
|
48
|
-
...(input.taskRef === undefined
|
|
49
|
+
...(input.taskRef === undefined
|
|
50
|
+
? []
|
|
51
|
+
: isTaskScopeSkill(input.skillName)
|
|
52
|
+
? ['--task', input.taskRef]
|
|
53
|
+
: [input.taskRef]),
|
|
49
54
|
...(input.version === undefined ? [] : [input.version])
|
|
50
55
|
];
|
|
51
56
|
|
package/lib/decide.ts
CHANGED
|
@@ -79,11 +79,11 @@ export async function decide(args: string[], options: DecideOptions = {}): Promi
|
|
|
79
79
|
metadataProvider: () => ({ timestamp: now, agentInfraVersion: options.version ?? VERSION })
|
|
80
80
|
};
|
|
81
81
|
let result;
|
|
82
|
-
const execute = () => {
|
|
82
|
+
const execute = async () => {
|
|
83
83
|
let current = applyHumanDecision(request, writeOptions);
|
|
84
84
|
if (current.status !== 'failed' || !parsedDecision.overrideTicket) return current;
|
|
85
85
|
if (!parsedDecision.overrideTarget || !parsedDecision.overrideScope) throw new Error('override ticket requires --override-target and --override-scope');
|
|
86
|
-
const consumed = consumeHumanOverride({
|
|
86
|
+
const consumed = await consumeHumanOverride({
|
|
87
87
|
taskRef: resolved.taskId,
|
|
88
88
|
ticketId: parsedDecision.overrideTicket,
|
|
89
89
|
failureId: failureId('decision-intent', current.error?.code ?? 'TASK_STATE_MISMATCH'),
|
|
@@ -102,7 +102,7 @@ export async function decide(args: string[], options: DecideOptions = {}): Promi
|
|
|
102
102
|
if (consumed.status === 'failed') throw new Error(consumed.error.message);
|
|
103
103
|
return current;
|
|
104
104
|
};
|
|
105
|
-
result = withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-decision', execute);
|
|
105
|
+
result = await withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-decision', execute);
|
|
106
106
|
if (result.error) throw new Error(result.error.message);
|
|
107
107
|
return 0;
|
|
108
108
|
} catch (error) {
|
package/lib/init.ts
CHANGED
|
@@ -40,7 +40,7 @@ type AgentConfig = {
|
|
|
40
40
|
project: string;
|
|
41
41
|
org: string;
|
|
42
42
|
language: string;
|
|
43
|
-
platform: { type: string };
|
|
43
|
+
platform: { type: string; providers?: Record<string, unknown> };
|
|
44
44
|
templateVersion: string;
|
|
45
45
|
sandbox: Record<string, unknown>;
|
|
46
46
|
task: { shortIdLength: number };
|
|
@@ -70,17 +70,17 @@ async function platformChecks(args: string[] = []): Promise<void> {
|
|
|
70
70
|
};
|
|
71
71
|
const unexpected = Object.keys(values).find((name) => !allowed[operation]!.includes(name));
|
|
72
72
|
if (unexpected) { fail(`${operation} does not accept --${unexpected}`); return; }
|
|
73
|
-
if (operation === 'inspect') { finish(inspectPullRequestReadiness(taskRef, { cwd })); return; }
|
|
73
|
+
if (operation === 'inspect') { finish(await inspectPullRequestReadiness(taskRef, { cwd })); return; }
|
|
74
74
|
if (operation === 'resolve-run') {
|
|
75
75
|
if (!values.checkName) { fail('resolve-run requires --check-name'); return; }
|
|
76
|
-
finish(resolvePlatformCheckRun(taskRef, { cwd, checkName: values.checkName, detailsUrl: values.detailsUrl }));
|
|
76
|
+
finish(await resolvePlatformCheckRun(taskRef, { cwd, checkName: values.checkName, detailsUrl: values.detailsUrl }));
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
79
|
if (operation === 'logs') {
|
|
80
80
|
const run = positive(values.run);
|
|
81
81
|
const job = values.job === undefined ? undefined : positive(values.job);
|
|
82
82
|
if (!run || values.job !== undefined && !job) { fail('logs requires a positive --run and optional positive --job'); return; }
|
|
83
|
-
finish(fetchPlatformCheckLogs(taskRef, { cwd, run, job: job || undefined }));
|
|
83
|
+
finish(await fetchPlatformCheckLogs(taskRef, { cwd, run, job: job || undefined }));
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
86
|
const intervalSeconds = positive(values.intervalSeconds);
|
|
@@ -11,7 +11,7 @@ import type { CommentKind } from '../platform/issue-comments.ts';
|
|
|
11
11
|
import type { PlatformResult } from '../platform/types.ts';
|
|
12
12
|
import { backfillCompletionComments } from '../platform/completion-backfill.ts';
|
|
13
13
|
|
|
14
|
-
const USAGE = `Usage: agent-infra-internal platform-comment list --issue <
|
|
14
|
+
const USAGE = `Usage: agent-infra-internal platform-comment list --issue <token> [--cwd <path>]
|
|
15
15
|
agent-infra-internal platform-comment owner <task-ref> [--cwd <path>]
|
|
16
16
|
agent-infra-internal platform-comment backfill <task-ref> --agent <agent> [--cwd <path>]
|
|
17
17
|
agent-infra-internal platform-comment sync <task-ref> --kind <kind> --agent <agent> [--artifact <file>] [--body-file <path|->] [--status-label <label>] [--backfill] [--cwd <path>]
|
|
@@ -52,7 +52,7 @@ function readBodyFile(value: string, cwd: string): string {
|
|
|
52
52
|
return fs.readFileSync(path.resolve(cwd, value), 'utf8');
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
function platformComment(args: string[] = []): void {
|
|
55
|
+
async function platformComment(args: string[] = []): Promise<void> {
|
|
56
56
|
if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
|
|
57
57
|
const operation = args[0];
|
|
58
58
|
if (!operation || !['list', 'owner', 'backfill', 'sync'].includes(operation)) { fail('a valid operation is required'); return; }
|
|
@@ -63,17 +63,17 @@ function platformComment(args: string[] = []): void {
|
|
|
63
63
|
if (parsed.error) { fail(parsed.error); return; }
|
|
64
64
|
const cwd = path.resolve(typeof parsed.values.cwd === 'string' ? parsed.values.cwd : process.cwd());
|
|
65
65
|
if (operation === 'list') {
|
|
66
|
-
const issue =
|
|
67
|
-
if (
|
|
66
|
+
const issue = parsed.values.issue;
|
|
67
|
+
if (typeof issue !== 'string' || !issue) { fail('list requires --issue <token>'); return; }
|
|
68
68
|
const unexpected = Object.keys(parsed.values).find((key) => !['issue', 'cwd'].includes(key));
|
|
69
69
|
if (unexpected) { fail(`list does not accept '--${unexpected}'`); return; }
|
|
70
|
-
finish(listPlatformComments(issue, cwd));
|
|
70
|
+
finish(await listPlatformComments(issue, cwd));
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
if (operation === 'owner') {
|
|
74
74
|
const unexpected = Object.keys(parsed.values).find((key) => key !== 'cwd');
|
|
75
75
|
if (unexpected) { fail(`owner does not accept '--${unexpected}'`); return; }
|
|
76
|
-
finish(checkPlatformCommentOwner(taskRef!, { cwd }));
|
|
76
|
+
finish(await checkPlatformCommentOwner(taskRef!, { cwd }));
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
79
|
if (operation === 'backfill') {
|
|
@@ -83,7 +83,7 @@ function platformComment(args: string[] = []): void {
|
|
|
83
83
|
if (typeof agent !== 'string' || !agent) { fail('backfill requires --agent'); return; }
|
|
84
84
|
const normalizedAgent = normalizeAgentToken(agent);
|
|
85
85
|
if (!normalizedAgent) { fail(`invalid --agent '${agent}': ${AGENT_USAGE_HINT}`); return; }
|
|
86
|
-
finish(backfillCompletionComments(taskRef!, { cwd, agent: normalizedAgent }));
|
|
86
|
+
finish(await backfillCompletionComments(taskRef!, { cwd, agent: normalizedAgent }));
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
89
|
const kind = parsed.values.kind;
|
|
@@ -101,7 +101,7 @@ function platformComment(args: string[] = []): void {
|
|
|
101
101
|
fail(`unable to read body file: ${error instanceof Error ? error.message : String(error)}`);
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
|
-
finish(syncPlatformComment(taskRef!, {
|
|
104
|
+
finish(await syncPlatformComment(taskRef!, {
|
|
105
105
|
kind: kind as CommentKind,
|
|
106
106
|
agent: normalizedAgent,
|
|
107
107
|
artifact: typeof parsed.values.artifact === 'string' ? parsed.values.artifact : undefined,
|
|
@@ -10,7 +10,7 @@ function fail(message: string): void {
|
|
|
10
10
|
process.exitCode = 1;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function platformContext(args: string[] = []): void {
|
|
13
|
+
async function platformContext(args: string[] = []): Promise<void> {
|
|
14
14
|
if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
|
|
15
15
|
if (args[0] !== 'resolve') { fail("operation must be 'resolve'"); return; }
|
|
16
16
|
let cwd = process.cwd();
|
|
@@ -24,7 +24,7 @@ function platformContext(args: string[] = []): void {
|
|
|
24
24
|
seen.add(flag);
|
|
25
25
|
cwd = path.resolve(value);
|
|
26
26
|
}
|
|
27
|
-
const result = resolvePlatformContext({ cwd });
|
|
27
|
+
const result = await resolvePlatformContext({ cwd });
|
|
28
28
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
29
29
|
if (result.status === 'failed') process.exitCode = 1;
|
|
30
30
|
if (result.status === 'blocked') process.exitCode = 2;
|
|
@@ -11,7 +11,7 @@ import type { IssueResult } from '../platform/issues.ts';
|
|
|
11
11
|
|
|
12
12
|
const USAGE = `Usage: agent-infra-internal platform-issue inspect <task-ref> [--cwd <path>]
|
|
13
13
|
agent-infra-internal platform-issue create <task-ref> --agent <agent> [--dry-run] [--cwd <path>]
|
|
14
|
-
agent-infra-internal platform-issue bind <task-ref> --issue <
|
|
14
|
+
agent-infra-internal platform-issue bind <task-ref> --issue <token> --agent <agent> [--dry-run] [--cwd <path>]
|
|
15
15
|
agent-infra-internal platform-issue sync <task-ref> --agent <agent> [--status <suffix|none>] [--assignees current|none] [--milestone initial|specific|none] [--issue-type] [--fields] [--requirements] [--in-labels from-diff|none] [--base <branch>] [--state open|closed] [--close-reason completed|not_planned] [--dry-run] [--cwd <path>]
|
|
16
16
|
`;
|
|
17
17
|
|
|
@@ -59,7 +59,7 @@ function oneOf(values: Record<string, string | boolean>, name: string, allowed:
|
|
|
59
59
|
return value;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
function platformIssue(args: string[] = []): void {
|
|
62
|
+
async function platformIssue(args: string[] = []): Promise<void> {
|
|
63
63
|
if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
|
|
64
64
|
const operation = args[0];
|
|
65
65
|
if (!operation || !['inspect', 'create', 'bind', 'sync'].includes(operation)) { fail('a valid operation is required'); return; }
|
|
@@ -75,18 +75,17 @@ function platformIssue(args: string[] = []): void {
|
|
|
75
75
|
};
|
|
76
76
|
const unexpected = Object.keys(values).find((name) => !allowed[operation]!.includes(name));
|
|
77
77
|
if (unexpected) { fail(`${operation} does not accept --${unexpected}`); return; }
|
|
78
|
-
if (operation === 'inspect') { finish(inspectPlatformIssue(taskRef, { cwd })); return; }
|
|
78
|
+
if (operation === 'inspect') { finish(await inspectPlatformIssue(taskRef, { cwd })); return; }
|
|
79
79
|
if (typeof values.agent !== 'string' || !values.agent) { fail(`${operation} requires --agent`); return; }
|
|
80
80
|
const agent = normalizeAgentToken(values.agent);
|
|
81
81
|
if (!agent) { fail(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
|
|
82
82
|
values.agent = agent;
|
|
83
83
|
if (operation === 'create') {
|
|
84
|
-
finish(createPlatformIssue(taskRef, { cwd, agent: values.agent, dryRun: values.dryRun === true })); return;
|
|
84
|
+
finish(await createPlatformIssue(taskRef, { cwd, agent: values.agent, dryRun: values.dryRun === true })); return;
|
|
85
85
|
}
|
|
86
86
|
if (operation === 'bind') {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
finish(bindPlatformIssue(taskRef, { cwd, agent: values.agent, issue, dryRun: values.dryRun === true })); return;
|
|
87
|
+
if (typeof values.issue !== 'string' || !values.issue) { fail('bind requires --issue <token>'); return; }
|
|
88
|
+
finish(await bindPlatformIssue(taskRef, { cwd, agent: values.agent, issue: values.issue, dryRun: values.dryRun === true })); return;
|
|
90
89
|
}
|
|
91
90
|
try {
|
|
92
91
|
const assignees = oneOf(values, 'assignees', ['current', 'none']);
|
|
@@ -99,7 +98,7 @@ function platformIssue(args: string[] = []): void {
|
|
|
99
98
|
if (closeReason && state !== 'closed') throw new Error('--close-reason requires --state closed');
|
|
100
99
|
const desiredKeys = ['status', 'assignees', 'milestone', 'issueType', 'fields', 'requirements', 'inLabels', 'state'];
|
|
101
100
|
if (!desiredKeys.some((name) => values[name] !== undefined)) throw new Error('sync requires at least one desired-state option');
|
|
102
|
-
finish(syncPlatformIssue(taskRef, {
|
|
101
|
+
finish(await syncPlatformIssue(taskRef, {
|
|
103
102
|
cwd, agent: values.agent, dryRun: values.dryRun === true,
|
|
104
103
|
status: typeof values.status === 'string' ? values.status : undefined,
|
|
105
104
|
assignees: assignees as 'current' | 'none' | undefined,
|
|
@@ -6,9 +6,9 @@ import { listPrReviews, publishPrReview } from '../platform/pr-review.ts';
|
|
|
6
6
|
import type { PrReviewEvent } from '../platform/pr-review.ts';
|
|
7
7
|
import type { PlatformResult } from '../platform/types.ts';
|
|
8
8
|
|
|
9
|
-
const USAGE = `Usage: agent-infra-internal platform-pr-review inspect --pr <
|
|
10
|
-
agent-infra-internal platform-pr-review list --pr <
|
|
11
|
-
agent-infra-internal platform-pr-review publish --pr <
|
|
9
|
+
const USAGE = `Usage: agent-infra-internal platform-pr-review inspect --pr <token> [--cwd <path>]
|
|
10
|
+
agent-infra-internal platform-pr-review list --pr <token> [--cwd <path>]
|
|
11
|
+
agent-infra-internal platform-pr-review publish --pr <token> --scope <taskId|pr{N}> --round <N> --commit <sha> --event <COMMENT|APPROVE|REQUEST_CHANGES> --body-file <path|-> [--dry-run] [--cwd <path>]
|
|
12
12
|
`;
|
|
13
13
|
|
|
14
14
|
const BOOLEAN_FLAGS = new Set(['--dry-run']);
|
|
@@ -50,7 +50,7 @@ function readBodyFile(value: string, cwd: string): string {
|
|
|
50
50
|
return value === '-' ? fs.readFileSync(0, 'utf8') : fs.readFileSync(path.resolve(cwd, value), 'utf8');
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
function platformPrReview(args: string[] = []): void {
|
|
53
|
+
async function platformPrReview(args: string[] = []): Promise<void> {
|
|
54
54
|
if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
|
|
55
55
|
const operation = args[0];
|
|
56
56
|
if (!operation || !['inspect', 'list', 'publish'].includes(operation)) { fail('a valid operation is required'); return; }
|
|
@@ -65,14 +65,14 @@ function platformPrReview(args: string[] = []): void {
|
|
|
65
65
|
};
|
|
66
66
|
const unexpected = Object.keys(values).find((name) => !allowed[operation]!.includes(name));
|
|
67
67
|
if (unexpected) { fail(`${operation} does not accept --${unexpected}`); return; }
|
|
68
|
-
const pr =
|
|
69
|
-
if (
|
|
68
|
+
const pr = values.pr;
|
|
69
|
+
if (typeof pr !== 'string' || !pr) { fail(`${operation} requires --pr <token>`); return; }
|
|
70
70
|
if (operation === 'inspect') {
|
|
71
|
-
finish(inspectPlatformPullRequestByNumber(pr, { cwd }));
|
|
71
|
+
finish(await inspectPlatformPullRequestByNumber(pr, { cwd }));
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
74
|
if (operation === 'list') {
|
|
75
|
-
finish(listPrReviews(pr, { cwd }));
|
|
75
|
+
finish(await listPrReviews(pr, { cwd }));
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
78
|
const scope = typeof values.scope === 'string' ? values.scope : '';
|
|
@@ -91,7 +91,7 @@ function platformPrReview(args: string[] = []): void {
|
|
|
91
91
|
fail(`unable to read body file: ${error instanceof Error ? error.message : String(error)}`);
|
|
92
92
|
return;
|
|
93
93
|
}
|
|
94
|
-
finish(publishPrReview({
|
|
94
|
+
finish(await publishPrReview({
|
|
95
95
|
cwd,
|
|
96
96
|
prNumber: pr,
|
|
97
97
|
identity: { scope, round, commitSha: commit },
|