@fitlab-ai/agent-infra 0.9.14 → 0.10.0
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/internal-cli.sh +45 -0
- package/dist/bin/internal-cli.js +93 -30
- package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +9 -4
- package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +43 -3
- package/dist/lib/defaults.json +103 -103
- package/dist/lib/fs/durable-write.js +39 -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/cli-route-inventory.js +4 -2
- package/dist/lib/internal/codex-lifecycle.js +6 -6
- package/dist/lib/internal/demo-promotion.js +322 -0
- package/dist/lib/internal/demo-transcript.js +454 -0
- package/dist/lib/internal/host-control.js +28 -0
- package/dist/lib/internal/manual-validation.js +331 -0
- package/dist/lib/internal/platform-pr.js +18 -4
- package/dist/lib/internal/release-workflow.js +63 -84
- package/dist/lib/internal/sandbox-control.js +149 -2
- package/dist/lib/internal/task-artifact.js +16 -263
- package/dist/lib/internal/task-create.js +6 -5
- package/dist/lib/internal/task-event.js +37 -37
- package/dist/lib/internal/task-lifecycle.js +2 -2
- package/dist/lib/internal/task-operation-registry.js +101 -4
- package/dist/lib/internal/task-review.js +11 -56
- package/dist/lib/internal/task-validate.js +30 -10
- package/dist/lib/owned-path.js +33 -0
- package/dist/lib/platform/check-status.js +11 -0
- package/dist/lib/platform/comment-safety.js +4 -1
- 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 +15 -20
- package/dist/lib/platform/issue-comments.js +18 -12
- package/dist/lib/platform/issues.js +2 -180
- package/dist/lib/platform/pr-change-report.js +5 -4
- package/dist/lib/platform/pr-checks.js +12 -65
- package/dist/lib/platform/pr-summary.js +117 -33
- package/dist/lib/platform/pull-requests.js +5 -108
- package/dist/lib/platform/snapshots.js +2 -0
- package/dist/lib/platform/task-identities.js +2 -9
- package/dist/lib/platform/verification-sync.js +132 -143
- package/dist/lib/pr-review/evidence-grading.js +4 -8
- package/dist/lib/release/workflow.js +1 -1
- package/dist/lib/sandbox/commands/create.js +7 -2
- package/dist/lib/sandbox/commands/rm.js +19 -1511
- package/dist/lib/sandbox/control/audit.js +203 -0
- package/dist/lib/sandbox/control/client.js +93 -54
- package/dist/lib/sandbox/control/executor.js +129 -65
- 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 +36 -2
- package/dist/lib/sandbox/control/native-file-lock.js +6 -98
- package/dist/lib/sandbox/control/protocol.js +55 -4
- package/dist/lib/sandbox/control/server.js +518 -127
- package/dist/lib/sandbox/control/state.js +64 -0
- package/dist/lib/sandbox/control/task-workflow.js +74 -0
- package/dist/lib/sandbox/control/workflow-executor.js +89 -0
- package/dist/lib/sandbox/index.js +1 -2
- package/dist/lib/sandbox/recovery.js +28 -4
- package/dist/lib/sandbox/removal.js +822 -0
- package/dist/lib/sandbox/task-cleanup.js +217 -0
- package/dist/lib/sandbox/workspace-identity.js +17 -1
- package/dist/lib/sandbox/workspace-view.js +13 -14
- 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 +79 -0
- package/dist/lib/task/artifact-lifecycle.js +30 -28
- package/dist/lib/task/artifact-name.js +36 -0
- package/dist/lib/task/artifact-operations.js +29 -289
- package/dist/lib/task/artifact-receipts.js +3 -15
- package/dist/lib/task/artifact-recovery.js +430 -0
- package/dist/lib/task/artifact-repair-intent.js +134 -29
- package/dist/lib/task/artifact-schema.js +6 -14
- package/dist/lib/task/capabilities.js +12 -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 +33 -20
- package/dist/lib/task/control-authority.js +403 -6
- package/dist/lib/task/control-recovery.js +140 -0
- package/dist/lib/task/create-service.js +1 -8
- package/dist/lib/task/create.js +62 -9
- package/dist/lib/task/decision-details.js +2 -46
- package/dist/lib/task/delegation-receipts.js +64 -3
- package/dist/lib/task/events.js +275 -22
- package/dist/lib/task/finalization-state.js +9 -0
- package/dist/lib/task/human-override.js +8 -14
- package/dist/lib/task/implementation-inputs.js +3 -3
- package/dist/lib/task/intermediate-cleanup.js +441 -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-recovery.js +549 -0
- package/dist/lib/task/lifecycle.js +31 -4
- package/dist/lib/task/local-artifact-finalization.js +197 -197
- 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 +105 -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 +66 -19
- package/dist/lib/task/pr-delivery-fact.js +12 -56
- package/dist/lib/task/qualification-audit.js +20 -34
- package/dist/lib/task/recovery-warning.js +19 -0
- package/dist/lib/task/review-artifacts.js +2 -18
- package/dist/lib/task/review-command.js +26 -0
- package/dist/lib/task/review-finalization.js +175 -216
- package/dist/lib/task/review-fingerprint.js +2 -2
- package/dist/lib/task/sections.js +34 -56
- package/dist/lib/task/short-id.js +15 -7
- package/dist/lib/task/task-execution-lock.js +1 -1
- package/dist/lib/task/verification-engine.js +119 -337
- package/dist/lib/task/verification.js +1 -1
- package/dist/lib/task/workflow-command.js +16 -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/lib/version.js +1 -11
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +10 -4
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +55 -3
- package/lib/fs/durable-write.ts +30 -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/cli-route-inventory.ts +4 -2
- package/lib/internal/codex-lifecycle.ts +6 -6
- package/lib/internal/demo-promotion.ts +354 -0
- package/lib/internal/demo-transcript.ts +419 -0
- package/lib/internal/host-control.ts +28 -0
- package/lib/internal/manual-validation.ts +315 -0
- package/lib/internal/platform-pr.ts +15 -4
- package/lib/internal/release-workflow.ts +74 -82
- package/lib/internal/sandbox-control.ts +162 -1
- package/lib/internal/task-artifact.ts +14 -217
- package/lib/internal/task-create.ts +5 -5
- package/lib/internal/task-event.ts +20 -11
- package/lib/internal/task-lifecycle.ts +4 -3
- package/lib/internal/task-operation-registry.ts +111 -4
- package/lib/internal/task-review.ts +9 -54
- package/lib/internal/task-validate.ts +26 -10
- package/lib/owned-path.ts +26 -0
- package/lib/platform/check-status.ts +9 -0
- package/lib/platform/comment-safety.ts +5 -0
- package/lib/platform/completion-backfill.ts +1 -1
- package/lib/platform/github-data.ts +322 -0
- package/lib/platform/github-provider.ts +15 -20
- package/lib/platform/issue-comments.ts +21 -14
- package/lib/platform/issues.ts +5 -246
- package/lib/platform/pr-change-report.ts +7 -5
- package/lib/platform/pr-checks.ts +13 -77
- package/lib/platform/pr-summary.ts +123 -35
- package/lib/platform/pull-requests.ts +6 -173
- package/lib/platform/snapshots.ts +53 -0
- package/lib/platform/task-identities.ts +3 -14
- package/lib/platform/verification-sync.ts +150 -156
- package/lib/pr-review/evidence-grading.ts +4 -9
- package/lib/release/workflow.ts +3 -3
- package/lib/sandbox/commands/create.ts +7 -6
- package/lib/sandbox/commands/rm.ts +21 -1895
- package/lib/sandbox/control/audit.ts +253 -0
- package/lib/sandbox/control/client.ts +109 -66
- package/lib/sandbox/control/executor.ts +134 -74
- package/lib/sandbox/control/finalization-response.ts +29 -0
- package/lib/sandbox/control/identity-sentinel.ts +137 -0
- package/lib/sandbox/control/lifecycle.ts +45 -3
- package/lib/sandbox/control/native-file-lock.ts +6 -107
- package/lib/sandbox/control/protocol.ts +80 -6
- package/lib/sandbox/control/server.ts +567 -132
- package/lib/sandbox/control/state.ts +86 -0
- package/lib/sandbox/control/task-workflow.ts +95 -0
- package/lib/sandbox/control/workflow-executor.ts +92 -0
- package/lib/sandbox/index.ts +1 -2
- package/lib/sandbox/recovery.ts +28 -5
- package/lib/sandbox/removal.ts +1142 -0
- package/lib/sandbox/task-cleanup.ts +209 -0
- package/lib/sandbox/workspace-identity.ts +19 -3
- package/lib/sandbox/workspace-view.ts +17 -15
- package/lib/task/activity-intent.ts +2 -2
- package/lib/task/activity-log.ts +27 -19
- package/lib/task/artifact-command.ts +85 -0
- package/lib/task/artifact-lifecycle.ts +31 -26
- package/lib/task/artifact-name.ts +55 -0
- package/lib/task/artifact-operations.ts +34 -310
- package/lib/task/artifact-receipts.ts +3 -14
- package/lib/task/artifact-recovery.ts +519 -0
- package/lib/task/artifact-repair-intent.ts +162 -33
- package/lib/task/artifact-schema.ts +5 -34
- package/lib/task/capabilities.ts +13 -22
- package/lib/task/codex-orchestration.ts +85 -24
- package/lib/task/commit-identity.ts +31 -0
- package/lib/task/commit-operation.ts +37 -20
- package/lib/task/control-authority.ts +540 -10
- package/lib/task/control-recovery.ts +186 -0
- package/lib/task/create-service.ts +1 -10
- package/lib/task/create.ts +63 -8
- package/lib/task/decision-details.ts +3 -71
- package/lib/task/delegation-receipts.ts +73 -2
- package/lib/task/events.ts +309 -24
- package/lib/task/finalization-state.ts +11 -0
- package/lib/task/human-override.ts +8 -16
- package/lib/task/implementation-inputs.ts +3 -3
- package/lib/task/intermediate-cleanup.ts +493 -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-recovery.ts +691 -0
- package/lib/task/lifecycle.ts +30 -5
- package/lib/task/local-artifact-finalization.ts +244 -234
- 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 +156 -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 +84 -19
- package/lib/task/pr-delivery-fact.ts +15 -62
- package/lib/task/qualification-audit.ts +22 -33
- package/lib/task/recovery-warning.ts +21 -0
- package/lib/task/review-artifacts.ts +1 -20
- package/lib/task/review-command.ts +24 -0
- package/lib/task/review-finalization.ts +183 -292
- package/lib/task/review-fingerprint.ts +2 -2
- package/lib/task/sections.ts +33 -54
- package/lib/task/short-id.ts +27 -5
- package/lib/task/task-execution-lock.ts +1 -1
- package/lib/task/verification-engine.ts +113 -383
- package/lib/task/verification-types.ts +15 -0
- package/lib/task/verification.ts +1 -1
- package/lib/task/workflow-command.ts +17 -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/lib/version.ts +1 -15
- package/package.json +6 -6
- package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
- package/templates/.agents/rules/create-issue.en.md +1 -1
- package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +4 -2
- package/templates/.agents/rules/issue-sync.zh-CN.md +4 -3
- package/templates/.agents/rules/local-artifact-repair.en.md +46 -39
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +43 -36
- 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 +6 -6
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +6 -6
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -1
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/block-task/config/verify.json +1 -1
- package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/cancel-task/config/verify.json +1 -1
- package/templates/.agents/skills/code-task/SKILL.en.md +7 -7
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +7 -7
- package/templates/.agents/skills/code-task/config/verify.en.json +1 -1
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +33 -21
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +33 -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 +2 -0
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +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 +3 -3
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/config/verify.json +1 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +2 -2
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +2 -2
- package/templates/.agents/skills/create-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/create-task/config/verify.json +1 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +8 -8
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/import-issue/config/verify.json +2 -2
- package/templates/.agents/skills/plan-task/SKILL.en.md +4 -4
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/plan-task/config/verify.en.json +1 -1
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -1
- 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/restore-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/restore-task/config/verify.json +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +2 -2
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +7 -7
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +6 -6
- package/templates/.agents/skills/review-code/SKILL.en.md +2 -2
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-code/reference/report-template.en.md +12 -12
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +12 -12
- package/templates/.agents/skills/review-plan/SKILL.en.md +2 -2
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +7 -7
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +7 -7
- package/templates/.agents/skills/review-pr/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +3 -3
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +3 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +20 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +20 -3
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +1 -1
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +1 -1
- 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 +2 -0
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -0
- 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 +17 -6
- package/templates/.agents/skills/test/SKILL.zh-CN.md +17 -6
- package/templates/.agents/templates/task.en.md +1 -1
- package/templates/.agents/templates/task.zh-CN.md +1 -1
- package/templates/.claude/commands/import-issue.en.md +1 -1
- package/templates/.claude/commands/import-issue.zh-CN.md +1 -1
- package/templates/.claude/commands/restore-task.en.md +1 -1
- package/templates/.claude/commands/restore-task.zh-CN.md +1 -1
- package/templates/.claude/commands/run-manual-validation.en.md +1 -1
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
- package/dist/lib/platform/adapters.js +0 -56
- package/lib/platform/adapters.ts +0 -197
|
@@ -24,20 +24,31 @@ 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";
|
|
38
43
|
import { validateQualificationAudit } from "./qualification-audit.ts";
|
|
39
44
|
import { getArtifactSchema } from "./artifact-schema.ts";
|
|
40
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";
|
|
51
|
+
import { taskIssueIdentity } from "../platform/task-identities.ts";
|
|
41
52
|
|
|
42
53
|
const TASK_ENUMS = {
|
|
43
54
|
type: ["feature", "bugfix", "refactor", "docs", "chore"],
|
|
@@ -58,7 +69,6 @@ const DEFAULT_REQUIRED_FIELDS = [
|
|
|
58
69
|
];
|
|
59
70
|
|
|
60
71
|
const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
|
|
61
|
-
const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
|
|
62
72
|
// Start markers (action suffixed with ` [started]`) are excluded from the
|
|
63
73
|
// "latest action" / freshness computation so a step's in-flight marker never
|
|
64
74
|
// satisfies a skill's expected_action_pattern; the matching done entry does.
|
|
@@ -67,28 +77,12 @@ const BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
|
67
77
|
|
|
68
78
|
// Review disagreement ledger (see .agents/rules/review-handshake.md).
|
|
69
79
|
const LEDGER_SECTION_NAMES = ["审查分歧账本", "Review Disagreement Ledger"];
|
|
70
|
-
const LEDGER_STATUSES = new Set([
|
|
71
|
-
"open",
|
|
72
|
-
"accepted",
|
|
73
|
-
"adjusted",
|
|
74
|
-
"refuted",
|
|
75
|
-
"cannot-judge",
|
|
76
|
-
"confirmed",
|
|
77
|
-
"needs-human-decision",
|
|
78
|
-
"closed",
|
|
79
|
-
"human-decided"
|
|
80
|
-
]);
|
|
81
|
-
const LEDGER_TERMINAL_OK = new Set(["confirmed", "closed", "human-decided"]);
|
|
82
80
|
const DEFAULT_MAX_HANDSHAKE_ROUNDS = 3;
|
|
83
81
|
const POST_REVIEW_COMMIT_STAGE = "post-review-commit";
|
|
84
82
|
const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
|
|
85
|
-
const WORKFLOW_WARNING_SECTION_NAMES = ["工作流告警", "Workflow Warnings"];
|
|
86
|
-
const WORKFLOW_WARNING_STATUSES = new Set(["open", "resolved", "ignored"]);
|
|
87
|
-
const WORKFLOW_WARNING_SEVERITIES = new Set(["IMPORTANT", "ACTION_REQUIRED"]);
|
|
88
|
-
const WORKFLOW_WARNING_ID_PATTERN = /^WW-\d+$/;
|
|
89
83
|
|
|
90
84
|
const scriptPath = fileURLToPath(import.meta.url);
|
|
91
|
-
|
|
85
|
+
const defaultRepoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
|
|
92
86
|
|
|
93
87
|
const PLATFORM_ADAPTERS: Record<string, (context: any, shared: any) => any> = {
|
|
94
88
|
"platform-sync": checkPlatformSync,
|
|
@@ -107,8 +101,6 @@ const sharedUtils = {
|
|
|
107
101
|
failResult,
|
|
108
102
|
blockedResult,
|
|
109
103
|
safeStat,
|
|
110
|
-
parseIssueNumber,
|
|
111
|
-
parsePrNumber
|
|
112
104
|
};
|
|
113
105
|
|
|
114
106
|
async function runCheck(type: any, context: any, shared: any): Promise<any> {
|
|
@@ -160,7 +152,7 @@ function checkOrchestrationState({ taskDir }: any): any {
|
|
|
160
152
|
const file = path.join(taskDir, 'orchestration.json');
|
|
161
153
|
const stat = safeStat(file);
|
|
162
154
|
if (!stat?.isFile()) return failResult('orchestration-state', 'orchestration.json is missing');
|
|
163
|
-
let run:
|
|
155
|
+
let run: OrchestrationRun | null;
|
|
164
156
|
try {
|
|
165
157
|
run = readRun(taskDir);
|
|
166
158
|
} catch (error) {
|
|
@@ -192,18 +184,16 @@ function exactText(value: unknown): value is string {
|
|
|
192
184
|
return typeof value === 'string' && value.length > 0 && value.trim() === value;
|
|
193
185
|
}
|
|
194
186
|
|
|
195
|
-
function validateCleanCompletionEvidence(run:
|
|
187
|
+
function validateCleanCompletionEvidence(run: OrchestrationRun): string | null {
|
|
196
188
|
const evidence = run.completionEvidence;
|
|
197
189
|
const shaPattern = /^[0-9a-f]{40}$/i;
|
|
198
190
|
if (
|
|
199
|
-
evidence
|
|
200
|
-
|| !exactText(evidence.observedAt)
|
|
191
|
+
!evidence
|
|
201
192
|
|| Number.isNaN(Date.parse(evidence.observedAt))
|
|
202
193
|
|| !shaPattern.test(evidence.head)
|
|
203
194
|
|| !shaPattern.test(evidence.headTree)
|
|
204
195
|
|| !shaPattern.test(evidence.worktreeTree)
|
|
205
196
|
|| !shaPattern.test(evidence.lastReviewedCommit)
|
|
206
|
-
|| !(evidence.prNumber === null || (Number.isInteger(evidence.prNumber) && evidence.prNumber > 0))
|
|
207
197
|
|| !(evidence.prHead === null || shaPattern.test(evidence.prHead))
|
|
208
198
|
) {
|
|
209
199
|
return 'Clean completion evidence has an invalid structure';
|
|
@@ -220,8 +210,7 @@ function validateCleanCompletionEvidence(run: any): string | null {
|
|
|
220
210
|
|| run.pendingDelegation !== null
|
|
221
211
|
|| run.commitAuthorization?.issuedAt !== null
|
|
222
212
|
|| run.commitAuthorization?.consumedAt !== null
|
|
223
|
-
||
|
|
224
|
-
|| run.receipts.some((receipt: any) => receipt.stage === 'commit')
|
|
213
|
+
|| run.receipts.some((receipt) => receipt.stage === 'commit')
|
|
225
214
|
) {
|
|
226
215
|
return 'Clean completion evidence conflicts with commit delegation state';
|
|
227
216
|
}
|
|
@@ -232,54 +221,16 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
232
221
|
const file = path.join(taskDir, 'orchestration.json');
|
|
233
222
|
const stat = safeStat(file);
|
|
234
223
|
if (!stat?.isFile()) return failResult('orchestration-evidence', 'orchestration.json is missing');
|
|
235
|
-
let run:
|
|
224
|
+
let run: OrchestrationRun | null;
|
|
236
225
|
try {
|
|
237
226
|
run = readRun(taskDir);
|
|
238
227
|
} catch (error) {
|
|
239
228
|
const message = error instanceof OrchestrationStateError ? error.message : String(error);
|
|
240
229
|
return failResult('orchestration-evidence', `Invalid orchestration.json: ${message}`);
|
|
241
230
|
}
|
|
231
|
+
if (!run) return failResult('orchestration-evidence', 'orchestration.json is missing');
|
|
232
|
+
// readRun validates the persisted schema, receipt identities and client provenance.
|
|
242
233
|
const policy = run.modelPolicy;
|
|
243
|
-
if (
|
|
244
|
-
!policy
|
|
245
|
-
|| !exactText(policy.executor?.model)
|
|
246
|
-
|| !exactText(policy.executor?.reasoningEffort)
|
|
247
|
-
|| !exactText(policy.reviewer?.model)
|
|
248
|
-
|| !exactText(policy.reviewer?.reasoningEffort)
|
|
249
|
-
) {
|
|
250
|
-
return failResult('orchestration-evidence', 'Run model policy requires exact executor and reviewer model and effort');
|
|
251
|
-
}
|
|
252
|
-
if (
|
|
253
|
-
!run.modelPolicySource
|
|
254
|
-
|| !['explicit', 'project-config'].includes(run.modelPolicySource.kind)
|
|
255
|
-
|| !exactText(run.modelPolicySource.client)
|
|
256
|
-
|| !exactText(run.modelPolicySource.resolvedAt)
|
|
257
|
-
|| !Array.isArray(run.recoveryHistory)
|
|
258
|
-
) {
|
|
259
|
-
return failResult('orchestration-evidence', 'Run model policy source or recovery history is invalid');
|
|
260
|
-
}
|
|
261
|
-
for (const recovery of run.recoveryHistory) {
|
|
262
|
-
const guards = recovery.guards;
|
|
263
|
-
const validClaudeCodeRecovery = recovery.code === 'CLIENT_CAPABILITY_ENABLED'
|
|
264
|
-
&& recovery.previousStatus === 'paused'
|
|
265
|
-
&& recovery.previousPause?.code === 'ORCHESTRATION_CLIENT_UNSUPPORTED'
|
|
266
|
-
&& recovery.client === 'claude-code'
|
|
267
|
-
&& recovery.resultingStatus === 'running'
|
|
268
|
-
&& exactText(recovery.recoveredAt)
|
|
269
|
-
&& guards?.stepCount === 0
|
|
270
|
-
&& guards?.nextStage === null
|
|
271
|
-
&& guards?.baselineEmpty === true
|
|
272
|
-
&& guards?.receiptCount === 0
|
|
273
|
-
&& guards?.pendingDelegation === false
|
|
274
|
-
&& guards?.commitAuthorizationUnused === true
|
|
275
|
-
&& guards?.completionEvidenceAbsent === true;
|
|
276
|
-
if (!validClaudeCodeRecovery) {
|
|
277
|
-
return failResult('orchestration-evidence', 'Run recovery history contains invalid provenance');
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
if (!Array.isArray(run.receipts)) {
|
|
281
|
-
return failResult('orchestration-evidence', 'Run receipts must be an array');
|
|
282
|
-
}
|
|
283
234
|
if (run.completionEvidence != null) {
|
|
284
235
|
const evidenceError = validateCleanCompletionEvidence(run);
|
|
285
236
|
if (evidenceError) return failResult('orchestration-evidence', evidenceError);
|
|
@@ -309,10 +260,6 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
309
260
|
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has no host-observed actual reasoning effort`);
|
|
310
261
|
}
|
|
311
262
|
}
|
|
312
|
-
// parentId/childId 校验对所有 client 保持统一(不新增分支);spawnMode 检查按 client 判断
|
|
313
|
-
if (!exactText(receipt.parentId) || !exactText(receipt.childId) || receipt.parentId === receipt.childId) {
|
|
314
|
-
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid delegation identity`);
|
|
315
|
-
}
|
|
316
263
|
if (!isClaudeCode && receipt.spawnMode !== 'fresh') {
|
|
317
264
|
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid fresh delegation identity`);
|
|
318
265
|
}
|
|
@@ -338,50 +285,9 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
338
285
|
) {
|
|
339
286
|
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has an unrelated reasoning-effort fallback reason`);
|
|
340
287
|
}
|
|
341
|
-
if (receipt.client === 'codex') {
|
|
342
|
-
const activatedCodex = ['activated', 'stage-completed', 'sealed', 'consumed'].includes(receipt.status);
|
|
343
|
-
const host = receipt.hostEvidence;
|
|
344
|
-
const provenance = receipt.lifecycleProvenance;
|
|
345
|
-
if (
|
|
346
|
-
!provenance
|
|
347
|
-
|| (activatedCodex && (
|
|
348
|
-
host?.kind !== 'codex-lifecycle-v2'
|
|
349
|
-
|| host.protocolVersion !== provenance.protocolVersion
|
|
350
|
-
|| host.hookDefinitionHash !== provenance.hookDefinitionHash
|
|
351
|
-
|| host.hookSource !== provenance.hookSource
|
|
352
|
-
|| host.hookSourcePathDigest !== provenance.hookSourcePathDigest
|
|
353
|
-
|| host.hookSourceHash !== provenance.hookSourceHash
|
|
354
|
-
|| host.capabilitySessionId !== provenance.capabilitySessionId
|
|
355
|
-
|| receipt.parentId !== provenance.capabilitySessionId
|
|
356
|
-
|| host.capabilityTurnId !== provenance.capabilityTurnId
|
|
357
|
-
|| host.controllerInstanceDigest !== provenance.controllerInstanceDigest
|
|
358
|
-
|| host.controlGeneration !== provenance.controlGeneration
|
|
359
|
-
|| host.spawnToolUseId === provenance.capabilityToolUseId
|
|
360
|
-
|| !exactText(host.spawnToolUseId)
|
|
361
|
-
|| !Number.isFinite(Date.parse(host.spawnObservedAt ?? ''))
|
|
362
|
-
|| !Number.isFinite(Date.parse(receipt.spawnDispatchedAt ?? ''))
|
|
363
|
-
|| !Number.isFinite(Date.parse(receipt.activationDeadlineAt ?? ''))
|
|
364
|
-
|| Date.parse(host.spawnObservedAt ?? '') < Date.parse(receipt.spawnDispatchedAt ?? '')
|
|
365
|
-
|| Date.parse(host.spawnObservedAt ?? '') > Date.parse(receipt.activationDeadlineAt ?? '')
|
|
366
|
-
|| !exactText(host.hookDefinitionHash)
|
|
367
|
-
|| !Number.isSafeInteger(host.startRevision)
|
|
368
|
-
|| host.startRevision < 1
|
|
369
|
-
))
|
|
370
|
-
) {
|
|
371
|
-
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid Codex start evidence`);
|
|
372
|
-
}
|
|
373
|
-
if (['sealed', 'consumed'].includes(receipt.status) && (
|
|
374
|
-
!Number.isSafeInteger(host.stopRevision)
|
|
375
|
-
|| host.stopRevision <= host.startRevision
|
|
376
|
-
|| host.consumer !== receipt.id
|
|
377
|
-
|| !exactText(host.consumedAt)
|
|
378
|
-
)) {
|
|
379
|
-
return failResult('orchestration-evidence', `Receipt '${receipt.id ?? '(unknown)'}' has invalid Codex consumed stop evidence`);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
288
|
}
|
|
383
289
|
}
|
|
384
|
-
if (run.receipts.some((receipt
|
|
290
|
+
if (run.receipts.some((receipt) => receipt.status !== 'consumed')) {
|
|
385
291
|
return failResult('orchestration-evidence', 'Historical receipts must be consumed');
|
|
386
292
|
}
|
|
387
293
|
return passResult('orchestration-evidence', 'Persisted orchestration model and delegation evidence is internally consistent');
|
|
@@ -389,7 +295,7 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
389
295
|
|
|
390
296
|
// === Check Functions ===
|
|
391
297
|
|
|
392
|
-
function checkTaskMeta({ taskDir, config }: any): any {
|
|
298
|
+
function checkTaskMeta({ taskDir, config, repositoryRoot }: any): any {
|
|
393
299
|
const task = loadTask(taskDir);
|
|
394
300
|
if (!task.ok) {
|
|
395
301
|
return failResult("task-meta", task.message);
|
|
@@ -427,14 +333,15 @@ function checkTaskMeta({ taskDir, config }: any): any {
|
|
|
427
333
|
}
|
|
428
334
|
}
|
|
429
335
|
|
|
430
|
-
const branchValidationError = validateTaskBranch(metadata);
|
|
336
|
+
const branchValidationError = validateTaskBranch(metadata, repositoryRoot);
|
|
431
337
|
if (branchValidationError) {
|
|
432
338
|
return failResult("task-meta", branchValidationError);
|
|
433
339
|
}
|
|
434
340
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
341
|
+
try {
|
|
342
|
+
parseWorkflowWarnings(task.content);
|
|
343
|
+
} catch (error) {
|
|
344
|
+
return failResult("task-meta", `Invalid Workflow Warnings: ${error instanceof Error ? error.message : String(error)}`);
|
|
438
345
|
}
|
|
439
346
|
|
|
440
347
|
const expectedStep = config.expected_step;
|
|
@@ -453,8 +360,8 @@ function checkTaskMeta({ taskDir, config }: any): any {
|
|
|
453
360
|
);
|
|
454
361
|
}
|
|
455
362
|
|
|
456
|
-
if (config.
|
|
457
|
-
return failResult("task-meta", "Expected a valid
|
|
363
|
+
if (config.require_platform_issue_identity && !taskIssueIdentity(metadata)) {
|
|
364
|
+
return failResult("task-meta", "Expected a valid platform_issue_identity in task metadata");
|
|
458
365
|
}
|
|
459
366
|
|
|
460
367
|
if (config.require_completed_at && isBlank(metadata.completed_at)) {
|
|
@@ -552,12 +459,12 @@ async function checkRequiredPrDelivery({ taskDir, repositoryRoot, mode }: any):
|
|
|
552
459
|
return passResult('required-pr-delivery', `Pull request delivery policy satisfied (${status})`);
|
|
553
460
|
}
|
|
554
461
|
|
|
555
|
-
function validateTaskBranch(metadata: any): any {
|
|
462
|
+
function validateTaskBranch(metadata: any, repoRoot: string): any {
|
|
556
463
|
if (isBlank(metadata.branch)) {
|
|
557
464
|
return null;
|
|
558
465
|
}
|
|
559
466
|
|
|
560
|
-
const projectName = loadProjectName();
|
|
467
|
+
const projectName = loadProjectName(repoRoot);
|
|
561
468
|
const expectedPrefix = projectName ? `${projectName}-${metadata.type}-` : "";
|
|
562
469
|
|
|
563
470
|
if (expectedPrefix && !String(metadata.branch).startsWith(expectedPrefix)) {
|
|
@@ -572,7 +479,7 @@ function validateTaskBranch(metadata: any): any {
|
|
|
572
479
|
return null;
|
|
573
480
|
}
|
|
574
481
|
|
|
575
|
-
function loadProjectName(): any {
|
|
482
|
+
function loadProjectName(repoRoot: string): any {
|
|
576
483
|
const configPath = path.join(repoRoot, ".agents", ".airc.json");
|
|
577
484
|
if (!fs.existsSync(configPath)) {
|
|
578
485
|
return "";
|
|
@@ -743,31 +650,17 @@ function checkImplementationInput({ taskDir, artifactFile }: any): any {
|
|
|
743
650
|
const artifactPath = path.join(taskDir, artifactFile);
|
|
744
651
|
if (!safeStat(artifactPath)?.isFile()) return failResult("implementation-input", `Artifact not found: ${artifactFile}`);
|
|
745
652
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
const expected = ["id", "ledger_id", "decision_evidence", "stage", "needs_implementation", "decided_at", "status", "consumed_by"];
|
|
752
|
-
if (table.length < 2 || JSON.stringify(cells(table[0])) !== JSON.stringify(expected)) {
|
|
753
|
-
return failResult("implementation-input", "Implementation Inputs table schema is invalid");
|
|
754
|
-
}
|
|
755
|
-
const seen = new Set();
|
|
756
|
-
for (const line of table.slice(2)) {
|
|
757
|
-
const row = cells(line);
|
|
758
|
-
if (row.length !== 8 || !/^II-[1-9]\d*$/.test(row[0]) || seen.has(row[0])) {
|
|
759
|
-
return failResult("implementation-input", "Implementation Inputs table contains an invalid or duplicate id");
|
|
760
|
-
}
|
|
761
|
-
seen.add(row[0]);
|
|
762
|
-
rows.push({ id: row[0], ledgerId: row[1], evidence: row[2], stage: row[3], needs: row[4], status: row[6], consumedBy: row[7] });
|
|
763
|
-
}
|
|
653
|
+
let rows: ImplementationInput[];
|
|
654
|
+
try {
|
|
655
|
+
rows = parseImplementationInputs(task.content).rows;
|
|
656
|
+
} catch (error) {
|
|
657
|
+
return failResult("implementation-input", `Invalid Implementation Inputs: ${error instanceof Error ? error.message : String(error)}`);
|
|
764
658
|
}
|
|
765
659
|
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
});
|
|
660
|
+
const doneActions = (inspectActivityLog(task.content).section?.entries ?? [])
|
|
661
|
+
.filter((entry) => !ACTIVITY_LOG_STARTED_RE.test(entry.step))
|
|
662
|
+
.map((entry) => entry.step)
|
|
663
|
+
.filter((step) => /^(?:Code Task|Code) \(Round \d+/.test(step));
|
|
771
664
|
const latestAction = doneActions.at(-1) || "";
|
|
772
665
|
const actionDecision = /(?:Code Task|Code) \(Round \d+, decision (II-[1-9]\d*)\)/.exec(latestAction)?.[1] || null;
|
|
773
666
|
const report = fs.readFileSync(artifactPath, "utf8");
|
|
@@ -794,10 +687,10 @@ function checkImplementationInput({ taskDir, artifactFile }: any): any {
|
|
|
794
687
|
const matches = rows.filter((row) => row.id === actionDecision);
|
|
795
688
|
if (matches.length !== 1) return failResult("implementation-input", `${actionDecision} is missing or duplicated in task table`);
|
|
796
689
|
const row = matches[0]!;
|
|
797
|
-
if (row.stage !== "code" || row.
|
|
690
|
+
if (row.stage !== "code" || !row.needsImplementation || row.status !== "consumed" || row.consumedBy !== artifactFile || !row.decisionEvidence) {
|
|
798
691
|
return failResult("implementation-input", `${actionDecision} is not a consumed input for ${artifactFile}`);
|
|
799
692
|
}
|
|
800
|
-
if (reportLedger !== row.ledgerId || reportEvidence !== row.
|
|
693
|
+
if (reportLedger !== row.ledgerId || reportEvidence !== row.decisionEvidence) {
|
|
801
694
|
return failResult("implementation-input", `${actionDecision} report identity does not match task table evidence`);
|
|
802
695
|
}
|
|
803
696
|
return passResult("implementation-input", `${actionDecision} matches Activity Log, report, and task table`);
|
|
@@ -809,19 +702,11 @@ function checkActivityLog({ taskDir, config }: any): any {
|
|
|
809
702
|
return failResult("activity-log", task.message);
|
|
810
703
|
}
|
|
811
704
|
|
|
812
|
-
const
|
|
813
|
-
if (!
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
const entries = logSection
|
|
818
|
-
.split(/\r?\n/)
|
|
819
|
-
.map((line: any) => line.trim())
|
|
820
|
-
.filter((line: any) => line.startsWith("- "));
|
|
821
|
-
|
|
822
|
-
if (entries.length === 0) {
|
|
823
|
-
return failResult("activity-log", "Activity Log has no entries");
|
|
824
|
-
}
|
|
705
|
+
const { section, invalidEntries } = inspectActivityLog(task.content);
|
|
706
|
+
if (!section) return failResult("activity-log", "Activity Log section not found or ambiguous");
|
|
707
|
+
if (invalidEntries.length) return failResult("activity-log", `Invalid Activity Log entry format: ${invalidEntries[0]}`);
|
|
708
|
+
const entries = section.entries;
|
|
709
|
+
if (entries.length === 0) return failResult("activity-log", "Activity Log has no entries");
|
|
825
710
|
|
|
826
711
|
let previousTimestamp = "";
|
|
827
712
|
let latestAction = "";
|
|
@@ -829,12 +714,8 @@ function checkActivityLog({ taskDir, config }: any): any {
|
|
|
829
714
|
const doneActions: string[] = [];
|
|
830
715
|
|
|
831
716
|
for (const entry of entries) {
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
return failResult("activity-log", `Invalid Activity Log entry format: ${entry}`);
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
const [, timestamp, action] = match;
|
|
717
|
+
if (!entry.note.trim()) return failResult("activity-log", "Activity Log entry note is required");
|
|
718
|
+
const { time: timestamp, step: action } = entry;
|
|
838
719
|
if (previousTimestamp && timestamp < previousTimestamp) {
|
|
839
720
|
return failResult("activity-log", "Activity Log timestamps are not in ascending order");
|
|
840
721
|
}
|
|
@@ -906,118 +787,7 @@ function checkCompletionChecklist({ taskDir, config }: any): any {
|
|
|
906
787
|
return passResult("completion-checklist", `Completion Checklist valid (${items.length} items checked)`);
|
|
907
788
|
}
|
|
908
789
|
|
|
909
|
-
function
|
|
910
|
-
let value = String(line || "").trim();
|
|
911
|
-
if (!value.startsWith("|")) {
|
|
912
|
-
return [];
|
|
913
|
-
}
|
|
914
|
-
value = value.replace(/^\|/, "").replace(/\|$/, "");
|
|
915
|
-
|
|
916
|
-
const cells = [];
|
|
917
|
-
let cell = "";
|
|
918
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
919
|
-
const char = value[index];
|
|
920
|
-
if (char === "|" && !isEscapedAt(value, index)) {
|
|
921
|
-
cells.push(unescapeMarkdownTableCell(cell.trim()));
|
|
922
|
-
cell = "";
|
|
923
|
-
continue;
|
|
924
|
-
}
|
|
925
|
-
cell += char;
|
|
926
|
-
}
|
|
927
|
-
cells.push(unescapeMarkdownTableCell(cell.trim()));
|
|
928
|
-
return cells;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
function unescapeMarkdownTableCell(value: any): any {
|
|
932
|
-
let output = "";
|
|
933
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
934
|
-
const char = value[index];
|
|
935
|
-
const next = value[index + 1];
|
|
936
|
-
if (char === "\\" && (next === "\\" || next === "|")) {
|
|
937
|
-
output += next;
|
|
938
|
-
index += 1;
|
|
939
|
-
continue;
|
|
940
|
-
}
|
|
941
|
-
output += char;
|
|
942
|
-
}
|
|
943
|
-
return output;
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
function isEscapedAt(value: any, index: any): any {
|
|
947
|
-
let backslashes = 0;
|
|
948
|
-
for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
|
|
949
|
-
backslashes += 1;
|
|
950
|
-
}
|
|
951
|
-
return backslashes % 2 === 1;
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
function parseWorkflowWarningRows(section: any): any {
|
|
955
|
-
const rows = [];
|
|
956
|
-
for (const rawLine of String(section || "").split(/\r?\n/)) {
|
|
957
|
-
const cells = splitMarkdownTableRow(rawLine);
|
|
958
|
-
if (cells.length === 0) {
|
|
959
|
-
continue;
|
|
960
|
-
}
|
|
961
|
-
if ((cells[0] || "").toLowerCase() === "id") {
|
|
962
|
-
continue;
|
|
963
|
-
}
|
|
964
|
-
if (cells.every((cell: any) => /^:?-{3,}:?$/.test(cell))) {
|
|
965
|
-
continue;
|
|
966
|
-
}
|
|
967
|
-
rows.push(cells);
|
|
968
|
-
}
|
|
969
|
-
return rows;
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
function validateWorkflowWarnings(content: any): any {
|
|
973
|
-
const section = getSectionContent(content, WORKFLOW_WARNING_SECTION_NAMES);
|
|
974
|
-
if (!section.trim()) {
|
|
975
|
-
return [];
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
const rows = parseWorkflowWarningRows(section);
|
|
979
|
-
const errors = [];
|
|
980
|
-
for (const cells of rows) {
|
|
981
|
-
if (cells.length < 11) {
|
|
982
|
-
errors.push(`malformed row (expected 11 columns): ${cells.join(" | ")}`);
|
|
983
|
-
continue;
|
|
984
|
-
}
|
|
985
|
-
const [id, time, step, severity, code, status, target, message, action, resolvedAt, resolution] = cells;
|
|
986
|
-
if (!WORKFLOW_WARNING_ID_PATTERN.test(id)) {
|
|
987
|
-
errors.push(`${id || "(empty id)"}: invalid id`);
|
|
988
|
-
}
|
|
989
|
-
if (!DATE_TIME_PATTERN.test(time)) {
|
|
990
|
-
errors.push(`${id}: invalid time '${time}'`);
|
|
991
|
-
}
|
|
992
|
-
if (isBlank(step)) {
|
|
993
|
-
errors.push(`${id}: step is required`);
|
|
994
|
-
}
|
|
995
|
-
if (!WORKFLOW_WARNING_SEVERITIES.has(severity)) {
|
|
996
|
-
errors.push(`${id}: illegal severity '${severity}'`);
|
|
997
|
-
}
|
|
998
|
-
if (isBlank(code)) {
|
|
999
|
-
errors.push(`${id}: code is required`);
|
|
1000
|
-
}
|
|
1001
|
-
if (!WORKFLOW_WARNING_STATUSES.has(status)) {
|
|
1002
|
-
errors.push(`${id}: illegal status '${status}'`);
|
|
1003
|
-
}
|
|
1004
|
-
if (isBlank(target)) {
|
|
1005
|
-
errors.push(`${id}: target is required`);
|
|
1006
|
-
}
|
|
1007
|
-
if (isBlank(message)) {
|
|
1008
|
-
errors.push(`${id}: message is required`);
|
|
1009
|
-
}
|
|
1010
|
-
if (status === "open" && isBlank(action)) {
|
|
1011
|
-
errors.push(`${id}: open warning requires action`);
|
|
1012
|
-
}
|
|
1013
|
-
if ((status === "resolved" || status === "ignored") && (isBlank(resolvedAt) || isBlank(resolution))) {
|
|
1014
|
-
errors.push(`${id}: ${status} warning requires resolved_at and resolution`);
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
return errors;
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
function resolveReviewSetting(config: any, key: any, fallback: any): any {
|
|
790
|
+
function resolveReviewSetting(config: any, key: any, fallback: any, repoRoot: string): any {
|
|
1021
791
|
if (config && config[key] !== undefined && config[key] !== null) {
|
|
1022
792
|
return config[key];
|
|
1023
793
|
}
|
|
@@ -1028,7 +798,7 @@ function resolveReviewSetting(config: any, key: any, fallback: any): any {
|
|
|
1028
798
|
return fallback;
|
|
1029
799
|
}
|
|
1030
800
|
|
|
1031
|
-
function checkReviewLedger({ taskDir, config }: any): any {
|
|
801
|
+
function checkReviewLedger({ taskDir, config, repositoryRoot }: any): any {
|
|
1032
802
|
const task = loadTask(taskDir);
|
|
1033
803
|
if (!task.ok) {
|
|
1034
804
|
return failResult("review-ledger", task.message);
|
|
@@ -1038,9 +808,7 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
1038
808
|
try {
|
|
1039
809
|
const ledger = parseLedgerDocument(task.content);
|
|
1040
810
|
if (!ledger.present) return failResult("review-ledger", `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`);
|
|
1041
|
-
rows = ledger.rows
|
|
1042
|
-
row.id, row.stage, row.round, row.severity, row.status, row.evidence
|
|
1043
|
-
]);
|
|
811
|
+
rows = ledger.rows;
|
|
1044
812
|
} catch (error) {
|
|
1045
813
|
return failResult("review-ledger", `Invalid disagreement ledger: ${error instanceof Error ? error.message : String(error)}`);
|
|
1046
814
|
}
|
|
@@ -1049,17 +817,12 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
1049
817
|
}
|
|
1050
818
|
|
|
1051
819
|
const stageScope = Array.isArray(config.stage_scope) ? config.stage_scope : null;
|
|
1052
|
-
const maxRounds = Number(resolveReviewSetting(config, "maxHandshakeRounds", DEFAULT_MAX_HANDSHAKE_ROUNDS));
|
|
820
|
+
const maxRounds = Number(resolveReviewSetting(config, "maxHandshakeRounds", DEFAULT_MAX_HANDSHAKE_ROUNDS, repositoryRoot));
|
|
1053
821
|
const problems = [];
|
|
1054
822
|
let inScopeCount = 0;
|
|
1055
823
|
|
|
1056
|
-
for (const
|
|
1057
|
-
|
|
1058
|
-
problems.push(`malformed row (expected 6 columns): ${cells.join(" | ")}`);
|
|
1059
|
-
continue;
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
const [id, stage, roundRaw, , status, evidence] = cells;
|
|
824
|
+
for (const row of rows) {
|
|
825
|
+
const { id, stage, round: roundRaw, status, evidence } = row;
|
|
1063
826
|
const stageScoped = stageScope ? stageScope.includes(stage) : true;
|
|
1064
827
|
// post-review-commit exemption rows are consumed by the post-review-commit
|
|
1065
828
|
// check, not enforced here.
|
|
@@ -1071,8 +834,9 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
1071
834
|
}
|
|
1072
835
|
inScopeCount += 1;
|
|
1073
836
|
|
|
1074
|
-
|
|
1075
|
-
|
|
837
|
+
const invalid = validateLedgerRows([row]);
|
|
838
|
+
if (invalid) {
|
|
839
|
+
problems.push(`${invalid.code}: ${invalid.message}`);
|
|
1076
840
|
continue;
|
|
1077
841
|
}
|
|
1078
842
|
if (status !== "open" && evidence === "") {
|
|
@@ -1082,12 +846,12 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
1082
846
|
if (
|
|
1083
847
|
Number.isFinite(round) &&
|
|
1084
848
|
round >= maxRounds &&
|
|
1085
|
-
!
|
|
849
|
+
!LEDGER_TERMINAL.has(status!) &&
|
|
1086
850
|
status !== "needs-human-decision"
|
|
1087
851
|
) {
|
|
1088
852
|
problems.push(`${id}: round ${round} reached limit ${maxRounds} without convergence; escalate to needs-human-decision`);
|
|
1089
853
|
}
|
|
1090
|
-
if (!
|
|
854
|
+
if (!LEDGER_TERMINAL.has(status!)) {
|
|
1091
855
|
problems.push(`${id}: unresolved (status '${status}')`);
|
|
1092
856
|
}
|
|
1093
857
|
}
|
|
@@ -1100,7 +864,7 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
1100
864
|
return passResult("review-ledger", `Disagreement ledger clean (${inScopeCount} in-scope entries terminal${scopeLabel})`);
|
|
1101
865
|
}
|
|
1102
866
|
|
|
1103
|
-
function checkManualValidation({ taskDir }: any): any {
|
|
867
|
+
async function checkManualValidation({ taskDir, repositoryRoot }: any): Promise<any> {
|
|
1104
868
|
// 1. Latest review-code artifact; none -> pass (no review, check not applicable).
|
|
1105
869
|
const review = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
1106
870
|
if (!review.ok) {
|
|
@@ -1132,15 +896,23 @@ function checkManualValidation({ taskDir }: any): any {
|
|
|
1132
896
|
const artifactName = path.basename(resolved.path);
|
|
1133
897
|
const task = loadTask(taskDir);
|
|
1134
898
|
if (!task.ok) return failResult("manual-validation", task.message);
|
|
1135
|
-
const
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
);
|
|
1139
|
-
if (!
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
899
|
+
const completion = readManualValidationCompletion(taskDir, {
|
|
900
|
+
taskId: task.metadata.id,
|
|
901
|
+
artifact: artifactName
|
|
902
|
+
});
|
|
903
|
+
if (!completion.ok) {
|
|
904
|
+
const source = completion.error.code.startsWith('MANUAL_VALIDATION_RECEIPT_') ? 'receipt' : 'transaction';
|
|
905
|
+
return failResult("manual-validation", `Manual validation ${source} is unavailable: ${completion.error.message}`);
|
|
906
|
+
}
|
|
907
|
+
const { receipt, transaction } = completion.value;
|
|
908
|
+
if (transaction.phase !== "committed" || !transaction.eventAppended || !transaction.postWriteVerified) {
|
|
909
|
+
return failResult("manual-validation", "Manual validation transaction has not reached the committed post-write-verified state");
|
|
910
|
+
}
|
|
911
|
+
if (transaction.pendingSummaryDigest !== receipt.pendingSummaryDigest || transaction.finalSummaryDigest !== receipt.finalSummaryDigest) {
|
|
912
|
+
return failResult("manual-validation", "Manual validation summary digests do not match the committed receipt");
|
|
913
|
+
}
|
|
914
|
+
if (sha256File(resolved.path) !== receipt.artifactSha256) {
|
|
915
|
+
return failResult("manual-validation", `Manual validation artifact digest does not match the receipt for ${artifactName}`);
|
|
1144
916
|
}
|
|
1145
917
|
// 6. Timing correlation (PL-3 fix, PL-4 corrected): the completion entry must
|
|
1146
918
|
// sit AFTER the latest review-code round's completion entry in the
|
|
@@ -1149,28 +921,32 @@ function checkManualValidation({ taskDir }: any): any {
|
|
|
1149
921
|
// which indexOf never matches). Not reusing completed.exec().index: exec
|
|
1150
922
|
// anchors to the first '**Complete Manual Validation**' heading, which can
|
|
1151
923
|
// belong to an earlier round's entry and misorder the standard path.
|
|
1152
|
-
const
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
);
|
|
924
|
+
const inspectedLog = inspectActivityLog(task.content);
|
|
925
|
+
if (!inspectedLog.section) return failResult("manual-validation", "Activity Log is missing or invalid");
|
|
926
|
+
const reviewDoneIndex = inspectedLog.section.entries.findIndex((entry) => entry.step === `Review Code (Round ${review.round})`);
|
|
927
|
+
const completedIndex = inspectedLog.section.entries.findIndex((entry) => entry.step === "Complete Manual Validation"
|
|
928
|
+
&& entry.note.includes(`Manual validation passed → ${artifactName};`)
|
|
929
|
+
&& entry.note.includes(`transaction=${receipt.transactionId};`)
|
|
930
|
+
&& entry.note.includes(`receipt=${receipt.receiptDigest};`)
|
|
931
|
+
&& entry.note.includes(`head=${receipt.prHeadSha}`));
|
|
932
|
+
if (reviewDoneIndex === -1) return failResult("manual-validation", `Latest review-code (round ${review.round}) completion entry is missing from the Activity Log`);
|
|
933
|
+
if (completedIndex === -1) return failResult("manual-validation", `Committed manual validation completion is not recorded for ${artifactName}`);
|
|
934
|
+
if (completedIndex < reviewDoneIndex) return failResult("manual-validation", `Latest review-code (round ${review.round}) came after the manual validation completion recorded for ${artifactName}`);
|
|
935
|
+
|
|
936
|
+
const fact = readPrDeliveryFact(task.metadata);
|
|
937
|
+
if (fact.status === "invalid") return failResult("manual-validation", fact.error.message);
|
|
938
|
+
if (fact.status === "valid" && fact.fact.state === "bound") {
|
|
939
|
+
const inspected = await inspectPlatformPullRequest(task.metadata.id, { cwd: repositoryRoot });
|
|
940
|
+
if (!inspected.pullRequest) return failResult("manual-validation", inspected.error?.message ?? "canonical pull-request head is unavailable");
|
|
941
|
+
if (inspected.pullRequest.head.sha !== receipt.prHeadSha) return failResult("manual-validation", "manual validation receipt is stale for the current pull-request head");
|
|
942
|
+
const summary = await summaryCommentState(task.metadata.id, { cwd: repositoryRoot });
|
|
943
|
+
if (!summary.comment) return failResult("manual-validation", "canonical pull-request summary comment is unavailable");
|
|
944
|
+
if (!manualValidationFinalSummaryProjectionMatches(summary.comment.body, receipt)) return failResult("manual-validation", "canonical pull-request summary does not match the committed manual validation projection");
|
|
1169
945
|
}
|
|
1170
|
-
return passResult("manual-validation", `Manual validation completed → ${artifactName}`);
|
|
946
|
+
return passResult("manual-validation", `Manual validation completed → ${artifactName} (committed receipt and post-write verification)`);
|
|
1171
947
|
}
|
|
1172
948
|
|
|
1173
|
-
async function checkPostReviewCommit({ taskDir, config }: any): Promise<any> {
|
|
949
|
+
async function checkPostReviewCommit({ taskDir, config, repositoryRoot }: any): Promise<any> {
|
|
1174
950
|
const reviewArtifact = findAuthoritativeReviewCodeArtifact(taskDir);
|
|
1175
951
|
if (!reviewArtifact.ok) {
|
|
1176
952
|
if (reviewArtifact.error) return failResult("post-review-commit", `Review-code artifact is unavailable: ${reviewArtifact.error}`);
|
|
@@ -1190,7 +966,7 @@ async function checkPostReviewCommit({ taskDir, config }: any): Promise<any> {
|
|
|
1190
966
|
if (factRead.status === 'invalid') return failResult("post-review-commit", factRead.error.message);
|
|
1191
967
|
const fact = factRead.status === 'valid' ? factRead.fact : null;
|
|
1192
968
|
const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
|
|
1193
|
-
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(
|
|
969
|
+
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repositoryRoot));
|
|
1194
970
|
const hasPullRequest = fact?.state === 'bound';
|
|
1195
971
|
let inspected: Awaited<ReturnType<typeof inspectPlatformPullRequest>> | null = null;
|
|
1196
972
|
if (hasPullRequest) {
|
|
@@ -1364,7 +1140,7 @@ function resolvePostReviewExemption(content: string):
|
|
|
1364
1140
|
}
|
|
1365
1141
|
}
|
|
1366
1142
|
|
|
1367
|
-
function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
1143
|
+
function checkReviewFact({ taskDir, artifactFile, repositoryRoot }: any): any {
|
|
1368
1144
|
const resolvedArtifact = resolveArtifactPath(
|
|
1369
1145
|
taskDir,
|
|
1370
1146
|
"review-code.md|review-code-r{N}.md",
|
|
@@ -1448,7 +1224,7 @@ function checkReviewFact({ taskDir, artifactFile }: any): any {
|
|
|
1448
1224
|
mode: "worktree",
|
|
1449
1225
|
baseline,
|
|
1450
1226
|
diffBase,
|
|
1451
|
-
globs: resolvePostReviewGlobs({}, loadPostReviewConfig(
|
|
1227
|
+
globs: resolvePostReviewGlobs({}, loadPostReviewConfig(repositoryRoot))
|
|
1452
1228
|
});
|
|
1453
1229
|
} catch {
|
|
1454
1230
|
return blockedResult(
|
|
@@ -1575,46 +1351,13 @@ function resolveArtifactPath(taskDir: any, filePattern: any, artifactFile: any):
|
|
|
1575
1351
|
return { ok: true, path: path.join(taskDir, matches[0]!.fileName) };
|
|
1576
1352
|
}
|
|
1577
1353
|
|
|
1578
|
-
function getSectionContent(content:
|
|
1579
|
-
const
|
|
1580
|
-
|
|
1581
|
-
function visibleHeadings(): any {
|
|
1582
|
-
const headings = [];
|
|
1583
|
-
let fence = null;
|
|
1584
|
-
for (let index = 0; index < lines.length; index += 1) {
|
|
1585
|
-
const line = lines[index];
|
|
1586
|
-
if (fence) {
|
|
1587
|
-
const closer = line.match(/^ {0,3}(`+|~+)\s*$/);
|
|
1588
|
-
if (closer && closer[1][0] === fence.character && closer[1].length >= fence.length) {
|
|
1589
|
-
fence = null;
|
|
1590
|
-
}
|
|
1591
|
-
continue;
|
|
1592
|
-
}
|
|
1593
|
-
const opener = line.match(/^ {0,3}(`{3,}|~{3,})(?:[^`~].*)?$/);
|
|
1594
|
-
if (opener) {
|
|
1595
|
-
fence = { character: opener[1][0], length: opener[1].length };
|
|
1596
|
-
continue;
|
|
1597
|
-
}
|
|
1598
|
-
if (line.startsWith("## ")) {
|
|
1599
|
-
headings.push({ index, text: line.trim() });
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
return headings;
|
|
1603
|
-
}
|
|
1604
|
-
|
|
1605
|
-
const headings = visibleHeadings();
|
|
1606
|
-
|
|
1354
|
+
function getSectionContent(content: string, names: readonly string[]): string {
|
|
1355
|
+
const headings = scanVisibleMarkdown(content).headings.filter((heading) => heading.level === 2);
|
|
1607
1356
|
for (const name of names) {
|
|
1608
|
-
const
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
continue;
|
|
1612
|
-
}
|
|
1613
|
-
const startIndex = headings[position]!.index;
|
|
1614
|
-
const endIndex = headings[position + 1]?.index ?? lines.length;
|
|
1615
|
-
return lines.slice(startIndex + 1, endIndex).join("\n").trim();
|
|
1357
|
+
const position = headings.findIndex((heading) => heading.text === name);
|
|
1358
|
+
if (position === -1) continue;
|
|
1359
|
+
return content.slice(headings[position]!.end + 1, headings[position + 1]?.start ?? content.length).replace(/\r\n/g, "\n").trim();
|
|
1616
1360
|
}
|
|
1617
|
-
|
|
1618
1361
|
return "";
|
|
1619
1362
|
}
|
|
1620
1363
|
|
|
@@ -1632,19 +1375,6 @@ function getCheckedRequirements(content: any): any {
|
|
|
1632
1375
|
.map((match: any) => match[1].trim());
|
|
1633
1376
|
}
|
|
1634
1377
|
|
|
1635
|
-
function parseIssueNumber(value: any): any {
|
|
1636
|
-
if (isBlank(value) || value === "N/A") {
|
|
1637
|
-
return null;
|
|
1638
|
-
}
|
|
1639
|
-
|
|
1640
|
-
const match = String(value).match(/\d+/);
|
|
1641
|
-
return match ? Number(match[0]) : null;
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
function parsePrNumber(value: any): any {
|
|
1645
|
-
return parseIssueNumber(value);
|
|
1646
|
-
}
|
|
1647
|
-
|
|
1648
1378
|
// === Utilities ===
|
|
1649
1379
|
|
|
1650
1380
|
function normalizeContent(text: any): any {
|
|
@@ -1742,14 +1472,14 @@ function isBlank(value: any): any {
|
|
|
1742
1472
|
}
|
|
1743
1473
|
|
|
1744
1474
|
async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks: requestedChecks, repositoryRoot }: any): Promise<any> {
|
|
1745
|
-
|
|
1746
|
-
|
|
1475
|
+
let repoRoot = repositoryRoot ? path.resolve(repositoryRoot) : defaultRepoRoot;
|
|
1476
|
+
if (!repositoryRoot) {
|
|
1747
1477
|
let cursor = path.resolve(taskDir);
|
|
1748
1478
|
while (path.dirname(cursor) !== cursor && !fs.existsSync(path.join(cursor, ".agents"))) cursor = path.dirname(cursor);
|
|
1749
1479
|
if (fs.existsSync(path.join(cursor, ".agents"))) repoRoot = cursor;
|
|
1750
1480
|
}
|
|
1751
1481
|
const verifyConfig = loadVerificationConfig(repoRoot, skillName);
|
|
1752
|
-
const shared = { ...sharedUtils, repoRoot };
|
|
1482
|
+
const shared: VerificationShared = { ...sharedUtils, repoRoot };
|
|
1753
1483
|
if (mode === "gate") {
|
|
1754
1484
|
const checks = [];
|
|
1755
1485
|
for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {
|