@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
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import type { PullRequestResult } from '../platform/pull-requests.ts';
|
|
15
15
|
import { reportWrite, summaryContext, syncPullRequestSummary } from '../platform/pr-summary.ts';
|
|
16
16
|
import type { PlatformResult } from '../platform/types.ts';
|
|
17
|
+
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
|
|
17
18
|
|
|
18
19
|
const USAGE = `Usage: agent-infra-internal platform-pr inspect <task-ref> [--cwd <path>]
|
|
19
20
|
agent-infra-internal platform-pr resolve-external <task-ref> --agent <agent> [--pr <token>] [--dry-run] [--cwd <path>]
|
|
@@ -24,11 +25,11 @@ const USAGE = `Usage: agent-infra-internal platform-pr inspect <task-ref> [--cwd
|
|
|
24
25
|
agent-infra-internal platform-pr sync-in-labels --pr <N> [--dry-run] [--cwd <path>]
|
|
25
26
|
agent-infra-internal platform-pr summary-context <task-ref> [--cwd <path>]
|
|
26
27
|
agent-infra-internal platform-pr change-report <task-ref> --agent <agent> --mechanical-file <path> --precheck-file <path> [--dry-run] [--cwd <path>]
|
|
27
|
-
agent-infra-internal platform-pr summary-sync <task-ref> --agent <agent> --body-file <path|-> --change-report-file <path> --result <pr_created|pr_reused|no_op> [--strict] [--dry-run] [--cwd <path>]
|
|
28
|
+
agent-infra-internal platform-pr summary-sync <task-ref> --agent <agent> --body-file <path|-> --change-report-file <path> --result <pr_created|pr_reused|no_op> [--manual-phase pending|final ...] [--strict] [--dry-run] [--cwd <path>]
|
|
28
29
|
`;
|
|
29
30
|
|
|
30
31
|
const BOOLEAN_FLAGS = new Set(['--draft', '--dry-run', '--metadata', '--closing-issue', '--strict']);
|
|
31
|
-
const VALUE_FLAGS = new Set(['--cwd', '--agent', '--base', '--head', '--title-file', '--body-file', '--change-report-file', '--mechanical-file', '--precheck-file', '--pr', '--result']);
|
|
32
|
+
const VALUE_FLAGS = new Set(['--cwd', '--agent', '--base', '--head', '--title-file', '--body-file', '--change-report-file', '--mechanical-file', '--precheck-file', '--pr', '--result', '--manual-phase', '--transaction-id', '--receipt-digest', '--pr-head-sha']);
|
|
32
33
|
|
|
33
34
|
function key(flag: string): string {
|
|
34
35
|
return flag.slice(2).replace(/-([a-z])/g, (_, letter: string) => letter.toUpperCase());
|
|
@@ -67,10 +68,22 @@ function readFile(value: string, cwd: string): string {
|
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
async function platformPr(args: string[] = []): Promise<void> {
|
|
71
|
+
if (!ensureInternalHandlerRoute('platform-pr', args)) return;
|
|
70
72
|
if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
|
|
71
73
|
const operation = args[0];
|
|
72
|
-
if (!operation || ![
|
|
73
|
-
|
|
74
|
+
if (!operation || ![
|
|
75
|
+
internalHandlerRoute('platform-pr', 'inspect', operation),
|
|
76
|
+
internalHandlerRoute('platform-pr', 'resolve-external', operation),
|
|
77
|
+
internalHandlerRoute('platform-pr', 'create', operation),
|
|
78
|
+
internalHandlerRoute('platform-pr', 'bind', operation),
|
|
79
|
+
internalHandlerRoute('platform-pr', 'skip', operation),
|
|
80
|
+
internalHandlerRoute('platform-pr', 'sync', operation),
|
|
81
|
+
internalHandlerRoute('platform-pr', 'sync-in-labels', operation),
|
|
82
|
+
internalHandlerRoute('platform-pr', 'summary-context', operation),
|
|
83
|
+
internalHandlerRoute('platform-pr', 'change-report', operation),
|
|
84
|
+
internalHandlerRoute('platform-pr', 'summary-sync', operation)
|
|
85
|
+
].some(Boolean)) { fail('a valid operation is required'); return; }
|
|
86
|
+
if (internalHandlerRoute('platform-pr', 'sync-in-labels', operation)) {
|
|
74
87
|
const parsed = parse(args, 1);
|
|
75
88
|
if (parsed.error) { fail(parsed.error); return; }
|
|
76
89
|
const values = parsed.values;
|
|
@@ -98,24 +111,24 @@ async function platformPr(args: string[] = []): Promise<void> {
|
|
|
98
111
|
'sync-in-labels': ['cwd', 'pr', 'dryRun'],
|
|
99
112
|
'summary-context': ['cwd'],
|
|
100
113
|
'change-report': ['cwd', 'agent', 'mechanicalFile', 'precheckFile', 'dryRun'],
|
|
101
|
-
'summary-sync': ['cwd', 'agent', 'bodyFile', 'changeReportFile', 'result', 'dryRun', 'strict']
|
|
114
|
+
'summary-sync': ['cwd', 'agent', 'bodyFile', 'changeReportFile', 'result', 'manualPhase', 'transactionId', 'receiptDigest', 'prHeadSha', 'dryRun', 'strict']
|
|
102
115
|
};
|
|
103
116
|
const unexpected = Object.keys(values).find((name) => !allowed[operation]!.includes(name));
|
|
104
117
|
if (unexpected) { fail(`${operation} does not accept --${unexpected}`); return; }
|
|
105
|
-
if (
|
|
106
|
-
if (
|
|
118
|
+
if (internalHandlerRoute('platform-pr', 'inspect', operation)) { finish(await inspectPlatformPullRequest(taskRef, { cwd })); return; }
|
|
119
|
+
if (internalHandlerRoute('platform-pr', 'summary-context', operation)) { finish(await summaryContext(taskRef, { cwd })); return; }
|
|
107
120
|
if (typeof values.agent !== 'string' || !values.agent) { fail(`${operation} requires --agent`); return; }
|
|
108
121
|
const agent = normalizeAgentToken(values.agent);
|
|
109
122
|
if (!agent) { fail(`invalid --agent '${values.agent}': ${AGENT_USAGE_HINT}`); return; }
|
|
110
123
|
values.agent = agent;
|
|
111
|
-
if (
|
|
124
|
+
if (internalHandlerRoute('platform-pr', 'change-report', operation)) {
|
|
112
125
|
if (typeof values.mechanicalFile !== 'string' || typeof values.precheckFile !== 'string') { fail('change-report requires --mechanical-file and --precheck-file'); return; }
|
|
113
126
|
finish(await reportWrite(taskRef, {
|
|
114
127
|
cwd, agent: values.agent, mechanicalFile: values.mechanicalFile, precheckFile: values.precheckFile, dryRun: values.dryRun === true
|
|
115
128
|
}));
|
|
116
129
|
return;
|
|
117
130
|
}
|
|
118
|
-
if (
|
|
131
|
+
if (internalHandlerRoute('platform-pr', 'skip', operation)) {
|
|
119
132
|
finish(await skipPlatformPullRequestFact(taskRef, { cwd, agent, dryRun: values.dryRun === true }));
|
|
120
133
|
return;
|
|
121
134
|
}
|
|
@@ -124,30 +137,41 @@ async function platformPr(args: string[] = []): Promise<void> {
|
|
|
124
137
|
fail('--result must be pr_created, pr_reused, or no_op');
|
|
125
138
|
return;
|
|
126
139
|
}
|
|
127
|
-
if (
|
|
140
|
+
if (internalHandlerRoute('platform-pr', 'resolve-external', operation)) {
|
|
128
141
|
const pr = values.pr === undefined ? undefined : values.pr;
|
|
129
142
|
if (pr !== undefined && (typeof pr !== 'string' || !pr)) { fail('resolve-external requires --pr <token>'); return; }
|
|
130
143
|
finish(await resolveExternalPullRequest(taskRef, { cwd, agent: values.agent, pr, dryRun: values.dryRun === true }));
|
|
131
144
|
return;
|
|
132
145
|
}
|
|
133
|
-
if (
|
|
146
|
+
if (internalHandlerRoute('platform-pr', 'bind', operation)) {
|
|
134
147
|
const pr = values.pr;
|
|
135
148
|
if (typeof pr !== 'string' || !pr) { fail('bind requires --pr <token>'); return; }
|
|
136
149
|
finish(await bindPlatformPullRequest(taskRef, { cwd, agent: values.agent, pr, dryRun: values.dryRun === true }));
|
|
137
150
|
return;
|
|
138
151
|
}
|
|
139
|
-
if (
|
|
152
|
+
if (internalHandlerRoute('platform-pr', 'sync', operation)) {
|
|
140
153
|
if (values.metadata !== true && values.closingIssue !== true) { fail('sync requires --metadata or --closing-issue'); return; }
|
|
141
154
|
if (!primaryResult) { fail('sync requires --result pr_created, pr_reused, or no_op'); return; }
|
|
142
155
|
finish(await syncPlatformPullRequest(taskRef, { cwd, agent: values.agent, metadata: values.metadata === true, closingIssue: values.closingIssue === true, primaryResult: primaryResult as 'pr_created' | 'pr_reused' | 'no_op', dryRun: values.dryRun === true }));
|
|
143
156
|
return;
|
|
144
157
|
}
|
|
145
|
-
if (
|
|
158
|
+
if (internalHandlerRoute('platform-pr', 'summary-sync', operation)) {
|
|
146
159
|
if (typeof values.bodyFile !== 'string') { fail('summary-sync requires --body-file'); return; }
|
|
147
160
|
if (typeof values.changeReportFile !== 'string') { fail('summary-sync requires --change-report-file'); return; }
|
|
148
161
|
if (!primaryResult) { fail('summary-sync requires --result pr_created, pr_reused, or no_op'); return; }
|
|
149
162
|
try {
|
|
150
|
-
|
|
163
|
+
const manualPhase = values.manualPhase;
|
|
164
|
+
if (manualPhase !== undefined && manualPhase !== 'pending' && manualPhase !== 'final') { fail('--manual-phase must be pending or final'); return; }
|
|
165
|
+
finish(await syncPullRequestSummary(taskRef, {
|
|
166
|
+
cwd, agent: values.agent, body: readFile(values.bodyFile, cwd), changeReportFile: values.changeReportFile,
|
|
167
|
+
primaryResult: primaryResult as 'pr_created' | 'pr_reused' | 'no_op', dryRun: values.dryRun === true, strict: values.strict === true,
|
|
168
|
+
...(manualPhase ? { manualValidation: {
|
|
169
|
+
phase: manualPhase,
|
|
170
|
+
...(typeof values.transactionId === 'string' ? { transactionId: values.transactionId } : {}),
|
|
171
|
+
...(typeof values.receiptDigest === 'string' ? { receiptDigest: values.receiptDigest } : {}),
|
|
172
|
+
...(typeof values.prHeadSha === 'string' ? { prHeadSha: values.prHeadSha } : {})
|
|
173
|
+
} } : {})
|
|
174
|
+
}));
|
|
151
175
|
} catch (error) {
|
|
152
176
|
fail(`unable to read body file: ${error instanceof Error ? error.message : String(error)}`);
|
|
153
177
|
}
|
|
@@ -2,6 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
4
|
import { publishReleaseNotes, releaseNoteContext, stageReleaseNotes } from '../platform/release-notes.ts';
|
|
5
|
+
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
|
|
5
6
|
|
|
6
7
|
type ParsedOptions = Readonly<{ values: ReadonlyMap<string, string>; switches: ReadonlySet<string> }>;
|
|
7
8
|
|
|
@@ -37,8 +38,9 @@ function finish(result: { status: string; [key: string]: unknown }): void {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
async function platformReleaseNotes(args: string[] = []): Promise<void> {
|
|
41
|
+
if (!ensureInternalHandlerRoute('platform-release-notes', args)) return;
|
|
40
42
|
const [action, ...rest] = args;
|
|
41
|
-
if (action
|
|
43
|
+
if (internalHandlerRoute('platform-release-notes', 'context', action ?? '')) {
|
|
42
44
|
const parsed = parseOptions(rest, ['--cwd', '--history-limit', '--from-tag', '--to-tag', '--branch']);
|
|
43
45
|
if (!parsed) return finish(invalidInput('invalid context options'));
|
|
44
46
|
const cwd = path.resolve(parsed.values.get('--cwd') || process.cwd());
|
|
@@ -51,7 +53,7 @@ async function platformReleaseNotes(args: string[] = []): Promise<void> {
|
|
|
51
53
|
}, { cwd }));
|
|
52
54
|
return;
|
|
53
55
|
}
|
|
54
|
-
if (action
|
|
56
|
+
if (internalHandlerRoute('platform-release-notes', 'stage', action ?? '')) {
|
|
55
57
|
const parsed = parseOptions(rest, ['--cwd', '--notes-file']);
|
|
56
58
|
if (!parsed) return finish(invalidInput('invalid stage options'));
|
|
57
59
|
const notesFile = parsed.values.get('--notes-file');
|
|
@@ -62,7 +64,7 @@ async function platformReleaseNotes(args: string[] = []): Promise<void> {
|
|
|
62
64
|
));
|
|
63
65
|
return;
|
|
64
66
|
}
|
|
65
|
-
if (action
|
|
67
|
+
if (internalHandlerRoute('platform-release-notes', 'publish', action ?? '')) {
|
|
66
68
|
const parsed = parseOptions(
|
|
67
69
|
rest,
|
|
68
70
|
['--cwd', '--notes-file', '--tag', '--title', '--expected-sha256'],
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
|
|
3
|
+
import { dismissSecurityAlert, readCommentFile, readSecurityAlert } from '../platform/security-alerts.ts';
|
|
4
|
+
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
|
|
5
|
+
|
|
6
|
+
const USAGE = `Usage: agent-infra-internal platform-security read --kind <dependabot|code-scanning> --number <number> [--cwd <path>]
|
|
7
|
+
agent-infra-internal platform-security dismiss --kind <dependabot|code-scanning> --number <number> --reason <reason> --comment-file <path> [--cwd <path>]
|
|
8
|
+
`;
|
|
9
|
+
|
|
10
|
+
function fail(message: string): void {
|
|
11
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'SECURITY_INPUT_INVALID', message, retryable: false } })}\n`);
|
|
12
|
+
process.stderr.write(USAGE);
|
|
13
|
+
process.exitCode = 1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function finish(result: { status: string; [key: string]: unknown }): void {
|
|
17
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
18
|
+
process.exitCode = result.status === 'blocked' ? 2 : result.status === 'failed' ? 1 : 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function parseOptions(args: string[]): { values: Map<string, string>; switches: Set<string> } | null {
|
|
22
|
+
const values = new Map<string, string>();
|
|
23
|
+
const switches = new Set<string>();
|
|
24
|
+
const valueFlags = new Set(['--cwd', '--kind', '--number', '--reason', '--comment-file']);
|
|
25
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
26
|
+
const flag = args[index]!;
|
|
27
|
+
if (flag === '--help' || flag === '-h') return null;
|
|
28
|
+
if (!valueFlags.has(flag) || values.has(flag) || switches.has(flag)) return null;
|
|
29
|
+
const value = args[++index];
|
|
30
|
+
if (!value || value.startsWith('--')) return null;
|
|
31
|
+
values.set(flag, value);
|
|
32
|
+
}
|
|
33
|
+
return { values, switches };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function required(values: Map<string, string>, flag: string): string | null {
|
|
37
|
+
const value = values.get(flag);
|
|
38
|
+
return value && !value.startsWith('--') ? value : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function platformSecurity(args: string[] = []): Promise<void> {
|
|
42
|
+
if (!ensureInternalHandlerRoute('platform-security', args)) return;
|
|
43
|
+
if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
|
|
44
|
+
const action = args[0];
|
|
45
|
+
if (!internalHandlerRoute('platform-security', 'read', action ?? '')
|
|
46
|
+
&& !internalHandlerRoute('platform-security', 'dismiss', action ?? '')) {
|
|
47
|
+
fail('a valid operation is required');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (action !== 'read' && action !== 'dismiss') { fail('a valid operation is required'); return; }
|
|
51
|
+
const parsed = parseOptions(args.slice(1));
|
|
52
|
+
if (!parsed) { fail('invalid security alert options'); return; }
|
|
53
|
+
const kind = required(parsed.values, '--kind');
|
|
54
|
+
const numberRaw = required(parsed.values, '--number');
|
|
55
|
+
const cwd = path.resolve(required(parsed.values, '--cwd') || process.cwd());
|
|
56
|
+
if (!kind || !numberRaw) { fail(`${action} requires --kind and --number`); return; }
|
|
57
|
+
const number = Number(numberRaw);
|
|
58
|
+
if (!Number.isSafeInteger(number) || number <= 0) { fail('--number must be a positive integer'); return; }
|
|
59
|
+
|
|
60
|
+
if (action === 'read') {
|
|
61
|
+
if ([...parsed.values.keys()].some((flag) => !['--kind', '--number', '--cwd'].includes(flag))) {
|
|
62
|
+
fail('read does not accept dismissal options');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
finish(await readSecurityAlert({ kind: kind as 'dependabot' | 'code-scanning', number }, { cwd }));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const reason = required(parsed.values, '--reason');
|
|
70
|
+
const commentFile = required(parsed.values, '--comment-file');
|
|
71
|
+
if (!reason || !commentFile) { fail('dismiss requires --reason and --comment-file'); return; }
|
|
72
|
+
const comment = readCommentFile(commentFile, cwd);
|
|
73
|
+
if (!comment.ok) {
|
|
74
|
+
finish({ status: 'failed', changed: false, error: comment.error });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
finish(await dismissSecurityAlert(
|
|
78
|
+
{ kind: kind as 'dependabot' | 'code-scanning', number, reason, comment: comment.value },
|
|
79
|
+
{ cwd }
|
|
80
|
+
));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { platformSecurity };
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import type { DecisionRecord, HostResolution } from '../pr-review/evidence-grading.ts';
|
|
12
12
|
import { inspectPlatformPullRequestByNumber } from '../platform/pull-requests.ts';
|
|
13
13
|
import { verifyInProcess } from '../task/verification-engine.ts';
|
|
14
|
+
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
|
|
14
15
|
|
|
15
16
|
const USAGE = `Usage: agent-infra-internal pr-review-grade decide --input-file <path|-> [--cwd <path>]
|
|
16
17
|
agent-infra-internal pr-review-grade resolve-host --pr <token> [--cwd <path>]
|
|
@@ -50,9 +51,14 @@ function readInput(value: string, cwd: string): string {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
async function prReviewGrade(args: string[] = []): Promise<void> {
|
|
54
|
+
if (!ensureInternalHandlerRoute('pr-review-grade', args)) return;
|
|
53
55
|
if (args[0] === '--help' || args[0] === '-h') { process.stdout.write(USAGE); return; }
|
|
54
56
|
const operation = args[0];
|
|
55
|
-
if (!operation || ![
|
|
57
|
+
if (!operation || ![
|
|
58
|
+
internalHandlerRoute('pr-review-grade', 'decide', operation),
|
|
59
|
+
internalHandlerRoute('pr-review-grade', 'resolve-host', operation),
|
|
60
|
+
internalHandlerRoute('pr-review-grade', 'verify-artifact', operation)
|
|
61
|
+
].some(Boolean)) { fail('a valid operation is required'); return; }
|
|
56
62
|
const parsed = parseFlags(args, 1);
|
|
57
63
|
if (parsed.error) { fail(parsed.error); return; }
|
|
58
64
|
const values = parsed.values;
|
|
@@ -65,7 +71,7 @@ async function prReviewGrade(args: string[] = []): Promise<void> {
|
|
|
65
71
|
const unexpected = Object.keys(values).find((key) => !allowed[operation]!.includes(key));
|
|
66
72
|
if (unexpected) { fail(`${operation} does not accept '--${unexpected}'`); return; }
|
|
67
73
|
|
|
68
|
-
if (
|
|
74
|
+
if (internalHandlerRoute('pr-review-grade', 'decide', operation)) {
|
|
69
75
|
if (typeof values.inputFile !== 'string') { fail('decide requires --input-file'); return; }
|
|
70
76
|
let input: unknown;
|
|
71
77
|
try {
|
|
@@ -84,7 +90,7 @@ async function prReviewGrade(args: string[] = []): Promise<void> {
|
|
|
84
90
|
return;
|
|
85
91
|
}
|
|
86
92
|
|
|
87
|
-
if (
|
|
93
|
+
if (internalHandlerRoute('pr-review-grade', 'resolve-host', operation)) {
|
|
88
94
|
const pr = typeof values.pr === 'string' ? values.pr : '';
|
|
89
95
|
if (!pr) { fail('resolve-host requires --pr <token>'); return; }
|
|
90
96
|
const inspected = await inspectPlatformPullRequestByNumber(pr, { cwd });
|
|
@@ -109,6 +115,7 @@ async function prReviewGrade(args: string[] = []): Promise<void> {
|
|
|
109
115
|
return;
|
|
110
116
|
}
|
|
111
117
|
|
|
118
|
+
if (!internalHandlerRoute('pr-review-grade', 'verify-artifact', operation)) { fail('operation is not registered'); return; }
|
|
112
119
|
if (typeof values.artifactFile !== 'string') { fail('verify-artifact requires --artifact-file'); return; }
|
|
113
120
|
const artifactPath = path.resolve(cwd, values.artifactFile);
|
|
114
121
|
let result: Record<string, unknown>;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import crypto from 'node:crypto';
|
|
4
3
|
import { spawnSync } from 'node:child_process';
|
|
5
4
|
import semver from 'semver';
|
|
6
5
|
|
|
@@ -9,114 +8,95 @@ import { inspectPlatformRelease, reconcileReleaseMilestones } from '../platform/
|
|
|
9
8
|
import { inspectHomebrewChannel, inspectNpmChannel } from '../release/channels.ts';
|
|
10
9
|
import { releaseSnapshot } from '../release/workflow.ts';
|
|
11
10
|
import type { PostReleaseFacts, ReleaseFacts } from '../release/workflow.ts';
|
|
11
|
+
import { collectDemoTranscript } from './demo-transcript.ts';
|
|
12
|
+
import { createDemoPromotion, promoteDemoAssets, recoverDemoPromotion } from './demo-promotion.ts';
|
|
13
|
+
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.ts';
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
type CommandOptions = { env?: NodeJS.ProcessEnv };
|
|
16
|
+
|
|
17
|
+
function command(cwd: string, executable: string, args: string[], options: CommandOptions = {}) {
|
|
18
|
+
return spawnSync(executable, args, {
|
|
19
|
+
cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], env: { ...process.env, ...options.env }
|
|
20
|
+
});
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
type CommandResult = ReturnType<typeof command>;
|
|
18
|
-
type CommandRunner = (cwd: string, executable: string, args: string[]) => CommandResult;
|
|
24
|
+
type CommandRunner = (cwd: string, executable: string, args: string[], options?: CommandOptions) => CommandResult;
|
|
19
25
|
type DemoResult = {
|
|
20
26
|
status: 'recorded' | 'skipped' | 'failed';
|
|
21
|
-
reasonCode: '
|
|
27
|
+
reasonCode: 'DEMO_TRANSCRIPT_UNCHANGED' | 'DEMO_TRANSCRIPT_UNAVAILABLE' | 'DEMO_TRANSCRIPT_FAILED'
|
|
28
|
+
| 'DEMO_PROMOTION_FAILED' | 'DEMO_PROMOTION_RECOVERY_REQUIRED' | 'DEMO_PROMOTION_CLEANUP_FAILED'
|
|
29
|
+
| 'GIT_LFS_MISSING' | 'VHS_MISSING' | 'FFMPEG_MISSING'
|
|
22
30
|
| 'DEMO_COMMAND_FAILED' | 'DEMO_OUTPUT_MISSING' | 'DEMO_OUTPUT_INVALID'
|
|
23
|
-
| 'DEMO_OUTPUT_TOO_LARGE' |
|
|
31
|
+
| 'DEMO_OUTPUT_TOO_LARGE' | null;
|
|
24
32
|
message: string | null;
|
|
25
33
|
outputPath: string | null;
|
|
26
34
|
};
|
|
27
35
|
|
|
28
|
-
|
|
29
|
-
// lib/init.ts: non-visual config serialization changes must not re-record it.
|
|
30
|
-
const DEMO_INPUT_PATHS = [
|
|
31
|
-
'assets/demo-init.tape',
|
|
32
|
-
'scripts/demo-regen.sh',
|
|
33
|
-
'scripts/normalize-gif-duration.py',
|
|
34
|
-
'bin/cli.ts',
|
|
35
|
-
'lib/log.ts',
|
|
36
|
-
'lib/prompt.ts',
|
|
37
|
-
'lib/paths.ts',
|
|
38
|
-
'lib/render.ts',
|
|
39
|
-
'lib/sandbox/engines/'
|
|
40
|
-
] as const;
|
|
41
|
-
const DEMO_DIGEST_PATH = 'assets/demo-init.inputs.sha256';
|
|
36
|
+
const DEMO_DIGEST_PATH = 'assets/demo-init.transcript.sha256';
|
|
42
37
|
const DEMO_OUTPUT_PATH = 'assets/demo-init.gif';
|
|
43
38
|
const DEMO_MAX_BYTES = 4 * 1024 * 1024;
|
|
44
39
|
|
|
45
|
-
function demoInputFiles(cwd: string): string[] {
|
|
46
|
-
const files = new Set<string>();
|
|
47
|
-
for (const input of DEMO_INPUT_PATHS) {
|
|
48
|
-
if (input.endsWith('/')) {
|
|
49
|
-
const listed = command(cwd, 'git', ['ls-files', '--', input]);
|
|
50
|
-
if (listed.status !== 0) throw new Error(String(listed.stderr || `Unable to list ${input}`));
|
|
51
|
-
const directoryFiles = String(listed.stdout).split('\n').filter(Boolean);
|
|
52
|
-
if (!directoryFiles.length) throw new Error(`Canonical demo input directory is empty: ${input}`);
|
|
53
|
-
for (const file of directoryFiles) files.add(file.replaceAll('\\', '/'));
|
|
54
|
-
} else {
|
|
55
|
-
files.add(input);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
const sorted = [...files].sort((left, right) => Buffer.from(left).compare(Buffer.from(right)));
|
|
59
|
-
if (!sorted.length) throw new Error('Canonical demo input set is empty');
|
|
60
|
-
for (const file of sorted) {
|
|
61
|
-
const absolute = path.join(cwd, file);
|
|
62
|
-
if (!fs.statSync(absolute).isFile()) throw new Error(`Canonical demo input is not a file: ${file}`);
|
|
63
|
-
}
|
|
64
|
-
return sorted;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function computeDemoInputDigest(cwd: string): string {
|
|
68
|
-
const hash = crypto.createHash('sha256');
|
|
69
|
-
for (const file of demoInputFiles(cwd)) {
|
|
70
|
-
const bytes = fs.readFileSync(path.join(cwd, file));
|
|
71
|
-
hash.update(file);
|
|
72
|
-
hash.update('\0');
|
|
73
|
-
hash.update(String(bytes.byteLength));
|
|
74
|
-
hash.update('\0');
|
|
75
|
-
hash.update(bytes);
|
|
76
|
-
hash.update('\0');
|
|
77
|
-
}
|
|
78
|
-
return hash.digest('hex');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
40
|
function validGif(filePath: string): boolean {
|
|
82
41
|
if (!fs.existsSync(filePath)) return false;
|
|
83
42
|
const header = fs.readFileSync(filePath).subarray(0, 6).toString('ascii');
|
|
84
43
|
return header === 'GIF87a' || header === 'GIF89a';
|
|
85
44
|
}
|
|
86
45
|
|
|
87
|
-
function
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return { status: 'failed', reasonCode: 'DEMO_DIGEST_FAILED', message: String(error), outputPath: null };
|
|
46
|
+
async function runOptionalDemo(
|
|
47
|
+
cwd: string,
|
|
48
|
+
run: CommandRunner = command,
|
|
49
|
+
collect = collectDemoTranscript
|
|
50
|
+
): Promise<DemoResult> {
|
|
51
|
+
const recovery = recoverDemoPromotion(cwd);
|
|
52
|
+
if (recovery?.status === 'failed') {
|
|
53
|
+
return { status: 'failed', reasonCode: recovery.code === 'DEMO_PROMOTION_CLEANUP_FAILED' ? recovery.code : 'DEMO_PROMOTION_RECOVERY_REQUIRED', message: recovery.message, outputPath: null };
|
|
54
|
+
}
|
|
55
|
+
const transcript = await collect(cwd);
|
|
56
|
+
if (transcript.status === 'failed') {
|
|
57
|
+
return { status: 'failed', reasonCode: transcript.reasonCode, message: transcript.message, outputPath: null };
|
|
100
58
|
}
|
|
101
59
|
const digestPath = path.join(cwd, DEMO_DIGEST_PATH);
|
|
102
60
|
const priorDigest = fs.existsSync(digestPath) ? fs.readFileSync(digestPath, 'utf8').trim() : '';
|
|
103
|
-
if (/^[0-9a-f]{64}$/.test(priorDigest) && priorDigest ===
|
|
104
|
-
return { status: 'skipped', reasonCode: '
|
|
61
|
+
if (/^[0-9a-f]{64}$/.test(priorDigest) && priorDigest === transcript.sha256) {
|
|
62
|
+
return { status: 'skipped', reasonCode: 'DEMO_TRANSCRIPT_UNCHANGED', message: null, outputPath: null };
|
|
105
63
|
}
|
|
64
|
+
const promotion = createDemoPromotion(cwd, transcript.transcript);
|
|
65
|
+
const discardPromotion = () => fs.rmSync(promotion.directory, { recursive: true, force: true });
|
|
106
66
|
const lfs = run(cwd, 'git', ['lfs', 'version']);
|
|
107
67
|
if (lfs.status !== 0) {
|
|
68
|
+
discardPromotion();
|
|
108
69
|
return { status: 'failed', reasonCode: 'GIT_LFS_MISSING', message: String(lfs.stderr || lfs.stdout), outputPath: null };
|
|
109
70
|
}
|
|
110
71
|
const lfsAttribute = run(cwd, 'git', ['check-attr', 'filter', '--', DEMO_OUTPUT_PATH]);
|
|
111
72
|
if (lfsAttribute.status !== 0 || !String(lfsAttribute.stdout).trim().endsWith(': lfs')) {
|
|
73
|
+
discardPromotion();
|
|
112
74
|
return { status: 'failed', reasonCode: 'GIT_LFS_MISSING', message: `${DEMO_OUTPUT_PATH} is not tracked by Git LFS`, outputPath: null };
|
|
113
75
|
}
|
|
114
76
|
const vhs = run(cwd, 'vhs', ['--version']);
|
|
115
|
-
if (vhs.status !== 0)
|
|
77
|
+
if (vhs.status !== 0) {
|
|
78
|
+
discardPromotion();
|
|
79
|
+
return {
|
|
80
|
+
status: 'failed',
|
|
81
|
+
reasonCode: 'VHS_MISSING',
|
|
82
|
+
message: String(vhs.stderr || vhs.stdout) || 'VHS is required to record the changed demo transcript',
|
|
83
|
+
outputPath: null
|
|
84
|
+
};
|
|
85
|
+
}
|
|
116
86
|
const ffmpeg = run(cwd, 'ffmpeg', ['-version']);
|
|
117
|
-
if (ffmpeg.status !== 0)
|
|
118
|
-
|
|
87
|
+
if (ffmpeg.status !== 0) {
|
|
88
|
+
discardPromotion();
|
|
89
|
+
return {
|
|
90
|
+
status: 'failed',
|
|
91
|
+
reasonCode: 'FFMPEG_MISSING',
|
|
92
|
+
message: String(ffmpeg.stderr || ffmpeg.stdout) || 'ffmpeg is required to record the changed demo transcript',
|
|
93
|
+
outputPath: null
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const stagedOutputPath = path.relative(cwd, promotion.staging.gif).replaceAll(path.sep, '/');
|
|
97
|
+
const demo = run(cwd, 'npm', ['run', 'demo:regen'], { env: { DEMO_OUTPUT_PATH: stagedOutputPath } });
|
|
119
98
|
if (demo.status !== 0) {
|
|
99
|
+
discardPromotion();
|
|
120
100
|
return {
|
|
121
101
|
status: 'failed',
|
|
122
102
|
reasonCode: 'DEMO_COMMAND_FAILED',
|
|
@@ -125,7 +105,8 @@ function runOptionalDemo(cwd: string, run: CommandRunner = command): DemoResult
|
|
|
125
105
|
};
|
|
126
106
|
}
|
|
127
107
|
const outputPath = DEMO_OUTPUT_PATH;
|
|
128
|
-
if (!fs.existsSync(
|
|
108
|
+
if (!fs.existsSync(promotion.staging.gif)) {
|
|
109
|
+
discardPromotion();
|
|
129
110
|
return {
|
|
130
111
|
status: 'failed',
|
|
131
112
|
reasonCode: 'DEMO_OUTPUT_MISSING',
|
|
@@ -133,18 +114,24 @@ function runOptionalDemo(cwd: string, run: CommandRunner = command): DemoResult
|
|
|
133
114
|
outputPath: null
|
|
134
115
|
};
|
|
135
116
|
}
|
|
136
|
-
const absoluteOutput =
|
|
117
|
+
const absoluteOutput = promotion.staging.gif;
|
|
137
118
|
if (!validGif(absoluteOutput)) {
|
|
119
|
+
discardPromotion();
|
|
138
120
|
return { status: 'failed', reasonCode: 'DEMO_OUTPUT_INVALID', message: `${outputPath} is not a GIF`, outputPath: null };
|
|
139
121
|
}
|
|
140
122
|
if (fs.statSync(absoluteOutput).size > DEMO_MAX_BYTES) {
|
|
123
|
+
discardPromotion();
|
|
141
124
|
return { status: 'failed', reasonCode: 'DEMO_OUTPUT_TOO_LARGE', message: `${outputPath} exceeds 4 MiB`, outputPath: null };
|
|
142
125
|
}
|
|
143
|
-
const pointer = run(cwd, 'git', ['lfs', 'pointer', `--file=${
|
|
126
|
+
const pointer = run(cwd, 'git', ['lfs', 'pointer', `--file=${stagedOutputPath}`]);
|
|
144
127
|
if (pointer.status !== 0 || !String(pointer.stdout).includes(`size ${fs.statSync(absoluteOutput).size}`)) {
|
|
128
|
+
discardPromotion();
|
|
145
129
|
return { status: 'failed', reasonCode: 'DEMO_OUTPUT_INVALID', message: 'Git LFS could not produce a matching pointer', outputPath: null };
|
|
146
130
|
}
|
|
147
|
-
|
|
131
|
+
const promoted = promoteDemoAssets(cwd, promotion.staging, `${process.pid}-${Date.now()}`);
|
|
132
|
+
if (promoted.status === 'failed') {
|
|
133
|
+
return { status: 'failed', reasonCode: promoted.code ?? 'DEMO_PROMOTION_FAILED', message: promoted.message, outputPath: null };
|
|
134
|
+
}
|
|
148
135
|
return { status: 'recorded', reasonCode: null, message: null, outputPath };
|
|
149
136
|
}
|
|
150
137
|
|
|
@@ -206,7 +193,7 @@ function inspectPostReleaseFacts(
|
|
|
206
193
|
remoteHead,
|
|
207
194
|
newVersion,
|
|
208
195
|
changedPaths,
|
|
209
|
-
|
|
196
|
+
demoTranscriptSha256: digest && /^[0-9a-f]{64}$/.test(digest) ? digest : null,
|
|
210
197
|
worktree: snapshot?.worktree ?? [],
|
|
211
198
|
staged: snapshot?.staged ?? []
|
|
212
199
|
};
|
|
@@ -312,20 +299,28 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
|
|
|
312
299
|
const version = String(rawVersion || '').replace(/^v/, '');
|
|
313
300
|
const cwdIndex = rest.indexOf('--cwd');
|
|
314
301
|
const cwd = path.resolve(cwdIndex >= 0 && rest[cwdIndex + 1] ? rest[cwdIndex + 1]! : process.cwd());
|
|
315
|
-
if (![
|
|
302
|
+
if (![
|
|
303
|
+
internalHandlerRoute('release-workflow', 'inspect', action || ''),
|
|
304
|
+
internalHandlerRoute('release-workflow', 'prepare', action || ''),
|
|
305
|
+
internalHandlerRoute('release-workflow', 'publish', action || ''),
|
|
306
|
+
internalHandlerRoute('release-workflow', 'post-prepare', action || ''),
|
|
307
|
+
internalHandlerRoute('release-workflow', 'post-publish', action || '')
|
|
308
|
+
].some(Boolean) || !semver.valid(version)) {
|
|
316
309
|
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'RELEASE_INPUT_INVALID', message: 'Usage: release-workflow inspect|prepare|publish|post-prepare|post-publish <version>' } })}\n`);
|
|
317
310
|
process.exitCode = 1; return;
|
|
318
311
|
}
|
|
312
|
+
if (!ensureInternalHandlerRoute('release-workflow', args)) return;
|
|
319
313
|
const before = releaseSnapshot(version, await inspectFacts(cwd, version));
|
|
320
|
-
if (action
|
|
314
|
+
if (internalHandlerRoute('release-workflow', 'inspect', action || '')) { process.stdout.write(`${JSON.stringify({ status: 'no-op', changed: false, snapshot: before, error: null })}\n`); return; }
|
|
321
315
|
if (before.facts.localTagConflict) {
|
|
322
316
|
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'GIT_TAG_CONFLICT', message: `Tag v${version} is not reachable from HEAD` } })}\n`);
|
|
323
317
|
process.exitCode = 1; return;
|
|
324
318
|
}
|
|
325
|
-
if (action
|
|
319
|
+
if (internalHandlerRoute('release-workflow', 'prepare', action || '')) {
|
|
326
320
|
if (before.phase !== 'unprepared') {
|
|
327
321
|
const milestones = await reconcileReleaseMilestones(version, { cwd });
|
|
328
|
-
|
|
322
|
+
const snapshot = releaseSnapshot(version, await inspectFacts(cwd, version));
|
|
323
|
+
process.stdout.write(`${JSON.stringify({ ...milestones, snapshot })}\n`);
|
|
329
324
|
process.exitCode = milestones.status === 'failed' ? 1 : milestones.status === 'blocked' ? 2 : 0;
|
|
330
325
|
return;
|
|
331
326
|
}
|
|
@@ -352,14 +347,14 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
|
|
|
352
347
|
process.stdout.write(`${JSON.stringify({ status, changed: true, snapshot, operations: milestones?.operations ?? [], error: tagged.status !== 0 ? { code: 'GIT_TAG_FAILED', message: String(tagged.stderr) } : milestones?.error ?? null })}\n`);
|
|
353
348
|
process.exitCode = failed ? 1 : blocked ? 2 : 0; return;
|
|
354
349
|
}
|
|
355
|
-
if (action
|
|
350
|
+
if (internalHandlerRoute('release-workflow', 'publish', action || '')) {
|
|
356
351
|
if (!before.facts.localTag || !['prepared', 'partially-published'].includes(before.phase)) { process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'RELEASE_PHASE_INVALID', message: `Cannot publish from ${before.phase}` } })}\n`); process.exitCode = 1; return; }
|
|
357
352
|
const branch = git(cwd, ['branch', '--show-current']) || '';
|
|
358
353
|
const refs = [...(!before.facts.remoteBranch ? [branch] : []), ...(!before.facts.remoteTag ? [`refs/tags/v${version}`] : [])];
|
|
359
354
|
const result = pushGitRefs({ cwd, remote: 'origin', refs });
|
|
360
355
|
process.stdout.write(`${JSON.stringify({ ...result, snapshot: releaseSnapshot(version, await inspectFacts(cwd, version)) })}\n`); process.exitCode = result.status === 'failed' ? 1 : result.status === 'degraded' ? 2 : 0; return;
|
|
361
356
|
}
|
|
362
|
-
if (
|
|
357
|
+
if (internalHandlerRoute('release-workflow', 'post-publish', action || '')) {
|
|
363
358
|
const expectedValues = optionValues(rest, '--expected-sha256');
|
|
364
359
|
if (expectedValues.length !== 1 || !/^sha256:[0-9a-f]{64}$/.test(expectedValues[0]!)) {
|
|
365
360
|
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'RELEASE_INPUT_INVALID', message: 'post-publish requires one --expected-sha256 sha256:<64 hex>' } })}\n`);
|
|
@@ -394,6 +389,10 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
|
|
|
394
389
|
process.exitCode = blocked ? 2 : 1; return;
|
|
395
390
|
}
|
|
396
391
|
|
|
392
|
+
if (!internalHandlerRoute('release-workflow', 'post-prepare', action || '')) {
|
|
393
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: { code: 'RELEASE_INPUT_INVALID', message: 'release-workflow action is not registered' } })}\n`);
|
|
394
|
+
process.exitCode = 1; return;
|
|
395
|
+
}
|
|
397
396
|
if (before.phase === 'complete') {
|
|
398
397
|
process.stdout.write(`${JSON.stringify({ status: 'no-op', changed: false, snapshot: before, error: null })}\n`);
|
|
399
398
|
return;
|
|
@@ -408,6 +407,11 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
|
|
|
408
407
|
if (!['published', 'post-pending'].includes(before.phase) || !channelsComplete || before.facts.smoke !== 'success') {
|
|
409
408
|
process.stdout.write(`${JSON.stringify({ status: before.facts.smoke === 'failed' ? 'failed' : 'blocked', changed: false, snapshot: before, error: { code: 'RELEASE_CHANNELS_PENDING', message: 'Release channels or smoke workflow are not complete' } })}\n`); process.exitCode = before.facts.smoke === 'failed' ? 1 : 2; return;
|
|
410
409
|
}
|
|
410
|
+
const recovery = recoverDemoPromotion(cwd);
|
|
411
|
+
if (recovery?.status === 'failed') {
|
|
412
|
+
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: true, snapshot: before, error: { code: recovery.code, message: recovery.message } })}\n`);
|
|
413
|
+
process.exitCode = 1; return;
|
|
414
|
+
}
|
|
411
415
|
const worktreeError = inspectPostWorktree(cwd);
|
|
412
416
|
if (worktreeError) {
|
|
413
417
|
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, snapshot: before, error: worktreeError })}\n`);
|
|
@@ -418,7 +422,7 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
|
|
|
418
422
|
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: true, snapshot: before, error: { code: 'RELEASE_POST_COMMAND_FAILED', message: String(built.stderr || built.stdout) } })}\n`);
|
|
419
423
|
process.exitCode = 1; return;
|
|
420
424
|
}
|
|
421
|
-
const demo = runOptionalDemo(cwd);
|
|
425
|
+
const demo = await runOptionalDemo(cwd);
|
|
422
426
|
if (demo.status === 'failed') {
|
|
423
427
|
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: true, snapshot: before, demo, error: { code: 'RELEASE_POST_DEMO_FAILED', message: demo.message } })}\n`);
|
|
424
428
|
process.exitCode = 1; return;
|
|
@@ -437,5 +441,5 @@ async function releaseWorkflow(args: string[] = []): Promise<void> {
|
|
|
437
441
|
process.stdout.write(`${JSON.stringify({ status: 'applied', changed: true, demo, snapshot, error: null })}\n`);
|
|
438
442
|
}
|
|
439
443
|
|
|
440
|
-
export { changedPaths,
|
|
444
|
+
export { changedPaths, inspectFacts, inspectLocalReleaseFacts, inspectPostReleaseFacts, inspectPostWorktree, releaseSmokeStatus, releaseWorkflow, runOptionalDemo };
|
|
441
445
|
export type { CommandRunner, DemoResult };
|