@fitlab-ai/agent-infra 0.9.13 → 0.9.14
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/bin/cli.ts +26 -9
- package/dist/bin/cli.js +173 -157
- package/dist/bin/internal-cli.js +42 -21
- package/dist/lib/agent-client.js +5 -0
- package/dist/lib/internal/agent-client.js +5 -2
- package/dist/lib/internal/cli-route-inventory.js +152 -0
- package/dist/lib/internal/codex-lifecycle.js +9 -6
- package/dist/lib/internal/codex-sandbox-controller.js +8 -2
- package/dist/lib/internal/git-workflow.js +10 -6
- package/dist/lib/internal/platform-checks.js +16 -4
- package/dist/lib/internal/platform-comment.js +16 -4
- package/dist/lib/internal/platform-context.js +4 -1
- package/dist/lib/internal/platform-issue.js +12 -4
- package/dist/lib/internal/platform-metadata.js +88 -0
- package/dist/lib/internal/platform-pr-review.js +16 -3
- package/dist/lib/internal/platform-pr.js +24 -10
- package/dist/lib/internal/platform-release-notes.js +6 -3
- package/dist/lib/internal/platform-security.js +93 -0
- package/dist/lib/internal/pr-review-grade.js +14 -3
- package/dist/lib/internal/release-workflow.js +19 -5
- package/dist/lib/internal/sandbox-control.js +22 -5
- package/dist/lib/internal/task-activity.js +13 -4
- package/dist/lib/internal/task-artifact.js +186 -27
- package/dist/lib/internal/task-context.js +4 -1
- package/dist/lib/internal/task-create.js +48 -15
- package/dist/lib/internal/task-delivery.js +4 -1
- package/dist/lib/internal/task-event.js +4 -1
- package/dist/lib/internal/task-finalization.js +4 -1
- package/dist/lib/internal/task-invalidation.js +4 -1
- package/dist/lib/internal/task-ledger.js +12 -1
- package/dist/lib/internal/task-lifecycle.js +4 -1
- package/dist/lib/internal/task-operation-registry.js +421 -0
- package/dist/lib/internal/task-orchestration.js +12 -0
- package/dist/lib/internal/task-override.js +10 -3
- package/dist/lib/internal/task-qualification.js +90 -0
- package/dist/lib/internal/task-review.js +4 -1
- package/dist/lib/internal/task-short-id.js +11 -1
- package/dist/lib/internal/task-snapshot.js +4 -1
- package/dist/lib/internal/task-validate.js +7 -2
- package/dist/lib/internal/task-verify.js +5 -1
- package/dist/lib/internal/task-warning.js +8 -1
- package/dist/lib/platform/comment-safety.js +226 -0
- package/dist/lib/platform/github-provider.js +233 -6
- package/dist/lib/platform/issue-comments.js +146 -34
- package/dist/lib/platform/pr-change-report.js +6 -12
- package/dist/lib/platform/pr-summary.js +28 -7
- package/dist/lib/platform/provider-contract.d.ts +67 -1
- package/dist/lib/platform/provider-contract.js +6 -2
- package/dist/lib/platform/provider-validation.js +76 -3
- package/dist/lib/platform/pull-requests.js +115 -170
- package/dist/lib/platform/repository-metadata.js +377 -0
- package/dist/lib/platform/security-alerts.js +155 -0
- package/dist/lib/platform/verification-sync.js +33 -26
- package/dist/lib/process-data/index.js +7 -0
- package/dist/lib/run/index.js +5 -0
- package/dist/lib/sandbox/commands/control-status.js +22 -0
- package/dist/lib/sandbox/commands/create.js +32 -6
- package/dist/lib/sandbox/commands/ls.js +5 -0
- package/dist/lib/sandbox/commands/rm.js +827 -120
- package/dist/lib/sandbox/commands/show.js +16 -0
- package/dist/lib/sandbox/control/client.js +83 -9
- package/dist/lib/sandbox/control/completed-reentry.js +85 -0
- package/dist/lib/sandbox/control/container-identity.js +28 -31
- package/dist/lib/sandbox/control/executor.js +149 -14
- package/dist/lib/sandbox/control/lifecycle.js +621 -127
- package/dist/lib/sandbox/control/native-file-lock.js +177 -0
- package/dist/lib/sandbox/control/server.js +305 -35
- package/dist/lib/sandbox/control/state.js +5 -3
- package/dist/lib/sandbox/control/task-view.js +183 -0
- package/dist/lib/sandbox/engines/authority.js +289 -0
- package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
- package/dist/lib/sandbox/index.js +5 -0
- package/dist/lib/sandbox/recovery.js +21 -1
- package/dist/lib/sandbox/workspace-view.js +2 -1
- package/dist/lib/sandbox/worktree-safety.js +4 -1
- package/dist/lib/server/index.js +8 -0
- package/dist/lib/task/artifact-lifecycle.js +42 -13
- package/dist/lib/task/artifact-operations.js +520 -0
- package/dist/lib/task/artifact-repair-intent.js +59 -0
- package/dist/lib/task/artifact-schema.js +135 -0
- package/dist/lib/task/capabilities.js +72 -1
- package/dist/lib/task/control-authority.js +4 -0
- package/dist/lib/task/create-service.js +103 -4
- package/dist/lib/task/create.js +25 -0
- package/dist/lib/task/events.js +186 -67
- package/dist/lib/task/index.js +11 -3
- package/dist/lib/task/local-artifact-finalization.js +75 -150
- package/dist/lib/task/orchestration.js +192 -52
- package/dist/lib/task/qualification-audit.js +490 -0
- package/dist/lib/task/qualification-confirmation.js +109 -0
- package/dist/lib/task/qualification-intents.js +148 -0
- package/dist/lib/task/review-artifacts.js +22 -23
- package/dist/lib/task/review-finalization.js +121 -4
- package/dist/lib/task/sections.js +6 -4
- package/dist/lib/task/verification-config.js +11 -0
- package/dist/lib/task/verification-engine.js +54 -4
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +9 -0
- package/lib/internal/agent-client.ts +4 -2
- package/lib/internal/cli-route-inventory.ts +140 -0
- package/lib/internal/codex-lifecycle.ts +8 -6
- package/lib/internal/codex-sandbox-controller.ts +7 -2
- package/lib/internal/git-workflow.ts +9 -6
- package/lib/internal/platform-checks.ts +12 -4
- package/lib/internal/platform-comment.ts +12 -4
- package/lib/internal/platform-context.ts +3 -1
- package/lib/internal/platform-issue.ts +11 -4
- package/lib/internal/platform-metadata.ts +70 -0
- package/lib/internal/platform-pr-review.ts +14 -3
- package/lib/internal/platform-pr.ts +23 -10
- package/lib/internal/platform-release-notes.ts +5 -3
- package/lib/internal/platform-security.ts +83 -0
- package/lib/internal/pr-review-grade.ts +10 -3
- package/lib/internal/release-workflow.ts +17 -5
- package/lib/internal/sandbox-control.ts +19 -5
- package/lib/internal/task-activity.ts +12 -4
- package/lib/internal/task-artifact.ts +164 -25
- package/lib/internal/task-context.ts +3 -1
- package/lib/internal/task-create.ts +76 -15
- package/lib/internal/task-delivery.ts +3 -1
- package/lib/internal/task-event.ts +3 -1
- package/lib/internal/task-finalization.ts +3 -1
- package/lib/internal/task-invalidation.ts +3 -1
- package/lib/internal/task-ledger.ts +11 -1
- package/lib/internal/task-lifecycle.ts +3 -1
- package/lib/internal/task-operation-registry.ts +482 -0
- package/lib/internal/task-orchestration.ts +12 -0
- package/lib/internal/task-override.ts +9 -3
- package/lib/internal/task-qualification.ts +61 -0
- package/lib/internal/task-review.ts +3 -1
- package/lib/internal/task-short-id.ts +10 -1
- package/lib/internal/task-snapshot.ts +3 -1
- package/lib/internal/task-validate.ts +6 -2
- package/lib/internal/task-verify.ts +4 -1
- package/lib/internal/task-warning.ts +7 -1
- package/lib/platform/comment-safety.ts +250 -0
- package/lib/platform/github-provider.ts +229 -7
- package/lib/platform/issue-comments.ts +160 -35
- package/lib/platform/pr-change-report.ts +6 -12
- package/lib/platform/pr-summary.ts +27 -6
- package/lib/platform/provider-contract.ts +78 -3
- package/lib/platform/provider-validation.ts +85 -3
- package/lib/platform/pull-requests.ts +126 -178
- package/lib/platform/repository-metadata.ts +453 -0
- package/lib/platform/security-alerts.ts +191 -0
- package/lib/platform/verification-sync.ts +32 -28
- package/lib/process-data/index.ts +7 -0
- package/lib/run/index.ts +5 -0
- package/lib/sandbox/commands/control-status.ts +26 -0
- package/lib/sandbox/commands/create.ts +46 -6
- package/lib/sandbox/commands/ls.ts +7 -0
- package/lib/sandbox/commands/rm.ts +1000 -87
- package/lib/sandbox/commands/show.ts +16 -0
- package/lib/sandbox/control/client.ts +103 -9
- package/lib/sandbox/control/completed-reentry.ts +98 -0
- package/lib/sandbox/control/container-identity.ts +27 -43
- package/lib/sandbox/control/executor.ts +177 -12
- package/lib/sandbox/control/lifecycle.ts +629 -17
- package/lib/sandbox/control/native-file-lock.ts +209 -0
- package/lib/sandbox/control/protocol.ts +5 -2
- package/lib/sandbox/control/server.ts +319 -37
- package/lib/sandbox/control/state.ts +6 -3
- package/lib/sandbox/control/task-view.ts +240 -0
- package/lib/sandbox/engines/authority.ts +365 -0
- package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
- package/lib/sandbox/index.ts +7 -0
- package/lib/sandbox/recovery.ts +21 -1
- package/lib/sandbox/workspace-view.ts +9 -3
- package/lib/sandbox/worktree-safety.ts +4 -1
- package/lib/server/index.ts +10 -0
- package/lib/task/artifact-lifecycle.ts +38 -16
- package/lib/task/artifact-operations.ts +626 -0
- package/lib/task/artifact-repair-intent.ts +71 -0
- package/lib/task/artifact-schema.ts +192 -0
- package/lib/task/capabilities.ts +70 -1
- package/lib/task/control-authority.ts +11 -1
- package/lib/task/create-service.ts +131 -6
- package/lib/task/create.ts +27 -0
- package/lib/task/events.ts +161 -65
- package/lib/task/index.ts +16 -3
- package/lib/task/local-artifact-finalization.ts +87 -218
- package/lib/task/orchestration.ts +172 -49
- package/lib/task/qualification-audit.ts +599 -0
- package/lib/task/qualification-confirmation.ts +117 -0
- package/lib/task/qualification-intents.ts +150 -0
- package/lib/task/review-artifacts.ts +21 -22
- package/lib/task/review-finalization.ts +133 -4
- package/lib/task/sections.ts +6 -4
- package/lib/task/verification-config.ts +12 -0
- package/lib/task/verification-engine.ts +55 -4
- package/package.json +6 -1
- package/templates/.agents/rules/README.en.md +2 -0
- package/templates/.agents/rules/README.zh-CN.md +2 -0
- package/templates/.agents/rules/decision-qualification.en.md +22 -0
- package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
- package/templates/.agents/rules/evidence-reporting.en.md +28 -0
- package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
- package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
- package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
- package/templates/.agents/rules/security-alerts.en.md +8 -8
- package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
- package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
- package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
- package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
- package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
- 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/fix-mode.en.md +3 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/complete-task/SKILL.en.md +9 -22
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +9 -22
- package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
- package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
- package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
- package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
- package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
- package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
- package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -1
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
- package/templates/.agents/skills/test/SKILL.en.md +13 -2
- package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
- package/templates/.agents/templates/task.en.md +6 -0
- package/templates/.agents/templates/task.zh-CN.md +6 -0
- package/templates/.agents/scripts/security-alerts.github.sh +0 -151
- package/templates/.agents/scripts/security-alerts.sh +0 -31
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
|
@@ -11,6 +11,7 @@ import type { PrDeliveryFact } from '../task/pr-delivery-fact.ts';
|
|
|
11
11
|
import { resolvePlatformProviderContext } from './context.ts';
|
|
12
12
|
import type { LoadedContext, PlatformClient } from './context.ts';
|
|
13
13
|
import { normalizeCommentContent } from './issue-comments.ts';
|
|
14
|
+
import { CONTROL_MARKER_PATTERN, escapeHtmlText, sanitizeMarkdownDocument, splitDocumentPlaceholder } from './comment-safety.ts';
|
|
14
15
|
import { platformResult } from './types.ts';
|
|
15
16
|
import type { PlatformResult } from './types.ts';
|
|
16
17
|
import type { OperationWarning } from '../task/operation-outcome.ts';
|
|
@@ -19,6 +20,7 @@ import type { PlatformChangeRequestSnapshot } from './adapters.ts';
|
|
|
19
20
|
import type { ChangeRequestSnapshot } from './provider-contract.ts';
|
|
20
21
|
import {
|
|
21
22
|
buildPrChangeReport,
|
|
23
|
+
CANONICAL_REPORT_PLACEHOLDER,
|
|
22
24
|
readPrChangeReport,
|
|
23
25
|
replaceCanonicalReportPlaceholder,
|
|
24
26
|
runMechanicalChangeReport,
|
|
@@ -57,11 +59,7 @@ function summaryMarker(taskId: string): string {
|
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
function escapeSummaryAuditText(value: string): string {
|
|
60
|
-
return value
|
|
61
|
-
.replace(/&/g, '&')
|
|
62
|
-
.replace(/</g, '<')
|
|
63
|
-
.replace(/>/g, '>')
|
|
64
|
-
.replace(/\r\n?/g, '\n');
|
|
62
|
+
return escapeHtmlText(value).replace(/\r\n?/g, '\n');
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
function renderSummaryAuditLine(value: string): string {
|
|
@@ -528,7 +526,30 @@ async function syncPullRequestSummary(
|
|
|
528
526
|
if (!report.ok) return fail('failed', context, platformError(report.error));
|
|
529
527
|
const checked = currentReportCheck(report.value, initial.value, taskContent, resolved.repoRoot);
|
|
530
528
|
if (!checked.ok) return fail('failed', context, checked.error);
|
|
531
|
-
const
|
|
529
|
+
const placeholder = CANONICAL_REPORT_PLACEHOLDER;
|
|
530
|
+
const split = splitDocumentPlaceholder(options.body, placeholder);
|
|
531
|
+
if (!split.ok) return fail('failed', context, {
|
|
532
|
+
code: 'PR_SUMMARY_BODY_CONTRACT_INVALID',
|
|
533
|
+
message: split.error.message,
|
|
534
|
+
retryable: false
|
|
535
|
+
});
|
|
536
|
+
const prefix = sanitizeMarkdownDocument(split.value.prefix, { reservedMarkers: [CONTROL_MARKER_PATTERN] });
|
|
537
|
+
const suffix = sanitizeMarkdownDocument(split.value.suffix, { reservedMarkers: [CONTROL_MARKER_PATTERN] });
|
|
538
|
+
if (!prefix.ok) {
|
|
539
|
+
return fail('failed', context, {
|
|
540
|
+
code: 'PR_SUMMARY_BODY_CONTRACT_INVALID',
|
|
541
|
+
message: `${prefix.error.message} at offset ${prefix.error.offset}`,
|
|
542
|
+
retryable: false
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
if (!suffix.ok) {
|
|
546
|
+
return fail('failed', context, {
|
|
547
|
+
code: 'PR_SUMMARY_BODY_CONTRACT_INVALID',
|
|
548
|
+
message: `${suffix.error.message} at offset ${suffix.error.offset}`,
|
|
549
|
+
retryable: false
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
const replaced = replaceCanonicalReportPlaceholder(`${prefix.value}${placeholder}${suffix.value}`, report.value);
|
|
532
553
|
if (!replaced.ok) return fail('failed', context, platformError(replaced.error));
|
|
533
554
|
const desired = buildPullRequestSummary(resolved.taskId, replaced.value, initial.value.head.sha, renderHumanOverrideAudit(taskContent));
|
|
534
555
|
if (!isSafeSummaryEnvelope(desired, resolved.taskId)) return fail('failed', context, {
|
|
@@ -22,7 +22,7 @@ type PlatformError = {
|
|
|
22
22
|
|
|
23
23
|
type ProviderResult<T> =
|
|
24
24
|
| { ok: true; value: T }
|
|
25
|
-
| { ok: false; error: PlatformError };
|
|
25
|
+
| { ok: false; error: PlatformError; value?: T };
|
|
26
26
|
|
|
27
27
|
type ProviderOperationContext = {
|
|
28
28
|
repositoryRoot: string;
|
|
@@ -162,6 +162,41 @@ type MutationReceipt = {
|
|
|
162
162
|
operationId?: string;
|
|
163
163
|
};
|
|
164
164
|
|
|
165
|
+
type SecurityAlertKind = 'dependabot' | 'code-scanning';
|
|
166
|
+
|
|
167
|
+
type SecurityAlertSnapshot = {
|
|
168
|
+
kind: SecurityAlertKind;
|
|
169
|
+
number: number;
|
|
170
|
+
state: string;
|
|
171
|
+
data: JsonValue;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
type LabelDefinition = {
|
|
175
|
+
name: string;
|
|
176
|
+
color: string;
|
|
177
|
+
description: string;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
type LabelReconciliation = {
|
|
181
|
+
changed: boolean;
|
|
182
|
+
created: string[];
|
|
183
|
+
updated: string[];
|
|
184
|
+
removed: string[];
|
|
185
|
+
skipped: string[];
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
type MilestoneDefinition = {
|
|
189
|
+
title: string;
|
|
190
|
+
description: string;
|
|
191
|
+
state: 'open' | 'closed';
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
type MilestoneInitialization = {
|
|
195
|
+
changed: boolean;
|
|
196
|
+
created: string[];
|
|
197
|
+
skipped: string[];
|
|
198
|
+
};
|
|
199
|
+
|
|
165
200
|
type RepositoryMetadataSnapshot = {
|
|
166
201
|
repository: { identity: ResourceIdentity; name: string; url: string | null };
|
|
167
202
|
labels: Array<{ identity: ResourceIdentity; name: string }>;
|
|
@@ -286,6 +321,8 @@ type PlatformProvider = {
|
|
|
286
321
|
head: string;
|
|
287
322
|
}): Promise<ProviderResult<{ sha: string }>>;
|
|
288
323
|
inspect(input: { context: ProviderOperationContext; target: ResourceIdentity }): Promise<ProviderResult<ChangeRequestSnapshot>>;
|
|
324
|
+
listFiles?(input: { context: ProviderOperationContext; target: ResourceIdentity }): Promise<ProviderResult<string[]>>;
|
|
325
|
+
listClosingIssues?(input: { context: ProviderOperationContext; target: ResourceIdentity }): Promise<ProviderResult<ResourceIdentity[]>>;
|
|
289
326
|
listClosing(input: { context: ProviderOperationContext; issue: ResourceIdentity }): Promise<ProviderResult<ChangeRequestSnapshot[]>>;
|
|
290
327
|
create(input: {
|
|
291
328
|
context: ProviderOperationContext;
|
|
@@ -383,6 +420,34 @@ type PlatformProvider = {
|
|
|
383
420
|
historyLimit: number;
|
|
384
421
|
}): Promise<ProviderResult<ReleaseNotesFacts>>;
|
|
385
422
|
};
|
|
423
|
+
securityAlerts?: {
|
|
424
|
+
inspect(input: {
|
|
425
|
+
context: ProviderOperationContext;
|
|
426
|
+
kind: SecurityAlertKind;
|
|
427
|
+
number: number;
|
|
428
|
+
}): Promise<ProviderResult<SecurityAlertSnapshot>>;
|
|
429
|
+
dismiss(input: {
|
|
430
|
+
context: ProviderOperationContext;
|
|
431
|
+
kind: SecurityAlertKind;
|
|
432
|
+
number: number;
|
|
433
|
+
reason: string;
|
|
434
|
+
comment: string;
|
|
435
|
+
mutation: MutationIdentity;
|
|
436
|
+
}): Promise<ProviderResult<MutationReceipt>>;
|
|
437
|
+
};
|
|
438
|
+
repositoryMetadata?: {
|
|
439
|
+
reconcileLabels(input: {
|
|
440
|
+
context: ProviderOperationContext;
|
|
441
|
+
desired: LabelDefinition[];
|
|
442
|
+
cleanupStaleIn: boolean;
|
|
443
|
+
mutation: MutationIdentity;
|
|
444
|
+
}): Promise<ProviderResult<LabelReconciliation>>;
|
|
445
|
+
reconcileMilestones(input: {
|
|
446
|
+
context: ProviderOperationContext;
|
|
447
|
+
desired: MilestoneDefinition[];
|
|
448
|
+
mutation: MutationIdentity;
|
|
449
|
+
}): Promise<ProviderResult<MilestoneInitialization>>;
|
|
450
|
+
};
|
|
386
451
|
verification?: {
|
|
387
452
|
fetchRemoteFacts(input: {
|
|
388
453
|
context: ProviderOperationContext;
|
|
@@ -414,12 +479,14 @@ function validatePlatformProvider(
|
|
|
414
479
|
providerType: string
|
|
415
480
|
): ProviderResult<PlatformProvider> {
|
|
416
481
|
const operationGroups: Record<string, { required: string[]; optional: string[] }> = {
|
|
417
|
-
issues: { required: ['inspect', 'create', 'update', 'describeRepository'], optional: [] },
|
|
482
|
+
issues: { required: ['inspect', 'create', 'update', 'describeRepository'], optional: ['listLabels', 'listMilestones'] },
|
|
418
483
|
comments: { required: ['list', 'write', 'delete'], optional: [] },
|
|
419
|
-
changeRequests: { required: ['inspect', 'listClosing', 'create', 'update', 'resolveGitEvidence'], optional: ['verifyHead'] },
|
|
484
|
+
changeRequests: { required: ['inspect', 'listClosing', 'create', 'update', 'resolveGitEvidence'], optional: ['verifyHead', 'listFiles', 'listClosingIssues'] },
|
|
420
485
|
checks: { required: ['inspectRequired', 'resolveRun', 'fetchLogs'], optional: [] },
|
|
421
486
|
reviews: { required: ['list', 'publish'], optional: [] },
|
|
422
487
|
releases: { required: ['inspect', 'create', 'update', 'reconcileMilestones', 'publishNotes', 'collectNotes'], optional: [] },
|
|
488
|
+
securityAlerts: { required: ['inspect', 'dismiss'], optional: [] },
|
|
489
|
+
repositoryMetadata: { required: ['reconcileLabels', 'reconcileMilestones'], optional: [] },
|
|
423
490
|
verification: { required: ['fetchRemoteFacts'], optional: [] }
|
|
424
491
|
};
|
|
425
492
|
const resourceKindsByGroup: Record<string, PlatformResourceKind[]> = {
|
|
@@ -429,6 +496,8 @@ function validatePlatformProvider(
|
|
|
429
496
|
checks: ['pull-request'],
|
|
430
497
|
reviews: ['pull-request'],
|
|
431
498
|
releases: ['release', 'issue', 'pull-request'],
|
|
499
|
+
securityAlerts: [],
|
|
500
|
+
repositoryMetadata: [],
|
|
432
501
|
verification: ['issue', 'pull-request']
|
|
433
502
|
};
|
|
434
503
|
if (!isRecord(value)
|
|
@@ -515,6 +584,10 @@ export type {
|
|
|
515
584
|
IssueSnapshot,
|
|
516
585
|
JsonValue,
|
|
517
586
|
MilestoneReconciliation,
|
|
587
|
+
MilestoneDefinition,
|
|
588
|
+
MilestoneInitialization,
|
|
589
|
+
LabelDefinition,
|
|
590
|
+
LabelReconciliation,
|
|
518
591
|
MutationIdentity,
|
|
519
592
|
MutationReceipt,
|
|
520
593
|
PlatformCapabilities,
|
|
@@ -531,6 +604,8 @@ export type {
|
|
|
531
604
|
RepositoryMetadataSnapshot,
|
|
532
605
|
ReleaseNotesFacts,
|
|
533
606
|
ResourceIdentity,
|
|
607
|
+
SecurityAlertKind,
|
|
608
|
+
SecurityAlertSnapshot,
|
|
534
609
|
ReviewSnapshot,
|
|
535
610
|
VerificationRemoteFacts
|
|
536
611
|
};
|
|
@@ -5,7 +5,11 @@ import type {
|
|
|
5
5
|
CheckLogSnapshot,
|
|
6
6
|
CheckRunSnapshot,
|
|
7
7
|
GitEvidenceSnapshot,
|
|
8
|
+
LabelDefinition,
|
|
9
|
+
LabelReconciliation,
|
|
8
10
|
IssueSnapshot,
|
|
11
|
+
MilestoneDefinition,
|
|
12
|
+
MilestoneInitialization,
|
|
9
13
|
MilestoneReconciliation,
|
|
10
14
|
MutationReceipt,
|
|
11
15
|
PlatformContextSnapshot,
|
|
@@ -18,6 +22,8 @@ import type {
|
|
|
18
22
|
RepositoryMetadataSnapshot,
|
|
19
23
|
RequiredCheckSnapshot,
|
|
20
24
|
ReviewSnapshot,
|
|
25
|
+
SecurityAlertKind,
|
|
26
|
+
SecurityAlertSnapshot,
|
|
21
27
|
VerificationRemoteFacts
|
|
22
28
|
} from './provider-contract.ts';
|
|
23
29
|
import type { JsonValue } from './provider-contract.ts';
|
|
@@ -273,6 +279,67 @@ function validateReceipt(value: unknown): MutationReceipt {
|
|
|
273
279
|
};
|
|
274
280
|
}
|
|
275
281
|
|
|
282
|
+
function positiveInteger(value: unknown, label: string): number {
|
|
283
|
+
if (!Number.isSafeInteger(value) || (value as number) <= 0) throw new Error(`${label} must be a positive integer`);
|
|
284
|
+
return value as number;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function validateSecurityAlert(value: unknown): SecurityAlertSnapshot {
|
|
288
|
+
const item = record(value, 'security alert');
|
|
289
|
+
exactKeys(item, ['kind', 'number', 'state', 'data'], 'security alert');
|
|
290
|
+
if (item.kind !== 'dependabot' && item.kind !== 'code-scanning') throw new Error('security alert.kind is invalid');
|
|
291
|
+
return {
|
|
292
|
+
kind: item.kind as SecurityAlertKind,
|
|
293
|
+
number: positiveInteger(item.number, 'security alert.number'),
|
|
294
|
+
state: stringValue(item.state, 'security alert.state'),
|
|
295
|
+
data: jsonValue(item.data, 'security alert.data')
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function validateLabelDefinition(value: unknown, label: string): LabelDefinition {
|
|
300
|
+
const item = record(value, label);
|
|
301
|
+
exactKeys(item, ['name', 'color', 'description'], label);
|
|
302
|
+
return {
|
|
303
|
+
name: stringValue(item.name, `${label}.name`),
|
|
304
|
+
color: stringValue(item.color, `${label}.color`),
|
|
305
|
+
description: stringValue(item.description, `${label}.description`, true)
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function validateLabelReconciliation(value: unknown): LabelReconciliation {
|
|
310
|
+
const item = record(value, 'label reconciliation');
|
|
311
|
+
exactKeys(item, ['changed', 'created', 'updated', 'removed', 'skipped'], 'label reconciliation');
|
|
312
|
+
const names = (field: string) => arrayValue(item[field], `label reconciliation.${field}`).map((entry) => stringValue(entry, `${field}[]`));
|
|
313
|
+
return {
|
|
314
|
+
changed: booleanValue(item.changed, 'label reconciliation.changed'),
|
|
315
|
+
created: names('created'),
|
|
316
|
+
updated: names('updated'),
|
|
317
|
+
removed: names('removed'),
|
|
318
|
+
skipped: names('skipped')
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function validateMilestoneDefinition(value: unknown, label: string): MilestoneDefinition {
|
|
323
|
+
const item = record(value, label);
|
|
324
|
+
exactKeys(item, ['title', 'description', 'state'], label);
|
|
325
|
+
if (item.state !== 'open' && item.state !== 'closed') throw new Error(`${label}.state is invalid`);
|
|
326
|
+
return {
|
|
327
|
+
title: stringValue(item.title, `${label}.title`),
|
|
328
|
+
description: stringValue(item.description, `${label}.description`, true),
|
|
329
|
+
state: item.state
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function validateMilestoneInitialization(value: unknown): MilestoneInitialization {
|
|
334
|
+
const item = record(value, 'milestone initialization');
|
|
335
|
+
exactKeys(item, ['changed', 'created', 'skipped'], 'milestone initialization');
|
|
336
|
+
return {
|
|
337
|
+
changed: booleanValue(item.changed, 'milestone initialization.changed'),
|
|
338
|
+
created: arrayValue(item.created, 'milestone initialization.created').map((entry) => stringValue(entry, 'created[]')),
|
|
339
|
+
skipped: arrayValue(item.skipped, 'milestone initialization.skipped').map((entry) => stringValue(entry, 'skipped[]'))
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
|
|
276
343
|
function validateMetadata(value: unknown): RepositoryMetadataSnapshot {
|
|
277
344
|
const item = record(value, 'repository metadata');
|
|
278
345
|
exactKeys(item, ['repository', 'labels', 'milestones', 'issueTypes', 'fields'], 'repository metadata');
|
|
@@ -375,6 +442,11 @@ const PROVIDER_ERROR_CATALOG: Readonly<Record<string, { message: string; retryab
|
|
|
375
442
|
ISSUE_NUMBER_INVALID: { message: 'The issue number is invalid', retryable: false },
|
|
376
443
|
ISSUE_CREATE_RESPONSE_INVALID: { message: 'Issue creation returned an invalid response', retryable: false },
|
|
377
444
|
COMMENT_ID_INVALID: { message: 'The comment identity is invalid', retryable: false },
|
|
445
|
+
SECURITY_KIND_INVALID: { message: 'The security alert kind is invalid', retryable: false },
|
|
446
|
+
SECURITY_NUMBER_INVALID: { message: 'The security alert number is invalid', retryable: false },
|
|
447
|
+
SECURITY_RESPONSE_INVALID: { message: 'The platform returned an invalid security alert', retryable: false },
|
|
448
|
+
LABEL_RESPONSE_INVALID: { message: 'The platform returned an invalid label response', retryable: false },
|
|
449
|
+
MILESTONE_RESPONSE_INVALID: { message: 'The platform returned an invalid milestone response', retryable: false },
|
|
378
450
|
MILESTONE_IDENTITY_INVALID: { message: 'The milestone identity is invalid', retryable: false },
|
|
379
451
|
CHECK_RUN_NOT_FOUND: { message: 'The check run was not found', retryable: false },
|
|
380
452
|
RELEASE_NOTES_AUTHORS_TRUNCATED: { message: 'Release note commit authors exceeded the supported limit', retryable: false },
|
|
@@ -415,6 +487,8 @@ function validators(providerType: string, declaration?: ProviderIdentityDeclarat
|
|
|
415
487
|
return { sha: stringValue(item.sha, 'change request head.sha') };
|
|
416
488
|
},
|
|
417
489
|
'changeRequests.inspect': (value) => validateChangeRequest(value, declaredIdentityKind(declaration, 'pull-request'), true),
|
|
490
|
+
'changeRequests.listFiles': (value) => arrayValue(value, 'pull request files').map((entry) => stringValue(entry, 'pull request files[]')),
|
|
491
|
+
'changeRequests.listClosingIssues': (value) => arrayValue(value, 'closing issues').map((entry) => identity(entry, 'closing issues[]', declaredIdentityKind(declaration, 'issue'))),
|
|
418
492
|
'changeRequests.listClosing': (value) => arrayValue(value, 'changeRequests').map((entry) => validateChangeRequest(entry, declaredIdentityKind(declaration, 'pull-request'), true)),
|
|
419
493
|
'changeRequests.create': validateReceipt,
|
|
420
494
|
'changeRequests.update': validateReceipt,
|
|
@@ -458,6 +532,10 @@ function validators(providerType: string, declaration?: ProviderIdentityDeclarat
|
|
|
458
532
|
},
|
|
459
533
|
'releases.publishNotes': validateReceipt,
|
|
460
534
|
'releases.collectNotes': (value) => validateReleaseNotes(value, declaration),
|
|
535
|
+
'securityAlerts.inspect': validateSecurityAlert,
|
|
536
|
+
'securityAlerts.dismiss': validateReceipt,
|
|
537
|
+
'repositoryMetadata.reconcileLabels': validateLabelReconciliation,
|
|
538
|
+
'repositoryMetadata.reconcileMilestones': validateMilestoneInitialization,
|
|
461
539
|
'verification.fetchRemoteFacts': (value) => {
|
|
462
540
|
const item = record(value, 'verification facts');
|
|
463
541
|
exactKeys(item, ['issue', 'comments', 'changeRequest', 'commit', 'fields'], 'verification facts');
|
|
@@ -491,11 +569,15 @@ async function invokeProviderOperation<T>(
|
|
|
491
569
|
}
|
|
492
570
|
if (envelope.ok === false && envelope.error && typeof envelope.error === 'object' && !Array.isArray(envelope.error)) {
|
|
493
571
|
try {
|
|
494
|
-
exactKeys(envelope, ['ok', 'error'], `${operation} result`);
|
|
572
|
+
exactKeys(envelope, Object.hasOwn(envelope, 'value') ? ['ok', 'error', 'value'] : ['ok', 'error'], `${operation} result`);
|
|
495
573
|
const error = envelope.error as Record<string, unknown>;
|
|
496
574
|
exactKeys(error, ['code', 'message', 'retryable'], `${operation} error`);
|
|
497
575
|
if (typeof error.code !== 'string' || !error.code || typeof error.message !== 'string' || !error.message || typeof error.retryable !== 'boolean') throw new Error('invalid provider error');
|
|
498
|
-
return {
|
|
576
|
+
return {
|
|
577
|
+
ok: false,
|
|
578
|
+
error: safeProviderError(providerType, operation, error),
|
|
579
|
+
...(Object.hasOwn(envelope, 'value') ? { value: validate(envelope.value) } : {})
|
|
580
|
+
};
|
|
499
581
|
} catch {
|
|
500
582
|
return { ok: false, error: validationError(providerType, operation, 'Provider operation returned an invalid error') };
|
|
501
583
|
}
|
|
@@ -510,7 +592,7 @@ function wrapProviderOperations(provider: PlatformProvider): PlatformProvider {
|
|
|
510
592
|
const map = validators(provider.type, provider.identity);
|
|
511
593
|
const wrapped: PlatformProvider = { ...provider, context: { ...provider.context } };
|
|
512
594
|
wrapped.context.resolve = (input) => invokeProviderOperation(provider.type, 'context.resolve', () => provider.context.resolve(input), map['context.resolve']! as ResultValidator<PlatformContextSnapshot>);
|
|
513
|
-
for (const groupName of ['issues', 'comments', 'changeRequests', 'checks', 'reviews', 'releases', 'verification'] as const) {
|
|
595
|
+
for (const groupName of ['issues', 'comments', 'changeRequests', 'checks', 'reviews', 'releases', 'securityAlerts', 'repositoryMetadata', 'verification'] as const) {
|
|
514
596
|
const group = provider[groupName];
|
|
515
597
|
if (!group) continue;
|
|
516
598
|
const target: Record<string, unknown> = { ...group };
|