@fitlab-ai/agent-infra 0.9.12 → 0.9.14
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 +11 -11
- package/README.zh-CN.md +11 -11
- package/bin/cli.ts +26 -9
- package/dist/bin/cli.js +173 -157
- package/dist/bin/internal-cli.js +66 -40
- package/dist/lib/agent-client.js +5 -0
- package/dist/lib/agent-clients/next-steps.js +6 -1
- package/dist/lib/decide.js +3 -3
- package/dist/lib/internal/agent-client.js +5 -2
- package/dist/lib/internal/cli-route-inventory.js +152 -0
- package/dist/lib/internal/codex-lifecycle.js +9 -6
- package/dist/lib/internal/codex-sandbox-controller.js +8 -2
- package/dist/lib/internal/git-workflow.js +10 -6
- package/dist/lib/internal/platform-checks.js +19 -7
- package/dist/lib/internal/platform-comment.js +25 -13
- package/dist/lib/internal/platform-context.js +6 -3
- package/dist/lib/internal/platform-issue.js +20 -13
- package/dist/lib/internal/platform-metadata.js +88 -0
- package/dist/lib/internal/platform-pr-review.js +26 -13
- package/dist/lib/internal/platform-pr.js +84 -31
- package/dist/lib/internal/platform-release-notes.js +9 -6
- package/dist/lib/internal/platform-security.js +93 -0
- package/dist/lib/internal/pr-review-grade.js +25 -12
- package/dist/lib/internal/release-workflow.js +23 -9
- package/dist/lib/internal/sandbox-control.js +50 -7
- package/dist/lib/internal/task-activity.js +16 -7
- package/dist/lib/internal/task-artifact.js +235 -24
- package/dist/lib/internal/task-context.js +4 -1
- package/dist/lib/internal/task-create.js +50 -17
- package/dist/lib/internal/task-delivery.js +4 -1
- package/dist/lib/internal/task-event.js +10 -4
- package/dist/lib/internal/task-finalization.js +6 -3
- package/dist/lib/internal/task-invalidation.js +63 -0
- package/dist/lib/internal/task-ledger.js +20 -6
- package/dist/lib/internal/task-lifecycle.js +6 -3
- package/dist/lib/internal/task-operation-registry.js +421 -0
- package/dist/lib/internal/task-orchestration.js +12 -0
- package/dist/lib/internal/task-override.js +14 -7
- package/dist/lib/internal/task-qualification.js +90 -0
- package/dist/lib/internal/task-review.js +7 -4
- 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 +7 -2
- package/dist/lib/internal/task-verify.js +11 -7
- package/dist/lib/internal/task-warning.js +11 -4
- package/dist/lib/platform/adapters.js +1 -3
- package/dist/lib/platform/change-request-git-evidence.js +27 -7
- package/dist/lib/platform/comment-safety.js +226 -0
- package/dist/lib/platform/completion-backfill.js +6 -5
- package/dist/lib/platform/context.js +70 -130
- package/dist/lib/platform/github-client.js +1 -1
- package/dist/lib/platform/github-provider.js +1130 -0
- package/dist/lib/platform/in-label-sync.js +143 -0
- package/dist/lib/platform/issue-comments.js +237 -72
- package/dist/lib/platform/issues.js +335 -189
- package/dist/lib/platform/metadata-labels.js +6 -2
- package/dist/lib/platform/none-provider.js +28 -0
- package/dist/lib/platform/pr-change-report.js +545 -0
- package/dist/lib/platform/pr-checks.js +119 -104
- package/dist/lib/platform/pr-review.js +88 -72
- package/dist/lib/platform/pr-summary.js +541 -50
- package/dist/lib/platform/provider-bridge.js +45 -0
- package/dist/lib/platform/provider-contract.d.ts +553 -0
- package/dist/lib/platform/provider-contract.js +99 -0
- package/dist/lib/platform/provider-loader.js +251 -0
- package/dist/lib/platform/provider-validation.js +577 -0
- package/dist/lib/platform/pull-request-metadata.js +8 -6
- package/dist/lib/platform/pull-requests.js +734 -543
- package/dist/lib/platform/release-notes.js +78 -55
- package/dist/lib/platform/releases.js +79 -50
- package/dist/lib/platform/repository-metadata.js +377 -0
- package/dist/lib/platform/resource-identity.d.ts +26 -0
- package/dist/lib/platform/resource-identity.js +92 -0
- package/dist/lib/platform/security-alerts.js +155 -0
- package/dist/lib/platform/task-identities.js +31 -0
- package/dist/lib/platform/verification-required.js +11 -12
- package/dist/lib/platform/verification-sync.js +129 -248
- package/dist/lib/pr-review/evidence-grading.js +19 -6
- package/dist/lib/process-data/index.js +7 -0
- package/dist/lib/run/index.js +68 -23
- package/dist/lib/sandbox/commands/control-status.js +22 -0
- package/dist/lib/sandbox/commands/create.js +32 -6
- package/dist/lib/sandbox/commands/ls.js +5 -0
- package/dist/lib/sandbox/commands/rm.js +827 -120
- package/dist/lib/sandbox/commands/show.js +16 -0
- package/dist/lib/sandbox/control/client.js +174 -19
- 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 +151 -16
- package/dist/lib/sandbox/control/lifecycle.js +621 -127
- package/dist/lib/sandbox/control/native-file-lock.js +177 -0
- package/dist/lib/sandbox/control/protocol.js +77 -0
- package/dist/lib/sandbox/control/server.js +677 -34
- package/dist/lib/sandbox/control/state.js +209 -4
- package/dist/lib/sandbox/control/task-view.js +183 -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 +5 -0
- package/dist/lib/sandbox/recovery.js +21 -1
- package/dist/lib/sandbox/workspace-view.js +2 -1
- package/dist/lib/sandbox/worktree-safety.js +4 -1
- package/dist/lib/server/index.js +8 -0
- package/dist/lib/server/protocol.js +38 -1
- package/dist/lib/task/activity-log.js +8 -1
- package/dist/lib/task/artifact-lifecycle.js +75 -18
- package/dist/lib/task/artifact-operations.js +520 -0
- package/dist/lib/task/artifact-repair-intent.js +59 -0
- package/dist/lib/task/artifact-schema.js +135 -0
- package/dist/lib/task/capabilities.js +310 -0
- package/dist/lib/task/commands/status.js +32 -0
- package/dist/lib/task/commit-operation.js +12 -1
- package/dist/lib/task/control-authority.js +12 -5
- package/dist/lib/task/create-service.js +111 -12
- package/dist/lib/task/create.js +25 -0
- package/dist/lib/task/current-contract.js +5 -1
- package/dist/lib/task/decision-details.js +1 -1
- package/dist/lib/task/events.js +416 -17
- package/dist/lib/task/finalization.js +37 -13
- package/dist/lib/task/human-override.js +58 -36
- package/dist/lib/task/index.js +11 -3
- package/dist/lib/task/invalidation-command.js +86 -0
- package/dist/lib/task/invalidation.js +260 -0
- package/dist/lib/task/ledger-intents.js +37 -0
- package/dist/lib/task/local-artifact-finalization.js +299 -0
- package/dist/lib/task/orchestration.js +240 -144
- package/dist/lib/task/pr-delivery-fact.js +102 -101
- package/dist/lib/task/qualification-audit.js +490 -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 +22 -23
- package/dist/lib/task/review-finalization.js +121 -4
- package/dist/lib/task/review-fingerprint.js +24 -2
- package/dist/lib/task/rework-intent.js +138 -0
- package/dist/lib/task/sections.js +6 -4
- package/dist/lib/task/skill-scope.js +23 -0
- package/dist/lib/task/task-execution-lock.js +27 -17
- package/dist/lib/task/verification-config.js +11 -0
- package/dist/lib/task/verification-engine.js +93 -16
- package/dist/lib/task/verification.js +3 -3
- package/dist/lib/task/workflow-warning-intents.js +1 -1
- package/dist/lib/task/write.js +11 -0
- package/dist/lib/version.js +11 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +9 -0
- package/lib/agent-clients/next-steps.ts +6 -1
- package/lib/decide.ts +3 -3
- package/lib/init.ts +1 -1
- package/lib/internal/agent-client.ts +4 -2
- package/lib/internal/cli-route-inventory.ts +140 -0
- package/lib/internal/codex-lifecycle.ts +8 -6
- package/lib/internal/codex-sandbox-controller.ts +7 -2
- package/lib/internal/git-workflow.ts +9 -6
- package/lib/internal/platform-checks.ts +14 -6
- package/lib/internal/platform-comment.ts +20 -12
- package/lib/internal/platform-context.ts +5 -3
- package/lib/internal/platform-issue.ts +17 -11
- package/lib/internal/platform-metadata.ts +70 -0
- package/lib/internal/platform-pr-review.ts +23 -12
- package/lib/internal/platform-pr.ts +65 -27
- package/lib/internal/platform-release-notes.ts +8 -6
- package/lib/internal/platform-security.ts +83 -0
- package/lib/internal/pr-review-grade.ts +20 -11
- package/lib/internal/release-workflow.ts +21 -9
- package/lib/internal/sandbox-control.ts +44 -6
- package/lib/internal/task-activity.ts +15 -7
- package/lib/internal/task-artifact.ts +204 -22
- package/lib/internal/task-context.ts +3 -1
- package/lib/internal/task-create.ts +78 -17
- package/lib/internal/task-delivery.ts +3 -1
- package/lib/internal/task-event.ts +9 -4
- package/lib/internal/task-finalization.ts +6 -4
- package/lib/internal/task-invalidation.ts +41 -0
- package/lib/internal/task-ledger.ts +21 -8
- package/lib/internal/task-lifecycle.ts +5 -3
- package/lib/internal/task-operation-registry.ts +482 -0
- package/lib/internal/task-orchestration.ts +12 -0
- package/lib/internal/task-override.ts +15 -9
- package/lib/internal/task-qualification.ts +61 -0
- package/lib/internal/task-review.ts +6 -4
- package/lib/internal/task-short-id.ts +10 -1
- package/lib/internal/task-snapshot.ts +3 -1
- package/lib/internal/task-validate.ts +6 -2
- package/lib/internal/task-verify.ts +10 -7
- package/lib/internal/task-warning.ts +10 -4
- package/lib/platform/adapters.ts +3 -2
- package/lib/platform/change-request-git-evidence.ts +36 -9
- package/lib/platform/comment-safety.ts +250 -0
- package/lib/platform/completion-backfill.ts +9 -8
- package/lib/platform/context.ts +97 -134
- package/lib/platform/github-client.ts +2 -2
- package/lib/platform/github-provider.ts +1132 -0
- package/lib/platform/in-label-sync.ts +208 -0
- package/lib/platform/issue-comments.ts +255 -80
- package/lib/platform/issues.ts +344 -174
- package/lib/platform/metadata-labels.ts +5 -2
- package/lib/platform/none-provider.ts +35 -0
- package/lib/platform/pr-change-report.ts +639 -0
- package/lib/platform/pr-checks.ts +126 -106
- package/lib/platform/pr-review.ts +88 -85
- package/lib/platform/pr-summary.ts +581 -53
- package/lib/platform/provider-bridge.ts +82 -0
- package/lib/platform/provider-contract.ts +611 -0
- package/lib/platform/provider-loader.ts +307 -0
- package/lib/platform/provider-validation.ts +611 -0
- package/lib/platform/pull-request-metadata.ts +10 -7
- package/lib/platform/pull-requests.ts +781 -550
- package/lib/platform/release-notes.ts +76 -59
- package/lib/platform/releases.ts +77 -43
- package/lib/platform/repository-metadata.ts +453 -0
- package/lib/platform/resource-identity.ts +121 -0
- package/lib/platform/security-alerts.ts +191 -0
- package/lib/platform/task-identities.ts +40 -0
- package/lib/platform/types.ts +4 -2
- package/lib/platform/verification-required.ts +11 -13
- package/lib/platform/verification-sync.ts +128 -304
- package/lib/pr-review/evidence-grading.ts +25 -8
- package/lib/process-data/index.ts +7 -0
- package/lib/run/index.ts +62 -22
- package/lib/sandbox/commands/control-status.ts +26 -0
- package/lib/sandbox/commands/create.ts +46 -6
- package/lib/sandbox/commands/ls.ts +7 -0
- package/lib/sandbox/commands/rm.ts +1000 -87
- package/lib/sandbox/commands/show.ts +16 -0
- package/lib/sandbox/control/client.ts +203 -19
- package/lib/sandbox/control/completed-reentry.ts +98 -0
- package/lib/sandbox/control/container-identity.ts +27 -43
- package/lib/sandbox/control/executor.ts +180 -15
- package/lib/sandbox/control/lifecycle.ts +629 -17
- package/lib/sandbox/control/native-file-lock.ts +209 -0
- package/lib/sandbox/control/protocol.ts +118 -2
- package/lib/sandbox/control/server.ts +724 -34
- package/lib/sandbox/control/state.ts +257 -4
- package/lib/sandbox/control/task-view.ts +240 -0
- package/lib/sandbox/engines/authority.ts +365 -0
- package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
- package/lib/sandbox/index.ts +7 -0
- package/lib/sandbox/recovery.ts +21 -1
- package/lib/sandbox/workspace-view.ts +9 -3
- package/lib/sandbox/worktree-safety.ts +4 -1
- package/lib/server/index.ts +10 -0
- package/lib/server/protocol.ts +36 -1
- package/lib/task/activity-log.ts +8 -0
- package/lib/task/artifact-lifecycle.ts +70 -22
- package/lib/task/artifact-operations.ts +626 -0
- package/lib/task/artifact-repair-intent.ts +71 -0
- package/lib/task/artifact-schema.ts +192 -0
- package/lib/task/capabilities.ts +331 -0
- package/lib/task/commands/status.ts +38 -0
- package/lib/task/commit-operation.ts +12 -1
- package/lib/task/control-authority.ts +22 -9
- package/lib/task/create-service.ts +139 -14
- package/lib/task/create.ts +27 -0
- package/lib/task/current-contract.ts +6 -1
- package/lib/task/decision-details.ts +6 -2
- package/lib/task/events.ts +392 -16
- package/lib/task/finalization.ts +50 -14
- package/lib/task/human-override.ts +70 -46
- package/lib/task/index.ts +16 -3
- package/lib/task/invalidation-command.ts +86 -0
- package/lib/task/invalidation.ts +332 -0
- package/lib/task/ledger-intents.ts +35 -1
- package/lib/task/local-artifact-finalization.ts +432 -0
- package/lib/task/orchestration.ts +223 -133
- package/lib/task/pr-delivery-fact.ts +131 -148
- package/lib/task/qualification-audit.ts +599 -0
- package/lib/task/qualification-confirmation.ts +117 -0
- package/lib/task/qualification-intents.ts +150 -0
- package/lib/task/review-artifacts.ts +21 -22
- package/lib/task/review-finalization.ts +133 -4
- package/lib/task/review-fingerprint.ts +23 -2
- package/lib/task/rework-intent.ts +165 -0
- package/lib/task/sections.ts +6 -4
- package/lib/task/skill-scope.ts +24 -0
- package/lib/task/task-execution-lock.ts +23 -14
- package/lib/task/verification-config.ts +12 -0
- package/lib/task/verification-engine.ts +103 -17
- package/lib/task/verification.ts +4 -4
- package/lib/task/workflow-warning-intents.ts +1 -1
- package/lib/task/write.ts +19 -0
- package/lib/update.ts +1 -1
- package/lib/version.ts +15 -1
- package/package.json +12 -1
- package/templates/.agents/rules/README.en.md +3 -1
- package/templates/.agents/rules/README.zh-CN.md +3 -1
- 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/issue-pr-commands.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +2 -0
- package/templates/.agents/rules/issue-sync.zh-CN.md +2 -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 +13 -2
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +13 -2
- package/templates/.agents/rules/pr-sync.en.md +10 -4
- package/templates/.agents/rules/pr-sync.zh-CN.md +17 -4
- 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/task-short-id.en.md +1 -4
- package/templates/.agents/rules/task-short-id.zh-CN.md +1 -3
- package/templates/.agents/skills/analyze-task/SKILL.en.md +28 -5
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +29 -5
- 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/check-task/SKILL.en.md +16 -37
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -37
- 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 +41 -9
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +43 -11
- package/templates/.agents/skills/code-task/config/verify.en.json +6 -14
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +6 -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/commit/reference/issue-metadata-sync.en.md +2 -0
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +2 -0
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +3 -3
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +3 -3
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +10 -4
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +10 -4
- 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 +4 -3
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +4 -3
- package/templates/.agents/skills/complete-task/SKILL.en.md +26 -21
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +25 -21
- package/templates/.agents/skills/create-pr/SKILL.en.md +7 -6
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +7 -7
- package/templates/.agents/skills/create-pr/config/verify.json +1 -0
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +16 -4
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +16 -4
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +5 -3
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +5 -3
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +1 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/scripts/change-report.mjs +3 -0
- 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 +27 -4
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +26 -4
- 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/review-analysis/SKILL.en.md +17 -4
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +17 -4
- 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 +18 -5
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +18 -5
- 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 +17 -4
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +17 -4
- 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 +9 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +9 -3
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
- package/templates/.agents/skills/test/SKILL.en.md +13 -2
- package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
- package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +6 -0
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +6 -0
- package/templates/.agents/templates/task.en.md +24 -1
- package/templates/.agents/templates/task.zh-CN.md +24 -1
- package/templates/.github/workflows/pr-label.yml +7 -26
- 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
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
const INVALIDATION_HEADINGS = ['产物失效记录', 'Artifact Invalidation'] as const;
|
|
4
|
+
const OPERATION_COLUMNS = [
|
|
5
|
+
'operation_id', 'source_family', 'source_artifact', 'source_round', 'source_sha256',
|
|
6
|
+
'status', 'processed', 'total', 'created_at', 'updated_at', 'completed_at', 'error'
|
|
7
|
+
] as const;
|
|
8
|
+
const TARGET_COLUMNS = [
|
|
9
|
+
'target_id', 'operation_id', 'target_kind', 'target_family', 'target_artifact',
|
|
10
|
+
'target_round', 'target_sha256', 'status', 'reason_code', 'updated_at'
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
type InvalidationStatus = 'pending' | 'in-progress' | 'completed';
|
|
14
|
+
type InvalidationTargetKind = 'artifact' | 'receipt' | 'approval' | 'reviewed-snapshot';
|
|
15
|
+
type InvalidationOperation = {
|
|
16
|
+
operationId: string;
|
|
17
|
+
sourceFamily: string;
|
|
18
|
+
sourceArtifact: string;
|
|
19
|
+
sourceRound: number;
|
|
20
|
+
sourceSha256: string;
|
|
21
|
+
status: InvalidationStatus;
|
|
22
|
+
processed: number;
|
|
23
|
+
total: number;
|
|
24
|
+
createdAt: string;
|
|
25
|
+
updatedAt: string;
|
|
26
|
+
completedAt: string;
|
|
27
|
+
error: string;
|
|
28
|
+
};
|
|
29
|
+
type InvalidationTarget = {
|
|
30
|
+
targetId: string;
|
|
31
|
+
operationId: string;
|
|
32
|
+
targetKind: InvalidationTargetKind;
|
|
33
|
+
targetFamily: string;
|
|
34
|
+
targetArtifact: string;
|
|
35
|
+
targetRound: number;
|
|
36
|
+
targetSha256: string;
|
|
37
|
+
status: InvalidationStatus;
|
|
38
|
+
reasonCode: string;
|
|
39
|
+
updatedAt: string;
|
|
40
|
+
};
|
|
41
|
+
type InvalidationDocument = {
|
|
42
|
+
operations: readonly InvalidationOperation[];
|
|
43
|
+
targets: readonly InvalidationTarget[];
|
|
44
|
+
};
|
|
45
|
+
type InvalidationParseResult =
|
|
46
|
+
| { ok: true; present: boolean; document: InvalidationDocument }
|
|
47
|
+
| { ok: false; code: 'TASK_INVALIDATION_INVALID'; message: string };
|
|
48
|
+
type InvalidationMutationResult = {
|
|
49
|
+
ok: true;
|
|
50
|
+
changed: boolean;
|
|
51
|
+
document: InvalidationDocument;
|
|
52
|
+
} | {
|
|
53
|
+
ok: false;
|
|
54
|
+
code: 'TASK_INVALIDATION_INVALID' | 'INVALIDATION_IDENTITY_CONFLICT';
|
|
55
|
+
message: string;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
function invalid(message: string): InvalidationParseResult {
|
|
59
|
+
return { ok: false, code: 'TASK_INVALIDATION_INVALID', message };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function hashIdentity(value: unknown): string {
|
|
63
|
+
return createHash('sha256').update(JSON.stringify(value)).digest('hex').slice(0, 16);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function operationIdFor(source: Pick<InvalidationOperation, 'sourceFamily' | 'sourceArtifact' | 'sourceRound' | 'sourceSha256'>): string {
|
|
67
|
+
return `INV-${hashIdentity([source.sourceFamily, source.sourceArtifact, source.sourceRound, source.sourceSha256])}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function targetIdFor(operationId: string, target: Pick<InvalidationTarget, 'targetKind' | 'targetFamily' | 'targetArtifact' | 'targetRound' | 'targetSha256'>): string {
|
|
71
|
+
return `INV-T-${hashIdentity([operationId, target.targetKind, target.targetFamily, target.targetArtifact, target.targetRound, target.targetSha256])}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function createInvalidationOperation(
|
|
75
|
+
source: Partial<Pick<InvalidationOperation, 'operationId'>> & Omit<InvalidationOperation, 'operationId' | 'status' | 'processed' | 'total' | 'completedAt' | 'error'>,
|
|
76
|
+
targets: readonly InvalidationTarget[] = []
|
|
77
|
+
): InvalidationOperation {
|
|
78
|
+
const operationId = source.operationId ?? operationIdFor(source);
|
|
79
|
+
return {
|
|
80
|
+
operationId, sourceFamily: source.sourceFamily, sourceArtifact: source.sourceArtifact,
|
|
81
|
+
sourceRound: source.sourceRound, sourceSha256: source.sourceSha256,
|
|
82
|
+
status: 'pending', processed: 0, total: targets.length,
|
|
83
|
+
createdAt: source.createdAt, updatedAt: source.updatedAt, completedAt: '', error: ''
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function lineCells(line: string): string[] | null {
|
|
88
|
+
const first = line.indexOf('|');
|
|
89
|
+
const last = line.lastIndexOf('|');
|
|
90
|
+
if (first < 0 || first === last || line.slice(0, first).trim() || line.slice(last + 1).trim()) return null;
|
|
91
|
+
const inner = line.slice(first + 1, last);
|
|
92
|
+
const cells: string[] = [];
|
|
93
|
+
let start = 0;
|
|
94
|
+
let escaped = false;
|
|
95
|
+
for (let index = 0; index < inner.length; index += 1) {
|
|
96
|
+
const char = inner[index]!;
|
|
97
|
+
if (char === '|' && !escaped) {
|
|
98
|
+
cells.push(inner.slice(start, index));
|
|
99
|
+
start = index + 1;
|
|
100
|
+
}
|
|
101
|
+
escaped = char === '\\' && !escaped;
|
|
102
|
+
if (char !== '\\') escaped = false;
|
|
103
|
+
}
|
|
104
|
+
cells.push(inner.slice(start));
|
|
105
|
+
return cells.map((cell) => cell.replace(/\\([\\|])/g, '$1').trim());
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function isSeparator(cells: readonly string[], count: number): boolean {
|
|
109
|
+
return cells.length === count && cells.every((cell) => /^:?-{3,}:?$/.test(cell));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function sectionBody(content: string): string | null {
|
|
113
|
+
const heading = INVALIDATION_HEADINGS.map((value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|');
|
|
114
|
+
const match = new RegExp(`^##\\s+(${heading})\\s*$`, 'm').exec(content);
|
|
115
|
+
if (!match) return null;
|
|
116
|
+
const start = (match.index ?? 0) + match[0].length;
|
|
117
|
+
const rest = content.slice(start);
|
|
118
|
+
const end = rest.search(/^##\s+/m);
|
|
119
|
+
return rest.slice(0, end < 0 ? rest.length : end);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function parseTable(body: string, heading: string, columns: readonly string[]): Record<string, string>[] | null | false {
|
|
123
|
+
const marker = new RegExp(`^###\\s+${heading}\\s*$`, 'm').exec(body);
|
|
124
|
+
if (!marker) return null;
|
|
125
|
+
const start = (marker.index ?? 0) + marker[0].length;
|
|
126
|
+
const rest = body.slice(start);
|
|
127
|
+
const end = rest.search(/^###\s+/m);
|
|
128
|
+
const lines = rest.slice(0, end < 0 ? rest.length : end).split(/\r?\n/).filter((line) => line.trim());
|
|
129
|
+
const header = lines.length > 0 ? lineCells(lines[0]!) : null;
|
|
130
|
+
const separator = lines.length > 1 ? lineCells(lines[1]!) : null;
|
|
131
|
+
if (!header || !separator || header.length !== columns.length || !header.every((value, index) => value === columns[index]) || !isSeparator(separator, columns.length)) return false;
|
|
132
|
+
const rows: Record<string, string>[] = [];
|
|
133
|
+
for (const line of lines.slice(2)) {
|
|
134
|
+
const cells = lineCells(line);
|
|
135
|
+
if (!cells || cells.length !== columns.length) return false;
|
|
136
|
+
rows.push(Object.fromEntries(columns.map((column, index) => [column, cells[index]!])));
|
|
137
|
+
}
|
|
138
|
+
return rows;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function required(value: string, field: string): string {
|
|
142
|
+
if (!value) throw new Error(`${field} is required`);
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function status(value: string, field: string): InvalidationStatus {
|
|
147
|
+
if (value !== 'pending' && value !== 'in-progress' && value !== 'completed') throw new Error(`${field} has an invalid status`);
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function numberValue(value: string, field: string, allowZero = true): number {
|
|
152
|
+
const parsed = Number(value);
|
|
153
|
+
if (!Number.isInteger(parsed) || (allowZero ? parsed < 0 : parsed < 1)) throw new Error(`${field} must be an integer`);
|
|
154
|
+
return parsed;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function parseInvalidationDocument(content: string): InvalidationParseResult {
|
|
158
|
+
const body = sectionBody(content);
|
|
159
|
+
if (body === null) return { ok: true, present: false, document: { operations: [], targets: [] } };
|
|
160
|
+
try {
|
|
161
|
+
const operationRows = parseTable(body, 'Operations', OPERATION_COLUMNS);
|
|
162
|
+
const targetRows = parseTable(body, 'Targets', TARGET_COLUMNS);
|
|
163
|
+
if (operationRows === null || targetRows === null || operationRows === false || targetRows === false) {
|
|
164
|
+
return invalid('invalidation section must contain Operations and Targets tables');
|
|
165
|
+
}
|
|
166
|
+
const operations = operationRows.map((row) => ({
|
|
167
|
+
operationId: required(row.operation_id!, 'operation_id'), sourceFamily: required(row.source_family!, 'source_family'),
|
|
168
|
+
sourceArtifact: required(row.source_artifact!, 'source_artifact'), sourceRound: numberValue(row.source_round!, 'source_round', false),
|
|
169
|
+
sourceSha256: required(row.source_sha256!, 'source_sha256'), status: status(row.status!, 'operation status'),
|
|
170
|
+
processed: numberValue(row.processed!, 'processed'), total: numberValue(row.total!, 'total'),
|
|
171
|
+
createdAt: required(row.created_at!, 'created_at'), updatedAt: required(row.updated_at!, 'updated_at'),
|
|
172
|
+
completedAt: row.completed_at ?? '', error: row.error ?? ''
|
|
173
|
+
} satisfies InvalidationOperation));
|
|
174
|
+
const targets = targetRows.map((row) => ({
|
|
175
|
+
targetId: required(row.target_id!, 'target_id'), operationId: required(row.operation_id!, 'operation_id'),
|
|
176
|
+
targetKind: row.target_kind as InvalidationTargetKind, targetFamily: required(row.target_family!, 'target_family'),
|
|
177
|
+
targetArtifact: required(row.target_artifact!, 'target_artifact'), targetRound: numberValue(row.target_round!, 'target_round', false),
|
|
178
|
+
targetSha256: required(row.target_sha256!, 'target_sha256'), status: status(row.status!, 'target status'),
|
|
179
|
+
reasonCode: required(row.reason_code!, 'reason_code'), updatedAt: required(row.updated_at!, 'updated_at')
|
|
180
|
+
} satisfies InvalidationTarget));
|
|
181
|
+
const operationIds = new Set<string>();
|
|
182
|
+
for (const operation of operations) {
|
|
183
|
+
if (operationIds.has(operation.operationId)) throw new Error(`duplicate operation '${operation.operationId}'`);
|
|
184
|
+
operationIds.add(operation.operationId);
|
|
185
|
+
if (operation.operationId !== operationIdFor(operation)) throw new Error(`operation '${operation.operationId}' has a non-canonical identity`);
|
|
186
|
+
if (operation.processed > operation.total) throw new Error(`operation '${operation.operationId}' progress is invalid`);
|
|
187
|
+
if (!/^[a-f0-9]{64}$/.test(operation.sourceSha256)) throw new Error(`operation '${operation.operationId}' source hash is invalid`);
|
|
188
|
+
}
|
|
189
|
+
const targetIds = new Set<string>();
|
|
190
|
+
for (const target of targets) {
|
|
191
|
+
if (!['artifact', 'receipt', 'approval', 'reviewed-snapshot'].includes(target.targetKind)) throw new Error(`target '${target.targetId}' kind is invalid`);
|
|
192
|
+
if (targetIds.has(target.targetId)) throw new Error(`duplicate target '${target.targetId}'`);
|
|
193
|
+
targetIds.add(target.targetId);
|
|
194
|
+
if (!operationIds.has(target.operationId)) throw new Error(`target '${target.targetId}' references an unknown operation`);
|
|
195
|
+
if (target.targetId !== targetIdFor(target.operationId, target)) throw new Error(`target '${target.targetId}' has a non-canonical identity`);
|
|
196
|
+
if (!/^[a-f0-9]{64}$/.test(target.targetSha256)) throw new Error(`target '${target.targetId}' hash is invalid`);
|
|
197
|
+
}
|
|
198
|
+
for (const operation of operations) {
|
|
199
|
+
const scoped = targets.filter((target) => target.operationId === operation.operationId);
|
|
200
|
+
const completed = scoped.filter((target) => target.status === 'completed').length;
|
|
201
|
+
if (operation.total !== scoped.length || operation.processed !== completed) throw new Error(`operation '${operation.operationId}' progress does not match its targets`);
|
|
202
|
+
if (operation.status === 'completed' && (completed !== scoped.length || !operation.completedAt)) throw new Error(`completed operation '${operation.operationId}' has incomplete targets`);
|
|
203
|
+
if (operation.status === 'pending' && completed !== 0) throw new Error(`pending operation '${operation.operationId}' has completed targets`);
|
|
204
|
+
if (operation.status === 'in-progress' && (completed === scoped.length || (completed === 0 && !scoped.some((target) => target.status === 'in-progress')))) throw new Error(`in-progress operation '${operation.operationId}' has invalid progress`);
|
|
205
|
+
}
|
|
206
|
+
return { ok: true, present: true, document: { operations, targets } };
|
|
207
|
+
} catch (error) {
|
|
208
|
+
return invalid(error instanceof Error ? error.message : String(error));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function cell(value: string | number): string {
|
|
213
|
+
return String(value).replace(/\\/g, '\\\\').replace(/\|/g, '\\|').replace(/[\r\n]/g, ' ');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function table(columns: readonly string[], rows: readonly (readonly (string | number)[])[]): string {
|
|
217
|
+
const header = `| ${columns.join(' | ')} |`;
|
|
218
|
+
const separator = `| ${columns.map(() => '---').join(' | ')} |`;
|
|
219
|
+
return [header, separator, ...rows.map((row) => `| ${row.map(cell).join(' | ')} |`)].join('\n');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function renderInvalidation(document: InvalidationDocument): string {
|
|
223
|
+
const operations = [...document.operations].sort((left, right) => left.operationId.localeCompare(right.operationId));
|
|
224
|
+
const targets = [...document.targets].sort((left, right) => left.targetId.localeCompare(right.targetId));
|
|
225
|
+
return [
|
|
226
|
+
'### Operations', '',
|
|
227
|
+
table(OPERATION_COLUMNS, operations.map((row) => [
|
|
228
|
+
row.operationId, row.sourceFamily, row.sourceArtifact, row.sourceRound, row.sourceSha256,
|
|
229
|
+
row.status, row.processed, row.total, row.createdAt, row.updatedAt, row.completedAt, row.error
|
|
230
|
+
])), '',
|
|
231
|
+
'### Targets', '',
|
|
232
|
+
table(TARGET_COLUMNS, targets.map((row) => [
|
|
233
|
+
row.targetId, row.operationId, row.targetKind, row.targetFamily, row.targetArtifact,
|
|
234
|
+
row.targetRound, row.targetSha256, row.status, row.reasonCode, row.updatedAt
|
|
235
|
+
]))
|
|
236
|
+
].join('\n');
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function reconcileInvalidation(document: InvalidationDocument, now: string, maxTargets = Number.POSITIVE_INFINITY): InvalidationMutationResult {
|
|
240
|
+
const nextTargets = document.targets.map((target) => {
|
|
241
|
+
if (target.status === 'completed' || maxTargets <= 0) return target;
|
|
242
|
+
maxTargets -= 1;
|
|
243
|
+
return { ...target, status: 'completed' as const, updatedAt: now };
|
|
244
|
+
});
|
|
245
|
+
const changed = nextTargets.some((target, index) => target !== document.targets[index]);
|
|
246
|
+
const nextOperations = document.operations.map((operation) => {
|
|
247
|
+
const scoped = nextTargets.filter((target) => target.operationId === operation.operationId);
|
|
248
|
+
const processed = scoped.filter((target) => target.status === 'completed').length;
|
|
249
|
+
const total = scoped.length;
|
|
250
|
+
const complete = total === processed;
|
|
251
|
+
const nextStatus: InvalidationStatus = complete ? 'completed' : processed > 0 ? 'in-progress' : 'pending';
|
|
252
|
+
if (operation.status === nextStatus && operation.processed === processed && operation.total === total && (!complete || operation.completedAt)) return operation;
|
|
253
|
+
return {
|
|
254
|
+
...operation, status: nextStatus, processed, total, updatedAt: changed ? now : operation.updatedAt,
|
|
255
|
+
completedAt: complete ? (operation.completedAt || now) : ''
|
|
256
|
+
};
|
|
257
|
+
});
|
|
258
|
+
const operationChanged = nextOperations.some((operation, index) => operation !== document.operations[index]);
|
|
259
|
+
return { ok: true, changed: changed || operationChanged, document: { operations: nextOperations, targets: nextTargets } };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function upsertInvalidation(
|
|
263
|
+
document: InvalidationDocument,
|
|
264
|
+
operation: InvalidationOperation,
|
|
265
|
+
targets: readonly InvalidationTarget[]
|
|
266
|
+
): InvalidationMutationResult {
|
|
267
|
+
const existing = document.operations.find((candidate) => candidate.operationId === operation.operationId);
|
|
268
|
+
if (existing && JSON.stringify(existing) !== JSON.stringify(operation)) {
|
|
269
|
+
return { ok: false, code: 'INVALIDATION_IDENTITY_CONFLICT', message: `operation '${operation.operationId}' identity conflicts with existing state` };
|
|
270
|
+
}
|
|
271
|
+
const existingTargets = document.targets.filter((target) => target.operationId === operation.operationId);
|
|
272
|
+
for (const target of targets) {
|
|
273
|
+
const old = existingTargets.find((candidate) => candidate.targetId === target.targetId);
|
|
274
|
+
if (old && JSON.stringify(old) !== JSON.stringify(target)) {
|
|
275
|
+
return { ok: false, code: 'INVALIDATION_IDENTITY_CONFLICT', message: `target '${target.targetId}' identity conflicts with existing state` };
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (existing) return { ok: true, changed: false, document };
|
|
279
|
+
return {
|
|
280
|
+
ok: true, changed: true,
|
|
281
|
+
document: { operations: [...document.operations, operation], targets: [...document.targets, ...targets] }
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function invalidationBlocks(document: InvalidationDocument): boolean {
|
|
286
|
+
return document.operations.some((operation) => operation.status !== 'completed')
|
|
287
|
+
|| document.targets.some((target) => target.status !== 'completed');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function isArtifactInvalidated(document: InvalidationDocument, family: string, artifact: string): boolean {
|
|
291
|
+
return document.targets.some((target) =>
|
|
292
|
+
target.status === 'completed'
|
|
293
|
+
&& target.targetKind === 'artifact'
|
|
294
|
+
&& target.targetFamily === family
|
|
295
|
+
&& target.targetArtifact === artifact
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function invalidationMutation(content: string, document: InvalidationDocument) {
|
|
300
|
+
const existing = sectionBody(content) !== null;
|
|
301
|
+
return {
|
|
302
|
+
kind: 'section' as const,
|
|
303
|
+
aliases: INVALIDATION_HEADINGS,
|
|
304
|
+
heading: existing && /^##\s+Artifact Invalidation\s*$/m.test(content) ? INVALIDATION_HEADINGS[1] : INVALIDATION_HEADINGS[0],
|
|
305
|
+
body: renderInvalidation(document)
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export {
|
|
310
|
+
INVALIDATION_HEADINGS,
|
|
311
|
+
OPERATION_COLUMNS,
|
|
312
|
+
TARGET_COLUMNS,
|
|
313
|
+
createInvalidationOperation,
|
|
314
|
+
isArtifactInvalidated,
|
|
315
|
+
invalidationBlocks,
|
|
316
|
+
invalidationMutation,
|
|
317
|
+
operationIdFor,
|
|
318
|
+
parseInvalidationDocument,
|
|
319
|
+
reconcileInvalidation,
|
|
320
|
+
renderInvalidation,
|
|
321
|
+
targetIdFor,
|
|
322
|
+
upsertInvalidation
|
|
323
|
+
};
|
|
324
|
+
export type {
|
|
325
|
+
InvalidationDocument,
|
|
326
|
+
InvalidationMutationResult,
|
|
327
|
+
InvalidationOperation,
|
|
328
|
+
InvalidationParseResult,
|
|
329
|
+
InvalidationStatus,
|
|
330
|
+
InvalidationTarget,
|
|
331
|
+
InvalidationTargetKind
|
|
332
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
3
4
|
|
|
4
5
|
import {
|
|
5
6
|
declareImplementationInput,
|
|
@@ -13,6 +14,8 @@ import { resolveTaskRef } from './resolve-ref.ts';
|
|
|
13
14
|
import { writeTask } from './write.ts';
|
|
14
15
|
import type { TaskMutation, TaskOperationSummary, TaskWriteOptions } from './write.ts';
|
|
15
16
|
import { allowsManualOverride } from './guard-override.ts';
|
|
17
|
+
import { parseReworkIntentDocument, reworkIntentMutation, upsertReworkIntent } from './rework-intent.ts';
|
|
18
|
+
import type { ReworkIntent, ReworkTarget } from './rework-intent.ts';
|
|
16
19
|
|
|
17
20
|
type ReviewSeverity = 'blocker' | 'major' | 'minor';
|
|
18
21
|
type ExecutorResponse = 'accepted' | 'adjusted' | 'refuted' | 'cannot-judge';
|
|
@@ -22,7 +25,8 @@ type LedgerIntent =
|
|
|
22
25
|
| { kind: 'finding-respond'; taskRef: string; id: string; round: number; status: ExecutorResponse; evidence: string; dryRun?: boolean }
|
|
23
26
|
| { kind: 'finding-review'; taskRef: string; id: string; status: ReviewDisposition; evidence: string; needsImplementation?: boolean; dryRun?: boolean }
|
|
24
27
|
| { kind: 'decision-next-id'; taskRef: string }
|
|
25
|
-
| { kind: 'decision-upsert'; taskRef: string; id: string; stage: ReviewStage; artifact: string; needsImplementation?: boolean; dryRun?: boolean }
|
|
28
|
+
| { kind: 'decision-upsert'; taskRef: string; id: string; stage: ReviewStage; artifact: string; needsImplementation?: boolean; dryRun?: boolean }
|
|
29
|
+
| { kind: 'rework-intent-upsert'; taskRef: string; intentId: string; findingId: string; sourceArtifact: string; sourceSha256: string; target: ReworkTarget; dryRun?: boolean };
|
|
26
30
|
|
|
27
31
|
type LedgerIntentError = { code: string; message: string };
|
|
28
32
|
type LedgerIntentResult = {
|
|
@@ -136,6 +140,36 @@ function applyLedgerIntent(intent: LedgerIntent, options: TaskWriteOptions = {})
|
|
|
136
140
|
return { status: 'no-op', changed: false, intent: intent.kind, taskId: resolved.taskId, entityId: nextHdId(rows), before: null, after: null, operations: [], error: null };
|
|
137
141
|
}
|
|
138
142
|
|
|
143
|
+
if (intent.kind === 'rework-intent-upsert') {
|
|
144
|
+
if (!/^RI-[1-9]\d*$/.test(intent.intentId) || !/^(AN|PL|CD)-[1-9]\d*$/.test(intent.findingId) || !['analysis', 'plan', 'code'].includes(intent.target) || !/^[a-f0-9]{64}$/.test(intent.sourceSha256)) {
|
|
145
|
+
return failed(intent, 'LEDGER_PAYLOAD_INVALID', 'rework intent identity, target, or source hash is invalid', resolved.taskId, intent.intentId);
|
|
146
|
+
}
|
|
147
|
+
const finding = rows.find((row) => row.id === intent.findingId);
|
|
148
|
+
if (!finding || finding.severity === 'decision') return failed(intent, 'LEDGER_NOT_FOUND', `finding '${intent.findingId}' was not found`, resolved.taskId, intent.findingId);
|
|
149
|
+
const sourceFromEvidence = finding.evidence.split('#')[0];
|
|
150
|
+
if (sourceFromEvidence !== intent.sourceArtifact || !REVIEW_ARTIFACT[finding.stage as ReviewStage]?.test(intent.sourceArtifact)) {
|
|
151
|
+
return failed(intent, 'LEDGER_IDENTITY_CONFLICT', 'rework intent source artifact does not match finding evidence', resolved.taskId, intent.intentId);
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
const actualHash = createHash('sha256').update(fs.readFileSync(path.join(resolved.taskDir, intent.sourceArtifact))).digest('hex');
|
|
155
|
+
if (actualHash !== intent.sourceSha256) return failed(intent, 'LEDGER_IDENTITY_CONFLICT', 'rework intent source artifact hash does not match', resolved.taskId, intent.intentId);
|
|
156
|
+
const parsed = parseReworkIntentDocument(content);
|
|
157
|
+
if (!parsed.ok) return failed(intent, parsed.code, parsed.message, resolved.taskId, intent.intentId);
|
|
158
|
+
const nextIntent: ReworkIntent = {
|
|
159
|
+
intentId: intent.intentId, findingId: intent.findingId, sourceArtifact: intent.sourceArtifact,
|
|
160
|
+
sourceSha256: intent.sourceSha256, target: intent.target, status: 'pending',
|
|
161
|
+
declaredAt: new Date().toISOString(), consumedAt: ''
|
|
162
|
+
};
|
|
163
|
+
const next = upsertReworkIntent(parsed.intents, nextIntent);
|
|
164
|
+
if (!next.changed) return { status: 'no-op', changed: false, intent: intent.kind, taskId: resolved.taskId, entityId: intent.intentId, before: null, after: null, operations: [], error: null };
|
|
165
|
+
const result = writeTask({ taskRef: intent.taskRef, expectedState: 'active', dryRun: intent.dryRun, mutations: [reworkIntentMutation(content, next.intents)] }, { ...options, taskLocation: { repoRoot: resolved.repoRoot, taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, state: resolved.state } });
|
|
166
|
+
if (result.status === 'failed') return failed(intent, result.error.code, result.error.message, result.taskId, intent.intentId);
|
|
167
|
+
return { status: result.status, changed: result.changed, intent: intent.kind, taskId: result.taskId, entityId: intent.intentId, before: null, after: null, operations: result.operations, error: null };
|
|
168
|
+
} catch (error) {
|
|
169
|
+
return failed(intent, 'LEDGER_IDENTITY_CONFLICT', error instanceof Error ? error.message : String(error), resolved.taskId, intent.intentId);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
139
173
|
let before: LedgerRow | null = null;
|
|
140
174
|
let after: LedgerRow;
|
|
141
175
|
if (intent.kind === 'finding-upsert') {
|