@fitlab-ai/agent-infra 0.9.12 → 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/README.md +11 -11
- package/README.zh-CN.md +11 -11
- package/bin/cli.ts +26 -9
- package/dist/bin/cli.js +173 -157
- package/dist/bin/internal-cli.js +66 -40
- package/dist/lib/agent-client.js +5 -0
- package/dist/lib/agent-clients/next-steps.js +6 -1
- package/dist/lib/decide.js +3 -3
- 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 +19 -7
- package/dist/lib/internal/platform-comment.js +25 -13
- package/dist/lib/internal/platform-context.js +6 -3
- package/dist/lib/internal/platform-issue.js +20 -13
- package/dist/lib/internal/platform-metadata.js +88 -0
- package/dist/lib/internal/platform-pr-review.js +26 -13
- package/dist/lib/internal/platform-pr.js +84 -31
- package/dist/lib/internal/platform-release-notes.js +9 -6
- package/dist/lib/internal/platform-security.js +93 -0
- package/dist/lib/internal/pr-review-grade.js +25 -12
- package/dist/lib/internal/release-workflow.js +23 -9
- package/dist/lib/internal/sandbox-control.js +50 -7
- package/dist/lib/internal/task-activity.js +16 -7
- package/dist/lib/internal/task-artifact.js +235 -24
- package/dist/lib/internal/task-context.js +4 -1
- package/dist/lib/internal/task-create.js +50 -17
- package/dist/lib/internal/task-delivery.js +4 -1
- package/dist/lib/internal/task-event.js +10 -4
- package/dist/lib/internal/task-finalization.js +6 -3
- package/dist/lib/internal/task-invalidation.js +63 -0
- package/dist/lib/internal/task-ledger.js +20 -6
- package/dist/lib/internal/task-lifecycle.js +6 -3
- 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 +14 -7
- package/dist/lib/internal/task-qualification.js +90 -0
- package/dist/lib/internal/task-review.js +7 -4
- 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 +11 -7
- package/dist/lib/internal/task-warning.js +11 -4
- package/dist/lib/platform/adapters.js +1 -3
- package/dist/lib/platform/change-request-git-evidence.js +27 -7
- package/dist/lib/platform/comment-safety.js +226 -0
- package/dist/lib/platform/completion-backfill.js +6 -5
- package/dist/lib/platform/context.js +70 -130
- package/dist/lib/platform/github-client.js +1 -1
- package/dist/lib/platform/github-provider.js +1130 -0
- package/dist/lib/platform/in-label-sync.js +143 -0
- package/dist/lib/platform/issue-comments.js +237 -72
- package/dist/lib/platform/issues.js +335 -189
- package/dist/lib/platform/metadata-labels.js +6 -2
- package/dist/lib/platform/none-provider.js +28 -0
- package/dist/lib/platform/pr-change-report.js +545 -0
- package/dist/lib/platform/pr-checks.js +119 -104
- package/dist/lib/platform/pr-review.js +88 -72
- package/dist/lib/platform/pr-summary.js +541 -50
- package/dist/lib/platform/provider-bridge.js +45 -0
- package/dist/lib/platform/provider-contract.d.ts +553 -0
- package/dist/lib/platform/provider-contract.js +99 -0
- package/dist/lib/platform/provider-loader.js +251 -0
- package/dist/lib/platform/provider-validation.js +577 -0
- package/dist/lib/platform/pull-request-metadata.js +8 -6
- package/dist/lib/platform/pull-requests.js +734 -543
- package/dist/lib/platform/release-notes.js +78 -55
- package/dist/lib/platform/releases.js +79 -50
- package/dist/lib/platform/repository-metadata.js +377 -0
- package/dist/lib/platform/resource-identity.d.ts +26 -0
- package/dist/lib/platform/resource-identity.js +92 -0
- package/dist/lib/platform/security-alerts.js +155 -0
- package/dist/lib/platform/task-identities.js +31 -0
- package/dist/lib/platform/verification-required.js +11 -12
- package/dist/lib/platform/verification-sync.js +129 -248
- package/dist/lib/pr-review/evidence-grading.js +19 -6
- package/dist/lib/process-data/index.js +7 -0
- package/dist/lib/run/index.js +68 -23
- 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 +174 -19
- 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 +151 -16
- 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/protocol.js +77 -0
- package/dist/lib/sandbox/control/server.js +677 -34
- package/dist/lib/sandbox/control/state.js +209 -4
- 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/server/protocol.js +38 -1
- package/dist/lib/task/activity-log.js +8 -1
- package/dist/lib/task/artifact-lifecycle.js +75 -18
- 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 +310 -0
- package/dist/lib/task/commands/status.js +32 -0
- package/dist/lib/task/commit-operation.js +12 -1
- package/dist/lib/task/control-authority.js +12 -5
- package/dist/lib/task/create-service.js +111 -12
- package/dist/lib/task/create.js +25 -0
- package/dist/lib/task/current-contract.js +5 -1
- package/dist/lib/task/decision-details.js +1 -1
- package/dist/lib/task/events.js +416 -17
- package/dist/lib/task/finalization.js +37 -13
- package/dist/lib/task/human-override.js +58 -36
- package/dist/lib/task/index.js +11 -3
- package/dist/lib/task/invalidation-command.js +86 -0
- package/dist/lib/task/invalidation.js +260 -0
- package/dist/lib/task/ledger-intents.js +37 -0
- package/dist/lib/task/local-artifact-finalization.js +299 -0
- package/dist/lib/task/orchestration.js +240 -144
- package/dist/lib/task/pr-delivery-fact.js +102 -101
- 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/review-fingerprint.js +24 -2
- package/dist/lib/task/rework-intent.js +138 -0
- package/dist/lib/task/sections.js +6 -4
- package/dist/lib/task/skill-scope.js +23 -0
- package/dist/lib/task/task-execution-lock.js +27 -17
- package/dist/lib/task/verification-config.js +11 -0
- package/dist/lib/task/verification-engine.js +93 -16
- package/dist/lib/task/verification.js +3 -3
- package/dist/lib/task/workflow-warning-intents.js +1 -1
- package/dist/lib/task/write.js +11 -0
- package/dist/lib/version.js +11 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +9 -0
- package/lib/agent-clients/next-steps.ts +6 -1
- package/lib/decide.ts +3 -3
- package/lib/init.ts +1 -1
- 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 +14 -6
- package/lib/internal/platform-comment.ts +20 -12
- package/lib/internal/platform-context.ts +5 -3
- package/lib/internal/platform-issue.ts +17 -11
- package/lib/internal/platform-metadata.ts +70 -0
- package/lib/internal/platform-pr-review.ts +23 -12
- package/lib/internal/platform-pr.ts +65 -27
- package/lib/internal/platform-release-notes.ts +8 -6
- package/lib/internal/platform-security.ts +83 -0
- package/lib/internal/pr-review-grade.ts +20 -11
- package/lib/internal/release-workflow.ts +21 -9
- package/lib/internal/sandbox-control.ts +44 -6
- package/lib/internal/task-activity.ts +15 -7
- package/lib/internal/task-artifact.ts +204 -22
- package/lib/internal/task-context.ts +3 -1
- package/lib/internal/task-create.ts +78 -17
- package/lib/internal/task-delivery.ts +3 -1
- package/lib/internal/task-event.ts +9 -4
- package/lib/internal/task-finalization.ts +6 -4
- package/lib/internal/task-invalidation.ts +41 -0
- package/lib/internal/task-ledger.ts +21 -8
- package/lib/internal/task-lifecycle.ts +5 -3
- package/lib/internal/task-operation-registry.ts +482 -0
- package/lib/internal/task-orchestration.ts +12 -0
- package/lib/internal/task-override.ts +15 -9
- package/lib/internal/task-qualification.ts +61 -0
- package/lib/internal/task-review.ts +6 -4
- 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 +10 -7
- package/lib/internal/task-warning.ts +10 -4
- package/lib/platform/adapters.ts +3 -2
- package/lib/platform/change-request-git-evidence.ts +36 -9
- package/lib/platform/comment-safety.ts +250 -0
- package/lib/platform/completion-backfill.ts +9 -8
- package/lib/platform/context.ts +97 -134
- package/lib/platform/github-client.ts +2 -2
- package/lib/platform/github-provider.ts +1132 -0
- package/lib/platform/in-label-sync.ts +208 -0
- package/lib/platform/issue-comments.ts +255 -80
- package/lib/platform/issues.ts +344 -174
- package/lib/platform/metadata-labels.ts +5 -2
- package/lib/platform/none-provider.ts +35 -0
- package/lib/platform/pr-change-report.ts +639 -0
- package/lib/platform/pr-checks.ts +126 -106
- package/lib/platform/pr-review.ts +88 -85
- package/lib/platform/pr-summary.ts +581 -53
- package/lib/platform/provider-bridge.ts +82 -0
- package/lib/platform/provider-contract.ts +611 -0
- package/lib/platform/provider-loader.ts +307 -0
- package/lib/platform/provider-validation.ts +611 -0
- package/lib/platform/pull-request-metadata.ts +10 -7
- package/lib/platform/pull-requests.ts +781 -550
- package/lib/platform/release-notes.ts +76 -59
- package/lib/platform/releases.ts +77 -43
- package/lib/platform/repository-metadata.ts +453 -0
- package/lib/platform/resource-identity.ts +121 -0
- package/lib/platform/security-alerts.ts +191 -0
- package/lib/platform/task-identities.ts +40 -0
- package/lib/platform/types.ts +4 -2
- package/lib/platform/verification-required.ts +11 -13
- package/lib/platform/verification-sync.ts +128 -304
- package/lib/pr-review/evidence-grading.ts +25 -8
- package/lib/process-data/index.ts +7 -0
- package/lib/run/index.ts +62 -22
- 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 +203 -19
- package/lib/sandbox/control/completed-reentry.ts +98 -0
- package/lib/sandbox/control/container-identity.ts +27 -43
- package/lib/sandbox/control/executor.ts +180 -15
- package/lib/sandbox/control/lifecycle.ts +629 -17
- package/lib/sandbox/control/native-file-lock.ts +209 -0
- package/lib/sandbox/control/protocol.ts +118 -2
- package/lib/sandbox/control/server.ts +724 -34
- package/lib/sandbox/control/state.ts +257 -4
- 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/server/protocol.ts +36 -1
- package/lib/task/activity-log.ts +8 -0
- package/lib/task/artifact-lifecycle.ts +70 -22
- 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 +331 -0
- package/lib/task/commands/status.ts +38 -0
- package/lib/task/commit-operation.ts +12 -1
- package/lib/task/control-authority.ts +22 -9
- package/lib/task/create-service.ts +139 -14
- package/lib/task/create.ts +27 -0
- package/lib/task/current-contract.ts +6 -1
- package/lib/task/decision-details.ts +6 -2
- package/lib/task/events.ts +392 -16
- package/lib/task/finalization.ts +50 -14
- package/lib/task/human-override.ts +70 -46
- package/lib/task/index.ts +16 -3
- package/lib/task/invalidation-command.ts +86 -0
- package/lib/task/invalidation.ts +332 -0
- package/lib/task/ledger-intents.ts +35 -1
- package/lib/task/local-artifact-finalization.ts +432 -0
- package/lib/task/orchestration.ts +223 -133
- package/lib/task/pr-delivery-fact.ts +131 -148
- 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/review-fingerprint.ts +23 -2
- package/lib/task/rework-intent.ts +165 -0
- package/lib/task/sections.ts +6 -4
- package/lib/task/skill-scope.ts +24 -0
- package/lib/task/task-execution-lock.ts +23 -14
- package/lib/task/verification-config.ts +12 -0
- package/lib/task/verification-engine.ts +103 -17
- package/lib/task/verification.ts +4 -4
- package/lib/task/workflow-warning-intents.ts +1 -1
- package/lib/task/write.ts +19 -0
- package/lib/update.ts +1 -1
- package/lib/version.ts +15 -1
- package/package.json +12 -1
- package/templates/.agents/rules/README.en.md +3 -1
- package/templates/.agents/rules/README.zh-CN.md +3 -1
- 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/issue-pr-commands.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +2 -0
- package/templates/.agents/rules/issue-sync.zh-CN.md +2 -0
- package/templates/.agents/rules/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 +13 -2
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +13 -2
- package/templates/.agents/rules/pr-sync.en.md +10 -4
- package/templates/.agents/rules/pr-sync.zh-CN.md +17 -4
- package/templates/.agents/rules/security-alerts.en.md +8 -8
- package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
- package/templates/.agents/rules/task-short-id.en.md +1 -4
- package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
- package/templates/.agents/skills/analyze-task/SKILL.en.md +28 -5
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +29 -5
- 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/check-task/SKILL.en.md +16 -37
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
- 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 +41 -9
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +43 -11
- package/templates/.agents/skills/code-task/config/verify.en.json +6 -14
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +6 -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/commit/reference/issue-metadata-sync.en.md +2 -0
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +3 -3
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +3 -3
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +10 -4
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +10 -4
- 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-manual-validation/reference/summary-update.en.md +4 -3
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +4 -3
- package/templates/.agents/skills/complete-task/SKILL.en.md +26 -21
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +25 -21
- package/templates/.agents/skills/create-pr/SKILL.en.md +7 -6
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +7 -7
- package/templates/.agents/skills/create-pr/config/verify.json +1 -0
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
- package/templates/.agents/skills/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 +27 -4
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +26 -4
- 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 +17 -4
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +17 -4
- 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 +18 -5
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +18 -5
- 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 +17 -4
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +17 -4
- 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 +9 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +9 -3
- 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/skills/watch-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
- package/templates/.agents/templates/task.en.md +24 -1
- package/templates/.agents/templates/task.zh-CN.md +24 -1
- package/templates/.github/workflows/pr-label.yml +7 -26
- 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
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { parseResourceIdentity } from './resource-identity.js';
|
|
2
|
+
import { isLegacyCompatibilityEnabled, legacyCompatibilityError, VERSION } from '../version.js';
|
|
3
|
+
import { parse as parseYaml } from 'yaml';
|
|
4
|
+
function taskIssueIdentity(frontmatter, _declaration, runtimeVersion = VERSION) {
|
|
5
|
+
const serialized = frontmatter.platform_issue_identity;
|
|
6
|
+
if (typeof serialized === 'string' && serialized.trim()) {
|
|
7
|
+
try {
|
|
8
|
+
const decoded = parseYaml(serialized);
|
|
9
|
+
return parseResourceIdentity(JSON.parse(typeof decoded === 'string' ? decoded : serialized), 'platform_issue_identity');
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const legacy = frontmatter.issue_number;
|
|
16
|
+
const number = typeof legacy === 'number' ? legacy : typeof legacy === 'string' && /^[1-9]\d*$/u.test(legacy) ? Number(legacy) : NaN;
|
|
17
|
+
// TODO(compat): Remove the numeric issue_number fallback before the first stable v1.0.0 release.
|
|
18
|
+
if (Number.isSafeInteger(number) && number > 0 && !isLegacyCompatibilityEnabled(runtimeVersion)) {
|
|
19
|
+
throw legacyCompatibilityError('issue_number', runtimeVersion);
|
|
20
|
+
}
|
|
21
|
+
return Number.isSafeInteger(number) && number > 0 ? { kind: 'number', value: number } : null;
|
|
22
|
+
}
|
|
23
|
+
function taskIssueIdentityError(error) {
|
|
24
|
+
const value = error && typeof error === 'object' ? error : {};
|
|
25
|
+
return {
|
|
26
|
+
code: typeof value.code === 'string' ? value.code : 'PLATFORM_IDENTITY_INVALID',
|
|
27
|
+
message: error instanceof Error ? error.message : String(error)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export { taskIssueIdentity, taskIssueIdentityError };
|
|
31
|
+
//# sourceMappingURL=task-identities.js.map
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { execFileSync } from "node:child_process";
|
|
4
|
-
import { hasPlatformCapability } from "./adapters.js";
|
|
5
4
|
import { inspectRequiredChecks } from "./pr-checks.js";
|
|
6
|
-
import {
|
|
5
|
+
import { resolvePlatformProviderContext } from "./context.js";
|
|
7
6
|
import { resolveReviewedHeadRelation } from "./merged-pr-equivalence.js";
|
|
8
7
|
import { readPrDeliveryFact } from "../task/pr-delivery-fact.js";
|
|
8
|
+
import { resourceIdentityNumber } from "./resource-identity.js";
|
|
9
9
|
const CHECK_TYPE = "required-checks";
|
|
10
10
|
const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
|
|
11
|
-
function validPrNumber(value) {
|
|
12
|
-
const parsed = Number(value);
|
|
13
|
-
return Number.isInteger(parsed) && parsed > 0;
|
|
14
|
-
}
|
|
15
11
|
function readPrFlow(repoRoot) {
|
|
16
12
|
try {
|
|
17
13
|
const config = JSON.parse(fs.readFileSync(path.join(repoRoot, ".agents", ".airc.json"), "utf8"));
|
|
@@ -36,8 +32,9 @@ export function evaluateRequiredChecks(context, shared) {
|
|
|
36
32
|
return shared.failResult(CHECK_TYPE, factRead.error.message, "check_failed");
|
|
37
33
|
}
|
|
38
34
|
const fact = factRead.status === "valid" ? factRead.fact : null;
|
|
39
|
-
const
|
|
40
|
-
|
|
35
|
+
const prIdentity = fact?.state === "bound" ? fact.identity.resource : null;
|
|
36
|
+
const prNumber = resourceIdentityNumber(prIdentity);
|
|
37
|
+
if (prFlow === "disabled" || fact?.state === "skipped" || !prIdentity) {
|
|
41
38
|
return shared.passResult(CHECK_TYPE, "Skipped: required checks are not applicable to this task");
|
|
42
39
|
}
|
|
43
40
|
const reviewedHead = String(metadata.last_reviewed_commit || "");
|
|
@@ -80,7 +77,7 @@ export function evaluateRequiredChecks(context, shared) {
|
|
|
80
77
|
}
|
|
81
78
|
return shared.failResult(CHECK_TYPE, inspection.error?.message || `Required checks are ${state || "unavailable"}`, "check_failed");
|
|
82
79
|
}
|
|
83
|
-
export function check({ taskDir }, shared) {
|
|
80
|
+
export async function check({ taskDir }, shared) {
|
|
84
81
|
const task = shared.loadTask(taskDir);
|
|
85
82
|
if (!task.ok)
|
|
86
83
|
return shared.failResult(CHECK_TYPE, task.message);
|
|
@@ -92,14 +89,16 @@ export function check({ taskDir }, shared) {
|
|
|
92
89
|
if (prFlow === "disabled" || (factRead.status === "valid" && factRead.fact.state === "skipped") || !bound) {
|
|
93
90
|
return evaluateRequiredChecks({ metadata: task.metadata, localHead: null, inspection: null, prFlow }, shared);
|
|
94
91
|
}
|
|
95
|
-
const
|
|
96
|
-
|
|
92
|
+
const loaded = await resolvePlatformProviderContext({ cwd: shared.repoRoot });
|
|
93
|
+
const platform = loaded.ok ? loaded.value.context : loaded.context;
|
|
94
|
+
const supportsChecks = loaded.ok && Boolean(loaded.value.provider.checks?.inspectRequired);
|
|
95
|
+
if (!supportsChecks) {
|
|
97
96
|
return shared.blockedResult(CHECK_TYPE, `Platform '${platform.platform.type || "none"}' does not provide required-checks inspection`, "dependency_error");
|
|
98
97
|
}
|
|
99
98
|
const localHead = readHead(shared.repoRoot);
|
|
100
99
|
if (!localHead)
|
|
101
100
|
return evaluateRequiredChecks({ metadata: task.metadata, localHead, inspection: null, prFlow }, shared);
|
|
102
|
-
const inspection = inspectRequiredChecks(task.metadata.id, { cwd: shared.repoRoot });
|
|
101
|
+
const inspection = await inspectRequiredChecks(task.metadata.id, { cwd: shared.repoRoot });
|
|
103
102
|
return evaluateRequiredChecks({
|
|
104
103
|
metadata: task.metadata,
|
|
105
104
|
localHead,
|
|
@@ -2,14 +2,14 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { execFileSync } from "node:child_process";
|
|
5
|
-
import {
|
|
6
|
-
import { resolvePlatformContext } from "./context.js";
|
|
5
|
+
import { resolvePlatformProviderContext } from "./context.js";
|
|
7
6
|
import { hasCheckedRequirement, resolveRequirementSection } from "./issue-metadata.js";
|
|
8
|
-
import {
|
|
9
|
-
import { listRemoteComments } from "./issue-comments.js";
|
|
7
|
+
import { requirementSectionAnchors } from "./issues.js";
|
|
10
8
|
import { taskTypeLabel } from "./metadata-labels.js";
|
|
11
|
-
import {
|
|
9
|
+
import { planInLabelUpdate, validateInLabelMapping } from "./in-label-sync.js";
|
|
12
10
|
import { readPrDeliveryFact } from "../task/pr-delivery-fact.js";
|
|
11
|
+
import { providerError, providerOperationContext, resourceIdentityNumber, unsupportedProviderOperation } from "./provider-bridge.js";
|
|
12
|
+
import { taskIssueIdentity } from "./task-identities.js";
|
|
13
13
|
const CHECK_TYPE = "platform-sync";
|
|
14
14
|
const VERSION_LINE_REGEX = /^[0-9]+\.[0-9]+\.x$/;
|
|
15
15
|
const FRONTMATTER_FIELD_MAP = {
|
|
@@ -26,7 +26,6 @@ const OPTION_LOCALIZATION = {
|
|
|
26
26
|
};
|
|
27
27
|
let activeShared = null;
|
|
28
28
|
let repoRoot = "";
|
|
29
|
-
const githubClient = createGitHubClient();
|
|
30
29
|
export function getDefaults() {
|
|
31
30
|
return {
|
|
32
31
|
statusLabels: {
|
|
@@ -79,20 +78,14 @@ function blockedResult(...args) {
|
|
|
79
78
|
function safeStat(...args) {
|
|
80
79
|
return getShared().safeStat(...args);
|
|
81
80
|
}
|
|
82
|
-
function
|
|
83
|
-
return getShared().parseIssueNumber(...args);
|
|
84
|
-
}
|
|
85
|
-
function parsePrNumber(...args) {
|
|
86
|
-
return getShared().parsePrNumber(...args);
|
|
87
|
-
}
|
|
88
|
-
export function check({ taskDir, config, artifactFile }, shared) {
|
|
81
|
+
export async function check({ taskDir, config, artifactFile }, shared) {
|
|
89
82
|
activeShared = shared;
|
|
90
83
|
repoRoot = shared.repoRoot;
|
|
91
|
-
const context = buildSyncContext({ taskDir, config, artifactFile });
|
|
84
|
+
const context = await buildSyncContext({ taskDir, config, artifactFile });
|
|
92
85
|
if (context.earlyReturn) {
|
|
93
86
|
return context.earlyReturn;
|
|
94
87
|
}
|
|
95
|
-
const remoteData = fetchRemoteData(context);
|
|
88
|
+
const remoteData = await fetchRemoteData(context);
|
|
96
89
|
if (remoteData.earlyReturn) {
|
|
97
90
|
return remoteData.earlyReturn;
|
|
98
91
|
}
|
|
@@ -120,29 +113,32 @@ export function check({ taskDir, config, artifactFile }, shared) {
|
|
|
120
113
|
return result;
|
|
121
114
|
}
|
|
122
115
|
}
|
|
123
|
-
return passResult(CHECK_TYPE, `
|
|
116
|
+
return passResult(CHECK_TYPE, `Platform sync checks passed for Issue ${context.issueNumber || "identity"}`);
|
|
124
117
|
}
|
|
125
|
-
function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
118
|
+
async function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
126
119
|
const task = loadTask(taskDir);
|
|
127
120
|
if (!task.ok) {
|
|
128
121
|
return { earlyReturn: failResult(CHECK_TYPE, task.message) };
|
|
129
122
|
}
|
|
130
|
-
const
|
|
123
|
+
const issueIdentity = taskIssueIdentity(task.metadata);
|
|
124
|
+
const issueNumber = resourceIdentityNumber(issueIdentity);
|
|
131
125
|
const fact = readPrDeliveryFact(task.metadata);
|
|
132
126
|
if (fact.status === "invalid") {
|
|
133
127
|
return { earlyReturn: failResult(CHECK_TYPE, fact.error.message, "check_failed") };
|
|
134
128
|
}
|
|
135
|
-
const
|
|
136
|
-
|
|
129
|
+
const prIdentity = fact.status === "valid" && fact.fact.state === "bound" ? fact.fact.identity.resource : null;
|
|
130
|
+
const prNumber = resourceIdentityNumber(prIdentity);
|
|
131
|
+
if (config.when === "issue_number_exists" && !issueIdentity) {
|
|
137
132
|
return { earlyReturn: passResult(CHECK_TYPE, "Skipped: task has no issue_number") };
|
|
138
133
|
}
|
|
139
|
-
if (config.when === "pr_fact_bound" && !
|
|
134
|
+
if (config.when === "pr_fact_bound" && !prIdentity) {
|
|
140
135
|
return { earlyReturn: passResult(CHECK_TYPE, "Skipped: task has no verified bound pull request") };
|
|
141
136
|
}
|
|
142
|
-
if (!
|
|
137
|
+
if (!issueIdentity) {
|
|
143
138
|
return { earlyReturn: passResult(CHECK_TYPE, "Skipped: platform-sync not required for this task") };
|
|
144
139
|
}
|
|
145
|
-
const
|
|
140
|
+
const loaded = await resolvePlatformProviderContext({ cwd: repoRoot });
|
|
141
|
+
const platformContext = loaded.ok ? loaded.value.context : loaded.context;
|
|
146
142
|
if (platformContext.status === "failed") {
|
|
147
143
|
return { earlyReturn: failResult(CHECK_TYPE, platformContext.error?.message || "Platform context failed", "check_failed") };
|
|
148
144
|
}
|
|
@@ -155,7 +151,6 @@ function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
|
155
151
|
}
|
|
156
152
|
return { earlyReturn: passResult(CHECK_TYPE, `Skipped: ${platformContext.error?.message || "platform unavailable"}`) };
|
|
157
153
|
}
|
|
158
|
-
const repoOwnerType = detectRepoOwnerType(platformContext.platform.repository, taskDir);
|
|
159
154
|
const expectedValues = resolveExpectedValues(config);
|
|
160
155
|
if (!expectedValues.ok) {
|
|
161
156
|
return { earlyReturn: failResult(CHECK_TYPE, expectedValues.message, "check_failed") };
|
|
@@ -173,15 +168,19 @@ function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
|
173
168
|
config,
|
|
174
169
|
artifactFile,
|
|
175
170
|
artifactPath,
|
|
171
|
+
issueIdentity,
|
|
172
|
+
prIdentity,
|
|
176
173
|
issueNumber,
|
|
177
174
|
prNumber,
|
|
178
|
-
|
|
179
|
-
repoOwnerType,
|
|
175
|
+
repoOwnerType: String(loaded.ok ? loaded.value.snapshot.metadata?.ownerType || "unknown" : "unknown"),
|
|
180
176
|
hasTriage: platformContext.capabilities.triage,
|
|
181
177
|
hasPush: platformContext.capabilities.push,
|
|
182
178
|
expectedStatusLabel: expectedValues.statusLabel,
|
|
183
179
|
marker,
|
|
184
|
-
prMarker
|
|
180
|
+
prMarker,
|
|
181
|
+
provider: loaded.ok ? loaded.value.provider : null,
|
|
182
|
+
providerType: loaded.ok ? loaded.value.providerType : null,
|
|
183
|
+
loadedContext: loaded.ok ? loaded.value : null
|
|
185
184
|
};
|
|
186
185
|
}
|
|
187
186
|
function resolveExpectedValues(config) {
|
|
@@ -230,139 +229,93 @@ function resolveDefaultValue({ collection, key, value, configKey }) {
|
|
|
230
229
|
}
|
|
231
230
|
return { ok: true, value: resolvedValue };
|
|
232
231
|
}
|
|
233
|
-
function fetchRemoteData(context) {
|
|
234
|
-
const
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
:
|
|
246
|
-
|
|
247
|
-
type: sharedIssue.error.retryable ? "network_error" : "check_failed",
|
|
248
|
-
message: sharedIssue.error.message
|
|
249
|
-
};
|
|
250
|
-
if (!issueResult.ok) {
|
|
232
|
+
async function fetchRemoteData(context) {
|
|
233
|
+
const provider = context.provider;
|
|
234
|
+
const operationContext = providerOperationContext(context.loadedContext, context.taskDir);
|
|
235
|
+
const facts = provider?.verification?.fetchRemoteFacts
|
|
236
|
+
? await provider.verification.fetchRemoteFacts({
|
|
237
|
+
context: operationContext,
|
|
238
|
+
taskId: context.task?.metadata?.id || context.task?.id || "",
|
|
239
|
+
...(context.issueIdentity ? { issue: context.issueIdentity } : {}),
|
|
240
|
+
...(context.prIdentity ? { changeRequest: context.prIdentity } : {}),
|
|
241
|
+
includeComments: shouldFetchComments(context.config),
|
|
242
|
+
includeFields: Boolean(context.config.verify_issue_fields)
|
|
243
|
+
})
|
|
244
|
+
: unsupportedProviderOperation(provider, "verification.fetchRemoteFacts");
|
|
245
|
+
if (!facts.ok) {
|
|
251
246
|
return {
|
|
252
|
-
earlyReturn:
|
|
253
|
-
?
|
|
254
|
-
:
|
|
247
|
+
earlyReturn: facts.error.retryable
|
|
248
|
+
? blockedResult(CHECK_TYPE, providerError(facts.error, "PLATFORM_PROVIDER_OPERATION_FAILED").message, "network_error")
|
|
249
|
+
: failResult(CHECK_TYPE, providerError(facts.error, "PLATFORM_PROVIDER_OPERATION_FAILED").message, "check_failed")
|
|
255
250
|
};
|
|
256
251
|
}
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (shouldFetchComments(context.config)) {
|
|
265
|
-
const commentsResult = withRetry(() => ghPaginatedJson([
|
|
266
|
-
"api",
|
|
267
|
-
"--paginate",
|
|
268
|
-
"--slurp",
|
|
269
|
-
`repos/${context.upstreamRepo}/issues/${context.issueNumber}/comments?per_page=100`
|
|
270
|
-
], context.taskDir));
|
|
271
|
-
if (!commentsResult.ok) {
|
|
272
|
-
return {
|
|
273
|
-
earlyReturn: commentsResult.type === "check_failed"
|
|
274
|
-
? failResult(CHECK_TYPE, commentsResult.message, commentsResult.type)
|
|
275
|
-
: blockedResult(CHECK_TYPE, commentsResult.message, commentsResult.type)
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
comments = flattenComments(commentsResult.value);
|
|
279
|
-
}
|
|
280
|
-
let prComments = null;
|
|
281
|
-
if (context.prMarker) {
|
|
282
|
-
if (!context.prNumber) {
|
|
283
|
-
return {
|
|
284
|
-
earlyReturn: failResult(CHECK_TYPE, "Expected a verified bound pull request for PR comment verification", "check_failed")
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
const prCommentsResult = listRemoteComments(githubClient, context.upstreamRepo, context.prNumber, context.taskDir);
|
|
288
|
-
if (!prCommentsResult.ok) {
|
|
289
|
-
return {
|
|
290
|
-
earlyReturn: prCommentsResult.error.retryable
|
|
291
|
-
? blockedResult(CHECK_TYPE, prCommentsResult.error.message, "network_error")
|
|
292
|
-
: failResult(CHECK_TYPE, prCommentsResult.error.message, "check_failed")
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
prComments = prCommentsResult.value;
|
|
296
|
-
}
|
|
297
|
-
let issueType;
|
|
298
|
-
if (context.config.verify_issue_type && context.hasPush) {
|
|
299
|
-
const issueTypeResult = withRetry(() => ghText([
|
|
300
|
-
"api",
|
|
301
|
-
`repos/${context.upstreamRepo}/issues/${context.issueNumber}`,
|
|
302
|
-
"--jq",
|
|
303
|
-
".type.name // empty"
|
|
304
|
-
], context.taskDir));
|
|
305
|
-
if (issueTypeResult.ok) {
|
|
306
|
-
issueType = issueTypeResult.value || null;
|
|
252
|
+
const issueSnapshot = facts.value.issue;
|
|
253
|
+
const issue = issueSnapshot
|
|
254
|
+
? {
|
|
255
|
+
state: issueSnapshot.state.toUpperCase(),
|
|
256
|
+
labels: issueSnapshot.labels.map((name) => ({ name })),
|
|
257
|
+
body: issueSnapshot.body,
|
|
258
|
+
milestone: issueSnapshot.milestone ? { title: issueSnapshot.milestone } : null
|
|
307
259
|
}
|
|
308
|
-
|
|
260
|
+
: null;
|
|
309
261
|
let issueFields;
|
|
310
|
-
if (context.config.verify_issue_fields &&
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
"
|
|
315
|
-
|
|
316
|
-
`query=${ISSUE_FIELDS_QUERY}`,
|
|
317
|
-
"-F",
|
|
318
|
-
`owner=${owner}`,
|
|
319
|
-
"-F",
|
|
320
|
-
`name=${name}`,
|
|
321
|
-
"-F",
|
|
322
|
-
`number=${context.issueNumber}`
|
|
323
|
-
], context.taskDir));
|
|
324
|
-
if (issueFieldsResult.ok) {
|
|
325
|
-
issueFields = normalizeIssueFields(issueFieldsResult.value);
|
|
326
|
-
}
|
|
262
|
+
if (context.config.verify_issue_fields && issueSnapshot?.issueType) {
|
|
263
|
+
const fieldKinds = new Map(issueSnapshot.issueType.fields.map((field) => [field.name, field.kind]));
|
|
264
|
+
issueFields = {
|
|
265
|
+
pinnedNames: new Set(issueSnapshot.issueType.fields.map((field) => field.name)),
|
|
266
|
+
values: new Map(Object.entries(issueSnapshot.fields).map(([name, value]) => [name, { kind: fieldKinds.get(name) || (typeof value === "number" ? "number" : "single-select"), value }]))
|
|
267
|
+
};
|
|
327
268
|
}
|
|
328
|
-
let
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
if (((context.config.verify_in_labels_match_pr && context.hasTriage)
|
|
333
|
-
|| (context.config.verify_pr_type_label && context.hasTriage)
|
|
334
|
-
|| (context.config.verify_milestone && context.hasTriage)
|
|
335
|
-
|| (context.config.verify_pr_assignee && context.hasPush)
|
|
336
|
-
|| context.config.verify_pr_comment_last_commit_matches_head) && context.prNumber) {
|
|
337
|
-
const prResult = inspectGitHubPullRequest(githubClient, context.upstreamRepo, context.prNumber, context.taskDir);
|
|
338
|
-
if (!prResult.ok) {
|
|
269
|
+
let prComments = null;
|
|
270
|
+
if (context.prMarker && context.prIdentity && shouldFetchComments(context.config) && provider?.comments?.list) {
|
|
271
|
+
const listed = await provider.comments.list({ context: operationContext, parent: context.prIdentity });
|
|
272
|
+
if (!listed.ok)
|
|
339
273
|
return {
|
|
340
|
-
earlyReturn:
|
|
341
|
-
? blockedResult(CHECK_TYPE,
|
|
342
|
-
: failResult(CHECK_TYPE,
|
|
274
|
+
earlyReturn: listed.error.retryable
|
|
275
|
+
? blockedResult(CHECK_TYPE, listed.error.message, "network_error")
|
|
276
|
+
: failResult(CHECK_TYPE, listed.error.message, "check_failed")
|
|
343
277
|
};
|
|
278
|
+
prComments = listed.value.map((comment) => ({ id: comment.id, body: comment.body }));
|
|
279
|
+
}
|
|
280
|
+
const changeRequest = facts.value.changeRequest;
|
|
281
|
+
let inLabelMapping = {};
|
|
282
|
+
let repositoryLabels = [];
|
|
283
|
+
if (context.config.verify_in_labels_computed && context.hasTriage) {
|
|
284
|
+
const mapping = loadInLabelMapping();
|
|
285
|
+
if (!mapping.ok)
|
|
286
|
+
return { earlyReturn: failResult(CHECK_TYPE, mapping.message, "check_failed") };
|
|
287
|
+
inLabelMapping = mapping.value;
|
|
288
|
+
if (Object.keys(inLabelMapping).length > 0) {
|
|
289
|
+
const labels = provider?.issues?.listLabels
|
|
290
|
+
? await provider.issues.listLabels({ context: operationContext })
|
|
291
|
+
: unsupportedProviderOperation(provider, "issues.listLabels");
|
|
292
|
+
if (!labels.ok) {
|
|
293
|
+
const error = providerError(labels.error, "PLATFORM_PROVIDER_OPERATION_FAILED");
|
|
294
|
+
return {
|
|
295
|
+
earlyReturn: error.retryable
|
|
296
|
+
? blockedResult(CHECK_TYPE, `${error.code}: ${error.message}`, "network_error")
|
|
297
|
+
: failResult(CHECK_TYPE, `${error.code}: ${error.message}`, "check_failed")
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
repositoryLabels = labels.value;
|
|
344
301
|
}
|
|
345
|
-
prLabels = (context.config.verify_in_labels_match_pr || context.config.verify_pr_type_label)
|
|
346
|
-
? prResult.value.labels
|
|
347
|
-
: null;
|
|
348
|
-
prMilestone = context.config.verify_milestone
|
|
349
|
-
? prResult.value.milestone ? { title: prResult.value.milestone } : null
|
|
350
|
-
: undefined;
|
|
351
|
-
prAssignees = context.config.verify_pr_assignee
|
|
352
|
-
? prResult.value.assignees
|
|
353
|
-
: undefined;
|
|
354
|
-
prHeadSha = prResult.value.head.sha;
|
|
355
302
|
}
|
|
356
303
|
return {
|
|
357
304
|
issue,
|
|
358
|
-
comments,
|
|
305
|
+
comments: facts.value.comments.map((comment) => ({ id: comment.id, body: comment.body })),
|
|
359
306
|
prComments,
|
|
360
|
-
prLabels,
|
|
361
|
-
issueType
|
|
307
|
+
prLabels: changeRequest?.labels || null,
|
|
308
|
+
issueType: issueSnapshot
|
|
309
|
+
? (issueSnapshot.issueType ? issueSnapshot.issueType.name : null)
|
|
310
|
+
: undefined,
|
|
362
311
|
issueFields,
|
|
363
|
-
prMilestone
|
|
364
|
-
|
|
365
|
-
|
|
312
|
+
prMilestone: changeRequest
|
|
313
|
+
? (changeRequest.milestone ? { title: changeRequest.milestone } : null)
|
|
314
|
+
: undefined,
|
|
315
|
+
prAssignees: changeRequest?.assignees,
|
|
316
|
+
prHeadSha: changeRequest?.headSha,
|
|
317
|
+
inLabelMapping,
|
|
318
|
+
repositoryLabels
|
|
366
319
|
};
|
|
367
320
|
}
|
|
368
321
|
function mapTaskTypeToLabel(taskType) {
|
|
@@ -377,12 +330,6 @@ function shouldFetchComments(config) {
|
|
|
377
330
|
|| config.verify_comment_content
|
|
378
331
|
|| config.verify_task_comment_content);
|
|
379
332
|
}
|
|
380
|
-
function flattenComments(value) {
|
|
381
|
-
if (!Array.isArray(value)) {
|
|
382
|
-
return [];
|
|
383
|
-
}
|
|
384
|
-
return value.flatMap((page) => Array.isArray(page) ? page : []);
|
|
385
|
-
}
|
|
386
333
|
function checkStatusLabel(context, remoteData) {
|
|
387
334
|
if (!context.expectedStatusLabel || !context.hasTriage) {
|
|
388
335
|
return null;
|
|
@@ -541,7 +488,7 @@ function checkInLabelsComputed(context, remoteData) {
|
|
|
541
488
|
if (!context.config.verify_in_labels_computed || !context.hasTriage) {
|
|
542
489
|
return null;
|
|
543
490
|
}
|
|
544
|
-
const expectedInLabels = computeExpectedInLabels(context.taskDir);
|
|
491
|
+
const expectedInLabels = computeExpectedInLabels(context.taskDir, remoteData.repositoryLabels, remoteData.inLabelMapping);
|
|
545
492
|
if (!expectedInLabels.ok) {
|
|
546
493
|
return expectedInLabels.type === "check_failed"
|
|
547
494
|
? failResult(CHECK_TYPE, expectedInLabels.message, expectedInLabels.type)
|
|
@@ -781,7 +728,6 @@ function mapTaskTypeToIssueType(taskType) {
|
|
|
781
728
|
};
|
|
782
729
|
return mapping[taskType] || "Task";
|
|
783
730
|
}
|
|
784
|
-
const ISSUE_FIELDS_QUERY = `query($owner:String!,$name:String!,$number:Int!){repository(owner:$owner,name:$name){issue(number:$number){issueType{name pinnedFields{__typename ... on IssueFieldSingleSelect{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{name}}} ... on IssueFieldDateValue{value field{... on IssueFieldDate{name}}} ... on IssueFieldTextValue{value field{... on IssueFieldText{name}}} ... on IssueFieldNumberValue{value field{... on IssueFieldNumber{name}}}}}}}}`;
|
|
785
731
|
function normalizeIssueFields(payload) {
|
|
786
732
|
const issue = payload?.data?.repository?.issue;
|
|
787
733
|
const pinnedFields = Array.isArray(issue?.issueType?.pinnedFields)
|
|
@@ -842,58 +788,37 @@ function arraysEqual(left, right) {
|
|
|
842
788
|
function formatLabelList(labels) {
|
|
843
789
|
return labels.length > 0 ? labels.join(", ") : "none";
|
|
844
790
|
}
|
|
845
|
-
function computeExpectedInLabels(taskDir) {
|
|
846
|
-
const
|
|
791
|
+
function computeExpectedInLabels(taskDir, repositoryLabels = [], mappingOverride) {
|
|
792
|
+
const task = loadTask(taskDir);
|
|
793
|
+
if (!task.ok) {
|
|
794
|
+
return task;
|
|
795
|
+
}
|
|
796
|
+
const baseRef = String(task.metadata?.delivery_base_ref || "").trim();
|
|
797
|
+
if (!baseRef) {
|
|
798
|
+
return { ok: false, type: "check_failed", message: "Task has no delivery_base_ref for in-label evidence" };
|
|
799
|
+
}
|
|
800
|
+
const changedFilesResult = gitText(["diff", `${baseRef}...HEAD`, "--name-only"], taskDir);
|
|
847
801
|
if (!changedFilesResult.ok) {
|
|
848
|
-
return changedFilesResult;
|
|
802
|
+
return { ...changedFilesResult, type: "network_error" };
|
|
849
803
|
}
|
|
850
804
|
const changedFiles = String(changedFilesResult.value || "")
|
|
851
805
|
.split(/\r?\n/)
|
|
852
806
|
.map((value) => value.trim())
|
|
853
807
|
.filter(Boolean);
|
|
854
|
-
const mapping =
|
|
855
|
-
if (
|
|
856
|
-
return
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
}
|
|
867
|
-
return { ok: true, labels: Array.from(labels).sort(), mode: "mapped" };
|
|
868
|
-
}
|
|
869
|
-
const repoLabelsResult = withRetry(() => ghJson([
|
|
870
|
-
"label",
|
|
871
|
-
"list",
|
|
872
|
-
"--limit",
|
|
873
|
-
"200",
|
|
874
|
-
"--json",
|
|
875
|
-
"name"
|
|
876
|
-
], taskDir));
|
|
877
|
-
if (!repoLabelsResult.ok) {
|
|
878
|
-
return repoLabelsResult;
|
|
879
|
-
}
|
|
880
|
-
const repoInLabels = new Set(extractLabelNames(repoLabelsResult.value)
|
|
881
|
-
.filter((label) => label.startsWith("in:")));
|
|
882
|
-
if (repoInLabels.size === 0) {
|
|
883
|
-
return { ok: true, labels: [], mode: "fallback" };
|
|
884
|
-
}
|
|
885
|
-
const labels = new Set();
|
|
886
|
-
for (const file of changedFiles) {
|
|
887
|
-
const topLevel = file.split("/")[0];
|
|
888
|
-
if (!topLevel) {
|
|
889
|
-
continue;
|
|
890
|
-
}
|
|
891
|
-
const candidate = `in: ${topLevel}`;
|
|
892
|
-
if (repoInLabels.has(candidate)) {
|
|
893
|
-
labels.add(candidate);
|
|
894
|
-
}
|
|
808
|
+
const mapping = mappingOverride ?? {};
|
|
809
|
+
if (Object.keys(mapping).length === 0) {
|
|
810
|
+
return { ok: true, labels: [], mode: "mapped" };
|
|
811
|
+
}
|
|
812
|
+
const planned = planInLabelUpdate({
|
|
813
|
+
changedFiles,
|
|
814
|
+
currentLabels: [],
|
|
815
|
+
mapping,
|
|
816
|
+
repositoryLabels: new Set(repositoryLabels)
|
|
817
|
+
});
|
|
818
|
+
if (planned.error) {
|
|
819
|
+
return { ok: false, type: "check_failed", message: planned.error.message };
|
|
895
820
|
}
|
|
896
|
-
return { ok: true, labels:
|
|
821
|
+
return { ok: true, labels: planned.target, mode: "mapped" };
|
|
897
822
|
}
|
|
898
823
|
function loadInLabelMapping() {
|
|
899
824
|
const configPath = path.join(repoRoot, ".agents", ".airc.json");
|
|
@@ -902,60 +827,16 @@ function loadInLabelMapping() {
|
|
|
902
827
|
}
|
|
903
828
|
try {
|
|
904
829
|
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
905
|
-
const mapping = config?.labels?.in;
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
const normalized = {};
|
|
910
|
-
for (const [label, prefixes] of Object.entries(mapping)) {
|
|
911
|
-
if (!Array.isArray(prefixes)) {
|
|
912
|
-
continue;
|
|
913
|
-
}
|
|
914
|
-
const cleaned = prefixes
|
|
915
|
-
.map((value) => String(value || "").trim())
|
|
916
|
-
.filter(Boolean);
|
|
917
|
-
if (cleaned.length > 0) {
|
|
918
|
-
normalized[label] = cleaned;
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
return { ok: true, value: normalized };
|
|
830
|
+
const mapping = validateInLabelMapping(config?.labels?.in);
|
|
831
|
+
return mapping.ok
|
|
832
|
+
? { ok: true, value: mapping.value }
|
|
833
|
+
: { ok: false, type: "check_failed", message: mapping.error.message };
|
|
922
834
|
}
|
|
923
835
|
catch (error) {
|
|
924
836
|
return { ok: false, type: "check_failed", message: `Unable to parse .agents/.airc.json: ${error.message}` };
|
|
925
837
|
}
|
|
926
838
|
}
|
|
927
|
-
// ===
|
|
928
|
-
function detectRepoOwnerType(upstreamRepo, taskDir) {
|
|
929
|
-
const ownerTypeResult = withRetry(() => ghText([
|
|
930
|
-
"api",
|
|
931
|
-
`repos/${upstreamRepo}`,
|
|
932
|
-
"--jq",
|
|
933
|
-
".owner.type // empty"
|
|
934
|
-
], taskDir));
|
|
935
|
-
if (!ownerTypeResult.ok) {
|
|
936
|
-
return "unknown";
|
|
937
|
-
}
|
|
938
|
-
return ownerTypeResult.value || "unknown";
|
|
939
|
-
}
|
|
940
|
-
function ghJson(args, cwd) {
|
|
941
|
-
return mapClientResult(githubClient.json(args, { cwd }));
|
|
942
|
-
}
|
|
943
|
-
function ghText(args, cwd) {
|
|
944
|
-
return mapClientResult(githubClient.text(args, { cwd }));
|
|
945
|
-
}
|
|
946
|
-
function ghPaginatedJson(args, cwd) {
|
|
947
|
-
return ghJson(args, cwd);
|
|
948
|
-
}
|
|
949
|
-
function mapClientResult(result) {
|
|
950
|
-
if (result.ok)
|
|
951
|
-
return result;
|
|
952
|
-
const checkFailed = ["RESOURCE_NOT_FOUND", "PERMISSION_DENIED", "PLATFORM_REQUEST_INVALID"].includes(result.error.code);
|
|
953
|
-
return {
|
|
954
|
-
ok: false,
|
|
955
|
-
type: checkFailed ? "check_failed" : "network_error",
|
|
956
|
-
message: result.error.message
|
|
957
|
-
};
|
|
958
|
-
}
|
|
839
|
+
// === Git working tree ===
|
|
959
840
|
function gitText(args, cwd) {
|
|
960
841
|
try {
|
|
961
842
|
const value = execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
|
|
@@ -2,6 +2,8 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { parseTypedTaskFrontmatter } from '../task/frontmatter.js';
|
|
4
4
|
import { readPrDeliveryFact } from '../task/pr-delivery-fact.js';
|
|
5
|
+
import { resourceIdentityEquals, resourceIdentityNumber } from '../platform/resource-identity.js';
|
|
6
|
+
import { taskIssueIdentity } from '../platform/task-identities.js';
|
|
5
7
|
export class HostResolutionError extends Error {
|
|
6
8
|
code;
|
|
7
9
|
constructor(code, message) {
|
|
@@ -70,14 +72,23 @@ export function collectHostCandidates(input) {
|
|
|
70
72
|
catch {
|
|
71
73
|
continue;
|
|
72
74
|
}
|
|
73
|
-
const
|
|
75
|
+
const issueIdentity = taskIssueIdentity(frontmatter);
|
|
76
|
+
const issueNumber = resourceIdentityNumber(issueIdentity) ?? toPositiveNumber(frontmatter.issue_number);
|
|
74
77
|
const fact = readPrDeliveryFact(frontmatter);
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
const prIdentity = fact.status === 'valid' && fact.fact.state === 'bound' ? fact.fact.identity.resource : null;
|
|
79
|
+
const prNumber = resourceIdentityNumber(prIdentity);
|
|
80
|
+
const matchesPr = input.prIdentity
|
|
81
|
+
? Boolean(prIdentity && resourceIdentityEquals(prIdentity, input.prIdentity))
|
|
82
|
+
: input.prNumber !== undefined && prNumber === input.prNumber;
|
|
83
|
+
const identityDetails = {
|
|
84
|
+
...(issueIdentity && issueIdentity.kind !== 'number' ? { issueIdentity } : {}),
|
|
85
|
+
...(prIdentity && prIdentity.kind !== 'number' ? { prIdentity } : {})
|
|
86
|
+
};
|
|
87
|
+
if (matchesPr) {
|
|
88
|
+
candidates.push({ taskId: entry.name, taskDir, issueNumber, prNumber, ...identityDetails });
|
|
78
89
|
}
|
|
79
90
|
else if (issueNumber !== null && input.closingIssues.includes(issueNumber)) {
|
|
80
|
-
candidates.push({ taskId: entry.name, taskDir, issueNumber, prNumber });
|
|
91
|
+
candidates.push({ taskId: entry.name, taskDir, issueNumber, prNumber, ...identityDetails });
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
94
|
return candidates;
|
|
@@ -97,7 +108,9 @@ export function resolveHostFromCandidates(candidates) {
|
|
|
97
108
|
taskId: candidate.taskId,
|
|
98
109
|
taskDir: candidate.taskDir,
|
|
99
110
|
issueNumber: candidate.issueNumber ?? 0,
|
|
100
|
-
prNumber: candidate.prNumber ?? 0
|
|
111
|
+
prNumber: candidate.prNumber ?? 0,
|
|
112
|
+
...(candidate.issueIdentity ? { issueIdentity: candidate.issueIdentity } : {}),
|
|
113
|
+
...(candidate.prIdentity ? { prIdentity: candidate.prIdentity } : {})
|
|
101
114
|
};
|
|
102
115
|
}
|
|
103
116
|
return {
|