@fitlab-ai/agent-infra 0.9.11 → 0.9.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -13
- package/README.zh-CN.md +13 -13
- package/dist/bin/internal-cli.js +29 -19
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
- package/dist/lib/agent-clients/next-steps.js +6 -1
- package/dist/lib/decide.js +3 -3
- package/dist/lib/defaults.json +4 -0
- package/dist/lib/git/workflow.js +43 -1
- package/dist/lib/init.js +1 -0
- package/dist/lib/internal/git-workflow.js +8 -1
- package/dist/lib/internal/platform-checks.js +3 -3
- package/dist/lib/internal/platform-comment.js +9 -9
- package/dist/lib/internal/platform-context.js +2 -2
- package/dist/lib/internal/platform-issue.js +8 -9
- package/dist/lib/internal/platform-pr-review.js +10 -10
- package/dist/lib/internal/platform-pr.js +68 -23
- package/dist/lib/internal/platform-release-notes.js +3 -3
- package/dist/lib/internal/pr-review-grade.js +11 -9
- package/dist/lib/internal/release-workflow.js +4 -4
- package/dist/lib/internal/sandbox-control.js +30 -4
- package/dist/lib/internal/task-activity.js +3 -3
- package/dist/lib/internal/task-artifact.js +76 -24
- package/dist/lib/internal/task-create.js +2 -2
- package/dist/lib/internal/task-delivery.js +59 -0
- package/dist/lib/internal/task-event.js +6 -3
- package/dist/lib/internal/task-finalization.js +2 -2
- package/dist/lib/internal/task-invalidation.js +60 -0
- package/dist/lib/internal/task-ledger.js +9 -6
- package/dist/lib/internal/task-lifecycle.js +2 -2
- package/dist/lib/internal/task-override.js +4 -4
- package/dist/lib/internal/task-review.js +3 -3
- package/dist/lib/internal/task-verify.js +6 -6
- package/dist/lib/internal/task-warning.js +3 -3
- package/dist/lib/platform/adapters.js +1 -3
- package/dist/lib/platform/change-request-git-evidence.js +27 -7
- package/dist/lib/platform/completion-backfill.js +6 -5
- package/dist/lib/platform/context.js +70 -130
- package/dist/lib/platform/github-client.js +8 -2
- package/dist/lib/platform/github-provider.js +903 -0
- package/dist/lib/platform/in-label-sync.js +143 -0
- package/dist/lib/platform/issue-comments.js +94 -41
- package/dist/lib/platform/issues.js +335 -189
- package/dist/lib/platform/metadata-labels.js +6 -2
- package/dist/lib/platform/none-provider.js +28 -0
- package/dist/lib/platform/pr-change-report.js +551 -0
- package/dist/lib/platform/pr-checks.js +124 -106
- package/dist/lib/platform/pr-review.js +88 -72
- package/dist/lib/platform/pr-summary.js +523 -49
- package/dist/lib/platform/provider-bridge.js +45 -0
- package/dist/lib/platform/provider-contract.d.ts +487 -0
- package/dist/lib/platform/provider-contract.js +95 -0
- package/dist/lib/platform/provider-loader.js +251 -0
- package/dist/lib/platform/provider-validation.js +504 -0
- package/dist/lib/platform/pull-request-metadata.js +8 -6
- package/dist/lib/platform/pull-requests.js +1050 -502
- package/dist/lib/platform/release-notes.js +78 -55
- package/dist/lib/platform/releases.js +79 -50
- package/dist/lib/platform/resource-identity.d.ts +26 -0
- package/dist/lib/platform/resource-identity.js +92 -0
- package/dist/lib/platform/task-identities.js +31 -0
- package/dist/lib/platform/verification-required.js +22 -12
- package/dist/lib/platform/verification-sync.js +118 -239
- package/dist/lib/pr-review/evidence-grading.js +30 -9
- package/dist/lib/run/index.js +63 -23
- package/dist/lib/sandbox/config.js +5 -0
- package/dist/lib/sandbox/control/client.js +96 -15
- package/dist/lib/sandbox/control/executor.js +3 -3
- package/dist/lib/sandbox/control/lifecycle.js +29 -7
- package/dist/lib/sandbox/control/protocol.js +77 -0
- package/dist/lib/sandbox/control/server.js +398 -25
- package/dist/lib/sandbox/control/state.js +204 -1
- package/dist/lib/server/process-state.js +2 -2
- package/dist/lib/server/protocol.js +38 -1
- package/dist/lib/task/activity-log.js +8 -1
- package/dist/lib/task/artifact-lifecycle.js +35 -7
- package/dist/lib/task/capabilities.js +239 -0
- package/dist/lib/task/commands/status.js +32 -0
- package/dist/lib/task/commit-intent.js +100 -0
- package/dist/lib/task/commit-operation.js +207 -102
- package/dist/lib/task/control-authority.js +8 -5
- package/dist/lib/task/create-service.js +8 -8
- package/dist/lib/task/create.js +33 -7
- package/dist/lib/task/current-contract.js +5 -1
- package/dist/lib/task/decision-details.js +3 -48
- package/dist/lib/task/delivery-target.js +97 -0
- package/dist/lib/task/delivery.js +153 -0
- package/dist/lib/task/events.js +297 -17
- package/dist/lib/task/finalization.js +37 -13
- package/dist/lib/task/human-override.js +61 -36
- package/dist/lib/task/invalidation-command.js +86 -0
- package/dist/lib/task/invalidation.js +260 -0
- package/dist/lib/task/ledger-intents.js +37 -0
- package/dist/lib/task/lifecycle.js +106 -9
- package/dist/lib/task/local-artifact-finalization.js +374 -0
- package/dist/lib/task/orchestration.js +100 -151
- package/dist/lib/task/pr-delivery-fact.js +183 -0
- package/dist/lib/task/review-finalization.js +4 -8
- package/dist/lib/task/review-fingerprint.js +32 -2
- package/dist/lib/task/rework-intent.js +138 -0
- package/dist/lib/task/skill-scope.js +23 -0
- package/dist/lib/task/task-execution-lock.js +27 -17
- package/dist/lib/task/verification-engine.js +89 -38
- package/dist/lib/task/verification-review.js +1 -1
- 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/update.js +9 -0
- package/dist/lib/version.js +11 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
- package/lib/agent-clients/next-steps.ts +6 -1
- package/lib/decide.ts +3 -3
- package/lib/defaults.json +4 -0
- package/lib/git/workflow.ts +38 -1
- package/lib/init.ts +4 -1
- package/lib/internal/git-workflow.ts +7 -1
- package/lib/internal/platform-checks.ts +3 -3
- package/lib/internal/platform-comment.ts +8 -8
- package/lib/internal/platform-context.ts +2 -2
- package/lib/internal/platform-issue.ts +7 -8
- package/lib/internal/platform-pr-review.ts +9 -9
- package/lib/internal/platform-pr.ts +53 -21
- package/lib/internal/platform-release-notes.ts +3 -3
- package/lib/internal/pr-review-grade.ts +10 -8
- package/lib/internal/release-workflow.ts +4 -4
- package/lib/internal/sandbox-control.ts +27 -3
- package/lib/internal/task-activity.ts +3 -3
- package/lib/internal/task-artifact.ts +65 -22
- package/lib/internal/task-create.ts +2 -2
- package/lib/internal/task-delivery.ts +53 -0
- package/lib/internal/task-event.ts +6 -3
- package/lib/internal/task-finalization.ts +3 -3
- package/lib/internal/task-invalidation.ts +39 -0
- package/lib/internal/task-ledger.ts +11 -8
- package/lib/internal/task-lifecycle.ts +2 -2
- package/lib/internal/task-override.ts +6 -6
- package/lib/internal/task-review.ts +3 -3
- package/lib/internal/task-verify.ts +6 -6
- package/lib/internal/task-warning.ts +3 -3
- package/lib/platform/adapters.ts +3 -2
- package/lib/platform/change-request-git-evidence.ts +36 -9
- package/lib/platform/completion-backfill.ts +9 -8
- package/lib/platform/context.ts +97 -134
- package/lib/platform/github-client.ts +10 -3
- package/lib/platform/github-provider.ts +910 -0
- package/lib/platform/in-label-sync.ts +208 -0
- package/lib/platform/issue-comments.ts +97 -47
- package/lib/platform/issues.ts +344 -174
- package/lib/platform/metadata-labels.ts +5 -2
- package/lib/platform/none-provider.ts +35 -0
- package/lib/platform/pr-change-report.ts +645 -0
- package/lib/platform/pr-checks.ts +129 -107
- package/lib/platform/pr-review.ts +88 -85
- package/lib/platform/pr-summary.ts +562 -52
- package/lib/platform/provider-bridge.ts +82 -0
- package/lib/platform/provider-contract.ts +536 -0
- package/lib/platform/provider-loader.ts +307 -0
- package/lib/platform/provider-validation.ts +529 -0
- package/lib/platform/pull-request-metadata.ts +10 -7
- package/lib/platform/pull-requests.ts +1126 -505
- package/lib/platform/release-notes.ts +76 -59
- package/lib/platform/releases.ts +77 -43
- package/lib/platform/resource-identity.ts +121 -0
- package/lib/platform/task-identities.ts +40 -0
- package/lib/platform/types.ts +4 -2
- package/lib/platform/verification-required.ts +21 -13
- package/lib/platform/verification-sync.ts +118 -293
- package/lib/pr-review/evidence-grading.ts +31 -11
- package/lib/run/index.ts +57 -22
- package/lib/sandbox/config.ts +7 -0
- package/lib/sandbox/control/client.ts +105 -15
- package/lib/sandbox/control/executor.ts +4 -4
- package/lib/sandbox/control/lifecycle.ts +30 -8
- package/lib/sandbox/control/protocol.ts +113 -0
- package/lib/sandbox/control/server.ts +431 -23
- package/lib/sandbox/control/state.ts +251 -1
- package/lib/server/process-state.ts +2 -2
- package/lib/server/protocol.ts +36 -1
- package/lib/task/activity-log.ts +8 -0
- package/lib/task/artifact-lifecycle.ts +34 -8
- package/lib/task/capabilities.ts +262 -0
- package/lib/task/commands/status.ts +38 -0
- package/lib/task/commit-intent.ts +137 -0
- package/lib/task/commit-operation.ts +186 -88
- package/lib/task/control-authority.ts +11 -8
- package/lib/task/create-service.ts +8 -8
- package/lib/task/create.ts +34 -9
- package/lib/task/current-contract.ts +6 -1
- package/lib/task/decision-details.ts +8 -64
- package/lib/task/delivery-target.ts +130 -0
- package/lib/task/delivery.ts +160 -0
- package/lib/task/events.ts +296 -16
- package/lib/task/finalization.ts +50 -14
- package/lib/task/human-override.ts +73 -46
- package/lib/task/invalidation-command.ts +86 -0
- package/lib/task/invalidation.ts +332 -0
- package/lib/task/ledger-intents.ts +35 -1
- package/lib/task/lifecycle.ts +93 -4
- package/lib/task/local-artifact-finalization.ts +563 -0
- package/lib/task/orchestration.ts +110 -146
- package/lib/task/pr-delivery-fact.ts +237 -0
- package/lib/task/review-finalization.ts +4 -14
- package/lib/task/review-fingerprint.ts +33 -2
- package/lib/task/rework-intent.ts +165 -0
- package/lib/task/skill-scope.ts +24 -0
- package/lib/task/task-execution-lock.ts +23 -14
- package/lib/task/verification-engine.ts +95 -43
- package/lib/task/verification-review.ts +2 -0
- 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 +11 -1
- package/lib/version.ts +15 -1
- package/package.json +7 -1
- package/templates/.agents/rules/README.en.md +4 -2
- package/templates/.agents/rules/README.zh-CN.md +4 -2
- package/templates/.agents/rules/create-issue.en.md +11 -2
- package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
- package/templates/.agents/rules/issue-pr-commands.en.md +4 -17
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +28 -5
- package/templates/.agents/rules/issue-sync.zh-CN.md +64 -5
- package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
- package/templates/.agents/rules/local-artifact-repair.en.md +53 -0
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +53 -0
- package/templates/.agents/rules/milestone-inference.en.md +12 -2
- package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
- package/templates/.agents/rules/pr-sync.en.md +28 -13
- package/templates/.agents/rules/pr-sync.zh-CN.md +39 -5
- package/templates/.agents/rules/release-commands.en.md +42 -3
- package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
- package/templates/.agents/rules/security-alerts.en.md +17 -2
- package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
- package/templates/.agents/rules/sync-content-generation.en.md +8 -0
- package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
- package/templates/.agents/rules/task-management.en.md +1 -1
- package/templates/.agents/rules/task-management.zh-CN.md +1 -1
- 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/scripts/security-alerts.github.sh +151 -0
- package/templates/.agents/scripts/security-alerts.sh +31 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +14 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -3
- package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
- package/templates/.agents/skills/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 +32 -10
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +35 -13
- package/templates/.agents/skills/code-task/config/verify.en.json +1 -0
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/commit/SKILL.en.md +3 -3
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/config/verify.json +1 -1
- package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
- package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
- 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 +4 -4
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +4 -4
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +7 -4
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +7 -4
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +5 -4
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +5 -4
- package/templates/.agents/skills/complete-task/SKILL.en.md +31 -13
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +30 -13
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.en.md +11 -10
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +11 -11
- 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 +1 -0
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -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 +9 -10
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
- package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
- package/templates/.agents/skills/plan-task/SKILL.en.md +14 -3
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +11 -3
- package/templates/.agents/skills/review-analysis/SKILL.en.md +6 -5
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +6 -5
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +10 -9
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +10 -9
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
- package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
- package/templates/.agents/skills/review-plan/SKILL.en.md +6 -5
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +6 -5
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -2
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -2
- package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +4 -0
- package/templates/.agents/skills/watch-pr/SKILL.en.md +6 -6
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +6 -6
- 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 +23 -2
- package/templates/.agents/templates/task.zh-CN.md +23 -2
- package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
- package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/feature-development.en.yaml +9 -8
- package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/refactoring.en.yaml +9 -8
- package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
- package/templates/.github/workflows/pr-label.yml +7 -26
- package/templates/.agents/rules/create-issue.github.en.md +0 -14
- package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
- package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
- package/templates/.agents/rules/issue-sync.github.en.md +0 -40
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
- package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
- package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
- package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
- package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
- package/templates/.agents/rules/pr-sync.github.en.md +0 -43
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
- package/templates/.agents/rules/release-commands.github.en.md +0 -44
- package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -44
- package/templates/.agents/rules/security-alerts.github.en.md +0 -43
- package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
- /package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +0 -0
- /package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { computeInLabels } from './metadata-labels.js';
|
|
2
|
+
function inLabels(labels) {
|
|
3
|
+
return [...new Set(labels.filter((label) => label.startsWith('in:')))].sort();
|
|
4
|
+
}
|
|
5
|
+
function mergeInLabels(labels, target) {
|
|
6
|
+
return [...new Set([
|
|
7
|
+
...labels.filter((label) => !label.startsWith('in:')),
|
|
8
|
+
...target
|
|
9
|
+
])].sort();
|
|
10
|
+
}
|
|
11
|
+
function invalidInLabelInput(code, message) {
|
|
12
|
+
return { ok: false, error: { code, message, retryable: false } };
|
|
13
|
+
}
|
|
14
|
+
function validateInLabelMapping(value) {
|
|
15
|
+
if (value === undefined)
|
|
16
|
+
return { ok: true, value: {} };
|
|
17
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
18
|
+
return invalidInLabelInput('IN_LABEL_SYNC_MAPPING_INVALID', 'labels.in must be an object of non-empty string arrays');
|
|
19
|
+
}
|
|
20
|
+
const normalized = {};
|
|
21
|
+
for (const [name, rawPrefixes] of Object.entries(value)) {
|
|
22
|
+
if (!name.trim() || !Array.isArray(rawPrefixes) || rawPrefixes.length === 0 || rawPrefixes.some((prefix) => typeof prefix !== 'string' || !prefix.trim())) {
|
|
23
|
+
return invalidInLabelInput('IN_LABEL_SYNC_MAPPING_INVALID', `labels.in entry '${name}' must be a non-empty string array`);
|
|
24
|
+
}
|
|
25
|
+
normalized[name] = rawPrefixes.map((prefix) => prefix.trim());
|
|
26
|
+
}
|
|
27
|
+
return { ok: true, value: normalized };
|
|
28
|
+
}
|
|
29
|
+
function repositoryLabelPages(value) {
|
|
30
|
+
if (!Array.isArray(value))
|
|
31
|
+
return null;
|
|
32
|
+
if (value.length === 0)
|
|
33
|
+
return [];
|
|
34
|
+
if (value.every((page) => Array.isArray(page)))
|
|
35
|
+
return value;
|
|
36
|
+
if (value.every((entry) => entry && typeof entry === 'object' && !Array.isArray(entry)))
|
|
37
|
+
return [value];
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
function validateRepositoryLabelPayload(value) {
|
|
41
|
+
const pages = repositoryLabelPages(value);
|
|
42
|
+
if (!pages)
|
|
43
|
+
return invalidInLabelInput('IN_LABEL_SYNC_LABELS_INVALID', 'Repository labels response must be an array of pages');
|
|
44
|
+
const names = [];
|
|
45
|
+
for (const page of pages) {
|
|
46
|
+
for (const entry of page) {
|
|
47
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry) || typeof entry.name !== 'string' || !entry.name.trim()) {
|
|
48
|
+
return invalidInLabelInput('IN_LABEL_SYNC_LABELS_INVALID', 'Repository labels response contains an entry without a valid name');
|
|
49
|
+
}
|
|
50
|
+
names.push(entry.name);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { ok: true, value: [...new Set(names)].sort() };
|
|
54
|
+
}
|
|
55
|
+
function validateRepositoryLabelSet(value) {
|
|
56
|
+
if (!(value instanceof Set) || [...value].some((label) => typeof label !== 'string' || !label.trim())) {
|
|
57
|
+
return invalidInLabelInput('IN_LABEL_SYNC_LABELS_INVALID', 'Repository labels must be a set of non-empty names');
|
|
58
|
+
}
|
|
59
|
+
return { ok: true, value: new Set([...value]) };
|
|
60
|
+
}
|
|
61
|
+
function planInLabelUpdate(input) {
|
|
62
|
+
const current = inLabels(input.currentLabels);
|
|
63
|
+
const mapping = validateInLabelMapping(input.mapping);
|
|
64
|
+
const repositoryLabels = validateRepositoryLabelSet(input.repositoryLabels);
|
|
65
|
+
if (!mapping.ok)
|
|
66
|
+
return { current, target: [...current], labels: [...input.currentLabels].sort(), changed: false, error: mapping.error };
|
|
67
|
+
if (!repositoryLabels.ok)
|
|
68
|
+
return { current, target: [...current], labels: [...input.currentLabels].sort(), changed: false, error: repositoryLabels.error };
|
|
69
|
+
const target = computeInLabels([...input.changedFiles], mapping.value, repositoryLabels.value);
|
|
70
|
+
const labels = mergeInLabels(input.currentLabels, target);
|
|
71
|
+
return { current, target, labels, changed: labels.join('\0') !== [...input.currentLabels].sort().join('\0'), error: null };
|
|
72
|
+
}
|
|
73
|
+
function startsWithPrefix(label, prefix) {
|
|
74
|
+
return (Array.isArray(prefix) ? prefix : [prefix]).some((value) => label.startsWith(value));
|
|
75
|
+
}
|
|
76
|
+
function labelDelta(current, target, prefix = 'in:') {
|
|
77
|
+
const currentLabels = [...new Set(current)].sort();
|
|
78
|
+
const targetLabels = [...new Set(target.filter((label) => startsWithPrefix(label, prefix)))].sort();
|
|
79
|
+
return {
|
|
80
|
+
add: targetLabels.filter((label) => !currentLabels.includes(label)),
|
|
81
|
+
remove: currentLabels.filter((label) => startsWithPrefix(label, prefix) && !targetLabels.includes(label))
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function syncLabelDelta(client, repository, number, cwd, current, target, prefix = 'in:') {
|
|
85
|
+
const delta = labelDelta(current, target, prefix);
|
|
86
|
+
let changed = false;
|
|
87
|
+
const failure = (error) => {
|
|
88
|
+
if (changed || error.retryable) {
|
|
89
|
+
return {
|
|
90
|
+
status: 'blocked',
|
|
91
|
+
changed,
|
|
92
|
+
error: { ...error, code: 'IN_LABEL_SYNC_PARTIAL', message: `In-label synchronization is partial or unknown: ${error.message}` }
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return { status: 'failed', changed: false, error };
|
|
96
|
+
};
|
|
97
|
+
for (const label of delta.remove) {
|
|
98
|
+
const removed = client.json([
|
|
99
|
+
'api', `repos/${repository}/issues/${number}/labels/${encodeURIComponent(label)}`, '-X', 'DELETE'
|
|
100
|
+
], { cwd, method: 'DELETE' });
|
|
101
|
+
if (!removed.ok)
|
|
102
|
+
return failure(removed.error);
|
|
103
|
+
changed = true;
|
|
104
|
+
}
|
|
105
|
+
for (const label of delta.add) {
|
|
106
|
+
const added = client.json([
|
|
107
|
+
'api', `repos/${repository}/issues/${number}/labels`, '-X', 'POST', '--input', '-'
|
|
108
|
+
], { cwd, method: 'POST', input: JSON.stringify({ labels: [label] }) });
|
|
109
|
+
if (!added.ok)
|
|
110
|
+
return failure(added.error);
|
|
111
|
+
changed = true;
|
|
112
|
+
}
|
|
113
|
+
return { status: changed ? 'applied' : 'no-op', changed, error: null };
|
|
114
|
+
}
|
|
115
|
+
function flattenPages(value) {
|
|
116
|
+
if (!Array.isArray(value))
|
|
117
|
+
return [];
|
|
118
|
+
return value.flatMap((page) => Array.isArray(page) ? page : [page]);
|
|
119
|
+
}
|
|
120
|
+
function extractRepositoryLabelNames(value) {
|
|
121
|
+
return flattenPages(value).flatMap((entry) => {
|
|
122
|
+
if (typeof entry === 'string')
|
|
123
|
+
return [entry];
|
|
124
|
+
if (entry && typeof entry === 'object' && typeof entry.name === 'string') {
|
|
125
|
+
return [entry.name];
|
|
126
|
+
}
|
|
127
|
+
return [];
|
|
128
|
+
}).filter(Boolean).sort();
|
|
129
|
+
}
|
|
130
|
+
function extractPullRequestFileNames(value) {
|
|
131
|
+
const entries = flattenPages(value);
|
|
132
|
+
if (!Array.isArray(value) || entries.some((entry) => !entry || typeof entry !== 'object'))
|
|
133
|
+
return null;
|
|
134
|
+
const names = entries.map((entry) => entry.filename);
|
|
135
|
+
if (names.some((name) => typeof name !== 'string' || !name.trim()))
|
|
136
|
+
return null;
|
|
137
|
+
return [...new Set(names)].sort();
|
|
138
|
+
}
|
|
139
|
+
function resourceSnapshot(kind, number, labels) {
|
|
140
|
+
return { kind, number, labels: [...labels].sort() };
|
|
141
|
+
}
|
|
142
|
+
export { extractPullRequestFileNames, extractRepositoryLabelNames, flattenPages, inLabels, labelDelta, mergeInLabels, planInLabelUpdate, resourceSnapshot, syncLabelDelta, validateInLabelMapping, validateRepositoryLabelPayload };
|
|
143
|
+
//# sourceMappingURL=in-label-sync.js.map
|
|
@@ -2,9 +2,14 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { parseTaskFrontmatter } from '../task/frontmatter.js';
|
|
4
4
|
import { resolveTaskRef } from '../task/resolve-ref.js';
|
|
5
|
-
import {
|
|
6
|
-
import { resolvePlatformContext } from './context.js';
|
|
5
|
+
import { resolvePlatformProviderContext } from './context.js';
|
|
7
6
|
import { platformResult } from './types.js';
|
|
7
|
+
import { providerError, providerOperationContext, providerStatus, providerResourceToken, unsupportedProviderOperation } from './provider-bridge.js';
|
|
8
|
+
import { resourceIdentityNumber } from './resource-identity.js';
|
|
9
|
+
import { taskIssueIdentity, taskIssueIdentityError } from './task-identities.js';
|
|
10
|
+
function providerCommentId(id, provider) {
|
|
11
|
+
return provider.identity?.comment === 'number' && /^\d+$/.test(id) ? Number(id) : id;
|
|
12
|
+
}
|
|
8
13
|
const MARKERS = {
|
|
9
14
|
task: (taskId) => `<!-- sync-issue:${taskId}:task -->`,
|
|
10
15
|
artifact: (taskId, stem) => `<!-- sync-issue:${taskId}:${stem} -->`,
|
|
@@ -137,7 +142,7 @@ function flattenComments(value) {
|
|
|
137
142
|
if (!Array.isArray(value))
|
|
138
143
|
return [];
|
|
139
144
|
const flattened = value.flatMap((entry) => Array.isArray(entry) ? entry : [entry]);
|
|
140
|
-
return flattened.filter((entry) => Boolean(entry && typeof entry === 'object' && typeof entry.id === 'number' && typeof entry.body === 'string'));
|
|
145
|
+
return flattened.filter((entry) => Boolean(entry && typeof entry === 'object' && (typeof entry.id === 'number' || typeof entry.id === 'string') && typeof entry.body === 'string'));
|
|
141
146
|
}
|
|
142
147
|
function issueNumberFromTask(content) {
|
|
143
148
|
const value = parseTaskFrontmatter(content).issue_number;
|
|
@@ -246,7 +251,7 @@ function writeComment(client, repo, issue, cwd, body, id) {
|
|
|
246
251
|
const endpoint = id ? `repos/${repo}/issues/comments/${id}` : `repos/${repo}/issues/${issue}/comments`;
|
|
247
252
|
return client.json(['api', endpoint, '-X', id ? 'PATCH' : 'POST', '--input', '-'], { cwd, method: id ? 'PATCH' : 'POST', input: JSON.stringify({ body }) });
|
|
248
253
|
}
|
|
249
|
-
function syncPlatformComment(taskRef, options) {
|
|
254
|
+
async function syncPlatformComment(taskRef, options) {
|
|
250
255
|
const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
|
|
251
256
|
if (!resolved.ok) {
|
|
252
257
|
return platformResult('failed', {
|
|
@@ -254,17 +259,35 @@ function syncPlatformComment(taskRef, options) {
|
|
|
254
259
|
});
|
|
255
260
|
}
|
|
256
261
|
const taskContent = fs.readFileSync(resolved.taskMdPath, 'utf8');
|
|
257
|
-
|
|
258
|
-
|
|
262
|
+
let issueIdentityFromTask;
|
|
263
|
+
try {
|
|
264
|
+
issueIdentityFromTask = taskIssueIdentity(parseTaskFrontmatter(taskContent), undefined, options.runtimeVersion);
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
return platformResult('failed', { error: { ...taskIssueIdentityError(error), retryable: false } });
|
|
268
|
+
}
|
|
269
|
+
if (!issueIdentityFromTask) {
|
|
259
270
|
return platformResult('no-op', {
|
|
260
271
|
error: { code: 'ISSUE_NOT_LINKED', message: 'Task has no valid issue_number', retryable: false }
|
|
261
272
|
});
|
|
262
273
|
}
|
|
263
|
-
const
|
|
264
|
-
|
|
274
|
+
const loaded = await resolvePlatformProviderContext({ cwd: resolved.repoRoot, client: options.client });
|
|
275
|
+
const context = loaded.ok ? loaded.value.context : loaded.context;
|
|
276
|
+
if (!hasResolvedPlatformContext(context) || !loaded.ok)
|
|
265
277
|
return context;
|
|
266
|
-
const
|
|
267
|
-
const listed =
|
|
278
|
+
const issue = resourceIdentityNumber(issueIdentityFromTask);
|
|
279
|
+
const listed = loaded.value.provider.comments?.list
|
|
280
|
+
? await loaded.value.provider.comments.list({
|
|
281
|
+
context: providerOperationContext(loaded.value),
|
|
282
|
+
parent: issueIdentityFromTask
|
|
283
|
+
}).then((response) => response.ok
|
|
284
|
+
? { ok: true, value: response.value.map((comment) => ({
|
|
285
|
+
id: providerCommentId(comment.id, loaded.value.provider),
|
|
286
|
+
body: comment.body,
|
|
287
|
+
user: comment.author?.name ? { login: comment.author.name } : undefined
|
|
288
|
+
})) }
|
|
289
|
+
: response)
|
|
290
|
+
: unsupportedProviderOperation(loaded.value.provider, 'comments.list');
|
|
268
291
|
if (!listed.ok) {
|
|
269
292
|
return platformResult(listed.error.retryable ? 'blocked' : 'failed', {
|
|
270
293
|
...contextFields(context), resource: { kind: 'issue', number: issue }, error: listed.error
|
|
@@ -310,7 +333,6 @@ function syncPlatformComment(taskRef, options) {
|
|
|
310
333
|
error: null
|
|
311
334
|
});
|
|
312
335
|
}
|
|
313
|
-
const repo = context.platform.repository;
|
|
314
336
|
const operations = [];
|
|
315
337
|
const ids = [];
|
|
316
338
|
for (const item of desired) {
|
|
@@ -320,16 +342,18 @@ function syncPlatformComment(taskRef, options) {
|
|
|
320
342
|
operations.push({ name: `comment:${item.marker}`, status: 'no-op', reasonCode: null });
|
|
321
343
|
continue;
|
|
322
344
|
}
|
|
323
|
-
const written =
|
|
345
|
+
const written = loaded.value.provider.comments?.write
|
|
346
|
+
? await loaded.value.provider.comments.write({
|
|
347
|
+
context: providerOperationContext(loaded.value),
|
|
348
|
+
parent: issueIdentityFromTask,
|
|
349
|
+
body: item.body,
|
|
350
|
+
...(current ? { existingComment: { kind: 'id', value: String(current.id) } } : {}),
|
|
351
|
+
mutation: { idempotencyKey: `comment:${resolved.taskId}:${item.marker}` }
|
|
352
|
+
})
|
|
353
|
+
: unsupportedProviderOperation(loaded.value.provider, 'comments.write');
|
|
324
354
|
if (!written.ok) {
|
|
325
355
|
if (!current && written.error.retryable) {
|
|
326
|
-
|
|
327
|
-
const found = reconciled.ok ? findMarkerComments(reconciled.value, item.marker) : [];
|
|
328
|
-
if (found.length === 1) {
|
|
329
|
-
ids.push(found[0].id);
|
|
330
|
-
operations.push({ name: `comment:${item.marker}`, status: 'applied', reasonCode: 'CREATE_RECONCILED' });
|
|
331
|
-
continue;
|
|
332
|
-
}
|
|
356
|
+
// A provider owns reconciliation because only it knows how to address the resource.
|
|
333
357
|
}
|
|
334
358
|
return platformResult(written.error.retryable ? 'blocked' : 'failed', {
|
|
335
359
|
...contextFields(context),
|
|
@@ -338,15 +362,20 @@ function syncPlatformComment(taskRef, options) {
|
|
|
338
362
|
error: written.error
|
|
339
363
|
});
|
|
340
364
|
}
|
|
341
|
-
ids.push(
|
|
365
|
+
ids.push(providerCommentId(written.value.remoteId, loaded.value.provider));
|
|
342
366
|
operations.push({ name: `comment:${item.marker}`, status: 'applied', reasonCode: null });
|
|
343
367
|
}
|
|
344
368
|
const desiredMarkers = new Set(desired.map((item) => item.marker));
|
|
345
369
|
const stale = existing.filter((comment) => !desiredMarkers.has(normalizeCommentContent(comment.body).split('\n', 1)[0]));
|
|
346
370
|
for (const comment of stale) {
|
|
347
|
-
const deleted =
|
|
348
|
-
|
|
349
|
-
|
|
371
|
+
const deleted = loaded.value.provider.comments?.delete
|
|
372
|
+
? await loaded.value.provider.comments.delete({
|
|
373
|
+
context: providerOperationContext(loaded.value),
|
|
374
|
+
parent: issueIdentityFromTask,
|
|
375
|
+
comment: { kind: 'id', value: String(comment.id) },
|
|
376
|
+
mutation: { idempotencyKey: `comment-delete:${resolved.taskId}:${comment.id}` }
|
|
377
|
+
})
|
|
378
|
+
: unsupportedProviderOperation(loaded.value.provider, 'comments.delete');
|
|
350
379
|
if (!deleted.ok) {
|
|
351
380
|
return platformResult(deleted.error.retryable ? 'blocked' : 'failed', {
|
|
352
381
|
...contextFields(context),
|
|
@@ -367,31 +396,55 @@ function syncPlatformComment(taskRef, options) {
|
|
|
367
396
|
error: null
|
|
368
397
|
});
|
|
369
398
|
}
|
|
370
|
-
function listPlatformComments(issue, cwd = process.cwd(), client
|
|
371
|
-
const
|
|
372
|
-
|
|
399
|
+
async function listPlatformComments(issue, cwd = process.cwd(), client) {
|
|
400
|
+
const loaded = await resolvePlatformProviderContext({ cwd, client });
|
|
401
|
+
const context = loaded.ok ? loaded.value.context : loaded.context;
|
|
402
|
+
if (!hasResolvedPlatformContext(context) || !loaded.ok)
|
|
373
403
|
return context;
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
404
|
+
let identity;
|
|
405
|
+
try {
|
|
406
|
+
identity = loaded.ok ? providerResourceToken(loaded.value.provider, 'issue', String(issue)) : null;
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
return platformResult('failed', { ...contextFields(context), error: { code: 'PLATFORM_IDENTITY_TOKEN_INVALID', message: error instanceof Error ? error.message : String(error), retryable: false } });
|
|
410
|
+
}
|
|
411
|
+
if (!loaded.ok || !identity)
|
|
412
|
+
return context;
|
|
413
|
+
const listed = loaded.value.provider.comments?.list
|
|
414
|
+
? await loaded.value.provider.comments.list({ context: providerOperationContext(loaded.value), parent: identity }).then((response) => response.ok
|
|
415
|
+
? { ok: true, value: response.value.map((comment) => ({ id: comment.id, body: comment.body, user: comment.author?.name ? { login: comment.author.name } : undefined })) }
|
|
416
|
+
: response)
|
|
417
|
+
: unsupportedProviderOperation(loaded.value.provider, 'comments.list');
|
|
418
|
+
if (!listed.ok) {
|
|
419
|
+
return platformResult(providerStatus(listed.error), {
|
|
420
|
+
...contextFields(context), resource: { kind: 'issue', number: resourceIdentityNumber(identity), identity }, error: providerError(listed.error, 'PLATFORM_PROVIDER_OPERATION_FAILED')
|
|
378
421
|
});
|
|
379
422
|
}
|
|
380
|
-
return { ...platformResult('no-op', { ...contextFields(context), resource: { kind: 'issue', number:
|
|
423
|
+
return { ...platformResult('no-op', { ...contextFields(context), resource: { kind: 'issue', number: resourceIdentityNumber(identity), identity }, error: null }), comments: listed.value };
|
|
381
424
|
}
|
|
382
|
-
function checkPlatformCommentOwner(taskRef, options = {}) {
|
|
425
|
+
async function checkPlatformCommentOwner(taskRef, options = {}) {
|
|
383
426
|
const resolved = resolveTaskRef(taskRef, options.cwd ? { repoRoot: options.cwd } : {});
|
|
384
427
|
if (!resolved.ok)
|
|
385
428
|
return platformResult('failed', { error: { code: resolved.code, message: resolved.message, retryable: false } });
|
|
386
429
|
const content = fs.readFileSync(resolved.taskMdPath, 'utf8');
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
430
|
+
let issueIdentity;
|
|
431
|
+
try {
|
|
432
|
+
issueIdentity = taskIssueIdentity(parseTaskFrontmatter(content), undefined, options.runtimeVersion);
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
return platformResult('failed', { error: { ...taskIssueIdentityError(error), retryable: false } });
|
|
436
|
+
}
|
|
437
|
+
if (!issueIdentity)
|
|
438
|
+
return platformResult('no-op', { error: { code: 'ISSUE_NOT_LINKED', message: 'Task has no valid platform issue identity', retryable: false } });
|
|
439
|
+
const loaded = await resolvePlatformProviderContext({ cwd: resolved.repoRoot, client: options.client });
|
|
440
|
+
const context = loaded.ok ? loaded.value.context : loaded.context;
|
|
441
|
+
if (!hasResolvedPlatformContext(context) || !loaded.ok)
|
|
393
442
|
return context;
|
|
394
|
-
const listed =
|
|
443
|
+
const listed = loaded.value.provider.comments?.list
|
|
444
|
+
? await loaded.value.provider.comments.list({ context: providerOperationContext(loaded.value), parent: issueIdentity }).then((response) => response.ok
|
|
445
|
+
? { ok: true, value: response.value.map((comment) => ({ id: comment.id, body: comment.body, user: comment.author?.name ? { login: comment.author.name } : undefined })) }
|
|
446
|
+
: response)
|
|
447
|
+
: unsupportedProviderOperation(loaded.value.provider, 'comments.list');
|
|
395
448
|
if (!listed.ok)
|
|
396
449
|
return platformResult(listed.error.retryable ? 'blocked' : 'failed', { ...contextFields(context), error: listed.error });
|
|
397
450
|
const matches = findMarkerComments(listed.value, MARKERS.task(resolved.taskId));
|
|
@@ -401,11 +454,11 @@ function checkPlatformCommentOwner(taskRef, options = {}) {
|
|
|
401
454
|
if (owner && owner !== context.platform.currentUser && !context.capabilities.triage) {
|
|
402
455
|
return platformResult('blocked', {
|
|
403
456
|
...contextFields(context),
|
|
404
|
-
resource: { kind: 'issue', number:
|
|
457
|
+
resource: { kind: 'issue', number: resourceIdentityNumber(issueIdentity), identity: issueIdentity },
|
|
405
458
|
error: { code: 'COMMENT_OWNER_CONFLICT', message: `Task comment is owned by '${owner}'`, retryable: false }
|
|
406
459
|
});
|
|
407
460
|
}
|
|
408
|
-
return platformResult('no-op', { ...contextFields(context), resource: { kind: 'issue', number:
|
|
461
|
+
return platformResult('no-op', { ...contextFields(context), resource: { kind: 'issue', number: resourceIdentityNumber(issueIdentity), identity: issueIdentity }, error: null });
|
|
409
462
|
}
|
|
410
463
|
export { MARKERS, chunkArtifactComment, findMarkerComments, listRemoteComments, checkPlatformCommentOwner, listPlatformComments, normalizeCommentContent, renderTaskComment, syncPlatformComment, validateRelatedMarkerSet, writeComment };
|
|
411
464
|
//# sourceMappingURL=issue-comments.js.map
|