@fitlab-ai/agent-infra 0.9.10 → 0.9.12
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 +19 -9
- package/README.zh-CN.md +19 -9
- package/bin/cli.ts +17 -4
- package/dist/bin/cli.js +19 -4
- package/dist/bin/internal-cli.js +55 -4
- package/dist/lib/agent-client.js +0 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
- package/dist/lib/agent-clients/adapters/opencode-sandbox.js +0 -4
- package/dist/lib/agent-clients/adapters/traecli.js +7 -8
- package/dist/lib/agent-clients/config.js +14 -99
- package/dist/lib/agent-clients/reconcile.js +1 -11
- package/dist/lib/agent-clients/schema.js +5 -4
- package/dist/lib/agent-clients/tokens.js +5 -15
- package/dist/lib/decide.js +14 -30
- package/dist/lib/defaults.json +8 -0
- package/dist/lib/git/workflow.js +43 -1
- package/dist/lib/init.js +3 -2
- package/dist/lib/internal/git-workflow.js +8 -1
- package/dist/lib/internal/platform-pr.js +8 -2
- package/dist/lib/internal/release-workflow.js +0 -1
- package/dist/lib/internal/task-delivery.js +59 -0
- package/dist/lib/internal/task-finalization.js +19 -9
- package/dist/lib/internal/task-ledger.js +8 -2
- package/dist/lib/internal/task-lifecycle.js +17 -93
- package/dist/lib/internal/task-orchestration.js +30 -216
- package/dist/lib/internal/task-validate.js +2 -1
- package/dist/lib/merge.js +205 -103
- package/dist/lib/platform/github-client.js +7 -1
- package/dist/lib/platform/pr-checks.js +8 -5
- package/dist/lib/platform/pr-summary.js +12 -8
- package/dist/lib/platform/pull-requests.js +393 -91
- package/dist/lib/platform/verification-required.js +13 -2
- package/dist/lib/platform/verification-sync.js +9 -4
- package/dist/lib/pr-review/evidence-grading.js +12 -4
- package/dist/lib/process-data/normalize.js +2 -9
- package/dist/lib/run/host.js +46 -16
- package/dist/lib/sandbox/agent-client-reconciler.js +4 -12
- package/dist/lib/sandbox/commands/create.js +3 -3
- package/dist/lib/sandbox/commands/enter.js +18 -4
- package/dist/lib/sandbox/config.js +8 -12
- package/dist/lib/sandbox/control/executor.js +131 -39
- package/dist/lib/sandbox/control/lifecycle.js +55 -24
- package/dist/lib/sandbox/control/server.js +18 -16
- package/dist/lib/sandbox/mounts.js +3 -2
- package/dist/lib/sandbox/recovery.js +123 -22
- package/dist/lib/sandbox/workspace-identity.js +14 -0
- package/dist/lib/sandbox/workspace-view.js +8 -9
- package/dist/lib/self-update.js +278 -0
- package/dist/lib/server/process-state.js +2 -2
- package/dist/lib/server/protocol.js +5 -5
- package/dist/lib/task/activity-log.js +4 -1
- package/dist/lib/task/artifact-lifecycle.js +6 -4
- package/dist/lib/task/codex-orchestration.js +1 -1
- package/dist/lib/task/command-options.js +1 -3
- package/dist/lib/task/commands/cat.js +0 -5
- package/dist/lib/task/commands/decisions.js +76 -92
- package/dist/lib/task/commands/files.js +6 -6
- package/dist/lib/task/commands/grep.js +25 -61
- package/dist/lib/task/commands/issue-body.js +6 -6
- package/dist/lib/task/commands/log.js +25 -10
- package/dist/lib/task/commands/show.js +5 -6
- package/dist/lib/task/commands/status.js +8 -8
- package/dist/lib/task/commit-intent.js +100 -0
- package/dist/lib/task/commit-operation.js +181 -91
- package/dist/lib/task/commit-policy.js +1 -1
- package/dist/lib/task/control-authority.js +431 -0
- package/dist/lib/task/create.js +39 -8
- package/dist/lib/task/current-contract.js +35 -0
- package/dist/lib/task/decision-details.js +218 -0
- package/dist/lib/task/decision-intents.js +5 -2
- package/dist/lib/task/delivery-target.js +97 -0
- package/dist/lib/task/delivery.js +153 -0
- package/dist/lib/task/events.js +11 -5
- package/dist/lib/task/human-override.js +5 -2
- package/dist/lib/task/index.js +19 -20
- package/dist/lib/task/ledger-intents.js +8 -9
- package/dist/lib/task/ledger.js +13 -6
- package/dist/lib/task/lifecycle.js +122 -9
- package/dist/lib/task/orchestration.js +105 -75
- package/dist/lib/task/pr-delivery-fact.js +182 -0
- package/dist/lib/task/review-artifacts.js +31 -12
- package/dist/lib/task/review-finalization.js +13 -4
- package/dist/lib/task/review-fingerprint.js +8 -0
- package/dist/lib/task/verification-engine.js +86 -39
- package/dist/lib/task/verification-review.js +2 -2
- package/dist/lib/task/workspace-snapshot.js +5 -11
- package/dist/lib/task/write.js +11 -1
- package/dist/lib/update.js +13 -35
- package/dist/lib/version.js +5 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +0 -1
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
- package/lib/agent-clients/adapters/opencode-sandbox.ts +0 -5
- package/lib/agent-clients/adapters/traecli.ts +7 -8
- package/lib/agent-clients/config.ts +14 -144
- package/lib/agent-clients/reconcile.ts +1 -12
- package/lib/agent-clients/schema.ts +5 -4
- package/lib/agent-clients/tokens.ts +5 -18
- package/lib/decide.ts +12 -22
- package/lib/defaults.json +8 -0
- package/lib/git/workflow.ts +38 -1
- package/lib/init.ts +5 -2
- package/lib/internal/git-workflow.ts +7 -1
- package/lib/internal/platform-pr.ts +8 -1
- package/lib/internal/release-workflow.ts +0 -1
- package/lib/internal/task-delivery.ts +53 -0
- package/lib/internal/task-finalization.ts +27 -13
- package/lib/internal/task-ledger.ts +8 -2
- package/lib/internal/task-lifecycle.ts +33 -76
- package/lib/internal/task-orchestration.ts +33 -190
- package/lib/internal/task-validate.ts +3 -2
- package/lib/merge.ts +236 -120
- package/lib/platform/github-client.ts +8 -1
- package/lib/platform/pr-checks.ts +7 -5
- package/lib/platform/pr-summary.ts +10 -7
- package/lib/platform/pull-requests.ts +425 -87
- package/lib/platform/verification-required.ts +12 -2
- package/lib/platform/verification-sync.ts +9 -4
- package/lib/pr-review/evidence-grading.ts +7 -4
- package/lib/process-data/normalize.ts +2 -8
- package/lib/run/host.ts +63 -14
- package/lib/sandbox/agent-client-reconciler.ts +5 -15
- package/lib/sandbox/commands/create.ts +4 -4
- package/lib/sandbox/commands/enter.ts +24 -4
- package/lib/sandbox/config.ts +9 -14
- package/lib/sandbox/control/container-identity.ts +2 -2
- package/lib/sandbox/control/executor.ts +148 -51
- package/lib/sandbox/control/lifecycle.ts +59 -31
- package/lib/sandbox/control/protocol.ts +1 -3
- package/lib/sandbox/control/server.ts +15 -12
- package/lib/sandbox/control/state.ts +7 -7
- package/lib/sandbox/mounts.ts +4 -3
- package/lib/sandbox/recovery.ts +162 -34
- package/lib/sandbox/tools.ts +1 -1
- package/lib/sandbox/workspace-identity.ts +28 -0
- package/lib/sandbox/workspace-view.ts +14 -10
- package/lib/self-update.ts +341 -0
- package/lib/server/process-state.ts +2 -2
- package/lib/server/protocol.ts +5 -5
- package/lib/task/activity-log.ts +6 -1
- package/lib/task/artifact-lifecycle.ts +7 -5
- package/lib/task/codex-orchestration.ts +2 -1
- package/lib/task/command-options.ts +1 -2
- package/lib/task/commands/cat.ts +0 -4
- package/lib/task/commands/decisions.ts +80 -75
- package/lib/task/commands/files.ts +6 -6
- package/lib/task/commands/grep.ts +23 -51
- package/lib/task/commands/issue-body.ts +6 -6
- package/lib/task/commands/log.ts +22 -10
- package/lib/task/commands/show.ts +5 -6
- package/lib/task/commands/status.ts +8 -8
- package/lib/task/commit-intent.ts +137 -0
- package/lib/task/commit-operation.ts +161 -79
- package/lib/task/commit-policy.ts +1 -2
- package/lib/task/control-authority.ts +563 -0
- package/lib/task/create.ts +40 -10
- package/lib/task/current-contract.ts +49 -0
- package/lib/task/decision-details.ts +280 -0
- package/lib/task/decision-intents.ts +7 -2
- package/lib/task/delivery-target.ts +130 -0
- package/lib/task/delivery.ts +160 -0
- package/lib/task/events.ts +10 -5
- package/lib/task/human-override.ts +5 -2
- package/lib/task/index.ts +19 -20
- package/lib/task/ledger-intents.ts +6 -8
- package/lib/task/ledger.ts +17 -7
- package/lib/task/lifecycle.ts +113 -4
- package/lib/task/orchestration.ts +102 -80
- package/lib/task/pr-delivery-fact.ts +254 -0
- package/lib/task/review-artifacts.ts +53 -15
- package/lib/task/review-finalization.ts +21 -5
- package/lib/task/review-fingerprint.ts +10 -0
- package/lib/task/verification-engine.ts +78 -46
- package/lib/task/verification-review.ts +3 -1
- package/lib/task/workspace-snapshot.ts +4 -13
- package/lib/task/write.ts +20 -1
- package/lib/update.ts +14 -38
- package/lib/version.ts +6 -1
- package/package.json +1 -1
- package/templates/.agents/README.en.md +5 -3
- package/templates/.agents/README.zh-CN.md +5 -3
- package/templates/.agents/rules/README.en.md +4 -2
- package/templates/.agents/rules/README.zh-CN.md +4 -2
- package/templates/.agents/rules/compatibility-policy.en.md +5 -4
- package/templates/.agents/rules/compatibility-policy.zh-CN.md +5 -4
- package/templates/.agents/rules/create-issue.en.md +11 -2
- package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
- package/templates/.agents/rules/human-decision-context.en.md +9 -7
- package/templates/.agents/rules/human-decision-context.zh-CN.md +9 -7
- package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +1 -1
- package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +1 -1
- package/templates/.agents/rules/issue-pr-commands.en.md +5 -18
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +26 -5
- package/templates/.agents/rules/issue-sync.zh-CN.md +62 -5
- package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
- package/templates/.agents/rules/local-artifact-repair.en.md +46 -0
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +46 -0
- package/templates/.agents/rules/milestone-inference.en.md +12 -2
- package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
- package/templates/.agents/rules/next-step-output.en.md +3 -3
- package/templates/.agents/rules/next-step-output.zh-CN.md +3 -3
- package/templates/.agents/rules/no-mid-flow-questions.en.md +1 -1
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +1 -1
- package/templates/.agents/rules/pr-sync.en.md +23 -14
- package/templates/.agents/rules/pr-sync.zh-CN.md +23 -2
- package/templates/.agents/rules/release-commands.en.md +42 -3
- package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
- package/templates/.agents/rules/review-handshake.en.md +1 -1
- package/templates/.agents/rules/review-handshake.zh-CN.md +1 -1
- package/templates/.agents/rules/security-alerts.en.md +17 -2
- package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
- package/templates/.agents/rules/sync-content-generation.en.md +8 -0
- package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
- package/templates/.agents/rules/task-management.en.md +2 -3
- package/templates/.agents/rules/task-management.zh-CN.md +2 -3
- package/templates/.agents/scripts/security-alerts.github.sh +151 -0
- package/templates/.agents/scripts/security-alerts.sh +31 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +4 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.en.md +3 -3
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +3 -3
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/code-task/SKILL.en.md +8 -5
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +9 -6
- package/templates/.agents/skills/commit/SKILL.en.md +30 -10
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +6 -7
- package/templates/.agents/skills/commit/config/verify.json +1 -1
- package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
- package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +7 -6
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +7 -6
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +13 -13
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +13 -13
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.en.md +9 -11
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +9 -11
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +9 -4
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +9 -4
- package/templates/.agents/skills/create-pr/scripts/change-report.mjs +203 -0
- package/templates/.agents/skills/create-release-note/SKILL.en.md +5 -6
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +5 -6
- package/templates/.agents/skills/create-task/SKILL.en.md +2 -1
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +2 -1
- 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/import-issue/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
- package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
- package/templates/.agents/skills/plan-task/SKILL.en.md +4 -3
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/restore-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +8 -5
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +8 -5
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +11 -8
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +11 -8
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.en.md +2 -1
- package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +2 -1
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
- package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
- package/templates/.agents/skills/review-plan/SKILL.en.md +8 -5
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +8 -5
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -0
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -0
- package/templates/.agents/skills/run-task/SKILL.en.md +5 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +2 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +144 -109
- package/templates/.agents/skills/watch-pr/SKILL.en.md +5 -5
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +5 -5
- package/templates/.agents/templates/task.en.md +6 -2
- package/templates/.agents/templates/task.zh-CN.md +6 -2
- package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
- package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/feature-development.en.yaml +9 -8
- package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/refactoring.en.yaml +9 -8
- package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
- package/templates/.claude/commands/analyze-task.en.md +1 -1
- package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
- package/templates/.claude/commands/block-task.en.md +1 -1
- package/templates/.claude/commands/block-task.zh-CN.md +1 -1
- package/templates/.claude/commands/cancel-task.en.md +1 -1
- package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
- package/templates/.claude/commands/check-task.en.md +1 -1
- package/templates/.claude/commands/check-task.zh-CN.md +1 -1
- package/templates/.claude/commands/code-task.en.md +1 -1
- package/templates/.claude/commands/code-task.zh-CN.md +1 -1
- package/templates/.claude/commands/commit.en.md +1 -1
- package/templates/.claude/commands/commit.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-task.en.md +1 -1
- package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
- package/templates/.claude/commands/create-pr.en.md +1 -1
- package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
- package/templates/.claude/commands/plan-task.en.md +1 -1
- package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
- package/templates/.claude/commands/review-analysis.en.md +1 -1
- package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
- package/templates/.claude/commands/review-code.en.md +1 -1
- package/templates/.claude/commands/review-code.zh-CN.md +1 -1
- package/templates/.claude/commands/review-plan.en.md +1 -1
- package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
- package/templates/.claude/commands/run-manual-validation.en.md +1 -1
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/run-task.en.md +1 -1
- package/templates/.claude/commands/run-task.zh-CN.md +1 -1
- package/templates/.claude/commands/watch-pr.en.md +1 -1
- package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
- package/templates/{.trae/skills → .traecli/commands}/update-agent-infra.en.md +0 -1
- package/templates/{.trae/skills → .traecli/commands}/update-agent-infra.zh-CN.md +0 -1
- package/dist/lib/builtin-tuis.js +0 -40
- package/lib/builtin-tuis.ts +0 -56
- package/templates/.agents/rules/create-issue.github.en.md +0 -14
- package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
- package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
- package/templates/.agents/rules/issue-sync.github.en.md +0 -40
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
- package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
- package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
- package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
- package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
- package/templates/.agents/rules/pr-sync.github.en.md +0 -43
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
- package/templates/.agents/rules/release-commands.github.en.md +0 -38
- package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -38
- package/templates/.agents/rules/security-alerts.github.en.md +0 -43
- package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
|
@@ -18,6 +18,21 @@ type ReviewSummaryErrorCode =
|
|
|
18
18
|
| 'REVIEW_SUMMARY_NOT_FOUND'
|
|
19
19
|
| 'REVIEW_SUMMARY_PLACEHOLDER_INVALID'
|
|
20
20
|
| 'REVIEW_SUMMARY_COUNT_MISMATCH';
|
|
21
|
+
type VerdictSemanticErrorCode =
|
|
22
|
+
| 'REVIEW_VERDICT_FINDING_MISMATCH'
|
|
23
|
+
| 'REVIEW_FINDING_COUNTS_NOT_FINALIZED';
|
|
24
|
+
type CanonicalVerdictResult =
|
|
25
|
+
| { ok: true; verdict: ReviewVerdict }
|
|
26
|
+
| { ok: false; verdict: null; code: VerdictSemanticErrorCode; message: string };
|
|
27
|
+
type PathVerdictErrorCode =
|
|
28
|
+
| 'REVIEW_ARTIFACT_NOT_FOUND'
|
|
29
|
+
| 'REVIEW_ARTIFACT_READ_FAILED'
|
|
30
|
+
| 'REVIEW_SUMMARY_NOT_FOUND'
|
|
31
|
+
| 'REVIEW_SUMMARY_PLACEHOLDER_INVALID'
|
|
32
|
+
| VerdictSemanticErrorCode;
|
|
33
|
+
type PathVerdictResult =
|
|
34
|
+
| { ok: true; verdict: ReviewVerdict }
|
|
35
|
+
| { ok: false; verdict: null; code: PathVerdictErrorCode; message: string };
|
|
21
36
|
type ReviewSummaryParseResult =
|
|
22
37
|
| { ok: true; summary: ReviewSummary; findingsStart: number; findingsEnd: number }
|
|
23
38
|
| { ok: false; code: ReviewSummaryErrorCode; message: string };
|
|
@@ -203,28 +218,46 @@ function finalizeReviewSummaryContent(
|
|
|
203
218
|
};
|
|
204
219
|
}
|
|
205
220
|
|
|
206
|
-
function
|
|
207
|
-
|
|
208
|
-
|
|
221
|
+
function resolveCanonicalVerdict(summary: ReviewSummary): CanonicalVerdictResult {
|
|
222
|
+
if (summary.counts === null) {
|
|
223
|
+
return {
|
|
224
|
+
ok: false,
|
|
225
|
+
verdict: null,
|
|
226
|
+
code: 'REVIEW_FINDING_COUNTS_NOT_FINALIZED',
|
|
227
|
+
message: 'review summary finding counts are not finalized'
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
if (summary.verdict === 'Approved' && !equalCounts(summary.counts, { blocker: 0, major: 0, minor: 0 })) {
|
|
231
|
+
return {
|
|
232
|
+
ok: false,
|
|
233
|
+
verdict: null,
|
|
234
|
+
code: 'REVIEW_VERDICT_FINDING_MISMATCH',
|
|
235
|
+
message: 'Approved verdict requires zero finalized findings'
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return { ok: true, verdict: summary.verdict };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function parseVerdict(reviewPath: string): PathVerdictResult {
|
|
209
242
|
if (!fs.existsSync(reviewPath)) {
|
|
210
|
-
return { ok: false, verdict: null, message: `Review artifact not found: ${path.basename(reviewPath)}` };
|
|
243
|
+
return { ok: false, verdict: null, code: 'REVIEW_ARTIFACT_NOT_FOUND', message: `Review artifact not found: ${path.basename(reviewPath)}` };
|
|
244
|
+
}
|
|
245
|
+
let content: string;
|
|
246
|
+
try {
|
|
247
|
+
content = fs.readFileSync(reviewPath, 'utf8');
|
|
248
|
+
} catch (error) {
|
|
249
|
+
return { ok: false, verdict: null, code: 'REVIEW_ARTIFACT_READ_FAILED', message: `Review artifact could not be read: ${String(error)}` };
|
|
211
250
|
}
|
|
212
|
-
const parsed = parseReviewSummary(
|
|
251
|
+
const parsed = parseReviewSummary(content);
|
|
213
252
|
if (!parsed.ok) {
|
|
214
253
|
return {
|
|
215
254
|
ok: false,
|
|
216
255
|
verdict: null,
|
|
256
|
+
code: parsed.code === 'REVIEW_SUMMARY_PLACEHOLDER_INVALID' ? parsed.code : 'REVIEW_SUMMARY_NOT_FOUND',
|
|
217
257
|
message: `cannot parse review summary in ${path.basename(reviewPath)}: ${parsed.message}`
|
|
218
258
|
};
|
|
219
259
|
}
|
|
220
|
-
|
|
221
|
-
if (verdict !== 'Approved') return { ok: true, verdict };
|
|
222
|
-
return {
|
|
223
|
-
ok: true,
|
|
224
|
-
verdict: counts && equalCounts(counts, { blocker: 0, major: 0, minor: 0 })
|
|
225
|
-
? 'Approved'
|
|
226
|
-
: 'Approved-with-issues'
|
|
227
|
-
};
|
|
260
|
+
return resolveCanonicalVerdict(parsed.summary);
|
|
228
261
|
}
|
|
229
262
|
|
|
230
263
|
export {
|
|
@@ -236,13 +269,18 @@ export {
|
|
|
236
269
|
maxRound,
|
|
237
270
|
normalizeVerdict,
|
|
238
271
|
parseReviewSummary,
|
|
239
|
-
parseVerdict
|
|
272
|
+
parseVerdict,
|
|
273
|
+
resolveCanonicalVerdict
|
|
240
274
|
};
|
|
241
275
|
export type {
|
|
276
|
+
CanonicalVerdictResult,
|
|
277
|
+
PathVerdictErrorCode,
|
|
278
|
+
PathVerdictResult,
|
|
242
279
|
ReviewFindingCounts,
|
|
243
280
|
ReviewSummary,
|
|
244
281
|
ReviewSummaryErrorCode,
|
|
245
282
|
ReviewSummaryFinalizeResult,
|
|
246
283
|
ReviewSummaryParseResult,
|
|
247
|
-
ReviewVerdict
|
|
284
|
+
ReviewVerdict,
|
|
285
|
+
VerdictSemanticErrorCode
|
|
248
286
|
};
|
|
@@ -2,11 +2,12 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
|
|
5
|
-
import { locateActivityLog, pairEntries } from './activity-log.ts';
|
|
5
|
+
import { locateActivityLog, pairEntries, startedBackedRows } from './activity-log.ts';
|
|
6
6
|
import { parseArtifactName, validateCompletedArtifact } from './artifact-lifecycle.ts';
|
|
7
|
-
import {
|
|
7
|
+
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.ts';
|
|
8
8
|
import type { LedgerStageStatus, ReviewStage } from './ledger.ts';
|
|
9
9
|
import { finalizeReviewSummaryContent } from './review-artifacts.ts';
|
|
10
|
+
import { inspectDecisionDetailDuplicates } from './decision-details.ts';
|
|
10
11
|
import { resolveTaskRef } from './resolve-ref.ts';
|
|
11
12
|
import { validateLifecycleExecution } from './lifecycle-execution.ts';
|
|
12
13
|
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.ts';
|
|
@@ -25,6 +26,7 @@ type ReviewFinalizationErrorCode =
|
|
|
25
26
|
| 'REVIEW_SUMMARY_NOT_FOUND'
|
|
26
27
|
| 'REVIEW_SUMMARY_PLACEHOLDER_INVALID'
|
|
27
28
|
| 'REVIEW_SUMMARY_COUNT_MISMATCH'
|
|
29
|
+
| 'REVIEW_DECISION_DETAIL_INVALID'
|
|
28
30
|
| 'REVIEW_ARTIFACT_CONFLICT'
|
|
29
31
|
| 'REVIEW_PROVENANCE_INVALID'
|
|
30
32
|
| 'REVIEW_TEMP_WRITE_FAILED'
|
|
@@ -106,8 +108,8 @@ function openReviewRound(content: string, action: string, round: number): boolea
|
|
|
106
108
|
const section = locateActivityLog(content);
|
|
107
109
|
if (!section) return false;
|
|
108
110
|
const expected = `${action} (Round ${round})`;
|
|
109
|
-
return pairEntries(section.entries).filter((row) => (
|
|
110
|
-
row.step === expected &&
|
|
111
|
+
return startedBackedRows(pairEntries(section.entries)).filter((row) => (
|
|
112
|
+
row.step === expected && !row.done
|
|
111
113
|
)).length === 1;
|
|
112
114
|
}
|
|
113
115
|
|
|
@@ -194,7 +196,11 @@ function finalizeReviewSummaryUnlocked(
|
|
|
194
196
|
|
|
195
197
|
let rows;
|
|
196
198
|
try {
|
|
197
|
-
|
|
199
|
+
const ledger = parseLedgerDocument(taskContent);
|
|
200
|
+
if (!ledger.present) {
|
|
201
|
+
return failed(request, 'REVIEW_LEDGER_INVALID', `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`, resolved.taskId);
|
|
202
|
+
}
|
|
203
|
+
rows = ledger.rows;
|
|
198
204
|
} catch (error) {
|
|
199
205
|
return failed(request, 'REVIEW_LEDGER_INVALID', String(error), resolved.taskId);
|
|
200
206
|
}
|
|
@@ -208,6 +214,16 @@ function finalizeReviewSummaryUnlocked(
|
|
|
208
214
|
);
|
|
209
215
|
}
|
|
210
216
|
const stageStatus = summarizeLedgerStage(rows, stage);
|
|
217
|
+
const detailInspection = inspectDecisionDetailDuplicates(artifactContent);
|
|
218
|
+
if (!detailInspection.ok) {
|
|
219
|
+
return failed(
|
|
220
|
+
request,
|
|
221
|
+
'REVIEW_DECISION_DETAIL_INVALID',
|
|
222
|
+
`${detailInspection.code}: ${detailInspection.message}`,
|
|
223
|
+
resolved.taskId,
|
|
224
|
+
stageStatus
|
|
225
|
+
);
|
|
226
|
+
}
|
|
211
227
|
const transformed = finalizeReviewSummaryContent(
|
|
212
228
|
artifactContent,
|
|
213
229
|
stageStatus.unresolvedFindingCounts
|
|
@@ -63,6 +63,16 @@ export function extractReviewBaseline(content: string): string {
|
|
|
63
63
|
return match ? match[1]!.trim().replace(/`/g, "") : "";
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
export function extractReviewTargetHead(content: string): string {
|
|
67
|
+
const match = String(content).match(/^[-*]?\s*\*\*(?:审查目标提交|审查目标 HEAD|Review Target Commit|Review Target Head)\*\*[::]\s*(.*?)\s*$/m);
|
|
68
|
+
return match ? match[1]!.trim().replace(/`/g, "") : "";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function extractReviewedHead(content: string): string {
|
|
72
|
+
const match = String(content).match(/^[-*]?\s*\*\*(?:审查已检视提交|已检视提交|Reviewed Head Commit|Reviewed Head)\*\*[::]\s*(.*?)\s*$/m);
|
|
73
|
+
return match ? match[1]!.trim().replace(/`/g, "") : "";
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
export function extractReviewDiffBase(content: string): string {
|
|
67
77
|
const match = String(content).match(/^[-*]?\s*\*\*(?:审查差异基线|Reviewed Diff Base)\*\*[::]\s*(.*?)\s*$/m);
|
|
68
78
|
return match ? match[1]!.trim().replace(/`/g, "") : "";
|
|
@@ -7,6 +7,8 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
extractReviewBaseline,
|
|
10
|
+
extractReviewTargetHead,
|
|
11
|
+
extractReviewedHead,
|
|
10
12
|
extractReviewDiffBase,
|
|
11
13
|
extractReviewDiffFingerprint,
|
|
12
14
|
extractReviewedSnapshotTree,
|
|
@@ -22,12 +24,16 @@ import { resolveMaterializedReviewedHeadRelation } from "../platform/change-requ
|
|
|
22
24
|
import { resolveReviewedHeadRelation } from "../platform/merged-pr-equivalence.ts";
|
|
23
25
|
import { resolveLocalReviewedCommitRelation } from "../git/reviewed-commit-equivalence.ts";
|
|
24
26
|
import { parseTypedTaskFrontmatter } from "./frontmatter.ts";
|
|
25
|
-
import {
|
|
27
|
+
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from "./ledger.ts";
|
|
26
28
|
import type { LedgerRow } from "./ledger.ts";
|
|
29
|
+
import { isValidAgentInfraVersion } from "../version.ts";
|
|
27
30
|
import { equalCounts, parseReviewSummary } from "./review-artifacts.ts";
|
|
31
|
+
import { inspectDecisionDetailDuplicates } from "./decision-details.ts";
|
|
28
32
|
import { loadVerificationConfig } from "./verification-config.ts";
|
|
29
33
|
import { snapshotReview } from "../git/review-snapshot.ts";
|
|
30
34
|
import { OrchestrationStateError, readRun } from "./orchestration.ts";
|
|
35
|
+
import { resolveDeliveryTarget } from "./delivery-target.ts";
|
|
36
|
+
import { readPrDeliveryFact } from "./pr-delivery-fact.ts";
|
|
31
37
|
|
|
32
38
|
const TASK_ENUMS = {
|
|
33
39
|
type: ["feature", "bugfix", "refactor", "docs", "chore"],
|
|
@@ -48,7 +54,6 @@ const DEFAULT_REQUIRED_FIELDS = [
|
|
|
48
54
|
];
|
|
49
55
|
|
|
50
56
|
const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
|
|
51
|
-
const AGENT_INFRA_VERSION_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
52
57
|
const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
|
|
53
58
|
// Start markers (action suffixed with ` [started]`) are excluded from the
|
|
54
59
|
// "latest action" / freshness computation so a step's in-flight marker never
|
|
@@ -108,6 +113,8 @@ function runCheck(type: any, context: any, shared: any): any {
|
|
|
108
113
|
return checkTaskMeta(context);
|
|
109
114
|
case "artifact":
|
|
110
115
|
return checkArtifact(context);
|
|
116
|
+
case "decision-details":
|
|
117
|
+
return checkDecisionDetails(context);
|
|
111
118
|
case "implementation-input":
|
|
112
119
|
return checkImplementationInput(context);
|
|
113
120
|
case "activity-log":
|
|
@@ -192,15 +199,14 @@ function validateCleanCompletionEvidence(run: any): string | null {
|
|
|
192
199
|
|| !shaPattern.test(evidence.headTree)
|
|
193
200
|
|| !shaPattern.test(evidence.worktreeTree)
|
|
194
201
|
|| !shaPattern.test(evidence.lastReviewedCommit)
|
|
195
|
-
|| !Number.isInteger(evidence.prNumber)
|
|
196
|
-
|| evidence.
|
|
197
|
-
|| !shaPattern.test(evidence.prHead)
|
|
202
|
+
|| !(evidence.prNumber === null || (Number.isInteger(evidence.prNumber) && evidence.prNumber > 0))
|
|
203
|
+
|| !(evidence.prHead === null || shaPattern.test(evidence.prHead))
|
|
198
204
|
) {
|
|
199
205
|
return 'Clean completion evidence has an invalid structure';
|
|
200
206
|
}
|
|
201
207
|
if (
|
|
202
208
|
evidence.head !== evidence.lastReviewedCommit
|
|
203
|
-
|| evidence.head !== evidence.prHead
|
|
209
|
+
|| (evidence.prHead !== null && evidence.head !== evidence.prHead)
|
|
204
210
|
|| evidence.headTree !== evidence.worktreeTree
|
|
205
211
|
) {
|
|
206
212
|
return 'Clean completion evidence does not bind matching commit and tree identities';
|
|
@@ -273,12 +279,8 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
273
279
|
if (run.completionEvidence != null) {
|
|
274
280
|
const evidenceError = validateCleanCompletionEvidence(run);
|
|
275
281
|
if (evidenceError) return failResult('orchestration-evidence', evidenceError);
|
|
276
|
-
} else if (run.status === 'completed'
|
|
277
|
-
|
|
278
|
-
|| run.receipts.at(-1)?.stage !== 'commit'
|
|
279
|
-
|| run.receipts.at(-1)?.status !== 'consumed'
|
|
280
|
-
)) {
|
|
281
|
-
return failResult('orchestration-evidence', 'Completed run requires a final consumed commit receipt');
|
|
282
|
+
} else if (run.status === 'completed') {
|
|
283
|
+
return failResult('orchestration-evidence', 'Completed run requires reviewed-head-clean completion evidence');
|
|
282
284
|
}
|
|
283
285
|
if (run.pendingDelegation && !['prepared', 'activated', 'stage-completed'].includes(run.pendingDelegation.status)) {
|
|
284
286
|
return failResult('orchestration-evidence', `Pending receipt has unsafe status '${run.pendingDelegation.status}'`);
|
|
@@ -392,23 +394,20 @@ function checkTaskMeta({ taskDir, config }: any): any {
|
|
|
392
394
|
const metadata = task.metadata;
|
|
393
395
|
const requiredFields = config.required_fields || DEFAULT_REQUIRED_FIELDS;
|
|
394
396
|
const missingFields = requiredFields.filter((field: any) => isBlank(metadata[field]));
|
|
395
|
-
const
|
|
397
|
+
const currentTask = metadata.status === 'active';
|
|
398
|
+
const blockingMissingFields = missingFields.filter((field: any) => field !== "agent_infra_version" || currentTask);
|
|
396
399
|
const warnings = [];
|
|
397
|
-
if (missingFields.includes("agent_infra_version")) {
|
|
400
|
+
if (missingFields.includes("agent_infra_version") && !currentTask) {
|
|
398
401
|
warnings.push("field 'agent_infra_version' missing — historical task or skipped version stamp");
|
|
399
402
|
}
|
|
400
403
|
if (blockingMissingFields.length > 0) {
|
|
401
404
|
return failResult("task-meta", `Missing required fields: ${blockingMissingFields.join(", ")}`);
|
|
402
405
|
}
|
|
403
406
|
|
|
404
|
-
if (
|
|
405
|
-
!isBlank(metadata.agent_infra_version) &&
|
|
406
|
-
metadata.agent_infra_version !== "unknown" &&
|
|
407
|
-
!AGENT_INFRA_VERSION_PATTERN.test(metadata.agent_infra_version)
|
|
408
|
-
) {
|
|
407
|
+
if (currentTask && !isValidAgentInfraVersion(metadata.agent_infra_version)) {
|
|
409
408
|
return failResult(
|
|
410
409
|
"task-meta",
|
|
411
|
-
`Invalid agent_infra_version: ${metadata.agent_infra_version}`
|
|
410
|
+
`Invalid agent_infra_version: ${String(metadata.agent_infra_version ?? 'missing')}`
|
|
412
411
|
);
|
|
413
412
|
}
|
|
414
413
|
|
|
@@ -500,18 +499,18 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }: any): any {
|
|
|
500
499
|
return failResult('required-pr-delivery', 'Project configuration is invalid');
|
|
501
500
|
}
|
|
502
501
|
const flow = projectConfig.prFlow;
|
|
503
|
-
const
|
|
504
|
-
|
|
502
|
+
const factRead = readPrDeliveryFact(task.metadata);
|
|
503
|
+
if (factRead.status === 'invalid') return failResult('required-pr-delivery', factRead.error.message);
|
|
504
|
+
const fact = factRead.status === 'valid' ? factRead.fact : null;
|
|
505
|
+
const status = fact?.state || 'unbound';
|
|
506
|
+
const prNumber = fact?.state === 'bound' ? fact.identity.number : null;
|
|
505
507
|
if (flow === 'disabled') return passResult('required-pr-delivery', 'Pull request delivery is disabled by project policy');
|
|
506
|
-
if (flow === 'required' && (status !== '
|
|
508
|
+
if (flow === 'required' && (status !== 'bound' || prNumber === null)) {
|
|
507
509
|
return failResult('required-pr-delivery', 'Project policy requires a bound pull request before completion');
|
|
508
510
|
}
|
|
509
|
-
if (flow !== 'required' && status === '
|
|
511
|
+
if (flow !== 'required' && status === 'unbound') {
|
|
510
512
|
return failResult('required-pr-delivery', 'Pull request delivery is pending; create a PR or explicitly skip it');
|
|
511
513
|
}
|
|
512
|
-
if (status === 'created' && prNumber === null) {
|
|
513
|
-
return failResult('required-pr-delivery', 'Task claims a created pull request without a valid pr_number');
|
|
514
|
-
}
|
|
515
514
|
if (flow === 'required') {
|
|
516
515
|
if (mode === 'gate') {
|
|
517
516
|
return passResult('required-pr-delivery', 'Bound pull request shape is valid; merged-state inspection is reserved for hard preflight');
|
|
@@ -527,6 +526,7 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }: any): any {
|
|
|
527
526
|
const pullRequest = inspected.pullRequest;
|
|
528
527
|
const repository = inspected.platform.repository?.toLowerCase() || '';
|
|
529
528
|
const taskBranch = String(task.metadata.branch || '').trim();
|
|
529
|
+
const deliveryBaseRef = String(task.metadata.delivery_base_ref || projectConfig.delivery?.baseRef || '').trim();
|
|
530
530
|
if (inspected.status !== 'no-op' || !pullRequest || pullRequest.number !== prNumber) {
|
|
531
531
|
return failResult('required-pr-delivery', 'Bound pull request identity could not be verified');
|
|
532
532
|
}
|
|
@@ -535,6 +535,7 @@ function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }: any): any {
|
|
|
535
535
|
|| pullRequest.repository.toLowerCase() !== repository
|
|
536
536
|
|| pullRequest.base.repository.toLowerCase() !== repository
|
|
537
537
|
|| (taskBranch && pullRequest.head.ref !== taskBranch)
|
|
538
|
+
|| (deliveryBaseRef && pullRequest.base.ref !== deliveryBaseRef)
|
|
538
539
|
) {
|
|
539
540
|
return failResult('required-pr-delivery', 'Bound pull request identity does not match the task');
|
|
540
541
|
}
|
|
@@ -622,6 +623,18 @@ function checkArtifact({ taskDir, config, artifactFile }: any): any {
|
|
|
622
623
|
);
|
|
623
624
|
}
|
|
624
625
|
|
|
626
|
+
function checkDecisionDetails({ taskDir, artifactFile }: any): any {
|
|
627
|
+
const resolvedArtifact = resolveArtifactPath(taskDir, "", artifactFile);
|
|
628
|
+
if (!resolvedArtifact.ok) return failResult("decision-details", resolvedArtifact.message);
|
|
629
|
+
const artifactPath = resolvedArtifact.path;
|
|
630
|
+
const stat = safeStat(artifactPath);
|
|
631
|
+
if (!stat?.isFile()) return failResult("decision-details", `Artifact not found: ${path.basename(artifactPath)}`);
|
|
632
|
+
if (stat.size === 0) return passResult("decision-details", `${path.basename(artifactPath)} contains no decision details`);
|
|
633
|
+
const inspection = inspectDecisionDetailDuplicates(fs.readFileSync(artifactPath, "utf8"));
|
|
634
|
+
if (!inspection.ok) return failResult("decision-details", `${path.basename(artifactPath)}: ${inspection.message}`);
|
|
635
|
+
return passResult("decision-details", `${path.basename(artifactPath)} has no duplicate decision detail ids`);
|
|
636
|
+
}
|
|
637
|
+
|
|
625
638
|
function checkReviewSummary({ taskDir, config, artifactFile }: any): any {
|
|
626
639
|
const stage = String(config.stage || "");
|
|
627
640
|
if (!["analysis", "plan", "code"].includes(stage)) {
|
|
@@ -640,7 +653,9 @@ function checkReviewSummary({ taskDir, config, artifactFile }: any): any {
|
|
|
640
653
|
if (!task.ok) return failResult("review-summary", task.message);
|
|
641
654
|
let rows;
|
|
642
655
|
try {
|
|
643
|
-
|
|
656
|
+
const ledger = parseLedgerDocument(task.content);
|
|
657
|
+
if (!ledger.present) return failResult("review-summary", `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`);
|
|
658
|
+
rows = ledger.rows;
|
|
644
659
|
} catch (error) {
|
|
645
660
|
return failResult("review-summary", `Invalid disagreement ledger: ${String(error)}`);
|
|
646
661
|
}
|
|
@@ -946,14 +961,11 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
946
961
|
return failResult("review-ledger", task.message);
|
|
947
962
|
}
|
|
948
963
|
|
|
949
|
-
const section = getSectionContent(task.content, LEDGER_SECTION_NAMES);
|
|
950
|
-
if (!section.trim()) {
|
|
951
|
-
return passResult("review-ledger", "No disagreement ledger section; treated as no open disagreements");
|
|
952
|
-
}
|
|
953
|
-
|
|
954
964
|
let rows;
|
|
955
965
|
try {
|
|
956
|
-
|
|
966
|
+
const ledger = parseLedgerDocument(task.content);
|
|
967
|
+
if (!ledger.present) return failResult("review-ledger", `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`);
|
|
968
|
+
rows = ledger.rows.map((row) => [
|
|
957
969
|
row.id, row.stage, row.round, row.severity, row.status, row.evidence
|
|
958
970
|
]);
|
|
959
971
|
} catch (error) {
|
|
@@ -1099,9 +1111,12 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
|
|
|
1099
1111
|
|
|
1100
1112
|
const task = loadTask(taskDir);
|
|
1101
1113
|
if (!task.ok) return failResult("post-review-commit", task.message);
|
|
1114
|
+
const factRead = readPrDeliveryFact(task.metadata);
|
|
1115
|
+
if (factRead.status === 'invalid') return failResult("post-review-commit", factRead.error.message);
|
|
1116
|
+
const fact = factRead.status === 'valid' ? factRead.fact : null;
|
|
1102
1117
|
const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
|
|
1103
1118
|
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repoRoot));
|
|
1104
|
-
const hasPullRequest =
|
|
1119
|
+
const hasPullRequest = fact?.state === 'bound';
|
|
1105
1120
|
let inspected: ReturnType<typeof inspectPlatformPullRequest> | null = null;
|
|
1106
1121
|
if (hasPullRequest) {
|
|
1107
1122
|
inspected = inspectPlatformPullRequest(task.metadata.id, { cwd: gitRoot });
|
|
@@ -1248,7 +1263,11 @@ function resolvePostReviewExemption(content: string):
|
|
|
1248
1263
|
| { ok: true; exemptions: readonly LedgerRow[] }
|
|
1249
1264
|
| { ok: false; code: "POST_REVIEW_EXEMPTION_INVALID"; message: string } {
|
|
1250
1265
|
try {
|
|
1251
|
-
const
|
|
1266
|
+
const ledger = parseLedgerDocument(content);
|
|
1267
|
+
if (!ledger.present) {
|
|
1268
|
+
return { ok: false, code: "POST_REVIEW_EXEMPTION_INVALID", message: `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}` };
|
|
1269
|
+
}
|
|
1270
|
+
const rows = ledger.rows;
|
|
1252
1271
|
const invalid = validateLedgerRows(rows);
|
|
1253
1272
|
if (invalid) {
|
|
1254
1273
|
return {
|
|
@@ -1287,7 +1306,8 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
|
1287
1306
|
|
|
1288
1307
|
const content = fs.readFileSync(resolvedArtifact.path, "utf8");
|
|
1289
1308
|
const verdict = parseReviewVerdict(content);
|
|
1290
|
-
const
|
|
1309
|
+
const reviewTargetHead = extractReviewTargetHead(content);
|
|
1310
|
+
const reviewReviewedHead = extractReviewedHead(content);
|
|
1291
1311
|
const reviewDiffBase = extractReviewDiffBase(content);
|
|
1292
1312
|
const reviewedFingerprint = extractReviewDiffFingerprint(content);
|
|
1293
1313
|
const reviewedTree = extractReviewedSnapshotTree(content);
|
|
@@ -1296,30 +1316,42 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
|
1296
1316
|
return failResult("review-fact", `Unsupported review verdict '${verdict}'`);
|
|
1297
1317
|
}
|
|
1298
1318
|
|
|
1319
|
+
const deliveryRemote = String(task.metadata.delivery_remote || "").trim();
|
|
1320
|
+
const deliveryBaseRef = String(task.metadata.delivery_base_ref || "").trim();
|
|
1321
|
+
if (!deliveryRemote || !deliveryBaseRef) {
|
|
1322
|
+
return failResult("review-fact", "Task delivery target is not bound; re-run task branch preparation before review-code");
|
|
1323
|
+
}
|
|
1324
|
+
if (!reviewTargetHead || !reviewReviewedHead || !reviewDiffBase) {
|
|
1325
|
+
return failResult("review-fact", "Review fact must record target head, reviewed head, and diff base");
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1299
1328
|
let gitRoot;
|
|
1300
1329
|
let head;
|
|
1301
1330
|
let baseline;
|
|
1331
|
+
let targetHead;
|
|
1302
1332
|
let diffBase;
|
|
1303
1333
|
try {
|
|
1304
1334
|
gitRoot = execFileSync("git", ["-C", taskDir, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
|
|
1305
1335
|
head = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
).trim();
|
|
1336
|
+
const target = resolveDeliveryTarget(gitRoot, { remote: deliveryRemote, baseRef: deliveryBaseRef });
|
|
1337
|
+
if (!target.ok) throw new Error(target.message);
|
|
1338
|
+
const reviewedRef = reviewReviewedHead;
|
|
1339
|
+
baseline = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewedRef}^{commit}`], { encoding: "utf8" }).trim();
|
|
1340
|
+
targetHead = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewTargetHead}^{commit}`], { encoding: "utf8" }).trim();
|
|
1341
|
+
const computed = execFileSync("git", ["-C", gitRoot, "merge-base", baseline, targetHead], { encoding: "utf8" }).trim();
|
|
1342
|
+
diffBase = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewDiffBase}^{commit}`], { encoding: "utf8" }).trim();
|
|
1343
|
+
if (diffBase !== computed) throw new Error('saved review diff base does not match merge-base(reviewed head, target head)');
|
|
1312
1344
|
} catch {
|
|
1313
1345
|
return blockedResult(
|
|
1314
1346
|
"review-fact",
|
|
1315
|
-
`Unable to resolve review
|
|
1347
|
+
`Unable to resolve saved review commits in the task repository; re-run review-code`
|
|
1316
1348
|
);
|
|
1317
1349
|
}
|
|
1318
1350
|
|
|
1319
1351
|
if (baseline !== head) {
|
|
1320
1352
|
return failResult(
|
|
1321
1353
|
"review-fact",
|
|
1322
|
-
`
|
|
1354
|
+
`Reviewed head ${baseline.slice(0, 8)} does not match current HEAD ${head.slice(0, 8)}; re-run review-code`
|
|
1323
1355
|
);
|
|
1324
1356
|
}
|
|
1325
1357
|
|
|
@@ -1363,7 +1395,7 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
|
1363
1395
|
if (cleanSnapshot && lastReviewedCommit !== baseline) {
|
|
1364
1396
|
return failResult(
|
|
1365
1397
|
"review-fact",
|
|
1366
|
-
`Approved clean review must set task last_reviewed_commit to
|
|
1398
|
+
`Approved clean review must set task last_reviewed_commit to reviewed head ${baseline.slice(0, 8)}`
|
|
1367
1399
|
);
|
|
1368
1400
|
}
|
|
1369
1401
|
if (!cleanSnapshot && lastReviewedCommit) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export {
|
|
2
2
|
extractReviewBaseline,
|
|
3
|
+
extractReviewTargetHead,
|
|
4
|
+
extractReviewedHead,
|
|
3
5
|
extractReviewDiffBase,
|
|
4
6
|
extractReviewDiffFingerprint,
|
|
5
7
|
extractReviewedSnapshotTree,
|
|
@@ -8,4 +10,4 @@ export {
|
|
|
8
10
|
parseReviewVerdict,
|
|
9
11
|
resolvePostReviewGlobs
|
|
10
12
|
} from './review-fingerprint.ts';
|
|
11
|
-
export {
|
|
13
|
+
export { parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.ts';
|
|
@@ -53,13 +53,6 @@ function captureWorktreeTree(repoRoot: string, forcedPath: string | null): strin
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
function captureLegacyWorkspaceSnapshot(repoRoot: string, taskId: string | null): string {
|
|
57
|
-
const workspaceRelative = taskId
|
|
58
|
-
? `.agents/workspace/active/${taskId}`
|
|
59
|
-
: '.agents/workspace/active';
|
|
60
|
-
return captureWorktreeTree(repoRoot, workspaceRelative);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
56
|
function taskFileFingerprints(stateRoot: string, taskId: string | null): TaskFileFingerprint[] {
|
|
64
57
|
const activeRoot = path.join(stateRoot, '.agents', 'workspace', 'active');
|
|
65
58
|
const roots = taskId ? [path.join(activeRoot, taskId)] : [activeRoot];
|
|
@@ -73,6 +66,7 @@ function taskFileFingerprints(stateRoot: string, taskId: string | null): TaskFil
|
|
|
73
66
|
return;
|
|
74
67
|
}
|
|
75
68
|
if (!stat.isFile() && !stat.isSymbolicLink()) return;
|
|
69
|
+
if (relative.startsWith('.agents/workspace/active/') && path.posix.basename(relative) === 'orchestration.json') return;
|
|
76
70
|
const content = stat.isSymbolicLink()
|
|
77
71
|
? Buffer.from(fs.readlinkSync(absolute))
|
|
78
72
|
: fs.readFileSync(absolute);
|
|
@@ -108,14 +102,11 @@ function decodeWorkspaceFingerprint(value: string): OrchestrationWorkspaceFinger
|
|
|
108
102
|
}
|
|
109
103
|
}
|
|
110
104
|
|
|
111
|
-
function captureWorkspaceSnapshot(context: WorkspaceSnapshotContext): string
|
|
112
|
-
function captureWorkspaceSnapshot(repoRoot: string, taskId: string | null): string;
|
|
113
|
-
function captureWorkspaceSnapshot(contextOrRoot: WorkspaceSnapshotContext | string, taskId?: string | null): string {
|
|
114
|
-
if (typeof contextOrRoot === 'string') return captureLegacyWorkspaceSnapshot(contextOrRoot, taskId ?? null);
|
|
105
|
+
function captureWorkspaceSnapshot(context: WorkspaceSnapshotContext): string {
|
|
115
106
|
return encodeWorkspaceFingerprint({
|
|
116
107
|
version: 2,
|
|
117
|
-
gitTree: captureWorktreeTree(
|
|
118
|
-
taskFiles: taskFileFingerprints(
|
|
108
|
+
gitTree: captureWorktreeTree(context.gitRoot, null),
|
|
109
|
+
taskFiles: taskFileFingerprints(context.stateRoot, context.taskId)
|
|
119
110
|
});
|
|
120
111
|
}
|
|
121
112
|
|
package/lib/task/write.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
-
import { VERSION } from '../version.ts';
|
|
4
|
+
import { isValidAgentInfraVersion, VERSION } from '../version.ts';
|
|
5
5
|
import {
|
|
6
6
|
parseTypedTaskFrontmatter,
|
|
7
7
|
updateTaskFrontmatter
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
import { allowsManualOverride } from './guard-override.ts';
|
|
16
16
|
import type { ManualOverrideCapability } from './guard-override.ts';
|
|
17
17
|
import { mutateTableRow, upsertSection } from './sections.ts';
|
|
18
|
+
import { validateCurrentTaskContract } from './current-contract.ts';
|
|
18
19
|
import type {
|
|
19
20
|
TableRowDeleteMutation,
|
|
20
21
|
TableRowUpsertMutation
|
|
@@ -84,6 +85,7 @@ type TaskWriteMetadata = {
|
|
|
84
85
|
type TaskWriteErrorCode =
|
|
85
86
|
| ResolveTaskRefErrorCode
|
|
86
87
|
| 'TASK_STATE_MISMATCH'
|
|
88
|
+
| 'TASK_CURRENT_CONTRACT_INVALID'
|
|
87
89
|
| 'TASK_READ_FAILED'
|
|
88
90
|
| 'TASK_DOCUMENT_INVALID'
|
|
89
91
|
| 'MUTATION_INVALID'
|
|
@@ -268,6 +270,13 @@ function writeTask(request: TaskWriteRequest, options: TaskWriteOptions = {}): T
|
|
|
268
270
|
);
|
|
269
271
|
}
|
|
270
272
|
|
|
273
|
+
if (resolved.state === 'active') {
|
|
274
|
+
const contract = validateCurrentTaskContract(original);
|
|
275
|
+
if (!contract.ok) {
|
|
276
|
+
return failure(request, identity, contract.code, contract.message);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
271
280
|
let candidate = original;
|
|
272
281
|
const operations: TaskOperationSummary[] = [];
|
|
273
282
|
try {
|
|
@@ -342,6 +351,16 @@ function writeTask(request: TaskWriteRequest, options: TaskWriteOptions = {}): T
|
|
|
342
351
|
operations
|
|
343
352
|
);
|
|
344
353
|
}
|
|
354
|
+
if (resolved.state === 'active' && !isValidAgentInfraVersion(metadata.agentInfraVersion)) {
|
|
355
|
+
return failure(
|
|
356
|
+
request,
|
|
357
|
+
identity,
|
|
358
|
+
'TASK_CURRENT_CONTRACT_INVALID',
|
|
359
|
+
`metadata agentInfraVersion must be a valid v-prefixed semver (received ${metadata.agentInfraVersion})`,
|
|
360
|
+
operations,
|
|
361
|
+
metadata
|
|
362
|
+
);
|
|
363
|
+
}
|
|
345
364
|
|
|
346
365
|
if (candidate === original) {
|
|
347
366
|
return {
|