@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
|
@@ -24,17 +24,30 @@ import { resolveMaterializedReviewedHeadRelation } from "../platform/change-requ
|
|
|
24
24
|
import { resolveReviewedHeadRelation } from "../platform/merged-pr-equivalence.ts";
|
|
25
25
|
import { resolveLocalReviewedCommitRelation } from "../git/reviewed-commit-equivalence.ts";
|
|
26
26
|
import { parseTypedTaskFrontmatter } from "./frontmatter.ts";
|
|
27
|
-
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from "./ledger.ts";
|
|
27
|
+
import { LEDGER_TERMINAL, LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from "./ledger.ts";
|
|
28
28
|
import type { LedgerRow } from "./ledger.ts";
|
|
29
29
|
import { isValidAgentInfraVersion } from "../version.ts";
|
|
30
30
|
import { equalCounts, parseReviewSummary } from "./review-artifacts.ts";
|
|
31
31
|
import { inspectDecisionDetailDuplicates } from "./decision-details.ts";
|
|
32
|
+
import { parseImplementationInputs, type ImplementationInput } from "./implementation-inputs.ts";
|
|
33
|
+
import { scanVisibleMarkdown } from "./markdown.ts";
|
|
32
34
|
import { loadVerificationConfig } from "./verification-config.ts";
|
|
33
35
|
import { snapshotReview } from "../git/review-snapshot.ts";
|
|
36
|
+
import { inspectActivityLog } from "./activity-log.ts";
|
|
37
|
+
import { parseWorkflowWarnings } from "./workflow-warnings.ts";
|
|
34
38
|
import { OrchestrationStateError, readRun } from "./orchestration.ts";
|
|
39
|
+
import type { OrchestrationRun } from "./orchestration.ts";
|
|
35
40
|
import { resolveDeliveryTarget } from "./delivery-target.ts";
|
|
36
41
|
import { readPrDeliveryFact } from "./pr-delivery-fact.ts";
|
|
37
42
|
import { validateLocalArtifact } from "./local-artifact-finalization.ts";
|
|
43
|
+
import { validateQualificationAudit } from "./qualification-audit.ts";
|
|
44
|
+
import { getArtifactSchema } from "./artifact-schema.ts";
|
|
45
|
+
import { inspectArtifactContract } from "./artifact-operations.ts";
|
|
46
|
+
import type { VerificationShared } from "./verification-types.ts";
|
|
47
|
+
import { manualValidationFinalSummaryProjectionMatches } from "./manual-validation-receipt.ts";
|
|
48
|
+
import { readManualValidationCompletion } from "./manual-validation-completion.ts";
|
|
49
|
+
import { sha256File } from "./artifact-receipts.ts";
|
|
50
|
+
import { summaryCommentState } from "../platform/pr-summary.ts";
|
|
38
51
|
|
|
39
52
|
const TASK_ENUMS = {
|
|
40
53
|
type: ["feature", "bugfix", "refactor", "docs", "chore"],
|
|
@@ -55,7 +68,6 @@ const DEFAULT_REQUIRED_FIELDS = [
|
|
|
55
68
|
];
|
|
56
69
|
|
|
57
70
|
const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
|
|
58
|
-
const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
|
|
59
71
|
// Start markers (action suffixed with ` [started]`) are excluded from the
|
|
60
72
|
// "latest action" / freshness computation so a step's in-flight marker never
|
|
61
73
|
// satisfies a skill's expected_action_pattern; the matching done entry does.
|
|
@@ -64,28 +76,12 @@ const BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
|
64
76
|
|
|
65
77
|
// Review disagreement ledger (see .agents/rules/review-handshake.md).
|
|
66
78
|
const LEDGER_SECTION_NAMES = ["审查分歧账本", "Review Disagreement Ledger"];
|
|
67
|
-
const LEDGER_STATUSES = new Set([
|
|
68
|
-
"open",
|
|
69
|
-
"accepted",
|
|
70
|
-
"adjusted",
|
|
71
|
-
"refuted",
|
|
72
|
-
"cannot-judge",
|
|
73
|
-
"confirmed",
|
|
74
|
-
"needs-human-decision",
|
|
75
|
-
"closed",
|
|
76
|
-
"human-decided"
|
|
77
|
-
]);
|
|
78
|
-
const LEDGER_TERMINAL_OK = new Set(["confirmed", "closed", "human-decided"]);
|
|
79
79
|
const DEFAULT_MAX_HANDSHAKE_ROUNDS = 3;
|
|
80
80
|
const POST_REVIEW_COMMIT_STAGE = "post-review-commit";
|
|
81
81
|
const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
|
|
82
|
-
const WORKFLOW_WARNING_SECTION_NAMES = ["工作流告警", "Workflow Warnings"];
|
|
83
|
-
const WORKFLOW_WARNING_STATUSES = new Set(["open", "resolved", "ignored"]);
|
|
84
|
-
const WORKFLOW_WARNING_SEVERITIES = new Set(["IMPORTANT", "ACTION_REQUIRED"]);
|
|
85
|
-
const WORKFLOW_WARNING_ID_PATTERN = /^WW-\d+$/;
|
|
86
82
|
|
|
87
83
|
const scriptPath = fileURLToPath(import.meta.url);
|
|
88
|
-
|
|
84
|
+
const defaultRepoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
|
|
89
85
|
|
|
90
86
|
const PLATFORM_ADAPTERS: Record<string, (context: any, shared: any) => any> = {
|
|
91
87
|
"platform-sync": checkPlatformSync,
|
|
@@ -157,7 +153,7 @@ function checkOrchestrationState({ taskDir }: any): any {
|
|
|
157
153
|
const file = path.join(taskDir, 'orchestration.json');
|
|
158
154
|
const stat = safeStat(file);
|
|
159
155
|
if (!stat?.isFile()) return failResult('orchestration-state', 'orchestration.json is missing');
|
|
160
|
-
let run:
|
|
156
|
+
let run: OrchestrationRun | null;
|
|
161
157
|
try {
|
|
162
158
|
run = readRun(taskDir);
|
|
163
159
|
} catch (error) {
|
|
@@ -189,18 +185,16 @@ function exactText(value: unknown): value is string {
|
|
|
189
185
|
return typeof value === 'string' && value.length > 0 && value.trim() === value;
|
|
190
186
|
}
|
|
191
187
|
|
|
192
|
-
function validateCleanCompletionEvidence(run:
|
|
188
|
+
function validateCleanCompletionEvidence(run: OrchestrationRun): string | null {
|
|
193
189
|
const evidence = run.completionEvidence;
|
|
194
190
|
const shaPattern = /^[0-9a-f]{40}$/i;
|
|
195
191
|
if (
|
|
196
|
-
evidence
|
|
197
|
-
|| !exactText(evidence.observedAt)
|
|
192
|
+
!evidence
|
|
198
193
|
|| Number.isNaN(Date.parse(evidence.observedAt))
|
|
199
194
|
|| !shaPattern.test(evidence.head)
|
|
200
195
|
|| !shaPattern.test(evidence.headTree)
|
|
201
196
|
|| !shaPattern.test(evidence.worktreeTree)
|
|
202
197
|
|| !shaPattern.test(evidence.lastReviewedCommit)
|
|
203
|
-
|| !(evidence.prNumber === null || (Number.isInteger(evidence.prNumber) && evidence.prNumber > 0))
|
|
204
198
|
|| !(evidence.prHead === null || shaPattern.test(evidence.prHead))
|
|
205
199
|
) {
|
|
206
200
|
return 'Clean completion evidence has an invalid structure';
|
|
@@ -217,8 +211,7 @@ function validateCleanCompletionEvidence(run: any): string | null {
|
|
|
217
211
|
|| run.pendingDelegation !== null
|
|
218
212
|
|| run.commitAuthorization?.issuedAt !== null
|
|
219
213
|
|| run.commitAuthorization?.consumedAt !== null
|
|
220
|
-
||
|
|
221
|
-
|| run.receipts.some((receipt: any) => receipt.stage === 'commit')
|
|
214
|
+
|| run.receipts.some((receipt) => receipt.stage === 'commit')
|
|
222
215
|
) {
|
|
223
216
|
return 'Clean completion evidence conflicts with commit delegation state';
|
|
224
217
|
}
|
|
@@ -229,54 +222,16 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
229
222
|
const file = path.join(taskDir, 'orchestration.json');
|
|
230
223
|
const stat = safeStat(file);
|
|
231
224
|
if (!stat?.isFile()) return failResult('orchestration-evidence', 'orchestration.json is missing');
|
|
232
|
-
let run:
|
|
225
|
+
let run: OrchestrationRun | null;
|
|
233
226
|
try {
|
|
234
227
|
run = readRun(taskDir);
|
|
235
228
|
} catch (error) {
|
|
236
229
|
const message = error instanceof OrchestrationStateError ? error.message : String(error);
|
|
237
230
|
return failResult('orchestration-evidence', `Invalid orchestration.json: ${message}`);
|
|
238
231
|
}
|
|
232
|
+
if (!run) return failResult('orchestration-evidence', 'orchestration.json is missing');
|
|
233
|
+
// readRun validates the persisted schema, receipt identities and client provenance.
|
|
239
234
|
const policy = run.modelPolicy;
|
|
240
|
-
if (
|
|
241
|
-
!policy
|
|
242
|
-
|| !exactText(policy.executor?.model)
|
|
243
|
-
|| !exactText(policy.executor?.reasoningEffort)
|
|
244
|
-
|| !exactText(policy.reviewer?.model)
|
|
245
|
-
|| !exactText(policy.reviewer?.reasoningEffort)
|
|
246
|
-
) {
|
|
247
|
-
return failResult('orchestration-evidence', 'Run model policy requires exact executor and reviewer model and effort');
|
|
248
|
-
}
|
|
249
|
-
if (
|
|
250
|
-
!run.modelPolicySource
|
|
251
|
-
|| !['explicit', 'project-config'].includes(run.modelPolicySource.kind)
|
|
252
|
-
|| !exactText(run.modelPolicySource.client)
|
|
253
|
-
|| !exactText(run.modelPolicySource.resolvedAt)
|
|
254
|
-
|| !Array.isArray(run.recoveryHistory)
|
|
255
|
-
) {
|
|
256
|
-
return failResult('orchestration-evidence', 'Run model policy source or recovery history is invalid');
|
|
257
|
-
}
|
|
258
|
-
for (const recovery of run.recoveryHistory) {
|
|
259
|
-
const guards = recovery.guards;
|
|
260
|
-
const validClaudeCodeRecovery = recovery.code === 'CLIENT_CAPABILITY_ENABLED'
|
|
261
|
-
&& recovery.previousStatus === 'paused'
|
|
262
|
-
&& recovery.previousPause?.code === 'ORCHESTRATION_CLIENT_UNSUPPORTED'
|
|
263
|
-
&& recovery.client === 'claude-code'
|
|
264
|
-
&& recovery.resultingStatus === 'running'
|
|
265
|
-
&& exactText(recovery.recoveredAt)
|
|
266
|
-
&& guards?.stepCount === 0
|
|
267
|
-
&& guards?.nextStage === null
|
|
268
|
-
&& guards?.baselineEmpty === true
|
|
269
|
-
&& guards?.receiptCount === 0
|
|
270
|
-
&& guards?.pendingDelegation === false
|
|
271
|
-
&& guards?.commitAuthorizationUnused === true
|
|
272
|
-
&& guards?.completionEvidenceAbsent === true;
|
|
273
|
-
if (!validClaudeCodeRecovery) {
|
|
274
|
-
return failResult('orchestration-evidence', 'Run recovery history contains invalid provenance');
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
if (!Array.isArray(run.receipts)) {
|
|
278
|
-
return failResult('orchestration-evidence', 'Run receipts must be an array');
|
|
279
|
-
}
|
|
280
235
|
if (run.completionEvidence != null) {
|
|
281
236
|
const evidenceError = validateCleanCompletionEvidence(run);
|
|
282
237
|
if (evidenceError) return failResult('orchestration-evidence', evidenceError);
|
|
@@ -306,10 +261,6 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
306
261
|
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has no host-observed actual reasoning effort`);
|
|
307
262
|
}
|
|
308
263
|
}
|
|
309
|
-
// parentId/childId 校验对所有 client 保持统一(不新增分支);spawnMode 检查按 client 判断
|
|
310
|
-
if (!exactText(receipt.parentId) || !exactText(receipt.childId) || receipt.parentId === receipt.childId) {
|
|
311
|
-
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid delegation identity`);
|
|
312
|
-
}
|
|
313
264
|
if (!isClaudeCode && receipt.spawnMode !== 'fresh') {
|
|
314
265
|
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid fresh delegation identity`);
|
|
315
266
|
}
|
|
@@ -335,50 +286,9 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
335
286
|
) {
|
|
336
287
|
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has an unrelated reasoning-effort fallback reason`);
|
|
337
288
|
}
|
|
338
|
-
if (receipt.client === 'codex') {
|
|
339
|
-
const activatedCodex = ['activated', 'stage-completed', 'sealed', 'consumed'].includes(receipt.status);
|
|
340
|
-
const host = receipt.hostEvidence;
|
|
341
|
-
const provenance = receipt.lifecycleProvenance;
|
|
342
|
-
if (
|
|
343
|
-
!provenance
|
|
344
|
-
|| (activatedCodex && (
|
|
345
|
-
host?.kind !== 'codex-lifecycle-v2'
|
|
346
|
-
|| host.protocolVersion !== provenance.protocolVersion
|
|
347
|
-
|| host.hookDefinitionHash !== provenance.hookDefinitionHash
|
|
348
|
-
|| host.hookSource !== provenance.hookSource
|
|
349
|
-
|| host.hookSourcePathDigest !== provenance.hookSourcePathDigest
|
|
350
|
-
|| host.hookSourceHash !== provenance.hookSourceHash
|
|
351
|
-
|| host.capabilitySessionId !== provenance.capabilitySessionId
|
|
352
|
-
|| receipt.parentId !== provenance.capabilitySessionId
|
|
353
|
-
|| host.capabilityTurnId !== provenance.capabilityTurnId
|
|
354
|
-
|| host.controllerInstanceDigest !== provenance.controllerInstanceDigest
|
|
355
|
-
|| host.controlGeneration !== provenance.controlGeneration
|
|
356
|
-
|| host.spawnToolUseId === provenance.capabilityToolUseId
|
|
357
|
-
|| !exactText(host.spawnToolUseId)
|
|
358
|
-
|| !Number.isFinite(Date.parse(host.spawnObservedAt ?? ''))
|
|
359
|
-
|| !Number.isFinite(Date.parse(receipt.spawnDispatchedAt ?? ''))
|
|
360
|
-
|| !Number.isFinite(Date.parse(receipt.activationDeadlineAt ?? ''))
|
|
361
|
-
|| Date.parse(host.spawnObservedAt ?? '') < Date.parse(receipt.spawnDispatchedAt ?? '')
|
|
362
|
-
|| Date.parse(host.spawnObservedAt ?? '') > Date.parse(receipt.activationDeadlineAt ?? '')
|
|
363
|
-
|| !exactText(host.hookDefinitionHash)
|
|
364
|
-
|| !Number.isSafeInteger(host.startRevision)
|
|
365
|
-
|| host.startRevision < 1
|
|
366
|
-
))
|
|
367
|
-
) {
|
|
368
|
-
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid Codex start evidence`);
|
|
369
|
-
}
|
|
370
|
-
if (['sealed', 'consumed'].includes(receipt.status) && (
|
|
371
|
-
!Number.isSafeInteger(host.stopRevision)
|
|
372
|
-
|| host.stopRevision <= host.startRevision
|
|
373
|
-
|| host.consumer !== receipt.id
|
|
374
|
-
|| !exactText(host.consumedAt)
|
|
375
|
-
)) {
|
|
376
|
-
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid Codex consumed stop evidence`);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
289
|
}
|
|
380
290
|
}
|
|
381
|
-
if (run.receipts.some((receipt
|
|
291
|
+
if (run.receipts.some((receipt) => receipt.status !== 'consumed')) {
|
|
382
292
|
return failResult('orchestration-evidence', 'Historical receipts must be consumed');
|
|
383
293
|
}
|
|
384
294
|
return passResult('orchestration-evidence', 'Persisted orchestration model and delegation evidence is internally consistent');
|
|
@@ -386,7 +296,7 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
386
296
|
|
|
387
297
|
// === Check Functions ===
|
|
388
298
|
|
|
389
|
-
function checkTaskMeta({ taskDir, config }: any): any {
|
|
299
|
+
function checkTaskMeta({ taskDir, config, repositoryRoot }: any): any {
|
|
390
300
|
const task = loadTask(taskDir);
|
|
391
301
|
if (!task.ok) {
|
|
392
302
|
return failResult("task-meta", task.message);
|
|
@@ -424,14 +334,15 @@ function checkTaskMeta({ taskDir, config }: any): any {
|
|
|
424
334
|
}
|
|
425
335
|
}
|
|
426
336
|
|
|
427
|
-
const branchValidationError = validateTaskBranch(metadata);
|
|
337
|
+
const branchValidationError = validateTaskBranch(metadata, repositoryRoot);
|
|
428
338
|
if (branchValidationError) {
|
|
429
339
|
return failResult("task-meta", branchValidationError);
|
|
430
340
|
}
|
|
431
341
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
342
|
+
try {
|
|
343
|
+
parseWorkflowWarnings(task.content);
|
|
344
|
+
} catch (error) {
|
|
345
|
+
return failResult("task-meta", `Invalid Workflow Warnings: ${error instanceof Error ? error.message : String(error)}`);
|
|
435
346
|
}
|
|
436
347
|
|
|
437
348
|
const expectedStep = config.expected_step;
|
|
@@ -549,12 +460,12 @@ async function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }: any):
|
|
|
549
460
|
return passResult('required-pr-delivery', `Pull request delivery policy satisfied (${status})`);
|
|
550
461
|
}
|
|
551
462
|
|
|
552
|
-
function validateTaskBranch(metadata: any): any {
|
|
463
|
+
function validateTaskBranch(metadata: any, repoRoot: string): any {
|
|
553
464
|
if (isBlank(metadata.branch)) {
|
|
554
465
|
return null;
|
|
555
466
|
}
|
|
556
467
|
|
|
557
|
-
const projectName = loadProjectName();
|
|
468
|
+
const projectName = loadProjectName(repoRoot);
|
|
558
469
|
const expectedPrefix = projectName ? `${projectName}-${metadata.type}-` : "";
|
|
559
470
|
|
|
560
471
|
if (expectedPrefix && !String(metadata.branch).startsWith(expectedPrefix)) {
|
|
@@ -569,7 +480,7 @@ function validateTaskBranch(metadata: any): any {
|
|
|
569
480
|
return null;
|
|
570
481
|
}
|
|
571
482
|
|
|
572
|
-
function loadProjectName(): any {
|
|
483
|
+
function loadProjectName(repoRoot: string): any {
|
|
573
484
|
const configPath = path.join(repoRoot, ".agents", ".airc.json");
|
|
574
485
|
if (!fs.existsSync(configPath)) {
|
|
575
486
|
return "";
|
|
@@ -600,15 +511,45 @@ function checkArtifact({ taskDir, config, artifactFile, skillName }: any): any {
|
|
|
600
511
|
}
|
|
601
512
|
|
|
602
513
|
const content = fs.readFileSync(artifactPath, "utf8");
|
|
603
|
-
|
|
514
|
+
let taskContent = "";
|
|
515
|
+
const taskPath = path.join(taskDir, "task.md");
|
|
516
|
+
if (fs.existsSync(taskPath)) {
|
|
517
|
+
try {
|
|
518
|
+
taskContent = fs.readFileSync(taskPath, "utf8");
|
|
519
|
+
} catch (error) {
|
|
520
|
+
return failResult("artifact", `Cannot read task qualification contract: ${error instanceof Error ? error.message : String(error)}`);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (taskContent && /^review-(?:analysis|plan|code)$/.test(skillName)) {
|
|
524
|
+
const qualification = validateQualificationAudit(taskContent, content, { artifact: path.basename(artifactPath) });
|
|
525
|
+
if (!qualification.ok) return failResult("artifact", `${path.basename(artifactPath)} has qualification audit errors: ${qualification.code}: ${qualification.message}`);
|
|
526
|
+
}
|
|
527
|
+
const schemaFamily = skillName === "analyze-task"
|
|
528
|
+
? "analysis"
|
|
529
|
+
: skillName === "review-analysis"
|
|
530
|
+
? "review-analysis"
|
|
531
|
+
: skillName === "plan-task"
|
|
532
|
+
? "plan"
|
|
533
|
+
: skillName === "review-plan"
|
|
534
|
+
? "review-plan"
|
|
535
|
+
: skillName === "code-task"
|
|
536
|
+
? "code"
|
|
537
|
+
: skillName === "review-code" ? "review-code" : null;
|
|
538
|
+
const schema = schemaFamily ? getArtifactSchema(schemaFamily) : null;
|
|
604
539
|
const localFamily = skillName === "analyze-task"
|
|
605
540
|
? "analysis"
|
|
606
541
|
: skillName === "plan-task" ? "plan" : skillName === "code-task" ? "code" : null;
|
|
542
|
+
if (schema) {
|
|
543
|
+
const structure = inspectArtifactContract(content, schema);
|
|
544
|
+
if (!structure.ok && !localFamily) {
|
|
545
|
+
return failResult("artifact", `${path.basename(artifactPath)} has shared structural errors: ${structure.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')}`);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
607
548
|
if (localFamily) {
|
|
608
549
|
const local = validateLocalArtifact(content, {
|
|
609
550
|
family: localFamily,
|
|
610
|
-
|
|
611
|
-
|
|
551
|
+
...(taskContent ? { taskContent } : {}),
|
|
552
|
+
artifact: path.basename(artifactPath)
|
|
612
553
|
});
|
|
613
554
|
if (!local.ok) {
|
|
614
555
|
return failResult(
|
|
@@ -618,9 +559,16 @@ function checkArtifact({ taskDir, config, artifactFile, skillName }: any): any {
|
|
|
618
559
|
}
|
|
619
560
|
return passResult(
|
|
620
561
|
"artifact",
|
|
621
|
-
`${path.basename(artifactPath)} passed (${
|
|
562
|
+
`${path.basename(artifactPath)} passed (${schema?.sections.length ?? 0} sections)`
|
|
622
563
|
);
|
|
623
564
|
}
|
|
565
|
+
if (schema) {
|
|
566
|
+
return passResult(
|
|
567
|
+
"artifact",
|
|
568
|
+
`${path.basename(artifactPath)} passed (${schema.sections.length} sections)`
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
const requiredSections = config.required_sections || [];
|
|
624
572
|
const missingSections = requiredSections.filter(
|
|
625
573
|
(section: any) => !new RegExp(`^##\\s+${escapeRegExp(section)}\\s*$`, "m").test(content)
|
|
626
574
|
);
|
|
@@ -703,31 +651,17 @@ function checkImplementationInput({ taskDir, artifactFile }: any): any {
|
|
|
703
651
|
const artifactPath = path.join(taskDir, artifactFile);
|
|
704
652
|
if (!safeStat(artifactPath)?.isFile()) return failResult("implementation-input", `Artifact not found: ${artifactFile}`);
|
|
705
653
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
const expected = ["id", "ledger_id", "decision_evidence", "stage", "needs_implementation", "decided_at", "status", "consumed_by"];
|
|
712
|
-
if (table.length < 2 || JSON.stringify(cells(table[0])) !== JSON.stringify(expected)) {
|
|
713
|
-
return failResult("implementation-input", "Implementation Inputs table schema is invalid");
|
|
714
|
-
}
|
|
715
|
-
const seen = new Set();
|
|
716
|
-
for (const line of table.slice(2)) {
|
|
717
|
-
const row = cells(line);
|
|
718
|
-
if (row.length !== 8 || !/^II-[1-9]\d*$/.test(row[0]) || seen.has(row[0])) {
|
|
719
|
-
return failResult("implementation-input", "Implementation Inputs table contains an invalid or duplicate id");
|
|
720
|
-
}
|
|
721
|
-
seen.add(row[0]);
|
|
722
|
-
rows.push({ id: row[0], ledgerId: row[1], evidence: row[2], stage: row[3], needs: row[4], status: row[6], consumedBy: row[7] });
|
|
723
|
-
}
|
|
654
|
+
let rows: ImplementationInput[];
|
|
655
|
+
try {
|
|
656
|
+
rows = parseImplementationInputs(task.content).rows;
|
|
657
|
+
} catch (error) {
|
|
658
|
+
return failResult("implementation-input", `Invalid Implementation Inputs: ${error instanceof Error ? error.message : String(error)}`);
|
|
724
659
|
}
|
|
725
660
|
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
});
|
|
661
|
+
const doneActions = (inspectActivityLog(task.content).section?.entries ?? [])
|
|
662
|
+
.filter((entry) => !ACTIVITY_LOG_STARTED_RE.test(entry.step))
|
|
663
|
+
.map((entry) => entry.step)
|
|
664
|
+
.filter((step) => /^(?:Code Task|Code) \(Round \d+/.test(step));
|
|
731
665
|
const latestAction = doneActions.at(-1) || "";
|
|
732
666
|
const actionDecision = /(?:Code Task|Code) \(Round \d+, decision (II-[1-9]\d*)\)/.exec(latestAction)?.[1] || null;
|
|
733
667
|
const report = fs.readFileSync(artifactPath, "utf8");
|
|
@@ -754,10 +688,10 @@ function checkImplementationInput({ taskDir, artifactFile }: any): any {
|
|
|
754
688
|
const matches = rows.filter((row) => row.id === actionDecision);
|
|
755
689
|
if (matches.length !== 1) return failResult("implementation-input", `${actionDecision} is missing or duplicated in task table`);
|
|
756
690
|
const row = matches[0]!;
|
|
757
|
-
if (row.stage !== "code" || row.
|
|
691
|
+
if (row.stage !== "code" || !row.needsImplementation || row.status !== "consumed" || row.consumedBy !== artifactFile || !row.decisionEvidence) {
|
|
758
692
|
return failResult("implementation-input", `${actionDecision} is not a consumed input for ${artifactFile}`);
|
|
759
693
|
}
|
|
760
|
-
if (reportLedger !== row.ledgerId || reportEvidence !== row.
|
|
694
|
+
if (reportLedger !== row.ledgerId || reportEvidence !== row.decisionEvidence) {
|
|
761
695
|
return failResult("implementation-input", `${actionDecision} report identity does not match task table evidence`);
|
|
762
696
|
}
|
|
763
697
|
return passResult("implementation-input", `${actionDecision} matches Activity Log, report, and task table`);
|
|
@@ -769,31 +703,20 @@ function checkActivityLog({ taskDir, config }: any): any {
|
|
|
769
703
|
return failResult("activity-log", task.message);
|
|
770
704
|
}
|
|
771
705
|
|
|
772
|
-
const
|
|
773
|
-
if (!
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
const entries = logSection
|
|
778
|
-
.split(/\r?\n/)
|
|
779
|
-
.map((line: any) => line.trim())
|
|
780
|
-
.filter((line: any) => line.startsWith("- "));
|
|
781
|
-
|
|
782
|
-
if (entries.length === 0) {
|
|
783
|
-
return failResult("activity-log", "Activity Log has no entries");
|
|
784
|
-
}
|
|
706
|
+
const { section, invalidEntries } = inspectActivityLog(task.content);
|
|
707
|
+
if (!section) return failResult("activity-log", "Activity Log section not found or ambiguous");
|
|
708
|
+
if (invalidEntries.length) return failResult("activity-log", `Invalid Activity Log entry format: ${invalidEntries[0]}`);
|
|
709
|
+
const entries = section.entries;
|
|
710
|
+
if (entries.length === 0) return failResult("activity-log", "Activity Log has no entries");
|
|
785
711
|
|
|
786
712
|
let previousTimestamp = "";
|
|
787
713
|
let latestAction = "";
|
|
788
714
|
let latestTimestamp = "";
|
|
715
|
+
const doneActions: string[] = [];
|
|
789
716
|
|
|
790
717
|
for (const entry of entries) {
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
return failResult("activity-log", `Invalid Activity Log entry format: ${entry}`);
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
const [, timestamp, action] = match;
|
|
718
|
+
if (!entry.note.trim()) return failResult("activity-log", "Activity Log entry note is required");
|
|
719
|
+
const { time: timestamp, step: action } = entry;
|
|
797
720
|
if (previousTimestamp && timestamp < previousTimestamp) {
|
|
798
721
|
return failResult("activity-log", "Activity Log timestamps are not in ascending order");
|
|
799
722
|
}
|
|
@@ -805,6 +728,16 @@ function checkActivityLog({ taskDir, config }: any): any {
|
|
|
805
728
|
if (!ACTIVITY_LOG_STARTED_RE.test(action)) {
|
|
806
729
|
latestTimestamp = timestamp;
|
|
807
730
|
latestAction = action;
|
|
731
|
+
doneActions.push(action);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
if (config.expected_action_pattern && !new RegExp(config.expected_action_pattern).test(latestAction)) {
|
|
736
|
+
const expected = new RegExp(config.expected_action_pattern);
|
|
737
|
+
let index = doneActions.length - 1;
|
|
738
|
+
while (index >= 0 && doneActions[index] === 'Commit' && !expected.test(doneActions[index]!)) index -= 1;
|
|
739
|
+
if (index >= 0 && expected.test(doneActions[index]!)) {
|
|
740
|
+
latestAction = doneActions[index]!;
|
|
808
741
|
}
|
|
809
742
|
}
|
|
810
743
|
|
|
@@ -855,118 +788,7 @@ function checkCompletionChecklist({ taskDir, config }: any): any {
|
|
|
855
788
|
return passResult("completion-checklist", `Completion Checklist valid (${items.length} items checked)`);
|
|
856
789
|
}
|
|
857
790
|
|
|
858
|
-
function
|
|
859
|
-
let value = String(line || "").trim();
|
|
860
|
-
if (!value.startsWith("|")) {
|
|
861
|
-
return [];
|
|
862
|
-
}
|
|
863
|
-
value = value.replace(/^\|/, "").replace(/\|$/, "");
|
|
864
|
-
|
|
865
|
-
const cells = [];
|
|
866
|
-
let cell = "";
|
|
867
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
868
|
-
const char = value[index];
|
|
869
|
-
if (char === "|" && !isEscapedAt(value, index)) {
|
|
870
|
-
cells.push(unescapeMarkdownTableCell(cell.trim()));
|
|
871
|
-
cell = "";
|
|
872
|
-
continue;
|
|
873
|
-
}
|
|
874
|
-
cell += char;
|
|
875
|
-
}
|
|
876
|
-
cells.push(unescapeMarkdownTableCell(cell.trim()));
|
|
877
|
-
return cells;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
function unescapeMarkdownTableCell(value: any): any {
|
|
881
|
-
let output = "";
|
|
882
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
883
|
-
const char = value[index];
|
|
884
|
-
const next = value[index + 1];
|
|
885
|
-
if (char === "\\" && (next === "\\" || next === "|")) {
|
|
886
|
-
output += next;
|
|
887
|
-
index += 1;
|
|
888
|
-
continue;
|
|
889
|
-
}
|
|
890
|
-
output += char;
|
|
891
|
-
}
|
|
892
|
-
return output;
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
function isEscapedAt(value: any, index: any): any {
|
|
896
|
-
let backslashes = 0;
|
|
897
|
-
for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
|
|
898
|
-
backslashes += 1;
|
|
899
|
-
}
|
|
900
|
-
return backslashes % 2 === 1;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
function parseWorkflowWarningRows(section: any): any {
|
|
904
|
-
const rows = [];
|
|
905
|
-
for (const rawLine of String(section || "").split(/\r?\n/)) {
|
|
906
|
-
const cells = splitMarkdownTableRow(rawLine);
|
|
907
|
-
if (cells.length === 0) {
|
|
908
|
-
continue;
|
|
909
|
-
}
|
|
910
|
-
if ((cells[0] || "").toLowerCase() === "id") {
|
|
911
|
-
continue;
|
|
912
|
-
}
|
|
913
|
-
if (cells.every((cell: any) => /^:?-{3,}:?$/.test(cell))) {
|
|
914
|
-
continue;
|
|
915
|
-
}
|
|
916
|
-
rows.push(cells);
|
|
917
|
-
}
|
|
918
|
-
return rows;
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
function validateWorkflowWarnings(content: any): any {
|
|
922
|
-
const section = getSectionContent(content, WORKFLOW_WARNING_SECTION_NAMES);
|
|
923
|
-
if (!section.trim()) {
|
|
924
|
-
return [];
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
const rows = parseWorkflowWarningRows(section);
|
|
928
|
-
const errors = [];
|
|
929
|
-
for (const cells of rows) {
|
|
930
|
-
if (cells.length < 11) {
|
|
931
|
-
errors.push(`malformed row (expected 11 columns): ${cells.join(" | ")}`);
|
|
932
|
-
continue;
|
|
933
|
-
}
|
|
934
|
-
const [id, time, step, severity, code, status, target, message, action, resolvedAt, resolution] = cells;
|
|
935
|
-
if (!WORKFLOW_WARNING_ID_PATTERN.test(id)) {
|
|
936
|
-
errors.push(`${id || "(empty id)"}: invalid id`);
|
|
937
|
-
}
|
|
938
|
-
if (!DATE_TIME_PATTERN.test(time)) {
|
|
939
|
-
errors.push(`${id}: invalid time '${time}'`);
|
|
940
|
-
}
|
|
941
|
-
if (isBlank(step)) {
|
|
942
|
-
errors.push(`${id}: step is required`);
|
|
943
|
-
}
|
|
944
|
-
if (!WORKFLOW_WARNING_SEVERITIES.has(severity)) {
|
|
945
|
-
errors.push(`${id}: illegal severity '${severity}'`);
|
|
946
|
-
}
|
|
947
|
-
if (isBlank(code)) {
|
|
948
|
-
errors.push(`${id}: code is required`);
|
|
949
|
-
}
|
|
950
|
-
if (!WORKFLOW_WARNING_STATUSES.has(status)) {
|
|
951
|
-
errors.push(`${id}: illegal status '${status}'`);
|
|
952
|
-
}
|
|
953
|
-
if (isBlank(target)) {
|
|
954
|
-
errors.push(`${id}: target is required`);
|
|
955
|
-
}
|
|
956
|
-
if (isBlank(message)) {
|
|
957
|
-
errors.push(`${id}: message is required`);
|
|
958
|
-
}
|
|
959
|
-
if (status === "open" && isBlank(action)) {
|
|
960
|
-
errors.push(`${id}: open warning requires action`);
|
|
961
|
-
}
|
|
962
|
-
if ((status === "resolved" || status === "ignored") && (isBlank(resolvedAt) || isBlank(resolution))) {
|
|
963
|
-
errors.push(`${id}: ${status} warning requires resolved_at and resolution`);
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
return errors;
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
function resolveReviewSetting(config: any, key: any, fallback: any): any {
|
|
791
|
+
function resolveReviewSetting(config: any, key: any, fallback: any, repoRoot: string): any {
|
|
970
792
|
if (config && config[key] !== undefined && config[key] !== null) {
|
|
971
793
|
return config[key];
|
|
972
794
|
}
|
|
@@ -977,7 +799,7 @@ function resolveReviewSetting(config: any, key: any, fallback: any): any {
|
|
|
977
799
|
return fallback;
|
|
978
800
|
}
|
|
979
801
|
|
|
980
|
-
function checkReviewLedger({ taskDir, config }: any): any {
|
|
802
|
+
function checkReviewLedger({ taskDir, config, repositoryRoot }: any): any {
|
|
981
803
|
const task = loadTask(taskDir);
|
|
982
804
|
if (!task.ok) {
|
|
983
805
|
return failResult("review-ledger", task.message);
|
|
@@ -987,9 +809,7 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
987
809
|
try {
|
|
988
810
|
const ledger = parseLedgerDocument(task.content);
|
|
989
811
|
if (!ledger.present) return failResult("review-ledger", `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`);
|
|
990
|
-
rows = ledger.rows
|
|
991
|
-
row.id, row.stage, row.round, row.severity, row.status, row.evidence
|
|
992
|
-
]);
|
|
812
|
+
rows = ledger.rows;
|
|
993
813
|
} catch (error) {
|
|
994
814
|
return failResult("review-ledger", `Invalid disagreement ledger: ${error instanceof Error ? error.message : String(error)}`);
|
|
995
815
|
}
|
|
@@ -998,17 +818,12 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
998
818
|
}
|
|
999
819
|
|
|
1000
820
|
const stageScope = Array.isArray(config.stage_scope) ? config.stage_scope : null;
|
|
1001
|
-
const maxRounds = Number(resolveReviewSetting(config, "maxHandshakeRounds", DEFAULT_MAX_HANDSHAKE_ROUNDS));
|
|
821
|
+
const maxRounds = Number(resolveReviewSetting(config, "maxHandshakeRounds", DEFAULT_MAX_HANDSHAKE_ROUNDS, repositoryRoot));
|
|
1002
822
|
const problems = [];
|
|
1003
823
|
let inScopeCount = 0;
|
|
1004
824
|
|
|
1005
|
-
for (const
|
|
1006
|
-
|
|
1007
|
-
problems.push(`malformed row (expected 6 columns): ${cells.join(" | ")}`);
|
|
1008
|
-
continue;
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
const [id, stage, roundRaw, , status, evidence] = cells;
|
|
825
|
+
for (const row of rows) {
|
|
826
|
+
const { id, stage, round: roundRaw, status, evidence } = row;
|
|
1012
827
|
const stageScoped = stageScope ? stageScope.includes(stage) : true;
|
|
1013
828
|
// post-review-commit exemption rows are consumed by the post-review-commit
|
|
1014
829
|
// check, not enforced here.
|
|
@@ -1020,8 +835,9 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
1020
835
|
}
|
|
1021
836
|
inScopeCount += 1;
|
|
1022
837
|
|
|
1023
|
-
|
|
1024
|
-
|
|
838
|
+
const invalid = validateLedgerRows([row]);
|
|
839
|
+
if (invalid) {
|
|
840
|
+
problems.push(`${invalid.code}: ${invalid.message}`);
|
|
1025
841
|
continue;
|
|
1026
842
|
}
|
|
1027
843
|
if (status !== "open" && evidence === "") {
|
|
@@ -1031,12 +847,12 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
1031
847
|
if (
|
|
1032
848
|
Number.isFinite(round) &&
|
|
1033
849
|
round >= maxRounds &&
|
|
1034
|
-
!
|
|
850
|
+
!LEDGER_TERMINAL.has(status!) &&
|
|
1035
851
|
status !== "needs-human-decision"
|
|
1036
852
|
) {
|
|
1037
853
|
problems.push(`${id}: round ${round} reached limit ${maxRounds} without convergence; escalate to needs-human-decision`);
|
|
1038
854
|
}
|
|
1039
|
-
if (!
|
|
855
|
+
if (!LEDGER_TERMINAL.has(status!)) {
|
|
1040
856
|
problems.push(`${id}: unresolved (status '${status}')`);
|
|
1041
857
|
}
|
|
1042
858
|
}
|
|
@@ -1049,7 +865,7 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
1049
865
|
return passResult("review-ledger", `Disagreement ledger clean (${inScopeCount} in-scope entries terminal${scopeLabel})`);
|
|
1050
866
|
}
|
|
1051
867
|
|
|
1052
|
-
function checkManualValidation({ taskDir }: any): any {
|
|
868
|
+
async function checkManualValidation({ taskDir, repositoryRoot }: any): Promise<any> {
|
|
1053
869
|
// 1. Latest review-code artifact; none -> pass (no review, check not applicable).
|
|
1054
870
|
const review = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
1055
871
|
if (!review.ok) {
|
|
@@ -1081,15 +897,23 @@ function checkManualValidation({ taskDir }: any): any {
|
|
|
1081
897
|
const artifactName = path.basename(resolved.path);
|
|
1082
898
|
const task = loadTask(taskDir);
|
|
1083
899
|
if (!task.ok) return failResult("manual-validation", task.message);
|
|
1084
|
-
const
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
);
|
|
1088
|
-
if (!
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
900
|
+
const completion = readManualValidationCompletion(taskDir, {
|
|
901
|
+
taskId: task.metadata.id,
|
|
902
|
+
artifact: artifactName
|
|
903
|
+
});
|
|
904
|
+
if (!completion.ok) {
|
|
905
|
+
const source = completion.error.code.startsWith('MANUAL_VALIDATION_RECEIPT_') ? 'receipt' : 'transaction';
|
|
906
|
+
return failResult("manual-validation", `Manual validation ${source} is unavailable: ${completion.error.message}`);
|
|
907
|
+
}
|
|
908
|
+
const { receipt, transaction } = completion.value;
|
|
909
|
+
if (transaction.phase !== "committed" || !transaction.eventAppended || !transaction.postWriteVerified) {
|
|
910
|
+
return failResult("manual-validation", "Manual validation transaction has not reached the committed post-write-verified state");
|
|
911
|
+
}
|
|
912
|
+
if (transaction.pendingSummaryDigest !== receipt.pendingSummaryDigest || transaction.finalSummaryDigest !== receipt.finalSummaryDigest) {
|
|
913
|
+
return failResult("manual-validation", "Manual validation summary digests do not match the committed receipt");
|
|
914
|
+
}
|
|
915
|
+
if (sha256File(resolved.path) !== receipt.artifactSha256) {
|
|
916
|
+
return failResult("manual-validation", `Manual validation artifact digest does not match the receipt for ${artifactName}`);
|
|
1093
917
|
}
|
|
1094
918
|
// 6. Timing correlation (PL-3 fix, PL-4 corrected): the completion entry must
|
|
1095
919
|
// sit AFTER the latest review-code round's completion entry in the
|
|
@@ -1098,28 +922,32 @@ function checkManualValidation({ taskDir }: any): any {
|
|
|
1098
922
|
// which indexOf never matches). Not reusing completed.exec().index: exec
|
|
1099
923
|
// anchors to the first '**Complete Manual Validation**' heading, which can
|
|
1100
924
|
// belong to an earlier round's entry and misorder the standard path.
|
|
1101
|
-
const
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
);
|
|
925
|
+
const inspectedLog = inspectActivityLog(task.content);
|
|
926
|
+
if (!inspectedLog.section) return failResult("manual-validation", "Activity Log is missing or invalid");
|
|
927
|
+
const reviewDoneIndex = inspectedLog.section.entries.findIndex((entry) => entry.step === `Review Code (Round ${review.round})`);
|
|
928
|
+
const completedIndex = inspectedLog.section.entries.findIndex((entry) => entry.step === "Complete Manual Validation"
|
|
929
|
+
&& entry.note.includes(`Manual validation passed → ${artifactName};`)
|
|
930
|
+
&& entry.note.includes(`transaction=${receipt.transactionId};`)
|
|
931
|
+
&& entry.note.includes(`receipt=${receipt.receiptDigest};`)
|
|
932
|
+
&& entry.note.includes(`head=${receipt.prHeadSha}`));
|
|
933
|
+
if (reviewDoneIndex === -1) return failResult("manual-validation", `Latest review-code (round ${review.round}) completion entry is missing from the Activity Log`);
|
|
934
|
+
if (completedIndex === -1) return failResult("manual-validation", `Committed manual validation completion is not recorded for ${artifactName}`);
|
|
935
|
+
if (completedIndex < reviewDoneIndex) return failResult("manual-validation", `Latest review-code (round ${review.round}) came after the manual validation completion recorded for ${artifactName}`);
|
|
936
|
+
|
|
937
|
+
const fact = readPrDeliveryFact(task.metadata);
|
|
938
|
+
if (fact.status === "invalid") return failResult("manual-validation", fact.error.message);
|
|
939
|
+
if (fact.status === "valid" && fact.fact.state === "bound") {
|
|
940
|
+
const inspected = await inspectPlatformPullRequest(task.metadata.id, { cwd: repositoryRoot });
|
|
941
|
+
if (!inspected.pullRequest) return failResult("manual-validation", inspected.error?.message ?? "canonical pull-request head is unavailable");
|
|
942
|
+
if (inspected.pullRequest.head.sha !== receipt.prHeadSha) return failResult("manual-validation", "manual validation receipt is stale for the current pull-request head");
|
|
943
|
+
const summary = await summaryCommentState(task.metadata.id, { cwd: repositoryRoot });
|
|
944
|
+
if (!summary.comment) return failResult("manual-validation", "canonical pull-request summary comment is unavailable");
|
|
945
|
+
if (!manualValidationFinalSummaryProjectionMatches(summary.comment.body, receipt)) return failResult("manual-validation", "canonical pull-request summary does not match the committed manual validation projection");
|
|
1118
946
|
}
|
|
1119
|
-
return passResult("manual-validation", `Manual validation completed → ${artifactName}`);
|
|
947
|
+
return passResult("manual-validation", `Manual validation completed → ${artifactName} (committed receipt and post-write verification)`);
|
|
1120
948
|
}
|
|
1121
949
|
|
|
1122
|
-
async function checkPostReviewCommit({ taskDir, config }: any): Promise<any> {
|
|
950
|
+
async function checkPostReviewCommit({ taskDir, config, repositoryRoot }: any): Promise<any> {
|
|
1123
951
|
const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
1124
952
|
if (!reviewArtifact.ok) {
|
|
1125
953
|
if (reviewArtifact.error) return failResult("post-review-commit", `Review-code artifact is unavailable: ${reviewArtifact.error}`);
|
|
@@ -1139,7 +967,7 @@ async function checkPostReviewCommit({ taskDir, config }: any): Promise<any> {
|
|
|
1139
967
|
if (factRead.status === 'invalid') return failResult("post-review-commit", factRead.error.message);
|
|
1140
968
|
const fact = factRead.status === 'valid' ? factRead.fact : null;
|
|
1141
969
|
const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
|
|
1142
|
-
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(
|
|
970
|
+
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repositoryRoot));
|
|
1143
971
|
const hasPullRequest = fact?.state === 'bound';
|
|
1144
972
|
let inspected: Awaited<ReturnType<typeof inspectPlatformPullRequest>> | null = null;
|
|
1145
973
|
if (hasPullRequest) {
|
|
@@ -1313,7 +1141,7 @@ function resolvePostReviewExemption(content: string):
|
|
|
1313
1141
|
}
|
|
1314
1142
|
}
|
|
1315
1143
|
|
|
1316
|
-
function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
1144
|
+
function checkReviewFact({ taskDir, artifactFile, repositoryRoot }: any): any {
|
|
1317
1145
|
const resolvedArtifact = resolveArtifactPath(
|
|
1318
1146
|
taskDir,
|
|
1319
1147
|
"review-code.md|review-code-r{N}.md",
|
|
@@ -1397,7 +1225,7 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
|
1397
1225
|
mode: "worktree",
|
|
1398
1226
|
baseline,
|
|
1399
1227
|
diffBase,
|
|
1400
|
-
globs: resolvePostReviewGlobs({}, loadPostReviewConfig(
|
|
1228
|
+
globs: resolvePostReviewGlobs({}, loadPostReviewConfig(repositoryRoot))
|
|
1401
1229
|
});
|
|
1402
1230
|
} catch {
|
|
1403
1231
|
return blockedResult(
|
|
@@ -1524,46 +1352,13 @@ function resolveArtifactPath(taskDir: any, filePattern: any, artifactFile: any):
|
|
|
1524
1352
|
return { ok: true, path: path.join(taskDir, matches[0]!.fileName) };
|
|
1525
1353
|
}
|
|
1526
1354
|
|
|
1527
|
-
function getSectionContent(content:
|
|
1528
|
-
const
|
|
1529
|
-
|
|
1530
|
-
function visibleHeadings(): any {
|
|
1531
|
-
const headings = [];
|
|
1532
|
-
let fence = null;
|
|
1533
|
-
for (let index = 0; index < lines.length; index += 1) {
|
|
1534
|
-
const line = lines[index];
|
|
1535
|
-
if (fence) {
|
|
1536
|
-
const closer = line.match(/^ {0,3}(`+|~+)\s*$/);
|
|
1537
|
-
if (closer && closer[1][0] === fence.character && closer[1].length >= fence.length) {
|
|
1538
|
-
fence = null;
|
|
1539
|
-
}
|
|
1540
|
-
continue;
|
|
1541
|
-
}
|
|
1542
|
-
const opener = line.match(/^ {0,3}(`{3,}|~{3,})(?:[^`~].*)?$/);
|
|
1543
|
-
if (opener) {
|
|
1544
|
-
fence = { character: opener[1][0], length: opener[1].length };
|
|
1545
|
-
continue;
|
|
1546
|
-
}
|
|
1547
|
-
if (line.startsWith("## ")) {
|
|
1548
|
-
headings.push({ index, text: line.trim() });
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
return headings;
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
const headings = visibleHeadings();
|
|
1555
|
-
|
|
1355
|
+
function getSectionContent(content: string, names: readonly string[]): string {
|
|
1356
|
+
const headings = scanVisibleMarkdown(content).headings.filter((heading) => heading.level === 2);
|
|
1556
1357
|
for (const name of names) {
|
|
1557
|
-
const
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
continue;
|
|
1561
|
-
}
|
|
1562
|
-
const startIndex = headings[position]!.index;
|
|
1563
|
-
const endIndex = headings[position + 1]?.index ?? lines.length;
|
|
1564
|
-
return lines.slice(startIndex + 1, endIndex).join("\n").trim();
|
|
1358
|
+
const position = headings.findIndex((heading) => heading.text === name);
|
|
1359
|
+
if (position === -1) continue;
|
|
1360
|
+
return content.slice(headings[position]!.end + 1, headings[position + 1]?.start ?? content.length).replace(/\r\n/g, "\n").trim();
|
|
1565
1361
|
}
|
|
1566
|
-
|
|
1567
1362
|
return "";
|
|
1568
1363
|
}
|
|
1569
1364
|
|
|
@@ -1691,14 +1486,14 @@ function isBlank(value: any): any {
|
|
|
1691
1486
|
}
|
|
1692
1487
|
|
|
1693
1488
|
async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }: any): Promise<any> {
|
|
1694
|
-
|
|
1695
|
-
|
|
1489
|
+
let repoRoot = repositoryRoot ? path.resolve(repositoryRoot) : defaultRepoRoot;
|
|
1490
|
+
if (!repositoryRoot) {
|
|
1696
1491
|
let cursor = path.resolve(taskDir);
|
|
1697
1492
|
while (path.dirname(cursor) !== cursor && !fs.existsSync(path.join(cursor, ".agents"))) cursor = path.dirname(cursor);
|
|
1698
1493
|
if (fs.existsSync(path.join(cursor, ".agents"))) repoRoot = cursor;
|
|
1699
1494
|
}
|
|
1700
1495
|
const verifyConfig = loadVerificationConfig(repoRoot, skillName);
|
|
1701
|
-
const shared = { ...sharedUtils, repoRoot };
|
|
1496
|
+
const shared: VerificationShared = { ...sharedUtils, repoRoot };
|
|
1702
1497
|
if (mode === "gate") {
|
|
1703
1498
|
const checks = [];
|
|
1704
1499
|
for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {
|