@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
package/dist/lib/task/events.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { appendActivityEntry, locateActivityLog, pairEntries, startedBackedRows } from './activity-log.js';
|
|
4
|
-
import { buildArtifactLinkSection,
|
|
4
|
+
import { buildArtifactLinkSection, inspectArtifactDirectory, parseReviewedInputReference, parseCodePlanInputReference, resolveArtifactContext, validateCompletedArtifact } from './artifact-lifecycle.js';
|
|
5
|
+
import { artifactName, parseArtifactName } from './artifact-name.js';
|
|
5
6
|
import { ArtifactReceiptError, parseArtifactReceipts, sha256File, upsertArtifactReceipt } from './artifact-receipts.js';
|
|
6
7
|
import { parseTypedTaskFrontmatter } from './frontmatter.js';
|
|
7
8
|
import { consumeImplementationInput, IMPLEMENTATION_INPUT_ALIASES, parseImplementationInputs, renderImplementationInputs } from './implementation-inputs.js';
|
|
@@ -14,11 +15,16 @@ import { commitOrchestrationStageCompletion } from './orchestration.js';
|
|
|
14
15
|
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
|
|
15
16
|
import { captureTaskWriteMetadata, writeTask } from './write.js';
|
|
16
17
|
import { allowsManualOverride } from './guard-override.js';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
18
|
+
import { consumeLocalArtifactFinalizationIntent, readLocalArtifactFinalizationIntent, validateLocalArtifact } from './local-artifact-finalization.js';
|
|
19
|
+
import { writeArtifactRepairIntent } from './artifact-repair-intent.js';
|
|
19
20
|
import { buildLifecycleFacts, canStart } from './capabilities.js';
|
|
20
21
|
import { createInvalidationOperation, invalidationMutation, parseInvalidationDocument, targetIdFor, upsertInvalidation } from './invalidation.js';
|
|
21
22
|
import { consumeReworkIntents, parseReworkIntentDocument, reworkIntentMutation, supersedeReworkIntents } from './rework-intent.js';
|
|
23
|
+
import { ARTIFACT_FAMILIES, expectedQualificationRelations, parseQualificationAudit, parseTaskQualification, upstreamArtifactDigest, validateQualificationAudit } from './qualification-audit.js';
|
|
24
|
+
import { getArtifactSchema } from './artifact-schema.js';
|
|
25
|
+
import { inspectArtifactContract } from './artifact-operations.js';
|
|
26
|
+
import { consumeLifecycleRecoveryAttestation, lifecycleRecoveryAttestationDigest, validateLifecycleRecoveryAttestation } from './control-authority.js';
|
|
27
|
+
import { readManualValidationCompletion } from './manual-validation-completion.js';
|
|
22
28
|
const eventCatalog = [
|
|
23
29
|
'analyze.started', 'analyze.awaiting-input', 'analyze.completed',
|
|
24
30
|
'review-analysis.started', 'review-analysis.completed',
|
|
@@ -44,36 +50,11 @@ const SCHEMAS = {
|
|
|
44
50
|
'code.completed': { required: ['artifact', 'artifactSha256', 'semanticDigest'], optional: ['round', 'fixFor', 'implementationInput', 'filesModified', 'testsPassed', 'blockers', 'major', 'minor', 'manualValidation', 'orchestrated'] },
|
|
45
51
|
'review-code.started': { optional: ['round'] },
|
|
46
52
|
'review-code.completed': { required: ['artifact', 'verdict', 'blockers', 'major', 'minor', 'manualValidation'], optional: ['round', 'orchestrated'] },
|
|
47
|
-
'manual-validation.started': { optional: ['round'] },
|
|
48
|
-
'manual-validation.completed': { required: ['artifact', 'summaryResult'], optional: ['round'] },
|
|
53
|
+
'manual-validation.started': { optional: ['round', 'transactionId'] },
|
|
54
|
+
'manual-validation.completed': { required: ['artifact', 'summaryResult', 'transactionId', 'receiptDigest', 'prHeadSha'], optional: ['round'] },
|
|
49
55
|
'validation-run.started': { optional: ['round'] },
|
|
50
56
|
'validation-run.completed': { required: ['artifact'], optional: ['round'] }
|
|
51
57
|
};
|
|
52
|
-
function localArtifactValidationConfig(repoRoot, family) {
|
|
53
|
-
const fallback = {
|
|
54
|
-
requiredSections: LOCAL_ARTIFACT_REQUIRED_SECTIONS[family],
|
|
55
|
-
requiredPatterns: LOCAL_ARTIFACT_REQUIRED_PATTERNS
|
|
56
|
-
};
|
|
57
|
-
const skillName = family === 'analysis' ? 'analyze-task' : family === 'plan' ? 'plan-task' : 'code-task';
|
|
58
|
-
try {
|
|
59
|
-
const artifact = loadVerificationConfig(repoRoot, skillName).checks.artifact;
|
|
60
|
-
if (!artifact || typeof artifact !== 'object' || Array.isArray(artifact))
|
|
61
|
-
return fallback;
|
|
62
|
-
const sections = artifact.required_sections;
|
|
63
|
-
const patterns = artifact.required_patterns;
|
|
64
|
-
return {
|
|
65
|
-
requiredSections: Array.isArray(sections)
|
|
66
|
-
? sections.filter((value) => typeof value === 'string')
|
|
67
|
-
: fallback.requiredSections,
|
|
68
|
-
requiredPatterns: Array.isArray(patterns)
|
|
69
|
-
? patterns.filter((value) => typeof value === 'string')
|
|
70
|
-
: fallback.requiredPatterns
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
return fallback;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
58
|
function validateTaskEventRequest(request) {
|
|
78
59
|
if (!eventCatalog.includes(request.event))
|
|
79
60
|
return { code: 'EVENT_UNKNOWN', message: `unknown task event '${request.event}'` };
|
|
@@ -115,7 +96,7 @@ function validateTaskEventRequest(request) {
|
|
|
115
96
|
if (modeRequired.some((key) => request[key] === undefined) || forbidden.some((key) => request[key] !== undefined))
|
|
116
97
|
return { code: 'EVENT_PAYLOAD_INVALID', message: 'code.completed requires either initial or fix completion payload' };
|
|
117
98
|
}
|
|
118
|
-
if (request.fixFor &&
|
|
99
|
+
if (request.fixFor && parseArtifactName(request.fixFor)?.family !== 'review-code')
|
|
119
100
|
return { code: 'EVENT_PAYLOAD_INVALID', message: 'fixFor must reference a canonical review-code artifact' };
|
|
120
101
|
if (request.implementationInput && !/^II-[1-9]\d*$/.test(request.implementationInput))
|
|
121
102
|
return { code: 'EVENT_PAYLOAD_INVALID', message: 'implementationInput must be a canonical II-N id' };
|
|
@@ -127,6 +108,19 @@ function validateTaskEventRequest(request) {
|
|
|
127
108
|
return { code: 'EVENT_PAYLOAD_INVALID', message: 'fixFor and implementationInput are mutually exclusive' };
|
|
128
109
|
if (request.summaryResult !== undefined && (!request.summaryResult.trim() || /[\r\n]/.test(request.summaryResult)))
|
|
129
110
|
return { code: 'EVENT_PAYLOAD_INVALID', message: 'summaryResult must be a non-empty single line' };
|
|
111
|
+
if (request.event === 'manual-validation.completed') {
|
|
112
|
+
for (const [name, value, pattern] of [
|
|
113
|
+
['transactionId', request.transactionId, /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u],
|
|
114
|
+
['receiptDigest', request.receiptDigest, /^[a-f0-9]{64}$/u],
|
|
115
|
+
['prHeadSha', request.prHeadSha, /^[a-f0-9]{40}$/u]
|
|
116
|
+
])
|
|
117
|
+
if (!value || !pattern.test(value))
|
|
118
|
+
return { code: 'EVENT_PAYLOAD_INVALID', message: `manual-validation.completed requires a valid ${name}` };
|
|
119
|
+
}
|
|
120
|
+
if (request.event === 'manual-validation.started' && request.transactionId !== undefined
|
|
121
|
+
&& !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(request.transactionId)) {
|
|
122
|
+
return { code: 'EVENT_PAYLOAD_INVALID', message: 'manual-validation.started requires a valid transactionId' };
|
|
123
|
+
}
|
|
130
124
|
if (request.event !== 'analyze.awaiting-input' && /\.(?:started|completed)$/.test(request.event)) {
|
|
131
125
|
if (!request.initiator || !request.requestId || !request.reasonCode) {
|
|
132
126
|
return { code: 'EVENT_TRIGGER_REQUIRED', message: `${request.event} requires --initiator, --request-id, and --reason-code` };
|
|
@@ -225,7 +219,9 @@ function identity(request) {
|
|
|
225
219
|
if (family === 'manual-validation') {
|
|
226
220
|
return {
|
|
227
221
|
family, phase, action: spec.label,
|
|
228
|
-
note: phase === 'started'
|
|
222
|
+
note: phase === 'started'
|
|
223
|
+
? `started${request.transactionId ? `; transaction=${request.transactionId}` : ''}`
|
|
224
|
+
: `Manual validation passed → ${request.artifact}; ${request.summaryResult}; transaction=${request.transactionId}; receipt=${request.receiptDigest}; head=${request.prHeadSha}`,
|
|
229
225
|
target: null
|
|
230
226
|
};
|
|
231
227
|
}
|
|
@@ -280,6 +276,24 @@ function normalizeStarted(request, repoRoot) {
|
|
|
280
276
|
return { error: { code: 'EVENT_ARTIFACT_CONFLICT', message: `implementationInput '${request.implementationInput ?? ''}' conflicts with artifact context` }, context };
|
|
281
277
|
return { request: { ...request, round, artifact: context.next.name, fixFor: expectedFix, implementationInput: expectedImplementation }, context };
|
|
282
278
|
}
|
|
279
|
+
function validateManualValidationCompletion(taskDir, taskId, request, artifactPath) {
|
|
280
|
+
const completion = readManualValidationCompletion(taskDir, {
|
|
281
|
+
transactionId: request.transactionId,
|
|
282
|
+
taskId,
|
|
283
|
+
prHeadSha: request.prHeadSha,
|
|
284
|
+
artifact: request.artifact,
|
|
285
|
+
receiptDigest: request.receiptDigest
|
|
286
|
+
});
|
|
287
|
+
if (!completion.ok)
|
|
288
|
+
return completion.error;
|
|
289
|
+
const { receipt, transaction } = completion.value;
|
|
290
|
+
if (!['receipt-committed', 'final-promotion-in-progress', 'committed'].includes(transaction.phase)) {
|
|
291
|
+
return { code: 'MANUAL_VALIDATION_TRANSACTION_PHASE_INVALID', message: 'manual validation completion requires the receipt-backed transaction phase' };
|
|
292
|
+
}
|
|
293
|
+
if (sha256File(artifactPath) !== receipt.artifactSha256)
|
|
294
|
+
return { code: 'MANUAL_VALIDATION_RECEIPT_INVALID', message: 'manual-validation artifact digest does not match the receipt' };
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
283
297
|
function openStartedIdentity(rows, family) {
|
|
284
298
|
const spec = FAMILY[family];
|
|
285
299
|
if (family === 'manual-validation') {
|
|
@@ -300,6 +314,24 @@ function openStartedIdentity(rows, family) {
|
|
|
300
314
|
function reviewInputFamily(family) {
|
|
301
315
|
return family === 'review-analysis' ? 'analysis' : family === 'review-plan' ? 'plan' : 'code';
|
|
302
316
|
}
|
|
317
|
+
function relationForStartedInput(family, input) {
|
|
318
|
+
if (family.startsWith('review-')) {
|
|
319
|
+
return input.family === reviewInputFamily(family) ? 'reviewed-input' : 'approval-context';
|
|
320
|
+
}
|
|
321
|
+
const consumer = family === 'analyze' ? 'analysis' : family;
|
|
322
|
+
if ((consumer === 'plan' && input.family === 'analysis') || (consumer === 'code' && input.family === 'plan'))
|
|
323
|
+
return 'required-input';
|
|
324
|
+
return 'review-context';
|
|
325
|
+
}
|
|
326
|
+
function qualificationRelationsForStarted(family, inputs) {
|
|
327
|
+
return inputs.map((input) => ({
|
|
328
|
+
upstreamFamily: input.family,
|
|
329
|
+
upstreamArtifact: input.name,
|
|
330
|
+
upstreamRound: input.round,
|
|
331
|
+
upstreamSha256: sha256File(input.path),
|
|
332
|
+
relation: relationForStartedInput(family, input)
|
|
333
|
+
}));
|
|
334
|
+
}
|
|
303
335
|
function lifecycleAction(family) {
|
|
304
336
|
return family === 'analyze' ? 'analysis' : family;
|
|
305
337
|
}
|
|
@@ -328,6 +360,7 @@ function invalidationMutationForCompletion(content, taskDir, family, artifact, t
|
|
|
328
360
|
code: ['review-code']
|
|
329
361
|
};
|
|
330
362
|
const sourceFamily = family;
|
|
363
|
+
const sourceArtifactFamily = sourceFamily === 'analyze' ? 'analysis' : sourceFamily;
|
|
331
364
|
let receipts = [];
|
|
332
365
|
try {
|
|
333
366
|
receipts = parseArtifactReceipts(content).rows;
|
|
@@ -335,46 +368,134 @@ function invalidationMutationForCompletion(content, taskDir, family, artifact, t
|
|
|
335
368
|
catch (error) {
|
|
336
369
|
return { error: error instanceof Error ? error.message : String(error) };
|
|
337
370
|
}
|
|
338
|
-
const
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
371
|
+
const inventory = fs.readdirSync(taskDir).flatMap((name) => {
|
|
372
|
+
const identity = parseArtifactName(name);
|
|
373
|
+
if (!identity || !ARTIFACT_FAMILIES.includes(identity.family))
|
|
374
|
+
return [];
|
|
375
|
+
try {
|
|
376
|
+
const stat = fs.lstatSync(path.join(taskDir, name));
|
|
377
|
+
if (!stat.isFile() || stat.isSymbolicLink())
|
|
378
|
+
return [];
|
|
379
|
+
return [{ family: identity.family, name, round: identity.round, sha256: sha256File(path.join(taskDir, name)) }];
|
|
380
|
+
}
|
|
381
|
+
catch (error) {
|
|
382
|
+
throw new Error(`cannot inspect invalidation artifact '${name}': ${error instanceof Error ? error.message : String(error)}`);
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
const taskQualification = parseTaskQualification(content);
|
|
386
|
+
if (!taskQualification.ok)
|
|
387
|
+
return { error: taskQualification.message };
|
|
388
|
+
const nodeMap = new Map(inventory.map((node) => [`${node.family}/${node.name}`, node]));
|
|
389
|
+
const audits = new Map();
|
|
390
|
+
let taskInputChanged = false;
|
|
391
|
+
let graphUsable = taskQualification.qualification.present;
|
|
392
|
+
if (graphUsable) {
|
|
393
|
+
for (const node of inventory) {
|
|
394
|
+
const artifactContent = fs.readFileSync(path.join(taskDir, node.name), 'utf8');
|
|
395
|
+
const parsedAudit = parseQualificationAudit(artifactContent);
|
|
396
|
+
if (!parsedAudit.ok || !parsedAudit.audit.present || !parsedAudit.audit.snapshot) {
|
|
397
|
+
graphUsable = false;
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
audits.set(`${node.family}/${node.name}`, parsedAudit.audit);
|
|
401
|
+
if (parsedAudit.audit.snapshot.taskInputDigest !== taskQualification.qualification.taskInputDigest)
|
|
402
|
+
taskInputChanged = true;
|
|
403
|
+
if (parsedAudit.audit.snapshot.nonConstraintInputDigest !== taskQualification.qualification.nonConstraintInputDigest) {
|
|
404
|
+
graphUsable = false;
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
if (parsedAudit.audit.snapshot.upstreamArtifactDigest !== upstreamArtifactDigest(parsedAudit.audit.upstreamRelations)) {
|
|
408
|
+
graphUsable = false;
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
for (const relation of parsedAudit.audit.upstreamRelations) {
|
|
412
|
+
const upstream = nodeMap.get(`${relation.upstreamFamily}/${relation.upstreamArtifact}`);
|
|
413
|
+
if (!upstream || upstream.round !== relation.upstreamRound || upstream.sha256 !== relation.upstreamSha256) {
|
|
414
|
+
graphUsable = false;
|
|
415
|
+
break;
|
|
367
416
|
}
|
|
368
|
-
return shapes.map((targetShape) => ({
|
|
369
|
-
...targetShape,
|
|
370
|
-
targetId: targetIdFor('pending', targetShape), operationId: 'pending', status: 'pending',
|
|
371
|
-
reasonCode: 'upstream-replaced', updatedAt: timestamp
|
|
372
|
-
}));
|
|
373
417
|
}
|
|
374
|
-
|
|
375
|
-
|
|
418
|
+
if (!graphUsable)
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const selected = new Set();
|
|
423
|
+
if (graphUsable) {
|
|
424
|
+
const changedConstraints = new Set();
|
|
425
|
+
for (const audit of audits.values()) {
|
|
426
|
+
for (const dependency of audit.constraintDependencies) {
|
|
427
|
+
const current = taskQualification.qualification.constraints.find((row) => row.constraintId === dependency.constraintId);
|
|
428
|
+
if (!current || current.digest !== dependency.constraintDigest)
|
|
429
|
+
changedConstraints.add(dependency.constraintId);
|
|
376
430
|
}
|
|
377
|
-
}
|
|
431
|
+
}
|
|
432
|
+
const currentCandidates = new Map(taskQualification.qualification.candidates.map((candidate) => [candidate.candidateId, candidate]));
|
|
433
|
+
const candidateSnapshotMatches = [...audits.values()].every((audit) => audit.candidateQualifications.length === currentCandidates.size && audit.candidateQualifications.every((row) => {
|
|
434
|
+
const current = currentCandidates.get(row.candidateId);
|
|
435
|
+
return Boolean(current && current.status === row.status && current.impact === row.impact
|
|
436
|
+
&& current.evidence === row.evidence && current.constraintIds.join(',') === row.constraintIds.join(','));
|
|
437
|
+
}));
|
|
438
|
+
// A task-input digest also covers candidates. A narrowed invalidation graph
|
|
439
|
+
// is safe only when the old audit rows show that the candidate projection
|
|
440
|
+
// stayed unchanged and the change is explained by at least one constraint.
|
|
441
|
+
if (taskInputChanged && (changedConstraints.size === 0 || !candidateSnapshotMatches))
|
|
442
|
+
graphUsable = false;
|
|
443
|
+
for (const node of inventory) {
|
|
444
|
+
const audit = audits.get(`${node.family}/${node.name}`);
|
|
445
|
+
if (audit.constraintDependencies.some((dependency) => changedConstraints.has(dependency.constraintId)))
|
|
446
|
+
selected.add(`${node.family}/${node.name}`);
|
|
447
|
+
if (audit.upstreamRelations.some((relation) => relation.upstreamFamily === sourceArtifactFamily))
|
|
448
|
+
selected.add(`${node.family}/${node.name}`);
|
|
449
|
+
}
|
|
450
|
+
// Relation rows point from a consumer to its actual upstream artifact. Walk
|
|
451
|
+
// that reverse edge so review-only seeds and multi-hop consumers receive the
|
|
452
|
+
// same derived targets as ordinary executor seeds.
|
|
453
|
+
let changed = true;
|
|
454
|
+
while (changed) {
|
|
455
|
+
changed = false;
|
|
456
|
+
for (const node of inventory) {
|
|
457
|
+
const key = `${node.family}/${node.name}`;
|
|
458
|
+
const audit = audits.get(key);
|
|
459
|
+
if (audit.upstreamRelations.some((relation) => selected.has(`${relation.upstreamFamily}/${relation.upstreamArtifact}`)) && !selected.has(key)) {
|
|
460
|
+
selected.add(key);
|
|
461
|
+
changed = true;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
// A relation cycle cannot establish a safe downstream closure.
|
|
466
|
+
const visiting = new Set();
|
|
467
|
+
const visited = new Set();
|
|
468
|
+
const hasCycle = (key) => {
|
|
469
|
+
if (visiting.has(key))
|
|
470
|
+
return true;
|
|
471
|
+
if (visited.has(key))
|
|
472
|
+
return false;
|
|
473
|
+
visiting.add(key);
|
|
474
|
+
const cycle = audits.get(key)?.upstreamRelations.some((relation) => hasCycle(`${relation.upstreamFamily}/${relation.upstreamArtifact}`)) ?? false;
|
|
475
|
+
visiting.delete(key);
|
|
476
|
+
visited.add(key);
|
|
477
|
+
return cycle;
|
|
478
|
+
};
|
|
479
|
+
if ([...nodeMap.keys()].some(hasCycle))
|
|
480
|
+
graphUsable = false;
|
|
481
|
+
}
|
|
482
|
+
const reasonCode = graphUsable ? 'qualification-changed' : 'upstream-replaced';
|
|
483
|
+
const targetNodes = (graphUsable
|
|
484
|
+
? inventory.filter((node) => selected.has(`${node.family}/${node.name}`))
|
|
485
|
+
: inventory.filter((node) => downstream[sourceFamily].includes(node.family)))
|
|
486
|
+
.filter((node) => !(node.family === FAMILY[family].artifact && node.name === artifact.name));
|
|
487
|
+
const targets = targetNodes.flatMap((node) => {
|
|
488
|
+
const shapes = [
|
|
489
|
+
{ targetKind: 'artifact', targetFamily: node.family, targetArtifact: node.name, targetRound: node.round, targetSha256: node.sha256 }
|
|
490
|
+
];
|
|
491
|
+
const receipt = receipts.find((candidate) => candidate.output === node.name);
|
|
492
|
+
if (receipt)
|
|
493
|
+
shapes.push({ targetKind: 'receipt', targetFamily: node.family, targetArtifact: node.name, targetRound: node.round, targetSha256: receipt.inputSha256 });
|
|
494
|
+
if (node.family.startsWith('review-'))
|
|
495
|
+
shapes.push({ targetKind: 'approval', targetFamily: node.family, targetArtifact: node.name, targetRound: node.round, targetSha256: node.sha256 });
|
|
496
|
+
if (node.family === 'review-code')
|
|
497
|
+
shapes.push({ targetKind: 'reviewed-snapshot', targetFamily: node.family, targetArtifact: node.name, targetRound: node.round, targetSha256: node.sha256 });
|
|
498
|
+
return shapes.map((targetShape) => ({ ...targetShape, targetId: targetIdFor('pending', targetShape), operationId: 'pending', status: 'pending', reasonCode, updatedAt: timestamp }));
|
|
378
499
|
});
|
|
379
500
|
if (targets.length === 0)
|
|
380
501
|
return { mutation: null };
|
|
@@ -539,6 +660,11 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
539
660
|
if (openIdentity) {
|
|
540
661
|
if (openIdentity.row.agent !== request.agent)
|
|
541
662
|
return failed(request, { code: 'EVENT_LOG_CONFLICT', message: 'open started event has a different agent' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
|
|
663
|
+
if (initialParts.family === 'manual-validation' && request.transactionId !== undefined) {
|
|
664
|
+
const existingTransactionId = /(?:^|;\s*)transaction=([A-Za-z0-9][A-Za-z0-9._-]{0,127})(?:;|$)/u.exec(openIdentity.row.note)?.[1];
|
|
665
|
+
if (existingTransactionId !== undefined && existingTransactionId !== request.transactionId)
|
|
666
|
+
return failed(request, { code: 'EVENT_LOG_CONFLICT', message: 'open manual-validation started event has a different transactionId' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
|
|
667
|
+
}
|
|
542
668
|
if (request.round !== undefined && request.round !== openIdentity.round)
|
|
543
669
|
return failed(request, { code: 'EVENT_ARTIFACT_CONFLICT', message: `round ${request.round} conflicts with open round ${openIdentity.round}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
|
|
544
670
|
if (request.fixFor !== undefined && request.fixFor !== openIdentity.fixFor)
|
|
@@ -560,6 +686,25 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
560
686
|
normalized = { ...request, round: identity.round };
|
|
561
687
|
}
|
|
562
688
|
const eventIdentity = identity(normalized);
|
|
689
|
+
const lifecycleAuthority = options.lifecycleRecoveryAttestation ?? null;
|
|
690
|
+
if (lifecycleAuthority) {
|
|
691
|
+
try {
|
|
692
|
+
validateLifecycleRecoveryAttestation(lifecycleAuthority);
|
|
693
|
+
}
|
|
694
|
+
catch (error) {
|
|
695
|
+
return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: error instanceof Error ? error.message : String(error) }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
|
|
696
|
+
}
|
|
697
|
+
const expectedFamily = eventIdentity.family === 'analyze' ? 'analysis' : eventIdentity.family;
|
|
698
|
+
if (eventIdentity.phase !== 'completed'
|
|
699
|
+
|| lifecycleAuthority.phase !== 'task-event.completed'
|
|
700
|
+
|| lifecycleAuthority.taskId !== resolved.taskId
|
|
701
|
+
|| lifecycleAuthority.family !== expectedFamily
|
|
702
|
+
|| lifecycleAuthority.artifact !== normalized.artifact
|
|
703
|
+
|| lifecycleAuthority.round !== normalized.round
|
|
704
|
+
|| (normalized.requestId !== undefined && lifecycleAuthority.lifecycleRequestId !== normalized.requestId)) {
|
|
705
|
+
return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: 'lifecycle completion authority does not match the event tuple' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
|
|
706
|
+
}
|
|
707
|
+
}
|
|
563
708
|
const currentStep = typeof frontmatter.current_step === 'string' ? frontmatter.current_step : '';
|
|
564
709
|
const matchingRows = rows.filter((item) => item.step === eventIdentity.action);
|
|
565
710
|
const manual = eventIdentity.family === 'manual-validation';
|
|
@@ -573,6 +718,12 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
573
718
|
if (eventIdentity.phase === 'started' && row) {
|
|
574
719
|
if (row.agent !== normalized.agent)
|
|
575
720
|
return failed(normalized, { code: 'EVENT_LOG_CONFLICT', message: 'open started event has a different agent' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
|
|
721
|
+
if (manual && normalized.transactionId !== undefined) {
|
|
722
|
+
const existingTransactionId = /(?:^|;\s*)transaction=([A-Za-z0-9][A-Za-z0-9._-]{0,127})(?:;|$)/u.exec(row.note)?.[1];
|
|
723
|
+
if (existingTransactionId !== undefined && existingTransactionId !== normalized.transactionId) {
|
|
724
|
+
return failed(normalized, { code: 'EVENT_LOG_CONFLICT', message: 'open manual-validation started event has a different transactionId' }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
|
|
725
|
+
}
|
|
726
|
+
}
|
|
576
727
|
return successNoOp(normalized, resolved.taskId, resolved.taskMdPath, currentStep, eventIdentity, row.started, frontmatter, artifactContext);
|
|
577
728
|
}
|
|
578
729
|
if (eventIdentity.phase === 'started' && !manual && completedRows.length > 0)
|
|
@@ -589,6 +740,37 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
589
740
|
if (!validated.ok)
|
|
590
741
|
return failed(normalized, validated.error, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
591
742
|
completedArtifact = validated.artifact;
|
|
743
|
+
if (eventIdentity.family === 'manual-validation') {
|
|
744
|
+
const validationError = validateManualValidationCompletion(resolved.taskDir, resolved.taskId, normalized, completedArtifact.path);
|
|
745
|
+
if (validationError)
|
|
746
|
+
return failed(normalized, validationError, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
747
|
+
}
|
|
748
|
+
if (eventIdentity.family.startsWith('review-')) {
|
|
749
|
+
let reviewContent;
|
|
750
|
+
try {
|
|
751
|
+
reviewContent = fs.readFileSync(completedArtifact.path, 'utf8');
|
|
752
|
+
}
|
|
753
|
+
catch (error) {
|
|
754
|
+
return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `cannot read qualification audit from ${completedArtifact.name}: ${error instanceof Error ? error.message : String(error)}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
755
|
+
}
|
|
756
|
+
const schema = getArtifactSchema(eventIdentity.family);
|
|
757
|
+
const structure = schema ? inspectArtifactContract(reviewContent, schema) : null;
|
|
758
|
+
if (structure && !structure.ok) {
|
|
759
|
+
return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `shared artifact structure invalid: ${structure.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; ')}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
760
|
+
}
|
|
761
|
+
const expected = expectedQualificationRelations(content, eventIdentity.family);
|
|
762
|
+
if (!expected.ok) {
|
|
763
|
+
return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `${expected.code}: ${expected.message}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
764
|
+
}
|
|
765
|
+
const qualification = validateQualificationAudit(content, reviewContent, {
|
|
766
|
+
family: eventIdentity.family,
|
|
767
|
+
artifact: completedArtifact.name,
|
|
768
|
+
expectedUpstreamRelations: expected.relations
|
|
769
|
+
});
|
|
770
|
+
if (!qualification.ok) {
|
|
771
|
+
return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `${qualification.code}: ${qualification.message}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
772
|
+
}
|
|
773
|
+
}
|
|
592
774
|
if (eventIdentity.family === 'analyze' || eventIdentity.family === 'plan' || eventIdentity.family === 'code') {
|
|
593
775
|
const localFamily = eventIdentity.family === 'analyze'
|
|
594
776
|
? 'analysis'
|
|
@@ -600,11 +782,10 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
600
782
|
catch (error) {
|
|
601
783
|
return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `cannot read ${completedArtifact.name}: ${String(error)}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
602
784
|
}
|
|
603
|
-
const validationConfig = localArtifactValidationConfig(resolved.repoRoot, localFamily);
|
|
604
785
|
const local = validateLocalArtifact(artifactContent, {
|
|
605
786
|
family: localFamily,
|
|
606
|
-
|
|
607
|
-
|
|
787
|
+
taskContent: content,
|
|
788
|
+
artifact: completedArtifact.name
|
|
608
789
|
});
|
|
609
790
|
if (!local.ok) {
|
|
610
791
|
return failed(normalized, {
|
|
@@ -634,7 +815,7 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
634
815
|
message: `cannot read local finalizer provenance for ${completedArtifact.name}: ${error instanceof Error ? error.message : String(error)}`
|
|
635
816
|
}, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
636
817
|
}
|
|
637
|
-
if (!localFinalizationIntent || !['passed', 'consumed'].includes(localFinalizationIntent.state)) {
|
|
818
|
+
if (!localFinalizationIntent || !['passed', 'consumed', 'finalize-ready', 'commit-started'].includes(localFinalizationIntent.state)) {
|
|
638
819
|
return failed(normalized, {
|
|
639
820
|
code: 'EVENT_ARTIFACT_CONFLICT',
|
|
640
821
|
message: `local finalizer provenance is missing or incomplete for ${completedArtifact.name}`
|
|
@@ -646,6 +827,18 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
646
827
|
message: `local finalizer provenance does not match ${completedArtifact.name}`
|
|
647
828
|
}, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
648
829
|
}
|
|
830
|
+
if (localFinalizationIntent.recoveryOperationId !== null) {
|
|
831
|
+
if (!lifecycleAuthority
|
|
832
|
+
|| localFinalizationIntent.recoveryOperationId !== lifecycleAuthority.operationId
|
|
833
|
+
|| localFinalizationIntent.requestId !== lifecycleAuthority.lifecycleRequestId
|
|
834
|
+
|| (localFinalizationIntent.phase !== 'artifact.finalize-local'
|
|
835
|
+
&& localFinalizationIntent.authorityDigest !== lifecycleRecoveryAttestationDigest(lifecycleAuthority))) {
|
|
836
|
+
return failed(normalized, {
|
|
837
|
+
code: 'EVENT_ARTIFACT_CONFLICT',
|
|
838
|
+
message: `local finalizer provenance does not match lifecycle completion authority for ${completedArtifact.name}`
|
|
839
|
+
}, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase, artifactContext });
|
|
840
|
+
}
|
|
841
|
+
}
|
|
649
842
|
}
|
|
650
843
|
}
|
|
651
844
|
if (eventIdentity.phase === 'waiting' && section.entries.some((entry) => entry.step === eventIdentity.action && entry.note === eventIdentity.note)) {
|
|
@@ -726,6 +919,14 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
726
919
|
const body = appendActivityEntry(section, { time: metadata.timestamp, step: logStep, agent: normalized.agent, note: eventIdentity.note });
|
|
727
920
|
const frontmatterSet = { current_step: step, assigned_to: normalized.agent };
|
|
728
921
|
let frontmatterRemove;
|
|
922
|
+
if (eventIdentity.phase === 'started' && artifactContext) {
|
|
923
|
+
try {
|
|
924
|
+
frontmatterSet.qualification_input_relations = JSON.stringify(qualificationRelationsForStarted(eventIdentity.family, artifactContext.inputs));
|
|
925
|
+
}
|
|
926
|
+
catch (error) {
|
|
927
|
+
return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: `cannot capture qualification input relations: ${error instanceof Error ? error.message : String(error)}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: step, action: eventIdentity.action, phase: eventIdentity.phase, artifactContext });
|
|
928
|
+
}
|
|
929
|
+
}
|
|
729
930
|
if (eventIdentity.phase === 'started' && eventIdentity.family === 'code') {
|
|
730
931
|
const planInput = artifactContext?.inputs.find((input) => input.family === 'plan');
|
|
731
932
|
if (!planInput)
|
|
@@ -757,6 +958,8 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
757
958
|
else if (eventIdentity.phase === 'completed' && eventIdentity.family.startsWith('review-')) {
|
|
758
959
|
frontmatterRemove = ['review_input_artifact', 'review_input_sha256'];
|
|
759
960
|
}
|
|
961
|
+
if (eventIdentity.phase === 'completed')
|
|
962
|
+
frontmatterRemove = [...(frontmatterRemove ?? []), 'qualification_input_relations'];
|
|
760
963
|
if (eventIdentity.phase === 'started' && normalized.implementationInput)
|
|
761
964
|
frontmatterSet.last_reviewed_commit = '';
|
|
762
965
|
const mutations = [
|
|
@@ -795,14 +998,28 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
795
998
|
});
|
|
796
999
|
}
|
|
797
1000
|
mutations.push({ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: section.heading, body });
|
|
798
|
-
if (!normalized.dryRun && localFinalizationIntent && completedArtifact
|
|
1001
|
+
if (!normalized.dryRun && localFinalizationIntent && completedArtifact) {
|
|
799
1002
|
try {
|
|
800
|
-
|
|
1003
|
+
if (lifecycleAuthority && localFinalizationIntent.state === 'passed') {
|
|
1004
|
+
const expectedIntent = localFinalizationIntent;
|
|
1005
|
+
localFinalizationIntent = {
|
|
1006
|
+
...localFinalizationIntent,
|
|
1007
|
+
state: 'commit-started',
|
|
1008
|
+
phase: 'task-event.completed',
|
|
1009
|
+
authorityDigest: lifecycleRecoveryAttestationDigest(lifecycleAuthority),
|
|
1010
|
+
requestId: lifecycleAuthority.lifecycleRequestId,
|
|
1011
|
+
updatedAt: Date.now()
|
|
1012
|
+
};
|
|
1013
|
+
writeArtifactRepairIntent(resolved.repoRoot, localFinalizationIntent, { expected: expectedIntent });
|
|
1014
|
+
}
|
|
1015
|
+
else if (!lifecycleAuthority && localFinalizationIntent.state === 'passed') {
|
|
1016
|
+
localFinalizationIntent = consumeLocalArtifactFinalizationIntent(resolved.repoRoot, localFinalizationIntent);
|
|
1017
|
+
}
|
|
801
1018
|
}
|
|
802
1019
|
catch (error) {
|
|
803
1020
|
return failed(normalized, {
|
|
804
1021
|
code: 'EVENT_ARTIFACT_CONFLICT',
|
|
805
|
-
message: `local finalizer provenance could not be
|
|
1022
|
+
message: `local finalizer provenance could not be advanced before task write for ${completedArtifact.name}: ${error instanceof Error ? error.message : String(error)}`
|
|
806
1023
|
}, {
|
|
807
1024
|
taskId: resolved.taskId,
|
|
808
1025
|
taskMdPath: resolved.taskMdPath,
|
|
@@ -819,6 +1036,19 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
819
1036
|
const result = writeTask({ taskRef: normalized.taskRef, expectedState: stateOverride ? resolved.state : 'active', dryRun: normalized.dryRun, mutations }, { ...options, invalidationContext: sourceCompletion ? 'source-completion' : 'standard', metadataProvider: () => metadata });
|
|
820
1037
|
if (result.status === 'failed')
|
|
821
1038
|
return failed(normalized, result.error, { taskId: result.taskId, taskMdPath: result.taskMdPath, fromStep: currentStep, toStep: step, action: eventIdentity.action, phase: eventIdentity.phase, timestamp: result.timestamp, agentInfraVersion: result.agentInfraVersion, operations: result.operations, artifactContext });
|
|
1039
|
+
if (!normalized.dryRun && lifecycleAuthority && localFinalizationIntent && completedArtifact) {
|
|
1040
|
+
try {
|
|
1041
|
+
if (!options.deferLifecycleRecoveryConsumption)
|
|
1042
|
+
consumeLifecycleRecoveryAttestation(lifecycleAuthority);
|
|
1043
|
+
writeArtifactRepairIntent(resolved.repoRoot, { ...localFinalizationIntent, state: 'consumed', updatedAt: Date.now() }, { expected: localFinalizationIntent });
|
|
1044
|
+
}
|
|
1045
|
+
catch (error) {
|
|
1046
|
+
return failed(normalized, {
|
|
1047
|
+
code: 'EVENT_ARTIFACT_CONFLICT',
|
|
1048
|
+
message: `task completion was written but lifecycle recovery consumption is incomplete: ${error instanceof Error ? error.message : String(error)}`
|
|
1049
|
+
}, { taskId: result.taskId, taskMdPath: result.taskMdPath, fromStep: currentStep, toStep: step, action: eventIdentity.action, phase: eventIdentity.phase, timestamp: result.timestamp, agentInfraVersion: result.agentInfraVersion, operations: result.operations, artifactContext });
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
822
1052
|
if (!normalized.dryRun && orchestrationCompletion) {
|
|
823
1053
|
try {
|
|
824
1054
|
(options.commitOrchestrationCompletion ?? commitOrchestrationStageCompletion)(orchestrationCompletion);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function taskFinalizationReceiptState(receipt) {
|
|
2
|
+
if (receipt.lifecycle !== 'done' || receipt.taskComment === 'pending'
|
|
3
|
+
|| receipt.verification === 'pending' || receipt.warningProjection !== 'done')
|
|
4
|
+
return 'pending';
|
|
5
|
+
if (receipt.lastError !== null || receipt.warnings.some((warning) => warning.status === 'open'))
|
|
6
|
+
return 'unresolved';
|
|
7
|
+
return 'complete';
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=finalization-state.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { createHash, randomUUID } from 'node:crypto';
|
|
4
|
+
import { parseArtifactName } from './artifact-name.js';
|
|
4
5
|
import { locateActivityLog } from './activity-log.js';
|
|
5
6
|
import { applyPrReviewActivityIntent } from './activity-intent.js';
|
|
6
7
|
import { applyHumanDecision } from './decision-intents.js';
|
|
@@ -577,12 +578,8 @@ function latestArtifact(taskDir, family) {
|
|
|
577
578
|
catch {
|
|
578
579
|
return undefined;
|
|
579
580
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
const round = (name) => Number(/-r(\d+)\.md$/.exec(name)?.[1] ?? 1);
|
|
583
|
-
return round(b) - round(a);
|
|
584
|
-
});
|
|
585
|
-
return candidates[0];
|
|
581
|
+
return names.map(parseArtifactName).filter((identity) => identity !== null)
|
|
582
|
+
.filter((identity) => identity.family === family).sort((left, right) => right.round - left.round)[0]?.name;
|
|
586
583
|
}
|
|
587
584
|
async function probeVerificationEngineFailure(policy, resolved) {
|
|
588
585
|
const candidates = [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseArtifactName } from './artifact-name.js';
|
|
1
2
|
import { parseTable } from './sections.js';
|
|
2
3
|
const SECTION_ALIASES = ['实现输入', 'Implementation Inputs'];
|
|
3
4
|
const COLUMNS = [
|
|
@@ -5,7 +6,6 @@ const COLUMNS = [
|
|
|
5
6
|
'decided_at', 'status', 'consumed_by'
|
|
6
7
|
];
|
|
7
8
|
const TIMESTAMP_RE = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/;
|
|
8
|
-
const ARTIFACT_RE = /^code(?:-r(?:[2-9]|[1-9]\d+))?\.md$/;
|
|
9
9
|
function validateInput(row) {
|
|
10
10
|
if (!/^II-[1-9]\d*$/.test(row.id))
|
|
11
11
|
throw new Error(`implementation input id '${row.id}' is invalid`);
|
|
@@ -17,7 +17,7 @@ function validateInput(row) {
|
|
|
17
17
|
const valid = (row.status === 'declared' && row.decidedAt === '' && row.consumedBy === '') ||
|
|
18
18
|
(hasValidTimestamp && row.needsImplementation && row.status === 'pending' && row.consumedBy === '') ||
|
|
19
19
|
(hasValidTimestamp && !row.needsImplementation && row.status === 'not-required' && row.consumedBy === '') ||
|
|
20
|
-
(hasValidTimestamp && row.needsImplementation && row.status === 'consumed' &&
|
|
20
|
+
(hasValidTimestamp && row.needsImplementation && row.status === 'consumed' && parseArtifactName(row.consumedBy)?.family === 'code');
|
|
21
21
|
if (!valid)
|
|
22
22
|
throw new Error(`implementation input ${row.id} has an invalid state combination`);
|
|
23
23
|
}
|
|
@@ -122,7 +122,7 @@ function selectPendingImplementationInput(rows) {
|
|
|
122
122
|
})[0] ?? null;
|
|
123
123
|
}
|
|
124
124
|
function consumeImplementationInput(rows, id, artifact) {
|
|
125
|
-
if (
|
|
125
|
+
if (parseArtifactName(artifact)?.family !== 'code')
|
|
126
126
|
throw new Error(`implementation input artifact '${artifact}' is invalid`);
|
|
127
127
|
let found = false;
|
|
128
128
|
const next = rows.map((row) => {
|