@fitlab-ai/agent-infra 0.9.12 → 0.9.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/README.zh-CN.md +11 -11
- package/bin/cli.ts +26 -9
- package/dist/bin/cli.js +173 -157
- package/dist/bin/internal-cli.js +66 -40
- package/dist/lib/agent-client.js +5 -0
- package/dist/lib/agent-clients/next-steps.js +6 -1
- package/dist/lib/decide.js +3 -3
- package/dist/lib/internal/agent-client.js +5 -2
- package/dist/lib/internal/cli-route-inventory.js +152 -0
- package/dist/lib/internal/codex-lifecycle.js +9 -6
- package/dist/lib/internal/codex-sandbox-controller.js +8 -2
- package/dist/lib/internal/git-workflow.js +10 -6
- package/dist/lib/internal/platform-checks.js +19 -7
- package/dist/lib/internal/platform-comment.js +25 -13
- package/dist/lib/internal/platform-context.js +6 -3
- package/dist/lib/internal/platform-issue.js +20 -13
- package/dist/lib/internal/platform-metadata.js +88 -0
- package/dist/lib/internal/platform-pr-review.js +26 -13
- package/dist/lib/internal/platform-pr.js +84 -31
- package/dist/lib/internal/platform-release-notes.js +9 -6
- package/dist/lib/internal/platform-security.js +93 -0
- package/dist/lib/internal/pr-review-grade.js +25 -12
- package/dist/lib/internal/release-workflow.js +23 -9
- package/dist/lib/internal/sandbox-control.js +50 -7
- package/dist/lib/internal/task-activity.js +16 -7
- package/dist/lib/internal/task-artifact.js +235 -24
- package/dist/lib/internal/task-context.js +4 -1
- package/dist/lib/internal/task-create.js +50 -17
- package/dist/lib/internal/task-delivery.js +4 -1
- package/dist/lib/internal/task-event.js +10 -4
- package/dist/lib/internal/task-finalization.js +6 -3
- package/dist/lib/internal/task-invalidation.js +63 -0
- package/dist/lib/internal/task-ledger.js +20 -6
- package/dist/lib/internal/task-lifecycle.js +6 -3
- package/dist/lib/internal/task-operation-registry.js +421 -0
- package/dist/lib/internal/task-orchestration.js +12 -0
- package/dist/lib/internal/task-override.js +14 -7
- package/dist/lib/internal/task-qualification.js +90 -0
- package/dist/lib/internal/task-review.js +7 -4
- package/dist/lib/internal/task-short-id.js +11 -1
- package/dist/lib/internal/task-snapshot.js +4 -1
- package/dist/lib/internal/task-validate.js +7 -2
- package/dist/lib/internal/task-verify.js +11 -7
- package/dist/lib/internal/task-warning.js +11 -4
- package/dist/lib/platform/adapters.js +1 -3
- package/dist/lib/platform/change-request-git-evidence.js +27 -7
- package/dist/lib/platform/comment-safety.js +226 -0
- package/dist/lib/platform/completion-backfill.js +6 -5
- package/dist/lib/platform/context.js +70 -130
- package/dist/lib/platform/github-client.js +1 -1
- package/dist/lib/platform/github-provider.js +1130 -0
- package/dist/lib/platform/in-label-sync.js +143 -0
- package/dist/lib/platform/issue-comments.js +237 -72
- package/dist/lib/platform/issues.js +335 -189
- package/dist/lib/platform/metadata-labels.js +6 -2
- package/dist/lib/platform/none-provider.js +28 -0
- package/dist/lib/platform/pr-change-report.js +545 -0
- package/dist/lib/platform/pr-checks.js +119 -104
- package/dist/lib/platform/pr-review.js +88 -72
- package/dist/lib/platform/pr-summary.js +541 -50
- package/dist/lib/platform/provider-bridge.js +45 -0
- package/dist/lib/platform/provider-contract.d.ts +553 -0
- package/dist/lib/platform/provider-contract.js +99 -0
- package/dist/lib/platform/provider-loader.js +251 -0
- package/dist/lib/platform/provider-validation.js +577 -0
- package/dist/lib/platform/pull-request-metadata.js +8 -6
- package/dist/lib/platform/pull-requests.js +734 -543
- package/dist/lib/platform/release-notes.js +78 -55
- package/dist/lib/platform/releases.js +79 -50
- package/dist/lib/platform/repository-metadata.js +377 -0
- package/dist/lib/platform/resource-identity.d.ts +26 -0
- package/dist/lib/platform/resource-identity.js +92 -0
- package/dist/lib/platform/security-alerts.js +155 -0
- package/dist/lib/platform/task-identities.js +31 -0
- package/dist/lib/platform/verification-required.js +11 -12
- package/dist/lib/platform/verification-sync.js +129 -248
- package/dist/lib/pr-review/evidence-grading.js +19 -6
- package/dist/lib/process-data/index.js +7 -0
- package/dist/lib/run/index.js +68 -23
- package/dist/lib/sandbox/commands/control-status.js +22 -0
- package/dist/lib/sandbox/commands/create.js +32 -6
- package/dist/lib/sandbox/commands/ls.js +5 -0
- package/dist/lib/sandbox/commands/rm.js +827 -120
- package/dist/lib/sandbox/commands/show.js +16 -0
- package/dist/lib/sandbox/control/client.js +174 -19
- package/dist/lib/sandbox/control/completed-reentry.js +85 -0
- package/dist/lib/sandbox/control/container-identity.js +28 -31
- package/dist/lib/sandbox/control/executor.js +151 -16
- package/dist/lib/sandbox/control/lifecycle.js +621 -127
- package/dist/lib/sandbox/control/native-file-lock.js +177 -0
- package/dist/lib/sandbox/control/protocol.js +77 -0
- package/dist/lib/sandbox/control/server.js +677 -34
- package/dist/lib/sandbox/control/state.js +209 -4
- package/dist/lib/sandbox/control/task-view.js +183 -0
- package/dist/lib/sandbox/engines/authority.js +289 -0
- package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
- package/dist/lib/sandbox/index.js +5 -0
- package/dist/lib/sandbox/recovery.js +21 -1
- package/dist/lib/sandbox/workspace-view.js +2 -1
- package/dist/lib/sandbox/worktree-safety.js +4 -1
- package/dist/lib/server/index.js +8 -0
- package/dist/lib/server/protocol.js +38 -1
- package/dist/lib/task/activity-log.js +8 -1
- package/dist/lib/task/artifact-lifecycle.js +75 -18
- package/dist/lib/task/artifact-operations.js +520 -0
- package/dist/lib/task/artifact-repair-intent.js +59 -0
- package/dist/lib/task/artifact-schema.js +135 -0
- package/dist/lib/task/capabilities.js +310 -0
- package/dist/lib/task/commands/status.js +32 -0
- package/dist/lib/task/commit-operation.js +12 -1
- package/dist/lib/task/control-authority.js +12 -5
- package/dist/lib/task/create-service.js +111 -12
- package/dist/lib/task/create.js +25 -0
- package/dist/lib/task/current-contract.js +5 -1
- package/dist/lib/task/decision-details.js +1 -1
- package/dist/lib/task/events.js +416 -17
- package/dist/lib/task/finalization.js +37 -13
- package/dist/lib/task/human-override.js +58 -36
- package/dist/lib/task/index.js +11 -3
- package/dist/lib/task/invalidation-command.js +86 -0
- package/dist/lib/task/invalidation.js +260 -0
- package/dist/lib/task/ledger-intents.js +37 -0
- package/dist/lib/task/local-artifact-finalization.js +299 -0
- package/dist/lib/task/orchestration.js +240 -144
- package/dist/lib/task/pr-delivery-fact.js +102 -101
- package/dist/lib/task/qualification-audit.js +490 -0
- package/dist/lib/task/qualification-confirmation.js +109 -0
- package/dist/lib/task/qualification-intents.js +148 -0
- package/dist/lib/task/review-artifacts.js +22 -23
- package/dist/lib/task/review-finalization.js +121 -4
- package/dist/lib/task/review-fingerprint.js +24 -2
- package/dist/lib/task/rework-intent.js +138 -0
- package/dist/lib/task/sections.js +6 -4
- package/dist/lib/task/skill-scope.js +23 -0
- package/dist/lib/task/task-execution-lock.js +27 -17
- package/dist/lib/task/verification-config.js +11 -0
- package/dist/lib/task/verification-engine.js +93 -16
- package/dist/lib/task/verification.js +3 -3
- package/dist/lib/task/workflow-warning-intents.js +1 -1
- package/dist/lib/task/write.js +11 -0
- package/dist/lib/version.js +11 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +9 -0
- package/lib/agent-clients/next-steps.ts +6 -1
- package/lib/decide.ts +3 -3
- package/lib/init.ts +1 -1
- package/lib/internal/agent-client.ts +4 -2
- package/lib/internal/cli-route-inventory.ts +140 -0
- package/lib/internal/codex-lifecycle.ts +8 -6
- package/lib/internal/codex-sandbox-controller.ts +7 -2
- package/lib/internal/git-workflow.ts +9 -6
- package/lib/internal/platform-checks.ts +14 -6
- package/lib/internal/platform-comment.ts +20 -12
- package/lib/internal/platform-context.ts +5 -3
- package/lib/internal/platform-issue.ts +17 -11
- package/lib/internal/platform-metadata.ts +70 -0
- package/lib/internal/platform-pr-review.ts +23 -12
- package/lib/internal/platform-pr.ts +65 -27
- package/lib/internal/platform-release-notes.ts +8 -6
- package/lib/internal/platform-security.ts +83 -0
- package/lib/internal/pr-review-grade.ts +20 -11
- package/lib/internal/release-workflow.ts +21 -9
- package/lib/internal/sandbox-control.ts +44 -6
- package/lib/internal/task-activity.ts +15 -7
- package/lib/internal/task-artifact.ts +204 -22
- package/lib/internal/task-context.ts +3 -1
- package/lib/internal/task-create.ts +78 -17
- package/lib/internal/task-delivery.ts +3 -1
- package/lib/internal/task-event.ts +9 -4
- package/lib/internal/task-finalization.ts +6 -4
- package/lib/internal/task-invalidation.ts +41 -0
- package/lib/internal/task-ledger.ts +21 -8
- package/lib/internal/task-lifecycle.ts +5 -3
- package/lib/internal/task-operation-registry.ts +482 -0
- package/lib/internal/task-orchestration.ts +12 -0
- package/lib/internal/task-override.ts +15 -9
- package/lib/internal/task-qualification.ts +61 -0
- package/lib/internal/task-review.ts +6 -4
- package/lib/internal/task-short-id.ts +10 -1
- package/lib/internal/task-snapshot.ts +3 -1
- package/lib/internal/task-validate.ts +6 -2
- package/lib/internal/task-verify.ts +10 -7
- package/lib/internal/task-warning.ts +10 -4
- package/lib/platform/adapters.ts +3 -2
- package/lib/platform/change-request-git-evidence.ts +36 -9
- package/lib/platform/comment-safety.ts +250 -0
- package/lib/platform/completion-backfill.ts +9 -8
- package/lib/platform/context.ts +97 -134
- package/lib/platform/github-client.ts +2 -2
- package/lib/platform/github-provider.ts +1132 -0
- package/lib/platform/in-label-sync.ts +208 -0
- package/lib/platform/issue-comments.ts +255 -80
- package/lib/platform/issues.ts +344 -174
- package/lib/platform/metadata-labels.ts +5 -2
- package/lib/platform/none-provider.ts +35 -0
- package/lib/platform/pr-change-report.ts +639 -0
- package/lib/platform/pr-checks.ts +126 -106
- package/lib/platform/pr-review.ts +88 -85
- package/lib/platform/pr-summary.ts +581 -53
- package/lib/platform/provider-bridge.ts +82 -0
- package/lib/platform/provider-contract.ts +611 -0
- package/lib/platform/provider-loader.ts +307 -0
- package/lib/platform/provider-validation.ts +611 -0
- package/lib/platform/pull-request-metadata.ts +10 -7
- package/lib/platform/pull-requests.ts +781 -550
- package/lib/platform/release-notes.ts +76 -59
- package/lib/platform/releases.ts +77 -43
- package/lib/platform/repository-metadata.ts +453 -0
- package/lib/platform/resource-identity.ts +121 -0
- package/lib/platform/security-alerts.ts +191 -0
- package/lib/platform/task-identities.ts +40 -0
- package/lib/platform/types.ts +4 -2
- package/lib/platform/verification-required.ts +11 -13
- package/lib/platform/verification-sync.ts +128 -304
- package/lib/pr-review/evidence-grading.ts +25 -8
- package/lib/process-data/index.ts +7 -0
- package/lib/run/index.ts +62 -22
- package/lib/sandbox/commands/control-status.ts +26 -0
- package/lib/sandbox/commands/create.ts +46 -6
- package/lib/sandbox/commands/ls.ts +7 -0
- package/lib/sandbox/commands/rm.ts +1000 -87
- package/lib/sandbox/commands/show.ts +16 -0
- package/lib/sandbox/control/client.ts +203 -19
- package/lib/sandbox/control/completed-reentry.ts +98 -0
- package/lib/sandbox/control/container-identity.ts +27 -43
- package/lib/sandbox/control/executor.ts +180 -15
- package/lib/sandbox/control/lifecycle.ts +629 -17
- package/lib/sandbox/control/native-file-lock.ts +209 -0
- package/lib/sandbox/control/protocol.ts +118 -2
- package/lib/sandbox/control/server.ts +724 -34
- package/lib/sandbox/control/state.ts +257 -4
- package/lib/sandbox/control/task-view.ts +240 -0
- package/lib/sandbox/engines/authority.ts +365 -0
- package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
- package/lib/sandbox/index.ts +7 -0
- package/lib/sandbox/recovery.ts +21 -1
- package/lib/sandbox/workspace-view.ts +9 -3
- package/lib/sandbox/worktree-safety.ts +4 -1
- package/lib/server/index.ts +10 -0
- package/lib/server/protocol.ts +36 -1
- package/lib/task/activity-log.ts +8 -0
- package/lib/task/artifact-lifecycle.ts +70 -22
- package/lib/task/artifact-operations.ts +626 -0
- package/lib/task/artifact-repair-intent.ts +71 -0
- package/lib/task/artifact-schema.ts +192 -0
- package/lib/task/capabilities.ts +331 -0
- package/lib/task/commands/status.ts +38 -0
- package/lib/task/commit-operation.ts +12 -1
- package/lib/task/control-authority.ts +22 -9
- package/lib/task/create-service.ts +139 -14
- package/lib/task/create.ts +27 -0
- package/lib/task/current-contract.ts +6 -1
- package/lib/task/decision-details.ts +6 -2
- package/lib/task/events.ts +392 -16
- package/lib/task/finalization.ts +50 -14
- package/lib/task/human-override.ts +70 -46
- package/lib/task/index.ts +16 -3
- package/lib/task/invalidation-command.ts +86 -0
- package/lib/task/invalidation.ts +332 -0
- package/lib/task/ledger-intents.ts +35 -1
- package/lib/task/local-artifact-finalization.ts +432 -0
- package/lib/task/orchestration.ts +223 -133
- package/lib/task/pr-delivery-fact.ts +131 -148
- package/lib/task/qualification-audit.ts +599 -0
- package/lib/task/qualification-confirmation.ts +117 -0
- package/lib/task/qualification-intents.ts +150 -0
- package/lib/task/review-artifacts.ts +21 -22
- package/lib/task/review-finalization.ts +133 -4
- package/lib/task/review-fingerprint.ts +23 -2
- package/lib/task/rework-intent.ts +165 -0
- package/lib/task/sections.ts +6 -4
- package/lib/task/skill-scope.ts +24 -0
- package/lib/task/task-execution-lock.ts +23 -14
- package/lib/task/verification-config.ts +12 -0
- package/lib/task/verification-engine.ts +103 -17
- package/lib/task/verification.ts +4 -4
- package/lib/task/workflow-warning-intents.ts +1 -1
- package/lib/task/write.ts +19 -0
- package/lib/update.ts +1 -1
- package/lib/version.ts +15 -1
- package/package.json +12 -1
- package/templates/.agents/rules/README.en.md +3 -1
- package/templates/.agents/rules/README.zh-CN.md +3 -1
- package/templates/.agents/rules/decision-qualification.en.md +22 -0
- package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
- package/templates/.agents/rules/evidence-reporting.en.md +28 -0
- package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
- package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +2 -0
- package/templates/.agents/rules/issue-sync.zh-CN.md +2 -0
- package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
- package/templates/.agents/rules/local-artifact-repair.en.md +13 -2
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +13 -2
- package/templates/.agents/rules/pr-sync.en.md +10 -4
- package/templates/.agents/rules/pr-sync.zh-CN.md +17 -4
- package/templates/.agents/rules/security-alerts.en.md +8 -8
- package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
- package/templates/.agents/rules/task-short-id.en.md +1 -4
- package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
- package/templates/.agents/skills/analyze-task/SKILL.en.md +28 -5
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +29 -5
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
- package/templates/.agents/skills/check-task/SKILL.en.md +16 -37
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
- package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.en.md +41 -9
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +43 -11
- package/templates/.agents/skills/code-task/config/verify.en.json +6 -14
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +6 -14
- package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
- package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +2 -0
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +3 -3
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +3 -3
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +10 -4
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +10 -4
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +4 -3
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +4 -3
- package/templates/.agents/skills/complete-task/SKILL.en.md +26 -21
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +25 -21
- package/templates/.agents/skills/create-pr/SKILL.en.md +7 -6
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +7 -7
- package/templates/.agents/skills/create-pr/config/verify.json +1 -0
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
- package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
- package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
- package/templates/.agents/skills/plan-task/SKILL.en.md +27 -4
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +26 -4
- package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
- package/templates/.agents/skills/review-analysis/SKILL.en.md +17 -4
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +17 -4
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-code/SKILL.en.md +18 -5
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +18 -5
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
- package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-plan/SKILL.en.md +17 -4
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +17 -4
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
- package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +9 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +9 -3
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
- package/templates/.agents/skills/test/SKILL.en.md +13 -2
- package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
- package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
- package/templates/.agents/templates/task.en.md +24 -1
- package/templates/.agents/templates/task.zh-CN.md +24 -1
- package/templates/.github/workflows/pr-label.yml +7 -26
- package/templates/.agents/scripts/security-alerts.github.sh +0 -151
- package/templates/.agents/scripts/security-alerts.sh +0 -31
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
|
@@ -42,7 +42,7 @@ function failed(taskId, error, overrides = {}) {
|
|
|
42
42
|
...overrides
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
|
-
function emptyReceipt(taskId) {
|
|
45
|
+
function emptyReceipt(taskId, controlBinding) {
|
|
46
46
|
return {
|
|
47
47
|
version: RECEIPT_VERSION,
|
|
48
48
|
taskId,
|
|
@@ -54,6 +54,7 @@ function emptyReceipt(taskId) {
|
|
|
54
54
|
verification: 'pending',
|
|
55
55
|
warningProjection: 'done',
|
|
56
56
|
warnings: [],
|
|
57
|
+
...(controlBinding ? { controlBinding } : {}),
|
|
57
58
|
updatedAt: now(),
|
|
58
59
|
lastError: null
|
|
59
60
|
};
|
|
@@ -79,6 +80,7 @@ function validateReceipt(value, taskId) {
|
|
|
79
80
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
80
81
|
throw new Error('receipt must be an object');
|
|
81
82
|
const receipt = value;
|
|
83
|
+
const controlBinding = receipt.controlBinding;
|
|
82
84
|
const states = ['pending', 'done', 'skipped'];
|
|
83
85
|
if (receipt.version !== RECEIPT_VERSION || receipt.taskId !== taskId || receipt.intent !== 'complete'
|
|
84
86
|
|| typeof receipt.receiptId !== 'string' || receipt.receiptId.length === 0
|
|
@@ -89,7 +91,11 @@ function validateReceipt(value, taskId) {
|
|
|
89
91
|
|| !['pending', 'done'].includes(String(receipt.warningProjection))
|
|
90
92
|
|| !Array.isArray(receipt.warnings) || receipt.warnings.some((warning) => !validWarning(warning))
|
|
91
93
|
|| typeof receipt.updatedAt !== 'string'
|
|
92
|
-
|| (receipt.lastError !== null && (typeof receipt.lastError !== 'object' || Array.isArray(receipt.lastError)))
|
|
94
|
+
|| (receipt.lastError !== null && (typeof receipt.lastError !== 'object' || Array.isArray(receipt.lastError)))
|
|
95
|
+
|| (receipt.controlBinding !== undefined && (!controlBinding || typeof controlBinding !== 'object'
|
|
96
|
+
|| Array.isArray(controlBinding)
|
|
97
|
+
|| typeof controlBinding.generation !== 'string' || controlBinding.generation.length === 0
|
|
98
|
+
|| typeof controlBinding.requestId !== 'string' || !/^[a-f0-9-]{16,64}$/u.test(controlBinding.requestId))))
|
|
93
99
|
throw new Error('receipt schema is invalid');
|
|
94
100
|
return receipt;
|
|
95
101
|
}
|
|
@@ -100,6 +106,13 @@ function readReceipt(repoRoot, taskId) {
|
|
|
100
106
|
const value = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
101
107
|
return validateReceipt(value, taskId);
|
|
102
108
|
}
|
|
109
|
+
function readTaskFinalizationReceipt(repoRoot, taskId) {
|
|
110
|
+
return readReceipt(path.resolve(repoRoot), taskId);
|
|
111
|
+
}
|
|
112
|
+
function controlBindingMatches(receipt, binding) {
|
|
113
|
+
return receipt.controlBinding?.generation === binding.generation
|
|
114
|
+
&& receipt.controlBinding.requestId === binding.requestId;
|
|
115
|
+
}
|
|
103
116
|
function writeReceipt(repoRoot, receipt) {
|
|
104
117
|
const directory = finalizationRoot(repoRoot);
|
|
105
118
|
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
@@ -346,7 +359,7 @@ function reconcileWarningProjection(repoRoot, taskId, receipt, consumed) {
|
|
|
346
359
|
return receipt;
|
|
347
360
|
}
|
|
348
361
|
}
|
|
349
|
-
function syncPendingTaskComment(input) {
|
|
362
|
+
async function syncPendingTaskComment(input) {
|
|
350
363
|
const { repoRoot, taskId, agent, commentSync, consumedCapabilities } = input;
|
|
351
364
|
let receipt = input.receipt;
|
|
352
365
|
if (receipt.taskComment !== 'pending') {
|
|
@@ -358,7 +371,7 @@ function syncPendingTaskComment(input) {
|
|
|
358
371
|
};
|
|
359
372
|
}
|
|
360
373
|
try {
|
|
361
|
-
const result = commentSync(taskId, { kind: 'task', agent, cwd: repoRoot });
|
|
374
|
+
const result = await commentSync(taskId, { kind: 'task', agent, cwd: repoRoot });
|
|
362
375
|
const step = commentStep(result);
|
|
363
376
|
if (result.status === 'applied' || result.status === 'no-op') {
|
|
364
377
|
const skipped = result.error?.code === 'ISSUE_NOT_LINKED';
|
|
@@ -416,7 +429,7 @@ function terminalResult(taskId, receipt, steps, changed, error = null) {
|
|
|
416
429
|
error: hardError ? error : postLifecyclePending ? null : error
|
|
417
430
|
};
|
|
418
431
|
}
|
|
419
|
-
function applyUnderLock(request, taskId, options) {
|
|
432
|
+
async function applyUnderLock(request, taskId, options) {
|
|
420
433
|
const repoRoot = path.resolve(options.repoRoot);
|
|
421
434
|
const lifecycle = options.lifecycle ?? applyTaskLifecycle;
|
|
422
435
|
const commentSync = options.commentSync ?? syncPlatformComment;
|
|
@@ -426,17 +439,28 @@ function applyUnderLock(request, taskId, options) {
|
|
|
426
439
|
try {
|
|
427
440
|
const file = receiptPath(repoRoot, taskId);
|
|
428
441
|
const existed = fs.existsSync(file);
|
|
429
|
-
receipt = readReceipt(repoRoot, taskId) ?? emptyReceipt(taskId);
|
|
442
|
+
receipt = readReceipt(repoRoot, taskId) ?? emptyReceipt(taskId, options.controlBinding);
|
|
430
443
|
if (!existed)
|
|
431
444
|
writeReceipt(repoRoot, receipt);
|
|
432
445
|
}
|
|
433
446
|
catch (error) {
|
|
434
447
|
return failed(taskId, errorOf(error, 'TASK_FINALIZATION_RECEIPT_INVALID'));
|
|
435
448
|
}
|
|
449
|
+
if (options.controlBinding && !controlBindingMatches(receipt, options.controlBinding)) {
|
|
450
|
+
const error = {
|
|
451
|
+
code: 'TASK_FINALIZATION_CONTROL_BINDING_CONFLICT',
|
|
452
|
+
message: 'finalization receipt belongs to a different sandbox request or generation',
|
|
453
|
+
retryable: false
|
|
454
|
+
};
|
|
455
|
+
return failed(taskId, error, {
|
|
456
|
+
completedSteps: completedSteps(receipt),
|
|
457
|
+
pendingSteps: pendingSteps(receipt)
|
|
458
|
+
});
|
|
459
|
+
}
|
|
436
460
|
const preflightState = resolveTaskRef(taskId, { repoRoot });
|
|
437
461
|
if (options.preflight && preflightState.ok && preflightState.state === 'active') {
|
|
438
462
|
try {
|
|
439
|
-
const preflight = options.preflight({ taskRef: taskId, event: 'complete-task.preflight' }, { repoRoot });
|
|
463
|
+
const preflight = await options.preflight({ taskRef: taskId, event: 'complete-task.preflight' }, { repoRoot });
|
|
440
464
|
if (preflight.status !== 'pass') {
|
|
441
465
|
const detail = verificationFailure(preflight);
|
|
442
466
|
return failed(taskId, detail, {
|
|
@@ -510,7 +534,7 @@ function applyUnderLock(request, taskId, options) {
|
|
|
510
534
|
}
|
|
511
535
|
let taskComment = null;
|
|
512
536
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
513
|
-
const initialComment = syncPendingTaskComment({
|
|
537
|
+
const initialComment = await syncPendingTaskComment({
|
|
514
538
|
repoRoot, taskId, agent: request.agent, receipt, commentSync, consumedCapabilities
|
|
515
539
|
});
|
|
516
540
|
receipt = initialComment.receipt;
|
|
@@ -526,7 +550,7 @@ function applyUnderLock(request, taskId, options) {
|
|
|
526
550
|
verification = { status: 'no-op', changed: false, error: null };
|
|
527
551
|
}
|
|
528
552
|
else {
|
|
529
|
-
const result = verify({ taskRef: taskId, event: 'complete-task.completed' }, { repoRoot });
|
|
553
|
+
const result = await verify({ taskRef: taskId, event: 'complete-task.completed' }, { repoRoot });
|
|
530
554
|
verification = verificationStep(result);
|
|
531
555
|
if (result.status === 'pass') {
|
|
532
556
|
const capability = issueCapability(receipt, 'verification');
|
|
@@ -534,7 +558,7 @@ function applyUnderLock(request, taskId, options) {
|
|
|
534
558
|
scope: 'verification', operation: 'succeeded'
|
|
535
559
|
}, consumedCapabilities);
|
|
536
560
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
537
|
-
const finalComment = syncPendingTaskComment({
|
|
561
|
+
const finalComment = await syncPendingTaskComment({
|
|
538
562
|
repoRoot, taskId, agent: request.agent, receipt, commentSync, consumedCapabilities
|
|
539
563
|
});
|
|
540
564
|
receipt = finalComment.receipt;
|
|
@@ -571,7 +595,7 @@ function applyUnderLock(request, taskId, options) {
|
|
|
571
595
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
572
596
|
return terminalResult(taskId, receipt, { lifecycle: lifecycleResult, taskComment, verification }, changed);
|
|
573
597
|
}
|
|
574
|
-
function applyTaskFinalization(request, options) {
|
|
598
|
+
async function applyTaskFinalization(request, options) {
|
|
575
599
|
if (request.intent !== 'complete' || !request.taskRef || !request.agent) {
|
|
576
600
|
return failed(null, { code: 'TASK_FINALIZATION_PAYLOAD_INVALID', message: 'complete finalization requires taskRef and agent', retryable: false });
|
|
577
601
|
}
|
|
@@ -580,7 +604,7 @@ function applyTaskFinalization(request, options) {
|
|
|
580
604
|
if (!resolved.ok)
|
|
581
605
|
return failed(resolved.taskId, { code: resolved.code, message: resolved.message, retryable: false });
|
|
582
606
|
try {
|
|
583
|
-
return withTaskExecutionLock(repoRoot, resolved.taskId, 'task-finalization.complete', () => applyUnderLock(request, resolved.taskId, options));
|
|
607
|
+
return await withTaskExecutionLock(repoRoot, resolved.taskId, 'task-finalization.complete', () => applyUnderLock(request, resolved.taskId, options));
|
|
584
608
|
}
|
|
585
609
|
catch (error) {
|
|
586
610
|
const detail = error instanceof TaskExecutionLockError
|
|
@@ -589,5 +613,5 @@ function applyTaskFinalization(request, options) {
|
|
|
589
613
|
return failed(resolved.taskId, detail);
|
|
590
614
|
}
|
|
591
615
|
}
|
|
592
|
-
export { applyFinalizationReceiptMutation, applyTaskFinalization, issueCapability as createFinalizationCapability };
|
|
616
|
+
export { applyFinalizationReceiptMutation, applyTaskFinalization, issueCapability as createFinalizationCapability, readTaskFinalizationReceipt };
|
|
593
617
|
//# sourceMappingURL=finalization.js.map
|
|
@@ -20,6 +20,8 @@ import { verifyTaskEvent } from './verification.js';
|
|
|
20
20
|
import { verifyInProcess } from './verification-engine.js';
|
|
21
21
|
import { canonicalTimestamp, writeTask } from './write.js';
|
|
22
22
|
import { readPrDeliveryFact } from './pr-delivery-fact.js';
|
|
23
|
+
import { resourceIdentity, resourceIdentityNumber } from '../platform/provider-bridge.js';
|
|
24
|
+
import { taskIssueIdentity } from '../platform/task-identities.js';
|
|
23
25
|
const LIFECYCLE_PRODUCER = 'lifecycle.apply';
|
|
24
26
|
const HUMAN_OVERRIDE_SECTION_ALIASES = ['人工豁免账本', 'Human Override Ledger'];
|
|
25
27
|
const HUMAN_OVERRIDE_COLUMNS = [
|
|
@@ -402,13 +404,20 @@ function snapshotEvidence(taskId, failureIdValue, target, content, frontmatter,
|
|
|
402
404
|
}
|
|
403
405
|
function resourceForSnapshot(policy, options, frontmatter) {
|
|
404
406
|
if (policy.producerId === 'platform.issue') {
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
+
const identity = options.probeIssueNumber !== undefined
|
|
408
|
+
? resourceIdentity(options.probeIssueNumber)
|
|
409
|
+
: taskIssueIdentity((frontmatter || {})) || (() => {
|
|
410
|
+
const number = toPositiveInteger(frontmatter?.issue_number);
|
|
411
|
+
return number === null ? null : resourceIdentity(number);
|
|
412
|
+
})();
|
|
413
|
+
return identity ? { kind: 'issue', identity, number: resourceIdentityNumber(identity) } : null;
|
|
407
414
|
}
|
|
408
415
|
if (policy.producerId === 'platform.pull-request') {
|
|
409
416
|
const fact = frontmatter ? readPrDeliveryFact(frontmatter) : null;
|
|
410
|
-
const
|
|
411
|
-
|
|
417
|
+
const identity = options.probePullRequestNumber !== undefined
|
|
418
|
+
? resourceIdentity(options.probePullRequestNumber)
|
|
419
|
+
: fact?.status === 'valid' && fact.fact.state === 'bound' ? fact.fact.identity.resource : null;
|
|
420
|
+
return identity ? { kind: 'pull-request', identity, number: resourceIdentityNumber(identity) } : null;
|
|
412
421
|
}
|
|
413
422
|
return null;
|
|
414
423
|
}
|
|
@@ -461,7 +470,7 @@ function probeResult(policy, result, state) {
|
|
|
461
470
|
function probeNotObserved(policy) {
|
|
462
471
|
return error('OVERRIDE_FAILURE_NOT_PRESENT', `producer ${policy.producerId} did not produce ${policy.code}`);
|
|
463
472
|
}
|
|
464
|
-
function probePlatformFailure(taskRef, policy, resolved, options) {
|
|
473
|
+
async function probePlatformFailure(taskRef, policy, resolved, options) {
|
|
465
474
|
let frontmatter;
|
|
466
475
|
try {
|
|
467
476
|
frontmatter = parseTypedTaskFrontmatter(fs.readFileSync(path.join(resolved.taskDir, 'task.md'), 'utf8'));
|
|
@@ -469,30 +478,40 @@ function probePlatformFailure(taskRef, policy, resolved, options) {
|
|
|
469
478
|
catch (cause) {
|
|
470
479
|
return error('OVERRIDE_DOCUMENT_INVALID', cause instanceof Error ? cause.message : String(cause));
|
|
471
480
|
}
|
|
472
|
-
const
|
|
481
|
+
const issueIdentity = options.probeIssueNumber !== undefined
|
|
482
|
+
? resourceIdentity(options.probeIssueNumber)
|
|
483
|
+
: taskIssueIdentity(frontmatter) || (() => {
|
|
484
|
+
const number = toPositiveInteger(frontmatter.issue_number);
|
|
485
|
+
return number === null ? null : resourceIdentity(number);
|
|
486
|
+
})();
|
|
473
487
|
const fact = readPrDeliveryFact(frontmatter);
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
|
|
488
|
+
const pullRequestIdentity = options.probePullRequestNumber !== undefined
|
|
489
|
+
? resourceIdentity(options.probePullRequestNumber)
|
|
490
|
+
: fact.status === 'valid' && fact.fact.state === 'bound' ? fact.fact.identity.resource : null;
|
|
491
|
+
const token = (identity) => identity ? String(identity.value) : null;
|
|
492
|
+
const issueToken = token(issueIdentity);
|
|
493
|
+
const pullRequestToken = token(pullRequestIdentity);
|
|
494
|
+
const operation = await (policy.producerId === 'platform.issue'
|
|
495
|
+
? issueToken === null
|
|
477
496
|
? null
|
|
478
497
|
: bindPlatformIssue(taskRef, {
|
|
479
|
-
issue:
|
|
498
|
+
issue: issueToken,
|
|
480
499
|
agent: options.probeOperator ?? 'local-operator',
|
|
481
500
|
dryRun: true,
|
|
482
501
|
cwd: resolved.repoRoot,
|
|
483
502
|
...(options.platformClient ? { client: options.platformClient } : {})
|
|
484
503
|
})
|
|
485
|
-
:
|
|
504
|
+
: pullRequestToken === null
|
|
486
505
|
? null
|
|
487
506
|
: bindPlatformPullRequest(taskRef, {
|
|
488
|
-
pr:
|
|
507
|
+
pr: pullRequestToken,
|
|
489
508
|
agent: options.probeOperator ?? 'local-operator',
|
|
490
509
|
dryRun: true,
|
|
491
510
|
cwd: resolved.repoRoot,
|
|
492
511
|
...(options.platformClient ? { client: options.platformClient } : {})
|
|
493
|
-
});
|
|
512
|
+
}));
|
|
494
513
|
if (!operation)
|
|
495
|
-
return error('OVERRIDE_PROBE_INPUT_MISSING', `${policy.producerId} requires a bound issue or pull request
|
|
514
|
+
return error('OVERRIDE_PROBE_INPUT_MISSING', `${policy.producerId} requires a bound issue or pull request identity`);
|
|
496
515
|
if (operation.status !== 'failed' && operation.status !== 'blocked')
|
|
497
516
|
return probeNotObserved(policy);
|
|
498
517
|
if (!operation.error)
|
|
@@ -530,6 +549,9 @@ function probeTaskEventFailure(taskRef, policy, resolved) {
|
|
|
530
549
|
event: candidate.event,
|
|
531
550
|
agent: 'codex',
|
|
532
551
|
dryRun: true,
|
|
552
|
+
initiator: 'model',
|
|
553
|
+
requestId: `override-probe:${taskRef}:${candidate.event}`,
|
|
554
|
+
reasonCode: 'user-request',
|
|
533
555
|
...(candidate.artifact ? { artifact: candidate.artifact } : {})
|
|
534
556
|
}, { repoRoot: resolved.repoRoot, lockAlreadyHeld: true });
|
|
535
557
|
const matched = probeResult(policy, result, resolved.state);
|
|
@@ -538,8 +560,8 @@ function probeTaskEventFailure(taskRef, policy, resolved) {
|
|
|
538
560
|
}
|
|
539
561
|
return probeNotObserved(policy);
|
|
540
562
|
}
|
|
541
|
-
function probeVerificationFailure(taskRef, policy, resolved) {
|
|
542
|
-
const result = verifyTaskEvent({
|
|
563
|
+
async function probeVerificationFailure(taskRef, policy, resolved) {
|
|
564
|
+
const result = await verifyTaskEvent({
|
|
543
565
|
taskRef,
|
|
544
566
|
event: 'review-code.completed',
|
|
545
567
|
artifact: policy.code === 'VERIFY_ARTIFACT_INVALID' ? 'invalid-artifact.md' : 'review-code.md'
|
|
@@ -562,7 +584,7 @@ function latestArtifact(taskDir, family) {
|
|
|
562
584
|
});
|
|
563
585
|
return candidates[0];
|
|
564
586
|
}
|
|
565
|
-
function probeVerificationEngineFailure(policy, resolved) {
|
|
587
|
+
async function probeVerificationEngineFailure(policy, resolved) {
|
|
566
588
|
const candidates = [
|
|
567
589
|
{ skillName: 'review-code', family: 'review-code' },
|
|
568
590
|
{ skillName: 'review-plan', family: 'review-plan' },
|
|
@@ -577,7 +599,7 @@ function probeVerificationEngineFailure(policy, resolved) {
|
|
|
577
599
|
if (candidate.family && !artifactFile)
|
|
578
600
|
continue;
|
|
579
601
|
try {
|
|
580
|
-
const payload = verifyInProcess({
|
|
602
|
+
const payload = await verifyInProcess({
|
|
581
603
|
mode: 'gate',
|
|
582
604
|
skillName: candidate.skillName,
|
|
583
605
|
taskDir: resolved.taskDir,
|
|
@@ -601,7 +623,7 @@ function probeVerificationEngineFailure(policy, resolved) {
|
|
|
601
623
|
}
|
|
602
624
|
return probeNotObserved(policy);
|
|
603
625
|
}
|
|
604
|
-
function probeGenericFailure(taskRef, policy, resolved, options = {}) {
|
|
626
|
+
async function probeGenericFailure(taskRef, policy, resolved, options = {}) {
|
|
605
627
|
switch (policy.producerId) {
|
|
606
628
|
case 'task.resolve':
|
|
607
629
|
return probeNotObserved(policy);
|
|
@@ -610,9 +632,9 @@ function probeGenericFailure(taskRef, policy, resolved, options = {}) {
|
|
|
610
632
|
case 'task-event':
|
|
611
633
|
return probeTaskEventFailure(taskRef, policy, resolved);
|
|
612
634
|
case 'task-verify':
|
|
613
|
-
return probeVerificationFailure(taskRef, policy, resolved);
|
|
635
|
+
return await probeVerificationFailure(taskRef, policy, resolved);
|
|
614
636
|
case 'verification-engine':
|
|
615
|
-
return probeVerificationEngineFailure(policy, resolved);
|
|
637
|
+
return await probeVerificationEngineFailure(policy, resolved);
|
|
616
638
|
case 'activity-intent':
|
|
617
639
|
return probeResult(policy, applyPrReviewActivityIntent({
|
|
618
640
|
kind: 'pr-review-start', taskRef, agent: 'codex', artifact: 'pr-review.md', head: '0'.repeat(40), dryRun: true
|
|
@@ -648,7 +670,7 @@ function probeGenericFailure(taskRef, policy, resolved, options = {}) {
|
|
|
648
670
|
}
|
|
649
671
|
case 'platform.issue':
|
|
650
672
|
case 'platform.pull-request':
|
|
651
|
-
return probePlatformFailure(taskRef, policy, resolved, options);
|
|
673
|
+
return await probePlatformFailure(taskRef, policy, resolved, options);
|
|
652
674
|
default:
|
|
653
675
|
return error('OVERRIDE_PROBE_INPUT_MISSING', `no producer probe is registered for ${policy.producerId}`);
|
|
654
676
|
}
|
|
@@ -656,7 +678,7 @@ function probeGenericFailure(taskRef, policy, resolved, options = {}) {
|
|
|
656
678
|
function isProducerFailure(value) {
|
|
657
679
|
return 'observedFacts' in value && 'state' in value && Array.isArray(value.observedFacts);
|
|
658
680
|
}
|
|
659
|
-
function captureFailureSnapshot(taskRef, failureIdValue, target, options = {}) {
|
|
681
|
+
async function captureFailureSnapshot(taskRef, failureIdValue, target, options = {}) {
|
|
660
682
|
const policy = policyFor(failureIdValue);
|
|
661
683
|
if (!policy)
|
|
662
684
|
return error('OVERRIDE_FAILURE_UNKNOWN', `failure policy '${failureIdValue}' is not registered`);
|
|
@@ -679,7 +701,7 @@ function captureFailureSnapshot(taskRef, failureIdValue, target, options = {}) {
|
|
|
679
701
|
catch { /* probe reports an unconfirmed identity */ }
|
|
680
702
|
const producer = policy.producerId === LIFECYCLE_PRODUCER
|
|
681
703
|
? probeLifecycleFailure(taskRef, policy, resolved, options)
|
|
682
|
-
: probeGenericFailure(taskRef, policy, resolved, options);
|
|
704
|
+
: await probeGenericFailure(taskRef, policy, resolved, options);
|
|
683
705
|
if (!isProducerFailure(producer))
|
|
684
706
|
return producer;
|
|
685
707
|
const digest = computeFailureDigest(snapshotEvidence(resolved.taskId, failureIdValue, target, content, frontmatter, producer, resourceForSnapshot(policy, options, frontmatter)));
|
|
@@ -736,7 +758,7 @@ function validateResourceNumbers(request) {
|
|
|
736
758
|
}
|
|
737
759
|
return null;
|
|
738
760
|
}
|
|
739
|
-
function issueHumanOverride(request, options = {}) {
|
|
761
|
+
async function issueHumanOverride(request, options = {}) {
|
|
740
762
|
const invalid = validateCommon(request);
|
|
741
763
|
if (invalid)
|
|
742
764
|
return failedIssue(invalid.code, invalid.message);
|
|
@@ -765,7 +787,7 @@ function issueHumanOverride(request, options = {}) {
|
|
|
765
787
|
return failedIssue(document.code, document.message, resolved.taskId);
|
|
766
788
|
if (document.frontmatter.id !== resolved.taskId)
|
|
767
789
|
return failedIssue('OVERRIDE_DOCUMENT_INVALID', 'task frontmatter id does not match resolved task', resolved.taskId);
|
|
768
|
-
const snapshotResult = captureFailureSnapshot(request.taskRef, request.failureId, request.target, {
|
|
790
|
+
const snapshotResult = await captureFailureSnapshot(request.taskRef, request.failureId, request.target, {
|
|
769
791
|
...options,
|
|
770
792
|
probeIntent: request.intent,
|
|
771
793
|
probeOperator: request.operator,
|
|
@@ -891,14 +913,14 @@ function lifecycleRequestFor(taskRef, intent, operator, reason, values = {}) {
|
|
|
891
913
|
return error('OVERRIDE_EFFECT_INPUT_MISSING', 'restore requires the original staging directory and issue number');
|
|
892
914
|
return { taskRef, intent: 'restore', agent: operator, stagingDir, issueNumber };
|
|
893
915
|
}
|
|
894
|
-
function applyOutcomeEffect(request, row, snapshot, outcome, options) {
|
|
916
|
+
async function applyOutcomeEffect(request, row, snapshot, outcome, options) {
|
|
895
917
|
if (outcome.effect === 'no-write' || outcome.effect === 'record-only')
|
|
896
918
|
return null;
|
|
897
919
|
const intent = outcome.target === 'safe-close' ? 'cancel' : row.intent || request.intent;
|
|
898
920
|
if (!intent && outcome.target === 'continue-local') {
|
|
899
921
|
if (!options.effectExecutor)
|
|
900
922
|
return error('OVERRIDE_EFFECT_EXECUTOR_MISSING', 'the producer must supply an effect executor for a continue-local outcome');
|
|
901
|
-
return options.effectExecutor({
|
|
923
|
+
return await options.effectExecutor({
|
|
902
924
|
failureId: request.failureId,
|
|
903
925
|
operator: row.operator ?? 'local-operator',
|
|
904
926
|
reason: row.reason ?? snapshot.message
|
|
@@ -991,7 +1013,7 @@ function snapshotFromTicket(taskId, row) {
|
|
|
991
1013
|
source: 'producer-result'
|
|
992
1014
|
};
|
|
993
1015
|
}
|
|
994
|
-
function consumeHumanOverride(request, options = {}) {
|
|
1016
|
+
async function consumeHumanOverride(request, options = {}) {
|
|
995
1017
|
const values = [request.taskRef, request.ticketId, request.failureId, request.target, request.scope];
|
|
996
1018
|
if (values.some((value) => !singleLine(value))) {
|
|
997
1019
|
return failedConsume('OVERRIDE_PAYLOAD_INVALID', 'consume fields must be non-empty single-line values', request.ticketId || null);
|
|
@@ -1043,7 +1065,7 @@ function consumeHumanOverride(request, options = {}) {
|
|
|
1043
1065
|
snapshot = recoverySnapshot;
|
|
1044
1066
|
}
|
|
1045
1067
|
else {
|
|
1046
|
-
const snapshotResult = captureFailureSnapshot(request.taskRef, request.failureId, request.target, {
|
|
1068
|
+
const snapshotResult = await captureFailureSnapshot(request.taskRef, request.failureId, request.target, {
|
|
1047
1069
|
...options,
|
|
1048
1070
|
probeIntent: row.values.intent ? row.values.intent : request.intent,
|
|
1049
1071
|
probeOperator: row.values.operator,
|
|
@@ -1097,7 +1119,7 @@ function consumeHumanOverride(request, options = {}) {
|
|
|
1097
1119
|
return failedConsume('OVERRIDE_WRITE_INVALID', 'override writes cannot be planned', request.ticketId, resolved.taskId);
|
|
1098
1120
|
effectRow = { ...row.values, status: 'consuming', effect: outcome.effect, result: outcome.result, context_id: outcome.contextId, residual: `effect pending: ${outcome.residual}` };
|
|
1099
1121
|
}
|
|
1100
|
-
const effectError = applyOutcomeEffect(request, effectRow, snapshot, outcome, options);
|
|
1122
|
+
const effectError = await applyOutcomeEffect(request, effectRow, snapshot, outcome, options);
|
|
1101
1123
|
if (effectError)
|
|
1102
1124
|
return failedConsume(effectError.code, effectError.message, request.ticketId, resolved.taskId);
|
|
1103
1125
|
const after = resolveTask(request.taskRef, options);
|
|
@@ -1137,7 +1159,7 @@ function diagnoseHumanOverride(failure, target) {
|
|
|
1137
1159
|
error: null
|
|
1138
1160
|
};
|
|
1139
1161
|
}
|
|
1140
|
-
function diagnoseHumanOverrideForTask(taskRef, failure, target, options = {}) {
|
|
1162
|
+
async function diagnoseHumanOverrideForTask(taskRef, failure, target, options = {}) {
|
|
1141
1163
|
const resolved = resolveTask(taskRef, options);
|
|
1142
1164
|
if (!resolved.ok) {
|
|
1143
1165
|
return {
|
|
@@ -1176,12 +1198,12 @@ function diagnoseHumanOverrideForTask(taskRef, failure, target, options = {}) {
|
|
|
1176
1198
|
error: error('OVERRIDE_FAILURE_UNKNOWN', `failure policy '${failure}' is not registered`)
|
|
1177
1199
|
};
|
|
1178
1200
|
}
|
|
1179
|
-
const probes = policies
|
|
1201
|
+
const probes = await Promise.all(policies
|
|
1180
1202
|
.filter((policy) => !target || policy.targets.includes(target))
|
|
1181
|
-
.map((policy) => {
|
|
1203
|
+
.map(async (policy) => {
|
|
1182
1204
|
const producer = policy.producerId === LIFECYCLE_PRODUCER
|
|
1183
1205
|
? probeLifecycleFailure(taskRef, policy, resolved, options)
|
|
1184
|
-
: probeGenericFailure(taskRef, policy, resolved, options);
|
|
1206
|
+
: await probeGenericFailure(taskRef, policy, resolved, options);
|
|
1185
1207
|
const observed = isProducerFailure(producer);
|
|
1186
1208
|
return {
|
|
1187
1209
|
failureId: policy.id,
|
|
@@ -1195,7 +1217,7 @@ function diagnoseHumanOverrideForTask(taskRef, failure, target, options = {}) {
|
|
|
1195
1217
|
message: observed ? producer.message : producer.message,
|
|
1196
1218
|
errorCode: observed ? null : producer.code
|
|
1197
1219
|
};
|
|
1198
|
-
});
|
|
1220
|
+
}));
|
|
1199
1221
|
const blockedBy = probes.filter((probe) => probe.status === 'observed');
|
|
1200
1222
|
return {
|
|
1201
1223
|
status: 'ready',
|
package/dist/lib/task/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PUBLIC_CLI_ROUTE_SELECTORS, PUBLIC_CLI_SELECTOR_ALIASES } from '../internal/cli-route-inventory.js';
|
|
1
2
|
const USAGE = `Usage: ai task <command> [options]
|
|
2
3
|
|
|
3
4
|
Commands:
|
|
@@ -30,6 +31,7 @@ Examples:
|
|
|
30
31
|
ai task status --task 11
|
|
31
32
|
|
|
32
33
|
Run 'ai task <command> --help' for details.`;
|
|
34
|
+
const TASK_OPERATIONS = PUBLIC_CLI_ROUTE_SELECTORS.task;
|
|
33
35
|
export async function runTask(args) {
|
|
34
36
|
const [subcommand, ...rest] = args;
|
|
35
37
|
if (!subcommand) {
|
|
@@ -41,14 +43,20 @@ export async function runTask(args) {
|
|
|
41
43
|
process.stdout.write(`${USAGE}\n`);
|
|
42
44
|
return;
|
|
43
45
|
}
|
|
44
|
-
|
|
46
|
+
const routeSelector = PUBLIC_CLI_SELECTOR_ALIASES.task[subcommand] ?? subcommand;
|
|
47
|
+
if (!TASK_OPERATIONS.includes(routeSelector)) {
|
|
48
|
+
process.stderr.write(`Unknown task command: ${subcommand}\n\n`);
|
|
49
|
+
process.stdout.write(`${USAGE}\n`);
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
switch (routeSelector) {
|
|
45
54
|
case 'cat': {
|
|
46
55
|
const { cat } = await import('./commands/cat.js');
|
|
47
56
|
cat(rest);
|
|
48
57
|
break;
|
|
49
58
|
}
|
|
50
|
-
case 'decisions':
|
|
51
|
-
case 'd': {
|
|
59
|
+
case 'decisions': {
|
|
52
60
|
const { decisions } = await import('./commands/decisions.js');
|
|
53
61
|
decisions(rest);
|
|
54
62
|
break;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parseArtifactReceipts, sha256File } from './artifact-receipts.js';
|
|
4
|
+
import { invalidationMutation, parseInvalidationDocument, reconcileInvalidation } from './invalidation.js';
|
|
5
|
+
import { resolveTaskRef } from './resolve-ref.js';
|
|
6
|
+
import { writeTask } from './write.js';
|
|
7
|
+
function reconcileTaskInvalidation(taskRef, options = {}) {
|
|
8
|
+
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
9
|
+
if (!resolved.ok)
|
|
10
|
+
return { status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: 0, error: { code: resolved.code, message: resolved.message } };
|
|
11
|
+
let content;
|
|
12
|
+
try {
|
|
13
|
+
content = fs.readFileSync(resolved.taskMdPath, 'utf8');
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
return { status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: 0, error: { code: 'TASK_READ_FAILED', message: error instanceof Error ? error.message : String(error) } };
|
|
17
|
+
}
|
|
18
|
+
const parsed = parseInvalidationDocument(content);
|
|
19
|
+
if (!parsed.ok)
|
|
20
|
+
return { status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: 0, error: { code: parsed.code, message: parsed.message } };
|
|
21
|
+
if (!parsed.present)
|
|
22
|
+
return { status: 'no-op', changed: false, taskId: resolved.taskId, processed: 0, remaining: 0, error: null };
|
|
23
|
+
const beforePending = parsed.document.targets.filter((target) => target.status !== 'completed').length;
|
|
24
|
+
let receipts;
|
|
25
|
+
try {
|
|
26
|
+
receipts = parseArtifactReceipts(content).rows;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (parsed.document.targets.some((target) => target.status !== 'completed' && target.targetKind === 'receipt')) {
|
|
30
|
+
return {
|
|
31
|
+
status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending,
|
|
32
|
+
error: { code: 'INVALIDATION_TARGET_HASH_CONFLICT', message: error instanceof Error ? error.message : String(error) }
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
receipts = [];
|
|
36
|
+
}
|
|
37
|
+
for (const target of parsed.document.targets) {
|
|
38
|
+
if (target.status === 'completed')
|
|
39
|
+
continue;
|
|
40
|
+
if (target.targetKind === 'receipt') {
|
|
41
|
+
const receipt = receipts.find((candidate) => candidate.output === target.targetArtifact);
|
|
42
|
+
if (!receipt || receipt.inputSha256 !== target.targetSha256) {
|
|
43
|
+
return {
|
|
44
|
+
status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending,
|
|
45
|
+
error: { code: 'INVALIDATION_TARGET_HASH_CONFLICT', message: `invalidation receipt target '${target.targetArtifact}' changed before reconcile` }
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const targetPath = path.join(resolved.taskDir, target.targetArtifact);
|
|
51
|
+
try {
|
|
52
|
+
const stat = fs.lstatSync(targetPath);
|
|
53
|
+
if (!stat.isFile() || stat.isSymbolicLink() || sha256File(targetPath) !== target.targetSha256) {
|
|
54
|
+
return {
|
|
55
|
+
status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending,
|
|
56
|
+
error: { code: 'INVALIDATION_TARGET_HASH_CONFLICT', message: `invalidation target '${target.targetArtifact}' changed before reconcile` }
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return {
|
|
62
|
+
status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending,
|
|
63
|
+
error: { code: 'INVALIDATION_TARGET_HASH_CONFLICT', message: `invalidation target '${target.targetArtifact}' is unavailable before reconcile` }
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const reconciled = reconcileInvalidation(parsed.document, (options.now ?? (() => new Date().toISOString()))(), options.maxTargets);
|
|
68
|
+
if (!reconciled.ok)
|
|
69
|
+
return { status: 'failed', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending, error: { code: reconciled.code, message: reconciled.message } };
|
|
70
|
+
if (!reconciled.changed)
|
|
71
|
+
return { status: 'no-op', changed: false, taskId: resolved.taskId, processed: 0, remaining: beforePending, error: null };
|
|
72
|
+
const result = writeTask({
|
|
73
|
+
taskRef, expectedState: resolved.state, dryRun: options.dryRun,
|
|
74
|
+
mutations: [invalidationMutation(content, reconciled.document)]
|
|
75
|
+
}, { ...options, invalidationContext: 'reconcile', taskLocation: { repoRoot: resolved.repoRoot, taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, state: resolved.state } });
|
|
76
|
+
if (result.status === 'failed')
|
|
77
|
+
return { status: 'failed', changed: false, taskId: resolved.taskId, processed: beforePending - reconciled.document.targets.filter((target) => target.status !== 'completed').length, remaining: reconciled.document.targets.filter((target) => target.status !== 'completed').length, error: result.error };
|
|
78
|
+
return {
|
|
79
|
+
status: result.status, changed: result.changed, taskId: resolved.taskId,
|
|
80
|
+
processed: beforePending - reconciled.document.targets.filter((target) => target.status !== 'completed').length,
|
|
81
|
+
remaining: reconciled.document.targets.filter((target) => target.status !== 'completed').length,
|
|
82
|
+
error: null
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export { reconcileTaskInvalidation };
|
|
86
|
+
//# sourceMappingURL=invalidation-command.js.map
|