@fitlab-ai/agent-infra 0.8.4 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.ts +2 -2
- package/dist/bin/cli.js +2 -2
- package/dist/bin/internal-cli.js +98 -0
- package/dist/lib/decide.js +81 -90
- package/dist/lib/defaults.json +9 -0
- package/dist/lib/git/review-snapshot.js +79 -0
- package/dist/lib/git/workflow.js +101 -0
- package/dist/lib/init.js +5 -0
- package/dist/lib/internal/git-workflow.js +42 -0
- package/dist/lib/internal/platform-checks.js +119 -0
- package/dist/lib/internal/platform-comment.js +129 -0
- package/dist/lib/internal/platform-context.js +46 -0
- package/dist/lib/internal/platform-issue.js +142 -0
- package/dist/lib/internal/platform-pr.js +146 -0
- package/dist/lib/internal/release-workflow.js +217 -0
- package/dist/lib/internal/task-artifact.js +67 -0
- package/dist/lib/internal/task-context.js +43 -0
- package/dist/lib/internal/task-event.js +70 -0
- package/dist/lib/internal/task-ledger.js +114 -0
- package/dist/lib/internal/task-lifecycle.js +58 -0
- package/dist/lib/internal/task-short-id.js +83 -0
- package/dist/lib/internal/task-snapshot.js +47 -0
- package/dist/lib/internal/task-verify.js +50 -0
- package/dist/lib/internal/task-warning.js +74 -0
- package/dist/lib/platform/adapters.js +14 -0
- package/dist/lib/platform/context.js +146 -0
- package/dist/lib/platform/github-client.js +124 -0
- package/dist/lib/platform/issue-comments.js +409 -0
- package/dist/lib/platform/issue-metadata.js +183 -0
- package/dist/lib/platform/issues.js +617 -0
- package/dist/lib/platform/metadata-labels.js +28 -0
- package/dist/lib/platform/pr-checks.js +216 -0
- package/dist/lib/platform/pr-summary.js +88 -0
- package/dist/lib/platform/pull-request-metadata.js +38 -0
- package/dist/lib/platform/pull-requests.js +338 -0
- package/dist/lib/platform/releases.js +82 -0
- package/dist/lib/platform/types.js +22 -0
- package/dist/lib/platform/verification-required.js +78 -0
- package/dist/lib/platform/verification-sync.js +1014 -0
- package/dist/lib/platform/verification.js +6 -0
- package/dist/lib/release/channels.js +31 -0
- package/dist/lib/release/workflow.js +32 -0
- package/dist/lib/render.js +3 -2
- package/dist/lib/run/index.js +24 -7
- package/dist/lib/sandbox/capture.js +25 -3
- package/dist/lib/sandbox/commands/create.js +66 -26
- package/dist/lib/sandbox/commands/enter.js +34 -11
- package/dist/lib/sandbox/commands/list-running.js +10 -8
- package/dist/lib/sandbox/commands/show.js +2 -2
- package/dist/lib/sandbox/commands/start.js +53 -15
- package/dist/lib/sandbox/engine.js +33 -3
- package/dist/lib/sandbox/engines/colima.js +2 -2
- package/dist/lib/sandbox/index.js +6 -6
- package/dist/lib/sandbox/mounts.js +36 -0
- package/dist/lib/sandbox/recovery.js +562 -0
- package/dist/lib/sandbox/runtimes/base.dockerfile +4 -0
- package/dist/lib/sandbox/task-resolver.js +5 -1
- package/dist/lib/sandbox/tools.js +19 -0
- package/dist/lib/server/daemon.js +9 -0
- package/dist/lib/server/process-control.js +66 -73
- package/dist/lib/server/process-state.js +168 -0
- package/dist/lib/server/protocol.js +5 -5
- package/dist/lib/task/activity-log.js +61 -0
- package/dist/lib/task/artifact-lifecycle.js +427 -0
- package/dist/lib/task/command-options.js +30 -0
- package/dist/lib/task/commands/cat.js +36 -6
- package/dist/lib/task/commands/decisions.js +80 -46
- package/dist/lib/task/commands/files.js +21 -7
- package/dist/lib/task/commands/grep.js +55 -7
- package/dist/lib/task/commands/issue-body.js +23 -14
- package/dist/lib/task/commands/log.js +27 -70
- package/dist/lib/task/commands/show.js +20 -7
- package/dist/lib/task/commands/status.js +18 -8
- package/dist/lib/task/decision-intents.js +154 -0
- package/dist/lib/task/decision-items.js +53 -0
- package/dist/lib/task/events.js +318 -0
- package/dist/lib/task/frontmatter.js +159 -1
- package/dist/lib/task/implementation-inputs.js +117 -0
- package/dist/lib/task/index.js +12 -9
- package/dist/lib/task/issue-form.js +19 -6
- package/dist/lib/task/ledger-intents.js +185 -0
- package/dist/lib/task/ledger.js +65 -35
- package/dist/lib/task/lifecycle.js +484 -0
- package/dist/lib/task/resolve-ref.js +152 -32
- package/dist/lib/task/review-artifacts.js +101 -0
- package/dist/lib/task/review-fingerprint.js +46 -0
- package/dist/lib/task/sections.js +358 -4
- package/dist/lib/task/short-id.js +292 -7
- package/dist/lib/task/snapshot.js +95 -0
- package/dist/lib/task/verification-checks.js +8 -0
- package/dist/lib/task/verification-config.js +14 -0
- package/dist/lib/task/verification-engine.js +906 -0
- package/dist/lib/task/verification-review.js +3 -0
- package/dist/lib/task/verification-types.js +2 -0
- package/dist/lib/task/verification.js +113 -0
- package/dist/lib/task/workflow-warning-intents.js +131 -0
- package/dist/lib/task/workflow-warnings.js +10 -78
- package/dist/lib/task/write.js +241 -0
- package/dist/lib/update.js +2 -0
- package/lib/decide.ts +57 -97
- package/lib/defaults.json +9 -0
- package/lib/git/review-snapshot.ts +73 -0
- package/lib/git/workflow.ts +101 -0
- package/lib/init.ts +9 -0
- package/lib/internal/git-workflow.ts +37 -0
- package/lib/internal/platform-checks.ts +101 -0
- package/lib/internal/platform-comment.ts +99 -0
- package/lib/internal/platform-context.ts +33 -0
- package/lib/internal/platform-issue.ts +116 -0
- package/lib/internal/platform-pr.ts +119 -0
- package/lib/internal/release-workflow.ts +186 -0
- package/lib/internal/task-artifact.ts +47 -0
- package/lib/internal/task-context.ts +35 -0
- package/lib/internal/task-event.ts +51 -0
- package/lib/internal/task-ledger.ts +86 -0
- package/lib/internal/task-lifecycle.ts +41 -0
- package/lib/internal/task-short-id.ts +55 -0
- package/lib/internal/task-snapshot.ts +32 -0
- package/lib/internal/task-verify.ts +33 -0
- package/lib/internal/task-warning.ts +50 -0
- package/lib/platform/adapters.ts +30 -0
- package/lib/platform/context.ts +164 -0
- package/lib/platform/github-client.ts +146 -0
- package/lib/platform/issue-comments.ts +479 -0
- package/lib/platform/issue-metadata.ts +250 -0
- package/lib/platform/issues.ts +691 -0
- package/lib/platform/metadata-labels.ts +33 -0
- package/lib/platform/pr-checks.ts +246 -0
- package/lib/platform/pr-summary.ts +90 -0
- package/lib/platform/pull-request-metadata.ts +69 -0
- package/lib/platform/pull-requests.ts +380 -0
- package/lib/platform/releases.ts +71 -0
- package/lib/platform/types.ts +74 -0
- package/lib/platform/verification-required.ts +83 -0
- package/{templates/.agents/scripts/platform-adapters/platform-sync.github.js → lib/platform/verification-sync.ts} +221 -363
- package/lib/platform/verification.ts +11 -0
- package/lib/release/channels.ts +30 -0
- package/lib/release/workflow.ts +31 -0
- package/lib/render.ts +3 -2
- package/lib/run/index.ts +25 -7
- package/lib/sandbox/capture.ts +29 -3
- package/lib/sandbox/commands/create.ts +75 -28
- package/lib/sandbox/commands/enter.ts +38 -11
- package/lib/sandbox/commands/list-running.ts +10 -8
- package/lib/sandbox/commands/show.ts +2 -2
- package/lib/sandbox/commands/start.ts +50 -16
- package/lib/sandbox/engine.ts +37 -3
- package/lib/sandbox/engines/colima.ts +2 -2
- package/lib/sandbox/index.ts +6 -6
- package/lib/sandbox/mounts.ts +55 -0
- package/lib/sandbox/recovery.ts +828 -0
- package/lib/sandbox/runtimes/base.dockerfile +4 -0
- package/lib/sandbox/task-resolver.ts +5 -1
- package/lib/sandbox/tools.ts +31 -0
- package/lib/server/daemon.ts +9 -0
- package/lib/server/process-control.ts +70 -71
- package/lib/server/process-state.ts +183 -0
- package/lib/server/protocol.ts +5 -5
- package/lib/task/activity-log.ts +62 -0
- package/lib/task/artifact-lifecycle.ts +484 -0
- package/lib/task/command-options.ts +32 -0
- package/lib/task/commands/cat.ts +22 -9
- package/lib/task/commands/decisions.ts +49 -47
- package/lib/task/commands/files.ts +14 -6
- package/lib/task/commands/grep.ts +34 -7
- package/lib/task/commands/issue-body.ts +16 -16
- package/lib/task/commands/log.ts +17 -70
- package/lib/task/commands/show.ts +14 -6
- package/lib/task/commands/status.ts +17 -7
- package/lib/task/decision-intents.ts +163 -0
- package/lib/task/decision-items.ts +64 -0
- package/lib/task/events.ts +320 -0
- package/lib/task/frontmatter.ts +202 -2
- package/lib/task/implementation-inputs.ts +137 -0
- package/lib/task/index.ts +12 -9
- package/lib/task/issue-form.ts +20 -6
- package/lib/task/ledger-intents.ts +201 -0
- package/lib/task/ledger.ts +77 -31
- package/lib/task/lifecycle.ts +458 -0
- package/lib/task/resolve-ref.ts +197 -36
- package/{templates/.agents/scripts/lib/review-artifacts.js → lib/task/review-artifacts.ts} +11 -12
- package/{templates/.agents/scripts/lib/post-review-commit.js → lib/task/review-fingerprint.ts} +20 -10
- package/lib/task/sections.ts +486 -4
- package/lib/task/short-id.ts +403 -9
- package/lib/task/snapshot.ts +143 -0
- package/lib/task/verification-checks.ts +9 -0
- package/lib/task/verification-config.ts +20 -0
- package/{templates/.agents/scripts/validate-artifact.js → lib/task/verification-engine.ts} +257 -451
- package/lib/task/verification-review.ts +9 -0
- package/lib/task/verification-types.ts +29 -0
- package/lib/task/verification.ts +156 -0
- package/lib/task/workflow-warning-intents.ts +142 -0
- package/lib/task/workflow-warnings.ts +10 -78
- package/lib/task/write.ts +468 -0
- package/lib/update.ts +6 -0
- package/package.json +5 -2
- package/templates/.agents/README.en.md +6 -3
- package/templates/.agents/README.zh-CN.md +6 -3
- package/templates/.agents/rules/README.en.md +6 -5
- package/templates/.agents/rules/README.zh-CN.md +6 -5
- package/templates/.agents/rules/create-issue.en.md +1 -1
- package/templates/.agents/rules/create-issue.github.en.md +5 -184
- package/templates/.agents/rules/create-issue.github.zh-CN.md +12 -178
- package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
- package/templates/.agents/rules/human-decision-context.en.md +36 -0
- package/templates/.agents/rules/human-decision-context.zh-CN.md +36 -0
- package/templates/.agents/rules/issue-fields.github.en.md +4 -148
- package/templates/.agents/rules/issue-fields.github.zh-CN.md +9 -144
- package/templates/.agents/rules/issue-pr-commands.en.md +43 -3
- package/templates/.agents/rules/issue-pr-commands.github.en.md +15 -220
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +23 -213
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +45 -3
- package/templates/.agents/rules/issue-sync.en.md +1 -1
- package/templates/.agents/rules/issue-sync.github.en.md +14 -301
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +36 -287
- package/templates/.agents/rules/issue-sync.zh-CN.md +1 -1
- package/templates/.agents/rules/milestone-inference.en.md +1 -1
- package/templates/.agents/rules/milestone-inference.github.en.md +7 -119
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +8 -108
- package/templates/.agents/rules/milestone-inference.zh-CN.md +1 -1
- package/templates/.agents/rules/next-step-output.en.md +12 -11
- package/templates/.agents/rules/next-step-output.zh-CN.md +12 -11
- package/templates/.agents/rules/no-mid-flow-questions.en.md +3 -3
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +3 -3
- package/templates/.agents/rules/pr-checks-commands.en.md +16 -3
- package/templates/.agents/rules/pr-checks-commands.github.en.md +10 -54
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +19 -47
- package/templates/.agents/rules/pr-checks-commands.zh-CN.md +30 -3
- package/templates/.agents/rules/pr-sync.en.md +30 -3
- package/templates/.agents/rules/pr-sync.github.en.md +12 -115
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +26 -104
- package/templates/.agents/rules/pr-sync.zh-CN.md +43 -3
- package/templates/.agents/rules/review-handshake.en.md +13 -9
- package/templates/.agents/rules/review-handshake.zh-CN.md +13 -9
- package/templates/.agents/rules/task-management.en.md +11 -2
- package/templates/.agents/rules/task-management.zh-CN.md +11 -3
- package/templates/.agents/rules/task-short-id.en.md +25 -29
- package/templates/.agents/rules/task-short-id.zh-CN.md +20 -23
- package/templates/.agents/scripts/lib/agent-infra-package.js +141 -0
- package/templates/.agents/scripts/task-short-id.js +71 -533
- package/templates/.agents/skills/analyze-task/SKILL.en.md +22 -55
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +26 -59
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -3
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -3
- package/templates/.agents/skills/block-task/SKILL.en.md +21 -47
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +23 -47
- package/templates/.agents/skills/block-task/config/verify.json +1 -2
- package/templates/.agents/skills/cancel-task/SKILL.en.md +16 -45
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +16 -45
- package/templates/.agents/skills/cancel-task/config/verify.json +1 -2
- package/templates/.agents/skills/check-task/SKILL.en.md +6 -3
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +6 -3
- package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -24
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -24
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -24
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -24
- package/templates/.agents/skills/code-task/SKILL.en.md +22 -35
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +28 -44
- package/templates/.agents/skills/code-task/config/verify.en.json +3 -3
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +3 -3
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +13 -9
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +13 -9
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +11 -1
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +11 -1
- package/templates/.agents/skills/commit/SKILL.en.md +18 -14
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +18 -14
- package/templates/.agents/skills/commit/config/verify.json +1 -2
- package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -11
- package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -11
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +4 -8
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +4 -8
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +6 -18
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +5 -17
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +42 -2
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +42 -2
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +13 -36
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +13 -36
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -3
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -3
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +10 -54
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +10 -79
- package/templates/.agents/skills/complete-task/SKILL.en.md +59 -63
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +59 -63
- package/templates/.agents/skills/complete-task/config/verify.en.json +11 -6
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +11 -6
- package/templates/.agents/skills/create-pr/SKILL.en.md +19 -44
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +19 -43
- package/templates/.agents/skills/create-pr/config/verify.json +1 -2
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +8 -12
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +7 -11
- package/templates/.agents/skills/create-task/SKILL.en.md +12 -13
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +12 -13
- package/templates/.agents/skills/create-task/config/verify.json +1 -2
- package/templates/.agents/skills/import-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/import-codescan/config/verify.json +1 -2
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/import-dependabot/config/verify.json +1 -2
- package/templates/.agents/skills/import-issue/SKILL.en.md +9 -13
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -14
- package/templates/.agents/skills/import-issue/config/verify.json +1 -2
- package/templates/.agents/skills/init-milestones/SKILL.en.md +2 -2
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +5 -4
- package/templates/.agents/skills/plan-task/SKILL.en.md +17 -42
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +22 -49
- package/templates/.agents/skills/plan-task/config/verify.en.json +1 -3
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -3
- package/templates/.agents/skills/post-release/SKILL.en.md +11 -81
- package/templates/.agents/skills/post-release/SKILL.zh-CN.md +8 -78
- package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
- package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/release/SKILL.en.md +16 -163
- package/templates/.agents/skills/release/SKILL.zh-CN.md +15 -162
- package/templates/.agents/skills/restore-task/SKILL.en.md +11 -29
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +11 -29
- package/templates/.agents/skills/restore-task/config/verify.json +1 -2
- package/templates/.agents/skills/review-analysis/SKILL.en.md +13 -25
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +13 -33
- package/templates/.agents/skills/review-analysis/config/verify.en.json +3 -4
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +3 -4
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +9 -12
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +9 -12
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +9 -2
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +9 -2
- package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +7 -0
- package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +7 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +22 -36
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +23 -41
- package/templates/.agents/skills/review-code/config/verify.en.json +5 -5
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +5 -5
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +56 -18
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +56 -18
- package/templates/.agents/skills/review-code/reference/report-template.en.md +12 -4
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +12 -4
- package/templates/.agents/skills/review-code/reference/review-criteria.en.md +7 -0
- package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +7 -0
- package/templates/.agents/skills/review-plan/SKILL.en.md +13 -25
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +13 -33
- package/templates/.agents/skills/review-plan/config/verify.en.json +3 -4
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +3 -4
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +9 -12
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +9 -12
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +9 -2
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +9 -2
- package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +7 -0
- package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +7 -0
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +6 -3
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +6 -3
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +177 -151
- package/templates/.agents/skills/watch-pr/SKILL.en.md +24 -14
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +25 -15
- package/templates/.agents/skills/watch-pr/config/verify.json +1 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +2 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +2 -2
- package/templates/.agents/templates/task.en.md +6 -1
- package/templates/.agents/templates/task.zh-CN.md +6 -1
- package/templates/.claude/commands/analyze-task.en.md +1 -1
- package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
- package/templates/.claude/commands/block-task.en.md +1 -1
- package/templates/.claude/commands/block-task.zh-CN.md +1 -1
- package/templates/.claude/commands/cancel-task.en.md +1 -1
- package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
- package/templates/.claude/commands/check-task.en.md +1 -1
- package/templates/.claude/commands/check-task.zh-CN.md +1 -1
- package/templates/.claude/commands/code-task.en.md +1 -1
- package/templates/.claude/commands/code-task.zh-CN.md +1 -1
- package/templates/.claude/commands/commit.en.md +1 -0
- package/templates/.claude/commands/commit.zh-CN.md +1 -0
- package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-task.en.md +1 -1
- package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
- package/templates/.claude/commands/create-pr.en.md +1 -1
- package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
- package/templates/.claude/commands/plan-task.en.md +1 -1
- package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
- package/templates/.claude/commands/review-analysis.en.md +1 -1
- package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
- package/templates/.claude/commands/review-code.en.md +1 -1
- package/templates/.claude/commands/review-code.zh-CN.md +1 -1
- package/templates/.claude/commands/review-plan.en.md +1 -1
- package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
- package/templates/.claude/commands/watch-pr.en.md +1 -1
- package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
- package/templates/.gemini/commands/_project_/analyze-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/block-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/cancel-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/check-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/code-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/commit.en.toml +4 -0
- package/templates/.gemini/commands/_project_/commit.zh-CN.toml +4 -0
- package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +2 -0
- package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/complete-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/create-pr.en.toml +2 -0
- package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/plan-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/review-analysis.en.toml +2 -0
- package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/review-code.en.toml +2 -0
- package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/review-plan.en.toml +2 -0
- package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/watch-pr.en.toml +2 -0
- package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +2 -0
- package/templates/.git-hooks/check-large-files.cjs +92 -0
- package/templates/.git-hooks/check-version-format.sh +5 -1
- package/templates/.git-hooks/pre-commit +1 -0
- package/templates/.opencode/commands/analyze-task.en.md +1 -1
- package/templates/.opencode/commands/analyze-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/check-task.en.md +1 -1
- package/templates/.opencode/commands/check-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/code-task.en.md +1 -1
- package/templates/.opencode/commands/code-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/commit.en.md +2 -0
- package/templates/.opencode/commands/commit.zh-CN.md +2 -0
- package/templates/.opencode/commands/complete-task.en.md +1 -1
- package/templates/.opencode/commands/complete-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/plan-task.en.md +1 -1
- package/templates/.opencode/commands/plan-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/review-analysis.en.md +1 -1
- package/templates/.opencode/commands/review-analysis.zh-CN.md +1 -1
- package/templates/.opencode/commands/review-code.en.md +1 -1
- package/templates/.opencode/commands/review-code.zh-CN.md +1 -1
- package/templates/.opencode/commands/review-plan.en.md +1 -1
- package/templates/.opencode/commands/review-plan.zh-CN.md +1 -1
- package/templates/.agents/scripts/platform-adapters/platform-sync.js +0 -13
- package/templates/.agents/scripts/review-diff-fingerprint.js +0 -99
- package/templates/.agents/scripts/workflow-warnings.js +0 -290
- package/templates/.agents/skills/code-task/scripts/detect-mode.js +0 -257
- package/templates/.agents/skills/release/scripts/manage-milestones.github.sh +0 -80
- package/templates/.agents/skills/release/scripts/manage-milestones.sh +0 -6
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
|
-
import
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
|
+
|
|
6
|
+
import { createGitHubClient } from "./github-client.ts";
|
|
7
|
+
import { resolvePlatformContext } from "./context.ts";
|
|
8
|
+
import { hasCheckedRequirement, resolveRequirementSection } from "./issue-metadata.ts";
|
|
9
|
+
import { inspectGitHubIssueMetadata, requirementSectionAnchors } from "./issues.ts";
|
|
10
|
+
import { listRemoteComments } from "./issue-comments.ts";
|
|
11
|
+
import { taskTypeLabel } from "./metadata-labels.ts";
|
|
12
|
+
import { inspectGitHubPullRequest } from "./pull-requests.ts";
|
|
5
13
|
|
|
6
14
|
const CHECK_TYPE = "platform-sync";
|
|
7
|
-
const DEFAULT_RETRY_DELAYS_MS = [3000, 10000];
|
|
8
15
|
const VERSION_LINE_REGEX = /^[0-9]+\.[0-9]+\.x$/;
|
|
9
16
|
const FRONTMATTER_FIELD_MAP = {
|
|
10
17
|
priority: "Priority",
|
|
@@ -12,17 +19,18 @@ const FRONTMATTER_FIELD_MAP = {
|
|
|
12
19
|
start_date: "Start date",
|
|
13
20
|
target_date: "Target date"
|
|
14
21
|
};
|
|
15
|
-
const OPTION_LOCALIZATION = {
|
|
22
|
+
const OPTION_LOCALIZATION: Record<string, string> = {
|
|
16
23
|
"紧急": "Urgent",
|
|
17
24
|
"高": "High",
|
|
18
25
|
"中": "Medium",
|
|
19
26
|
"低": "Low"
|
|
20
27
|
};
|
|
21
28
|
|
|
22
|
-
let activeShared = null;
|
|
29
|
+
let activeShared: any = null;
|
|
23
30
|
let repoRoot = "";
|
|
31
|
+
const githubClient = createGitHubClient();
|
|
24
32
|
|
|
25
|
-
export function getDefaults() {
|
|
33
|
+
export function getDefaults(): any {
|
|
26
34
|
return {
|
|
27
35
|
statusLabels: {
|
|
28
36
|
pendingDesignWork: "status: pending-design-work",
|
|
@@ -42,7 +50,7 @@ export function getDefaults() {
|
|
|
42
50
|
};
|
|
43
51
|
}
|
|
44
52
|
|
|
45
|
-
function getShared() {
|
|
53
|
+
function getShared(): any {
|
|
46
54
|
if (!activeShared) {
|
|
47
55
|
throw new Error("platform-sync adapter shared utilities are unavailable");
|
|
48
56
|
}
|
|
@@ -50,51 +58,51 @@ function getShared() {
|
|
|
50
58
|
return activeShared;
|
|
51
59
|
}
|
|
52
60
|
|
|
53
|
-
function loadTask(...args) {
|
|
61
|
+
function loadTask(...args: any[]): any {
|
|
54
62
|
return getShared().loadTask(...args);
|
|
55
63
|
}
|
|
56
64
|
|
|
57
|
-
function getCheckedRequirements(...args) {
|
|
65
|
+
function getCheckedRequirements(...args: any[]): any {
|
|
58
66
|
return getShared().getCheckedRequirements(...args);
|
|
59
67
|
}
|
|
60
68
|
|
|
61
|
-
function normalizeContent(...args) {
|
|
69
|
+
function normalizeContent(...args: any[]): any {
|
|
62
70
|
return getShared().normalizeContent(...args);
|
|
63
71
|
}
|
|
64
72
|
|
|
65
|
-
function isBlank(...args) {
|
|
73
|
+
function isBlank(...args: any[]): any {
|
|
66
74
|
return getShared().isBlank(...args);
|
|
67
75
|
}
|
|
68
76
|
|
|
69
|
-
function escapeRegExp(...args) {
|
|
77
|
+
function escapeRegExp(...args: any[]): any {
|
|
70
78
|
return getShared().escapeRegExp(...args);
|
|
71
79
|
}
|
|
72
80
|
|
|
73
|
-
function passResult(...args) {
|
|
81
|
+
function passResult(...args: any[]): any {
|
|
74
82
|
return getShared().passResult(...args);
|
|
75
83
|
}
|
|
76
84
|
|
|
77
|
-
function failResult(...args) {
|
|
85
|
+
function failResult(...args: any[]): any {
|
|
78
86
|
return getShared().failResult(...args);
|
|
79
87
|
}
|
|
80
88
|
|
|
81
|
-
function blockedResult(...args) {
|
|
89
|
+
function blockedResult(...args: any[]): any {
|
|
82
90
|
return getShared().blockedResult(...args);
|
|
83
91
|
}
|
|
84
92
|
|
|
85
|
-
function safeStat(...args) {
|
|
93
|
+
function safeStat(...args: any[]): any {
|
|
86
94
|
return getShared().safeStat(...args);
|
|
87
95
|
}
|
|
88
96
|
|
|
89
|
-
function parseIssueNumber(...args) {
|
|
97
|
+
function parseIssueNumber(...args: any[]): any {
|
|
90
98
|
return getShared().parseIssueNumber(...args);
|
|
91
99
|
}
|
|
92
100
|
|
|
93
|
-
function parsePrNumber(...args) {
|
|
101
|
+
function parsePrNumber(...args: any[]): any {
|
|
94
102
|
return getShared().parsePrNumber(...args);
|
|
95
103
|
}
|
|
96
104
|
|
|
97
|
-
export function check({ taskDir, config, artifactFile }, shared) {
|
|
105
|
+
export function check({ taskDir, config, artifactFile }: any, shared: any): any {
|
|
98
106
|
activeShared = shared;
|
|
99
107
|
repoRoot = shared.repoRoot;
|
|
100
108
|
const context = buildSyncContext({ taskDir, config, artifactFile });
|
|
@@ -108,6 +116,7 @@ export function check({ taskDir, config, artifactFile }, shared) {
|
|
|
108
116
|
}
|
|
109
117
|
|
|
110
118
|
const subChecks = [
|
|
119
|
+
checkClosedIssueStatusLabels,
|
|
111
120
|
checkStatusLabel,
|
|
112
121
|
checkCommentMarker,
|
|
113
122
|
checkPrCommentMarker,
|
|
@@ -135,7 +144,7 @@ export function check({ taskDir, config, artifactFile }, shared) {
|
|
|
135
144
|
return passResult(CHECK_TYPE, `GitHub sync checks passed for Issue #${context.issueNumber}`);
|
|
136
145
|
}
|
|
137
146
|
|
|
138
|
-
function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
147
|
+
function buildSyncContext({ taskDir, config, artifactFile }: any): any {
|
|
139
148
|
const task = loadTask(taskDir);
|
|
140
149
|
if (!task.ok) {
|
|
141
150
|
return { earlyReturn: failResult(CHECK_TYPE, task.message) };
|
|
@@ -154,12 +163,20 @@ function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
|
154
163
|
return { earlyReturn: passResult(CHECK_TYPE, "Skipped: platform-sync not required for this task") };
|
|
155
164
|
}
|
|
156
165
|
|
|
157
|
-
const
|
|
158
|
-
if (
|
|
159
|
-
return { earlyReturn:
|
|
166
|
+
const platformContext = resolvePlatformContext({ cwd: repoRoot, client: githubClient });
|
|
167
|
+
if (platformContext.status === "failed") {
|
|
168
|
+
return { earlyReturn: failResult(CHECK_TYPE, platformContext.error?.message || "Platform context failed", "check_failed") };
|
|
169
|
+
}
|
|
170
|
+
if (platformContext.status === "blocked") {
|
|
171
|
+
return { earlyReturn: blockedResult(CHECK_TYPE, platformContext.error?.message || "Platform context blocked", "network_error") };
|
|
160
172
|
}
|
|
161
|
-
|
|
162
|
-
|
|
173
|
+
if (!platformContext.platform.repository) {
|
|
174
|
+
if (platformContext.error?.code === "REMOTE_MISSING" || platformContext.error?.code === "REMOTE_INVALID") {
|
|
175
|
+
return { earlyReturn: blockedResult(CHECK_TYPE, platformContext.error.message, "network_error") };
|
|
176
|
+
}
|
|
177
|
+
return { earlyReturn: passResult(CHECK_TYPE, `Skipped: ${platformContext.error?.message || "platform unavailable"}`) };
|
|
178
|
+
}
|
|
179
|
+
const repoOwnerType = detectRepoOwnerType(platformContext.platform.repository, taskDir);
|
|
163
180
|
const expectedValues = resolveExpectedValues(config);
|
|
164
181
|
if (!expectedValues.ok) {
|
|
165
182
|
return { earlyReturn: failResult(CHECK_TYPE, expectedValues.message, "check_failed") };
|
|
@@ -181,17 +198,17 @@ function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
|
181
198
|
artifactPath,
|
|
182
199
|
issueNumber,
|
|
183
200
|
prNumber,
|
|
184
|
-
upstreamRepo:
|
|
201
|
+
upstreamRepo: platformContext.platform.repository,
|
|
185
202
|
repoOwnerType,
|
|
186
|
-
hasTriage:
|
|
187
|
-
hasPush:
|
|
203
|
+
hasTriage: platformContext.capabilities.triage,
|
|
204
|
+
hasPush: platformContext.capabilities.push,
|
|
188
205
|
expectedStatusLabel: expectedValues.statusLabel,
|
|
189
206
|
marker,
|
|
190
207
|
prMarker
|
|
191
208
|
};
|
|
192
209
|
}
|
|
193
210
|
|
|
194
|
-
function resolveExpectedValues(config) {
|
|
211
|
+
function resolveExpectedValues(config: any): any {
|
|
195
212
|
const defaults = getDefaults();
|
|
196
213
|
const statusLabel = resolveDefaultValue({
|
|
197
214
|
collection: defaults.statusLabels,
|
|
@@ -231,7 +248,7 @@ function resolveExpectedValues(config) {
|
|
|
231
248
|
};
|
|
232
249
|
}
|
|
233
250
|
|
|
234
|
-
function resolveDefaultValue({ collection, key, value, configKey }) {
|
|
251
|
+
function resolveDefaultValue({ collection, key, value, configKey }: any): any {
|
|
235
252
|
if (!key) {
|
|
236
253
|
return { ok: true, value: value || null };
|
|
237
254
|
}
|
|
@@ -244,30 +261,28 @@ function resolveDefaultValue({ collection, key, value, configKey }) {
|
|
|
244
261
|
return { ok: true, value: resolvedValue };
|
|
245
262
|
}
|
|
246
263
|
|
|
247
|
-
function fetchRemoteData(context) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
"view",
|
|
251
|
-
String(context.issueNumber),
|
|
252
|
-
"-R",
|
|
264
|
+
function fetchRemoteData(context: any): any {
|
|
265
|
+
const sharedIssue = inspectGitHubIssueMetadata(
|
|
266
|
+
githubClient,
|
|
253
267
|
context.upstreamRepo,
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
"api",
|
|
260
|
-
`repos/${context.upstreamRepo}/issues/${context.issueNumber}`
|
|
261
|
-
], context.taskDir));
|
|
262
|
-
if (fallbackIssueResult.ok) {
|
|
263
|
-
issueResult = {
|
|
268
|
+
context.issueNumber,
|
|
269
|
+
context.taskDir
|
|
270
|
+
);
|
|
271
|
+
const issueResult = sharedIssue.ok
|
|
272
|
+
? {
|
|
264
273
|
ok: true,
|
|
265
|
-
value:
|
|
274
|
+
value: {
|
|
275
|
+
state: sharedIssue.value.state.toUpperCase(),
|
|
276
|
+
labels: sharedIssue.value.labels.map((name) => ({ name })),
|
|
277
|
+
body: sharedIssue.value.body,
|
|
278
|
+
milestone: sharedIssue.value.milestone ? { title: sharedIssue.value.milestone } : null
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
: {
|
|
282
|
+
ok: false,
|
|
283
|
+
type: sharedIssue.error.retryable ? "network_error" : "check_failed",
|
|
284
|
+
message: sharedIssue.error.message
|
|
266
285
|
};
|
|
267
|
-
} else {
|
|
268
|
-
issueResult = fallbackIssueResult;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
286
|
if (!issueResult.ok) {
|
|
272
287
|
return {
|
|
273
288
|
earlyReturn: issueResult.type === "check_failed"
|
|
@@ -311,22 +326,22 @@ function fetchRemoteData(context) {
|
|
|
311
326
|
};
|
|
312
327
|
}
|
|
313
328
|
|
|
314
|
-
const prCommentsResult =
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
329
|
+
const prCommentsResult = listRemoteComments(
|
|
330
|
+
githubClient,
|
|
331
|
+
context.upstreamRepo,
|
|
332
|
+
context.prNumber,
|
|
333
|
+
context.taskDir
|
|
334
|
+
);
|
|
320
335
|
|
|
321
336
|
if (!prCommentsResult.ok) {
|
|
322
337
|
return {
|
|
323
|
-
earlyReturn: prCommentsResult.
|
|
324
|
-
?
|
|
325
|
-
:
|
|
338
|
+
earlyReturn: prCommentsResult.error.retryable
|
|
339
|
+
? blockedResult(CHECK_TYPE, prCommentsResult.error.message, "network_error")
|
|
340
|
+
: failResult(CHECK_TYPE, prCommentsResult.error.message, "check_failed")
|
|
326
341
|
};
|
|
327
342
|
}
|
|
328
343
|
|
|
329
|
-
prComments =
|
|
344
|
+
prComments = prCommentsResult.value;
|
|
330
345
|
}
|
|
331
346
|
|
|
332
347
|
let issueType;
|
|
@@ -367,46 +382,37 @@ function fetchRemoteData(context) {
|
|
|
367
382
|
let prLabels = null;
|
|
368
383
|
let prMilestone;
|
|
369
384
|
let prAssignees;
|
|
385
|
+
let prHeadSha;
|
|
370
386
|
if (((context.config.verify_in_labels_match_pr && context.hasTriage)
|
|
371
387
|
|| (context.config.verify_pr_type_label && context.hasTriage)
|
|
372
388
|
|| (context.config.verify_milestone && context.hasTriage)
|
|
373
|
-
|| (context.config.verify_pr_assignee && context.hasPush)
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
if (context.config.verify_pr_assignee) {
|
|
382
|
-
prFields.push("assignees");
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
const prResult = withRetry(() => ghJson([
|
|
386
|
-
"pr",
|
|
387
|
-
"view",
|
|
388
|
-
String(context.prNumber),
|
|
389
|
-
"--json",
|
|
390
|
-
prFields.join(",")
|
|
391
|
-
], context.taskDir));
|
|
389
|
+
|| (context.config.verify_pr_assignee && context.hasPush)
|
|
390
|
+
|| context.config.verify_pr_comment_last_commit_matches_head) && context.prNumber) {
|
|
391
|
+
const prResult = inspectGitHubPullRequest(
|
|
392
|
+
githubClient,
|
|
393
|
+
context.upstreamRepo,
|
|
394
|
+
context.prNumber,
|
|
395
|
+
context.taskDir
|
|
396
|
+
);
|
|
392
397
|
|
|
393
398
|
if (!prResult.ok) {
|
|
394
399
|
return {
|
|
395
|
-
earlyReturn: prResult.
|
|
396
|
-
?
|
|
397
|
-
:
|
|
400
|
+
earlyReturn: prResult.error.retryable
|
|
401
|
+
? blockedResult(CHECK_TYPE, prResult.error.message, "network_error")
|
|
402
|
+
: failResult(CHECK_TYPE, prResult.error.message, "check_failed")
|
|
398
403
|
};
|
|
399
404
|
}
|
|
400
405
|
|
|
401
406
|
prLabels = (context.config.verify_in_labels_match_pr || context.config.verify_pr_type_label)
|
|
402
|
-
?
|
|
407
|
+
? prResult.value.labels
|
|
403
408
|
: null;
|
|
404
409
|
prMilestone = context.config.verify_milestone
|
|
405
|
-
? prResult.value
|
|
410
|
+
? prResult.value.milestone ? { title: prResult.value.milestone } : null
|
|
406
411
|
: undefined;
|
|
407
412
|
prAssignees = context.config.verify_pr_assignee
|
|
408
|
-
?
|
|
413
|
+
? prResult.value.assignees
|
|
409
414
|
: undefined;
|
|
415
|
+
prHeadSha = prResult.value.head.sha;
|
|
410
416
|
}
|
|
411
417
|
|
|
412
418
|
return {
|
|
@@ -417,27 +423,16 @@ function fetchRemoteData(context) {
|
|
|
417
423
|
issueType,
|
|
418
424
|
issueFields,
|
|
419
425
|
prMilestone,
|
|
420
|
-
prAssignees
|
|
426
|
+
prAssignees,
|
|
427
|
+
prHeadSha
|
|
421
428
|
};
|
|
422
429
|
}
|
|
423
430
|
|
|
424
|
-
function mapTaskTypeToLabel(taskType) {
|
|
425
|
-
|
|
426
|
-
bug: "type: bug",
|
|
427
|
-
bugfix: "type: bug",
|
|
428
|
-
feature: "type: feature",
|
|
429
|
-
enhancement: "type: enhancement",
|
|
430
|
-
refactor: "type: enhancement",
|
|
431
|
-
refactoring: "type: enhancement",
|
|
432
|
-
documentation: "type: documentation",
|
|
433
|
-
"dependency-upgrade": "type: dependency-upgrade",
|
|
434
|
-
task: "type: task"
|
|
435
|
-
};
|
|
436
|
-
|
|
437
|
-
return mapping[taskType] || null;
|
|
431
|
+
function mapTaskTypeToLabel(taskType: any): any {
|
|
432
|
+
return taskTypeLabel(taskType);
|
|
438
433
|
}
|
|
439
434
|
|
|
440
|
-
function shouldFetchComments(config) {
|
|
435
|
+
function shouldFetchComments(config: any): any {
|
|
441
436
|
return Boolean(
|
|
442
437
|
config.expected_comment_marker
|
|
443
438
|
|| config.expected_comment_marker_key
|
|
@@ -449,7 +444,7 @@ function shouldFetchComments(config) {
|
|
|
449
444
|
);
|
|
450
445
|
}
|
|
451
446
|
|
|
452
|
-
function flattenComments(value) {
|
|
447
|
+
function flattenComments(value: any): any {
|
|
453
448
|
if (!Array.isArray(value)) {
|
|
454
449
|
return [];
|
|
455
450
|
}
|
|
@@ -457,7 +452,7 @@ function flattenComments(value) {
|
|
|
457
452
|
return value.flatMap((page) => Array.isArray(page) ? page : []);
|
|
458
453
|
}
|
|
459
454
|
|
|
460
|
-
function checkStatusLabel(context, remoteData) {
|
|
455
|
+
function checkStatusLabel(context: any, remoteData: any): any {
|
|
461
456
|
if (!context.expectedStatusLabel || !context.hasTriage) {
|
|
462
457
|
return null;
|
|
463
458
|
}
|
|
@@ -477,7 +472,28 @@ function checkStatusLabel(context, remoteData) {
|
|
|
477
472
|
);
|
|
478
473
|
}
|
|
479
474
|
|
|
480
|
-
function
|
|
475
|
+
function checkClosedIssueStatusLabels(context: any, remoteData: any): any {
|
|
476
|
+
if (!context.config.verify_closed_issue_has_no_status_labels) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (String(remoteData.issue.state || "").toUpperCase() !== "CLOSED") {
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
const statusLabels = extractLabelNames(remoteData.issue.labels)
|
|
485
|
+
.filter((label: any) => label.startsWith("status:"));
|
|
486
|
+
if (statusLabels.length === 0) {
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return failResult(CHECK_TYPE,
|
|
491
|
+
`Closed Issue #${context.issueNumber} retains status labels: ${statusLabels.join(", ")}`,
|
|
492
|
+
"check_failed"
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function checkCommentMarker(context: any, remoteData: any): any {
|
|
481
497
|
if (!context.marker) {
|
|
482
498
|
return null;
|
|
483
499
|
}
|
|
@@ -493,7 +509,7 @@ function checkCommentMarker(context, remoteData) {
|
|
|
493
509
|
);
|
|
494
510
|
}
|
|
495
511
|
|
|
496
|
-
function checkPrCommentMarker(context, remoteData) {
|
|
512
|
+
function checkPrCommentMarker(context: any, remoteData: any): any {
|
|
497
513
|
if (!context.prMarker) {
|
|
498
514
|
return null;
|
|
499
515
|
}
|
|
@@ -509,7 +525,7 @@ function checkPrCommentMarker(context, remoteData) {
|
|
|
509
525
|
);
|
|
510
526
|
}
|
|
511
527
|
|
|
512
|
-
function checkPrCommentLastCommit(context, remoteData) {
|
|
528
|
+
function checkPrCommentLastCommit(context: any, remoteData: any): any {
|
|
513
529
|
if (!context.config.verify_pr_comment_last_commit_matches_head) {
|
|
514
530
|
return null;
|
|
515
531
|
}
|
|
@@ -537,15 +553,9 @@ function checkPrCommentLastCommit(context, remoteData) {
|
|
|
537
553
|
);
|
|
538
554
|
}
|
|
539
555
|
|
|
540
|
-
const
|
|
541
|
-
if (!
|
|
542
|
-
|
|
543
|
-
? failResult(CHECK_TYPE, headResult.message, headResult.type)
|
|
544
|
-
: blockedResult(CHECK_TYPE, headResult.message, headResult.type);
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
const expectedHead = String(headResult.value || "").trim();
|
|
548
|
-
const actualHead = match[1].trim();
|
|
556
|
+
const expectedHead = String(remoteData.prHeadSha || "").trim();
|
|
557
|
+
if (!expectedHead) return blockedResult(CHECK_TYPE, "Unable to resolve the PR head SHA", "network_error");
|
|
558
|
+
const actualHead = match[1]!.trim();
|
|
549
559
|
if (expectedHead === actualHead) {
|
|
550
560
|
return null;
|
|
551
561
|
}
|
|
@@ -556,7 +566,7 @@ function checkPrCommentLastCommit(context, remoteData) {
|
|
|
556
566
|
);
|
|
557
567
|
}
|
|
558
568
|
|
|
559
|
-
function checkPrCommentRequiredPatterns(context, remoteData) {
|
|
569
|
+
function checkPrCommentRequiredPatterns(context: any, remoteData: any): any {
|
|
560
570
|
const patterns = context.config.expected_pr_comment_required_patterns || [];
|
|
561
571
|
if (!Array.isArray(patterns) || patterns.length === 0) {
|
|
562
572
|
return null;
|
|
@@ -591,7 +601,7 @@ function checkPrCommentRequiredPatterns(context, remoteData) {
|
|
|
591
601
|
return null;
|
|
592
602
|
}
|
|
593
603
|
|
|
594
|
-
function checkCommentContent(context, remoteData) {
|
|
604
|
+
function checkCommentContent(context: any, remoteData: any): any {
|
|
595
605
|
if (!context.config.verify_comment_content) {
|
|
596
606
|
return null;
|
|
597
607
|
}
|
|
@@ -626,7 +636,7 @@ function checkCommentContent(context, remoteData) {
|
|
|
626
636
|
);
|
|
627
637
|
}
|
|
628
638
|
|
|
629
|
-
function checkTaskCommentContent(context, remoteData) {
|
|
639
|
+
function checkTaskCommentContent(context: any, remoteData: any): any {
|
|
630
640
|
if (!context.config.verify_task_comment_content) {
|
|
631
641
|
return null;
|
|
632
642
|
}
|
|
@@ -653,7 +663,7 @@ function checkTaskCommentContent(context, remoteData) {
|
|
|
653
663
|
);
|
|
654
664
|
}
|
|
655
665
|
|
|
656
|
-
function checkPrTypeLabel(context, remoteData) {
|
|
666
|
+
function checkPrTypeLabel(context: any, remoteData: any): any {
|
|
657
667
|
if (!context.config.verify_pr_type_label || !context.hasTriage || !context.prNumber || !remoteData.prLabels) {
|
|
658
668
|
return null;
|
|
659
669
|
}
|
|
@@ -673,16 +683,16 @@ function checkPrTypeLabel(context, remoteData) {
|
|
|
673
683
|
);
|
|
674
684
|
}
|
|
675
685
|
|
|
676
|
-
function checkInLabelsMatchPr(context, remoteData) {
|
|
686
|
+
function checkInLabelsMatchPr(context: any, remoteData: any): any {
|
|
677
687
|
if (!context.config.verify_in_labels_match_pr || !context.hasTriage || !context.prNumber || !remoteData.prLabels) {
|
|
678
688
|
return null;
|
|
679
689
|
}
|
|
680
690
|
|
|
681
691
|
const issueInLabels = extractLabelNames(remoteData.issue.labels)
|
|
682
|
-
.filter((label) => label.startsWith("in:"))
|
|
692
|
+
.filter((label: any) => label.startsWith("in:"))
|
|
683
693
|
.sort();
|
|
684
694
|
const prInLabels = remoteData.prLabels
|
|
685
|
-
.filter((label) => label.startsWith("in:"))
|
|
695
|
+
.filter((label: any) => label.startsWith("in:"))
|
|
686
696
|
.sort();
|
|
687
697
|
|
|
688
698
|
if (arraysEqual(issueInLabels, prInLabels)) {
|
|
@@ -695,7 +705,7 @@ function checkInLabelsMatchPr(context, remoteData) {
|
|
|
695
705
|
);
|
|
696
706
|
}
|
|
697
707
|
|
|
698
|
-
function checkInLabelsComputed(context, remoteData) {
|
|
708
|
+
function checkInLabelsComputed(context: any, remoteData: any): any {
|
|
699
709
|
if (!context.config.verify_in_labels_computed || !context.hasTriage) {
|
|
700
710
|
return null;
|
|
701
711
|
}
|
|
@@ -712,7 +722,7 @@ function checkInLabelsComputed(context, remoteData) {
|
|
|
712
722
|
}
|
|
713
723
|
|
|
714
724
|
const actualInLabels = extractLabelNames(remoteData.issue.labels)
|
|
715
|
-
.filter((label) => label.startsWith("in:"))
|
|
725
|
+
.filter((label: any) => label.startsWith("in:"))
|
|
716
726
|
.sort();
|
|
717
727
|
|
|
718
728
|
if (arraysEqual(expectedInLabels.labels, actualInLabels)) {
|
|
@@ -726,7 +736,7 @@ function checkInLabelsComputed(context, remoteData) {
|
|
|
726
736
|
);
|
|
727
737
|
}
|
|
728
738
|
|
|
729
|
-
function checkSyncedRequirements(context, remoteData) {
|
|
739
|
+
function checkSyncedRequirements(context: any, remoteData: any): any {
|
|
730
740
|
if (!context.config.sync_checked_requirements || !context.hasTriage) {
|
|
731
741
|
return null;
|
|
732
742
|
}
|
|
@@ -737,8 +747,22 @@ function checkSyncedRequirements(context, remoteData) {
|
|
|
737
747
|
}
|
|
738
748
|
|
|
739
749
|
const issueBody = remoteData.issue.body || "";
|
|
750
|
+
const resolution = resolveRequirementSection(
|
|
751
|
+
issueBody,
|
|
752
|
+
requirementSectionAnchors(repoRoot, context.task.metadata.type || "task")
|
|
753
|
+
);
|
|
754
|
+
if (resolution.status === "missing") {
|
|
755
|
+
return null;
|
|
756
|
+
}
|
|
757
|
+
if (resolution.status === "ambiguous") {
|
|
758
|
+
return failResult(CHECK_TYPE,
|
|
759
|
+
`Issue #${context.issueNumber} requirements section is ambiguous`,
|
|
760
|
+
"check_failed"
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
const requirementBody = issueBody.slice(resolution.bodyStart, resolution.bodyEnd);
|
|
740
764
|
const missingRequirements = checkedRequirements.filter(
|
|
741
|
-
(item) => !
|
|
765
|
+
(item: any) => !hasCheckedRequirement(requirementBody, item)
|
|
742
766
|
);
|
|
743
767
|
if (missingRequirements.length === 0) {
|
|
744
768
|
return null;
|
|
@@ -750,7 +774,7 @@ function checkSyncedRequirements(context, remoteData) {
|
|
|
750
774
|
);
|
|
751
775
|
}
|
|
752
776
|
|
|
753
|
-
function checkIssueType(context, remoteData) {
|
|
777
|
+
function checkIssueType(context: any, remoteData: any): any {
|
|
754
778
|
if (!context.config.verify_issue_type || !context.hasPush) {
|
|
755
779
|
return null;
|
|
756
780
|
}
|
|
@@ -781,7 +805,7 @@ function checkIssueType(context, remoteData) {
|
|
|
781
805
|
return null;
|
|
782
806
|
}
|
|
783
807
|
|
|
784
|
-
function checkIssueFields(context, remoteData) {
|
|
808
|
+
function checkIssueFields(context: any, remoteData: any): any {
|
|
785
809
|
if (!context.config.verify_issue_fields || !context.hasPush) {
|
|
786
810
|
return null;
|
|
787
811
|
}
|
|
@@ -820,7 +844,7 @@ function checkIssueFields(context, remoteData) {
|
|
|
820
844
|
return null;
|
|
821
845
|
}
|
|
822
846
|
|
|
823
|
-
function checkPrAssignee(context, remoteData) {
|
|
847
|
+
function checkPrAssignee(context: any, remoteData: any): any {
|
|
824
848
|
if (!context.config.verify_pr_assignee || !context.hasPush || !context.prNumber) {
|
|
825
849
|
return null;
|
|
826
850
|
}
|
|
@@ -835,7 +859,7 @@ function checkPrAssignee(context, remoteData) {
|
|
|
835
859
|
return null;
|
|
836
860
|
}
|
|
837
861
|
|
|
838
|
-
function checkMilestone(context, remoteData) {
|
|
862
|
+
function checkMilestone(context: any, remoteData: any): any {
|
|
839
863
|
if (!context.config.verify_milestone || !context.hasTriage) {
|
|
840
864
|
return null;
|
|
841
865
|
}
|
|
@@ -873,44 +897,48 @@ function checkMilestone(context, remoteData) {
|
|
|
873
897
|
return null;
|
|
874
898
|
}
|
|
875
899
|
|
|
876
|
-
function findCommentByMarker(comments, marker) {
|
|
877
|
-
return (comments || []).find((comment) => typeof comment.body === "string" && comment.body.includes(marker)) || null;
|
|
900
|
+
function findCommentByMarker(comments: any, marker: any): any {
|
|
901
|
+
return (comments || []).find((comment: any) => typeof comment.body === "string" && comment.body.includes(marker)) || null;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
function isGeneratedMarkerLine(line: any): any {
|
|
905
|
+
return line.startsWith("<!--") && line.endsWith("-->");
|
|
878
906
|
}
|
|
879
907
|
|
|
880
|
-
function extractCommentBody(commentBody) {
|
|
908
|
+
function extractCommentBody(commentBody: any): any {
|
|
881
909
|
const lines = String(commentBody || "").split(/\r?\n/);
|
|
882
910
|
|
|
883
911
|
let start = 0;
|
|
884
|
-
while (start < lines.length && (lines[start]
|
|
912
|
+
while (start < lines.length && (lines[start]!.trim() === "" || isGeneratedMarkerLine(lines[start]!.trim()))) {
|
|
885
913
|
start += 1;
|
|
886
914
|
}
|
|
887
915
|
|
|
888
|
-
if (start < lines.length && lines[start]
|
|
916
|
+
if (start < lines.length && lines[start]!.startsWith("## ")) {
|
|
889
917
|
start += 1;
|
|
890
918
|
}
|
|
891
919
|
|
|
892
|
-
while (start < lines.length && lines[start]
|
|
920
|
+
while (start < lines.length && lines[start]!.trim() === "") {
|
|
893
921
|
start += 1;
|
|
894
922
|
}
|
|
895
923
|
|
|
896
|
-
if (start < lines.length && /^> \*\*.+\*\* · .+$/.test(lines[start]
|
|
924
|
+
if (start < lines.length && /^> \*\*.+\*\* · .+$/.test(lines[start]!.trim())) {
|
|
897
925
|
start += 1;
|
|
898
926
|
}
|
|
899
927
|
|
|
900
|
-
while (start < lines.length && lines[start]
|
|
928
|
+
while (start < lines.length && lines[start]!.trim() === "") {
|
|
901
929
|
start += 1;
|
|
902
930
|
}
|
|
903
931
|
|
|
904
932
|
let end = lines.length;
|
|
905
933
|
for (let index = lines.length - 1; index >= start; index -= 1) {
|
|
906
|
-
const trimmed = lines[index]
|
|
934
|
+
const trimmed = lines[index]!.trim();
|
|
907
935
|
if (trimmed === "") {
|
|
908
936
|
continue;
|
|
909
937
|
}
|
|
910
938
|
|
|
911
939
|
if (/^\*.*\*$/.test(trimmed)) {
|
|
912
940
|
end = index;
|
|
913
|
-
if (end > start && lines[end - 1]
|
|
941
|
+
if (end > start && lines[end - 1]!.trim() === "---") {
|
|
914
942
|
end -= 1;
|
|
915
943
|
}
|
|
916
944
|
}
|
|
@@ -920,7 +948,7 @@ function extractCommentBody(commentBody) {
|
|
|
920
948
|
return lines.slice(start, end).join("\n");
|
|
921
949
|
}
|
|
922
950
|
|
|
923
|
-
function buildExpectedTaskBody(taskContent) {
|
|
951
|
+
function buildExpectedTaskBody(taskContent: any): any {
|
|
924
952
|
const frontmatterMatch = taskContent.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
|
|
925
953
|
if (!frontmatterMatch) {
|
|
926
954
|
return taskContent.trim();
|
|
@@ -940,7 +968,7 @@ function buildExpectedTaskBody(taskContent) {
|
|
|
940
968
|
].join("\n").trim();
|
|
941
969
|
}
|
|
942
970
|
|
|
943
|
-
function buildTaskFrontmatterSummary() {
|
|
971
|
+
function buildTaskFrontmatterSummary(): any {
|
|
944
972
|
const language = loadProjectLanguage();
|
|
945
973
|
if (language === "en" || language === "en-US") {
|
|
946
974
|
return "<details><summary>Metadata (frontmatter)</summary>";
|
|
@@ -949,7 +977,7 @@ function buildTaskFrontmatterSummary() {
|
|
|
949
977
|
return "<details><summary>元数据 (frontmatter)</summary>";
|
|
950
978
|
}
|
|
951
979
|
|
|
952
|
-
function loadProjectLanguage() {
|
|
980
|
+
function loadProjectLanguage(): any {
|
|
953
981
|
const override = process.env.VALIDATE_ARTIFACT_LANGUAGE;
|
|
954
982
|
if (!isBlank(override)) {
|
|
955
983
|
return String(override).trim();
|
|
@@ -968,14 +996,14 @@ function loadProjectLanguage() {
|
|
|
968
996
|
}
|
|
969
997
|
}
|
|
970
998
|
|
|
971
|
-
function buildCommentContentMismatchMessage(fileStem, issueNumber, localContent, commentContent) {
|
|
999
|
+
function buildCommentContentMismatchMessage(fileStem: any, issueNumber: any, localContent: any, commentContent: any): any {
|
|
972
1000
|
const diffIndex = firstDifferenceIndex(localContent, commentContent);
|
|
973
1001
|
const position = indexToLineColumn(localContent, diffIndex);
|
|
974
1002
|
|
|
975
1003
|
return `Comment content mismatch for '${fileStem}' on Issue #${issueNumber}: local file has ${localContent.length} chars, comment body has ${commentContent.length} chars (first difference near char ${diffIndex + 1}, line ${position.line}, column ${position.column})`;
|
|
976
1004
|
}
|
|
977
1005
|
|
|
978
|
-
function firstDifferenceIndex(left, right) {
|
|
1006
|
+
function firstDifferenceIndex(left: any, right: any): any {
|
|
979
1007
|
const limit = Math.max(left.length, right.length);
|
|
980
1008
|
for (let index = 0; index < limit; index += 1) {
|
|
981
1009
|
if (left[index] !== right[index]) {
|
|
@@ -986,7 +1014,7 @@ function firstDifferenceIndex(left, right) {
|
|
|
986
1014
|
return limit;
|
|
987
1015
|
}
|
|
988
1016
|
|
|
989
|
-
function indexToLineColumn(text, index) {
|
|
1017
|
+
function indexToLineColumn(text: any, index: any): any {
|
|
990
1018
|
const prefix = text.slice(0, Math.min(index, text.length));
|
|
991
1019
|
const lines = prefix.split("\n");
|
|
992
1020
|
return {
|
|
@@ -995,14 +1023,14 @@ function indexToLineColumn(text, index) {
|
|
|
995
1023
|
};
|
|
996
1024
|
}
|
|
997
1025
|
|
|
998
|
-
function extractLabelNames(labels) {
|
|
1026
|
+
function extractLabelNames(labels: any): any {
|
|
999
1027
|
return (labels || [])
|
|
1000
|
-
.map((label) => typeof label === "string" ? label : label?.name)
|
|
1001
|
-
.filter((label) => typeof label === "string" && label.length > 0);
|
|
1028
|
+
.map((label: any) => typeof label === "string" ? label : label?.name)
|
|
1029
|
+
.filter((label: any) => typeof label === "string" && label.length > 0);
|
|
1002
1030
|
}
|
|
1003
1031
|
|
|
1004
|
-
function mapTaskTypeToIssueType(taskType) {
|
|
1005
|
-
const mapping = {
|
|
1032
|
+
function mapTaskTypeToIssueType(taskType: any): any {
|
|
1033
|
+
const mapping: Record<string, string> = {
|
|
1006
1034
|
bug: "Bug",
|
|
1007
1035
|
bugfix: "Bug",
|
|
1008
1036
|
enhancement: "Feature",
|
|
@@ -1021,7 +1049,7 @@ function mapTaskTypeToIssueType(taskType) {
|
|
|
1021
1049
|
|
|
1022
1050
|
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}}}}}}}}`;
|
|
1023
1051
|
|
|
1024
|
-
function normalizeIssueFields(payload) {
|
|
1052
|
+
function normalizeIssueFields(payload: any): any {
|
|
1025
1053
|
const issue = payload?.data?.repository?.issue;
|
|
1026
1054
|
const pinnedFields = Array.isArray(issue?.issueType?.pinnedFields)
|
|
1027
1055
|
? issue.issueType.pinnedFields
|
|
@@ -1031,7 +1059,7 @@ function normalizeIssueFields(payload) {
|
|
|
1031
1059
|
: [];
|
|
1032
1060
|
const pinnedNames = new Set(
|
|
1033
1061
|
pinnedFields
|
|
1034
|
-
.map((field) => typeof field?.name === "string" ? field.name : "")
|
|
1062
|
+
.map((field: any) => typeof field?.name === "string" ? field.name : "")
|
|
1035
1063
|
.filter(Boolean)
|
|
1036
1064
|
);
|
|
1037
1065
|
const normalizedValues = new Map();
|
|
@@ -1058,7 +1086,7 @@ function normalizeIssueFields(payload) {
|
|
|
1058
1086
|
return { pinnedNames, values: normalizedValues };
|
|
1059
1087
|
}
|
|
1060
1088
|
|
|
1061
|
-
function normalizeExpectedIssueField(metadataKey, rawValue) {
|
|
1089
|
+
function normalizeExpectedIssueField(metadataKey: any, rawValue: any): any {
|
|
1062
1090
|
const value = String(rawValue || "").trim();
|
|
1063
1091
|
if (!value) {
|
|
1064
1092
|
return null;
|
|
@@ -1071,30 +1099,30 @@ function normalizeExpectedIssueField(metadataKey, rawValue) {
|
|
|
1071
1099
|
return { kind: "single-select", value: normalizeOptionName(value) };
|
|
1072
1100
|
}
|
|
1073
1101
|
|
|
1074
|
-
function normalizeOptionName(value) {
|
|
1102
|
+
function normalizeOptionName(value: any): any {
|
|
1075
1103
|
const normalized = String(value || "").trim();
|
|
1076
1104
|
return OPTION_LOCALIZATION[normalized] || normalized;
|
|
1077
1105
|
}
|
|
1078
1106
|
|
|
1079
|
-
function normalizeDateValue(value) {
|
|
1107
|
+
function normalizeDateValue(value: any): any {
|
|
1080
1108
|
const normalized = String(value || "").trim();
|
|
1081
1109
|
const match = normalized.match(/^\d{4}-\d{2}-\d{2}/);
|
|
1082
1110
|
return match ? match[0] : normalized;
|
|
1083
1111
|
}
|
|
1084
1112
|
|
|
1085
|
-
function arraysEqual(left, right) {
|
|
1113
|
+
function arraysEqual(left: any, right: any): any {
|
|
1086
1114
|
if (left.length !== right.length) {
|
|
1087
1115
|
return false;
|
|
1088
1116
|
}
|
|
1089
1117
|
|
|
1090
|
-
return left.every((value, index) => value === right[index]);
|
|
1118
|
+
return left.every((value: any, index: any) => value === right[index]);
|
|
1091
1119
|
}
|
|
1092
1120
|
|
|
1093
|
-
function formatLabelList(labels) {
|
|
1121
|
+
function formatLabelList(labels: any): any {
|
|
1094
1122
|
return labels.length > 0 ? labels.join(", ") : "none";
|
|
1095
1123
|
}
|
|
1096
1124
|
|
|
1097
|
-
function computeExpectedInLabels(taskDir) {
|
|
1125
|
+
function computeExpectedInLabels(taskDir: any): any {
|
|
1098
1126
|
const changedFilesResult = gitText(["diff", "main...HEAD", "--name-only"], taskDir);
|
|
1099
1127
|
if (!changedFilesResult.ok) {
|
|
1100
1128
|
return changedFilesResult;
|
|
@@ -1110,12 +1138,12 @@ function computeExpectedInLabels(taskDir) {
|
|
|
1110
1138
|
return mapping;
|
|
1111
1139
|
}
|
|
1112
1140
|
|
|
1113
|
-
if (Object.keys(mapping.value).length > 0) {
|
|
1141
|
+
if (Object.keys(mapping.value ?? {}).length > 0) {
|
|
1114
1142
|
const labels = new Set();
|
|
1115
1143
|
|
|
1116
1144
|
for (const file of changedFiles) {
|
|
1117
|
-
for (const [label, prefixes] of Object.entries(mapping.value)) {
|
|
1118
|
-
if (prefixes.some((prefix) => file.startsWith(prefix))) {
|
|
1145
|
+
for (const [label, prefixes] of Object.entries(mapping.value ?? {}) as Array<[string, string[]]>) {
|
|
1146
|
+
if (prefixes.some((prefix: any) => file.startsWith(prefix))) {
|
|
1119
1147
|
labels.add(`in: ${label}`);
|
|
1120
1148
|
}
|
|
1121
1149
|
}
|
|
@@ -1138,7 +1166,7 @@ function computeExpectedInLabels(taskDir) {
|
|
|
1138
1166
|
|
|
1139
1167
|
const repoInLabels = new Set(
|
|
1140
1168
|
extractLabelNames(repoLabelsResult.value)
|
|
1141
|
-
.filter((label) => label.startsWith("in:"))
|
|
1169
|
+
.filter((label: any) => label.startsWith("in:"))
|
|
1142
1170
|
);
|
|
1143
1171
|
|
|
1144
1172
|
if (repoInLabels.size === 0) {
|
|
@@ -1161,7 +1189,7 @@ function computeExpectedInLabels(taskDir) {
|
|
|
1161
1189
|
return { ok: true, labels: Array.from(labels).sort(), mode: "fallback" };
|
|
1162
1190
|
}
|
|
1163
1191
|
|
|
1164
|
-
function loadInLabelMapping() {
|
|
1192
|
+
function loadInLabelMapping(): any {
|
|
1165
1193
|
const configPath = path.join(repoRoot, ".agents", ".airc.json");
|
|
1166
1194
|
if (!fs.existsSync(configPath)) {
|
|
1167
1195
|
return { ok: true, value: {} };
|
|
@@ -1174,7 +1202,7 @@ function loadInLabelMapping() {
|
|
|
1174
1202
|
return { ok: true, value: {} };
|
|
1175
1203
|
}
|
|
1176
1204
|
|
|
1177
|
-
const normalized = {};
|
|
1205
|
+
const normalized: Record<string, string[]> = {};
|
|
1178
1206
|
for (const [label, prefixes] of Object.entries(mapping)) {
|
|
1179
1207
|
if (!Array.isArray(prefixes)) {
|
|
1180
1208
|
continue;
|
|
@@ -1189,88 +1217,14 @@ function loadInLabelMapping() {
|
|
|
1189
1217
|
}
|
|
1190
1218
|
|
|
1191
1219
|
return { ok: true, value: normalized };
|
|
1192
|
-
} catch (error) {
|
|
1220
|
+
} catch (error: any) {
|
|
1193
1221
|
return { ok: false, type: "check_failed", message: `Unable to parse .agents/.airc.json: ${error.message}` };
|
|
1194
1222
|
}
|
|
1195
1223
|
}
|
|
1196
1224
|
|
|
1197
1225
|
// === GitHub API ===
|
|
1198
1226
|
|
|
1199
|
-
function
|
|
1200
|
-
return {
|
|
1201
|
-
state: String(payload?.state || "").toUpperCase(),
|
|
1202
|
-
labels: Array.isArray(payload?.labels) ? payload.labels : [],
|
|
1203
|
-
body: typeof payload?.body === "string" ? payload.body : "",
|
|
1204
|
-
milestone: payload?.milestone ?? null
|
|
1205
|
-
};
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
function resolveUpstreamRepo(taskDir) {
|
|
1209
|
-
const ownerRepo = resolveOwnerRepo(taskDir);
|
|
1210
|
-
if (!ownerRepo.ok) {
|
|
1211
|
-
return ownerRepo;
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
const repoResult = withRetry(() => ghJson([
|
|
1215
|
-
"api",
|
|
1216
|
-
`repos/${ownerRepo.value}`
|
|
1217
|
-
], taskDir));
|
|
1218
|
-
|
|
1219
|
-
if (!repoResult.ok) {
|
|
1220
|
-
return repoResult;
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
const repo = repoResult.value && typeof repoResult.value === "object" ? repoResult.value : {};
|
|
1224
|
-
const upstreamRepo = repo.fork ? repo.parent?.full_name : repo.full_name;
|
|
1225
|
-
if (isBlank(upstreamRepo)) {
|
|
1226
|
-
return { ok: false, message: "Unable to resolve upstream repository" };
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
return { ok: true, value: upstreamRepo };
|
|
1230
|
-
}
|
|
1231
|
-
|
|
1232
|
-
function resolveOwnerRepo(taskDir) {
|
|
1233
|
-
const gitResult = spawn.sync("git", ["remote", "get-url", "origin"], {
|
|
1234
|
-
cwd: taskDir,
|
|
1235
|
-
encoding: "utf8"
|
|
1236
|
-
});
|
|
1237
|
-
|
|
1238
|
-
if (gitResult.status !== 0) {
|
|
1239
|
-
return { ok: false, message: `Unable to resolve git remote: ${gitResult.stderr.trim() || gitResult.stdout.trim()}` };
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
const remote = gitResult.stdout.trim();
|
|
1243
|
-
const sshMatch = remote.match(/[:/]([^/]+\/[^/]+?)(?:\.git)?$/);
|
|
1244
|
-
if (!sshMatch) {
|
|
1245
|
-
return { ok: false, message: `Unable to parse owner/repo from remote '${remote}'` };
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
return { ok: true, value: sshMatch[1] };
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
function detectPermissions(upstreamRepo, taskDir) {
|
|
1252
|
-
const permissionsResult = withRetry(() => ghJson([
|
|
1253
|
-
"api",
|
|
1254
|
-
`repos/${upstreamRepo}`,
|
|
1255
|
-
"--jq",
|
|
1256
|
-
".permissions"
|
|
1257
|
-
], taskDir));
|
|
1258
|
-
|
|
1259
|
-
if (!permissionsResult.ok) {
|
|
1260
|
-
return { hasTriage: false, hasPush: false };
|
|
1261
|
-
}
|
|
1262
|
-
|
|
1263
|
-
const permissions = permissionsResult.value && typeof permissionsResult.value === "object"
|
|
1264
|
-
? permissionsResult.value
|
|
1265
|
-
: {};
|
|
1266
|
-
|
|
1267
|
-
return {
|
|
1268
|
-
hasTriage: permissions.triage === true,
|
|
1269
|
-
hasPush: permissions.push === true
|
|
1270
|
-
};
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
function detectRepoOwnerType(upstreamRepo, taskDir) {
|
|
1227
|
+
function detectRepoOwnerType(upstreamRepo: any, taskDir: any): any {
|
|
1274
1228
|
const ownerTypeResult = withRetry(() => ghText([
|
|
1275
1229
|
"api",
|
|
1276
1230
|
`repos/${upstreamRepo}`,
|
|
@@ -1285,88 +1239,43 @@ function detectRepoOwnerType(upstreamRepo, taskDir) {
|
|
|
1285
1239
|
return ownerTypeResult.value || "unknown";
|
|
1286
1240
|
}
|
|
1287
1241
|
|
|
1288
|
-
function ghJson(args, cwd) {
|
|
1289
|
-
|
|
1290
|
-
if (!result.ok) {
|
|
1291
|
-
return result;
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
try {
|
|
1295
|
-
return { ok: true, value: JSON.parse(result.value || "null") };
|
|
1296
|
-
} catch (error) {
|
|
1297
|
-
return { ok: false, type: "network_error", message: `Invalid JSON from gh: ${error.message}` };
|
|
1298
|
-
}
|
|
1242
|
+
function ghJson(args: any, cwd: any): any {
|
|
1243
|
+
return mapClientResult(githubClient.json(args, { cwd }));
|
|
1299
1244
|
}
|
|
1300
1245
|
|
|
1301
|
-
function ghText(args, cwd) {
|
|
1302
|
-
|
|
1303
|
-
if (!result.ok) {
|
|
1304
|
-
return result;
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
return { ok: true, value: String(result.value || "").trim() };
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
function ghCommand(args, cwd) {
|
|
1311
|
-
const gh = resolveGhCommand();
|
|
1312
|
-
const result = spawn.sync(gh.command, [...gh.preArgs, ...args], {
|
|
1313
|
-
cwd,
|
|
1314
|
-
encoding: "utf8",
|
|
1315
|
-
env: process.env
|
|
1316
|
-
});
|
|
1317
|
-
|
|
1318
|
-
if (result.status !== 0) {
|
|
1319
|
-
const stderr = `${result.stderr || ""}${result.stdout || ""}`.trim();
|
|
1320
|
-
const classified = classifyGhFailure(stderr, args);
|
|
1321
|
-
return { ok: false, type: classified.type, message: classified.message };
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
return { ok: true, value: result.stdout };
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
|
-
function resolveGhCommand() {
|
|
1328
|
-
const command = process.env.AGENT_INFRA_GH_BIN || "gh";
|
|
1329
|
-
const rawPreArgs = process.env.AGENT_INFRA_GH_ARGS_JSON;
|
|
1330
|
-
if (!rawPreArgs) {
|
|
1331
|
-
return { command, preArgs: [] };
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
try {
|
|
1335
|
-
const preArgs = JSON.parse(rawPreArgs);
|
|
1336
|
-
if (Array.isArray(preArgs) && preArgs.every((arg) => typeof arg === "string")) {
|
|
1337
|
-
return { command, preArgs };
|
|
1338
|
-
}
|
|
1339
|
-
} catch {
|
|
1340
|
-
return { command, preArgs: [] };
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
return { command, preArgs: [] };
|
|
1246
|
+
function ghText(args: any, cwd: any): any {
|
|
1247
|
+
return mapClientResult(githubClient.text(args, { cwd }));
|
|
1344
1248
|
}
|
|
1345
1249
|
|
|
1346
|
-
function ghPaginatedJson(args, cwd) {
|
|
1250
|
+
function ghPaginatedJson(args: any, cwd: any): any {
|
|
1347
1251
|
return ghJson(args, cwd);
|
|
1348
1252
|
}
|
|
1349
1253
|
|
|
1350
|
-
function
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1254
|
+
function mapClientResult(result: any): any {
|
|
1255
|
+
if (result.ok) return result;
|
|
1256
|
+
const checkFailed = ["RESOURCE_NOT_FOUND", "PERMISSION_DENIED", "PLATFORM_REQUEST_INVALID"].includes(result.error.code);
|
|
1257
|
+
return {
|
|
1258
|
+
ok: false,
|
|
1259
|
+
type: checkFailed ? "check_failed" : "network_error",
|
|
1260
|
+
message: result.error.message
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1356
1263
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1264
|
+
function gitText(args: any, cwd: any): any {
|
|
1265
|
+
try {
|
|
1266
|
+
const value = execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] });
|
|
1267
|
+
return { ok: true, value: String(value || "").trim() };
|
|
1268
|
+
} catch (error: any) {
|
|
1269
|
+
const stderr = `${error?.stderr || ""}${error?.stdout || ""}`.trim();
|
|
1359
1270
|
return {
|
|
1360
1271
|
ok: false,
|
|
1361
1272
|
type: "check_failed",
|
|
1362
1273
|
message: stderr || `git ${args.join(" ")} failed`
|
|
1363
1274
|
};
|
|
1364
1275
|
}
|
|
1365
|
-
|
|
1366
|
-
return { ok: true, value: String(result.stdout || "").trim() };
|
|
1367
1276
|
}
|
|
1368
1277
|
|
|
1369
|
-
function resolvePrHeadSha(context) {
|
|
1278
|
+
function resolvePrHeadSha(context: any): any {
|
|
1370
1279
|
const fallback = () => withRetry(() => gitText(["rev-parse", "HEAD"], context.taskDir));
|
|
1371
1280
|
const branch = String(context.task?.metadata?.branch || "").trim();
|
|
1372
1281
|
if (!branch) {
|
|
@@ -1391,7 +1300,7 @@ function resolvePrHeadSha(context) {
|
|
|
1391
1300
|
return headInWorktree;
|
|
1392
1301
|
}
|
|
1393
1302
|
|
|
1394
|
-
function findWorktreeForBranch(porcelainOutput, branch) {
|
|
1303
|
+
function findWorktreeForBranch(porcelainOutput: any, branch: any): any {
|
|
1395
1304
|
let currentWorktree = "";
|
|
1396
1305
|
for (const rawLine of String(porcelainOutput || "").split("\n")) {
|
|
1397
1306
|
const line = rawLine.trimEnd();
|
|
@@ -1411,62 +1320,11 @@ function findWorktreeForBranch(porcelainOutput, branch) {
|
|
|
1411
1320
|
return null;
|
|
1412
1321
|
}
|
|
1413
1322
|
|
|
1414
|
-
function withRetry(operation) {
|
|
1415
|
-
|
|
1416
|
-
let lastFailure = null;
|
|
1417
|
-
|
|
1418
|
-
for (let attempt = 0; attempt <= delays.length; attempt += 1) {
|
|
1419
|
-
const result = operation();
|
|
1420
|
-
if (result.ok) {
|
|
1421
|
-
return result;
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
|
-
lastFailure = result;
|
|
1425
|
-
if (result.type === "check_failed") {
|
|
1426
|
-
return result;
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
if (attempt < delays.length) {
|
|
1430
|
-
sleep(delays[attempt]);
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
return lastFailure || { ok: false, type: "network_error", message: "Unknown GitHub sync failure" };
|
|
1435
|
-
}
|
|
1436
|
-
|
|
1437
|
-
function classifyGhFailure(stderr, args) {
|
|
1438
|
-
const message = stderr || `gh ${args.join(" ")} failed`;
|
|
1439
|
-
|
|
1440
|
-
if (/not found|could not resolve to an issue|http 404/i.test(message)) {
|
|
1441
|
-
return { type: "check_failed", message };
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
return { type: "network_error", message };
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
function getRetryDelays() {
|
|
1448
|
-
const override = process.env.VALIDATE_ARTIFACT_RETRY_DELAYS_MS;
|
|
1449
|
-
if (!override) {
|
|
1450
|
-
return DEFAULT_RETRY_DELAYS_MS;
|
|
1451
|
-
}
|
|
1452
|
-
|
|
1453
|
-
const parsed = override
|
|
1454
|
-
.split(",")
|
|
1455
|
-
.map((value) => Number(value.trim()))
|
|
1456
|
-
.filter((value) => Number.isFinite(value) && value >= 0);
|
|
1457
|
-
|
|
1458
|
-
return parsed.length > 0 ? parsed : DEFAULT_RETRY_DELAYS_MS;
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
function sleep(delayMs) {
|
|
1462
|
-
if (delayMs <= 0) {
|
|
1463
|
-
return;
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delayMs);
|
|
1323
|
+
function withRetry(operation: any): any {
|
|
1324
|
+
return operation();
|
|
1467
1325
|
}
|
|
1468
1326
|
|
|
1469
|
-
function interpolate(template, taskDir, artifactFile) {
|
|
1327
|
+
function interpolate(template: any, taskDir: any, artifactFile: any): any {
|
|
1470
1328
|
const artifactStem = artifactFile ? path.basename(artifactFile, path.extname(artifactFile)) : "";
|
|
1471
1329
|
return template
|
|
1472
1330
|
.replace(/\{task-id\}/g, path.basename(taskDir))
|