@fitlab-ai/agent-infra 0.9.13 → 0.9.15
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 +10 -0
- package/README.zh-CN.md +10 -0
- package/bin/cli.ts +26 -9
- package/bin/internal-cli.sh +45 -0
- package/dist/bin/cli.js +173 -157
- package/dist/bin/internal-cli.js +126 -42
- package/dist/lib/agent-client.js +5 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -2
- package/dist/lib/defaults.json +103 -103
- package/dist/lib/fs/durable-write.js +37 -0
- package/dist/lib/fs/file-lock.js +111 -0
- package/dist/lib/host-control/audit.js +19 -0
- package/dist/lib/host-control/client.js +142 -0
- package/dist/lib/host-control/command.js +49 -0
- package/dist/lib/host-control/path.js +160 -0
- package/dist/lib/host-control/secure-fs.js +140 -0
- package/dist/lib/host-control/server.js +159 -0
- package/dist/lib/host-control/service.js +112 -0
- package/dist/lib/init.js +11 -2
- package/dist/lib/internal/agent-client.js +5 -2
- package/dist/lib/internal/cli-route-inventory.js +154 -0
- package/dist/lib/internal/codex-lifecycle.js +15 -12
- package/dist/lib/internal/codex-sandbox-controller.js +8 -2
- package/dist/lib/internal/demo-promotion.js +322 -0
- package/dist/lib/internal/demo-transcript.js +454 -0
- package/dist/lib/internal/git-workflow.js +10 -6
- package/dist/lib/internal/host-control.js +28 -0
- package/dist/lib/internal/manual-validation.js +322 -0
- 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 +42 -14
- 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 +82 -89
- package/dist/lib/internal/sandbox-control.js +171 -7
- package/dist/lib/internal/task-activity.js +13 -4
- package/dist/lib/internal/task-artifact.js +19 -107
- package/dist/lib/internal/task-context.js +4 -1
- package/dist/lib/internal/task-create.js +48 -14
- package/dist/lib/internal/task-delivery.js +4 -1
- package/dist/lib/internal/task-event.js +38 -35
- 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 +519 -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 +10 -52
- 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 +37 -12
- package/dist/lib/internal/task-verify.js +5 -1
- package/dist/lib/internal/task-warning.js +8 -1
- package/dist/lib/owned-path.js +33 -0
- package/dist/lib/platform/check-status.js +11 -0
- package/dist/lib/platform/comment-safety.js +229 -0
- package/dist/lib/platform/completion-backfill.js +1 -1
- package/dist/lib/platform/github-data.js +241 -0
- package/dist/lib/platform/github-provider.js +248 -26
- package/dist/lib/platform/issue-comments.js +146 -34
- package/dist/lib/platform/issues.js +1 -179
- package/dist/lib/platform/pr-change-report.js +6 -12
- package/dist/lib/platform/pr-checks.js +12 -65
- package/dist/lib/platform/pr-summary.js +83 -10
- 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 +117 -275
- package/dist/lib/platform/repository-metadata.js +377 -0
- package/dist/lib/platform/security-alerts.js +155 -0
- package/dist/lib/platform/snapshots.js +2 -0
- package/dist/lib/platform/verification-sync.js +154 -162
- package/dist/lib/process-data/index.js +7 -0
- package/dist/lib/release/workflow.js +1 -1
- 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 +39 -8
- package/dist/lib/sandbox/commands/ls.js +5 -0
- package/dist/lib/sandbox/commands/rm.js +3 -807
- package/dist/lib/sandbox/commands/show.js +16 -0
- package/dist/lib/sandbox/control/audit.js +203 -0
- package/dist/lib/sandbox/control/client.js +125 -12
- 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 +233 -34
- package/dist/lib/sandbox/control/finalization-response.js +27 -0
- package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
- package/dist/lib/sandbox/control/lifecycle.js +656 -128
- package/dist/lib/sandbox/control/native-file-lock.js +85 -0
- package/dist/lib/sandbox/control/protocol.js +55 -4
- package/dist/lib/sandbox/control/server.js +720 -79
- package/dist/lib/sandbox/control/state.js +63 -3
- package/dist/lib/sandbox/control/task-view.js +183 -0
- package/dist/lib/sandbox/control/task-workflow.js +74 -0
- package/dist/lib/sandbox/control/workflow-executor.js +99 -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 +7 -2
- package/dist/lib/sandbox/recovery.js +49 -5
- package/dist/lib/sandbox/removal.js +1717 -0
- package/dist/lib/sandbox/task-cleanup.js +217 -0
- package/dist/lib/sandbox/workspace-view.js +15 -15
- package/dist/lib/sandbox/worktree-safety.js +4 -1
- package/dist/lib/server/index.js +8 -0
- package/dist/lib/task/activity-intent.js +2 -1
- package/dist/lib/task/activity-log.js +30 -24
- package/dist/lib/task/artifact-command.js +101 -0
- package/dist/lib/task/artifact-lifecycle.js +71 -40
- package/dist/lib/task/artifact-name.js +36 -0
- package/dist/lib/task/artifact-operations.js +474 -0
- package/dist/lib/task/artifact-receipts.js +3 -15
- package/dist/lib/task/artifact-repair-intent.js +130 -0
- package/dist/lib/task/artifact-schema.js +127 -0
- package/dist/lib/task/capabilities.js +83 -19
- package/dist/lib/task/codex-orchestration.js +71 -25
- package/dist/lib/task/commit-identity.js +28 -0
- package/dist/lib/task/commit-operation.js +2 -16
- package/dist/lib/task/control-authority.js +375 -5
- package/dist/lib/task/control-recovery.js +128 -0
- package/dist/lib/task/create-service.js +103 -4
- package/dist/lib/task/create.js +80 -2
- package/dist/lib/task/decision-details.js +2 -46
- package/dist/lib/task/events.js +306 -76
- package/dist/lib/task/finalization-state.js +9 -0
- package/dist/lib/task/human-override.js +3 -6
- package/dist/lib/task/implementation-inputs.js +3 -3
- package/dist/lib/task/index.js +11 -3
- package/dist/lib/task/intermediate-cleanup.js +383 -0
- package/dist/lib/task/invalidation.js +18 -65
- package/dist/lib/task/ledger-intents.js +7 -22
- package/dist/lib/task/ledger.js +1 -3
- package/dist/lib/task/lifecycle.js +19 -1
- package/dist/lib/task/local-artifact-finalization.js +190 -290
- package/dist/lib/task/manual-validation-completion.js +26 -0
- package/dist/lib/task/manual-validation-evidence.js +130 -0
- package/dist/lib/task/manual-validation-receipt.js +101 -0
- package/dist/lib/task/manual-validation-shared.js +40 -0
- package/dist/lib/task/manual-validation-transaction.js +243 -0
- package/dist/lib/task/markdown.js +47 -0
- package/dist/lib/task/orchestration.js +206 -69
- package/dist/lib/task/qualification-audit.js +476 -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 +23 -40
- package/dist/lib/task/review-command.js +25 -0
- package/dist/lib/task/review-finalization.js +146 -97
- package/dist/lib/task/review-fingerprint.js +2 -2
- package/dist/lib/task/sections.js +34 -54
- package/dist/lib/task/verification-config.js +11 -0
- package/dist/lib/task/verification-engine.js +170 -327
- package/dist/lib/task/verification.js +1 -1
- package/dist/lib/task/workflow-command.js +17 -0
- package/dist/lib/task/workflow-warning-intents.js +0 -16
- package/dist/lib/task/workflow-warnings.js +28 -2
- package/dist/lib/update.js +2 -0
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +9 -0
- package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -2
- package/lib/fs/durable-write.ts +29 -0
- package/lib/fs/file-lock.ts +113 -0
- package/lib/host-control/audit.ts +22 -0
- package/lib/host-control/client.ts +172 -0
- package/lib/host-control/command.ts +60 -0
- package/lib/host-control/path.ts +167 -0
- package/lib/host-control/secure-fs.ts +135 -0
- package/lib/host-control/server.ts +180 -0
- package/lib/host-control/service.ts +133 -0
- package/lib/init.ts +15 -2
- package/lib/internal/agent-client.ts +4 -2
- package/lib/internal/cli-route-inventory.ts +142 -0
- package/lib/internal/codex-lifecycle.ts +14 -12
- package/lib/internal/codex-sandbox-controller.ts +7 -2
- package/lib/internal/demo-promotion.ts +354 -0
- package/lib/internal/demo-transcript.ts +419 -0
- package/lib/internal/git-workflow.ts +9 -6
- package/lib/internal/host-control.ts +28 -0
- package/lib/internal/manual-validation.ts +306 -0
- 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 +38 -14
- 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 +91 -87
- package/lib/internal/sandbox-control.ts +181 -6
- package/lib/internal/task-activity.ts +12 -4
- package/lib/internal/task-artifact.ts +15 -79
- 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 +21 -10
- 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 +590 -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 +7 -50
- package/lib/internal/task-short-id.ts +10 -1
- package/lib/internal/task-snapshot.ts +3 -1
- package/lib/internal/task-validate.ts +32 -12
- package/lib/internal/task-verify.ts +4 -1
- package/lib/internal/task-warning.ts +7 -1
- package/lib/owned-path.ts +26 -0
- package/lib/platform/check-status.ts +9 -0
- package/lib/platform/comment-safety.ts +255 -0
- package/lib/platform/completion-backfill.ts +1 -1
- package/lib/platform/github-data.ts +322 -0
- package/lib/platform/github-provider.ts +244 -27
- package/lib/platform/issue-comments.ts +159 -35
- package/lib/platform/issues.ts +4 -245
- package/lib/platform/pr-change-report.ts +6 -12
- package/lib/platform/pr-checks.ts +13 -77
- package/lib/platform/pr-summary.ts +88 -11
- package/lib/platform/provider-contract.ts +78 -3
- package/lib/platform/provider-validation.ts +85 -3
- package/lib/platform/pull-requests.ts +129 -348
- package/lib/platform/repository-metadata.ts +453 -0
- package/lib/platform/security-alerts.ts +191 -0
- package/lib/platform/snapshots.ts +53 -0
- package/lib/platform/verification-sync.ts +171 -177
- package/lib/process-data/index.ts +7 -0
- package/lib/release/workflow.ts +3 -3
- package/lib/run/index.ts +5 -0
- package/lib/sandbox/commands/control-status.ts +26 -0
- package/lib/sandbox/commands/create.ts +53 -12
- package/lib/sandbox/commands/ls.ts +7 -0
- package/lib/sandbox/commands/rm.ts +3 -996
- package/lib/sandbox/commands/show.ts +16 -0
- package/lib/sandbox/control/audit.ts +253 -0
- package/lib/sandbox/control/client.ts +150 -13
- package/lib/sandbox/control/completed-reentry.ts +98 -0
- package/lib/sandbox/control/container-identity.ts +27 -43
- package/lib/sandbox/control/executor.ts +262 -37
- package/lib/sandbox/control/finalization-response.ts +29 -0
- package/lib/sandbox/control/identity-sentinel.ts +137 -0
- package/lib/sandbox/control/lifecycle.ts +672 -18
- package/lib/sandbox/control/native-file-lock.ts +108 -0
- package/lib/sandbox/control/protocol.ts +80 -8
- package/lib/sandbox/control/server.ts +779 -82
- package/lib/sandbox/control/state.ts +84 -3
- package/lib/sandbox/control/task-view.ts +240 -0
- package/lib/sandbox/control/task-workflow.ts +95 -0
- package/lib/sandbox/control/workflow-executor.ts +102 -0
- package/lib/sandbox/engines/authority.ts +365 -0
- package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
- package/lib/sandbox/index.ts +9 -2
- package/lib/sandbox/recovery.ts +49 -6
- package/lib/sandbox/removal.ts +2144 -0
- package/lib/sandbox/task-cleanup.ts +209 -0
- package/lib/sandbox/workspace-view.ts +26 -18
- package/lib/sandbox/worktree-safety.ts +4 -1
- package/lib/server/index.ts +10 -0
- package/lib/task/activity-intent.ts +2 -2
- package/lib/task/activity-log.ts +27 -19
- package/lib/task/artifact-command.ts +104 -0
- package/lib/task/artifact-lifecycle.ts +66 -39
- package/lib/task/artifact-name.ts +55 -0
- package/lib/task/artifact-operations.ts +580 -0
- package/lib/task/artifact-receipts.ts +3 -14
- package/lib/task/artifact-repair-intent.ts +152 -0
- package/lib/task/artifact-schema.ts +163 -0
- package/lib/task/capabilities.ts +82 -22
- package/lib/task/codex-orchestration.ts +85 -24
- package/lib/task/commit-identity.ts +31 -0
- package/lib/task/commit-operation.ts +2 -16
- package/lib/task/control-authority.ts +513 -6
- package/lib/task/control-recovery.ts +174 -0
- package/lib/task/create-service.ts +131 -6
- package/lib/task/create.ts +83 -1
- package/lib/task/decision-details.ts +3 -71
- package/lib/task/events.ts +292 -75
- package/lib/task/finalization-state.ts +11 -0
- package/lib/task/human-override.ts +3 -8
- package/lib/task/implementation-inputs.ts +3 -3
- package/lib/task/index.ts +16 -3
- package/lib/task/intermediate-cleanup.ts +455 -0
- package/lib/task/invalidation.ts +18 -62
- package/lib/task/ledger-intents.ts +7 -24
- package/lib/task/ledger.ts +1 -3
- package/lib/task/lifecycle.ts +17 -1
- package/lib/task/local-artifact-finalization.ts +223 -388
- package/lib/task/manual-validation-completion.ts +40 -0
- package/lib/task/manual-validation-evidence.ts +209 -0
- package/lib/task/manual-validation-receipt.ts +152 -0
- package/lib/task/manual-validation-shared.ts +50 -0
- package/lib/task/manual-validation-transaction.ts +304 -0
- package/lib/task/markdown.ts +70 -0
- package/lib/task/orchestration.ts +191 -68
- package/lib/task/qualification-audit.ts +588 -0
- package/lib/task/qualification-confirmation.ts +117 -0
- package/lib/task/qualification-intents.ts +150 -0
- package/lib/task/review-artifacts.ts +21 -41
- package/lib/task/review-command.ts +23 -0
- package/lib/task/review-finalization.ts +154 -153
- package/lib/task/review-fingerprint.ts +2 -2
- package/lib/task/sections.ts +33 -52
- package/lib/task/verification-config.ts +12 -0
- package/lib/task/verification-engine.ts +165 -370
- package/lib/task/verification-types.ts +17 -0
- package/lib/task/verification.ts +1 -1
- package/lib/task/workflow-command.ts +18 -0
- package/lib/task/workflow-warning-intents.ts +0 -13
- package/lib/task/workflow-warnings.ts +21 -2
- package/lib/update.ts +6 -0
- package/package.json +7 -2
- package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
- 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/rules/testing-discipline.en.md +2 -0
- package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
- package/templates/.agents/scripts/package.json +3 -0
- 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 +37 -21
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +37 -21
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +4 -0
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +4 -0
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
- package/templates/.agents/skills/complete-task/SKILL.en.md +10 -23
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -23
- 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/release/SKILL.en.md +7 -3
- package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
- 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 +25 -4
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +25 -4
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +5 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +5 -1
- package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/test/SKILL.en.md +29 -7
- package/templates/.agents/skills/test/SKILL.zh-CN.md +29 -7
- 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/.claude/commands/run-manual-validation.en.md +1 -1
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
- package/dist/lib/platform/adapters.js +0 -56
- package/lib/platform/adapters.ts +0 -197
- 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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { COMPLETION_BACKFILL_FAMILIES, inspectCompletionArtifacts } from '../task/finalization-artifacts.js';
|
|
4
|
-
import { parseArtifactName } from '../task/artifact-
|
|
4
|
+
import { parseArtifactName } from '../task/artifact-name.js';
|
|
5
5
|
import { parseTaskFrontmatter } from '../task/frontmatter.js';
|
|
6
6
|
import { resolveTaskRef } from '../task/resolve-ref.js';
|
|
7
7
|
import { getOpenWorkflowWarnings } from '../task/workflow-warnings.js';
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { checkStatusBucket } from './check-status.js';
|
|
2
|
+
const ISSUE_FIELDS_QUERY = `query($owner:String!,$name:String!,$number:Int!){repository(owner:$owner,name:$name){issue(number:$number){id issueType{id name pinnedFields{__typename ... on IssueFieldSingleSelect{id name options{id name}} ... on IssueFieldDate{id name} ... on IssueFieldText{id name} ... on IssueFieldNumber{id name}}} issueFieldValues(first:50){nodes{__typename ... on IssueFieldSingleSelectValue{name optionId field{... on IssueFieldSingleSelect{id name}}} ... on IssueFieldDateValue{value field{... on IssueFieldDate{id name}}} ... on IssueFieldTextValue{value field{... on IssueFieldText{id name}}} ... on IssueFieldNumberValue{value field{... on IssueFieldNumber{id name}}}}}}}}`;
|
|
3
|
+
function normalizeIssue(remote, repository, fallbackNumber) {
|
|
4
|
+
const number = Number.isInteger(remote.number) && Number(remote.number) > 0
|
|
5
|
+
? Number(remote.number)
|
|
6
|
+
: fallbackNumber;
|
|
7
|
+
if (!number || !Number.isSafeInteger(number) || remote.pull_request)
|
|
8
|
+
return null;
|
|
9
|
+
return {
|
|
10
|
+
repository,
|
|
11
|
+
number,
|
|
12
|
+
databaseId: Number.isInteger(remote.id) ? Number(remote.id) : null,
|
|
13
|
+
nodeId: remote.node_id || `issue-${number}`,
|
|
14
|
+
url: remote.html_url || `https://github.com/${repository}/issues/${number}`,
|
|
15
|
+
state: String(remote.state || '').toLowerCase() === 'closed' ? 'closed' : 'open',
|
|
16
|
+
title: remote.title || '',
|
|
17
|
+
body: remote.body || '',
|
|
18
|
+
labels: (remote.labels || []).map((label) => typeof label === 'string' ? label : label.name || '').filter(Boolean).sort(),
|
|
19
|
+
assignees: (remote.assignees || []).map((assignee) => assignee.login || '').filter(Boolean).sort(),
|
|
20
|
+
milestone: remote.milestone?.title || null,
|
|
21
|
+
issueType: remote.type?.name || null,
|
|
22
|
+
fields: {}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function fieldKind(value) {
|
|
26
|
+
if (value.__typename === 'IssueFieldSingleSelect' || value.__typename === 'IssueFieldSingleSelectValue')
|
|
27
|
+
return 'single-select';
|
|
28
|
+
if (value.__typename === 'IssueFieldDate' || value.__typename === 'IssueFieldDateValue')
|
|
29
|
+
return 'date';
|
|
30
|
+
if (value.__typename === 'IssueFieldText' || value.__typename === 'IssueFieldTextValue')
|
|
31
|
+
return 'text';
|
|
32
|
+
if (value.__typename === 'IssueFieldNumber' || value.__typename === 'IssueFieldNumberValue')
|
|
33
|
+
return 'number';
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function normalizeFieldSchemas(value) {
|
|
37
|
+
if (!Array.isArray(value))
|
|
38
|
+
return [];
|
|
39
|
+
return value.flatMap((raw) => {
|
|
40
|
+
const item = raw;
|
|
41
|
+
const kind = fieldKind(item);
|
|
42
|
+
return item.id && item.name && kind ? [{
|
|
43
|
+
id: item.id,
|
|
44
|
+
name: item.name,
|
|
45
|
+
kind,
|
|
46
|
+
options: (item.options || []).flatMap((option) => option.id && option.name ? [{ id: option.id, name: option.name }] : [])
|
|
47
|
+
}] : [];
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function normalizeCurrentFields(value) {
|
|
51
|
+
const issue = value?.data?.repository?.issue;
|
|
52
|
+
const type = issue?.issueType?.name ? {
|
|
53
|
+
id: issue.issueType.id || issue.issueType.name,
|
|
54
|
+
name: issue.issueType.name,
|
|
55
|
+
fields: normalizeFieldSchemas(issue.issueType.pinnedFields)
|
|
56
|
+
} : null;
|
|
57
|
+
const values = (issue?.issueFieldValues?.nodes || []).flatMap((raw) => {
|
|
58
|
+
const item = raw;
|
|
59
|
+
const kind = fieldKind(item);
|
|
60
|
+
const value = kind === 'single-select' ? item.name : item.value;
|
|
61
|
+
return item.field?.name && kind && value !== undefined
|
|
62
|
+
? [{ id: item.field.id || item.field.name, name: item.field.name, kind, value: value ?? null }]
|
|
63
|
+
: [];
|
|
64
|
+
});
|
|
65
|
+
return { issueId: issue?.id || null, type, values };
|
|
66
|
+
}
|
|
67
|
+
function graphState(client, repository, issue, cwd) {
|
|
68
|
+
const [owner, name] = repository.split('/');
|
|
69
|
+
if (!owner || !name)
|
|
70
|
+
return null;
|
|
71
|
+
const current = client.json([
|
|
72
|
+
'api', 'graphql', '-f', `query=${ISSUE_FIELDS_QUERY}`, '-F', `owner=${owner}`, '-F', `name=${name}`, '-F', `number=${issue}`
|
|
73
|
+
], { cwd });
|
|
74
|
+
if (!current.ok)
|
|
75
|
+
return null;
|
|
76
|
+
return normalizeCurrentFields(current.value);
|
|
77
|
+
}
|
|
78
|
+
function fetchIssue(client, repository, issue, cwd) {
|
|
79
|
+
return client.json(['api', `repos/${repository}/issues/${issue}`], { cwd });
|
|
80
|
+
}
|
|
81
|
+
function inspectGitHubIssue(client, repository, issue, cwd) {
|
|
82
|
+
const fetched = fetchIssue(client, repository, issue, cwd);
|
|
83
|
+
if (!fetched.ok)
|
|
84
|
+
return fetched;
|
|
85
|
+
const snapshot = normalizeIssue(fetched.value, repository, issue);
|
|
86
|
+
return snapshot
|
|
87
|
+
? { ok: true, value: snapshot }
|
|
88
|
+
: { ok: false, error: { code: 'ISSUE_IDENTITY_INVALID', message: 'Remote resource is not a valid Issue', retryable: false } };
|
|
89
|
+
}
|
|
90
|
+
const CLOSING_PULL_REQUESTS_QUERY = `query($owner:String!,$name:String!,$issue:Int!,$cursor:String){repository(owner:$owner,name:$name){issue(number:$issue){closedByPullRequestsReferences(first:100,after:$cursor){nodes{number id url state title body isDraft headRefName headRefOid headRepository{nameWithOwner} baseRefName baseRefOid baseRepository{nameWithOwner} mergedAt mergeCommit{oid} labels(first:100){nodes{name}} assignees(first:100){nodes{login}} milestone{title}} pageInfo{hasNextPage endCursor}}}}}`;
|
|
91
|
+
function normalizePullRequest(remote, repository) {
|
|
92
|
+
const number = Number(remote.number);
|
|
93
|
+
const headRepository = remote.head?.repo?.full_name;
|
|
94
|
+
const baseRepository = remote.base?.repo?.full_name;
|
|
95
|
+
if (!Number.isInteger(number) || number <= 0 || !remote.node_id || !remote.html_url ||
|
|
96
|
+
!remote.head?.ref || !remote.head.sha || !headRepository || !remote.base?.ref || !baseRepository)
|
|
97
|
+
return null;
|
|
98
|
+
const mergeabilityDetail = remote.mergeable_state?.trim().toLowerCase() || null;
|
|
99
|
+
const mergeability = remote.mergeable === false
|
|
100
|
+
? { state: 'conflicting', detail: mergeabilityDetail }
|
|
101
|
+
: remote.mergeable === true && mergeabilityDetail !== 'dirty'
|
|
102
|
+
? { state: 'mergeable', detail: mergeabilityDetail }
|
|
103
|
+
: { state: 'unknown', detail: mergeabilityDetail };
|
|
104
|
+
return {
|
|
105
|
+
repository,
|
|
106
|
+
number,
|
|
107
|
+
nodeId: remote.node_id,
|
|
108
|
+
url: remote.html_url,
|
|
109
|
+
state: remote.state === 'closed' ? 'closed' : 'open',
|
|
110
|
+
title: remote.title || '',
|
|
111
|
+
body: remote.body || '',
|
|
112
|
+
draft: Boolean(remote.draft),
|
|
113
|
+
head: { repository: headRepository, ref: remote.head.ref, sha: remote.head.sha },
|
|
114
|
+
base: { repository: baseRepository, ref: remote.base.ref, sha: remote.base.sha || '' },
|
|
115
|
+
mergedAt: remote.merged_at || null,
|
|
116
|
+
mergeCommitSha: remote.merge_commit_sha || null,
|
|
117
|
+
labels: (remote.labels || []).map((label) => typeof label === 'string' ? label : label.name || '').filter(Boolean).sort(),
|
|
118
|
+
assignees: (remote.assignees || []).map((assignee) => assignee.login || '').filter(Boolean).sort(),
|
|
119
|
+
milestone: remote.milestone?.title || null,
|
|
120
|
+
mergeability
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function normalizeClosingPullRequest(node, repository) {
|
|
124
|
+
return normalizePullRequest({
|
|
125
|
+
number: node.number,
|
|
126
|
+
node_id: node.id,
|
|
127
|
+
html_url: node.url,
|
|
128
|
+
state: node.state === 'OPEN' ? 'open' : 'closed',
|
|
129
|
+
title: node.title,
|
|
130
|
+
body: node.body,
|
|
131
|
+
draft: node.isDraft,
|
|
132
|
+
head: { ref: node.headRefName, sha: node.headRefOid, repo: node.headRepository ? { full_name: node.headRepository.nameWithOwner } : null },
|
|
133
|
+
base: { ref: node.baseRefName, sha: node.baseRefOid, repo: node.baseRepository ? { full_name: node.baseRepository.nameWithOwner } : null },
|
|
134
|
+
merged_at: node.mergedAt,
|
|
135
|
+
merge_commit_sha: node.mergeCommit?.oid,
|
|
136
|
+
labels: node.labels?.nodes,
|
|
137
|
+
assignees: node.assignees?.nodes,
|
|
138
|
+
milestone: node.milestone
|
|
139
|
+
}, repository);
|
|
140
|
+
}
|
|
141
|
+
function inspectGitHubIssueClosingChangeRequests(client, repository, issueNumber, cwd) {
|
|
142
|
+
const [owner, name] = repository.split('/');
|
|
143
|
+
if (!owner || !name || !Number.isInteger(issueNumber) || issueNumber <= 0)
|
|
144
|
+
return {
|
|
145
|
+
ok: false,
|
|
146
|
+
error: { code: 'PR_IDENTITY_INVALID', message: 'Repository or Issue identity is invalid', retryable: false }
|
|
147
|
+
};
|
|
148
|
+
const candidates = [];
|
|
149
|
+
let cursor = null;
|
|
150
|
+
for (;;) {
|
|
151
|
+
const args = [
|
|
152
|
+
'api', 'graphql', '-f', `query=${CLOSING_PULL_REQUESTS_QUERY}`,
|
|
153
|
+
'-F', `owner=${owner}`, '-F', `name=${name}`, '-F', `issue=${issueNumber}`
|
|
154
|
+
];
|
|
155
|
+
if (cursor)
|
|
156
|
+
args.push('-F', `cursor=${cursor}`);
|
|
157
|
+
const response = client.json(args, { cwd });
|
|
158
|
+
if (!response.ok)
|
|
159
|
+
return response;
|
|
160
|
+
const connection = response.value?.data?.repository?.issue?.closedByPullRequestsReferences;
|
|
161
|
+
if (!connection || !Array.isArray(connection.nodes) || !connection.pageInfo)
|
|
162
|
+
return {
|
|
163
|
+
ok: false,
|
|
164
|
+
error: { code: 'PR_IDENTITY_INVALID', message: 'Closing pull request response is incomplete', retryable: false }
|
|
165
|
+
};
|
|
166
|
+
for (const node of connection.nodes) {
|
|
167
|
+
const normalized = normalizeClosingPullRequest(node, repository);
|
|
168
|
+
if (!normalized)
|
|
169
|
+
return {
|
|
170
|
+
ok: false,
|
|
171
|
+
error: { code: 'PR_IDENTITY_INVALID', message: 'Closing pull request identity is incomplete', retryable: false }
|
|
172
|
+
};
|
|
173
|
+
candidates.push(normalized);
|
|
174
|
+
}
|
|
175
|
+
if (!connection.pageInfo.hasNextPage)
|
|
176
|
+
return { ok: true, value: candidates };
|
|
177
|
+
if (!connection.pageInfo.endCursor || connection.pageInfo.endCursor === cursor)
|
|
178
|
+
return {
|
|
179
|
+
ok: false,
|
|
180
|
+
error: { code: 'PR_IDENTITY_INVALID', message: 'Closing pull request pagination cursor is invalid', retryable: false }
|
|
181
|
+
};
|
|
182
|
+
cursor = connection.pageInfo.endCursor;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function inspectGitHubPullRequest(client, repository, number, cwd) {
|
|
186
|
+
const fetched = client.json(['api', `repos/${repository}/pulls/${number}`], { cwd });
|
|
187
|
+
if (!fetched.ok)
|
|
188
|
+
return fetched;
|
|
189
|
+
const pullRequest = normalizePullRequest(fetched.value, repository);
|
|
190
|
+
return pullRequest
|
|
191
|
+
? { ok: true, value: pullRequest }
|
|
192
|
+
: { ok: false, error: { code: 'PR_IDENTITY_INVALID', message: 'Remote resource is not a valid pull request', retryable: false } };
|
|
193
|
+
}
|
|
194
|
+
function normalizeGitHubChecks(value) {
|
|
195
|
+
if (!Array.isArray(value))
|
|
196
|
+
return [];
|
|
197
|
+
return value.flatMap((raw) => {
|
|
198
|
+
const item = raw;
|
|
199
|
+
const name = String(item.name || item.context || '');
|
|
200
|
+
return name ? [{
|
|
201
|
+
name,
|
|
202
|
+
status: checkStatusBucket(String(item.bucket || item.status || item.conclusion || item.state || '')),
|
|
203
|
+
conclusion: item.conclusion ? String(item.conclusion) : item.state ? String(item.state) : null,
|
|
204
|
+
detailsUrl: item.link ? String(item.link) : item.detailsUrl ? String(item.detailsUrl) : null
|
|
205
|
+
}] : [];
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function inspectGitHubRequiredChecks(client, repository, number, cwd) {
|
|
209
|
+
const inspected = client.json([
|
|
210
|
+
'pr', 'checks', String(number), '--repo', repository,
|
|
211
|
+
'--json', 'name,state,bucket,link,workflow,startedAt,completedAt'
|
|
212
|
+
], { cwd });
|
|
213
|
+
return inspected.ok
|
|
214
|
+
? { ok: true, value: normalizeGitHubChecks(inspected.value) }
|
|
215
|
+
: { ok: false, error: inspected.error };
|
|
216
|
+
}
|
|
217
|
+
function parseRunJobIdentity(detailsUrl) {
|
|
218
|
+
try {
|
|
219
|
+
const url = new URL(detailsUrl);
|
|
220
|
+
if (url.hostname !== 'github.com')
|
|
221
|
+
return null;
|
|
222
|
+
const match = url.pathname.match(/\/actions\/runs\/(\d+)(?:\/job\/(\d+))?/);
|
|
223
|
+
if (!match)
|
|
224
|
+
return null;
|
|
225
|
+
return { runId: Number(match[1]), jobId: match[2] ? Number(match[2]) : null };
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function fetchCheckLogText(client, args, cwd) {
|
|
232
|
+
if (!client.text)
|
|
233
|
+
return { ok: false, error: { code: 'PLATFORM_CLIENT_TEXT_UNAVAILABLE', message: 'Platform client does not support text responses', retryable: false } };
|
|
234
|
+
const fetched = client.text(args, { cwd });
|
|
235
|
+
if (fetched.ok || args[0] !== 'api' || !/response contains terminal escape sequences/i.test(fetched.error.message)) {
|
|
236
|
+
return fetched;
|
|
237
|
+
}
|
|
238
|
+
return client.text([...args, '--allow-escape-sequences'], { cwd });
|
|
239
|
+
}
|
|
240
|
+
export { ISSUE_FIELDS_QUERY, graphState, inspectGitHubIssue, normalizePullRequest, inspectGitHubIssueClosingChangeRequests, inspectGitHubPullRequest, inspectGitHubRequiredChecks, parseRunJobIdentity, fetchCheckLogText };
|
|
241
|
+
//# sourceMappingURL=github-data.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ISSUE_FIELDS_QUERY, graphState, inspectGitHubIssue, inspectGitHubPullRequest, inspectGitHubIssueClosingChangeRequests, inspectGitHubRequiredChecks, parseRunJobIdentity, fetchCheckLogText } from './github-data.js';
|
|
1
2
|
import { execFileSync } from 'node:child_process';
|
|
2
3
|
import fs from 'node:fs';
|
|
3
4
|
import os from 'node:os';
|
|
@@ -5,10 +6,10 @@ import path from 'node:path';
|
|
|
5
6
|
import semver from 'semver';
|
|
6
7
|
import { createGitHubClient, MINIMUM_GITHUB_CLI_VERSION } from './github-client.js';
|
|
7
8
|
import { resourceIdentityNumber, resourceIdentityString } from './resource-identity.js';
|
|
8
|
-
import { syncLabelDelta } from './in-label-sync.js';
|
|
9
|
+
import { extractPullRequestFileNames, syncLabelDelta } from './in-label-sync.js';
|
|
9
10
|
const CURRENT_USER_QUERY = 'query { viewer { login } }';
|
|
10
11
|
const ISSUE_TYPES_QUERY = `query($owner:String!){organization(login:$owner){issueTypes(first:20){nodes{id name pinnedFields{__typename ... on IssueFieldSingleSelect{id name options{id name}} ... on IssueFieldDate{id name} ... on IssueFieldText{id name} ... on IssueFieldNumber{id name}}}}}}`;
|
|
11
|
-
const
|
|
12
|
+
const CLOSING_ISSUES_QUERY = 'query($owner:String!,$name:String!,$number:Int!,$cursor:String){repository(owner:$owner,name:$name){pullRequest(number:$number){closingIssuesReferences(first:100,after:$cursor){nodes{number} pageInfo{hasNextPage endCursor}}}}}';
|
|
12
13
|
function parseGitHubRemote(remote) {
|
|
13
14
|
const trimmed = remote.trim().replace(/\.git$/, '');
|
|
14
15
|
const match = trimmed.match(/^(?:https?:\/\/github\.com\/|ssh:\/\/(?:git@)?github\.com\/|git@github\.com:)([^/\s]+\/[^/\s]+)$/i);
|
|
@@ -289,6 +290,21 @@ function commentSnapshot(value) {
|
|
|
289
290
|
function createReceipt(remoteId) {
|
|
290
291
|
return { ok: true, value: { changed: true, remoteId } };
|
|
291
292
|
}
|
|
293
|
+
function partialFailure(response, value) {
|
|
294
|
+
return { ok: false, error: response.error, value };
|
|
295
|
+
}
|
|
296
|
+
function labelReconciliation(created, updated, removed, skipped) {
|
|
297
|
+
return {
|
|
298
|
+
changed: created.length > 0 || updated.length > 0 || removed.length > 0,
|
|
299
|
+
created,
|
|
300
|
+
updated,
|
|
301
|
+
removed,
|
|
302
|
+
skipped
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function milestoneInitialization(created, skipped) {
|
|
306
|
+
return { changed: created.length > 0, created, skipped };
|
|
307
|
+
}
|
|
292
308
|
function githubResourceToken(identity) {
|
|
293
309
|
return resourceIdentityString(identity) || (identity?.kind === 'number' ? String(identity.value) : null);
|
|
294
310
|
}
|
|
@@ -383,14 +399,27 @@ function createGitHubOperations(client) {
|
|
|
383
399
|
const number = resourceIdentityNumber(target);
|
|
384
400
|
if (!number)
|
|
385
401
|
return invalid('ISSUE_NUMBER_INVALID', 'Issue number must be positive');
|
|
386
|
-
const
|
|
387
|
-
const fetched = module.inspectGitHubIssue(client, repository(context), number, context.workingDirectory);
|
|
402
|
+
const fetched = inspectGitHubIssue(client, repository(context), number, context.workingDirectory);
|
|
388
403
|
if (!fetched.ok)
|
|
389
404
|
return fetched;
|
|
390
|
-
const graph =
|
|
405
|
+
const graph = graphState(client, repository(context), number, context.workingDirectory);
|
|
391
406
|
return { ok: true, value: issueSnapshot(fetched.value, graph || undefined) };
|
|
392
407
|
},
|
|
393
408
|
async create({ context, desired }) {
|
|
409
|
+
let milestone = null;
|
|
410
|
+
if (desired.milestone) {
|
|
411
|
+
const milestones = client.json(['api', '--paginate', '--slurp', `repos/${repository(context)}/milestones?state=open&per_page=100`], { cwd: context.workingDirectory });
|
|
412
|
+
if (!milestones.ok)
|
|
413
|
+
return milestones;
|
|
414
|
+
const values = Array.isArray(milestones.value)
|
|
415
|
+
? milestones.value.flatMap((entry) => Array.isArray(entry) ? entry : [entry])
|
|
416
|
+
: [];
|
|
417
|
+
const selected = values.find((item) => item?.title === desired.milestone);
|
|
418
|
+
if (!Number.isSafeInteger(selected?.number) || selected.number <= 0) {
|
|
419
|
+
return invalid('MILESTONE_IDENTITY_INVALID', 'Milestone title does not resolve to a positive number');
|
|
420
|
+
}
|
|
421
|
+
milestone = selected.number;
|
|
422
|
+
}
|
|
394
423
|
const response = client.json(['api', `repos/${repository(context)}/issues`, '-X', 'POST', '--input', '-'], {
|
|
395
424
|
cwd: context.workingDirectory,
|
|
396
425
|
method: 'POST',
|
|
@@ -399,7 +428,7 @@ function createGitHubOperations(client) {
|
|
|
399
428
|
body: desired.body,
|
|
400
429
|
labels: desired.labels,
|
|
401
430
|
assignees: desired.assignees,
|
|
402
|
-
...(
|
|
431
|
+
...(milestone ? { milestone } : {})
|
|
403
432
|
})
|
|
404
433
|
});
|
|
405
434
|
if (!response.ok)
|
|
@@ -576,18 +605,71 @@ function createGitHubOperations(client) {
|
|
|
576
605
|
const number = resourceIdentityNumber(target);
|
|
577
606
|
if (!number)
|
|
578
607
|
return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
|
|
579
|
-
const
|
|
580
|
-
const fetched = module.inspectGitHubPullRequest(client, repository(context), number, context.workingDirectory);
|
|
608
|
+
const fetched = inspectGitHubPullRequest(client, repository(context), number, context.workingDirectory);
|
|
581
609
|
if (!fetched.ok)
|
|
582
610
|
return fetched;
|
|
583
611
|
return { ok: true, value: changeRequestSnapshot(fetched.value) };
|
|
584
612
|
},
|
|
613
|
+
async listFiles({ context, target }) {
|
|
614
|
+
const number = resourceIdentityNumber(target);
|
|
615
|
+
if (!number)
|
|
616
|
+
return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
|
|
617
|
+
const response = client.json(['api', '--paginate', '--slurp', `repos/${repository(context)}/pulls/${number}/files?per_page=100`], { cwd: context.workingDirectory });
|
|
618
|
+
if (!response.ok)
|
|
619
|
+
return response;
|
|
620
|
+
const files = extractPullRequestFileNames(response.value);
|
|
621
|
+
return files
|
|
622
|
+
? { ok: true, value: files }
|
|
623
|
+
: invalid('IN_LABEL_SYNC_FILES_INVALID', 'Pull request files response is incomplete');
|
|
624
|
+
},
|
|
625
|
+
async listClosingIssues({ context, target }) {
|
|
626
|
+
const number = resourceIdentityNumber(target);
|
|
627
|
+
if (!number)
|
|
628
|
+
return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
|
|
629
|
+
const [owner, name] = repository(context).split('/');
|
|
630
|
+
if (!owner || !name)
|
|
631
|
+
return invalid('IN_LABEL_SYNC_REPOSITORY_INVALID', 'Repository identity is invalid');
|
|
632
|
+
const identities = [];
|
|
633
|
+
let cursor = null;
|
|
634
|
+
for (;;) {
|
|
635
|
+
const args = ['api', 'graphql', '-f', `query=${CLOSING_ISSUES_QUERY}`, '-F', `owner=${owner}`, '-F', `name=${name}`, '-F', `number=${number}`];
|
|
636
|
+
if (cursor)
|
|
637
|
+
args.push('-F', `cursor=${cursor}`);
|
|
638
|
+
const response = client.json(args, { cwd: context.workingDirectory });
|
|
639
|
+
if (!response.ok)
|
|
640
|
+
return response;
|
|
641
|
+
const connection = response.value?.data?.repository?.pullRequest?.closingIssuesReferences;
|
|
642
|
+
if (!connection || !Array.isArray(connection.nodes) || !connection.pageInfo) {
|
|
643
|
+
return invalid('IN_LABEL_SYNC_ASSOCIATION_INVALID', 'Closing Issue response is incomplete');
|
|
644
|
+
}
|
|
645
|
+
for (const node of connection.nodes) {
|
|
646
|
+
const issue = Number(node?.number);
|
|
647
|
+
if (!Number.isSafeInteger(issue) || issue <= 0) {
|
|
648
|
+
return invalid('IN_LABEL_SYNC_ASSOCIATION_INVALID', 'Closing Issue identity is invalid');
|
|
649
|
+
}
|
|
650
|
+
identities.push({ kind: 'number', value: issue });
|
|
651
|
+
}
|
|
652
|
+
if (!connection.pageInfo.hasNextPage) {
|
|
653
|
+
const seen = new Set();
|
|
654
|
+
return { ok: true, value: identities.filter((identity) => {
|
|
655
|
+
const key = `${identity.kind}:${identity.value}`;
|
|
656
|
+
if (seen.has(key))
|
|
657
|
+
return false;
|
|
658
|
+
seen.add(key);
|
|
659
|
+
return true;
|
|
660
|
+
}) };
|
|
661
|
+
}
|
|
662
|
+
if (!connection.pageInfo.endCursor || connection.pageInfo.endCursor === cursor) {
|
|
663
|
+
return invalid('IN_LABEL_SYNC_ASSOCIATION_INVALID', 'Closing Issue pagination cursor is invalid');
|
|
664
|
+
}
|
|
665
|
+
cursor = connection.pageInfo.endCursor;
|
|
666
|
+
}
|
|
667
|
+
},
|
|
585
668
|
async listClosing({ context, issue }) {
|
|
586
669
|
const number = resourceIdentityNumber(issue);
|
|
587
670
|
if (!number)
|
|
588
671
|
return invalid('ISSUE_NUMBER_INVALID', 'Issue number must be positive');
|
|
589
|
-
const
|
|
590
|
-
const fetched = module.inspectGitHubIssueClosingChangeRequests(client, repository(context), number, context.workingDirectory);
|
|
672
|
+
const fetched = inspectGitHubIssueClosingChangeRequests(client, repository(context), number, context.workingDirectory);
|
|
591
673
|
if (!fetched.ok)
|
|
592
674
|
return fetched;
|
|
593
675
|
return { ok: true, value: fetched.value.map(changeRequestSnapshot) };
|
|
@@ -671,8 +753,7 @@ function createGitHubOperations(client) {
|
|
|
671
753
|
const number = resourceIdentityNumber(target);
|
|
672
754
|
if (!number)
|
|
673
755
|
return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
|
|
674
|
-
|
|
675
|
-
return module.resolveGitHubChangeRequestGitEvidence({
|
|
756
|
+
return resolveGitHubChangeRequestGitEvidence({
|
|
676
757
|
cwd: context.workingDirectory,
|
|
677
758
|
repository: repository(context),
|
|
678
759
|
number,
|
|
@@ -686,18 +767,13 @@ function createGitHubOperations(client) {
|
|
|
686
767
|
const number = resourceIdentityNumber(changeRequest);
|
|
687
768
|
if (!number)
|
|
688
769
|
return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
|
|
689
|
-
|
|
690
|
-
const fetched = module.inspectGitHubRequiredChecks(client, repository(context), number, context.workingDirectory);
|
|
691
|
-
if (!fetched.ok)
|
|
692
|
-
return fetched;
|
|
693
|
-
return { ok: true, value: fetched.value.map((check) => ({ name: check.name, status: check.bucket, conclusion: check.conclusion, detailsUrl: check.detailsUrl })) };
|
|
770
|
+
return inspectGitHubRequiredChecks(client, repository(context), number, context.workingDirectory);
|
|
694
771
|
},
|
|
695
772
|
async resolveRun({ context, changeRequest, checkName, detailsUrl }) {
|
|
696
773
|
const number = resourceIdentityNumber(changeRequest);
|
|
697
774
|
if (!number)
|
|
698
775
|
return invalid('PR_NUMBER_INVALID', 'Pull request number must be positive');
|
|
699
|
-
const
|
|
700
|
-
const direct = detailsUrl ? module.parseRunJobIdentity(detailsUrl) : null;
|
|
776
|
+
const direct = detailsUrl ? parseRunJobIdentity(detailsUrl) : null;
|
|
701
777
|
if (direct) {
|
|
702
778
|
const run = client.json(['api', `repos/${repository(context)}/actions/runs/${direct.runId}`], { cwd: context.workingDirectory });
|
|
703
779
|
if (!run.ok)
|
|
@@ -713,11 +789,10 @@ function createGitHubOperations(client) {
|
|
|
713
789
|
: invalid('CHECK_RUN_NOT_FOUND', 'Check run was not found');
|
|
714
790
|
},
|
|
715
791
|
async fetchLogs({ context, runId, jobId }) {
|
|
716
|
-
const module = await import('./pr-checks.js');
|
|
717
792
|
const args = jobId
|
|
718
793
|
? ['api', `repos/${repository(context)}/actions/jobs/${jobId}/logs`]
|
|
719
794
|
: ['run', 'view', runId, '--repo', repository(context), '--log-failed'];
|
|
720
|
-
const fetched =
|
|
795
|
+
const fetched = fetchCheckLogText(client, args, context.workingDirectory);
|
|
721
796
|
if (!fetched.ok)
|
|
722
797
|
return fetched;
|
|
723
798
|
return { ok: true, value: { runId, jobId, text: fetched.value || '' } };
|
|
@@ -798,7 +873,12 @@ function createGitHubOperations(client) {
|
|
|
798
873
|
}
|
|
799
874
|
continue;
|
|
800
875
|
}
|
|
801
|
-
const response = client.json([
|
|
876
|
+
const response = client.json([
|
|
877
|
+
'api', '--method', 'POST', `repos/${repository(context)}/milestones`,
|
|
878
|
+
'-f', `title=${item.title}`,
|
|
879
|
+
'-f', `description=${item.description}`,
|
|
880
|
+
'-f', `state=${item.state}`
|
|
881
|
+
], { cwd: context.workingDirectory });
|
|
802
882
|
if (!response.ok)
|
|
803
883
|
return response;
|
|
804
884
|
created.push(item.title);
|
|
@@ -855,23 +935,165 @@ function createGitHubOperations(client) {
|
|
|
855
935
|
};
|
|
856
936
|
}
|
|
857
937
|
};
|
|
938
|
+
const securityAlerts = {
|
|
939
|
+
async inspect({ context, kind, number }) {
|
|
940
|
+
if (!Number.isSafeInteger(number) || number <= 0)
|
|
941
|
+
return invalid('SECURITY_NUMBER_INVALID', 'Alert number must be a positive integer');
|
|
942
|
+
const suffix = kind === 'dependabot' ? 'dependabot' : kind === 'code-scanning' ? 'code-scanning' : null;
|
|
943
|
+
if (!suffix)
|
|
944
|
+
return invalid('SECURITY_KIND_INVALID', 'Alert kind is invalid');
|
|
945
|
+
const response = client.json(['api', `repos/${repository(context)}/${suffix}/alerts/${number}`], { cwd: context.workingDirectory });
|
|
946
|
+
if (!response.ok)
|
|
947
|
+
return response;
|
|
948
|
+
const data = response.value;
|
|
949
|
+
if (!data || typeof data !== 'object' || Array.isArray(data))
|
|
950
|
+
return invalid('SECURITY_RESPONSE_INVALID', 'The platform returned an invalid security alert');
|
|
951
|
+
const value = {
|
|
952
|
+
kind,
|
|
953
|
+
number,
|
|
954
|
+
state: typeof data.state === 'string' ? data.state : 'invalid',
|
|
955
|
+
data
|
|
956
|
+
};
|
|
957
|
+
return { ok: true, value };
|
|
958
|
+
},
|
|
959
|
+
async dismiss({ context, kind, number, reason, comment }) {
|
|
960
|
+
const suffix = kind === 'dependabot' ? 'dependabot' : kind === 'code-scanning' ? 'code-scanning' : null;
|
|
961
|
+
if (!suffix)
|
|
962
|
+
return invalid('SECURITY_KIND_INVALID', 'Alert kind is invalid');
|
|
963
|
+
if (!Number.isSafeInteger(number) || number <= 0)
|
|
964
|
+
return invalid('SECURITY_NUMBER_INVALID', 'Alert number must be a positive integer');
|
|
965
|
+
const response = client.json(['api', `repos/${repository(context)}/${suffix}/alerts/${number}`, '-X', 'PATCH', '--input', '-'], {
|
|
966
|
+
cwd: context.workingDirectory,
|
|
967
|
+
method: 'PATCH',
|
|
968
|
+
input: JSON.stringify({ state: 'dismissed', dismissed_reason: reason, dismissed_comment: comment })
|
|
969
|
+
});
|
|
970
|
+
if (!response.ok)
|
|
971
|
+
return response;
|
|
972
|
+
return createReceipt(String(response.value?.id || `${kind}:${number}`));
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
const repositoryMetadata = {
|
|
976
|
+
async reconcileLabels({ context, desired, cleanupStaleIn }) {
|
|
977
|
+
const endpoint = `repos/${repository(context)}/labels?per_page=100`;
|
|
978
|
+
const listed = client.json(['api', '--paginate', '--slurp', endpoint], { cwd: context.workingDirectory });
|
|
979
|
+
if (!listed.ok)
|
|
980
|
+
return listed;
|
|
981
|
+
if (!Array.isArray(listed.value))
|
|
982
|
+
return invalid('LABEL_RESPONSE_INVALID', 'The platform returned an invalid label list');
|
|
983
|
+
const values = Array.isArray(listed.value)
|
|
984
|
+
? listed.value.flatMap((entry) => Array.isArray(entry) ? entry : [entry])
|
|
985
|
+
: [];
|
|
986
|
+
if (values.some((entry) => !entry || typeof entry.name !== 'string' || !entry.name)) {
|
|
987
|
+
return invalid('LABEL_RESPONSE_INVALID', 'The platform returned a label without a valid name');
|
|
988
|
+
}
|
|
989
|
+
const current = new Map(values.map((entry) => [String(entry.name), entry]));
|
|
990
|
+
const created = [];
|
|
991
|
+
const updated = [];
|
|
992
|
+
const skipped = [];
|
|
993
|
+
const removed = [];
|
|
994
|
+
for (const label of desired) {
|
|
995
|
+
const existing = current.get(label.name);
|
|
996
|
+
if (!existing) {
|
|
997
|
+
const response = client.json(['api', `repos/${repository(context)}/labels`, '-X', 'POST', '--input', '-'], {
|
|
998
|
+
cwd: context.workingDirectory,
|
|
999
|
+
method: 'POST',
|
|
1000
|
+
input: JSON.stringify({ name: label.name, color: label.color, description: label.description })
|
|
1001
|
+
});
|
|
1002
|
+
if (!response.ok)
|
|
1003
|
+
return partialFailure(response, labelReconciliation(created, updated, removed, skipped));
|
|
1004
|
+
created.push(label.name);
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
const sameColor = typeof existing.color === 'string' && existing.color.toUpperCase() === label.color.toUpperCase();
|
|
1008
|
+
const sameDescription = String(existing.description || '') === label.description;
|
|
1009
|
+
if (sameColor && sameDescription) {
|
|
1010
|
+
skipped.push(label.name);
|
|
1011
|
+
continue;
|
|
1012
|
+
}
|
|
1013
|
+
const response = client.json(['api', `repos/${repository(context)}/labels/${encodeURIComponent(label.name)}`, '-X', 'PATCH', '--input', '-'], {
|
|
1014
|
+
cwd: context.workingDirectory,
|
|
1015
|
+
method: 'PATCH',
|
|
1016
|
+
input: JSON.stringify({ new_name: label.name, color: label.color, description: label.description })
|
|
1017
|
+
});
|
|
1018
|
+
if (!response.ok)
|
|
1019
|
+
return partialFailure(response, labelReconciliation(created, updated, removed, skipped));
|
|
1020
|
+
updated.push(label.name);
|
|
1021
|
+
}
|
|
1022
|
+
const desiredNames = new Set(desired.map((label) => label.name));
|
|
1023
|
+
if (cleanupStaleIn) {
|
|
1024
|
+
for (const name of current.keys()) {
|
|
1025
|
+
if (!name.startsWith('in:') || desiredNames.has(name))
|
|
1026
|
+
continue;
|
|
1027
|
+
const response = client.text(['api', `repos/${repository(context)}/labels/${encodeURIComponent(name)}`, '-X', 'DELETE'], {
|
|
1028
|
+
cwd: context.workingDirectory,
|
|
1029
|
+
method: 'DELETE'
|
|
1030
|
+
});
|
|
1031
|
+
if (!response.ok)
|
|
1032
|
+
return partialFailure(response, labelReconciliation(created, updated, removed, skipped));
|
|
1033
|
+
removed.push(name);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
return {
|
|
1037
|
+
ok: true,
|
|
1038
|
+
value: {
|
|
1039
|
+
changed: created.length > 0 || updated.length > 0 || removed.length > 0,
|
|
1040
|
+
created,
|
|
1041
|
+
updated,
|
|
1042
|
+
removed,
|
|
1043
|
+
skipped
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
},
|
|
1047
|
+
async reconcileMilestones({ context, desired }) {
|
|
1048
|
+
const listed = client.json(['api', '--paginate', '--slurp', `repos/${repository(context)}/milestones?state=all&per_page=100`], { cwd: context.workingDirectory });
|
|
1049
|
+
if (!listed.ok)
|
|
1050
|
+
return listed;
|
|
1051
|
+
if (!Array.isArray(listed.value))
|
|
1052
|
+
return invalid('MILESTONE_RESPONSE_INVALID', 'The platform returned an invalid milestone list');
|
|
1053
|
+
const values = Array.isArray(listed.value)
|
|
1054
|
+
? listed.value.flatMap((entry) => Array.isArray(entry) ? entry : [entry])
|
|
1055
|
+
: [];
|
|
1056
|
+
if (values.some((entry) => !entry || typeof entry.title !== 'string' || !entry.title)) {
|
|
1057
|
+
return invalid('MILESTONE_RESPONSE_INVALID', 'The platform returned a milestone without a valid title');
|
|
1058
|
+
}
|
|
1059
|
+
const existing = new Set(values.map((entry) => String(entry.title)));
|
|
1060
|
+
const created = [];
|
|
1061
|
+
const skipped = [];
|
|
1062
|
+
for (const milestone of desired) {
|
|
1063
|
+
if (existing.has(milestone.title)) {
|
|
1064
|
+
skipped.push(milestone.title);
|
|
1065
|
+
continue;
|
|
1066
|
+
}
|
|
1067
|
+
const response = client.json(['api', `repos/${repository(context)}/milestones`, '-X', 'POST', '--input', '-'], {
|
|
1068
|
+
cwd: context.workingDirectory,
|
|
1069
|
+
method: 'POST',
|
|
1070
|
+
input: JSON.stringify({ title: milestone.title, description: milestone.description, state: milestone.state })
|
|
1071
|
+
});
|
|
1072
|
+
if (!response.ok)
|
|
1073
|
+
return partialFailure(response, milestoneInitialization(created, skipped));
|
|
1074
|
+
existing.add(milestone.title);
|
|
1075
|
+
created.push(milestone.title);
|
|
1076
|
+
}
|
|
1077
|
+
return { ok: true, value: { changed: created.length > 0, created, skipped } };
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
858
1080
|
const verification = {
|
|
859
1081
|
async fetchRemoteFacts(input) {
|
|
860
1082
|
const issue = input.issue && issues.inspect
|
|
861
1083
|
? await issues.inspect({ context: input.context, target: input.issue })
|
|
862
1084
|
: { ok: true, value: null };
|
|
863
1085
|
if (!issue.ok)
|
|
864
|
-
return issue;
|
|
1086
|
+
return { ok: false, error: issue.error };
|
|
865
1087
|
const commentFacts = input.includeComments && input.issue && comments.list
|
|
866
1088
|
? await comments.list({ context: input.context, parent: input.issue })
|
|
867
1089
|
: { ok: true, value: [] };
|
|
868
1090
|
if (!commentFacts.ok)
|
|
869
|
-
return commentFacts;
|
|
1091
|
+
return { ok: false, error: commentFacts.error };
|
|
870
1092
|
const changeRequest = input.changeRequest && changeRequests.inspect
|
|
871
1093
|
? await changeRequests.inspect({ context: input.context, target: input.changeRequest })
|
|
872
1094
|
: { ok: true, value: null };
|
|
873
1095
|
if (!changeRequest.ok)
|
|
874
|
-
return changeRequest;
|
|
1096
|
+
return { ok: false, error: changeRequest.error };
|
|
875
1097
|
return {
|
|
876
1098
|
ok: true,
|
|
877
1099
|
value: {
|
|
@@ -884,7 +1106,7 @@ function createGitHubOperations(client) {
|
|
|
884
1106
|
};
|
|
885
1107
|
}
|
|
886
1108
|
};
|
|
887
|
-
return { issues, comments, changeRequests, checks, reviews, releases, verification };
|
|
1109
|
+
return { issues, comments, changeRequests, checks, reviews, releases, securityAlerts, repositoryMetadata, verification };
|
|
888
1110
|
}
|
|
889
1111
|
function createGitHubProvider(input, client = createGitHubClient()) {
|
|
890
1112
|
return {
|