@fitlab-ai/agent-infra 0.9.13 → 0.9.15
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 +10 -0
- package/README.zh-CN.md +10 -0
- package/bin/cli.ts +26 -9
- package/bin/internal-cli.sh +45 -0
- package/dist/bin/cli.js +173 -157
- package/dist/bin/internal-cli.js +126 -42
- package/dist/lib/agent-client.js +5 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -2
- package/dist/lib/defaults.json +103 -103
- package/dist/lib/fs/durable-write.js +37 -0
- package/dist/lib/fs/file-lock.js +111 -0
- package/dist/lib/host-control/audit.js +19 -0
- package/dist/lib/host-control/client.js +142 -0
- package/dist/lib/host-control/command.js +49 -0
- package/dist/lib/host-control/path.js +160 -0
- package/dist/lib/host-control/secure-fs.js +140 -0
- package/dist/lib/host-control/server.js +159 -0
- package/dist/lib/host-control/service.js +112 -0
- package/dist/lib/init.js +11 -2
- package/dist/lib/internal/agent-client.js +5 -2
- package/dist/lib/internal/cli-route-inventory.js +154 -0
- package/dist/lib/internal/codex-lifecycle.js +15 -12
- package/dist/lib/internal/codex-sandbox-controller.js +8 -2
- package/dist/lib/internal/demo-promotion.js +322 -0
- package/dist/lib/internal/demo-transcript.js +454 -0
- package/dist/lib/internal/git-workflow.js +10 -6
- package/dist/lib/internal/host-control.js +28 -0
- package/dist/lib/internal/manual-validation.js +322 -0
- package/dist/lib/internal/platform-checks.js +16 -4
- package/dist/lib/internal/platform-comment.js +16 -4
- package/dist/lib/internal/platform-context.js +4 -1
- package/dist/lib/internal/platform-issue.js +12 -4
- package/dist/lib/internal/platform-metadata.js +88 -0
- package/dist/lib/internal/platform-pr-review.js +16 -3
- package/dist/lib/internal/platform-pr.js +42 -14
- package/dist/lib/internal/platform-release-notes.js +6 -3
- package/dist/lib/internal/platform-security.js +93 -0
- package/dist/lib/internal/pr-review-grade.js +14 -3
- package/dist/lib/internal/release-workflow.js +82 -89
- package/dist/lib/internal/sandbox-control.js +171 -7
- package/dist/lib/internal/task-activity.js +13 -4
- package/dist/lib/internal/task-artifact.js +19 -107
- package/dist/lib/internal/task-context.js +4 -1
- package/dist/lib/internal/task-create.js +48 -14
- package/dist/lib/internal/task-delivery.js +4 -1
- package/dist/lib/internal/task-event.js +38 -35
- package/dist/lib/internal/task-finalization.js +4 -1
- package/dist/lib/internal/task-invalidation.js +4 -1
- package/dist/lib/internal/task-ledger.js +12 -1
- package/dist/lib/internal/task-lifecycle.js +4 -1
- package/dist/lib/internal/task-operation-registry.js +519 -0
- package/dist/lib/internal/task-orchestration.js +12 -0
- package/dist/lib/internal/task-override.js +10 -3
- package/dist/lib/internal/task-qualification.js +90 -0
- package/dist/lib/internal/task-review.js +10 -52
- package/dist/lib/internal/task-short-id.js +11 -1
- package/dist/lib/internal/task-snapshot.js +4 -1
- package/dist/lib/internal/task-validate.js +37 -12
- package/dist/lib/internal/task-verify.js +5 -1
- package/dist/lib/internal/task-warning.js +8 -1
- package/dist/lib/owned-path.js +33 -0
- package/dist/lib/platform/check-status.js +11 -0
- package/dist/lib/platform/comment-safety.js +229 -0
- package/dist/lib/platform/completion-backfill.js +1 -1
- package/dist/lib/platform/github-data.js +241 -0
- package/dist/lib/platform/github-provider.js +248 -26
- package/dist/lib/platform/issue-comments.js +146 -34
- package/dist/lib/platform/issues.js +1 -179
- package/dist/lib/platform/pr-change-report.js +6 -12
- package/dist/lib/platform/pr-checks.js +12 -65
- package/dist/lib/platform/pr-summary.js +83 -10
- package/dist/lib/platform/provider-contract.d.ts +67 -1
- package/dist/lib/platform/provider-contract.js +6 -2
- package/dist/lib/platform/provider-validation.js +76 -3
- package/dist/lib/platform/pull-requests.js +117 -275
- package/dist/lib/platform/repository-metadata.js +377 -0
- package/dist/lib/platform/security-alerts.js +155 -0
- package/dist/lib/platform/snapshots.js +2 -0
- package/dist/lib/platform/verification-sync.js +154 -162
- package/dist/lib/process-data/index.js +7 -0
- package/dist/lib/release/workflow.js +1 -1
- package/dist/lib/run/index.js +5 -0
- package/dist/lib/sandbox/commands/control-status.js +22 -0
- package/dist/lib/sandbox/commands/create.js +39 -8
- package/dist/lib/sandbox/commands/ls.js +5 -0
- package/dist/lib/sandbox/commands/rm.js +3 -807
- package/dist/lib/sandbox/commands/show.js +16 -0
- package/dist/lib/sandbox/control/audit.js +203 -0
- package/dist/lib/sandbox/control/client.js +125 -12
- package/dist/lib/sandbox/control/completed-reentry.js +85 -0
- package/dist/lib/sandbox/control/container-identity.js +28 -31
- package/dist/lib/sandbox/control/executor.js +233 -34
- package/dist/lib/sandbox/control/finalization-response.js +27 -0
- package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
- package/dist/lib/sandbox/control/lifecycle.js +656 -128
- package/dist/lib/sandbox/control/native-file-lock.js +85 -0
- package/dist/lib/sandbox/control/protocol.js +55 -4
- package/dist/lib/sandbox/control/server.js +720 -79
- package/dist/lib/sandbox/control/state.js +63 -3
- package/dist/lib/sandbox/control/task-view.js +183 -0
- package/dist/lib/sandbox/control/task-workflow.js +74 -0
- package/dist/lib/sandbox/control/workflow-executor.js +99 -0
- package/dist/lib/sandbox/engines/authority.js +289 -0
- package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
- package/dist/lib/sandbox/index.js +7 -2
- package/dist/lib/sandbox/recovery.js +49 -5
- package/dist/lib/sandbox/removal.js +1717 -0
- package/dist/lib/sandbox/task-cleanup.js +217 -0
- package/dist/lib/sandbox/workspace-view.js +15 -15
- package/dist/lib/sandbox/worktree-safety.js +4 -1
- package/dist/lib/server/index.js +8 -0
- package/dist/lib/task/activity-intent.js +2 -1
- package/dist/lib/task/activity-log.js +30 -24
- package/dist/lib/task/artifact-command.js +101 -0
- package/dist/lib/task/artifact-lifecycle.js +71 -40
- package/dist/lib/task/artifact-name.js +36 -0
- package/dist/lib/task/artifact-operations.js +474 -0
- package/dist/lib/task/artifact-receipts.js +3 -15
- package/dist/lib/task/artifact-repair-intent.js +130 -0
- package/dist/lib/task/artifact-schema.js +127 -0
- package/dist/lib/task/capabilities.js +83 -19
- package/dist/lib/task/codex-orchestration.js +71 -25
- package/dist/lib/task/commit-identity.js +28 -0
- package/dist/lib/task/commit-operation.js +2 -16
- package/dist/lib/task/control-authority.js +375 -5
- package/dist/lib/task/control-recovery.js +128 -0
- package/dist/lib/task/create-service.js +103 -4
- package/dist/lib/task/create.js +80 -2
- package/dist/lib/task/decision-details.js +2 -46
- package/dist/lib/task/events.js +306 -76
- package/dist/lib/task/finalization-state.js +9 -0
- package/dist/lib/task/human-override.js +3 -6
- package/dist/lib/task/implementation-inputs.js +3 -3
- package/dist/lib/task/index.js +11 -3
- package/dist/lib/task/intermediate-cleanup.js +383 -0
- package/dist/lib/task/invalidation.js +18 -65
- package/dist/lib/task/ledger-intents.js +7 -22
- package/dist/lib/task/ledger.js +1 -3
- package/dist/lib/task/lifecycle.js +19 -1
- package/dist/lib/task/local-artifact-finalization.js +190 -290
- package/dist/lib/task/manual-validation-completion.js +26 -0
- package/dist/lib/task/manual-validation-evidence.js +130 -0
- package/dist/lib/task/manual-validation-receipt.js +101 -0
- package/dist/lib/task/manual-validation-shared.js +40 -0
- package/dist/lib/task/manual-validation-transaction.js +243 -0
- package/dist/lib/task/markdown.js +47 -0
- package/dist/lib/task/orchestration.js +206 -69
- package/dist/lib/task/qualification-audit.js +476 -0
- package/dist/lib/task/qualification-confirmation.js +109 -0
- package/dist/lib/task/qualification-intents.js +148 -0
- package/dist/lib/task/review-artifacts.js +23 -40
- package/dist/lib/task/review-command.js +25 -0
- package/dist/lib/task/review-finalization.js +146 -97
- package/dist/lib/task/review-fingerprint.js +2 -2
- package/dist/lib/task/sections.js +34 -54
- package/dist/lib/task/verification-config.js +11 -0
- package/dist/lib/task/verification-engine.js +170 -327
- package/dist/lib/task/verification.js +1 -1
- package/dist/lib/task/workflow-command.js +17 -0
- package/dist/lib/task/workflow-warning-intents.js +0 -16
- package/dist/lib/task/workflow-warnings.js +28 -2
- package/dist/lib/update.js +2 -0
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +9 -0
- package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -2
- package/lib/fs/durable-write.ts +29 -0
- package/lib/fs/file-lock.ts +113 -0
- package/lib/host-control/audit.ts +22 -0
- package/lib/host-control/client.ts +172 -0
- package/lib/host-control/command.ts +60 -0
- package/lib/host-control/path.ts +167 -0
- package/lib/host-control/secure-fs.ts +135 -0
- package/lib/host-control/server.ts +180 -0
- package/lib/host-control/service.ts +133 -0
- package/lib/init.ts +15 -2
- package/lib/internal/agent-client.ts +4 -2
- package/lib/internal/cli-route-inventory.ts +142 -0
- package/lib/internal/codex-lifecycle.ts +14 -12
- package/lib/internal/codex-sandbox-controller.ts +7 -2
- package/lib/internal/demo-promotion.ts +354 -0
- package/lib/internal/demo-transcript.ts +419 -0
- package/lib/internal/git-workflow.ts +9 -6
- package/lib/internal/host-control.ts +28 -0
- package/lib/internal/manual-validation.ts +306 -0
- package/lib/internal/platform-checks.ts +12 -4
- package/lib/internal/platform-comment.ts +12 -4
- package/lib/internal/platform-context.ts +3 -1
- package/lib/internal/platform-issue.ts +11 -4
- package/lib/internal/platform-metadata.ts +70 -0
- package/lib/internal/platform-pr-review.ts +14 -3
- package/lib/internal/platform-pr.ts +38 -14
- package/lib/internal/platform-release-notes.ts +5 -3
- package/lib/internal/platform-security.ts +83 -0
- package/lib/internal/pr-review-grade.ts +10 -3
- package/lib/internal/release-workflow.ts +91 -87
- package/lib/internal/sandbox-control.ts +181 -6
- package/lib/internal/task-activity.ts +12 -4
- package/lib/internal/task-artifact.ts +15 -79
- package/lib/internal/task-context.ts +3 -1
- package/lib/internal/task-create.ts +76 -15
- package/lib/internal/task-delivery.ts +3 -1
- package/lib/internal/task-event.ts +21 -10
- package/lib/internal/task-finalization.ts +3 -1
- package/lib/internal/task-invalidation.ts +3 -1
- package/lib/internal/task-ledger.ts +11 -1
- package/lib/internal/task-lifecycle.ts +3 -1
- package/lib/internal/task-operation-registry.ts +590 -0
- package/lib/internal/task-orchestration.ts +12 -0
- package/lib/internal/task-override.ts +9 -3
- package/lib/internal/task-qualification.ts +61 -0
- package/lib/internal/task-review.ts +7 -50
- package/lib/internal/task-short-id.ts +10 -1
- package/lib/internal/task-snapshot.ts +3 -1
- package/lib/internal/task-validate.ts +32 -12
- package/lib/internal/task-verify.ts +4 -1
- package/lib/internal/task-warning.ts +7 -1
- package/lib/owned-path.ts +26 -0
- package/lib/platform/check-status.ts +9 -0
- package/lib/platform/comment-safety.ts +255 -0
- package/lib/platform/completion-backfill.ts +1 -1
- package/lib/platform/github-data.ts +322 -0
- package/lib/platform/github-provider.ts +244 -27
- package/lib/platform/issue-comments.ts +159 -35
- package/lib/platform/issues.ts +4 -245
- package/lib/platform/pr-change-report.ts +6 -12
- package/lib/platform/pr-checks.ts +13 -77
- package/lib/platform/pr-summary.ts +88 -11
- package/lib/platform/provider-contract.ts +78 -3
- package/lib/platform/provider-validation.ts +85 -3
- package/lib/platform/pull-requests.ts +129 -348
- package/lib/platform/repository-metadata.ts +453 -0
- package/lib/platform/security-alerts.ts +191 -0
- package/lib/platform/snapshots.ts +53 -0
- package/lib/platform/verification-sync.ts +171 -177
- package/lib/process-data/index.ts +7 -0
- package/lib/release/workflow.ts +3 -3
- package/lib/run/index.ts +5 -0
- package/lib/sandbox/commands/control-status.ts +26 -0
- package/lib/sandbox/commands/create.ts +53 -12
- package/lib/sandbox/commands/ls.ts +7 -0
- package/lib/sandbox/commands/rm.ts +3 -996
- package/lib/sandbox/commands/show.ts +16 -0
- package/lib/sandbox/control/audit.ts +253 -0
- package/lib/sandbox/control/client.ts +150 -13
- package/lib/sandbox/control/completed-reentry.ts +98 -0
- package/lib/sandbox/control/container-identity.ts +27 -43
- package/lib/sandbox/control/executor.ts +262 -37
- package/lib/sandbox/control/finalization-response.ts +29 -0
- package/lib/sandbox/control/identity-sentinel.ts +137 -0
- package/lib/sandbox/control/lifecycle.ts +672 -18
- package/lib/sandbox/control/native-file-lock.ts +108 -0
- package/lib/sandbox/control/protocol.ts +80 -8
- package/lib/sandbox/control/server.ts +779 -82
- package/lib/sandbox/control/state.ts +84 -3
- package/lib/sandbox/control/task-view.ts +240 -0
- package/lib/sandbox/control/task-workflow.ts +95 -0
- package/lib/sandbox/control/workflow-executor.ts +102 -0
- package/lib/sandbox/engines/authority.ts +365 -0
- package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
- package/lib/sandbox/index.ts +9 -2
- package/lib/sandbox/recovery.ts +49 -6
- package/lib/sandbox/removal.ts +2144 -0
- package/lib/sandbox/task-cleanup.ts +209 -0
- package/lib/sandbox/workspace-view.ts +26 -18
- package/lib/sandbox/worktree-safety.ts +4 -1
- package/lib/server/index.ts +10 -0
- package/lib/task/activity-intent.ts +2 -2
- package/lib/task/activity-log.ts +27 -19
- package/lib/task/artifact-command.ts +104 -0
- package/lib/task/artifact-lifecycle.ts +66 -39
- package/lib/task/artifact-name.ts +55 -0
- package/lib/task/artifact-operations.ts +580 -0
- package/lib/task/artifact-receipts.ts +3 -14
- package/lib/task/artifact-repair-intent.ts +152 -0
- package/lib/task/artifact-schema.ts +163 -0
- package/lib/task/capabilities.ts +82 -22
- package/lib/task/codex-orchestration.ts +85 -24
- package/lib/task/commit-identity.ts +31 -0
- package/lib/task/commit-operation.ts +2 -16
- package/lib/task/control-authority.ts +513 -6
- package/lib/task/control-recovery.ts +174 -0
- package/lib/task/create-service.ts +131 -6
- package/lib/task/create.ts +83 -1
- package/lib/task/decision-details.ts +3 -71
- package/lib/task/events.ts +292 -75
- package/lib/task/finalization-state.ts +11 -0
- package/lib/task/human-override.ts +3 -8
- package/lib/task/implementation-inputs.ts +3 -3
- package/lib/task/index.ts +16 -3
- package/lib/task/intermediate-cleanup.ts +455 -0
- package/lib/task/invalidation.ts +18 -62
- package/lib/task/ledger-intents.ts +7 -24
- package/lib/task/ledger.ts +1 -3
- package/lib/task/lifecycle.ts +17 -1
- package/lib/task/local-artifact-finalization.ts +223 -388
- package/lib/task/manual-validation-completion.ts +40 -0
- package/lib/task/manual-validation-evidence.ts +209 -0
- package/lib/task/manual-validation-receipt.ts +152 -0
- package/lib/task/manual-validation-shared.ts +50 -0
- package/lib/task/manual-validation-transaction.ts +304 -0
- package/lib/task/markdown.ts +70 -0
- package/lib/task/orchestration.ts +191 -68
- package/lib/task/qualification-audit.ts +588 -0
- package/lib/task/qualification-confirmation.ts +117 -0
- package/lib/task/qualification-intents.ts +150 -0
- package/lib/task/review-artifacts.ts +21 -41
- package/lib/task/review-command.ts +23 -0
- package/lib/task/review-finalization.ts +154 -153
- package/lib/task/review-fingerprint.ts +2 -2
- package/lib/task/sections.ts +33 -52
- package/lib/task/verification-config.ts +12 -0
- package/lib/task/verification-engine.ts +165 -370
- package/lib/task/verification-types.ts +17 -0
- package/lib/task/verification.ts +1 -1
- package/lib/task/workflow-command.ts +18 -0
- package/lib/task/workflow-warning-intents.ts +0 -13
- package/lib/task/workflow-warnings.ts +21 -2
- package/lib/update.ts +6 -0
- package/package.json +7 -2
- package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
- package/templates/.agents/rules/README.en.md +2 -0
- package/templates/.agents/rules/README.zh-CN.md +2 -0
- package/templates/.agents/rules/decision-qualification.en.md +22 -0
- package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
- package/templates/.agents/rules/evidence-reporting.en.md +28 -0
- package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
- package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
- package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
- package/templates/.agents/rules/security-alerts.en.md +8 -8
- package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
- package/templates/.agents/rules/testing-discipline.en.md +2 -0
- package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
- package/templates/.agents/scripts/package.json +3 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
- package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
- package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
- package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +37 -21
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +37 -21
- 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/report-template.en.md +4 -0
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +4 -0
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
- package/templates/.agents/skills/complete-task/SKILL.en.md +10 -23
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -23
- package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
- package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
- package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
- package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
- package/templates/.agents/skills/release/SKILL.en.md +7 -3
- package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
- package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
- package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
- package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +25 -4
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +25 -4
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +5 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +5 -1
- package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/test/SKILL.en.md +29 -7
- package/templates/.agents/skills/test/SKILL.zh-CN.md +29 -7
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
- package/templates/.agents/templates/task.en.md +6 -0
- package/templates/.agents/templates/task.zh-CN.md +6 -0
- package/templates/.claude/commands/run-manual-validation.en.md +1 -1
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
- package/dist/lib/platform/adapters.js +0 -56
- package/lib/platform/adapters.ts +0 -197
- package/templates/.agents/scripts/security-alerts.github.sh +0 -151
- package/templates/.agents/scripts/security-alerts.sh +0 -31
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
|
@@ -12,16 +12,27 @@ import { resolveMaterializedReviewedHeadRelation } from "../platform/change-requ
|
|
|
12
12
|
import { resolveReviewedHeadRelation } from "../platform/merged-pr-equivalence.js";
|
|
13
13
|
import { resolveLocalReviewedCommitRelation } from "../git/reviewed-commit-equivalence.js";
|
|
14
14
|
import { parseTypedTaskFrontmatter } from "./frontmatter.js";
|
|
15
|
-
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from "./ledger.js";
|
|
15
|
+
import { LEDGER_TERMINAL, LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from "./ledger.js";
|
|
16
16
|
import { isValidAgentInfraVersion } from "../version.js";
|
|
17
17
|
import { equalCounts, parseReviewSummary } from "./review-artifacts.js";
|
|
18
18
|
import { inspectDecisionDetailDuplicates } from "./decision-details.js";
|
|
19
|
+
import { parseImplementationInputs } from "./implementation-inputs.js";
|
|
20
|
+
import { scanVisibleMarkdown } from "./markdown.js";
|
|
19
21
|
import { loadVerificationConfig } from "./verification-config.js";
|
|
20
22
|
import { snapshotReview } from "../git/review-snapshot.js";
|
|
23
|
+
import { inspectActivityLog } from "./activity-log.js";
|
|
24
|
+
import { parseWorkflowWarnings } from "./workflow-warnings.js";
|
|
21
25
|
import { OrchestrationStateError, readRun } from "./orchestration.js";
|
|
22
26
|
import { resolveDeliveryTarget } from "./delivery-target.js";
|
|
23
27
|
import { readPrDeliveryFact } from "./pr-delivery-fact.js";
|
|
24
28
|
import { validateLocalArtifact } from "./local-artifact-finalization.js";
|
|
29
|
+
import { validateQualificationAudit } from "./qualification-audit.js";
|
|
30
|
+
import { getArtifactSchema } from "./artifact-schema.js";
|
|
31
|
+
import { inspectArtifactContract } from "./artifact-operations.js";
|
|
32
|
+
import { manualValidationFinalSummaryProjectionMatches } from "./manual-validation-receipt.js";
|
|
33
|
+
import { readManualValidationCompletion } from "./manual-validation-completion.js";
|
|
34
|
+
import { sha256File } from "./artifact-receipts.js";
|
|
35
|
+
import { summaryCommentState } from "../platform/pr-summary.js";
|
|
25
36
|
const TASK_ENUMS = {
|
|
26
37
|
type: ["feature", "bugfix", "refactor", "docs", "chore"],
|
|
27
38
|
workflow: ["feature-development", "bug-fix", "refactoring"],
|
|
@@ -39,7 +50,6 @@ const DEFAULT_REQUIRED_FIELDS = [
|
|
|
39
50
|
"assigned_to"
|
|
40
51
|
];
|
|
41
52
|
const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
|
|
42
|
-
const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
|
|
43
53
|
// Start markers (action suffixed with ` [started]`) are excluded from the
|
|
44
54
|
// "latest action" / freshness computation so a step's in-flight marker never
|
|
45
55
|
// satisfies a skill's expected_action_pattern; the matching done entry does.
|
|
@@ -47,27 +57,11 @@ const ACTIVITY_LOG_STARTED_RE = /\s*\[started\]\s*$/;
|
|
|
47
57
|
const BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
48
58
|
// Review disagreement ledger (see .agents/rules/review-handshake.md).
|
|
49
59
|
const LEDGER_SECTION_NAMES = ["审查分歧账本", "Review Disagreement Ledger"];
|
|
50
|
-
const LEDGER_STATUSES = new Set([
|
|
51
|
-
"open",
|
|
52
|
-
"accepted",
|
|
53
|
-
"adjusted",
|
|
54
|
-
"refuted",
|
|
55
|
-
"cannot-judge",
|
|
56
|
-
"confirmed",
|
|
57
|
-
"needs-human-decision",
|
|
58
|
-
"closed",
|
|
59
|
-
"human-decided"
|
|
60
|
-
]);
|
|
61
|
-
const LEDGER_TERMINAL_OK = new Set(["confirmed", "closed", "human-decided"]);
|
|
62
60
|
const DEFAULT_MAX_HANDSHAKE_ROUNDS = 3;
|
|
63
61
|
const POST_REVIEW_COMMIT_STAGE = "post-review-commit";
|
|
64
62
|
const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
|
|
65
|
-
const WORKFLOW_WARNING_SECTION_NAMES = ["工作流告警", "Workflow Warnings"];
|
|
66
|
-
const WORKFLOW_WARNING_STATUSES = new Set(["open", "resolved", "ignored"]);
|
|
67
|
-
const WORKFLOW_WARNING_SEVERITIES = new Set(["IMPORTANT", "ACTION_REQUIRED"]);
|
|
68
|
-
const WORKFLOW_WARNING_ID_PATTERN = /^WW-\d+$/;
|
|
69
63
|
const scriptPath = fileURLToPath(import.meta.url);
|
|
70
|
-
|
|
64
|
+
const defaultRepoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
|
|
71
65
|
const PLATFORM_ADAPTERS = {
|
|
72
66
|
"platform-sync": checkPlatformSync,
|
|
73
67
|
"platform-sync-preflight": async (context, shared) => ({ ...await checkPlatformSync(context, shared), type: "platform-sync-preflight" }),
|
|
@@ -172,14 +166,12 @@ function exactText(value) {
|
|
|
172
166
|
function validateCleanCompletionEvidence(run) {
|
|
173
167
|
const evidence = run.completionEvidence;
|
|
174
168
|
const shaPattern = /^[0-9a-f]{40}$/i;
|
|
175
|
-
if (evidence
|
|
176
|
-
|| !exactText(evidence.observedAt)
|
|
169
|
+
if (!evidence
|
|
177
170
|
|| Number.isNaN(Date.parse(evidence.observedAt))
|
|
178
171
|
|| !shaPattern.test(evidence.head)
|
|
179
172
|
|| !shaPattern.test(evidence.headTree)
|
|
180
173
|
|| !shaPattern.test(evidence.worktreeTree)
|
|
181
174
|
|| !shaPattern.test(evidence.lastReviewedCommit)
|
|
182
|
-
|| !(evidence.prNumber === null || (Number.isInteger(evidence.prNumber) && evidence.prNumber > 0))
|
|
183
175
|
|| !(evidence.prHead === null || shaPattern.test(evidence.prHead))) {
|
|
184
176
|
return 'Clean completion evidence has an invalid structure';
|
|
185
177
|
}
|
|
@@ -192,7 +184,6 @@ function validateCleanCompletionEvidence(run) {
|
|
|
192
184
|
|| run.pendingDelegation !== null
|
|
193
185
|
|| run.commitAuthorization?.issuedAt !== null
|
|
194
186
|
|| run.commitAuthorization?.consumedAt !== null
|
|
195
|
-
|| !Array.isArray(run.receipts)
|
|
196
187
|
|| run.receipts.some((receipt) => receipt.stage === 'commit')) {
|
|
197
188
|
return 'Clean completion evidence conflicts with commit delegation state';
|
|
198
189
|
}
|
|
@@ -211,43 +202,10 @@ function checkOrchestrationEvidence({ taskDir }) {
|
|
|
211
202
|
const message = error instanceof OrchestrationStateError ? error.message : String(error);
|
|
212
203
|
return failResult('orchestration-evidence', `Invalid orchestration.json: ${message}`);
|
|
213
204
|
}
|
|
205
|
+
if (!run)
|
|
206
|
+
return failResult('orchestration-evidence', 'orchestration.json is missing');
|
|
207
|
+
// readRun validates the persisted schema, receipt identities and client provenance.
|
|
214
208
|
const policy = run.modelPolicy;
|
|
215
|
-
if (!policy
|
|
216
|
-
|| !exactText(policy.executor?.model)
|
|
217
|
-
|| !exactText(policy.executor?.reasoningEffort)
|
|
218
|
-
|| !exactText(policy.reviewer?.model)
|
|
219
|
-
|| !exactText(policy.reviewer?.reasoningEffort)) {
|
|
220
|
-
return failResult('orchestration-evidence', 'Run model policy requires exact executor and reviewer model and effort');
|
|
221
|
-
}
|
|
222
|
-
if (!run.modelPolicySource
|
|
223
|
-
|| !['explicit', 'project-config'].includes(run.modelPolicySource.kind)
|
|
224
|
-
|| !exactText(run.modelPolicySource.client)
|
|
225
|
-
|| !exactText(run.modelPolicySource.resolvedAt)
|
|
226
|
-
|| !Array.isArray(run.recoveryHistory)) {
|
|
227
|
-
return failResult('orchestration-evidence', 'Run model policy source or recovery history is invalid');
|
|
228
|
-
}
|
|
229
|
-
for (const recovery of run.recoveryHistory) {
|
|
230
|
-
const guards = recovery.guards;
|
|
231
|
-
const validClaudeCodeRecovery = recovery.code === 'CLIENT_CAPABILITY_ENABLED'
|
|
232
|
-
&& recovery.previousStatus === 'paused'
|
|
233
|
-
&& recovery.previousPause?.code === 'ORCHESTRATION_CLIENT_UNSUPPORTED'
|
|
234
|
-
&& recovery.client === 'claude-code'
|
|
235
|
-
&& recovery.resultingStatus === 'running'
|
|
236
|
-
&& exactText(recovery.recoveredAt)
|
|
237
|
-
&& guards?.stepCount === 0
|
|
238
|
-
&& guards?.nextStage === null
|
|
239
|
-
&& guards?.baselineEmpty === true
|
|
240
|
-
&& guards?.receiptCount === 0
|
|
241
|
-
&& guards?.pendingDelegation === false
|
|
242
|
-
&& guards?.commitAuthorizationUnused === true
|
|
243
|
-
&& guards?.completionEvidenceAbsent === true;
|
|
244
|
-
if (!validClaudeCodeRecovery) {
|
|
245
|
-
return failResult('orchestration-evidence', 'Run recovery history contains invalid provenance');
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
if (!Array.isArray(run.receipts)) {
|
|
249
|
-
return failResult('orchestration-evidence', 'Run receipts must be an array');
|
|
250
|
-
}
|
|
251
209
|
if (run.completionEvidence != null) {
|
|
252
210
|
const evidenceError = validateCleanCompletionEvidence(run);
|
|
253
211
|
if (evidenceError)
|
|
@@ -279,10 +237,6 @@ function checkOrchestrationEvidence({ taskDir }) {
|
|
|
279
237
|
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has no host-observed actual reasoning effort`);
|
|
280
238
|
}
|
|
281
239
|
}
|
|
282
|
-
// parentId/childId 校验对所有 client 保持统一(不新增分支);spawnMode 检查按 client 判断
|
|
283
|
-
if (!exactText(receipt.parentId) || !exactText(receipt.childId) || receipt.parentId === receipt.childId) {
|
|
284
|
-
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid delegation identity`);
|
|
285
|
-
}
|
|
286
240
|
if (!isClaudeCode && receipt.spawnMode !== 'fresh') {
|
|
287
241
|
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid fresh delegation identity`);
|
|
288
242
|
}
|
|
@@ -304,41 +258,6 @@ function checkOrchestrationEvidence({ taskDir }) {
|
|
|
304
258
|
&& receipt.reasoningEffortFallbackReason !== null) {
|
|
305
259
|
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has an unrelated reasoning-effort fallback reason`);
|
|
306
260
|
}
|
|
307
|
-
if (receipt.client === 'codex') {
|
|
308
|
-
const activatedCodex = ['activated', 'stage-completed', 'sealed', 'consumed'].includes(receipt.status);
|
|
309
|
-
const host = receipt.hostEvidence;
|
|
310
|
-
const provenance = receipt.lifecycleProvenance;
|
|
311
|
-
if (!provenance
|
|
312
|
-
|| (activatedCodex && (host?.kind !== 'codex-lifecycle-v2'
|
|
313
|
-
|| host.protocolVersion !== provenance.protocolVersion
|
|
314
|
-
|| host.hookDefinitionHash !== provenance.hookDefinitionHash
|
|
315
|
-
|| host.hookSource !== provenance.hookSource
|
|
316
|
-
|| host.hookSourcePathDigest !== provenance.hookSourcePathDigest
|
|
317
|
-
|| host.hookSourceHash !== provenance.hookSourceHash
|
|
318
|
-
|| host.capabilitySessionId !== provenance.capabilitySessionId
|
|
319
|
-
|| receipt.parentId !== provenance.capabilitySessionId
|
|
320
|
-
|| host.capabilityTurnId !== provenance.capabilityTurnId
|
|
321
|
-
|| host.controllerInstanceDigest !== provenance.controllerInstanceDigest
|
|
322
|
-
|| host.controlGeneration !== provenance.controlGeneration
|
|
323
|
-
|| host.spawnToolUseId === provenance.capabilityToolUseId
|
|
324
|
-
|| !exactText(host.spawnToolUseId)
|
|
325
|
-
|| !Number.isFinite(Date.parse(host.spawnObservedAt ?? ''))
|
|
326
|
-
|| !Number.isFinite(Date.parse(receipt.spawnDispatchedAt ?? ''))
|
|
327
|
-
|| !Number.isFinite(Date.parse(receipt.activationDeadlineAt ?? ''))
|
|
328
|
-
|| Date.parse(host.spawnObservedAt ?? '') < Date.parse(receipt.spawnDispatchedAt ?? '')
|
|
329
|
-
|| Date.parse(host.spawnObservedAt ?? '') > Date.parse(receipt.activationDeadlineAt ?? '')
|
|
330
|
-
|| !exactText(host.hookDefinitionHash)
|
|
331
|
-
|| !Number.isSafeInteger(host.startRevision)
|
|
332
|
-
|| host.startRevision < 1))) {
|
|
333
|
-
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid Codex start evidence`);
|
|
334
|
-
}
|
|
335
|
-
if (['sealed', 'consumed'].includes(receipt.status) && (!Number.isSafeInteger(host.stopRevision)
|
|
336
|
-
|| host.stopRevision <= host.startRevision
|
|
337
|
-
|| host.consumer !== receipt.id
|
|
338
|
-
|| !exactText(host.consumedAt))) {
|
|
339
|
-
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid Codex consumed stop evidence`);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
261
|
}
|
|
343
262
|
}
|
|
344
263
|
if (run.receipts.some((receipt) => receipt.status !== 'consumed')) {
|
|
@@ -347,7 +266,7 @@ function checkOrchestrationEvidence({ taskDir }) {
|
|
|
347
266
|
return passResult('orchestration-evidence', 'Persisted orchestration model and delegation evidence is internally consistent');
|
|
348
267
|
}
|
|
349
268
|
// === Check Functions ===
|
|
350
|
-
function checkTaskMeta({ taskDir, config }) {
|
|
269
|
+
function checkTaskMeta({ taskDir, config, repositoryRoot }) {
|
|
351
270
|
const task = loadTask(taskDir);
|
|
352
271
|
if (!task.ok) {
|
|
353
272
|
return failResult("task-meta", task.message);
|
|
@@ -377,13 +296,15 @@ function checkTaskMeta({ taskDir, config }) {
|
|
|
377
296
|
return failResult("task-meta", `Invalid ${field}: ${metadata[field]}`);
|
|
378
297
|
}
|
|
379
298
|
}
|
|
380
|
-
const branchValidationError = validateTaskBranch(metadata);
|
|
299
|
+
const branchValidationError = validateTaskBranch(metadata, repositoryRoot);
|
|
381
300
|
if (branchValidationError) {
|
|
382
301
|
return failResult("task-meta", branchValidationError);
|
|
383
302
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
303
|
+
try {
|
|
304
|
+
parseWorkflowWarnings(task.content);
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
return failResult("task-meta", `Invalid Workflow Warnings: ${error instanceof Error ? error.message : String(error)}`);
|
|
387
308
|
}
|
|
388
309
|
const expectedStep = config.expected_step;
|
|
389
310
|
if (expectedStep && metadata.current_step !== expectedStep) {
|
|
@@ -478,11 +399,11 @@ async function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }) {
|
|
|
478
399
|
}
|
|
479
400
|
return passResult('required-pr-delivery', `Pull request delivery policy satisfied (${status})`);
|
|
480
401
|
}
|
|
481
|
-
function validateTaskBranch(metadata) {
|
|
402
|
+
function validateTaskBranch(metadata, repoRoot) {
|
|
482
403
|
if (isBlank(metadata.branch)) {
|
|
483
404
|
return null;
|
|
484
405
|
}
|
|
485
|
-
const projectName = loadProjectName();
|
|
406
|
+
const projectName = loadProjectName(repoRoot);
|
|
486
407
|
const expectedPrefix = projectName ? `${projectName}-${metadata.type}-` : "";
|
|
487
408
|
if (expectedPrefix && !String(metadata.branch).startsWith(expectedPrefix)) {
|
|
488
409
|
return `Invalid branch: expected prefix '${expectedPrefix}', got '${metadata.branch}'`;
|
|
@@ -493,7 +414,7 @@ function validateTaskBranch(metadata) {
|
|
|
493
414
|
}
|
|
494
415
|
return null;
|
|
495
416
|
}
|
|
496
|
-
function loadProjectName() {
|
|
417
|
+
function loadProjectName(repoRoot) {
|
|
497
418
|
const configPath = path.join(repoRoot, ".agents", ".airc.json");
|
|
498
419
|
if (!fs.existsSync(configPath)) {
|
|
499
420
|
return "";
|
|
@@ -520,21 +441,57 @@ function checkArtifact({ taskDir, config, artifactFile, skillName }) {
|
|
|
520
441
|
return failResult("artifact", `Artifact is empty: ${path.basename(artifactPath)}`);
|
|
521
442
|
}
|
|
522
443
|
const content = fs.readFileSync(artifactPath, "utf8");
|
|
523
|
-
|
|
444
|
+
let taskContent = "";
|
|
445
|
+
const taskPath = path.join(taskDir, "task.md");
|
|
446
|
+
if (fs.existsSync(taskPath)) {
|
|
447
|
+
try {
|
|
448
|
+
taskContent = fs.readFileSync(taskPath, "utf8");
|
|
449
|
+
}
|
|
450
|
+
catch (error) {
|
|
451
|
+
return failResult("artifact", `Cannot read task qualification contract: ${error instanceof Error ? error.message : String(error)}`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
if (taskContent && /^review-(?:analysis|plan|code)$/.test(skillName)) {
|
|
455
|
+
const qualification = validateQualificationAudit(taskContent, content, { artifact: path.basename(artifactPath) });
|
|
456
|
+
if (!qualification.ok)
|
|
457
|
+
return failResult("artifact", `${path.basename(artifactPath)} has qualification audit errors: ${qualification.code}: ${qualification.message}`);
|
|
458
|
+
}
|
|
459
|
+
const schemaFamily = skillName === "analyze-task"
|
|
460
|
+
? "analysis"
|
|
461
|
+
: skillName === "review-analysis"
|
|
462
|
+
? "review-analysis"
|
|
463
|
+
: skillName === "plan-task"
|
|
464
|
+
? "plan"
|
|
465
|
+
: skillName === "review-plan"
|
|
466
|
+
? "review-plan"
|
|
467
|
+
: skillName === "code-task"
|
|
468
|
+
? "code"
|
|
469
|
+
: skillName === "review-code" ? "review-code" : null;
|
|
470
|
+
const schema = schemaFamily ? getArtifactSchema(schemaFamily) : null;
|
|
524
471
|
const localFamily = skillName === "analyze-task"
|
|
525
472
|
? "analysis"
|
|
526
473
|
: skillName === "plan-task" ? "plan" : skillName === "code-task" ? "code" : null;
|
|
474
|
+
if (schema) {
|
|
475
|
+
const structure = inspectArtifactContract(content, schema);
|
|
476
|
+
if (!structure.ok && !localFamily) {
|
|
477
|
+
return failResult("artifact", `${path.basename(artifactPath)} has shared structural errors: ${structure.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')}`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
527
480
|
if (localFamily) {
|
|
528
481
|
const local = validateLocalArtifact(content, {
|
|
529
482
|
family: localFamily,
|
|
530
|
-
|
|
531
|
-
|
|
483
|
+
...(taskContent ? { taskContent } : {}),
|
|
484
|
+
artifact: path.basename(artifactPath)
|
|
532
485
|
});
|
|
533
486
|
if (!local.ok) {
|
|
534
487
|
return failResult("artifact", `${path.basename(artifactPath)} has local structural errors: ${local.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')}`);
|
|
535
488
|
}
|
|
536
|
-
return passResult("artifact", `${path.basename(artifactPath)} passed (${
|
|
489
|
+
return passResult("artifact", `${path.basename(artifactPath)} passed (${schema?.sections.length ?? 0} sections)`);
|
|
490
|
+
}
|
|
491
|
+
if (schema) {
|
|
492
|
+
return passResult("artifact", `${path.basename(artifactPath)} passed (${schema.sections.length} sections)`);
|
|
537
493
|
}
|
|
494
|
+
const requiredSections = config.required_sections || [];
|
|
538
495
|
const missingSections = requiredSections.filter((section) => !new RegExp(`^##\\s+${escapeRegExp(section)}\\s*$`, "m").test(content));
|
|
539
496
|
if (missingSections.length > 0) {
|
|
540
497
|
return failResult("artifact", `${path.basename(artifactPath)} is missing sections: ${missingSections.join(", ")}`);
|
|
@@ -608,30 +565,17 @@ function checkImplementationInput({ taskDir, artifactFile }) {
|
|
|
608
565
|
const artifactPath = path.join(taskDir, artifactFile);
|
|
609
566
|
if (!safeStat(artifactPath)?.isFile())
|
|
610
567
|
return failResult("implementation-input", `Artifact not found: ${artifactFile}`);
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
const table = inputSection.split(/\r?\n/).filter((line) => line.trim().startsWith("|"));
|
|
615
|
-
const cells = (line) => line.split("|").slice(1, -1).map((cell) => cell.trim());
|
|
616
|
-
const expected = ["id", "ledger_id", "decision_evidence", "stage", "needs_implementation", "decided_at", "status", "consumed_by"];
|
|
617
|
-
if (table.length < 2 || JSON.stringify(cells(table[0])) !== JSON.stringify(expected)) {
|
|
618
|
-
return failResult("implementation-input", "Implementation Inputs table schema is invalid");
|
|
619
|
-
}
|
|
620
|
-
const seen = new Set();
|
|
621
|
-
for (const line of table.slice(2)) {
|
|
622
|
-
const row = cells(line);
|
|
623
|
-
if (row.length !== 8 || !/^II-[1-9]\d*$/.test(row[0]) || seen.has(row[0])) {
|
|
624
|
-
return failResult("implementation-input", "Implementation Inputs table contains an invalid or duplicate id");
|
|
625
|
-
}
|
|
626
|
-
seen.add(row[0]);
|
|
627
|
-
rows.push({ id: row[0], ledgerId: row[1], evidence: row[2], stage: row[3], needs: row[4], status: row[6], consumedBy: row[7] });
|
|
628
|
-
}
|
|
568
|
+
let rows;
|
|
569
|
+
try {
|
|
570
|
+
rows = parseImplementationInputs(task.content).rows;
|
|
629
571
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
572
|
+
catch (error) {
|
|
573
|
+
return failResult("implementation-input", `Invalid Implementation Inputs: ${error instanceof Error ? error.message : String(error)}`);
|
|
574
|
+
}
|
|
575
|
+
const doneActions = (inspectActivityLog(task.content).section?.entries ?? [])
|
|
576
|
+
.filter((entry) => !ACTIVITY_LOG_STARTED_RE.test(entry.step))
|
|
577
|
+
.map((entry) => entry.step)
|
|
578
|
+
.filter((step) => /^(?:Code Task|Code) \(Round \d+/.test(step));
|
|
635
579
|
const latestAction = doneActions.at(-1) || "";
|
|
636
580
|
const actionDecision = /(?:Code Task|Code) \(Round \d+, decision (II-[1-9]\d*)\)/.exec(latestAction)?.[1] || null;
|
|
637
581
|
const report = fs.readFileSync(artifactPath, "utf8");
|
|
@@ -659,10 +603,10 @@ function checkImplementationInput({ taskDir, artifactFile }) {
|
|
|
659
603
|
if (matches.length !== 1)
|
|
660
604
|
return failResult("implementation-input", `${actionDecision} is missing or duplicated in task table`);
|
|
661
605
|
const row = matches[0];
|
|
662
|
-
if (row.stage !== "code" || row.
|
|
606
|
+
if (row.stage !== "code" || !row.needsImplementation || row.status !== "consumed" || row.consumedBy !== artifactFile || !row.decisionEvidence) {
|
|
663
607
|
return failResult("implementation-input", `${actionDecision} is not a consumed input for ${artifactFile}`);
|
|
664
608
|
}
|
|
665
|
-
if (reportLedger !== row.ledgerId || reportEvidence !== row.
|
|
609
|
+
if (reportLedger !== row.ledgerId || reportEvidence !== row.decisionEvidence) {
|
|
666
610
|
return failResult("implementation-input", `${actionDecision} report identity does not match task table evidence`);
|
|
667
611
|
}
|
|
668
612
|
return passResult("implementation-input", `${actionDecision} matches Activity Log, report, and task table`);
|
|
@@ -672,26 +616,22 @@ function checkActivityLog({ taskDir, config }) {
|
|
|
672
616
|
if (!task.ok) {
|
|
673
617
|
return failResult("activity-log", task.message);
|
|
674
618
|
}
|
|
675
|
-
const
|
|
676
|
-
if (!
|
|
677
|
-
return failResult("activity-log", "Activity Log section not found");
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
.filter((line) => line.startsWith("- "));
|
|
683
|
-
if (entries.length === 0) {
|
|
619
|
+
const { section, invalidEntries } = inspectActivityLog(task.content);
|
|
620
|
+
if (!section)
|
|
621
|
+
return failResult("activity-log", "Activity Log section not found or ambiguous");
|
|
622
|
+
if (invalidEntries.length)
|
|
623
|
+
return failResult("activity-log", `Invalid Activity Log entry format: ${invalidEntries[0]}`);
|
|
624
|
+
const entries = section.entries;
|
|
625
|
+
if (entries.length === 0)
|
|
684
626
|
return failResult("activity-log", "Activity Log has no entries");
|
|
685
|
-
}
|
|
686
627
|
let previousTimestamp = "";
|
|
687
628
|
let latestAction = "";
|
|
688
629
|
let latestTimestamp = "";
|
|
630
|
+
const doneActions = [];
|
|
689
631
|
for (const entry of entries) {
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
}
|
|
694
|
-
const [, timestamp, action] = match;
|
|
632
|
+
if (!entry.note.trim())
|
|
633
|
+
return failResult("activity-log", "Activity Log entry note is required");
|
|
634
|
+
const { time: timestamp, step: action } = entry;
|
|
695
635
|
if (previousTimestamp && timestamp < previousTimestamp) {
|
|
696
636
|
return failResult("activity-log", "Activity Log timestamps are not in ascending order");
|
|
697
637
|
}
|
|
@@ -702,6 +642,16 @@ function checkActivityLog({ taskDir, config }) {
|
|
|
702
642
|
if (!ACTIVITY_LOG_STARTED_RE.test(action)) {
|
|
703
643
|
latestTimestamp = timestamp;
|
|
704
644
|
latestAction = action;
|
|
645
|
+
doneActions.push(action);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
if (config.expected_action_pattern && !new RegExp(config.expected_action_pattern).test(latestAction)) {
|
|
649
|
+
const expected = new RegExp(config.expected_action_pattern);
|
|
650
|
+
let index = doneActions.length - 1;
|
|
651
|
+
while (index >= 0 && doneActions[index] === 'Commit' && !expected.test(doneActions[index]))
|
|
652
|
+
index -= 1;
|
|
653
|
+
if (index >= 0 && expected.test(doneActions[index])) {
|
|
654
|
+
latestAction = doneActions[index];
|
|
705
655
|
}
|
|
706
656
|
}
|
|
707
657
|
if (config.expected_action_pattern && !new RegExp(config.expected_action_pattern).test(latestAction)) {
|
|
@@ -736,111 +686,7 @@ function checkCompletionChecklist({ taskDir, config }) {
|
|
|
736
686
|
}
|
|
737
687
|
return passResult("completion-checklist", `Completion Checklist valid (${items.length} items checked)`);
|
|
738
688
|
}
|
|
739
|
-
function
|
|
740
|
-
let value = String(line || "").trim();
|
|
741
|
-
if (!value.startsWith("|")) {
|
|
742
|
-
return [];
|
|
743
|
-
}
|
|
744
|
-
value = value.replace(/^\|/, "").replace(/\|$/, "");
|
|
745
|
-
const cells = [];
|
|
746
|
-
let cell = "";
|
|
747
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
748
|
-
const char = value[index];
|
|
749
|
-
if (char === "|" && !isEscapedAt(value, index)) {
|
|
750
|
-
cells.push(unescapeMarkdownTableCell(cell.trim()));
|
|
751
|
-
cell = "";
|
|
752
|
-
continue;
|
|
753
|
-
}
|
|
754
|
-
cell += char;
|
|
755
|
-
}
|
|
756
|
-
cells.push(unescapeMarkdownTableCell(cell.trim()));
|
|
757
|
-
return cells;
|
|
758
|
-
}
|
|
759
|
-
function unescapeMarkdownTableCell(value) {
|
|
760
|
-
let output = "";
|
|
761
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
762
|
-
const char = value[index];
|
|
763
|
-
const next = value[index + 1];
|
|
764
|
-
if (char === "\\" && (next === "\\" || next === "|")) {
|
|
765
|
-
output += next;
|
|
766
|
-
index += 1;
|
|
767
|
-
continue;
|
|
768
|
-
}
|
|
769
|
-
output += char;
|
|
770
|
-
}
|
|
771
|
-
return output;
|
|
772
|
-
}
|
|
773
|
-
function isEscapedAt(value, index) {
|
|
774
|
-
let backslashes = 0;
|
|
775
|
-
for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
|
|
776
|
-
backslashes += 1;
|
|
777
|
-
}
|
|
778
|
-
return backslashes % 2 === 1;
|
|
779
|
-
}
|
|
780
|
-
function parseWorkflowWarningRows(section) {
|
|
781
|
-
const rows = [];
|
|
782
|
-
for (const rawLine of String(section || "").split(/\r?\n/)) {
|
|
783
|
-
const cells = splitMarkdownTableRow(rawLine);
|
|
784
|
-
if (cells.length === 0) {
|
|
785
|
-
continue;
|
|
786
|
-
}
|
|
787
|
-
if ((cells[0] || "").toLowerCase() === "id") {
|
|
788
|
-
continue;
|
|
789
|
-
}
|
|
790
|
-
if (cells.every((cell) => /^:?-{3,}:?$/.test(cell))) {
|
|
791
|
-
continue;
|
|
792
|
-
}
|
|
793
|
-
rows.push(cells);
|
|
794
|
-
}
|
|
795
|
-
return rows;
|
|
796
|
-
}
|
|
797
|
-
function validateWorkflowWarnings(content) {
|
|
798
|
-
const section = getSectionContent(content, WORKFLOW_WARNING_SECTION_NAMES);
|
|
799
|
-
if (!section.trim()) {
|
|
800
|
-
return [];
|
|
801
|
-
}
|
|
802
|
-
const rows = parseWorkflowWarningRows(section);
|
|
803
|
-
const errors = [];
|
|
804
|
-
for (const cells of rows) {
|
|
805
|
-
if (cells.length < 11) {
|
|
806
|
-
errors.push(`malformed row (expected 11 columns): ${cells.join(" | ")}`);
|
|
807
|
-
continue;
|
|
808
|
-
}
|
|
809
|
-
const [id, time, step, severity, code, status, target, message, action, resolvedAt, resolution] = cells;
|
|
810
|
-
if (!WORKFLOW_WARNING_ID_PATTERN.test(id)) {
|
|
811
|
-
errors.push(`${id || "(empty id)"}: invalid id`);
|
|
812
|
-
}
|
|
813
|
-
if (!DATE_TIME_PATTERN.test(time)) {
|
|
814
|
-
errors.push(`${id}: invalid time '${time}'`);
|
|
815
|
-
}
|
|
816
|
-
if (isBlank(step)) {
|
|
817
|
-
errors.push(`${id}: step is required`);
|
|
818
|
-
}
|
|
819
|
-
if (!WORKFLOW_WARNING_SEVERITIES.has(severity)) {
|
|
820
|
-
errors.push(`${id}: illegal severity '${severity}'`);
|
|
821
|
-
}
|
|
822
|
-
if (isBlank(code)) {
|
|
823
|
-
errors.push(`${id}: code is required`);
|
|
824
|
-
}
|
|
825
|
-
if (!WORKFLOW_WARNING_STATUSES.has(status)) {
|
|
826
|
-
errors.push(`${id}: illegal status '${status}'`);
|
|
827
|
-
}
|
|
828
|
-
if (isBlank(target)) {
|
|
829
|
-
errors.push(`${id}: target is required`);
|
|
830
|
-
}
|
|
831
|
-
if (isBlank(message)) {
|
|
832
|
-
errors.push(`${id}: message is required`);
|
|
833
|
-
}
|
|
834
|
-
if (status === "open" && isBlank(action)) {
|
|
835
|
-
errors.push(`${id}: open warning requires action`);
|
|
836
|
-
}
|
|
837
|
-
if ((status === "resolved" || status === "ignored") && (isBlank(resolvedAt) || isBlank(resolution))) {
|
|
838
|
-
errors.push(`${id}: ${status} warning requires resolved_at and resolution`);
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
return errors;
|
|
842
|
-
}
|
|
843
|
-
function resolveReviewSetting(config, key, fallback) {
|
|
689
|
+
function resolveReviewSetting(config, key, fallback, repoRoot) {
|
|
844
690
|
if (config && config[key] !== undefined && config[key] !== null) {
|
|
845
691
|
return config[key];
|
|
846
692
|
}
|
|
@@ -850,7 +696,7 @@ function resolveReviewSetting(config, key, fallback) {
|
|
|
850
696
|
}
|
|
851
697
|
return fallback;
|
|
852
698
|
}
|
|
853
|
-
function checkReviewLedger({ taskDir, config }) {
|
|
699
|
+
function checkReviewLedger({ taskDir, config, repositoryRoot }) {
|
|
854
700
|
const task = loadTask(taskDir);
|
|
855
701
|
if (!task.ok) {
|
|
856
702
|
return failResult("review-ledger", task.message);
|
|
@@ -860,9 +706,7 @@ function checkReviewLedger({ taskDir, config }) {
|
|
|
860
706
|
const ledger = parseLedgerDocument(task.content);
|
|
861
707
|
if (!ledger.present)
|
|
862
708
|
return failResult("review-ledger", `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`);
|
|
863
|
-
rows = ledger.rows
|
|
864
|
-
row.id, row.stage, row.round, row.severity, row.status, row.evidence
|
|
865
|
-
]);
|
|
709
|
+
rows = ledger.rows;
|
|
866
710
|
}
|
|
867
711
|
catch (error) {
|
|
868
712
|
return failResult("review-ledger", `Invalid disagreement ledger: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -871,15 +715,11 @@ function checkReviewLedger({ taskDir, config }) {
|
|
|
871
715
|
return passResult("review-ledger", "Disagreement ledger has no entries");
|
|
872
716
|
}
|
|
873
717
|
const stageScope = Array.isArray(config.stage_scope) ? config.stage_scope : null;
|
|
874
|
-
const maxRounds = Number(resolveReviewSetting(config, "maxHandshakeRounds", DEFAULT_MAX_HANDSHAKE_ROUNDS));
|
|
718
|
+
const maxRounds = Number(resolveReviewSetting(config, "maxHandshakeRounds", DEFAULT_MAX_HANDSHAKE_ROUNDS, repositoryRoot));
|
|
875
719
|
const problems = [];
|
|
876
720
|
let inScopeCount = 0;
|
|
877
|
-
for (const
|
|
878
|
-
|
|
879
|
-
problems.push(`malformed row (expected 6 columns): ${cells.join(" | ")}`);
|
|
880
|
-
continue;
|
|
881
|
-
}
|
|
882
|
-
const [id, stage, roundRaw, , status, evidence] = cells;
|
|
721
|
+
for (const row of rows) {
|
|
722
|
+
const { id, stage, round: roundRaw, status, evidence } = row;
|
|
883
723
|
const stageScoped = stageScope ? stageScope.includes(stage) : true;
|
|
884
724
|
// post-review-commit exemption rows are consumed by the post-review-commit
|
|
885
725
|
// check, not enforced here.
|
|
@@ -890,8 +730,9 @@ function checkReviewLedger({ taskDir, config }) {
|
|
|
890
730
|
continue;
|
|
891
731
|
}
|
|
892
732
|
inScopeCount += 1;
|
|
893
|
-
|
|
894
|
-
|
|
733
|
+
const invalid = validateLedgerRows([row]);
|
|
734
|
+
if (invalid) {
|
|
735
|
+
problems.push(`${invalid.code}: ${invalid.message}`);
|
|
895
736
|
continue;
|
|
896
737
|
}
|
|
897
738
|
if (status !== "open" && evidence === "") {
|
|
@@ -900,11 +741,11 @@ function checkReviewLedger({ taskDir, config }) {
|
|
|
900
741
|
const round = Number.parseInt(roundRaw, 10);
|
|
901
742
|
if (Number.isFinite(round) &&
|
|
902
743
|
round >= maxRounds &&
|
|
903
|
-
!
|
|
744
|
+
!LEDGER_TERMINAL.has(status) &&
|
|
904
745
|
status !== "needs-human-decision") {
|
|
905
746
|
problems.push(`${id}: round ${round} reached limit ${maxRounds} without convergence; escalate to needs-human-decision`);
|
|
906
747
|
}
|
|
907
|
-
if (!
|
|
748
|
+
if (!LEDGER_TERMINAL.has(status)) {
|
|
908
749
|
problems.push(`${id}: unresolved (status '${status}')`);
|
|
909
750
|
}
|
|
910
751
|
}
|
|
@@ -914,7 +755,7 @@ function checkReviewLedger({ taskDir, config }) {
|
|
|
914
755
|
const scopeLabel = stageScope ? ` for stages [${stageScope.join(", ")}]` : "";
|
|
915
756
|
return passResult("review-ledger", `Disagreement ledger clean (${inScopeCount} in-scope entries terminal${scopeLabel})`);
|
|
916
757
|
}
|
|
917
|
-
function checkManualValidation({ taskDir }) {
|
|
758
|
+
async function checkManualValidation({ taskDir, repositoryRoot }) {
|
|
918
759
|
// 1. Latest review-code artifact; none -> pass (no review, check not applicable).
|
|
919
760
|
const review = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
920
761
|
if (!review.ok) {
|
|
@@ -945,10 +786,23 @@ function checkManualValidation({ taskDir }) {
|
|
|
945
786
|
const task = loadTask(taskDir);
|
|
946
787
|
if (!task.ok)
|
|
947
788
|
return failResult("manual-validation", task.message);
|
|
948
|
-
const
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
789
|
+
const completion = readManualValidationCompletion(taskDir, {
|
|
790
|
+
taskId: task.metadata.id,
|
|
791
|
+
artifact: artifactName
|
|
792
|
+
});
|
|
793
|
+
if (!completion.ok) {
|
|
794
|
+
const source = completion.error.code.startsWith('MANUAL_VALIDATION_RECEIPT_') ? 'receipt' : 'transaction';
|
|
795
|
+
return failResult("manual-validation", `Manual validation ${source} is unavailable: ${completion.error.message}`);
|
|
796
|
+
}
|
|
797
|
+
const { receipt, transaction } = completion.value;
|
|
798
|
+
if (transaction.phase !== "committed" || !transaction.eventAppended || !transaction.postWriteVerified) {
|
|
799
|
+
return failResult("manual-validation", "Manual validation transaction has not reached the committed post-write-verified state");
|
|
800
|
+
}
|
|
801
|
+
if (transaction.pendingSummaryDigest !== receipt.pendingSummaryDigest || transaction.finalSummaryDigest !== receipt.finalSummaryDigest) {
|
|
802
|
+
return failResult("manual-validation", "Manual validation summary digests do not match the committed receipt");
|
|
803
|
+
}
|
|
804
|
+
if (sha256File(resolved.path) !== receipt.artifactSha256) {
|
|
805
|
+
return failResult("manual-validation", `Manual validation artifact digest does not match the receipt for ${artifactName}`);
|
|
952
806
|
}
|
|
953
807
|
// 6. Timing correlation (PL-3 fix, PL-4 corrected): the completion entry must
|
|
954
808
|
// sit AFTER the latest review-code round's completion entry in the
|
|
@@ -957,21 +811,39 @@ function checkManualValidation({ taskDir }) {
|
|
|
957
811
|
// which indexOf never matches). Not reusing completed.exec().index: exec
|
|
958
812
|
// anchors to the first '**Complete Manual Validation**' heading, which can
|
|
959
813
|
// belong to an earlier round's entry and misorder the standard path.
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
if (
|
|
970
|
-
return failResult("manual-validation", `Latest review-code (round ${review.round})
|
|
971
|
-
|
|
972
|
-
|
|
814
|
+
const inspectedLog = inspectActivityLog(task.content);
|
|
815
|
+
if (!inspectedLog.section)
|
|
816
|
+
return failResult("manual-validation", "Activity Log is missing or invalid");
|
|
817
|
+
const reviewDoneIndex = inspectedLog.section.entries.findIndex((entry) => entry.step === `Review Code (Round ${review.round})`);
|
|
818
|
+
const completedIndex = inspectedLog.section.entries.findIndex((entry) => entry.step === "Complete Manual Validation"
|
|
819
|
+
&& entry.note.includes(`Manual validation passed → ${artifactName};`)
|
|
820
|
+
&& entry.note.includes(`transaction=${receipt.transactionId};`)
|
|
821
|
+
&& entry.note.includes(`receipt=${receipt.receiptDigest};`)
|
|
822
|
+
&& entry.note.includes(`head=${receipt.prHeadSha}`));
|
|
823
|
+
if (reviewDoneIndex === -1)
|
|
824
|
+
return failResult("manual-validation", `Latest review-code (round ${review.round}) completion entry is missing from the Activity Log`);
|
|
825
|
+
if (completedIndex === -1)
|
|
826
|
+
return failResult("manual-validation", `Committed manual validation completion is not recorded for ${artifactName}`);
|
|
827
|
+
if (completedIndex < reviewDoneIndex)
|
|
828
|
+
return failResult("manual-validation", `Latest review-code (round ${review.round}) came after the manual validation completion recorded for ${artifactName}`);
|
|
829
|
+
const fact = readPrDeliveryFact(task.metadata);
|
|
830
|
+
if (fact.status === "invalid")
|
|
831
|
+
return failResult("manual-validation", fact.error.message);
|
|
832
|
+
if (fact.status === "valid" && fact.fact.state === "bound") {
|
|
833
|
+
const inspected = await inspectPlatformPullRequest(task.metadata.id, { cwd: repositoryRoot });
|
|
834
|
+
if (!inspected.pullRequest)
|
|
835
|
+
return failResult("manual-validation", inspected.error?.message ?? "canonical pull-request head is unavailable");
|
|
836
|
+
if (inspected.pullRequest.head.sha !== receipt.prHeadSha)
|
|
837
|
+
return failResult("manual-validation", "manual validation receipt is stale for the current pull-request head");
|
|
838
|
+
const summary = await summaryCommentState(task.metadata.id, { cwd: repositoryRoot });
|
|
839
|
+
if (!summary.comment)
|
|
840
|
+
return failResult("manual-validation", "canonical pull-request summary comment is unavailable");
|
|
841
|
+
if (!manualValidationFinalSummaryProjectionMatches(summary.comment.body, receipt))
|
|
842
|
+
return failResult("manual-validation", "canonical pull-request summary does not match the committed manual validation projection");
|
|
843
|
+
}
|
|
844
|
+
return passResult("manual-validation", `Manual validation completed → ${artifactName} (committed receipt and post-write verification)`);
|
|
973
845
|
}
|
|
974
|
-
async function checkPostReviewCommit({ taskDir, config }) {
|
|
846
|
+
async function checkPostReviewCommit({ taskDir, config, repositoryRoot }) {
|
|
975
847
|
const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
976
848
|
if (!reviewArtifact.ok) {
|
|
977
849
|
if (reviewArtifact.error)
|
|
@@ -993,7 +865,7 @@ async function checkPostReviewCommit({ taskDir, config }) {
|
|
|
993
865
|
return failResult("post-review-commit", factRead.error.message);
|
|
994
866
|
const fact = factRead.status === 'valid' ? factRead.fact : null;
|
|
995
867
|
const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
|
|
996
|
-
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(
|
|
868
|
+
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repositoryRoot));
|
|
997
869
|
const hasPullRequest = fact?.state === 'bound';
|
|
998
870
|
let inspected = null;
|
|
999
871
|
if (hasPullRequest) {
|
|
@@ -1139,7 +1011,7 @@ function resolvePostReviewExemption(content) {
|
|
|
1139
1011
|
};
|
|
1140
1012
|
}
|
|
1141
1013
|
}
|
|
1142
|
-
function checkReviewFact({ taskDir, artifactFile }) {
|
|
1014
|
+
function checkReviewFact({ taskDir, artifactFile, repositoryRoot }) {
|
|
1143
1015
|
const resolvedArtifact = resolveArtifactPath(taskDir, "review-code.md|review-code-r{N}.md", artifactFile);
|
|
1144
1016
|
if (!resolvedArtifact.ok) {
|
|
1145
1017
|
return failResult("review-fact", resolvedArtifact.message);
|
|
@@ -1205,7 +1077,7 @@ function checkReviewFact({ taskDir, artifactFile }) {
|
|
|
1205
1077
|
mode: "worktree",
|
|
1206
1078
|
baseline,
|
|
1207
1079
|
diffBase,
|
|
1208
|
-
globs: resolvePostReviewGlobs({}, loadPostReviewConfig(
|
|
1080
|
+
globs: resolvePostReviewGlobs({}, loadPostReviewConfig(repositoryRoot))
|
|
1209
1081
|
});
|
|
1210
1082
|
}
|
|
1211
1083
|
catch {
|
|
@@ -1292,40 +1164,12 @@ function resolveArtifactPath(taskDir, filePattern, artifactFile) {
|
|
|
1292
1164
|
return { ok: true, path: path.join(taskDir, matches[0].fileName) };
|
|
1293
1165
|
}
|
|
1294
1166
|
function getSectionContent(content, names) {
|
|
1295
|
-
const
|
|
1296
|
-
function visibleHeadings() {
|
|
1297
|
-
const headings = [];
|
|
1298
|
-
let fence = null;
|
|
1299
|
-
for (let index = 0; index < lines.length; index += 1) {
|
|
1300
|
-
const line = lines[index];
|
|
1301
|
-
if (fence) {
|
|
1302
|
-
const closer = line.match(/^ {0,3}(`+|~+)\s*$/);
|
|
1303
|
-
if (closer && closer[1][0] === fence.character && closer[1].length >= fence.length) {
|
|
1304
|
-
fence = null;
|
|
1305
|
-
}
|
|
1306
|
-
continue;
|
|
1307
|
-
}
|
|
1308
|
-
const opener = line.match(/^ {0,3}(`{3,}|~{3,})(?:[^`~].*)?$/);
|
|
1309
|
-
if (opener) {
|
|
1310
|
-
fence = { character: opener[1][0], length: opener[1].length };
|
|
1311
|
-
continue;
|
|
1312
|
-
}
|
|
1313
|
-
if (line.startsWith("## ")) {
|
|
1314
|
-
headings.push({ index, text: line.trim() });
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
return headings;
|
|
1318
|
-
}
|
|
1319
|
-
const headings = visibleHeadings();
|
|
1167
|
+
const headings = scanVisibleMarkdown(content).headings.filter((heading) => heading.level === 2);
|
|
1320
1168
|
for (const name of names) {
|
|
1321
|
-
const
|
|
1322
|
-
|
|
1323
|
-
if (position === -1) {
|
|
1169
|
+
const position = headings.findIndex((heading) => heading.text === name);
|
|
1170
|
+
if (position === -1)
|
|
1324
1171
|
continue;
|
|
1325
|
-
|
|
1326
|
-
const startIndex = headings[position].index;
|
|
1327
|
-
const endIndex = headings[position + 1]?.index ?? lines.length;
|
|
1328
|
-
return lines.slice(startIndex + 1, endIndex).join("\n").trim();
|
|
1172
|
+
return content.slice(headings[position].end + 1, headings[position + 1]?.start ?? content.length).replace(/\r\n/g, "\n").trim();
|
|
1329
1173
|
}
|
|
1330
1174
|
return "";
|
|
1331
1175
|
}
|
|
@@ -1429,9 +1273,8 @@ function isBlank(value) {
|
|
|
1429
1273
|
return value === undefined || value === null || String(value).trim() === "";
|
|
1430
1274
|
}
|
|
1431
1275
|
async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }) {
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
else {
|
|
1276
|
+
let repoRoot = repositoryRoot ? path.resolve(repositoryRoot) : defaultRepoRoot;
|
|
1277
|
+
if (!repositoryRoot) {
|
|
1435
1278
|
let cursor = path.resolve(taskDir);
|
|
1436
1279
|
while (path.dirname(cursor) !== cursor && !fs.existsSync(path.join(cursor, ".agents")))
|
|
1437
1280
|
cursor = path.dirname(cursor);
|