@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
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
4
4
|
|
|
5
5
|
import { parseTypedTaskFrontmatter } from './frontmatter.ts';
|
|
6
6
|
import { validateCurrentTaskContract } from './current-contract.ts';
|
|
7
|
-
import { parseReviewSummary
|
|
8
|
-
import { inspectArtifactDirectory } from './artifact-lifecycle.ts';
|
|
7
|
+
import { parseReviewSummary } from './review-artifacts.ts';
|
|
9
8
|
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.ts';
|
|
10
9
|
import type { LedgerDocument } from './ledger.ts';
|
|
11
10
|
import { resolveTaskRef } from './resolve-ref.ts';
|
|
@@ -53,6 +52,11 @@ import { hasActiveCodexLifecycleEvidence } from '../agent-clients/adapters/codex
|
|
|
53
52
|
import type { CodexCapabilityProvenanceDetail } from '../agent-clients/adapters/codex-lifecycle/capability-store.ts';
|
|
54
53
|
import { extractReviewBaseline, extractReviewDiffBase, extractReviewTargetHead, extractReviewedHead } from './review-fingerprint.ts';
|
|
55
54
|
import { resolveDeliveryTarget, resolveDiffBase, resolveTargetHead } from './delivery-target.ts';
|
|
55
|
+
import { buildLifecycleFacts, canStart, recommendNext } from './capabilities.ts';
|
|
56
|
+
import { hasOpenLifecycleExecution } from './activity-log.ts';
|
|
57
|
+
import { invalidationBlocks } from './invalidation.ts';
|
|
58
|
+
import type { InvalidationDocument } from './invalidation.ts';
|
|
59
|
+
import type { LifecycleAction, LifecycleFacts } from './capabilities.ts';
|
|
56
60
|
|
|
57
61
|
type OrchestrationStatus = 'running' | 'paused' | 'completed';
|
|
58
62
|
type ModelPolicySource = Readonly<{
|
|
@@ -108,7 +112,7 @@ type OrchestrationRun = Readonly<{
|
|
|
108
112
|
updatedAt: string;
|
|
109
113
|
}>;
|
|
110
114
|
type OrchestrationNext = Readonly<{
|
|
111
|
-
action: 'analyze-task' | 'review-analysis' | 'plan-task' | 'review-plan' | 'code-task' | 'review-code'
|
|
115
|
+
action: 'analyze-task' | 'review-analysis' | 'plan-task' | 'review-plan' | 'code-task' | 'review-code';
|
|
112
116
|
role: DelegationRole;
|
|
113
117
|
stage: DelegationStage;
|
|
114
118
|
round: number;
|
|
@@ -150,6 +154,7 @@ type OrchestrationCompletionPlanResult = Readonly<{
|
|
|
150
154
|
type OrchestrationOptions = {
|
|
151
155
|
repoRoot?: string;
|
|
152
156
|
gitWorktreeRoot?: string;
|
|
157
|
+
diagnosticLog?: OrchestrationDiagnosticLogger;
|
|
153
158
|
id?: () => string;
|
|
154
159
|
now?: () => string;
|
|
155
160
|
maxSteps?: number;
|
|
@@ -174,6 +179,10 @@ type OrchestrationOptions = {
|
|
|
174
179
|
hasActiveLifecycleEvidence?: (receipt: DelegationReceipt) => boolean;
|
|
175
180
|
};
|
|
176
181
|
|
|
182
|
+
export type OrchestrationDiagnosticValue = string | number | boolean | null;
|
|
183
|
+
export type OrchestrationDiagnosticFields = Readonly<Record<string, OrchestrationDiagnosticValue>>;
|
|
184
|
+
export type OrchestrationDiagnosticLogger = (event: string, fields: OrchestrationDiagnosticFields) => void;
|
|
185
|
+
|
|
177
186
|
function supportsLifecycleDelegation(client: AgentClientId): boolean {
|
|
178
187
|
return getAgentClientCapability(client, 'subagents').level !== 'unsupported'
|
|
179
188
|
&& getAgentClientCapability(client, 'orchestration').level !== 'unsupported'
|
|
@@ -190,11 +199,13 @@ const ORCHESTRATION_STATE_INVALID_MESSAGE = 'orchestration.json does not match t
|
|
|
190
199
|
class OrchestrationStateError extends Error {
|
|
191
200
|
readonly code = 'ORCHESTRATION_STATE_INVALID';
|
|
192
201
|
readonly taskId: string | null;
|
|
202
|
+
readonly reasonCodes: readonly string[];
|
|
193
203
|
|
|
194
|
-
constructor(taskId: string | null = null) {
|
|
204
|
+
constructor(taskId: string | null = null, reasonCodes: readonly string[] = []) {
|
|
195
205
|
super(ORCHESTRATION_STATE_INVALID_MESSAGE);
|
|
196
206
|
this.name = 'OrchestrationStateError';
|
|
197
207
|
this.taskId = taskId;
|
|
208
|
+
this.reasonCodes = Object.freeze([...reasonCodes]);
|
|
198
209
|
}
|
|
199
210
|
}
|
|
200
211
|
|
|
@@ -284,46 +295,128 @@ const ORCHESTRATION_RUN_KEYS = [
|
|
|
284
295
|
'pause', 'commitAuthorization', 'completionEvidence', 'createdAt', 'updatedAt'
|
|
285
296
|
] as const;
|
|
286
297
|
|
|
287
|
-
function
|
|
288
|
-
if (!hasExactKeys(value, ORCHESTRATION_RUN_KEYS)
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
298
|
+
function orchestrationStateReasonCodes(value: unknown, expectedTaskId?: string): string[] {
|
|
299
|
+
if (!hasExactKeys(value, ORCHESTRATION_RUN_KEYS)) return ['top-level-keys'];
|
|
300
|
+
const record = value;
|
|
301
|
+
const reasons: string[] = [];
|
|
302
|
+
if (!exactText(record.taskId)) reasons.push('taskId');
|
|
303
|
+
else if (expectedTaskId !== undefined && record.taskId !== expectedTaskId) reasons.push('taskId-mismatch');
|
|
304
|
+
if (!exactText(record.runId)) reasons.push('runId');
|
|
305
|
+
if (!['running', 'paused', 'completed'].includes(record.status as string)) reasons.push('status');
|
|
306
|
+
if (!(record.nextStage === null || ['analysis', 'review-analysis', 'plan', 'review-plan', 'code', 'review-code', 'commit'].includes(record.nextStage as string))) {
|
|
307
|
+
reasons.push('nextStage');
|
|
308
|
+
}
|
|
309
|
+
if (!Number.isSafeInteger(record.stepCount) || (record.stepCount as number) < 0) reasons.push('stepCount');
|
|
310
|
+
if (!Number.isSafeInteger(record.maxSteps) || (record.maxSteps as number) < 1) reasons.push('maxSteps');
|
|
311
|
+
if (!isModelPolicy(record.modelPolicy)) reasons.push('modelPolicy');
|
|
312
|
+
if (!isModelPolicySource(record.modelPolicySource)) reasons.push('modelPolicySource');
|
|
313
|
+
if (!Array.isArray(record.recoveryHistory) || !record.recoveryHistory.every(isRecovery)) reasons.push('recoveryHistory');
|
|
314
|
+
if (typeof record.baseline !== 'string') reasons.push('baseline');
|
|
315
|
+
if (!(record.pendingDelegation === null || isDelegationReceipt(record.pendingDelegation))) reasons.push('pendingDelegation');
|
|
316
|
+
if (!Array.isArray(record.receipts) || !record.receipts.every(isDelegationReceipt)) reasons.push('receipts');
|
|
317
|
+
if (!(record.pause === null || isPause(record.pause))) reasons.push('pause');
|
|
318
|
+
if (!hasExactKeys(record.commitAuthorization, ['issuedAt', 'consumedAt'])) {
|
|
319
|
+
reasons.push('commitAuthorization');
|
|
320
|
+
} else {
|
|
321
|
+
if (!nullableText(record.commitAuthorization.issuedAt)) reasons.push('commitAuthorization.issuedAt');
|
|
322
|
+
if (!nullableText(record.commitAuthorization.consumedAt)) reasons.push('commitAuthorization.consumedAt');
|
|
323
|
+
}
|
|
324
|
+
if (!(record.completionEvidence === null || isCompletionEvidence(record.completionEvidence))) reasons.push('completionEvidence');
|
|
325
|
+
if (!exactText(record.createdAt)) reasons.push('createdAt');
|
|
326
|
+
if (!exactText(record.updatedAt)) reasons.push('updatedAt');
|
|
327
|
+
if (Array.isArray(record.receipts) && record.receipts.every(isDelegationReceipt)
|
|
328
|
+
&& (record.pendingDelegation === null || isDelegationReceipt(record.pendingDelegation))) {
|
|
329
|
+
const receipts = [...record.receipts, ...(record.pendingDelegation ? [record.pendingDelegation] : [])];
|
|
330
|
+
if (receipts.some((receipt) => receipt.taskId !== record.taskId || receipt.runId !== record.runId)) {
|
|
331
|
+
reasons.push('receipt-identity');
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return reasons;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function emitDiagnostic(options: Pick<OrchestrationOptions, 'diagnosticLog'> | undefined, event: string, fields: OrchestrationDiagnosticFields): void {
|
|
338
|
+
try {
|
|
339
|
+
options?.diagnosticLog?.(event, fields);
|
|
340
|
+
} catch {
|
|
341
|
+
// Diagnostics must never change lifecycle behavior.
|
|
310
342
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function fileObservation(file: string): OrchestrationDiagnosticFields {
|
|
346
|
+
try {
|
|
347
|
+
const stat = fs.lstatSync(file);
|
|
348
|
+
let realpath: string | null = null;
|
|
349
|
+
try { realpath = fs.realpathSync.native(file); } catch { /* retain the lstat observation */ }
|
|
350
|
+
return {
|
|
351
|
+
file,
|
|
352
|
+
exists: true,
|
|
353
|
+
fileType: stat.isFile() ? 'file' : stat.isDirectory() ? 'directory' : 'other',
|
|
354
|
+
symbolicLink: stat.isSymbolicLink(),
|
|
355
|
+
bytes: stat.isFile() ? stat.size : null,
|
|
356
|
+
mtimeMs: stat.mtimeMs,
|
|
357
|
+
device: stat.dev,
|
|
358
|
+
inode: stat.ino,
|
|
359
|
+
realpath
|
|
360
|
+
};
|
|
361
|
+
} catch (error) {
|
|
362
|
+
return {
|
|
363
|
+
file,
|
|
364
|
+
exists: false,
|
|
365
|
+
fileType: null,
|
|
366
|
+
symbolicLink: null,
|
|
367
|
+
bytes: null,
|
|
368
|
+
mtimeMs: null,
|
|
369
|
+
device: null,
|
|
370
|
+
inode: null,
|
|
371
|
+
realpath: null,
|
|
372
|
+
fsError: error instanceof Error && 'code' in error ? String(error.code) : null
|
|
373
|
+
};
|
|
314
374
|
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function parseOrchestrationRun(value: unknown, expectedTaskId?: string): OrchestrationRun {
|
|
378
|
+
const reasonCodes = orchestrationStateReasonCodes(value, expectedTaskId);
|
|
379
|
+
if (reasonCodes.length > 0) throw new OrchestrationStateError(expectedTaskId ?? null, reasonCodes);
|
|
315
380
|
return value as OrchestrationRun;
|
|
316
381
|
}
|
|
317
382
|
|
|
318
|
-
function readRun(taskDir: string): OrchestrationRun | null {
|
|
383
|
+
function readRun(taskDir: string, options: Pick<OrchestrationOptions, 'diagnosticLog'> = {}): OrchestrationRun | null {
|
|
319
384
|
const file = orchestrationPath(taskDir);
|
|
320
|
-
if (!fs.existsSync(file)) return null;
|
|
321
385
|
const taskId = path.basename(taskDir);
|
|
386
|
+
const observed = options.diagnosticLog ? fileObservation(file) : {};
|
|
387
|
+
if (!fs.existsSync(file)) {
|
|
388
|
+
emitDiagnostic(options, 'orchestration-state-missing', { taskId, taskDir, ...observed });
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
emitDiagnostic(options, 'orchestration-state-read-start', { taskId, taskDir, ...observed });
|
|
392
|
+
let rawBytes: number | null = null;
|
|
393
|
+
let rawSha256: string | null = null;
|
|
322
394
|
try {
|
|
323
|
-
|
|
395
|
+
const raw = fs.readFileSync(file, 'utf8');
|
|
396
|
+
if (options.diagnosticLog) {
|
|
397
|
+
rawBytes = Buffer.byteLength(raw, 'utf8');
|
|
398
|
+
rawSha256 = createHash('sha256').update(raw, 'utf8').digest('hex');
|
|
399
|
+
}
|
|
400
|
+
const run = parseOrchestrationRun(JSON.parse(raw), taskId);
|
|
401
|
+
emitDiagnostic(options, 'orchestration-state-read-ok', {
|
|
402
|
+
taskId, taskDir, file, rawBytes, rawSha256, status: run.status, runId: run.runId,
|
|
403
|
+
stepCount: run.stepCount, pendingDelegation: run.pendingDelegation !== null
|
|
404
|
+
});
|
|
405
|
+
return run;
|
|
324
406
|
} catch (error) {
|
|
325
|
-
|
|
326
|
-
|
|
407
|
+
const reasonCodes = error instanceof OrchestrationStateError && error.reasonCodes.length > 0
|
|
408
|
+
? error.reasonCodes
|
|
409
|
+
: [error instanceof SyntaxError ? 'json-parse' : 'file-read'];
|
|
410
|
+
emitDiagnostic(options, 'orchestration-state-read-failed', {
|
|
411
|
+
taskId,
|
|
412
|
+
taskDir,
|
|
413
|
+
...observed,
|
|
414
|
+
rawBytes,
|
|
415
|
+
rawSha256,
|
|
416
|
+
reasonCodes: reasonCodes.join(','),
|
|
417
|
+
errorType: error instanceof Error ? error.name : typeof error,
|
|
418
|
+
});
|
|
419
|
+
throw new OrchestrationStateError(taskId, reasonCodes);
|
|
327
420
|
}
|
|
328
421
|
}
|
|
329
422
|
|
|
@@ -413,7 +506,7 @@ function beginOrResumeOrchestration(taskRef: string, options: OrchestrationOptio
|
|
|
413
506
|
}
|
|
414
507
|
let existing: OrchestrationRun | null;
|
|
415
508
|
try {
|
|
416
|
-
existing = readRun(resolved.taskDir);
|
|
509
|
+
existing = readRun(resolved.taskDir, options);
|
|
417
510
|
} catch (error) {
|
|
418
511
|
return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
419
512
|
}
|
|
@@ -561,78 +654,19 @@ function validateSavedCurrentDiffBase(
|
|
|
561
654
|
return null;
|
|
562
655
|
}
|
|
563
656
|
|
|
564
|
-
function
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
const
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
try { content = fs.readFileSync(path.join(taskDir, artifactName(family, round)), 'utf8'); }
|
|
578
|
-
catch (error) { return { approved: false, error: String(error) }; }
|
|
579
|
-
const parsed = parseReviewSummary(content);
|
|
580
|
-
if (!parsed.ok) return { approved: false, error: `${parsed.code}: ${parsed.message}` };
|
|
581
|
-
const verdict = resolveCanonicalVerdict(parsed.summary);
|
|
582
|
-
if (!verdict.ok) return { approved: false, error: `${verdict.code}: ${verdict.message}` };
|
|
583
|
-
return { approved: verdict.verdict === 'Approved', error: null };
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
function routeFromFacts(taskDir: string): Omit<OrchestrationNext, 'requestedModel' | 'requestedReasoningEffort'> | { error: string } | null {
|
|
587
|
-
const analysisRound = highestRound(taskDir, 'analysis');
|
|
588
|
-
const analysisReviewRound = highestRound(taskDir, 'review-analysis');
|
|
589
|
-
const planRound = highestRound(taskDir, 'plan');
|
|
590
|
-
const planReviewRound = highestRound(taskDir, 'review-plan');
|
|
591
|
-
const codeRound = highestRound(taskDir, 'code');
|
|
592
|
-
const codeReviewRound = highestRound(taskDir, 'review-code');
|
|
593
|
-
if (analysisRound === 0) {
|
|
594
|
-
const round = analysisRound + 1;
|
|
595
|
-
return { action: 'analyze-task', role: 'executor', stage: 'analysis', round, artifact: artifactName('analysis', round) };
|
|
596
|
-
}
|
|
597
|
-
if (!hasReviewAfterArtifact(taskDir, 'analysis', 'review-analysis')) {
|
|
598
|
-
const round = analysisReviewRound + 1;
|
|
599
|
-
return { action: 'review-analysis', role: 'reviewer', stage: 'review-analysis', round, artifact: artifactName('review-analysis', round) };
|
|
600
|
-
}
|
|
601
|
-
const analysisVerdict = latestReviewApproved(taskDir, 'review-analysis');
|
|
602
|
-
if (analysisVerdict.error) return { error: analysisVerdict.error };
|
|
603
|
-
if (!analysisVerdict.approved) {
|
|
604
|
-
const round = analysisRound + 1;
|
|
605
|
-
return { action: 'analyze-task', role: 'executor', stage: 'analysis', round, artifact: artifactName('analysis', round) };
|
|
606
|
-
}
|
|
607
|
-
if (planRound === 0) {
|
|
608
|
-
const round = planRound + 1;
|
|
609
|
-
return { action: 'plan-task', role: 'executor', stage: 'plan', round, artifact: artifactName('plan', round) };
|
|
610
|
-
}
|
|
611
|
-
if (!hasReviewAfterArtifact(taskDir, 'plan', 'review-plan')) {
|
|
612
|
-
const round = planReviewRound + 1;
|
|
613
|
-
return { action: 'review-plan', role: 'reviewer', stage: 'review-plan', round, artifact: artifactName('review-plan', round) };
|
|
614
|
-
}
|
|
615
|
-
const planVerdict = latestReviewApproved(taskDir, 'review-plan');
|
|
616
|
-
if (planVerdict.error) return { error: planVerdict.error };
|
|
617
|
-
if (!planVerdict.approved) {
|
|
618
|
-
const round = planRound + 1;
|
|
619
|
-
return { action: 'plan-task', role: 'executor', stage: 'plan', round, artifact: artifactName('plan', round) };
|
|
620
|
-
}
|
|
621
|
-
if (codeRound === 0) {
|
|
622
|
-
const round = codeRound + 1;
|
|
623
|
-
return { action: 'code-task', role: 'executor', stage: 'code', round, artifact: artifactName('code', round) };
|
|
624
|
-
}
|
|
625
|
-
if (!hasReviewAfterArtifact(taskDir, 'code', 'review-code')) {
|
|
626
|
-
const round = codeReviewRound + 1;
|
|
627
|
-
return { action: 'review-code', role: 'reviewer', stage: 'review-code', round, artifact: artifactName('review-code', round) };
|
|
628
|
-
}
|
|
629
|
-
const codeVerdict = latestReviewApproved(taskDir, 'review-code');
|
|
630
|
-
if (codeVerdict.error) return { error: codeVerdict.error };
|
|
631
|
-
if (!codeVerdict.approved) {
|
|
632
|
-
const round = codeRound + 1;
|
|
633
|
-
return { action: 'code-task', role: 'executor', stage: 'code', round, artifact: artifactName('code', round) };
|
|
634
|
-
}
|
|
635
|
-
return { action: 'commit', role: 'executor', stage: 'commit', round: 1, artifact: 'commit' };
|
|
657
|
+
function routeFromFacts(facts: LifecycleFacts): Omit<OrchestrationNext, 'requestedModel' | 'requestedReasoningEffort'> | { completion: true } | null {
|
|
658
|
+
const recommendation = recommendNext(facts);
|
|
659
|
+
if (!recommendation.action) return { completion: true };
|
|
660
|
+
const action = recommendation.action;
|
|
661
|
+
if (action === 'manual-validation' || action === 'validation-run') return null;
|
|
662
|
+
const family = action === 'analysis' ? 'analysis' : action;
|
|
663
|
+
const round = Math.max(0, ...[...(facts.artifacts[family] ?? []), ...(facts.staleArtifacts?.[family] ?? [])].map((name) => {
|
|
664
|
+
const match = /-r(\d+)\.md$/.exec(name);
|
|
665
|
+
return match ? Number(match[1]) : 1;
|
|
666
|
+
})) + 1;
|
|
667
|
+
const command = action === 'analysis' ? 'analyze-task' : action === 'plan' ? 'plan-task' : action === 'code' ? 'code-task' : action;
|
|
668
|
+
const role = action.startsWith('review-') ? 'reviewer' : 'executor';
|
|
669
|
+
return { action: command, role, stage: action, round, artifact: artifactName(family, round) };
|
|
636
670
|
}
|
|
637
671
|
|
|
638
672
|
function routeOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
|
|
@@ -652,11 +686,13 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
|
|
|
652
686
|
}
|
|
653
687
|
let metadata: ReturnType<typeof parseTypedTaskFrontmatter>;
|
|
654
688
|
let currentLedger: LedgerDocument | null = null;
|
|
689
|
+
let currentInvalidation: InvalidationDocument = { operations: [], targets: [] };
|
|
655
690
|
if (resolved.state === 'active') {
|
|
656
691
|
const contract = validateCurrentTaskContract(content);
|
|
657
692
|
if (!contract.ok) return failed('ORCHESTRATION_CURRENT_CONTRACT_INVALID', contract.message, resolved.taskId);
|
|
658
693
|
metadata = contract.metadata;
|
|
659
694
|
currentLedger = contract.ledger;
|
|
695
|
+
currentInvalidation = contract.invalidation;
|
|
660
696
|
} else {
|
|
661
697
|
try {
|
|
662
698
|
metadata = parseTypedTaskFrontmatter(content);
|
|
@@ -664,17 +700,25 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
|
|
|
664
700
|
return failed('ORCHESTRATION_TASK_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
665
701
|
}
|
|
666
702
|
}
|
|
667
|
-
|
|
668
|
-
|
|
703
|
+
if (invalidationBlocks(currentInvalidation)) {
|
|
704
|
+
return failed('ORCHESTRATION_INVALIDATION_INCOMPLETE', 'artifact invalidation is incomplete; reconcile task.md before routing downstream work', resolved.taskId);
|
|
705
|
+
}
|
|
706
|
+
let run: OrchestrationRun | null;
|
|
707
|
+
try {
|
|
708
|
+
run = readRun(resolved.taskDir, options);
|
|
709
|
+
} catch (error) {
|
|
710
|
+
return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
711
|
+
}
|
|
712
|
+
const facts = buildLifecycleFacts(
|
|
713
|
+
resolved.taskDir,
|
|
714
|
+
content,
|
|
715
|
+
resolved.state,
|
|
716
|
+
hasOpenLifecycleExecution(content) || Boolean(run?.pendingDelegation)
|
|
717
|
+
);
|
|
718
|
+
if (!facts.ok) return failed('ORCHESTRATION_CAPABILITY_FACTS_INVALID', facts.message, resolved.taskId);
|
|
719
|
+
const routed = routeFromFacts(facts.facts);
|
|
669
720
|
if (!routed) return failed('ORCHESTRATION_ROUTE_UNKNOWN', 'cannot determine a unique lifecycle action', resolved.taskId);
|
|
670
|
-
|
|
671
|
-
const policy = run ? rolePolicy(run, routed.role) : null;
|
|
672
|
-
const next: OrchestrationNext = {
|
|
673
|
-
...routed,
|
|
674
|
-
requestedModel: policy?.model ?? null,
|
|
675
|
-
requestedReasoningEffort: policy?.reasoningEffort ?? null
|
|
676
|
-
};
|
|
677
|
-
if (next.stage === 'commit') {
|
|
721
|
+
if ('completion' in routed) {
|
|
678
722
|
const reviewRound = highestRound(resolved.taskDir, 'review-code');
|
|
679
723
|
const review = parseReviewSummary(fs.readFileSync(
|
|
680
724
|
path.join(resolved.taskDir, artifactName('review-code', reviewRound)),
|
|
@@ -756,13 +800,25 @@ function routeOrchestration(taskRef: string, options: OrchestrationOptions = {})
|
|
|
756
800
|
saveRun(resolved.taskDir, completed);
|
|
757
801
|
return { status: 'completed', changed: true, taskId: resolved.taskId, run: completed, next: null, error: null };
|
|
758
802
|
}
|
|
803
|
+
const action = routed.stage as LifecycleAction;
|
|
804
|
+
const capability = canStart(action, facts.facts, {
|
|
805
|
+
initiator: 'orchestrator', requestId: `orchestration:${resolved.taskId}:${routed.stage}:${routed.round}`,
|
|
806
|
+
requestedAction: action, reasonCode: 'user-request', explicitRequest: true
|
|
807
|
+
});
|
|
808
|
+
if (!capability.allowed) return failed('ORCHESTRATION_CAPABILITY_DENIED', `${capability.reasonCode}: ${capability.evidence.join(', ')}`, resolved.taskId);
|
|
809
|
+
const policy = run ? rolePolicy(run, routed.role) : null;
|
|
810
|
+
const next: OrchestrationNext = {
|
|
811
|
+
...routed,
|
|
812
|
+
requestedModel: policy?.model ?? null,
|
|
813
|
+
requestedReasoningEffort: policy?.reasoningEffort ?? null
|
|
814
|
+
};
|
|
759
815
|
return { status: 'running', changed: false, taskId: resolved.taskId, run, next, error: null };
|
|
760
816
|
}
|
|
761
817
|
|
|
762
818
|
function statusOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
|
|
763
819
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
764
820
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
765
|
-
const run = readRun(resolved.taskDir);
|
|
821
|
+
const run = readRun(resolved.taskDir, options);
|
|
766
822
|
if (!run) return failed('ORCHESTRATION_RUN_MISSING', 'no orchestration run exists', resolved.taskId);
|
|
767
823
|
return { status: run.status, changed: false, taskId: resolved.taskId, run, next: null, error: null };
|
|
768
824
|
}
|
|
@@ -782,7 +838,15 @@ function prepareOrchestrationDelegationUnlocked(
|
|
|
782
838
|
if (!(options.supportsLifecycleDelegation ?? supportsLifecycleDelegation)(input.client)) {
|
|
783
839
|
return failed('ORCHESTRATION_CLIENT_UNSUPPORTED', `client '${input.client}' does not support lifecycle orchestration`, resolved.taskId);
|
|
784
840
|
}
|
|
785
|
-
|
|
841
|
+
emitDiagnostic(options, 'orchestration-prepare-start', {
|
|
842
|
+
taskId: resolved.taskId,
|
|
843
|
+
taskDir: resolved.taskDir,
|
|
844
|
+
repoRoot: resolved.repoRoot,
|
|
845
|
+
client: input.client,
|
|
846
|
+
requestedModel: input.requestedModel ?? null,
|
|
847
|
+
requestedReasoningEffort: input.requestedReasoningEffort ?? null
|
|
848
|
+
});
|
|
849
|
+
const run = readRun(resolved.taskDir, options);
|
|
786
850
|
if (!run || run.status !== 'running') return failed('ORCHESTRATION_RUN_NOT_RUNNING', 'a running orchestration is required', resolved.taskId);
|
|
787
851
|
if (run.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_BUSY', 'the run already has a pending delegation', resolved.taskId);
|
|
788
852
|
const repositoryPending = matchingDelegations(() => true, options);
|
|
@@ -895,7 +959,7 @@ function dispatchOrchestrationDelegationUnlocked(
|
|
|
895
959
|
): OrchestrationResult {
|
|
896
960
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
897
961
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
898
|
-
const run = readRun(resolved.taskDir);
|
|
962
|
+
const run = readRun(resolved.taskDir, options);
|
|
899
963
|
if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
900
964
|
if (run.status !== 'running') {
|
|
901
965
|
return failed('ORCHESTRATION_STATE_INVALID', 'spawn dispatch requires a running orchestration', resolved.taskId);
|
|
@@ -941,16 +1005,42 @@ function matchingDelegations(
|
|
|
941
1005
|
const repoRoot = options.repoRoot ?? process.cwd();
|
|
942
1006
|
const activeRoot = path.join(repoRoot, '.agents', 'workspace', 'active');
|
|
943
1007
|
if (!fs.existsSync(activeRoot)) return [];
|
|
944
|
-
|
|
1008
|
+
emitDiagnostic(options, 'orchestration-active-scan-start', {
|
|
1009
|
+
activeRoot
|
|
1010
|
+
});
|
|
1011
|
+
const matches = fs.readdirSync(activeRoot, { withFileTypes: true })
|
|
945
1012
|
.filter((entry) => entry.isDirectory())
|
|
946
1013
|
.flatMap((entry) => {
|
|
947
|
-
const
|
|
1014
|
+
const candidateTaskId = entry.name;
|
|
1015
|
+
const candidateTaskDir = path.join(activeRoot, candidateTaskId);
|
|
1016
|
+
emitDiagnostic(options, 'orchestration-active-scan-candidate', {
|
|
1017
|
+
candidateTaskId,
|
|
1018
|
+
candidateTaskDir,
|
|
1019
|
+
orchestrationPath: orchestrationPath(candidateTaskDir)
|
|
1020
|
+
});
|
|
1021
|
+
let run: OrchestrationRun | null;
|
|
1022
|
+
try {
|
|
1023
|
+
run = readRun(candidateTaskDir, options);
|
|
1024
|
+
} catch (error) {
|
|
1025
|
+
emitDiagnostic(options, 'orchestration-active-scan-candidate-failed', {
|
|
1026
|
+
candidateTaskId,
|
|
1027
|
+
candidateTaskDir,
|
|
1028
|
+
errorType: error instanceof Error ? error.name : typeof error,
|
|
1029
|
+
reasonCodes: error instanceof OrchestrationStateError ? error.reasonCodes.join(',') : null
|
|
1030
|
+
});
|
|
1031
|
+
throw error;
|
|
1032
|
+
}
|
|
948
1033
|
if (!run || run.status !== 'running' || !run.pendingDelegation) return [];
|
|
949
1034
|
const receipt = run.pendingDelegation;
|
|
950
1035
|
return predicate(receipt)
|
|
951
|
-
? [{ taskId:
|
|
1036
|
+
? [{ taskId: candidateTaskId, run }]
|
|
952
1037
|
: [];
|
|
953
1038
|
});
|
|
1039
|
+
emitDiagnostic(options, 'orchestration-active-scan-finished', {
|
|
1040
|
+
activeRoot,
|
|
1041
|
+
matchingDelegations: matches.length
|
|
1042
|
+
});
|
|
1043
|
+
return matches;
|
|
954
1044
|
}
|
|
955
1045
|
|
|
956
1046
|
function uniqueMatchingDelegation(
|
|
@@ -1196,7 +1286,7 @@ function activateOrchestrationDelegation(
|
|
|
1196
1286
|
): OrchestrationResult {
|
|
1197
1287
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1198
1288
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1199
|
-
const run = readRun(resolved.taskDir);
|
|
1289
|
+
const run = readRun(resolved.taskDir, options);
|
|
1200
1290
|
if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
1201
1291
|
if (run.status !== 'running') {
|
|
1202
1292
|
return { status: run.status, changed: false, taskId: resolved.taskId, run, next: null, error: null };
|
|
@@ -1224,7 +1314,7 @@ async function awaitOrchestrationDelegationActivation(
|
|
|
1224
1314
|
while (true) {
|
|
1225
1315
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1226
1316
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1227
|
-
const run = readRun(resolved.taskDir);
|
|
1317
|
+
const run = readRun(resolved.taskDir, options);
|
|
1228
1318
|
if (!run?.pendingDelegation) {
|
|
1229
1319
|
return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
1230
1320
|
}
|
|
@@ -1290,7 +1380,7 @@ function recoverPreparedOrchestrationDelegation(
|
|
|
1290
1380
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1291
1381
|
try {
|
|
1292
1382
|
return withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-orchestration.recover-prepared', () => {
|
|
1293
|
-
const run = readRun(resolved.taskDir);
|
|
1383
|
+
const run = readRun(resolved.taskDir, options);
|
|
1294
1384
|
const receipt = run?.pendingDelegation;
|
|
1295
1385
|
if (!run || !receipt) {
|
|
1296
1386
|
return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
@@ -1362,7 +1452,7 @@ function completeOrchestrationStage(
|
|
|
1362
1452
|
): OrchestrationResult {
|
|
1363
1453
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1364
1454
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1365
|
-
const run = readRun(resolved.taskDir);
|
|
1455
|
+
const run = readRun(resolved.taskDir, options);
|
|
1366
1456
|
if (!run) return { status: 'running', changed: false, taskId: resolved.taskId, run: null, next: null, error: null };
|
|
1367
1457
|
if (!run.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'active run has no pending delegation', resolved.taskId);
|
|
1368
1458
|
const result = completeDelegationStage(run.pendingDelegation, event);
|
|
@@ -1381,7 +1471,7 @@ function inspectOrchestrationStage(
|
|
|
1381
1471
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1382
1472
|
let run: OrchestrationRun | null;
|
|
1383
1473
|
try {
|
|
1384
|
-
run = readRun(resolved.taskDir);
|
|
1474
|
+
run = readRun(resolved.taskDir, options);
|
|
1385
1475
|
} catch (error) {
|
|
1386
1476
|
return failed('ORCHESTRATION_STATE_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
1387
1477
|
}
|
|
@@ -1442,7 +1532,7 @@ function sealOrchestrationDelegation(
|
|
|
1442
1532
|
): OrchestrationResult {
|
|
1443
1533
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1444
1534
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1445
|
-
const run = readRun(resolved.taskDir);
|
|
1535
|
+
const run = readRun(resolved.taskDir, options);
|
|
1446
1536
|
if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
1447
1537
|
const result = sealDelegation(run.pendingDelegation, event, { now: options.now });
|
|
1448
1538
|
if (!result.ok) return pauseOrchestration(taskRef, result.code, result.message, true, options);
|
|
@@ -1454,7 +1544,7 @@ function sealOrchestrationDelegation(
|
|
|
1454
1544
|
function advanceOrchestration(taskRef: string, options: OrchestrationOptions = {}): OrchestrationResult {
|
|
1455
1545
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1456
1546
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1457
|
-
const run = readRun(resolved.taskDir);
|
|
1547
|
+
const run = readRun(resolved.taskDir, options);
|
|
1458
1548
|
if (!run?.pendingDelegation) return failed('ORCHESTRATION_DELEGATION_MISSING', 'no pending delegation exists', resolved.taskId);
|
|
1459
1549
|
const result = consumeDelegation(run.pendingDelegation, { now: options.now });
|
|
1460
1550
|
if (!result.ok) return pauseOrchestration(taskRef, result.code, result.message, true, options);
|
|
@@ -1481,7 +1571,7 @@ function pauseOrchestration(
|
|
|
1481
1571
|
): OrchestrationResult {
|
|
1482
1572
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
1483
1573
|
if (!resolved.ok) return failed(resolved.code, resolved.message, resolved.taskId);
|
|
1484
|
-
const run = readRun(resolved.taskDir);
|
|
1574
|
+
const run = readRun(resolved.taskDir, options);
|
|
1485
1575
|
if (!run) return failed('ORCHESTRATION_RUN_MISSING', 'no orchestration run exists', resolved.taskId);
|
|
1486
1576
|
const updated = withUpdatedRun(run, { status: 'paused', pause: { code, message, recoverable } });
|
|
1487
1577
|
saveRun(resolved.taskDir, updated);
|