@fitlab-ai/agent-infra 0.9.1 → 0.9.3
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 +24 -11
- package/README.zh-CN.md +24 -11
- package/bin/cli.ts +12 -0
- package/dist/bin/cli.js +14 -0
- package/dist/bin/internal-cli.js +30 -0
- package/dist/lib/agent-client.js +163 -0
- package/dist/lib/agent-clients/adapter.js +337 -0
- package/dist/lib/agent-clients/adapters/antigravity-cli.js +64 -0
- package/dist/lib/agent-clients/adapters/claude-code.js +71 -0
- package/dist/lib/agent-clients/adapters/codex-sandbox.js +210 -0
- package/dist/lib/agent-clients/adapters/codex.js +63 -0
- package/dist/lib/agent-clients/adapters/index.js +20 -0
- package/dist/lib/agent-clients/adapters/opencode.js +73 -0
- package/dist/lib/agent-clients/config.js +215 -0
- package/dist/lib/agent-clients/custom-tuis.js +99 -0
- package/dist/lib/agent-clients/invocation.js +9 -0
- package/dist/lib/agent-clients/next-steps.js +47 -0
- package/dist/lib/agent-clients/project-assets.js +45 -0
- package/dist/lib/agent-clients/reconcile.js +236 -0
- package/dist/lib/agent-clients/registry.js +78 -0
- package/dist/lib/agent-clients/schema.js +75 -0
- package/dist/lib/agent-clients/tokens.js +49 -0
- package/dist/lib/agent-clients/types.js +29 -0
- package/dist/lib/builtin-tuis.js +9 -14
- package/dist/lib/defaults.json +85 -73
- package/dist/lib/git/review-snapshot.js +25 -10
- package/dist/lib/git/reviewed-commit-equivalence.js +110 -0
- package/dist/lib/git/workflow.js +54 -1
- package/dist/lib/init.js +47 -91
- package/dist/lib/internal/agent-client.js +174 -0
- package/dist/lib/internal/git-workflow.js +7 -2
- package/dist/lib/internal/platform-checks.js +3 -3
- package/dist/lib/internal/platform-comment.js +29 -2
- package/dist/lib/internal/platform-issue.js +7 -0
- package/dist/lib/internal/platform-pr-review.js +132 -0
- package/dist/lib/internal/platform-pr.js +20 -2
- package/dist/lib/internal/platform-release-notes.js +52 -16
- package/dist/lib/internal/pr-review-grade.js +140 -0
- package/dist/lib/internal/release-workflow.js +82 -20
- package/dist/lib/internal/task-activity.js +73 -0
- package/dist/lib/internal/task-event.js +17 -1
- package/dist/lib/internal/task-lifecycle.js +7 -0
- package/dist/lib/internal/task-orchestration.js +196 -0
- package/dist/lib/internal/task-review.js +70 -0
- package/dist/lib/merge.js +2 -1
- package/dist/lib/platform/adapters.js +45 -1
- package/dist/lib/platform/change-request-git-evidence.js +113 -0
- package/dist/lib/platform/completion-backfill.js +122 -0
- package/dist/lib/platform/issue-comments.js +3 -2
- package/dist/lib/platform/merged-pr-equivalence.js +156 -16
- package/dist/lib/platform/pr-checks.js +101 -50
- package/dist/lib/platform/pr-review.js +166 -0
- package/dist/lib/platform/pull-requests.js +432 -7
- package/dist/lib/platform/release-notes.js +85 -3
- package/dist/lib/platform/releases.js +1 -1
- package/dist/lib/platform/verification-required.js +8 -10
- package/dist/lib/pr-review/evidence-grading.js +229 -0
- package/dist/lib/prompt.js +15 -3
- package/dist/lib/release/channels.js +4 -1
- package/dist/lib/release/workflow.js +4 -2
- package/dist/lib/remove-dir.js +25 -0
- package/dist/lib/run/tui.js +11 -7
- package/dist/lib/sandbox/agent-client-reconciler.js +234 -0
- package/dist/lib/sandbox/clipboard/linux.js +2 -1
- package/dist/lib/sandbox/commands/create.js +76 -200
- package/dist/lib/sandbox/commands/enter.js +17 -1
- package/dist/lib/sandbox/commands/prune.js +2 -2
- package/dist/lib/sandbox/commands/rm.js +3 -2
- package/dist/lib/sandbox/commands/show.js +1 -1
- package/dist/lib/sandbox/config.js +21 -4
- package/dist/lib/sandbox/constants.js +3 -0
- package/dist/lib/sandbox/dockerfile.js +2 -1
- package/dist/lib/sandbox/managed-fs.js +10 -5
- package/dist/lib/sandbox/recovery.js +52 -36
- package/dist/lib/sandbox/shell.js +1 -1
- package/dist/lib/sandbox/tool-types.js +8 -0
- package/dist/lib/sandbox/tools.js +2 -126
- package/dist/lib/task/activity-intent.js +101 -0
- package/dist/lib/task/artifact-lifecycle.js +3 -50
- package/dist/lib/task/commands/decisions.js +50 -20
- package/dist/lib/task/commands/log.js +15 -14
- package/dist/lib/task/delegation-receipts.js +128 -0
- package/dist/lib/task/events.js +146 -8
- package/dist/lib/task/finalization-artifacts.js +35 -0
- package/dist/lib/task/lifecycle-execution.js +46 -0
- package/dist/lib/task/orchestration.js +784 -0
- package/dist/lib/task/review-artifacts.js +143 -59
- package/dist/lib/task/review-finalization.js +186 -0
- package/dist/lib/task/review-fingerprint.js +4 -0
- package/dist/lib/task/task-execution-lock.js +231 -0
- package/dist/lib/task/verification-checks.js +2 -1
- package/dist/lib/task/verification-engine.js +372 -28
- package/dist/lib/task/verification-review.js +1 -1
- package/dist/lib/task/verification.js +5 -2
- package/dist/lib/task/workspace-snapshot.js +46 -0
- package/dist/lib/update.js +42 -161
- package/lib/agent-client.ts +214 -0
- package/lib/agent-clients/adapter.ts +534 -0
- package/lib/agent-clients/adapters/antigravity-cli.ts +65 -0
- package/lib/agent-clients/adapters/claude-code.ts +79 -0
- package/lib/agent-clients/adapters/codex-sandbox.ts +245 -0
- package/lib/agent-clients/adapters/codex.ts +67 -0
- package/lib/agent-clients/adapters/index.ts +27 -0
- package/lib/agent-clients/adapters/opencode.ts +75 -0
- package/lib/agent-clients/config.ts +323 -0
- package/lib/agent-clients/custom-tuis.ts +149 -0
- package/lib/agent-clients/invocation.ts +19 -0
- package/lib/agent-clients/next-steps.ts +85 -0
- package/lib/agent-clients/project-assets.ts +96 -0
- package/lib/agent-clients/reconcile.ts +325 -0
- package/lib/agent-clients/registry.ts +154 -0
- package/lib/agent-clients/schema.ts +80 -0
- package/lib/agent-clients/tokens.ts +53 -0
- package/lib/agent-clients/types.ts +92 -0
- package/lib/benchmark/schemas/v1.0.0/case-manifest.schema.json +120 -0
- package/lib/benchmark/schemas/v1.0.0/common.schema.json +109 -0
- package/lib/benchmark/schemas/v1.0.0/grader-result.schema.json +160 -0
- package/lib/benchmark/schemas/v1.0.0/run-manifest.schema.json +122 -0
- package/lib/benchmark/schemas/v1.0.0/subject.schema.json +227 -0
- package/lib/builtin-tuis.ts +16 -15
- package/lib/defaults.json +24 -12
- package/lib/git/review-snapshot.ts +39 -9
- package/lib/git/reviewed-commit-equivalence.ts +135 -0
- package/lib/git/workflow.ts +66 -2
- package/lib/init.ts +53 -121
- package/lib/internal/agent-client.ts +186 -0
- package/lib/internal/git-workflow.ts +6 -2
- package/lib/internal/platform-checks.ts +4 -4
- package/lib/internal/platform-comment.ts +17 -2
- package/lib/internal/platform-issue.ts +4 -0
- package/lib/internal/platform-pr-review.ts +104 -0
- package/lib/internal/platform-pr.ts +14 -1
- package/lib/internal/platform-release-notes.ts +59 -16
- package/lib/internal/pr-review-grade.ts +130 -0
- package/lib/internal/release-workflow.ts +79 -20
- package/lib/internal/task-activity.ts +55 -0
- package/lib/internal/task-event.ts +9 -1
- package/lib/internal/task-lifecycle.ts +4 -0
- package/lib/internal/task-orchestration.ts +171 -0
- package/lib/internal/task-review.ts +70 -0
- package/lib/merge.ts +2 -1
- package/lib/platform/adapters.ts +169 -3
- package/lib/platform/change-request-git-evidence.ts +159 -0
- package/lib/platform/completion-backfill.ts +134 -0
- package/lib/platform/issue-comments.ts +3 -2
- package/lib/platform/merged-pr-equivalence.ts +178 -19
- package/lib/platform/pr-checks.ts +121 -66
- package/lib/platform/pr-review.ts +201 -0
- package/lib/platform/pull-requests.ts +529 -27
- package/lib/platform/release-notes.ts +100 -4
- package/lib/platform/releases.ts +1 -1
- package/lib/platform/verification-required.ts +12 -10
- package/lib/pr-review/evidence-grading.ts +318 -0
- package/lib/prompt.ts +16 -3
- package/lib/release/channels.ts +4 -1
- package/lib/release/workflow.ts +4 -3
- package/lib/remove-dir.ts +28 -0
- package/lib/run/tui.ts +12 -5
- package/lib/sandbox/agent-client-reconciler.ts +378 -0
- package/lib/sandbox/clipboard/linux.ts +2 -1
- package/lib/sandbox/commands/create.ts +111 -212
- package/lib/sandbox/commands/enter.ts +23 -1
- package/lib/sandbox/commands/prune.ts +2 -2
- package/lib/sandbox/commands/rm.ts +3 -2
- package/lib/sandbox/commands/show.ts +1 -1
- package/lib/sandbox/config.ts +31 -4
- package/lib/sandbox/constants.ts +6 -0
- package/lib/sandbox/dockerfile.ts +2 -1
- package/lib/sandbox/managed-fs.ts +18 -5
- package/lib/sandbox/recovery.ts +98 -67
- package/lib/sandbox/shell.ts +1 -1
- package/lib/sandbox/tool-types.ts +143 -0
- package/lib/sandbox/tools.ts +5 -157
- package/lib/server/server.schema.json +2 -2
- package/lib/task/activity-intent.ts +128 -0
- package/lib/task/artifact-lifecycle.ts +3 -39
- package/lib/task/commands/decisions.ts +53 -20
- package/lib/task/commands/log.ts +15 -14
- package/lib/task/delegation-receipts.ts +199 -0
- package/lib/task/events.ts +164 -11
- package/lib/task/finalization-artifacts.ts +58 -0
- package/lib/task/lifecycle-execution.ts +106 -0
- package/lib/task/orchestration.ts +1022 -0
- package/lib/task/review-artifacts.ts +201 -69
- package/lib/task/review-finalization.ts +306 -0
- package/lib/task/review-fingerprint.ts +5 -0
- package/lib/task/task-execution-lock.ts +296 -0
- package/lib/task/verification-checks.ts +2 -1
- package/lib/task/verification-engine.ts +424 -28
- package/lib/task/verification-review.ts +1 -0
- package/lib/task/verification.ts +8 -3
- package/lib/task/workspace-snapshot.ts +57 -0
- package/lib/update.ts +48 -184
- package/package.json +4 -4
- package/templates/.agents/QUICKSTART.en.md +25 -8
- package/templates/.agents/QUICKSTART.zh-CN.md +25 -8
- package/templates/.agents/README.en.md +29 -25
- package/templates/.agents/README.zh-CN.md +29 -25
- package/templates/.agents/hooks/lifecycle-delegation.js +75 -0
- package/templates/.agents/rules/README.en.md +2 -0
- package/templates/.agents/rules/README.zh-CN.md +2 -0
- package/templates/.agents/rules/commit-and-pr.en.md +1 -0
- package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -0
- package/templates/.agents/rules/create-issue.github.en.md +4 -2
- package/templates/.agents/rules/create-issue.github.zh-CN.md +4 -2
- package/templates/.agents/rules/human-decision-context.en.md +14 -12
- package/templates/.agents/rules/human-decision-context.zh-CN.md +14 -12
- package/templates/.agents/rules/issue-fields.github.en.md +3 -1
- package/templates/.agents/rules/issue-fields.github.zh-CN.md +3 -1
- package/templates/.agents/rules/issue-pr-commands.en.md +5 -3
- package/templates/.agents/rules/issue-pr-commands.github.en.md +5 -3
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +5 -3
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +5 -3
- package/templates/.agents/rules/issue-sync.github.en.md +7 -3
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +8 -4
- package/templates/.agents/rules/lifecycle-orchestration.en.md +24 -0
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +24 -0
- package/templates/.agents/rules/milestone-inference.github.en.md +4 -2
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +4 -2
- package/templates/.agents/rules/next-step-output.en.md +18 -0
- package/templates/.agents/rules/next-step-output.zh-CN.md +18 -0
- package/templates/.agents/rules/no-mid-flow-questions.en.md +19 -0
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +19 -0
- package/templates/.agents/rules/pr-checks-commands.en.md +3 -3
- package/templates/.agents/rules/pr-checks-commands.github.en.md +2 -2
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +2 -2
- package/templates/.agents/rules/pr-checks-commands.zh-CN.md +3 -3
- package/templates/.agents/rules/pr-sync.en.md +3 -1
- package/templates/.agents/rules/pr-sync.github.en.md +11 -1
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +11 -1
- package/templates/.agents/rules/pr-sync.zh-CN.md +3 -1
- package/templates/.agents/rules/release-commands.en.md +1 -1
- package/templates/.agents/rules/release-commands.github.en.md +21 -5
- package/templates/.agents/rules/release-commands.github.zh-CN.md +21 -5
- package/templates/.agents/rules/release-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/review-handshake.en.md +4 -4
- package/templates/.agents/rules/review-handshake.zh-CN.md +4 -4
- package/templates/.agents/rules/review-method.en.md +113 -0
- package/templates/.agents/rules/review-method.zh-CN.md +98 -0
- package/templates/.agents/rules/task-management.en.md +11 -0
- package/templates/.agents/rules/task-management.zh-CN.md +11 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -12
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +15 -12
- package/templates/.agents/skills/block-task/SKILL.en.md +11 -9
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +11 -9
- package/templates/.agents/skills/cancel-task/SKILL.en.md +10 -8
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +11 -9
- package/templates/.agents/skills/check-task/SKILL.en.md +16 -16
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -16
- package/templates/.agents/skills/close-codescan/SKILL.en.md +7 -5
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +7 -5
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +7 -5
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +7 -5
- package/templates/.agents/skills/code-task/SKILL.en.md +10 -7
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +13 -10
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +14 -16
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +14 -16
- package/templates/.agents/skills/code-task/reference/output-template.en.md +3 -3
- package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/SKILL.en.md +13 -1
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +13 -1
- package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
- package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
- 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 +24 -28
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +24 -28
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +6 -4
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +6 -4
- 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 +23 -8
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +23 -8
- package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +17 -0
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +17 -0
- package/templates/.agents/skills/create-pr/SKILL.en.md +13 -11
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +13 -11
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +3 -3
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +3 -3
- package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -16
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -16
- package/templates/.agents/skills/create-task/SKILL.en.md +16 -14
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +16 -14
- package/templates/.agents/skills/import-codescan/SKILL.en.md +5 -5
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +5 -5
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/import-issue/SKILL.en.md +10 -8
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -8
- package/templates/.agents/skills/init-labels/SKILL.en.md +4 -4
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/init-milestones/SKILL.en.md +4 -4
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/plan-task/SKILL.en.md +13 -10
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +13 -10
- package/templates/.agents/skills/post-release/SKILL.en.md +2 -0
- package/templates/.agents/skills/post-release/SKILL.zh-CN.md +2 -0
- package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
- package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/release/SKILL.en.md +16 -10
- package/templates/.agents/skills/release/SKILL.zh-CN.md +16 -10
- package/templates/.agents/skills/restore-task/SKILL.en.md +4 -1
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +18 -4
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +19 -5
- package/templates/.agents/skills/review-analysis/config/verify.en.json +6 -0
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +6 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +13 -15
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +13 -15
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +51 -5
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +52 -6
- package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +25 -22
- package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +25 -22
- package/templates/.agents/skills/review-code/SKILL.en.md +35 -12
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +35 -12
- package/templates/.agents/skills/review-code/config/verify.en.json +7 -0
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +7 -0
- package/templates/.agents/skills/review-code/reference/concurrency-risks.en.md +25 -0
- package/templates/.agents/skills/review-code/reference/concurrency-risks.zh-CN.md +25 -0
- package/templates/.agents/skills/review-code/reference/cross-platform-risks.en.md +27 -0
- package/templates/.agents/skills/review-code/reference/cross-platform-risks.zh-CN.md +27 -0
- package/templates/.agents/skills/review-code/reference/documentation-antipatterns.en.md +13 -0
- package/templates/.agents/skills/review-code/reference/documentation-antipatterns.zh-CN.md +13 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.en.md +25 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +25 -0
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +22 -24
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +22 -24
- package/templates/.agents/skills/review-code/reference/report-template.en.md +54 -7
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +54 -7
- package/templates/.agents/skills/review-code/reference/review-criteria.en.md +29 -24
- package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +29 -24
- package/templates/.agents/skills/review-code/reference/security-risks.en.md +25 -0
- package/templates/.agents/skills/review-code/reference/security-risks.zh-CN.md +25 -0
- package/templates/.agents/skills/review-plan/SKILL.en.md +18 -4
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +19 -5
- package/templates/.agents/skills/review-plan/config/verify.en.json +6 -0
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +6 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +13 -15
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +13 -15
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +61 -5
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +61 -5
- package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +21 -24
- package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +21 -24
- package/templates/.agents/skills/review-pr/SKILL.en.md +158 -0
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +158 -0
- package/templates/.agents/skills/review-pr/config/verify.en.json +37 -0
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +37 -0
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +65 -0
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +65 -0
- package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +18 -0
- package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +18 -0
- package/templates/.agents/skills/review-pr/reference/report-template.en.md +85 -0
- package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +85 -0
- package/templates/.agents/skills/run-task/SKILL.en.md +22 -0
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +22 -0
- package/templates/.agents/skills/run-task/config/verify.en.json +10 -0
- package/templates/.agents/skills/run-task/config/verify.zh-CN.json +10 -0
- package/templates/.agents/skills/run-task/reference/host-validation.en.md +20 -0
- package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +20 -0
- package/templates/.agents/skills/test/SKILL.en.md +4 -4
- package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/test-integration/SKILL.en.md +4 -4
- package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +5 -5
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +664 -246
- package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +4 -4
- package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/watch-pr/SKILL.en.md +21 -21
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +21 -21
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +27 -6
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +26 -5
- package/templates/.agents/templates/task.en.md +1 -1
- package/templates/.agents/templates/task.zh-CN.md +1 -1
- package/templates/.agents/workflows/bug-fix.en.yaml +3 -3
- package/templates/.agents/workflows/bug-fix.zh-CN.yaml +3 -3
- package/templates/.agents/workflows/code-review.en.yaml +1 -1
- package/templates/.agents/workflows/code-review.zh-CN.yaml +1 -1
- package/templates/.agents/workflows/feature-development.en.yaml +4 -4
- package/templates/.agents/workflows/feature-development.zh-CN.yaml +4 -4
- package/templates/.agents/workflows/refactoring.en.yaml +3 -3
- package/templates/.agents/workflows/refactoring.zh-CN.yaml +3 -3
- package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +6 -0
- package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +6 -0
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +6 -0
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +6 -0
- package/templates/.claude/commands/post-release.en.md +1 -0
- package/templates/.claude/commands/post-release.zh-CN.md +1 -0
- package/templates/.claude/commands/review-pr.en.md +8 -0
- package/templates/.claude/commands/review-pr.zh-CN.md +8 -0
- package/templates/.claude/commands/run-task.en.md +8 -0
- package/templates/.claude/commands/run-task.zh-CN.md +8 -0
- package/templates/.claude/settings.json +24 -0
- package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +3 -0
- package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +3 -0
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +3 -0
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +3 -0
- package/templates/.gemini/commands/_project_/review-pr.en.toml +10 -0
- package/templates/.gemini/commands/_project_/review-pr.zh-CN.toml +10 -0
- package/templates/.opencode/commands/post-release.en.md +2 -0
- package/templates/.opencode/commands/post-release.zh-CN.md +2 -0
- package/templates/.opencode/commands/review-pr.en.md +11 -0
- package/templates/.opencode/commands/review-pr.zh-CN.md +11 -0
- package/templates/.opencode/commands/run-task.en.md +11 -0
- package/templates/.opencode/commands/run-task.zh-CN.md +11 -0
- package/templates/.gemini/commands/_project_/analyze-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/archive-tasks.en.toml +0 -10
- package/templates/.gemini/commands/_project_/archive-tasks.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/block-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/cancel-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/check-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/close-codescan.en.toml +0 -8
- package/templates/.gemini/commands/_project_/close-codescan.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/close-dependabot.en.toml +0 -8
- package/templates/.gemini/commands/_project_/close-dependabot.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/code-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/commit.en.toml +0 -10
- package/templates/.gemini/commands/_project_/commit.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +0 -10
- package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/complete-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/create-pr.en.toml +0 -10
- package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/create-release-note.en.toml +0 -8
- package/templates/.gemini/commands/_project_/create-release-note.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/create-task.en.toml +0 -8
- package/templates/.gemini/commands/_project_/create-task.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/import-codescan.en.toml +0 -8
- package/templates/.gemini/commands/_project_/import-codescan.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/import-dependabot.en.toml +0 -8
- package/templates/.gemini/commands/_project_/import-dependabot.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/import-issue.en.toml +0 -8
- package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/init-labels.en.toml +0 -8
- package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/init-milestones.en.toml +0 -10
- package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/plan-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/post-release.en.toml +0 -6
- package/templates/.gemini/commands/_project_/post-release.zh-CN.toml +0 -6
- package/templates/.gemini/commands/_project_/refine-title.en.toml +0 -8
- package/templates/.gemini/commands/_project_/refine-title.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/release.en.toml +0 -8
- package/templates/.gemini/commands/_project_/release.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/restore-task.en.toml +0 -8
- package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/review-analysis.en.toml +0 -10
- package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/review-code.en.toml +0 -10
- package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/review-plan.en.toml +0 -10
- package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/test-integration.en.toml +0 -6
- package/templates/.gemini/commands/_project_/test-integration.zh-CN.toml +0 -6
- package/templates/.gemini/commands/_project_/test.en.toml +0 -6
- package/templates/.gemini/commands/_project_/test.zh-CN.toml +0 -6
- package/templates/.gemini/commands/_project_/update-agent-infra.en.toml +0 -6
- package/templates/.gemini/commands/_project_/update-agent-infra.zh-CN.toml +0 -6
- package/templates/.gemini/commands/_project_/upgrade-dependency.en.toml +0 -8
- package/templates/.gemini/commands/_project_/upgrade-dependency.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/watch-pr.en.toml +0 -10
- package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +0 -10
- package/templates/.gemini/settings.json +0 -3
|
@@ -7,6 +7,7 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
extractReviewBaseline,
|
|
10
|
+
extractReviewDiffBase,
|
|
10
11
|
extractReviewDiffFingerprint,
|
|
11
12
|
extractReviewedSnapshotTree,
|
|
12
13
|
findAuthoritativeReviewCodeArtifact,
|
|
@@ -17,9 +18,12 @@ import {
|
|
|
17
18
|
import { check as checkPlatformSync } from "../platform/verification-sync.ts";
|
|
18
19
|
import { check as checkRequiredChecks } from "../platform/verification-required.ts";
|
|
19
20
|
import { inspectPlatformPullRequest } from "../platform/pull-requests.ts";
|
|
21
|
+
import { resolveMaterializedReviewedHeadRelation } from "../platform/change-request-git-evidence.ts";
|
|
20
22
|
import { resolveReviewedHeadRelation } from "../platform/merged-pr-equivalence.ts";
|
|
23
|
+
import { resolveLocalReviewedCommitRelation } from "../git/reviewed-commit-equivalence.ts";
|
|
21
24
|
import { parseTypedTaskFrontmatter } from "./frontmatter.ts";
|
|
22
|
-
import { parseLedger } from "./ledger.ts";
|
|
25
|
+
import { parseLedger, summarizeLedgerStage, validateLedgerRows } from "./ledger.ts";
|
|
26
|
+
import { equalCounts, parseReviewSummary } from "./review-artifacts.ts";
|
|
23
27
|
import { loadVerificationConfig } from "./verification-config.ts";
|
|
24
28
|
import { snapshotReview } from "../git/review-snapshot.ts";
|
|
25
29
|
|
|
@@ -110,10 +114,18 @@ function runCheck(type: any, context: any, shared: any): any {
|
|
|
110
114
|
return checkCompletionChecklist(context);
|
|
111
115
|
case "review-ledger":
|
|
112
116
|
return checkReviewLedger(context);
|
|
117
|
+
case "manual-validation":
|
|
118
|
+
return checkManualValidation(context);
|
|
119
|
+
case "review-summary":
|
|
120
|
+
return checkReviewSummary(context);
|
|
113
121
|
case "review-fact":
|
|
114
122
|
return checkReviewFact(context);
|
|
115
123
|
case "post-review-commit":
|
|
116
124
|
return checkPostReviewCommit(context);
|
|
125
|
+
case "orchestration-state":
|
|
126
|
+
return checkOrchestrationState(context);
|
|
127
|
+
case "orchestration-evidence":
|
|
128
|
+
return checkOrchestrationEvidence(context);
|
|
117
129
|
default: {
|
|
118
130
|
const adapter = PLATFORM_ADAPTERS[type];
|
|
119
131
|
if (!adapter) {
|
|
@@ -129,6 +141,206 @@ function runCheck(type: any, context: any, shared: any): any {
|
|
|
129
141
|
}
|
|
130
142
|
}
|
|
131
143
|
|
|
144
|
+
function isFailClosedLegacyPause(run: any): boolean {
|
|
145
|
+
if (
|
|
146
|
+
run.schemaVersion !== 1
|
|
147
|
+
|| run.status !== 'paused'
|
|
148
|
+
|| run.pause?.recoverable !== false
|
|
149
|
+
|| !exactText(run.pause?.message)
|
|
150
|
+
|| !Array.isArray(run.receipts)
|
|
151
|
+
) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
if (run.pause.code === 'ORCHESTRATION_HISTORICAL_EFFORT_UNVERIFIED') {
|
|
155
|
+
return run.receipts.length > 0 && run.pendingDelegation === null;
|
|
156
|
+
}
|
|
157
|
+
if (run.pause.code === 'ORCHESTRATION_DELEGATION_BUSY') {
|
|
158
|
+
return run.pendingDelegation != null && run.pendingDelegation.status !== 'sealed';
|
|
159
|
+
}
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function checkOrchestrationState({ taskDir }: any): any {
|
|
164
|
+
const file = path.join(taskDir, 'orchestration.json');
|
|
165
|
+
const stat = safeStat(file);
|
|
166
|
+
if (!stat?.isFile()) return failResult('orchestration-state', 'orchestration.json is missing');
|
|
167
|
+
let run: any;
|
|
168
|
+
try {
|
|
169
|
+
run = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
170
|
+
} catch (error) {
|
|
171
|
+
return failResult('orchestration-state', `Invalid orchestration.json: ${String(error)}`);
|
|
172
|
+
}
|
|
173
|
+
if (isFailClosedLegacyPause(run)) {
|
|
174
|
+
return passResult('orchestration-state', 'Legacy orchestration run is safely paused');
|
|
175
|
+
}
|
|
176
|
+
if (run.schemaVersion !== 2 || !['paused', 'completed'].includes(run.status)) {
|
|
177
|
+
return failResult('orchestration-state', `Expected paused or completed run, received '${run.status}'`);
|
|
178
|
+
}
|
|
179
|
+
if (run.status === 'paused' && (!run.pause?.code || !run.pause?.message)) {
|
|
180
|
+
return failResult('orchestration-state', 'Paused run requires a stable pause code and message');
|
|
181
|
+
}
|
|
182
|
+
if (run.status === 'completed') {
|
|
183
|
+
if (run.completionEvidence != null) {
|
|
184
|
+
const evidenceError = validateCleanCompletionEvidence(run);
|
|
185
|
+
if (evidenceError) return failResult('orchestration-state', evidenceError);
|
|
186
|
+
} else if (run.pendingDelegation !== null || !run.commitAuthorization?.consumedAt) {
|
|
187
|
+
return failResult('orchestration-state', 'Completed run must consume commit authorization and clear pending delegation');
|
|
188
|
+
}
|
|
189
|
+
} else if (run.completionEvidence != null) {
|
|
190
|
+
return failResult('orchestration-state', 'Clean completion evidence requires a completed run');
|
|
191
|
+
} else if (run.pendingDelegation?.status === 'sealed') {
|
|
192
|
+
return failResult('orchestration-state', 'Paused run has a sealed delegation that could still advance');
|
|
193
|
+
}
|
|
194
|
+
return passResult('orchestration-state', `Orchestration run is safely ${run.status}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function exactText(value: unknown): value is string {
|
|
198
|
+
return typeof value === 'string' && value.length > 0 && value.trim() === value;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function validateCleanCompletionEvidence(run: any): string | null {
|
|
202
|
+
const evidence = run.completionEvidence;
|
|
203
|
+
const shaPattern = /^[0-9a-f]{40}$/i;
|
|
204
|
+
if (
|
|
205
|
+
evidence?.kind !== 'reviewed-head-clean'
|
|
206
|
+
|| !exactText(evidence.observedAt)
|
|
207
|
+
|| Number.isNaN(Date.parse(evidence.observedAt))
|
|
208
|
+
|| !shaPattern.test(evidence.head)
|
|
209
|
+
|| !shaPattern.test(evidence.headTree)
|
|
210
|
+
|| !shaPattern.test(evidence.worktreeTree)
|
|
211
|
+
|| !shaPattern.test(evidence.lastReviewedCommit)
|
|
212
|
+
|| !Number.isInteger(evidence.prNumber)
|
|
213
|
+
|| evidence.prNumber <= 0
|
|
214
|
+
|| !shaPattern.test(evidence.prHead)
|
|
215
|
+
) {
|
|
216
|
+
return 'Clean completion evidence has an invalid structure';
|
|
217
|
+
}
|
|
218
|
+
if (
|
|
219
|
+
evidence.head !== evidence.lastReviewedCommit
|
|
220
|
+
|| evidence.head !== evidence.prHead
|
|
221
|
+
|| evidence.headTree !== evidence.worktreeTree
|
|
222
|
+
) {
|
|
223
|
+
return 'Clean completion evidence does not bind matching commit and tree identities';
|
|
224
|
+
}
|
|
225
|
+
if (
|
|
226
|
+
run.status !== 'completed'
|
|
227
|
+
|| run.pendingDelegation !== null
|
|
228
|
+
|| run.commitAuthorization?.issuedAt !== null
|
|
229
|
+
|| run.commitAuthorization?.consumedAt !== null
|
|
230
|
+
|| !Array.isArray(run.receipts)
|
|
231
|
+
|| run.receipts.some((receipt: any) => receipt.stage === 'commit')
|
|
232
|
+
) {
|
|
233
|
+
return 'Clean completion evidence conflicts with commit delegation state';
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
239
|
+
const file = path.join(taskDir, 'orchestration.json');
|
|
240
|
+
const stat = safeStat(file);
|
|
241
|
+
if (!stat?.isFile()) return failResult('orchestration-evidence', 'orchestration.json is missing');
|
|
242
|
+
let run: any;
|
|
243
|
+
try {
|
|
244
|
+
run = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
245
|
+
} catch (error) {
|
|
246
|
+
return failResult('orchestration-evidence', `Invalid orchestration.json: ${String(error)}`);
|
|
247
|
+
}
|
|
248
|
+
if (isFailClosedLegacyPause(run)) {
|
|
249
|
+
return passResult('orchestration-evidence', 'Legacy orchestration evidence is preserved in a fail-closed pause');
|
|
250
|
+
}
|
|
251
|
+
const policy = run.modelPolicy;
|
|
252
|
+
if (
|
|
253
|
+
!policy
|
|
254
|
+
|| !exactText(policy.executor?.model)
|
|
255
|
+
|| !exactText(policy.executor?.reasoningEffort)
|
|
256
|
+
|| !exactText(policy.reviewer?.model)
|
|
257
|
+
|| !exactText(policy.reviewer?.reasoningEffort)
|
|
258
|
+
) {
|
|
259
|
+
return failResult('orchestration-evidence', 'Run model policy requires exact executor and reviewer model and effort');
|
|
260
|
+
}
|
|
261
|
+
if (
|
|
262
|
+
!run.modelPolicySource
|
|
263
|
+
|| !['explicit', 'project-config'].includes(run.modelPolicySource.kind)
|
|
264
|
+
|| !exactText(run.modelPolicySource.client)
|
|
265
|
+
|| !exactText(run.modelPolicySource.resolvedAt)
|
|
266
|
+
|| !Array.isArray(run.recoveryHistory)
|
|
267
|
+
) {
|
|
268
|
+
return failResult('orchestration-evidence', 'Run model policy source or recovery history is invalid');
|
|
269
|
+
}
|
|
270
|
+
for (const recovery of run.recoveryHistory) {
|
|
271
|
+
if (
|
|
272
|
+
recovery.code !== 'MODEL_POLICY_SUPPLEMENTED'
|
|
273
|
+
|| recovery.previousSchemaVersion !== 1
|
|
274
|
+
|| recovery.receiptCount !== 0
|
|
275
|
+
|| recovery.pendingDelegation !== false
|
|
276
|
+
|| !exactText(recovery.recoveredAt)
|
|
277
|
+
|| !recovery.policySource
|
|
278
|
+
) {
|
|
279
|
+
return failResult('orchestration-evidence', 'Run recovery history contains invalid provenance');
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (!Array.isArray(run.receipts)) {
|
|
283
|
+
return failResult('orchestration-evidence', 'Run receipts must be an array');
|
|
284
|
+
}
|
|
285
|
+
if (run.completionEvidence != null) {
|
|
286
|
+
const evidenceError = validateCleanCompletionEvidence(run);
|
|
287
|
+
if (evidenceError) return failResult('orchestration-evidence', evidenceError);
|
|
288
|
+
} else if (run.status === 'completed' && (
|
|
289
|
+
run.receipts.length === 0
|
|
290
|
+
|| run.receipts.at(-1)?.stage !== 'commit'
|
|
291
|
+
|| run.receipts.at(-1)?.status !== 'consumed'
|
|
292
|
+
)) {
|
|
293
|
+
return failResult('orchestration-evidence', 'Completed run requires a final consumed commit receipt');
|
|
294
|
+
}
|
|
295
|
+
if (run.pendingDelegation && !['prepared', 'activated', 'stage-completed'].includes(run.pendingDelegation.status)) {
|
|
296
|
+
return failResult('orchestration-evidence', `Pending receipt has unsafe status '${run.pendingDelegation.status}'`);
|
|
297
|
+
}
|
|
298
|
+
const receipts = [...run.receipts, ...(run.pendingDelegation ? [run.pendingDelegation] : [])];
|
|
299
|
+
for (const receipt of receipts) {
|
|
300
|
+
const expectedPolicy = policy[receipt.role];
|
|
301
|
+
if (!expectedPolicy || receipt.requestedModel !== expectedPolicy.model) {
|
|
302
|
+
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' requested model does not match its role policy`);
|
|
303
|
+
}
|
|
304
|
+
if (receipt.requestedReasoningEffort !== expectedPolicy.reasoningEffort) {
|
|
305
|
+
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' requested reasoning effort does not match its role policy`);
|
|
306
|
+
}
|
|
307
|
+
const activated = ['activated', 'stage-completed', 'sealed', 'consumed'].includes(receipt.status);
|
|
308
|
+
if (activated) {
|
|
309
|
+
if (!exactText(receipt.actualModel)) {
|
|
310
|
+
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has no host-observed actual model`);
|
|
311
|
+
}
|
|
312
|
+
if (!exactText(receipt.actualReasoningEffort)) {
|
|
313
|
+
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has no host-observed actual reasoning effort`);
|
|
314
|
+
}
|
|
315
|
+
if (!exactText(receipt.parentId) || !exactText(receipt.childId) || receipt.parentId === receipt.childId || receipt.spawnMode !== 'fresh') {
|
|
316
|
+
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid fresh delegation identity`);
|
|
317
|
+
}
|
|
318
|
+
if (receipt.actualModel !== receipt.requestedModel && !exactText(receipt.modelFallbackReason)) {
|
|
319
|
+
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' model fallback is not justified`);
|
|
320
|
+
}
|
|
321
|
+
if (receipt.actualModel === receipt.requestedModel && receipt.modelFallbackReason !== null) {
|
|
322
|
+
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has an unrelated model fallback reason`);
|
|
323
|
+
}
|
|
324
|
+
if (
|
|
325
|
+
receipt.actualReasoningEffort !== receipt.requestedReasoningEffort
|
|
326
|
+
&& !exactText(receipt.reasoningEffortFallbackReason)
|
|
327
|
+
) {
|
|
328
|
+
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' reasoning-effort fallback is not justified`);
|
|
329
|
+
}
|
|
330
|
+
if (
|
|
331
|
+
receipt.actualReasoningEffort === receipt.requestedReasoningEffort
|
|
332
|
+
&& receipt.reasoningEffortFallbackReason !== null
|
|
333
|
+
) {
|
|
334
|
+
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has an unrelated reasoning-effort fallback reason`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (run.receipts.some((receipt: any) => receipt.status !== 'consumed')) {
|
|
339
|
+
return failResult('orchestration-evidence', 'Historical receipts must be consumed');
|
|
340
|
+
}
|
|
341
|
+
return passResult('orchestration-evidence', 'Persisted orchestration model and delegation evidence is internally consistent');
|
|
342
|
+
}
|
|
343
|
+
|
|
132
344
|
// === Check Functions ===
|
|
133
345
|
|
|
134
346
|
function checkTaskMeta({ taskDir, config }: any): any {
|
|
@@ -313,6 +525,43 @@ function checkArtifact({ taskDir, config, artifactFile }: any): any {
|
|
|
313
525
|
);
|
|
314
526
|
}
|
|
315
527
|
|
|
528
|
+
function checkReviewSummary({ taskDir, config, artifactFile }: any): any {
|
|
529
|
+
const stage = String(config.stage || "");
|
|
530
|
+
if (!["analysis", "plan", "code"].includes(stage)) {
|
|
531
|
+
return failResult("review-summary", `Invalid review stage '${stage}'`);
|
|
532
|
+
}
|
|
533
|
+
const resolvedArtifact = resolveArtifactPath(taskDir, "", artifactFile);
|
|
534
|
+
if (!resolvedArtifact.ok || !safeStat(resolvedArtifact.path)?.isFile()) {
|
|
535
|
+
return failResult("review-summary", resolvedArtifact.message || "Review artifact is missing");
|
|
536
|
+
}
|
|
537
|
+
const parsed = parseReviewSummary(fs.readFileSync(resolvedArtifact.path, "utf8"));
|
|
538
|
+
if (!parsed.ok) return failResult("review-summary", `${parsed.code}: ${parsed.message}`);
|
|
539
|
+
if (!parsed.summary.counts) {
|
|
540
|
+
return failResult("review-summary", "Review summary finding counts are not finalized");
|
|
541
|
+
}
|
|
542
|
+
const task = loadTask(taskDir);
|
|
543
|
+
if (!task.ok) return failResult("review-summary", task.message);
|
|
544
|
+
let rows;
|
|
545
|
+
try {
|
|
546
|
+
rows = parseLedger(task.content);
|
|
547
|
+
} catch (error) {
|
|
548
|
+
return failResult("review-summary", `Invalid disagreement ledger: ${String(error)}`);
|
|
549
|
+
}
|
|
550
|
+
const invalid = validateLedgerRows(rows);
|
|
551
|
+
if (invalid) return failResult("review-summary", `${invalid.code}: ${invalid.message}`);
|
|
552
|
+
const expected = summarizeLedgerStage(rows, stage as "analysis" | "plan" | "code").unresolvedFindingCounts;
|
|
553
|
+
if (!equalCounts(parsed.summary.counts, expected)) {
|
|
554
|
+
return failResult(
|
|
555
|
+
"review-summary",
|
|
556
|
+
`Review summary counts ${JSON.stringify(parsed.summary.counts)} do not match ledger ${JSON.stringify(expected)}`
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
return passResult(
|
|
560
|
+
"review-summary",
|
|
561
|
+
`${path.basename(resolvedArtifact.path)} finding counts match the ${stage} ledger`
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
|
|
316
565
|
function checkImplementationInput({ taskDir, artifactFile }: any): any {
|
|
317
566
|
const task = loadTask(taskDir);
|
|
318
567
|
if (!task.ok) return failResult("implementation-input", task.message);
|
|
@@ -669,6 +918,75 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
669
918
|
return passResult("review-ledger", `Disagreement ledger clean (${inScopeCount} in-scope entries terminal${scopeLabel})`);
|
|
670
919
|
}
|
|
671
920
|
|
|
921
|
+
function checkManualValidation({ taskDir }: any): any {
|
|
922
|
+
// 1. Latest review-code artifact; none -> pass (no review, check not applicable).
|
|
923
|
+
const review = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
924
|
+
if (!review.ok) {
|
|
925
|
+
return passResult("manual-validation", "No review-code artifact; manual validation not applicable");
|
|
926
|
+
}
|
|
927
|
+
// 2. Parse the numeric manual-validation count; unparseable/null -> fail closed
|
|
928
|
+
// (review-code.completed already enforces a numeric count on the normal path).
|
|
929
|
+
const parsed = parseReviewSummary(fs.readFileSync(review.path!, "utf8"));
|
|
930
|
+
if (!parsed.ok || parsed.summary.manualValidation === null) {
|
|
931
|
+
return failResult("manual-validation", "Latest review-code has no numeric manual-validation count");
|
|
932
|
+
}
|
|
933
|
+
// 3. Count 0 -> pass (no pending items to cover).
|
|
934
|
+
if (parsed.summary.manualValidation === 0) {
|
|
935
|
+
return passResult("manual-validation", "No pending manual validation items");
|
|
936
|
+
}
|
|
937
|
+
// 4. Highest-round manual-validation artifact; none -> fail (items pending,
|
|
938
|
+
// run complete-manual-validation first). A falsy artifactFile goes through
|
|
939
|
+
// pattern parsing; resolveArtifactPath only returns { ok, path }.
|
|
940
|
+
const resolved = resolveArtifactPath(taskDir, "manual-validation.md|manual-validation-r{N}.md", "");
|
|
941
|
+
if (!resolved.ok) {
|
|
942
|
+
return failResult(
|
|
943
|
+
"manual-validation",
|
|
944
|
+
`${parsed.summary.manualValidation} manual validation item(s) pending: run /complete-manual-validation`
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
// 5. The Activity Log must record the matching completion entry; the file name
|
|
948
|
+
// is derived with path.basename (resolveArtifactPath does not return fileName).
|
|
949
|
+
const artifactName = path.basename(resolved.path);
|
|
950
|
+
const task = loadTask(taskDir);
|
|
951
|
+
if (!task.ok) return failResult("manual-validation", task.message);
|
|
952
|
+
const log = getSectionContent(task.content, ["活动日志", "Activity Log"]);
|
|
953
|
+
const completed = new RegExp(
|
|
954
|
+
`\\*\\*Complete Manual Validation\\*\\*[\\s\\S]*?Manual validation passed → ${escapeRegExp(artifactName)};`
|
|
955
|
+
);
|
|
956
|
+
if (!completed.test(log)) {
|
|
957
|
+
return failResult(
|
|
958
|
+
"manual-validation",
|
|
959
|
+
`Manual validation artifact exists but completion is not recorded for ${artifactName}: re-run /complete-manual-validation`
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
// 6. Timing correlation (PL-3 fix, PL-4 corrected): the completion entry must
|
|
963
|
+
// sit AFTER the latest review-code round's completion entry in the
|
|
964
|
+
// append-only Activity Log. indexOf is a literal search, so the artifactName
|
|
965
|
+
// must NOT be passed through escapeRegExp here (that escapes '.' to '\.',
|
|
966
|
+
// which indexOf never matches). Not reusing completed.exec().index: exec
|
|
967
|
+
// anchors to the first '**Complete Manual Validation**' heading, which can
|
|
968
|
+
// belong to an earlier round's entry and misorder the standard path.
|
|
969
|
+
const reviewDoneIndex = log.indexOf(`**Review Code (Round ${review.round})** by `);
|
|
970
|
+
const completedIndex = log.indexOf(`Manual validation passed → ${artifactName};`);
|
|
971
|
+
if (reviewDoneIndex === -1) {
|
|
972
|
+
// The latest review-code round's completion entry is missing entirely (abnormal
|
|
973
|
+
// state, e.g. a restored/historical task without a review-code.completed record).
|
|
974
|
+
// Re-running complete-manual-validation cannot restore it, so the remediation
|
|
975
|
+
// targets the review record itself. Fail closed either way.
|
|
976
|
+
return failResult(
|
|
977
|
+
"manual-validation",
|
|
978
|
+
`Latest review-code (round ${review.round}) completion entry is missing from the Activity Log (abnormal state): re-run review-code or restore the completion record`
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
if (completedIndex < reviewDoneIndex) {
|
|
982
|
+
return failResult(
|
|
983
|
+
"manual-validation",
|
|
984
|
+
`Latest review-code (round ${review.round}) came after the manual validation completion recorded for ${artifactName}: re-run /complete-manual-validation to cover new pending items`
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
return passResult("manual-validation", `Manual validation completed → ${artifactName}`);
|
|
988
|
+
}
|
|
989
|
+
|
|
672
990
|
function checkPostReviewCommit({ taskDir, config }: any): any {
|
|
673
991
|
const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
674
992
|
if (!reviewArtifact.ok) {
|
|
@@ -683,8 +1001,51 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
|
|
|
683
1001
|
}
|
|
684
1002
|
|
|
685
1003
|
const task = loadTask(taskDir);
|
|
686
|
-
|
|
1004
|
+
if (!task.ok) return failResult("post-review-commit", task.message);
|
|
687
1005
|
const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
|
|
1006
|
+
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repoRoot));
|
|
1007
|
+
const hasPullRequest = Number(task.metadata.pr_number) > 0;
|
|
1008
|
+
let inspected: ReturnType<typeof inspectPlatformPullRequest> | null = null;
|
|
1009
|
+
if (hasPullRequest) {
|
|
1010
|
+
inspected = inspectPlatformPullRequest(task.metadata.id, { cwd: gitRoot });
|
|
1011
|
+
if (!inspected.pullRequest) {
|
|
1012
|
+
const message = inspected.error?.message || "PR merge snapshot is unavailable";
|
|
1013
|
+
const code = inspected.error?.code || "PR_INSPECTION_INVALID";
|
|
1014
|
+
return inspected.status === "blocked"
|
|
1015
|
+
? blockedResult("post-review-commit", message, code)
|
|
1016
|
+
: failResult("post-review-commit", message, code);
|
|
1017
|
+
}
|
|
1018
|
+
if (
|
|
1019
|
+
inspected.pullRequest.state === "closed" &&
|
|
1020
|
+
inspected.pullRequest.mergedAt &&
|
|
1021
|
+
inspected.pullRequest.mergeCommitSha
|
|
1022
|
+
) {
|
|
1023
|
+
const relation = resolveMaterializedReviewedHeadRelation({
|
|
1024
|
+
cwd: gitRoot,
|
|
1025
|
+
platformType: inspected.platform.type,
|
|
1026
|
+
lastReviewedCommit,
|
|
1027
|
+
pullRequest: inspected.pullRequest
|
|
1028
|
+
});
|
|
1029
|
+
if (relation.status === "merged-equivalent") {
|
|
1030
|
+
return passResult(
|
|
1031
|
+
"post-review-commit",
|
|
1032
|
+
`Reviewed PR head is content-equivalent to squash merge ${relation.mergeCommit.slice(0, 8)} on target ${relation.comparisonHead.slice(0, 8)}`
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
if (relation.status === "blocked") {
|
|
1036
|
+
return blockedResult("post-review-commit", relation.message, relation.code);
|
|
1037
|
+
}
|
|
1038
|
+
if (relation.status === "strict") {
|
|
1039
|
+
return failResult(
|
|
1040
|
+
"post-review-commit",
|
|
1041
|
+
"Merged PR evidence did not establish squash merge equivalence",
|
|
1042
|
+
"PR_MERGE_IDENTITY_INVALID"
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
return failResult("post-review-commit", relation.message, relation.code);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
|
|
688
1049
|
const baselineSource = resolvePostReviewBaseline({
|
|
689
1050
|
gitRoot,
|
|
690
1051
|
lastReviewedCommit,
|
|
@@ -695,7 +1056,6 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
|
|
|
695
1056
|
}
|
|
696
1057
|
|
|
697
1058
|
const sha = baselineSource.sha;
|
|
698
|
-
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repoRoot));
|
|
699
1059
|
let commits;
|
|
700
1060
|
try {
|
|
701
1061
|
const out = execFileSync("git", ["-C", gitRoot, "rev-list", `${sha}..HEAD`, "--", ...globs], { encoding: "utf8" });
|
|
@@ -708,42 +1068,50 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
|
|
|
708
1068
|
return passResult("post-review-commit", `No post-review commits to code/rule paths since ${sha.slice(0, 8)}`);
|
|
709
1069
|
}
|
|
710
1070
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
1071
|
+
let localHead = "";
|
|
1072
|
+
try {
|
|
1073
|
+
localHead = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
|
|
1074
|
+
} catch {
|
|
1075
|
+
return blockedResult("post-review-commit", "Unable to resolve the local HEAD");
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
if (hasPullRequest) {
|
|
1079
|
+
if (inspected?.pullRequest) {
|
|
720
1080
|
const relation = resolveReviewedHeadRelation({
|
|
721
1081
|
gitRoot,
|
|
722
|
-
localHead,
|
|
1082
|
+
comparisonHead: localHead,
|
|
723
1083
|
lastReviewedCommit: sha,
|
|
724
|
-
pullRequest: inspected.pullRequest
|
|
725
|
-
pathspecs: globs
|
|
1084
|
+
pullRequest: inspected.pullRequest
|
|
726
1085
|
});
|
|
727
1086
|
if (relation.status === "merged-equivalent") {
|
|
728
1087
|
return passResult("post-review-commit", `Reviewed PR head is content-equivalent to squash merge ${relation.mergeCommit.slice(0, 8)}`);
|
|
729
1088
|
}
|
|
730
1089
|
if (relation.status === "blocked") {
|
|
731
|
-
return blockedResult("post-review-commit", relation.message);
|
|
1090
|
+
return blockedResult("post-review-commit", relation.message, relation.code);
|
|
732
1091
|
}
|
|
733
|
-
}
|
|
734
|
-
|
|
1092
|
+
}
|
|
1093
|
+
} else if (commits.length === 1) {
|
|
1094
|
+
const relation = resolveLocalReviewedCommitRelation({
|
|
1095
|
+
gitRoot,
|
|
1096
|
+
localHead,
|
|
1097
|
+
lastReviewedCommit: sha,
|
|
1098
|
+
rewrittenCommit: commits[0]!,
|
|
1099
|
+
pathspecs: globs
|
|
1100
|
+
});
|
|
1101
|
+
if (relation.status === "local-equivalent") {
|
|
1102
|
+
return passResult(
|
|
1103
|
+
"post-review-commit",
|
|
1104
|
+
`Reviewed commit is content-equivalent to local rewrite ${relation.rewrittenCommit.slice(0, 8)}`
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
if (relation.status === "blocked") {
|
|
1108
|
+
return blockedResult("post-review-commit", relation.message);
|
|
735
1109
|
}
|
|
736
1110
|
}
|
|
737
1111
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
(row) => row.stage === POST_REVIEW_COMMIT_STAGE && row.status === "human-decided"
|
|
742
|
-
);
|
|
743
|
-
} catch {
|
|
744
|
-
return failResult("post-review-commit", "Invalid disagreement ledger");
|
|
745
|
-
}
|
|
746
|
-
if (exempt) {
|
|
1112
|
+
const exemption = resolvePostReviewExemption(task.content);
|
|
1113
|
+
if (!exemption.ok) return failResult("post-review-commit", exemption.message);
|
|
1114
|
+
if (exemption.exempt) {
|
|
747
1115
|
return passResult(
|
|
748
1116
|
"post-review-commit",
|
|
749
1117
|
`${commits.length} post-review commit(s) covered by a human-decided exemption`
|
|
@@ -756,6 +1124,21 @@ function checkPostReviewCommit({ taskDir, config }: any): any {
|
|
|
756
1124
|
);
|
|
757
1125
|
}
|
|
758
1126
|
|
|
1127
|
+
function resolvePostReviewExemption(content: string):
|
|
1128
|
+
| { ok: true; exempt: boolean }
|
|
1129
|
+
| { ok: false; message: string } {
|
|
1130
|
+
try {
|
|
1131
|
+
return {
|
|
1132
|
+
ok: true,
|
|
1133
|
+
exempt: parseLedger(content).some(
|
|
1134
|
+
(row) => row.stage === POST_REVIEW_COMMIT_STAGE && row.status === "human-decided"
|
|
1135
|
+
)
|
|
1136
|
+
};
|
|
1137
|
+
} catch {
|
|
1138
|
+
return { ok: false, message: "Invalid disagreement ledger" };
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
|
|
759
1142
|
function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
760
1143
|
const resolvedArtifact = resolveArtifactPath(
|
|
761
1144
|
taskDir,
|
|
@@ -774,6 +1157,7 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
|
774
1157
|
const content = fs.readFileSync(resolvedArtifact.path, "utf8");
|
|
775
1158
|
const verdict = parseReviewVerdict(content);
|
|
776
1159
|
const reviewBaseline = extractReviewBaseline(content);
|
|
1160
|
+
const reviewDiffBase = extractReviewDiffBase(content);
|
|
777
1161
|
const reviewedFingerprint = extractReviewDiffFingerprint(content);
|
|
778
1162
|
const reviewedTree = extractReviewedSnapshotTree(content);
|
|
779
1163
|
|
|
@@ -784,10 +1168,16 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
|
784
1168
|
let gitRoot;
|
|
785
1169
|
let head;
|
|
786
1170
|
let baseline;
|
|
1171
|
+
let diffBase;
|
|
787
1172
|
try {
|
|
788
1173
|
gitRoot = execFileSync("git", ["-C", taskDir, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
|
|
789
1174
|
head = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
|
|
790
1175
|
baseline = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewBaseline}^{commit}`], { encoding: "utf8" }).trim();
|
|
1176
|
+
diffBase = execFileSync(
|
|
1177
|
+
"git",
|
|
1178
|
+
["-C", gitRoot, "rev-parse", `${reviewDiffBase || reviewBaseline}^{commit}`],
|
|
1179
|
+
{ encoding: "utf8" }
|
|
1180
|
+
).trim();
|
|
791
1181
|
} catch {
|
|
792
1182
|
return blockedResult(
|
|
793
1183
|
"review-fact",
|
|
@@ -804,7 +1194,13 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
|
804
1194
|
|
|
805
1195
|
let actualSnapshot;
|
|
806
1196
|
try {
|
|
807
|
-
actualSnapshot = snapshotReview({
|
|
1197
|
+
actualSnapshot = snapshotReview({
|
|
1198
|
+
cwd: gitRoot,
|
|
1199
|
+
mode: "worktree",
|
|
1200
|
+
baseline,
|
|
1201
|
+
diffBase,
|
|
1202
|
+
globs: resolvePostReviewGlobs({}, loadPostReviewConfig(repoRoot))
|
|
1203
|
+
});
|
|
808
1204
|
} catch {
|
|
809
1205
|
return blockedResult(
|
|
810
1206
|
"review-fact",
|
package/lib/task/verification.ts
CHANGED
|
@@ -16,7 +16,9 @@ type VerificationEvent =
|
|
|
16
16
|
| 'complete-task.preflight' | 'complete-task.completed'
|
|
17
17
|
| 'create-pr.completed' | 'create-task.completed'
|
|
18
18
|
| 'import-codescan.completed' | 'import-dependabot.completed'
|
|
19
|
-
| 'import-issue.completed' | 'watch-pr.completed'
|
|
19
|
+
| 'import-issue.completed' | 'watch-pr.completed'
|
|
20
|
+
| 'review-pr.completed'
|
|
21
|
+
| 'run-task.paused' | 'run-task.completed';
|
|
20
22
|
type VerificationSpec = {
|
|
21
23
|
skill: string;
|
|
22
24
|
expectedState: 'active' | 'blocked' | 'completed';
|
|
@@ -63,14 +65,17 @@ const VERIFICATION_CATALOG: Readonly<Record<VerificationEvent, VerificationSpec>
|
|
|
63
65
|
'block-task.completed': gate('block-task', 'blocked'),
|
|
64
66
|
'cancel-task.completed': gate('cancel-task', 'completed'),
|
|
65
67
|
'commit.completed': gate('commit', 'active'),
|
|
66
|
-
'complete-task.preflight': { skill: 'complete-task', expectedState: 'active', mode: 'checks', checks: ['review-ledger', 'post-review-commit', 'platform-sync-preflight'] },
|
|
68
|
+
'complete-task.preflight': { skill: 'complete-task', expectedState: 'active', mode: 'checks', checks: ['review-ledger', 'manual-validation', 'post-review-commit', 'platform-sync-preflight'] },
|
|
67
69
|
'complete-task.completed': gate('complete-task', 'completed'),
|
|
68
70
|
'create-pr.completed': gate('create-pr', 'active'),
|
|
69
71
|
'create-task.completed': gate('create-task', 'active'),
|
|
70
72
|
'import-codescan.completed': gate('import-codescan', 'active'),
|
|
71
73
|
'import-dependabot.completed': gate('import-dependabot', 'active'),
|
|
72
74
|
'import-issue.completed': gate('import-issue', 'active'),
|
|
73
|
-
'watch-pr.completed': gate('watch-pr', 'active')
|
|
75
|
+
'watch-pr.completed': gate('watch-pr', 'active'),
|
|
76
|
+
'review-pr.completed': gate('review-pr', 'active', 'pr-review'),
|
|
77
|
+
'run-task.paused': { skill: 'run-task', expectedState: 'active', mode: 'checks', checks: ['orchestration-state', 'orchestration-evidence'] },
|
|
78
|
+
'run-task.completed': { skill: 'run-task', expectedState: 'active', mode: 'checks', checks: ['orchestration-state', 'orchestration-evidence'] }
|
|
74
79
|
};
|
|
75
80
|
|
|
76
81
|
function failure(request: { taskRef: string; event: string; artifact?: string }, code: string, message: string, extra: Partial<TaskVerificationResult> = {}): TaskVerificationResult {
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
|
|
6
|
+
function git(repoRoot: string, indexFile: string | null, args: string[]): string {
|
|
7
|
+
const env = indexFile ? { ...process.env, GIT_INDEX_FILE: indexFile } : process.env;
|
|
8
|
+
const result = spawnSync('git', args, { cwd: repoRoot, env, encoding: 'utf8' });
|
|
9
|
+
if (result.status !== 0) {
|
|
10
|
+
throw new Error(String(result.stderr || result.stdout || `git ${args[0]} failed`).trim());
|
|
11
|
+
}
|
|
12
|
+
return result.stdout;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type RepositorySnapshot = Readonly<{
|
|
16
|
+
head: string;
|
|
17
|
+
headTree: string;
|
|
18
|
+
worktreeTree: string;
|
|
19
|
+
}>;
|
|
20
|
+
|
|
21
|
+
function captureWorktreeTree(repoRoot: string, forcedPath: string | null): string {
|
|
22
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-infra-orchestration-index-'));
|
|
23
|
+
const indexFile = path.join(tempDir, 'index');
|
|
24
|
+
try {
|
|
25
|
+
git(repoRoot, indexFile, ['read-tree', 'HEAD']);
|
|
26
|
+
git(repoRoot, indexFile, ['add', '-A', '--', ':/']);
|
|
27
|
+
if (forcedPath && fs.existsSync(path.join(repoRoot, forcedPath))) {
|
|
28
|
+
git(repoRoot, indexFile, ['add', '-f', '--', forcedPath]);
|
|
29
|
+
}
|
|
30
|
+
return git(repoRoot, indexFile, ['write-tree']).trim();
|
|
31
|
+
} finally {
|
|
32
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function captureWorkspaceSnapshot(repoRoot: string, taskId: string | null): string {
|
|
37
|
+
const workspaceRelative = taskId
|
|
38
|
+
? `.agents/workspace/active/${taskId}`
|
|
39
|
+
: '.agents/workspace/active';
|
|
40
|
+
return captureWorktreeTree(repoRoot, workspaceRelative);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function captureRepositorySnapshot(repoRoot: string): RepositorySnapshot {
|
|
44
|
+
return {
|
|
45
|
+
head: git(repoRoot, null, ['rev-parse', 'HEAD']).trim(),
|
|
46
|
+
headTree: git(repoRoot, null, ['rev-parse', 'HEAD^{tree}']).trim(),
|
|
47
|
+
worktreeTree: captureWorktreeTree(repoRoot, null)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function diffWorkspaceSnapshots(repoRoot: string, before: string, after: string): string[] {
|
|
52
|
+
const output = git(repoRoot, null, ['diff', '--name-only', '-z', before, after]);
|
|
53
|
+
return output.split('\0').filter(Boolean);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { captureRepositorySnapshot, captureWorkspaceSnapshot, diffWorkspaceSnapshots };
|
|
57
|
+
export type { RepositorySnapshot };
|