@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
|
@@ -2,8 +2,8 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { parseArtifactName } from './artifact-name.ts';
|
|
6
|
+
import { validateCompletedArtifact, hasOpenArtifactRound, validateArtifactPublication } from './artifact-lifecycle.ts';
|
|
7
7
|
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.ts';
|
|
8
8
|
import type { LedgerStageStatus, ReviewStage } from './ledger.ts';
|
|
9
9
|
import { finalizeReviewSummaryContent } from './review-artifacts.ts';
|
|
@@ -14,6 +14,11 @@ import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-
|
|
|
14
14
|
import type { ResolveTaskRefErrorCode } from './resolve-ref.ts';
|
|
15
15
|
import { allowsManualOverride } from './guard-override.ts';
|
|
16
16
|
import type { ManualOverrideCapability } from './guard-override.ts';
|
|
17
|
+
import { getArtifactSchema } from './artifact-schema.ts';
|
|
18
|
+
import { canonicalSemanticDigest, inspectArtifactContract, sha256Content } from './artifact-operations.ts';
|
|
19
|
+
import { readArtifactRepairIntent, writeArtifactRepairIntent } from './artifact-repair-intent.ts';
|
|
20
|
+
import type { ArtifactRepairOperation } from './artifact-operations.ts';
|
|
21
|
+
import type { ArtifactRepairIntent } from './artifact-repair-intent.ts';
|
|
17
22
|
|
|
18
23
|
type ReviewFinalizationErrorCode =
|
|
19
24
|
| ResolveTaskRefErrorCode
|
|
@@ -26,6 +31,7 @@ type ReviewFinalizationErrorCode =
|
|
|
26
31
|
| 'REVIEW_SUMMARY_NOT_FOUND'
|
|
27
32
|
| 'REVIEW_SUMMARY_PLACEHOLDER_INVALID'
|
|
28
33
|
| 'REVIEW_SUMMARY_COUNT_MISMATCH'
|
|
34
|
+
| 'REVIEW_ARTIFACT_STRUCTURE_INVALID'
|
|
29
35
|
| 'REVIEW_DECISION_DETAIL_INVALID'
|
|
30
36
|
| 'REVIEW_ARTIFACT_CONFLICT'
|
|
31
37
|
| 'REVIEW_PROVENANCE_INVALID'
|
|
@@ -48,6 +54,10 @@ type ReviewFinalizationResult = {
|
|
|
48
54
|
stage: string;
|
|
49
55
|
artifact: string;
|
|
50
56
|
stageStatus: LedgerStageStatus | null;
|
|
57
|
+
artifactSha256: string | null;
|
|
58
|
+
semanticDigest: string | null;
|
|
59
|
+
repairable: boolean;
|
|
60
|
+
operation: ArtifactRepairOperation | null;
|
|
51
61
|
operations: readonly {
|
|
52
62
|
kind: 'artifact';
|
|
53
63
|
artifact: string;
|
|
@@ -70,10 +80,10 @@ type ReviewFinalizationOptions = {
|
|
|
70
80
|
lockAlreadyHeld?: boolean;
|
|
71
81
|
};
|
|
72
82
|
|
|
73
|
-
const STAGES: Record<ReviewStage, { family: 'review-analysis' | 'review-plan' | 'review-code'
|
|
74
|
-
analysis: { family: 'review-analysis'
|
|
75
|
-
plan: { family: 'review-plan'
|
|
76
|
-
code: { family: 'review-code'
|
|
83
|
+
const STAGES: Record<ReviewStage, { family: 'review-analysis' | 'review-plan' | 'review-code' }> = {
|
|
84
|
+
analysis: { family: 'review-analysis' },
|
|
85
|
+
plan: { family: 'review-plan' },
|
|
86
|
+
code: { family: 'review-code' }
|
|
77
87
|
};
|
|
78
88
|
const DEFAULT_FILE_SYSTEM: ReviewFileSystem = {
|
|
79
89
|
readFileSync: (file) => fs.readFileSync(file, 'utf8'),
|
|
@@ -88,7 +98,8 @@ function failed(
|
|
|
88
98
|
code: ReviewFinalizationErrorCode,
|
|
89
99
|
message: string,
|
|
90
100
|
taskId: string | null = null,
|
|
91
|
-
stageStatus: LedgerStageStatus | null = null
|
|
101
|
+
stageStatus: LedgerStageStatus | null = null,
|
|
102
|
+
extra: Partial<ReviewFinalizationResult> = {}
|
|
92
103
|
): ReviewFinalizationResult {
|
|
93
104
|
return {
|
|
94
105
|
status: 'failed',
|
|
@@ -99,20 +110,16 @@ function failed(
|
|
|
99
110
|
stage: request.stage,
|
|
100
111
|
artifact: request.artifact,
|
|
101
112
|
stageStatus,
|
|
113
|
+
artifactSha256: null,
|
|
114
|
+
semanticDigest: null,
|
|
115
|
+
repairable: false,
|
|
116
|
+
operation: null,
|
|
102
117
|
operations: [],
|
|
103
|
-
error: { code, message }
|
|
118
|
+
error: { code, message },
|
|
119
|
+
...extra
|
|
104
120
|
};
|
|
105
121
|
}
|
|
106
122
|
|
|
107
|
-
function openReviewRound(content: string, action: string, round: number): boolean {
|
|
108
|
-
const section = locateActivityLog(content);
|
|
109
|
-
if (!section) return false;
|
|
110
|
-
const expected = `${action} (Round ${round})`;
|
|
111
|
-
return startedBackedRows(pairEntries(section.entries)).filter((row) => (
|
|
112
|
-
row.step === expected && !row.done
|
|
113
|
-
)).length === 1;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
123
|
function cleanupTemp(fileSystem: ReviewFileSystem, tempPath: string): void {
|
|
117
124
|
try {
|
|
118
125
|
fileSystem.unlinkSync(tempPath);
|
|
@@ -121,174 +128,167 @@ function cleanupTemp(fileSystem: ReviewFileSystem, tempPath: string): void {
|
|
|
121
128
|
}
|
|
122
129
|
}
|
|
123
130
|
|
|
124
|
-
|
|
131
|
+
type ReviewSummaryCandidatePreparation = Readonly<{
|
|
132
|
+
result: ReviewFinalizationResult;
|
|
133
|
+
content: string;
|
|
134
|
+
provenance?: Parameters<typeof writeArtifactRepairIntent>[1];
|
|
135
|
+
expectedIntent?: ArtifactRepairIntent | null;
|
|
136
|
+
}>;
|
|
137
|
+
|
|
138
|
+
/** Prepare domain validation, summary bytes and provenance before any publication. */
|
|
139
|
+
function prepareReviewSummaryCandidate(
|
|
125
140
|
request: ReviewFinalizationRequest,
|
|
141
|
+
artifactContent: string,
|
|
126
142
|
options: ReviewFinalizationOptions = {}
|
|
127
|
-
):
|
|
143
|
+
): ReviewSummaryCandidatePreparation {
|
|
144
|
+
let taskId: string | null = null;
|
|
145
|
+
let stageStatus: LedgerStageStatus | null = null;
|
|
146
|
+
const reject = (code: ReviewFinalizationErrorCode, message: string, extra: Partial<ReviewFinalizationResult> = {}): ReviewSummaryCandidatePreparation => ({
|
|
147
|
+
result: failed(request, code, message, taskId, stageStatus, extra), content: artifactContent
|
|
148
|
+
});
|
|
128
149
|
const stage = request.stage as ReviewStage;
|
|
129
150
|
const spec = STAGES[stage];
|
|
130
|
-
if (!spec) return
|
|
131
|
-
if (!request.taskRef || !request.artifact)
|
|
132
|
-
return failed(request, 'REVIEW_PAYLOAD_INVALID', 'taskRef, stage, and artifact are required');
|
|
133
|
-
}
|
|
151
|
+
if (!spec) return reject('REVIEW_STAGE_INVALID', `unsupported review stage '${request.stage}'`);
|
|
152
|
+
if (!request.taskRef || !request.artifact) return reject('REVIEW_PAYLOAD_INVALID', 'taskRef, stage, and artifact are required');
|
|
134
153
|
const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
|
|
135
|
-
|
|
154
|
+
taskId = resolved.taskId ?? null;
|
|
155
|
+
if (!resolved.ok) return reject(resolved.code, resolved.message);
|
|
136
156
|
if (resolved.state !== 'active' && !allowsManualOverride(options.manualOverride, 'review-finalization', 'TASK_STATE_MISMATCH')) {
|
|
137
|
-
return
|
|
157
|
+
return reject('TASK_STATE_MISMATCH', `task ${taskId} is ${resolved.state}, expected active`);
|
|
138
158
|
}
|
|
139
|
-
const
|
|
140
|
-
if (!
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
159
|
+
const parsed = parseArtifactName(request.artifact);
|
|
160
|
+
if (!parsed || parsed.family !== spec.family) return reject('REVIEW_ARTIFACT_IDENTITY_INVALID', `artifact '${request.artifact}' does not match ${spec.family}`);
|
|
161
|
+
const publicationError = validateArtifactPublication(resolved.taskDir, spec.family, request.artifact);
|
|
162
|
+
if (publicationError) return reject('REVIEW_ARTIFACT_IDENTITY_INVALID', publicationError.message);
|
|
163
|
+
let taskContent: string;
|
|
164
|
+
try { taskContent = (options.fileSystem?.readFileSync ?? DEFAULT_FILE_SYSTEM.readFileSync)(resolved.taskMdPath); }
|
|
165
|
+
catch (error) { return reject('REVIEW_ARTIFACT_NOT_REGULAR', String(error)); }
|
|
166
|
+
const artifactSha256 = sha256Content(artifactContent);
|
|
167
|
+
const semanticDigest = canonicalSemanticDigest(artifactContent);
|
|
168
|
+
const digests = { artifactSha256, semanticDigest };
|
|
169
|
+
let repairIntent;
|
|
170
|
+
try { repairIntent = readArtifactRepairIntent(resolved.repoRoot, taskId!, spec.family, request.artifact); }
|
|
171
|
+
catch (error) { return reject('REVIEW_PROVENANCE_INVALID', String(error), digests); }
|
|
172
|
+
const schema = getArtifactSchema(spec.family)!;
|
|
173
|
+
const structure = inspectArtifactContract(artifactContent, schema);
|
|
174
|
+
if (!structure.ok) {
|
|
175
|
+
const repairable = structure.repair !== null && structure.diagnostics.length === 1 && structure.diagnostics[0]?.repairable === true;
|
|
176
|
+
if (repairable && repairIntent && (repairIntent.state !== 'awaiting-repair'
|
|
177
|
+
|| repairIntent.artifactSha256 !== artifactSha256 || repairIntent.semanticDigest !== structure.semanticDigest)) {
|
|
178
|
+
return reject('REVIEW_PROVENANCE_INVALID', 'a different review repair baseline is already recorded for this artifact', digests);
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
...reject('REVIEW_ARTIFACT_STRUCTURE_INVALID', structure.diagnostics.map((item) => `${item.code}: ${item.message}`).join('; '), {
|
|
182
|
+
artifactSha256, semanticDigest: structure.semanticDigest, repairable, operation: structure.repair
|
|
183
|
+
}),
|
|
184
|
+
...(repairable && !repairIntent ? { provenance: {
|
|
185
|
+
version: 2 as const, taskId: taskId!, family: spec.family, artifact: request.artifact,
|
|
186
|
+
state: 'awaiting-repair' as const, baselineSemanticDigest: structure.semanticDigest,
|
|
187
|
+
artifactSha256, semanticDigest: structure.semanticDigest,
|
|
188
|
+
recoveryOperationId: null, phase: null, authorityDigest: null,
|
|
189
|
+
requestId: `review-finalize:${taskId!}`, createdAt: Date.now(), updatedAt: Date.now()
|
|
190
|
+
}, expectedIntent: null } : {})
|
|
191
|
+
};
|
|
147
192
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
spec.family,
|
|
151
|
-
request.artifact,
|
|
152
|
-
parsedArtifact.round
|
|
153
|
-
);
|
|
154
|
-
if (!validated.ok) {
|
|
155
|
-
const code = validated.error.code === 'ARTIFACT_NOT_REGULAR'
|
|
156
|
-
? 'REVIEW_ARTIFACT_NOT_REGULAR'
|
|
157
|
-
: 'REVIEW_ARTIFACT_IDENTITY_INVALID';
|
|
158
|
-
return failed(request, code, validated.error.message, resolved.taskId);
|
|
193
|
+
if (repairIntent?.state === 'awaiting-repair' && repairIntent.baselineSemanticDigest !== semanticDigest) {
|
|
194
|
+
return reject('REVIEW_PROVENANCE_INVALID', 'the repaired review artifact semantic digest does not match the recorded repair baseline', digests);
|
|
159
195
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
let artifactContent: string;
|
|
164
|
-
try {
|
|
165
|
-
taskContent = fileSystem.readFileSync(resolved.taskMdPath);
|
|
166
|
-
artifactContent = fileSystem.readFileSync(validated.artifact.path);
|
|
167
|
-
} catch (error) {
|
|
168
|
-
return failed(request, 'REVIEW_ARTIFACT_NOT_REGULAR', String(error), resolved.taskId);
|
|
196
|
+
if ((repairIntent?.state === 'passed' || repairIntent?.state === 'consumed')
|
|
197
|
+
&& (repairIntent.artifactSha256 !== artifactSha256 || repairIntent.semanticDigest !== semanticDigest)) {
|
|
198
|
+
return reject('REVIEW_PROVENANCE_INVALID', 'the review artifact changed after its finalization provenance was recorded', digests);
|
|
169
199
|
}
|
|
170
|
-
if (!
|
|
171
|
-
return
|
|
172
|
-
request,
|
|
173
|
-
'REVIEW_ARTIFACT_IDENTITY_INVALID',
|
|
174
|
-
`${request.artifact} does not have one matching open started review event`,
|
|
175
|
-
resolved.taskId
|
|
176
|
-
);
|
|
200
|
+
if (!hasOpenArtifactRound(taskContent, spec.family, parsed.round)) {
|
|
201
|
+
return reject('REVIEW_ARTIFACT_IDENTITY_INVALID', `${request.artifact} does not have one matching open started review event`);
|
|
177
202
|
}
|
|
178
203
|
const execution = validateLifecycleExecution(request.taskRef, {
|
|
179
204
|
mode: request.orchestrated ? 'orchestrated' : 'standalone',
|
|
180
|
-
identity: {
|
|
181
|
-
stage: spec.family,
|
|
182
|
-
round: parsedArtifact.round,
|
|
183
|
-
artifact: request.artifact,
|
|
184
|
-
role: 'reviewer'
|
|
185
|
-
},
|
|
205
|
+
identity: { stage: spec.family, round: parsed.round, artifact: request.artifact, role: 'reviewer' },
|
|
186
206
|
dryRun: request.dryRun
|
|
187
207
|
}, { repoRoot: options.repoRoot });
|
|
188
208
|
if (!execution.ok) {
|
|
189
|
-
return failed
|
|
190
|
-
request,
|
|
191
|
-
'REVIEW_PROVENANCE_INVALID',
|
|
192
|
-
`${execution.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH'}: ${execution.error?.message ?? 'orchestration provenance validation failed'}`,
|
|
193
|
-
resolved.taskId
|
|
194
|
-
);
|
|
209
|
+
return reject('REVIEW_PROVENANCE_INVALID', `${execution.error?.code ?? 'ORCHESTRATION_PROVENANCE_MISMATCH'}: ${execution.error?.message ?? 'orchestration provenance validation failed'}`);
|
|
195
210
|
}
|
|
196
|
-
|
|
197
|
-
let rows;
|
|
198
211
|
try {
|
|
199
212
|
const ledger = parseLedgerDocument(taskContent);
|
|
200
|
-
if (!ledger.present) {
|
|
201
|
-
|
|
213
|
+
if (!ledger.present) return reject('REVIEW_LEDGER_INVALID', `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`);
|
|
214
|
+
const error = validateLedgerRows(ledger.rows);
|
|
215
|
+
if (error) return reject('REVIEW_LEDGER_INVALID', `${error.code}: ${error.message}`);
|
|
216
|
+
stageStatus = summarizeLedgerStage(ledger.rows, stage);
|
|
217
|
+
} catch (error) { return reject('REVIEW_LEDGER_INVALID', String(error)); }
|
|
218
|
+
const detail = inspectDecisionDetailDuplicates(artifactContent);
|
|
219
|
+
if (!detail.ok) return reject('REVIEW_DECISION_DETAIL_INVALID', `${detail.code}: ${detail.message}`);
|
|
220
|
+
const transformed = finalizeReviewSummaryContent(artifactContent, stageStatus.unresolvedFindingCounts);
|
|
221
|
+
if (!transformed.ok) return reject(transformed.code, transformed.message);
|
|
222
|
+
const finalDigests = { artifactSha256: sha256Content(transformed.content), semanticDigest: canonicalSemanticDigest(transformed.content) };
|
|
223
|
+
return {
|
|
224
|
+
content: transformed.content,
|
|
225
|
+
result: {
|
|
226
|
+
...failed(request, 'REVIEW_ARTIFACT_CONFLICT', '', taskId, stageStatus, finalDigests),
|
|
227
|
+
status: transformed.changed ? request.dryRun ? 'planned' : 'applied' : 'no-op',
|
|
228
|
+
changed: transformed.changed,
|
|
229
|
+
operations: transformed.changed ? [{ kind: 'artifact', artifact: request.artifact, operation: 'update' }] : [],
|
|
230
|
+
error: null
|
|
231
|
+
},
|
|
232
|
+
...(repairIntent?.state === 'awaiting-repair' ? {
|
|
233
|
+
provenance: { ...repairIntent, state: 'passed' as const, ...finalDigests },
|
|
234
|
+
expectedIntent: repairIntent
|
|
235
|
+
} : {})
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function commitReviewSummaryProvenance(
|
|
240
|
+
prepared: ReviewSummaryCandidatePreparation,
|
|
241
|
+
repoRoot: string
|
|
242
|
+
): ReviewFinalizationResult {
|
|
243
|
+
try {
|
|
244
|
+
if (prepared.provenance) {
|
|
245
|
+
writeArtifactRepairIntent(repoRoot, prepared.provenance, { expected: prepared.expectedIntent ?? null });
|
|
202
246
|
}
|
|
203
|
-
|
|
247
|
+
return prepared.result;
|
|
204
248
|
} catch (error) {
|
|
205
|
-
return
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (ledgerError) {
|
|
209
|
-
return failed(
|
|
210
|
-
request,
|
|
211
|
-
'REVIEW_LEDGER_INVALID',
|
|
212
|
-
`${ledgerError.code}: ${ledgerError.message}`,
|
|
213
|
-
resolved.taskId
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
const stageStatus = summarizeLedgerStage(rows, stage);
|
|
217
|
-
const detailInspection = inspectDecisionDetailDuplicates(artifactContent);
|
|
218
|
-
if (!detailInspection.ok) {
|
|
219
|
-
return failed(
|
|
220
|
-
request,
|
|
221
|
-
'REVIEW_DECISION_DETAIL_INVALID',
|
|
222
|
-
`${detailInspection.code}: ${detailInspection.message}`,
|
|
223
|
-
resolved.taskId,
|
|
224
|
-
stageStatus
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
const transformed = finalizeReviewSummaryContent(
|
|
228
|
-
artifactContent,
|
|
229
|
-
stageStatus.unresolvedFindingCounts
|
|
230
|
-
);
|
|
231
|
-
if (!transformed.ok) {
|
|
232
|
-
return failed(request, transformed.code, transformed.message, resolved.taskId, stageStatus);
|
|
233
|
-
}
|
|
234
|
-
if (!transformed.changed) {
|
|
235
|
-
return {
|
|
236
|
-
...failed(request, 'REVIEW_ARTIFACT_CONFLICT', '', resolved.taskId, stageStatus),
|
|
237
|
-
status: 'no-op',
|
|
238
|
-
error: null
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
const operations = [{ kind: 'artifact' as const, artifact: request.artifact, operation: 'update' as const }];
|
|
242
|
-
if (request.dryRun) {
|
|
243
|
-
return {
|
|
244
|
-
...failed(request, 'REVIEW_ARTIFACT_CONFLICT', '', resolved.taskId, stageStatus),
|
|
245
|
-
status: 'planned',
|
|
246
|
-
changed: true,
|
|
247
|
-
operations,
|
|
248
|
-
error: null
|
|
249
|
-
};
|
|
249
|
+
return { ...prepared.result, status: 'failed', error: {
|
|
250
|
+
code: 'REVIEW_PROVENANCE_INVALID', message: `cannot record review provenance: ${String(error)}`
|
|
251
|
+
} };
|
|
250
252
|
}
|
|
253
|
+
}
|
|
251
254
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
255
|
+
function finalizeReviewSummaryUnlocked(
|
|
256
|
+
request: ReviewFinalizationRequest,
|
|
257
|
+
options: ReviewFinalizationOptions = {}
|
|
258
|
+
): ReviewFinalizationResult {
|
|
259
|
+
const spec = STAGES[request.stage as ReviewStage];
|
|
260
|
+
if (!spec || !request.taskRef || !request.artifact) return prepareReviewSummaryCandidate(request, '', options).result;
|
|
261
|
+
const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
|
|
262
|
+
if (!resolved.ok) return failed(request, resolved.code, resolved.message, resolved.taskId);
|
|
263
|
+
const validated = validateCompletedArtifact(resolved.taskDir, spec.family, request.artifact);
|
|
264
|
+
if (!validated.ok) {
|
|
265
|
+
return failed(request, validated.error.code === 'ARTIFACT_NOT_REGULAR' ? 'REVIEW_ARTIFACT_NOT_REGULAR' : 'REVIEW_ARTIFACT_IDENTITY_INVALID', validated.error.message, resolved.taskId);
|
|
266
|
+
}
|
|
267
|
+
const fileSystem = { ...DEFAULT_FILE_SYSTEM, ...options.fileSystem };
|
|
268
|
+
let content: string;
|
|
269
|
+
try { content = fileSystem.readFileSync(validated.artifact.path); }
|
|
270
|
+
catch (error) { return failed(request, 'REVIEW_ARTIFACT_NOT_REGULAR', String(error), resolved.taskId); }
|
|
271
|
+
const prepared = prepareReviewSummaryCandidate(request, content, options);
|
|
272
|
+
if (request.dryRun) return prepared.result;
|
|
273
|
+
if (prepared.result.status !== 'applied') return commitReviewSummaryProvenance(prepared, resolved.repoRoot);
|
|
274
|
+
const tempPath = path.join(resolved.taskDir, `.${request.artifact}.tmp-${process.pid}-${(options.randomSuffix ?? randomUUID)()}`);
|
|
257
275
|
try {
|
|
258
|
-
|
|
259
|
-
fileSystem.writeFileSync(tempPath, transformed.content, mode);
|
|
276
|
+
fileSystem.writeFileSync(tempPath, prepared.content, fileSystem.statModeSync(validated.artifact.path));
|
|
260
277
|
} catch (error) {
|
|
261
278
|
cleanupTemp(fileSystem, tempPath);
|
|
262
|
-
return failed(request, 'REVIEW_TEMP_WRITE_FAILED', String(error), resolved.taskId, stageStatus);
|
|
279
|
+
return failed(request, 'REVIEW_TEMP_WRITE_FAILED', String(error), resolved.taskId, prepared.result.stageStatus);
|
|
263
280
|
}
|
|
264
281
|
try {
|
|
265
|
-
if (fileSystem.readFileSync(validated.artifact.path) !==
|
|
282
|
+
if (fileSystem.readFileSync(validated.artifact.path) !== content) {
|
|
266
283
|
cleanupTemp(fileSystem, tempPath);
|
|
267
|
-
return failed(
|
|
268
|
-
request,
|
|
269
|
-
'REVIEW_ARTIFACT_CONFLICT',
|
|
270
|
-
`${request.artifact} changed during finalization`,
|
|
271
|
-
resolved.taskId,
|
|
272
|
-
stageStatus
|
|
273
|
-
);
|
|
284
|
+
return failed(request, 'REVIEW_ARTIFACT_CONFLICT', `${request.artifact} changed during finalization`, resolved.taskId, prepared.result.stageStatus);
|
|
274
285
|
}
|
|
275
286
|
fileSystem.renameSync(tempPath, validated.artifact.path);
|
|
276
287
|
} catch (error) {
|
|
277
288
|
cleanupTemp(fileSystem, tempPath);
|
|
278
|
-
return failed(request, 'REVIEW_RENAME_FAILED', String(error), resolved.taskId, stageStatus);
|
|
289
|
+
return failed(request, 'REVIEW_RENAME_FAILED', String(error), resolved.taskId, prepared.result.stageStatus);
|
|
279
290
|
}
|
|
280
|
-
return
|
|
281
|
-
status: 'applied',
|
|
282
|
-
changed: true,
|
|
283
|
-
intent: 'finalize-summary',
|
|
284
|
-
requestRef: request.taskRef,
|
|
285
|
-
taskId: resolved.taskId,
|
|
286
|
-
stage,
|
|
287
|
-
artifact: request.artifact,
|
|
288
|
-
stageStatus,
|
|
289
|
-
operations,
|
|
290
|
-
error: null
|
|
291
|
-
};
|
|
291
|
+
return commitReviewSummaryProvenance(prepared, resolved.repoRoot);
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
function finalizeReviewSummary(
|
|
@@ -316,11 +316,12 @@ function finalizeReviewSummary(
|
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
-
export { finalizeReviewSummary };
|
|
319
|
+
export { finalizeReviewSummary, prepareReviewSummaryCandidate, commitReviewSummaryProvenance };
|
|
320
320
|
export type {
|
|
321
321
|
ReviewFinalizationError,
|
|
322
322
|
ReviewFinalizationErrorCode,
|
|
323
323
|
ReviewFinalizationOptions,
|
|
324
324
|
ReviewFinalizationRequest,
|
|
325
|
-
ReviewFinalizationResult
|
|
325
|
+
ReviewFinalizationResult,
|
|
326
|
+
ReviewSummaryCandidatePreparation
|
|
326
327
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
-
import { artifactName,
|
|
4
|
+
import { artifactName, maxArtifactRound } from "./artifact-name.ts";
|
|
5
5
|
import { invalidationBlocks, isArtifactInvalidated, parseInvalidationDocument } from "./invalidation.ts";
|
|
6
6
|
|
|
7
7
|
type ReviewedGitTree = string & { readonly __reviewedGitTree: unique symbol };
|
|
@@ -45,7 +45,7 @@ export function resolvePostReviewGlobs(
|
|
|
45
45
|
|
|
46
46
|
export function findAuthoritativeReviewCodeArtifact(taskDir: string) {
|
|
47
47
|
const entries = fs.existsSync(taskDir) ? fs.readdirSync(taskDir) : [];
|
|
48
|
-
const round =
|
|
48
|
+
const round = maxArtifactRound(entries, "review-code");
|
|
49
49
|
if (round === 0) {
|
|
50
50
|
return { ok: false, round: 0, fileName: null, path: null, error: null };
|
|
51
51
|
}
|
package/lib/task/sections.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FrontmatterScalar } from './frontmatter.ts';
|
|
2
|
+
import { scanVisibleMarkdown } from './markdown.ts';
|
|
2
3
|
|
|
3
4
|
function escapeRegExp(value: string): string {
|
|
4
5
|
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
@@ -93,12 +94,14 @@ function parseTable(
|
|
|
93
94
|
throw new DocumentMutationError('TASK_DOCUMENT_INVALID', 'table section is ambiguous');
|
|
94
95
|
}
|
|
95
96
|
const section = sections[0]!;
|
|
97
|
+
const visibleStarts = new Set(scanVisibleMarkdown(content).lines.map((line) => line.start));
|
|
96
98
|
const sectionLines = linesOf(content).filter(
|
|
97
99
|
(line) => line.start >= section.bodyStart && line.start < section.end
|
|
98
100
|
);
|
|
99
101
|
const firstContent = sectionLines.findIndex((line) => line.text.trim() !== '');
|
|
100
102
|
const tables: number[] = [];
|
|
101
103
|
for (let index = 0; index + 1 < sectionLines.length; index += 1) {
|
|
104
|
+
if (!visibleStarts.has(sectionLines[index]!.start) || !visibleStarts.has(sectionLines[index + 1]!.start)) continue;
|
|
102
105
|
const header = splitTableCells(sectionLines[index]!.text);
|
|
103
106
|
const separator = splitTableCells(sectionLines[index + 1]!.text);
|
|
104
107
|
if (!header || !separator || header.cells.length !== input.columns.length) continue;
|
|
@@ -173,22 +176,24 @@ function documentEol(content: string): '\n' | '\r\n' {
|
|
|
173
176
|
|
|
174
177
|
function matchingSections(content: string, aliases: readonly string[]) {
|
|
175
178
|
const allowed = new Set(aliases);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return { heading: match[1], line, bodyStart: line.end, end };
|
|
179
|
+
const lines = new Map(linesOf(content).map((line) => [line.start, line]));
|
|
180
|
+
const headings = scanVisibleMarkdown(content).headings.filter((heading) => heading.level === 2 || heading.level === 3);
|
|
181
|
+
return headings
|
|
182
|
+
.map((heading, index) => {
|
|
183
|
+
if (!allowed.has(heading.text)) return null;
|
|
184
|
+
const next = headings.slice(index + 1).find((candidate) => candidate.level <= heading.level);
|
|
185
|
+
const line = lines.get(heading.start)!;
|
|
186
|
+
return { heading: heading.text, level: heading.level, line, bodyStart: line.end, end: next?.start ?? content.length };
|
|
188
187
|
})
|
|
189
188
|
.filter((match): match is NonNullable<typeof match> => match !== null);
|
|
190
189
|
}
|
|
191
190
|
|
|
191
|
+
// Select the first visible section at the requested level, in document order.
|
|
192
|
+
function findSectionRange(content: string, aliases: readonly string[], level: 2 | 3 = 2) {
|
|
193
|
+
const section = matchingSections(content, aliases).find((candidate) => candidate.level === level);
|
|
194
|
+
return section ? { start: section.line.start, bodyStart: section.bodyStart, end: section.end, heading: section.heading } : null;
|
|
195
|
+
}
|
|
196
|
+
|
|
192
197
|
function validateAliases(aliases: readonly string[], name: string): void {
|
|
193
198
|
if (!Array.isArray(aliases) || aliases.length === 0 || aliases.some((alias) => !alias || /[\r\n]/.test(alias))) {
|
|
194
199
|
throw new DocumentMutationError('MUTATION_INVALID', `${name} must contain headings`);
|
|
@@ -349,11 +354,13 @@ function mutateTableRow(content: string, mutation: TableRowMutation): TableMutat
|
|
|
349
354
|
);
|
|
350
355
|
}
|
|
351
356
|
const section = sections[0]!;
|
|
357
|
+
const visibleStarts = new Set(scanVisibleMarkdown(content).lines.map((line) => line.start));
|
|
352
358
|
const sectionLines = linesOf(content).filter(
|
|
353
359
|
(line) => line.start >= section.bodyStart && line.start < section.end
|
|
354
360
|
);
|
|
355
361
|
const tables: { headerIndex: number; cells: string[] }[] = [];
|
|
356
362
|
for (let i = 0; i + 1 < sectionLines.length; i += 1) {
|
|
363
|
+
if (!visibleStarts.has(sectionLines[i]!.start) || !visibleStarts.has(sectionLines[i + 1]!.start)) continue;
|
|
357
364
|
const header = splitTableCells(sectionLines[i]!.text);
|
|
358
365
|
const separator = splitTableCells(sectionLines[i + 1]!.text);
|
|
359
366
|
if (!header || !separator || header.cells.length !== mutation.columns.length) continue;
|
|
@@ -475,24 +482,11 @@ function mutateTableRow(content: string, mutation: TableRowMutation): TableMutat
|
|
|
475
482
|
* lines are trimmed. Returns '' when no alias heading is present.
|
|
476
483
|
*/
|
|
477
484
|
function extractSection(content: string, aliases: string[]): string {
|
|
478
|
-
const
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
start = i + 1;
|
|
484
|
-
break;
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
if (start === -1) return '';
|
|
488
|
-
let end = lines.length;
|
|
489
|
-
for (let i = start; i < lines.length; i += 1) {
|
|
490
|
-
if (/^##\s+/.test(lines[i]!)) {
|
|
491
|
-
end = i;
|
|
492
|
-
break;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
return lines.slice(start, end).join('\n').replace(/^\n+/, '').replace(/\n+$/, '');
|
|
485
|
+
const headings = scanVisibleMarkdown(content).headings.filter((heading) => heading.level === 2);
|
|
486
|
+
const index = headings.findIndex((heading) => aliases.includes(heading.text));
|
|
487
|
+
if (index === -1) return '';
|
|
488
|
+
return content.slice(headings[index]!.end + 1, headings[index + 1]?.start ?? content.length)
|
|
489
|
+
.replace(/^(?:\r?\n)+|(?:\r?\n)+$/g, '');
|
|
496
490
|
}
|
|
497
491
|
|
|
498
492
|
/**
|
|
@@ -501,10 +495,8 @@ function extractSection(content: string, aliases: string[]): string {
|
|
|
501
495
|
* alias when none is present.
|
|
502
496
|
*/
|
|
503
497
|
function findSectionHeading(content: string, aliases: string[]): string {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
}
|
|
507
|
-
return aliases[0]!;
|
|
498
|
+
const headings = scanVisibleMarkdown(content).headings.filter((heading) => heading.level === 2);
|
|
499
|
+
return aliases.find((alias) => headings.some((heading) => heading.text === alias)) ?? aliases[0]!;
|
|
508
500
|
}
|
|
509
501
|
|
|
510
502
|
/**
|
|
@@ -516,27 +508,16 @@ function findSectionHeading(content: string, aliases: string[]): string {
|
|
|
516
508
|
* and trailing blank lines are trimmed. Returns '' when no match is present.
|
|
517
509
|
*/
|
|
518
510
|
function extractSubSection(content: string, headingPrefix: string): string {
|
|
519
|
-
const
|
|
520
|
-
const headRe = new RegExp(
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
break;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
if (start === -1) return '';
|
|
529
|
-
let end = lines.length;
|
|
530
|
-
for (let i = start + 1; i < lines.length; i += 1) {
|
|
531
|
-
if (/^###?\s+/.test(lines[i]!)) {
|
|
532
|
-
end = i;
|
|
533
|
-
break;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
return lines.slice(start, end).join('\n').replace(/^\n+/, '').replace(/\n+$/, '');
|
|
511
|
+
const headings = scanVisibleMarkdown(content).headings.filter((heading) => heading.level === 2 || heading.level === 3);
|
|
512
|
+
const headRe = new RegExp(`^${escapeRegExp(headingPrefix)}(?![\\w-])`);
|
|
513
|
+
const index = headings.findIndex((heading) => heading.level === 3 && headRe.test(heading.text));
|
|
514
|
+
if (index === -1) return '';
|
|
515
|
+
return content.slice(headings[index]!.start, headings[index + 1]?.start ?? content.length)
|
|
516
|
+
.replace(/^(?:\r?\n)+|(?:\r?\n)+$/g, '');
|
|
537
517
|
}
|
|
538
518
|
|
|
539
519
|
export {
|
|
520
|
+
findSectionRange,
|
|
540
521
|
extractSection,
|
|
541
522
|
findSectionHeading,
|
|
542
523
|
extractSubSection,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
+
import { getArtifactSchema } from './artifact-schema.ts';
|
|
5
|
+
|
|
4
6
|
type VerificationConfig = {
|
|
5
7
|
skill?: string;
|
|
6
8
|
checks: Record<string, Record<string, unknown> | null>;
|
|
@@ -13,6 +15,16 @@ function loadVerificationConfig(repositoryRoot: string, skillName: string): Veri
|
|
|
13
15
|
if (!parsed.checks || typeof parsed.checks !== 'object' || Array.isArray(parsed.checks)) {
|
|
14
16
|
throw new Error(`config/verify.json has invalid checks for skill '${skillName}'`);
|
|
15
17
|
}
|
|
18
|
+
const artifact = parsed.checks.artifact;
|
|
19
|
+
if (artifact && typeof artifact === 'object' && !Array.isArray(artifact)) {
|
|
20
|
+
const schema = artifact.schema;
|
|
21
|
+
if (schema !== undefined && (typeof schema !== 'string' || !getArtifactSchema(schema))) {
|
|
22
|
+
throw new Error(`config/verify.json has unknown artifact schema '${String(schema)}' for skill '${skillName}'`);
|
|
23
|
+
}
|
|
24
|
+
if (schema !== undefined && 'required_patterns' in artifact) {
|
|
25
|
+
throw new Error(`config/verify.json must not duplicate required_patterns for schema '${String(schema)}' in skill '${skillName}'`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
16
28
|
return { ...(parsed.skill ? { skill: parsed.skill } : {}), checks: parsed.checks };
|
|
17
29
|
}
|
|
18
30
|
|