@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
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
export const PUBLIC_CLI_COMMAND_ALIASES = Object.freeze({
|
|
2
|
+
'': 'help',
|
|
3
|
+
s: 'sandbox',
|
|
4
|
+
t: 'task',
|
|
5
|
+
'--version': 'version',
|
|
6
|
+
'-v': 'version'
|
|
7
|
+
});
|
|
8
|
+
export const PUBLIC_CLI_SELECTOR_ALIASES = Object.freeze({
|
|
9
|
+
task: Object.freeze({ d: 'decisions' })
|
|
10
|
+
});
|
|
11
|
+
export const PUBLIC_CLI_ROUTE_SELECTORS = Object.freeze({
|
|
12
|
+
'agent-client': ['list', 'status', 'enable', 'disable', 'configure'],
|
|
13
|
+
cp: ['cp'],
|
|
14
|
+
data: ['capture', 'verify', 'audit', 'repair', 'export'],
|
|
15
|
+
decide: ['decide'],
|
|
16
|
+
help: ['help'],
|
|
17
|
+
init: ['init'],
|
|
18
|
+
merge: ['merge'],
|
|
19
|
+
run: ['create-task', 'task-skill', 'recreate'],
|
|
20
|
+
sandbox: ['create', 'exec', 'ls', 'show', 'prune', 'rebuild', 'refresh', 'rm', 'start', 'vm'],
|
|
21
|
+
server: ['start', 'stop', 'status', 'logs', '__daemon'],
|
|
22
|
+
task: ['cat', 'decisions', 'files', 'grep', 'issue-body', 'log', 'ls', 'show', 'status'],
|
|
23
|
+
sync: ['sync'],
|
|
24
|
+
update: ['update'],
|
|
25
|
+
version: ['version']
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* The selector definitions consumed by every internal handler. Keep this
|
|
29
|
+
* module free of handler imports so the pre-import task-view guard remains
|
|
30
|
+
* effective.
|
|
31
|
+
*/
|
|
32
|
+
export const INTERNAL_HANDLER_ROUTE_SELECTORS = Object.freeze({
|
|
33
|
+
'task-create': ['input'],
|
|
34
|
+
'task-qualification': ['proposal', 'confirm', 'supersede', 'revoke'],
|
|
35
|
+
'sandbox-control': ['serve', 'execute', 'recover', 'client'],
|
|
36
|
+
'host-control': ['serve', 'status', 'install', 'uninstall'],
|
|
37
|
+
'agent-client': ['next-steps', 'model-selection'],
|
|
38
|
+
'codex-lifecycle': ['preflight', 'capability-arm', 'hook-event', 'resolve-start', 'resolve-stop', 'consume'],
|
|
39
|
+
'codex-sandbox-controller': ['verify-context', 'run'],
|
|
40
|
+
'git-workflow': ['inspect', 'preview-tree', 'snapshot', 'compare-trees', 'commit', 'push-rebased'],
|
|
41
|
+
'task-delivery': ['deliver'],
|
|
42
|
+
'release-workflow': ['inspect', 'prepare', 'publish', 'post-prepare', 'post-publish'],
|
|
43
|
+
'platform-release-notes': ['context', 'stage', 'publish'],
|
|
44
|
+
'platform-security': ['read', 'dismiss'],
|
|
45
|
+
'platform-metadata': ['init-labels', 'init-milestones'],
|
|
46
|
+
'platform-context': ['resolve'],
|
|
47
|
+
'platform-comment': ['list', 'owner', 'backfill', 'sync'],
|
|
48
|
+
'platform-issue': ['inspect', 'create', 'bind', 'sync'],
|
|
49
|
+
'platform-pr': ['inspect', 'summary-context', 'resolve-external', 'create', 'bind', 'skip', 'sync', 'change-report', 'summary-sync', 'sync-in-labels'],
|
|
50
|
+
'platform-pr-review': ['inspect', 'list', 'publish-pr', 'publish-task'],
|
|
51
|
+
'pr-review-grade': ['decide', 'resolve-host', 'verify-artifact'],
|
|
52
|
+
'platform-checks': ['inspect', 'watch', 'resolve-run', 'logs'],
|
|
53
|
+
'task-context': ['resolve'],
|
|
54
|
+
'task-ledger': ['decision-next-id', 'stage-status', 'finding-upsert', 'finding-respond', 'finding-review', 'decision-upsert', 'rework-intent-upsert'],
|
|
55
|
+
'task-warning': ['list', 'add', 'set-status'],
|
|
56
|
+
'task-activity': ['pr-review-inspect', 'pr-review-start', 'pr-review-complete', 'pr-review-terminate'],
|
|
57
|
+
'task-artifact': ['inspect', 'init', 'repair', 'finalize-local'],
|
|
58
|
+
'task-orchestration': ['status', 'progress'],
|
|
59
|
+
'task-review': ['finalize-summary'],
|
|
60
|
+
'task-event': ['event'],
|
|
61
|
+
'task-invalidation': ['reconcile'],
|
|
62
|
+
'task-override': ['diagnose', 'issue', 'consume'],
|
|
63
|
+
'task-lifecycle': ['intent'],
|
|
64
|
+
'task-finalization': ['complete'],
|
|
65
|
+
'task-short-id': ['list', 'list-verify', 'alloc', 'release', 'resolve'],
|
|
66
|
+
'task-snapshot': ['snapshot'],
|
|
67
|
+
'task-verify': ['event'],
|
|
68
|
+
'task-validate': ['snapshot', 'inplace'],
|
|
69
|
+
'manual-validation': ['transaction']
|
|
70
|
+
});
|
|
71
|
+
export const INTERNAL_CLI_ROUTE_SELECTORS = INTERNAL_HANDLER_ROUTE_SELECTORS;
|
|
72
|
+
function first(args) {
|
|
73
|
+
return args[0] ?? '';
|
|
74
|
+
}
|
|
75
|
+
function optionValue(args, name) {
|
|
76
|
+
const index = args.indexOf(name);
|
|
77
|
+
if (index >= 0)
|
|
78
|
+
return args[index + 1];
|
|
79
|
+
const prefix = `${name}=`;
|
|
80
|
+
return args.find((arg) => arg.startsWith(prefix))?.slice(prefix.length);
|
|
81
|
+
}
|
|
82
|
+
export function internalRouteSelector(command, args) {
|
|
83
|
+
if (command === 'sandbox-control')
|
|
84
|
+
return first(args);
|
|
85
|
+
if (command === 'task-create')
|
|
86
|
+
return 'input';
|
|
87
|
+
if (command === 'task-qualification')
|
|
88
|
+
return args[1] ?? '';
|
|
89
|
+
if (command === 'task-lifecycle')
|
|
90
|
+
return args[1] ? 'intent' : '';
|
|
91
|
+
if (command === 'task-finalization')
|
|
92
|
+
return args[1] === 'complete' ? 'complete' : '';
|
|
93
|
+
if (command === 'task-event')
|
|
94
|
+
return args[1] ? 'event' : '';
|
|
95
|
+
if (command === 'task-verify')
|
|
96
|
+
return args[0] && args[1] ? 'event' : '';
|
|
97
|
+
if (command === 'task-snapshot')
|
|
98
|
+
return 'snapshot';
|
|
99
|
+
if (command === 'task-validate')
|
|
100
|
+
return optionValue(args, '--scope') ?? 'snapshot';
|
|
101
|
+
if (command === 'task-short-id')
|
|
102
|
+
return first(args) === 'list' && args.includes('--verify') ? 'list-verify' : first(args);
|
|
103
|
+
if (command === 'task-orchestration')
|
|
104
|
+
return args[1] === 'status' ? 'status' : args[1] ? 'progress' : '';
|
|
105
|
+
if (command === 'task-review')
|
|
106
|
+
return args[1] ?? '';
|
|
107
|
+
if (command === 'task-invalidation')
|
|
108
|
+
return args[1] ?? '';
|
|
109
|
+
if (command === 'task-override')
|
|
110
|
+
return args[1] ?? '';
|
|
111
|
+
if (command === 'task-artifact')
|
|
112
|
+
return args[1] ?? '';
|
|
113
|
+
if (command === 'platform-pr-review' && first(args) === 'publish') {
|
|
114
|
+
const scope = optionValue(args, '--scope') ?? '';
|
|
115
|
+
return /^TASK-\d{8}-\d{6}$/u.test(scope) ? 'publish-task' : /^pr\d+$/u.test(scope) ? 'publish-pr' : '';
|
|
116
|
+
}
|
|
117
|
+
if (['task-ledger', 'task-warning', 'task-activity'].includes(command))
|
|
118
|
+
return args[1] ?? '';
|
|
119
|
+
if (command === 'task-delivery')
|
|
120
|
+
return args[1] ?? '';
|
|
121
|
+
if (command === 'task-context')
|
|
122
|
+
return first(args);
|
|
123
|
+
return first(args);
|
|
124
|
+
}
|
|
125
|
+
export function isInternalHandlerRoute(command, args) {
|
|
126
|
+
if (args[0] === '--help' || args[0] === '-h')
|
|
127
|
+
return true;
|
|
128
|
+
const selector = internalRouteSelector(command, args);
|
|
129
|
+
const selectors = INTERNAL_HANDLER_ROUTE_SELECTORS[command];
|
|
130
|
+
return Boolean(selector && selectors?.some((candidate) => candidate === selector));
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Marks a selector at the handler's actual dispatch branch.
|
|
134
|
+
*
|
|
135
|
+
* The call is intentionally side-effect free so the top-level task-view guard
|
|
136
|
+
* can still run before a handler module is imported. Route coverage tests read
|
|
137
|
+
* these branch markers independently from the pre-import inventory.
|
|
138
|
+
*/
|
|
139
|
+
export function internalHandlerRoute(command, selector, actualSelector) {
|
|
140
|
+
return command.length > 0 && selector === actualSelector;
|
|
141
|
+
}
|
|
142
|
+
export function ensureInternalHandlerRoute(command, args) {
|
|
143
|
+
if (isInternalHandlerRoute(command, args))
|
|
144
|
+
return true;
|
|
145
|
+
const selector = internalRouteSelector(command, args);
|
|
146
|
+
process.stdout.write(`${JSON.stringify({
|
|
147
|
+
status: 'failed',
|
|
148
|
+
changed: false,
|
|
149
|
+
error: { code: 'INTERNAL_ROUTE_UNREGISTERED', message: `operation '${command} ${selector || first(args)}' is not registered` }
|
|
150
|
+
})}\n`);
|
|
151
|
+
process.exitCode = 1;
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=cli-route-inventory.js.map
|
|
@@ -10,6 +10,7 @@ import { verifyCodexSandboxControllerContextWithWarnings } from '../agent-client
|
|
|
10
10
|
import { resolveTaskRef } from '../task/resolve-ref.js';
|
|
11
11
|
import { hasSealableOrchestrationDelegation } from '../task/orchestration.js';
|
|
12
12
|
import { activateCodexOrchestrationDelegation, activateCodexSpawnDelegation, reconcileCodexOrchestrationDelegation, sealCodexOrchestrationDelegation, sealCodexParentDelegation } from '../task/codex-orchestration.js';
|
|
13
|
+
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
|
|
13
14
|
const USAGE = 'Usage: agent-infra-internal codex-lifecycle <capability-arm|hook-event|resolve-start|resolve-stop|preflight|consume> [options]\n';
|
|
14
15
|
const MANAGED_AGENT = /^agent-infra-lifecycle-(executor|reviewer)$/;
|
|
15
16
|
function output(value) {
|
|
@@ -144,11 +145,13 @@ function payloadText(payload, key) {
|
|
|
144
145
|
: '';
|
|
145
146
|
}
|
|
146
147
|
async function codexLifecycle(args = []) {
|
|
148
|
+
if (!ensureInternalHandlerRoute('codex-lifecycle', args))
|
|
149
|
+
return;
|
|
147
150
|
const parsed = parse(args);
|
|
148
151
|
if (!parsed || process.exitCode)
|
|
149
152
|
return;
|
|
150
153
|
try {
|
|
151
|
-
if (
|
|
154
|
+
if (internalHandlerRoute('codex-lifecycle', 'preflight', parsed.operation)) {
|
|
152
155
|
const format = parsed.values['--format'] ?? 'json';
|
|
153
156
|
if (!['text', 'json'].includes(format))
|
|
154
157
|
throw new Error("format must be 'text' or 'json'");
|
|
@@ -173,7 +176,7 @@ async function codexLifecycle(args = []) {
|
|
|
173
176
|
output({ status: 'ready', changed: false, evidence: result, diagnostics: result.diagnostics, error: null });
|
|
174
177
|
return;
|
|
175
178
|
}
|
|
176
|
-
if (
|
|
179
|
+
if (internalHandlerRoute('codex-lifecycle', 'capability-arm', parsed.operation)) {
|
|
177
180
|
const taskId = parsed.values['--task-id'];
|
|
178
181
|
if (!taskId)
|
|
179
182
|
throw new Error('capability-arm requires --task-id');
|
|
@@ -188,7 +191,7 @@ async function codexLifecycle(args = []) {
|
|
|
188
191
|
output({
|
|
189
192
|
status: 'armed',
|
|
190
193
|
changed: true,
|
|
191
|
-
|
|
194
|
+
capabilityRef: armed.capabilityRef,
|
|
192
195
|
marker: armed.marker,
|
|
193
196
|
expiresAt: armed.expiresAt,
|
|
194
197
|
buildIdentity: armed.buildIdentity,
|
|
@@ -197,7 +200,7 @@ async function codexLifecycle(args = []) {
|
|
|
197
200
|
return;
|
|
198
201
|
}
|
|
199
202
|
const store = createCodexLifecycleStore({ cliVersion: cliVersion() });
|
|
200
|
-
if (
|
|
203
|
+
if (internalHandlerRoute('codex-lifecycle', 'hook-event', parsed.operation)) {
|
|
201
204
|
const phase = parsed.values['--event'];
|
|
202
205
|
if (!phase || !['pre-tool', 'subagent-start', 'post-tool', 'subagent-stop'].includes(phase)) {
|
|
203
206
|
throw new Error('hook-event requires a known --event');
|
|
@@ -207,12 +210,12 @@ async function codexLifecycle(args = []) {
|
|
|
207
210
|
}
|
|
208
211
|
const payload = await readStdin();
|
|
209
212
|
if (phase === 'post-tool') {
|
|
210
|
-
const
|
|
211
|
-
if (
|
|
213
|
+
const capabilityRef = payloadText(payload, 'capabilityRef');
|
|
214
|
+
if (capabilityRef) {
|
|
212
215
|
const capabilityStore = createCodexCapabilityStore();
|
|
213
|
-
const armed = capabilityStore.
|
|
214
|
-
const capability =
|
|
215
|
-
|
|
216
|
+
const armed = capabilityStore.inspectReference(capabilityRef);
|
|
217
|
+
const capability = capabilityStore.attestByReference({
|
|
218
|
+
capabilityRef,
|
|
216
219
|
sessionId: payloadText(payload, 'sessionId'),
|
|
217
220
|
turnId: payloadText(payload, 'turnId'),
|
|
218
221
|
toolUseId: payloadText(payload, 'toolUseId'),
|
|
@@ -337,7 +340,7 @@ async function codexLifecycle(args = []) {
|
|
|
337
340
|
const childThreadId = parsed.values['--child-id'];
|
|
338
341
|
if (!childThreadId)
|
|
339
342
|
throw new Error(`operation '${parsed.operation}' requires --child-id`);
|
|
340
|
-
if (
|
|
343
|
+
if (internalHandlerRoute('codex-lifecycle', 'resolve-start', parsed.operation)) {
|
|
341
344
|
if (store.read(childThreadId).state.spawn?.hookDefinitionHash !== hookDefinitionHash()) {
|
|
342
345
|
throw new Error('Codex lifecycle hook definition hash is stale');
|
|
343
346
|
}
|
|
@@ -351,7 +354,7 @@ async function codexLifecycle(args = []) {
|
|
|
351
354
|
process.exitCode = 1;
|
|
352
355
|
return;
|
|
353
356
|
}
|
|
354
|
-
if (
|
|
357
|
+
if (internalHandlerRoute('codex-lifecycle', 'resolve-stop', parsed.operation)) {
|
|
355
358
|
const stopTurnId = store.read(childThreadId).state.stop?.turnId;
|
|
356
359
|
if (!stopTurnId)
|
|
357
360
|
throw new Error('Codex lifecycle stop hook is not available');
|
|
@@ -363,7 +366,7 @@ async function codexLifecycle(args = []) {
|
|
|
363
366
|
output({ status: latest.state.status, changed: true, evidence: latest.state.stopEvidence, diagnostics: [], error: latest.state.error });
|
|
364
367
|
return;
|
|
365
368
|
}
|
|
366
|
-
if (
|
|
369
|
+
if (internalHandlerRoute('codex-lifecycle', 'consume', parsed.operation)) {
|
|
367
370
|
const consumer = parsed.values['--consumer'];
|
|
368
371
|
if (!consumer)
|
|
369
372
|
throw new Error('consume requires --consumer');
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { runCodexSandboxController, verifyCodexSandboxControllerContextWithWarnings } from '../agent-clients/adapters/codex-lifecycle/sandbox-controller.js';
|
|
2
|
+
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
|
|
2
3
|
const USAGE = 'Usage: agent-infra-internal codex-sandbox-controller <run|verify-context> [options]\n';
|
|
3
4
|
function fail(code, message, exitCode = 1) {
|
|
4
5
|
process.stdout.write(`${JSON.stringify({
|
|
@@ -14,7 +15,10 @@ function parse(args) {
|
|
|
14
15
|
return null;
|
|
15
16
|
}
|
|
16
17
|
const operation = args[0];
|
|
17
|
-
if (!operation || ![
|
|
18
|
+
if (!operation || ![
|
|
19
|
+
internalHandlerRoute('codex-sandbox-controller', 'run', operation),
|
|
20
|
+
internalHandlerRoute('codex-sandbox-controller', 'verify-context', operation)
|
|
21
|
+
].some(Boolean)) {
|
|
18
22
|
process.stderr.write(USAGE);
|
|
19
23
|
fail('CODEX_SANDBOX_CONTROLLER_PAYLOAD_INVALID', 'operation must be run or verify-context', 2);
|
|
20
24
|
return null;
|
|
@@ -44,11 +48,13 @@ function parse(args) {
|
|
|
44
48
|
return { operation, values };
|
|
45
49
|
}
|
|
46
50
|
async function codexSandboxController(args = []) {
|
|
51
|
+
if (!ensureInternalHandlerRoute('codex-sandbox-controller', args))
|
|
52
|
+
return;
|
|
47
53
|
const parsed = parse(args);
|
|
48
54
|
if (!parsed || process.exitCode)
|
|
49
55
|
return;
|
|
50
56
|
try {
|
|
51
|
-
if (
|
|
57
|
+
if (internalHandlerRoute('codex-sandbox-controller', 'verify-context', parsed.operation)) {
|
|
52
58
|
const contextPath = parsed.values['--context']
|
|
53
59
|
?? process.env.AGENT_INFRA_CODEX_CONTROLLER_CONTEXT;
|
|
54
60
|
if (!contextPath)
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
const DEMO_ASSET_NAMES = ['gif', 'transcript', 'sha256'];
|
|
5
|
+
const JOURNAL_RELATIVE_PATH = 'assets/.demo-init.promotion.json';
|
|
6
|
+
const PROMOTION_DIR_PREFIX = '.demo-init.promotion-';
|
|
7
|
+
function sha256Bytes(value) {
|
|
8
|
+
return crypto.createHash('sha256').update(value).digest('hex');
|
|
9
|
+
}
|
|
10
|
+
function sha256File(filePath, io = fs) {
|
|
11
|
+
return sha256Bytes(io.readFileSync(filePath));
|
|
12
|
+
}
|
|
13
|
+
function assetTargets(cwd) {
|
|
14
|
+
return {
|
|
15
|
+
gif: path.join(cwd, 'assets', 'demo-init.gif'),
|
|
16
|
+
transcript: path.join(cwd, 'assets', 'demo-init.transcript'),
|
|
17
|
+
sha256: path.join(cwd, 'assets', 'demo-init.transcript.sha256')
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function journalPath(cwd) {
|
|
21
|
+
return path.join(cwd, JOURNAL_RELATIVE_PATH);
|
|
22
|
+
}
|
|
23
|
+
function isUnsupportedFsyncError(error) {
|
|
24
|
+
const code = error.code;
|
|
25
|
+
return code === 'EINVAL' || code === 'ENOSYS' || code === 'ENOTSUP' || code === 'EPERM';
|
|
26
|
+
}
|
|
27
|
+
function syncFile(filePath, io) {
|
|
28
|
+
if (!io.openSync || !io.closeSync || !io.fsyncSync)
|
|
29
|
+
return;
|
|
30
|
+
const descriptor = io.openSync(filePath, 'r');
|
|
31
|
+
try {
|
|
32
|
+
try {
|
|
33
|
+
io.fsyncSync(descriptor);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (!isUnsupportedFsyncError(error))
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
io.closeSync(descriptor);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function writeJournal(cwd, journal, io) {
|
|
45
|
+
const target = journalPath(cwd);
|
|
46
|
+
const temporary = `${target}.tmp-${process.pid}`;
|
|
47
|
+
io.writeFileSync(temporary, `${JSON.stringify(journal, null, 2)}\n`);
|
|
48
|
+
syncFile(temporary, io);
|
|
49
|
+
try {
|
|
50
|
+
io.renameSync(temporary, target);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
try {
|
|
54
|
+
io.unlinkSync(temporary);
|
|
55
|
+
}
|
|
56
|
+
catch { /* preserve primary error */ }
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function existingRegularFile(filePath, io) {
|
|
61
|
+
if (!io.existsSync(filePath))
|
|
62
|
+
return false;
|
|
63
|
+
const stat = io.lstatSync(filePath);
|
|
64
|
+
if (!stat.isFile() || stat.isSymbolicLink())
|
|
65
|
+
throw new Error(`promotion target is not a regular file: ${filePath}`);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
function removeIfPresent(filePath, io) {
|
|
69
|
+
if (io.existsSync(filePath))
|
|
70
|
+
io.unlinkSync(filePath);
|
|
71
|
+
}
|
|
72
|
+
function samePath(left, right) {
|
|
73
|
+
return path.normalize(path.resolve(left)) === path.normalize(path.resolve(right));
|
|
74
|
+
}
|
|
75
|
+
function pathIsInside(root, candidate) {
|
|
76
|
+
const relative = path.relative(root, candidate);
|
|
77
|
+
return relative !== '' && !path.isAbsolute(relative) && relative !== '..' && !relative.startsWith(`..${path.sep}`);
|
|
78
|
+
}
|
|
79
|
+
function existingStat(filePath, io) {
|
|
80
|
+
try {
|
|
81
|
+
return io.lstatSync(filePath);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error.code === 'ENOENT')
|
|
85
|
+
return null;
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function validatePromotionJournal(cwd, journal, io) {
|
|
90
|
+
if (!journal || typeof journal !== 'object')
|
|
91
|
+
throw new Error('promotion journal is invalid');
|
|
92
|
+
if (journal.version !== 1 || !['prepared', 'promoting', 'committed'].includes(journal.phase)) {
|
|
93
|
+
throw new Error('promotion journal is invalid');
|
|
94
|
+
}
|
|
95
|
+
if (typeof journal.generation !== 'string' || !journal.generation || /[\r\n]/u.test(journal.generation)) {
|
|
96
|
+
throw new Error('promotion journal generation is invalid');
|
|
97
|
+
}
|
|
98
|
+
if (!Array.isArray(journal.entries) || journal.entries.length !== DEMO_ASSET_NAMES.length) {
|
|
99
|
+
throw new Error('promotion journal entries are invalid');
|
|
100
|
+
}
|
|
101
|
+
if (!Number.isInteger(journal.currentIndex) || journal.currentIndex < -1 || journal.currentIndex >= journal.entries.length) {
|
|
102
|
+
throw new Error('promotion journal index is invalid');
|
|
103
|
+
}
|
|
104
|
+
const assets = path.join(cwd, 'assets');
|
|
105
|
+
const assetsStat = existingStat(assets, io);
|
|
106
|
+
if (!assetsStat || assetsStat.isSymbolicLink() || !assetsStat.isDirectory()) {
|
|
107
|
+
throw new Error('promotion assets directory is invalid');
|
|
108
|
+
}
|
|
109
|
+
if (typeof journal.directory !== 'string' || path.isAbsolute(journal.directory)) {
|
|
110
|
+
throw new Error('promotion journal directory is invalid');
|
|
111
|
+
}
|
|
112
|
+
const directory = path.resolve(cwd, journal.directory);
|
|
113
|
+
const directoryName = path.basename(directory);
|
|
114
|
+
if (!directoryName.startsWith(PROMOTION_DIR_PREFIX) || directoryName === PROMOTION_DIR_PREFIX
|
|
115
|
+
|| journal.directory !== path.relative(cwd, directory)
|
|
116
|
+
|| !samePath(directory, path.join(assets, directoryName))) {
|
|
117
|
+
throw new Error('promotion journal directory is invalid');
|
|
118
|
+
}
|
|
119
|
+
const directoryStat = existingStat(directory, io);
|
|
120
|
+
if (directoryStat && (directoryStat.isSymbolicLink() || !directoryStat.isDirectory())) {
|
|
121
|
+
throw new Error('promotion journal directory is invalid');
|
|
122
|
+
}
|
|
123
|
+
const targets = assetTargets(cwd);
|
|
124
|
+
for (const [index, name] of DEMO_ASSET_NAMES.entries()) {
|
|
125
|
+
const entry = journal.entries[index];
|
|
126
|
+
if (!entry || entry.name !== name || typeof entry.target !== 'string' || typeof entry.staging !== 'string'
|
|
127
|
+
|| typeof entry.backup !== 'string' || typeof entry.existed !== 'boolean'
|
|
128
|
+
|| (entry.oldSha256 !== null && typeof entry.oldSha256 !== 'string')
|
|
129
|
+
|| typeof entry.newSha256 !== 'string') {
|
|
130
|
+
throw new Error('promotion journal entry is invalid');
|
|
131
|
+
}
|
|
132
|
+
const target = targets[name];
|
|
133
|
+
const staging = path.join(directory, path.basename(target));
|
|
134
|
+
const backup = path.join(directory, `old-${name}`);
|
|
135
|
+
if (!samePath(entry.target, target) || !samePath(entry.staging, staging) || !samePath(entry.backup, backup)) {
|
|
136
|
+
throw new Error(`promotion journal path is invalid: ${name}`);
|
|
137
|
+
}
|
|
138
|
+
for (const [label, filePath] of [['target', target], ['staging', staging], ['backup', backup]]) {
|
|
139
|
+
if (!pathIsInside(assets, filePath))
|
|
140
|
+
throw new Error(`promotion journal path is invalid: ${name}.${label}`);
|
|
141
|
+
const stat = existingStat(filePath, io);
|
|
142
|
+
if (stat && (stat.isSymbolicLink() || !stat.isFile())) {
|
|
143
|
+
throw new Error(`promotion journal path is invalid: ${name}.${label}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (entry.existed !== (entry.oldSha256 !== null)) {
|
|
147
|
+
throw new Error(`promotion journal entry is invalid: ${name}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return journal;
|
|
151
|
+
}
|
|
152
|
+
function cleanupJournal(journal, cwd, io) {
|
|
153
|
+
for (const entry of journal.entries) {
|
|
154
|
+
removeIfPresent(entry.staging, io);
|
|
155
|
+
removeIfPresent(entry.backup, io);
|
|
156
|
+
}
|
|
157
|
+
io.rmSync(path.join(cwd, journal.directory), { recursive: true, force: true });
|
|
158
|
+
removeIfPresent(journalPath(cwd), io);
|
|
159
|
+
}
|
|
160
|
+
function verifyTargets(entries, io, expected) {
|
|
161
|
+
for (const entry of entries) {
|
|
162
|
+
if (!entry.existed && expected === 'old') {
|
|
163
|
+
if (io.existsSync(entry.target))
|
|
164
|
+
throw new Error(`old promotion target unexpectedly exists: ${entry.target}`);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (!io.existsSync(entry.target))
|
|
168
|
+
throw new Error(`promotion target is missing: ${entry.target}`);
|
|
169
|
+
const actual = sha256File(entry.target, io);
|
|
170
|
+
const wanted = expected === 'old' ? entry.oldSha256 : entry.newSha256;
|
|
171
|
+
if (!wanted || actual !== wanted)
|
|
172
|
+
throw new Error(`promotion target has unexpected content: ${entry.target}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function restoreOld(journal, io) {
|
|
176
|
+
for (const entry of [...journal.entries].reverse()) {
|
|
177
|
+
if (!entry.existed) {
|
|
178
|
+
removeIfPresent(entry.target, io);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (!io.existsSync(entry.backup) || sha256File(entry.backup, io) !== entry.oldSha256) {
|
|
182
|
+
throw new Error(`promotion backup is missing or corrupt: ${entry.backup}`);
|
|
183
|
+
}
|
|
184
|
+
const restore = `${entry.target}.restore-${process.pid}`;
|
|
185
|
+
io.copyFileSync(entry.backup, restore);
|
|
186
|
+
removeIfPresent(entry.target, io);
|
|
187
|
+
io.renameSync(restore, entry.target);
|
|
188
|
+
}
|
|
189
|
+
verifyTargets(journal.entries, io, 'old');
|
|
190
|
+
}
|
|
191
|
+
function recoveryFailure(error) {
|
|
192
|
+
return {
|
|
193
|
+
status: 'failed',
|
|
194
|
+
code: 'DEMO_PROMOTION_RECOVERY_REQUIRED',
|
|
195
|
+
message: error instanceof Error ? error.message : String(error)
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function recoverDemoPromotion(cwd, io = fs) {
|
|
199
|
+
const target = journalPath(cwd);
|
|
200
|
+
if (!io.existsSync(target))
|
|
201
|
+
return null;
|
|
202
|
+
let journal;
|
|
203
|
+
try {
|
|
204
|
+
const journalStat = io.lstatSync(target);
|
|
205
|
+
if (journalStat.isSymbolicLink() || !journalStat.isFile())
|
|
206
|
+
throw new Error('promotion journal is invalid');
|
|
207
|
+
journal = JSON.parse(io.readFileSync(target, 'utf8'));
|
|
208
|
+
journal = validatePromotionJournal(cwd, journal, io);
|
|
209
|
+
if (journal.phase === 'committed') {
|
|
210
|
+
try {
|
|
211
|
+
verifyTargets(journal.entries, io, 'new');
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
restoreOld(journal, io);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
restoreOld(journal, io);
|
|
219
|
+
}
|
|
220
|
+
cleanupJournal(journal, cwd, io);
|
|
221
|
+
return { status: 'committed', code: null, message: null };
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
return recoveryFailure(error);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function createDemoPromotion(cwd, transcript) {
|
|
228
|
+
const assets = path.join(cwd, 'assets');
|
|
229
|
+
const directory = fs.mkdtempSync(path.join(assets, PROMOTION_DIR_PREFIX));
|
|
230
|
+
const staging = {
|
|
231
|
+
gif: path.join(directory, 'demo-init.gif'),
|
|
232
|
+
transcript: path.join(directory, 'demo-init.transcript'),
|
|
233
|
+
sha256: path.join(directory, 'demo-init.transcript.sha256')
|
|
234
|
+
};
|
|
235
|
+
const sha256 = sha256Bytes(Buffer.from(transcript, 'utf8'));
|
|
236
|
+
fs.writeFileSync(staging.transcript, transcript);
|
|
237
|
+
fs.writeFileSync(staging.sha256, `${sha256}\n`);
|
|
238
|
+
return { directory, staging, sha256 };
|
|
239
|
+
}
|
|
240
|
+
function promoteDemoAssets(cwd, staging, generation, io = fs) {
|
|
241
|
+
const targets = assetTargets(cwd);
|
|
242
|
+
const directory = path.relative(cwd, path.dirname(staging.gif));
|
|
243
|
+
const journal = {
|
|
244
|
+
version: 1,
|
|
245
|
+
generation,
|
|
246
|
+
phase: 'prepared',
|
|
247
|
+
currentIndex: -1,
|
|
248
|
+
directory,
|
|
249
|
+
entries: []
|
|
250
|
+
};
|
|
251
|
+
try {
|
|
252
|
+
for (const name of DEMO_ASSET_NAMES) {
|
|
253
|
+
if (!io.existsSync(staging[name]))
|
|
254
|
+
throw new Error(`staged demo asset is missing: ${staging[name]}`);
|
|
255
|
+
const target = targets[name];
|
|
256
|
+
const backup = path.join(path.dirname(staging[name]), `old-${name}`);
|
|
257
|
+
const existed = existingRegularFile(target, io);
|
|
258
|
+
const oldSha256 = existed ? sha256File(target, io) : null;
|
|
259
|
+
if (existed) {
|
|
260
|
+
io.copyFileSync(target, backup);
|
|
261
|
+
if (sha256File(backup, io) !== oldSha256)
|
|
262
|
+
throw new Error(`promotion backup verification failed: ${target}`);
|
|
263
|
+
}
|
|
264
|
+
journal.entries.push({
|
|
265
|
+
name, target, staging: staging[name], backup, existed, oldSha256,
|
|
266
|
+
newSha256: sha256File(staging[name], io)
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
writeJournal(cwd, journal, io);
|
|
270
|
+
for (let index = 0; index < journal.entries.length; index += 1) {
|
|
271
|
+
journal.phase = 'promoting';
|
|
272
|
+
journal.currentIndex = index;
|
|
273
|
+
writeJournal(cwd, journal, io);
|
|
274
|
+
const entry = journal.entries[index];
|
|
275
|
+
removeIfPresent(entry.target, io);
|
|
276
|
+
io.renameSync(entry.staging, entry.target);
|
|
277
|
+
if (sha256File(entry.target, io) !== entry.newSha256)
|
|
278
|
+
throw new Error(`promoted asset verification failed: ${entry.target}`);
|
|
279
|
+
writeJournal(cwd, journal, io);
|
|
280
|
+
}
|
|
281
|
+
verifyTargets(journal.entries, io, 'new');
|
|
282
|
+
journal.phase = 'committed';
|
|
283
|
+
writeJournal(cwd, journal, io);
|
|
284
|
+
try {
|
|
285
|
+
cleanupJournal(journal, cwd, io);
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
return {
|
|
289
|
+
status: 'failed',
|
|
290
|
+
code: 'DEMO_PROMOTION_CLEANUP_FAILED',
|
|
291
|
+
message: error instanceof Error ? error.message : String(error)
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
return { status: 'committed', code: null, message: null };
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
try {
|
|
298
|
+
if (io.existsSync(journalPath(cwd))) {
|
|
299
|
+
const persisted = validatePromotionJournal(cwd, JSON.parse(io.readFileSync(journalPath(cwd), 'utf8')), io);
|
|
300
|
+
if (persisted.phase === 'committed') {
|
|
301
|
+
verifyTargets(persisted.entries, io, 'new');
|
|
302
|
+
return {
|
|
303
|
+
status: 'failed',
|
|
304
|
+
code: 'DEMO_PROMOTION_CLEANUP_FAILED',
|
|
305
|
+
message: error instanceof Error ? error.message : String(error)
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
restoreOld(persisted, io);
|
|
309
|
+
cleanupJournal(persisted, cwd, io);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
io.rmSync(path.dirname(staging.gif), { recursive: true, force: true });
|
|
313
|
+
}
|
|
314
|
+
return { status: 'failed', code: 'DEMO_PROMOTION_FAILED', message: error instanceof Error ? error.message : String(error) };
|
|
315
|
+
}
|
|
316
|
+
catch (rollbackError) {
|
|
317
|
+
return recoveryFailure(rollbackError);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
export { DEMO_ASSET_NAMES, JOURNAL_RELATIVE_PATH, assetTargets, createDemoPromotion, journalPath, promoteDemoAssets, recoverDemoPromotion, sha256Bytes };
|
|
322
|
+
//# sourceMappingURL=demo-promotion.js.map
|