@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,289 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { runProbe } from '../shell.js';
|
|
3
|
+
import { getAdapter } from './index.js';
|
|
4
|
+
function digest(value) {
|
|
5
|
+
return createHash('sha256').update(value).digest('hex');
|
|
6
|
+
}
|
|
7
|
+
function canonical(value) {
|
|
8
|
+
if (Array.isArray(value))
|
|
9
|
+
return `[${value.map(canonical).join(',')}]`;
|
|
10
|
+
if (!value || typeof value !== 'object')
|
|
11
|
+
return JSON.stringify(value) ?? 'null';
|
|
12
|
+
return `{${Object.entries(value)
|
|
13
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
14
|
+
.map(([key, entry]) => `${JSON.stringify(key)}:${canonical(entry)}`)
|
|
15
|
+
.join(',')}}`;
|
|
16
|
+
}
|
|
17
|
+
function text(value) {
|
|
18
|
+
return typeof value === 'string' ? value : value?.toString('utf8') ?? '';
|
|
19
|
+
}
|
|
20
|
+
function safeEndpoint(value) {
|
|
21
|
+
if (!value)
|
|
22
|
+
return 'docker-default';
|
|
23
|
+
try {
|
|
24
|
+
const parsed = new URL(value);
|
|
25
|
+
const hasUnreplayableParts = Boolean(parsed.username || parsed.password || parsed.search || parsed.hash);
|
|
26
|
+
parsed.username = '';
|
|
27
|
+
parsed.password = '';
|
|
28
|
+
parsed.search = '';
|
|
29
|
+
parsed.hash = '';
|
|
30
|
+
const normalized = parsed.toString().replace(/\/$/u, '');
|
|
31
|
+
return hasUnreplayableParts
|
|
32
|
+
? `${normalized}#<redacted>`
|
|
33
|
+
: normalized;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
const normalized = value
|
|
37
|
+
.replace(/\/\/[^/@]+@/u, '//<redacted>@')
|
|
38
|
+
.replace(/[?&](?:token|password|secret|key)=[^&]*/giu, '');
|
|
39
|
+
return /[@?#]/u.test(value) ? `${normalized.replace(/[?#].*$/u, '')}#<redacted>` : normalized;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function lockDomainFor(engine, endpoint) {
|
|
43
|
+
return digest(`${process.platform}\0${process.arch}\0${engine}\0${endpoint}`);
|
|
44
|
+
}
|
|
45
|
+
function contextRoute(context) {
|
|
46
|
+
return {
|
|
47
|
+
kind: 'context',
|
|
48
|
+
selector: { context },
|
|
49
|
+
endpoint: `docker-context://${context}`,
|
|
50
|
+
command: (args) => ({ cmd: 'docker', args: ['--context', context, ...args] })
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function endpointRoute(endpoint, rawEndpoint, unreplayable) {
|
|
54
|
+
return {
|
|
55
|
+
kind: 'endpoint',
|
|
56
|
+
selector: {
|
|
57
|
+
source: 'DOCKER_HOST',
|
|
58
|
+
endpoint,
|
|
59
|
+
...(unreplayable ? { unreplayable } : {})
|
|
60
|
+
},
|
|
61
|
+
endpoint,
|
|
62
|
+
command: (args) => ({ cmd: 'docker', args: ['--host', rawEndpoint, ...args] })
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function tlsEnvironmentReason(env) {
|
|
66
|
+
return env.DOCKER_TLS_VERIFY || env.DOCKER_CERT_PATH || env.DOCKER_TLS
|
|
67
|
+
? 'tls-environment'
|
|
68
|
+
: undefined;
|
|
69
|
+
}
|
|
70
|
+
function routeFor(engine, env) {
|
|
71
|
+
const context = getAdapter(engine).dockerContext;
|
|
72
|
+
if (context) {
|
|
73
|
+
return contextRoute(context);
|
|
74
|
+
}
|
|
75
|
+
if (env.DOCKER_CONTEXT) {
|
|
76
|
+
return contextRoute(env.DOCKER_CONTEXT);
|
|
77
|
+
}
|
|
78
|
+
if (env.DOCKER_HOST) {
|
|
79
|
+
return endpointRoute(safeEndpoint(env.DOCKER_HOST), env.DOCKER_HOST, tlsEnvironmentReason(env));
|
|
80
|
+
}
|
|
81
|
+
return contextRoute('default');
|
|
82
|
+
}
|
|
83
|
+
function validRouteName(value) {
|
|
84
|
+
return /^[A-Za-z0-9][A-Za-z0-9_.@/-]*$/u.test(value);
|
|
85
|
+
}
|
|
86
|
+
function resolveWslDistro(probe, timeoutMs, explicit) {
|
|
87
|
+
if (explicit) {
|
|
88
|
+
if (!validRouteName(explicit))
|
|
89
|
+
throw new Error('SANDBOX_AUTHORITY_ROUTE_CAPTURE_FAILED');
|
|
90
|
+
return explicit;
|
|
91
|
+
}
|
|
92
|
+
const result = probe('wsl.exe', ['--list', '--verbose'], timeoutMs === undefined ? {} : { timeout: timeoutMs });
|
|
93
|
+
if (result.status !== 0)
|
|
94
|
+
throw new Error('SANDBOX_AUTHORITY_ROUTE_CAPTURE_FAILED');
|
|
95
|
+
const output = text(result.stdout).replace(/\0/gu, '').replace(/\r/gu, '');
|
|
96
|
+
const defaultLine = output.split('\n').find((line) => /^\s*\*\s+/u.test(line));
|
|
97
|
+
const distro = defaultLine?.replace(/^\s*\*\s+/u, '').replace(/\s+(?:Running|Stopped)\s+\d+\s*$/iu, '').trim();
|
|
98
|
+
if (!distro || !validRouteName(distro))
|
|
99
|
+
throw new Error('SANDBOX_AUTHORITY_ROUTE_CAPTURE_FAILED');
|
|
100
|
+
return distro;
|
|
101
|
+
}
|
|
102
|
+
function wslRoute(distro, context, env) {
|
|
103
|
+
const endpoint = env.DOCKER_HOST
|
|
104
|
+
? safeEndpoint(env.DOCKER_HOST)
|
|
105
|
+
: `wsl://${distro}/${context ?? 'default'}`;
|
|
106
|
+
const unreplayable = tlsEnvironmentReason(env)
|
|
107
|
+
?? (endpoint.includes('<redacted>') ? 'ambient-endpoint-secret' : undefined);
|
|
108
|
+
return {
|
|
109
|
+
kind: 'wsl2',
|
|
110
|
+
selector: {
|
|
111
|
+
distro,
|
|
112
|
+
...(context ? { context } : {}),
|
|
113
|
+
...(unreplayable ? { unreplayable } : {}),
|
|
114
|
+
...(env.DOCKER_HOST ? { endpoint } : {})
|
|
115
|
+
},
|
|
116
|
+
endpoint,
|
|
117
|
+
command: (args) => ({
|
|
118
|
+
cmd: 'wsl.exe',
|
|
119
|
+
args: [
|
|
120
|
+
'--distribution', distro,
|
|
121
|
+
'--exec', 'docker',
|
|
122
|
+
...(context ? ['--context', context] : []),
|
|
123
|
+
...(env.DOCKER_HOST ? ['--host', env.DOCKER_HOST] : []),
|
|
124
|
+
...args
|
|
125
|
+
]
|
|
126
|
+
})
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function currentWslRoute(env, probe, timeoutMs) {
|
|
130
|
+
const distro = resolveWslDistro(probe, timeoutMs, env.WSL_DISTRO_NAME);
|
|
131
|
+
let context = env.DOCKER_CONTEXT;
|
|
132
|
+
if (!context && !env.DOCKER_HOST) {
|
|
133
|
+
const result = probe('wsl.exe', ['--distribution', distro, '--exec', 'docker', 'context', 'show'], timeoutMs === undefined ? {} : { timeout: timeoutMs });
|
|
134
|
+
context = text(result.stdout).trim();
|
|
135
|
+
if (result.status !== 0 || !validRouteName(context)) {
|
|
136
|
+
throw new Error('SANDBOX_AUTHORITY_ROUTE_CAPTURE_FAILED');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return wslRoute(distro, context, env);
|
|
140
|
+
}
|
|
141
|
+
function routeFromEvidence(evidence) {
|
|
142
|
+
return {
|
|
143
|
+
kind: evidence.routeKind,
|
|
144
|
+
selector: evidence.routeSelector,
|
|
145
|
+
endpoint: evidence.normalizedEndpoint,
|
|
146
|
+
command: (args) => commandForSandboxAuthority(evidence, 'docker', args)
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function currentContextRoute(engine, env, probe, timeoutMs) {
|
|
150
|
+
const configured = routeFor(engine, env);
|
|
151
|
+
if (configured.kind !== 'context' || configured.selector.context !== 'default')
|
|
152
|
+
return configured;
|
|
153
|
+
if (env.DOCKER_CONTEXT || env.DOCKER_HOST || getAdapter(engine).dockerContext)
|
|
154
|
+
return configured;
|
|
155
|
+
const result = probe('docker', ['context', 'show'], timeoutMs === undefined ? {} : { timeout: timeoutMs });
|
|
156
|
+
const context = text(result.stdout).trim();
|
|
157
|
+
if (result.status !== 0 || !/^[A-Za-z0-9][A-Za-z0-9_.@/-]*$/u.test(context)) {
|
|
158
|
+
throw new Error('SANDBOX_AUTHORITY_ROUTE_CAPTURE_FAILED');
|
|
159
|
+
}
|
|
160
|
+
return contextRoute(context);
|
|
161
|
+
}
|
|
162
|
+
/** Build a command using only the route persisted with the sandbox authority. */
|
|
163
|
+
export function commandForSandboxAuthority(evidence, cmd, args = []) {
|
|
164
|
+
if (cmd !== 'docker') {
|
|
165
|
+
throw new Error('SANDBOX_AUTHORITY_ROUTE_UNSUPPORTED');
|
|
166
|
+
}
|
|
167
|
+
if (evidence.routeKind === 'context') {
|
|
168
|
+
const context = evidence.routeSelector.context;
|
|
169
|
+
if (!context)
|
|
170
|
+
throw new Error('SANDBOX_AUTHORITY_ROUTE_INVALID');
|
|
171
|
+
return { cmd, args: ['--context', context, ...args] };
|
|
172
|
+
}
|
|
173
|
+
if (evidence.routeKind === 'endpoint') {
|
|
174
|
+
const endpoint = evidence.routeSelector.endpoint;
|
|
175
|
+
if (!endpoint || endpoint.includes('<redacted>') || evidence.routeSelector.unreplayable) {
|
|
176
|
+
throw new Error('SANDBOX_AUTHORITY_ROUTE_UNREPLAYABLE');
|
|
177
|
+
}
|
|
178
|
+
return { cmd, args: ['--host', endpoint, ...args] };
|
|
179
|
+
}
|
|
180
|
+
if (evidence.routeKind === 'wsl2') {
|
|
181
|
+
const distro = evidence.routeSelector.distro;
|
|
182
|
+
const context = evidence.routeSelector.context;
|
|
183
|
+
const endpoint = evidence.routeSelector.endpoint;
|
|
184
|
+
if (!distro || evidence.routeSelector.unreplayable || endpoint?.includes('<redacted>')) {
|
|
185
|
+
throw new Error('SANDBOX_AUTHORITY_ROUTE_UNREPLAYABLE');
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
cmd: 'wsl.exe',
|
|
189
|
+
args: [
|
|
190
|
+
'--distribution', distro,
|
|
191
|
+
'--exec', cmd,
|
|
192
|
+
...(context ? ['--context', context] : []),
|
|
193
|
+
...(endpoint && !endpoint.startsWith('wsl://') ? ['--host', endpoint] : []),
|
|
194
|
+
...args
|
|
195
|
+
]
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return { cmd, args: ['--context', 'default', ...args] };
|
|
199
|
+
}
|
|
200
|
+
export function authorityVersionArgs() {
|
|
201
|
+
return ['version', '--format', '{{json .Server}}'];
|
|
202
|
+
}
|
|
203
|
+
export function captureSandboxAuthority(engine, options = {}) {
|
|
204
|
+
const env = options.env ?? process.env;
|
|
205
|
+
const probe = options.probe ?? runProbe;
|
|
206
|
+
const route = options.route
|
|
207
|
+
? routeFromEvidence(options.route)
|
|
208
|
+
: engine === 'wsl2'
|
|
209
|
+
? currentWslRoute(env, probe, options.timeoutMs)
|
|
210
|
+
: currentContextRoute(engine, env, probe, options.timeoutMs);
|
|
211
|
+
function probeJson(args) {
|
|
212
|
+
const command = options.route
|
|
213
|
+
? commandForSandboxAuthority(options.route, 'docker', args)
|
|
214
|
+
: route.command(args);
|
|
215
|
+
try {
|
|
216
|
+
const response = probe(command.cmd, command.args, options.timeoutMs === undefined ? {} : { timeout: options.timeoutMs });
|
|
217
|
+
if (response.status !== 0)
|
|
218
|
+
throw new Error('SANDBOX_AUTHORITY_CAPTURE_FAILED');
|
|
219
|
+
return JSON.parse(text(response.stdout).trim());
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
throw new Error('SANDBOX_AUTHORITY_CAPTURE_FAILED');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const server = probeJson(authorityVersionArgs());
|
|
226
|
+
if (!server || typeof server !== 'object' || Array.isArray(server)) {
|
|
227
|
+
throw new Error('SANDBOX_AUTHORITY_CAPTURE_FAILED');
|
|
228
|
+
}
|
|
229
|
+
const record = server;
|
|
230
|
+
const api = typeof record.ApiVersion === 'string' ? /^(\d+)\.(\d+)$/u.exec(record.ApiVersion) : null;
|
|
231
|
+
if (!api)
|
|
232
|
+
throw new Error('SANDBOX_AUTHORITY_CAPTURE_FAILED');
|
|
233
|
+
// Docker version exposes API metadata; the daemon ID belongs to Docker info.
|
|
234
|
+
const serverId = probeJson(['info', '--format', '{{json .ID}}']);
|
|
235
|
+
if (typeof serverId !== 'string' || !serverId.trim())
|
|
236
|
+
throw new Error('SANDBOX_AUTHORITY_CAPTURE_FAILED');
|
|
237
|
+
const normalizedEndpoint = route.endpoint;
|
|
238
|
+
const evidenceWithoutFingerprint = {
|
|
239
|
+
version: 1,
|
|
240
|
+
provider: engine,
|
|
241
|
+
lockDomain: options.lockDomain ?? options.route?.lockDomain ?? lockDomainFor(engine, normalizedEndpoint),
|
|
242
|
+
routeKind: route.kind,
|
|
243
|
+
routeSelector: route.selector,
|
|
244
|
+
normalizedEndpoint,
|
|
245
|
+
endpointFingerprint: digest(normalizedEndpoint),
|
|
246
|
+
daemonIdentity: { kind: 'docker-server-id', fingerprint: digest(serverId) },
|
|
247
|
+
apiVersion: { major: Number(api[1]), minor: Number(api[2]) }
|
|
248
|
+
};
|
|
249
|
+
return {
|
|
250
|
+
...evidenceWithoutFingerprint,
|
|
251
|
+
authorityFingerprint: digest(canonical(evidenceWithoutFingerprint))
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
export function verifySandboxAuthority(expected, actual) {
|
|
255
|
+
if (!expected)
|
|
256
|
+
return { state: 'unknown', reason: 'SANDBOX_AUTHORITY_EVIDENCE_MISSING' };
|
|
257
|
+
if (!actual)
|
|
258
|
+
return { state: 'unknown', reason: 'SANDBOX_AUTHORITY_UNAVAILABLE' };
|
|
259
|
+
if (expected.authorityFingerprint !== actual.authorityFingerprint
|
|
260
|
+
|| expected.lockDomain !== actual.lockDomain
|
|
261
|
+
|| expected.routeKind !== actual.routeKind
|
|
262
|
+
|| expected.endpointFingerprint !== actual.endpointFingerprint
|
|
263
|
+
|| expected.daemonIdentity.fingerprint !== actual.daemonIdentity.fingerprint) {
|
|
264
|
+
return { state: 'conflict', reason: 'SANDBOX_AUTHORITY_DRIFT' };
|
|
265
|
+
}
|
|
266
|
+
return { state: 'verified' };
|
|
267
|
+
}
|
|
268
|
+
export function isSandboxAuthorityEvidence(value) {
|
|
269
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
270
|
+
return false;
|
|
271
|
+
const evidence = value;
|
|
272
|
+
const selector = evidence.routeSelector;
|
|
273
|
+
const daemon = evidence.daemonIdentity;
|
|
274
|
+
const api = evidence.apiVersion;
|
|
275
|
+
return evidence.version === 1
|
|
276
|
+
&& typeof evidence.provider === 'string'
|
|
277
|
+
&& /^[a-f0-9]{64}$/u.test(evidence.lockDomain)
|
|
278
|
+
&& ['default', 'context', 'endpoint', 'wsl2'].includes(evidence.routeKind)
|
|
279
|
+
&& !!selector && typeof selector === 'object' && !Array.isArray(selector)
|
|
280
|
+
&& Object.values(selector).every((entry) => typeof entry === 'string')
|
|
281
|
+
&& typeof evidence.normalizedEndpoint === 'string'
|
|
282
|
+
&& /^[a-f0-9]{64}$/u.test(evidence.endpointFingerprint)
|
|
283
|
+
&& !!daemon && daemon.kind === 'docker-server-id'
|
|
284
|
+
&& /^[a-f0-9]{64}$/u.test(daemon.fingerprint)
|
|
285
|
+
&& !!api && Number.isSafeInteger(api.major) && api.major >= 0
|
|
286
|
+
&& Number.isSafeInteger(api.minor) && api.minor >= 0
|
|
287
|
+
&& /^[a-f0-9]{64}$/u.test(evidence.authorityFingerprint);
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=authority.js.map
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { commandForEngine, runProbe } from '../shell.js';
|
|
2
|
+
import { commandForSandboxAuthority } from './authority.js';
|
|
3
|
+
const FULL_CONTAINER_ID = /^[a-f0-9]{64}$/u;
|
|
4
|
+
function outputText(value) {
|
|
5
|
+
return typeof value === 'string' ? value : value?.toString('utf8') ?? '';
|
|
6
|
+
}
|
|
7
|
+
function unknown(reason) {
|
|
8
|
+
return { state: 'unknown', reason };
|
|
9
|
+
}
|
|
10
|
+
export function buildExactContainerListArgs(id) {
|
|
11
|
+
if (!FULL_CONTAINER_ID.test(id))
|
|
12
|
+
throw new Error('SANDBOX_CONTAINER_ID_NOT_FULL');
|
|
13
|
+
return ['container', 'ls', '--all', '--no-trunc', '--filter', `id=${id}`, '--format', '{{.ID}}'];
|
|
14
|
+
}
|
|
15
|
+
function buildExactContainerInspectArgs(id) {
|
|
16
|
+
return ['container', 'inspect', '--format', '{{json .}}', id];
|
|
17
|
+
}
|
|
18
|
+
function runDockerProbe(engine, args, options) {
|
|
19
|
+
const command = options.authority
|
|
20
|
+
? commandForSandboxAuthority(options.authority, 'docker', args)
|
|
21
|
+
: commandForEngine(engine, 'docker', args);
|
|
22
|
+
return (options.probe ?? runProbe)(command.cmd, command.args, options.timeoutMs === undefined ? {} : { timeout: options.timeoutMs });
|
|
23
|
+
}
|
|
24
|
+
function parseExactList(stdout, expectedId) {
|
|
25
|
+
const rows = stdout.split(/\r?\n/u).map((row) => row.trim()).filter(Boolean);
|
|
26
|
+
if (rows.length === 0)
|
|
27
|
+
return 'empty';
|
|
28
|
+
if (rows.length !== 1)
|
|
29
|
+
return 'exact container query returned multiple rows';
|
|
30
|
+
if (!FULL_CONTAINER_ID.test(rows[0]))
|
|
31
|
+
return 'exact container query returned a malformed ID';
|
|
32
|
+
if (rows[0] !== expectedId)
|
|
33
|
+
return 'conflict';
|
|
34
|
+
return 'present';
|
|
35
|
+
}
|
|
36
|
+
function parseExactInspect(stdout, expectedId) {
|
|
37
|
+
let value;
|
|
38
|
+
try {
|
|
39
|
+
value = JSON.parse(stdout);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return unknown('exact container inspection returned malformed JSON');
|
|
43
|
+
}
|
|
44
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
45
|
+
return unknown('exact container inspection returned an incomplete object');
|
|
46
|
+
}
|
|
47
|
+
const inspected = value;
|
|
48
|
+
if (inspected.Id !== expectedId || typeof inspected.State?.Running !== 'boolean'
|
|
49
|
+
|| !inspected.Config?.Labels || typeof inspected.Config.Labels !== 'object'
|
|
50
|
+
|| Array.isArray(inspected.Config.Labels)) {
|
|
51
|
+
return unknown('exact container inspection identity is incomplete');
|
|
52
|
+
}
|
|
53
|
+
const rawLabels = inspected.Config.Labels;
|
|
54
|
+
if (Object.values(rawLabels).some((value) => typeof value !== 'string')) {
|
|
55
|
+
return unknown('exact container inspection labels are malformed');
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
state: 'found',
|
|
59
|
+
id: expectedId,
|
|
60
|
+
running: inspected.State.Running,
|
|
61
|
+
labels: { ...rawLabels },
|
|
62
|
+
evidence: 'exact-present'
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function discoverExactContainer(engine, id, options = {}) {
|
|
66
|
+
if (!FULL_CONTAINER_ID.test(id))
|
|
67
|
+
return unknown('container identity is not a full 64-character ID');
|
|
68
|
+
let listed;
|
|
69
|
+
try {
|
|
70
|
+
listed = runDockerProbe(engine, buildExactContainerListArgs(id), options);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return unknown('exact container query failed before producing a result');
|
|
74
|
+
}
|
|
75
|
+
if (listed.status !== 0) {
|
|
76
|
+
return unknown(`exact container query exited with ${listed.status ?? 'unknown status'}`);
|
|
77
|
+
}
|
|
78
|
+
const listState = parseExactList(outputText(listed.stdout), id);
|
|
79
|
+
if (listState === 'empty')
|
|
80
|
+
return { state: 'absent', id, evidence: 'exact-empty' };
|
|
81
|
+
if (listState === 'conflict')
|
|
82
|
+
return { state: 'conflict', reason: 'exact container query returned a different ID' };
|
|
83
|
+
if (listState !== 'present')
|
|
84
|
+
return unknown(listState);
|
|
85
|
+
let inspected;
|
|
86
|
+
try {
|
|
87
|
+
inspected = runDockerProbe(engine, buildExactContainerInspectArgs(id), options);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return unknown('exact container inspection failed before producing a result');
|
|
91
|
+
}
|
|
92
|
+
if (inspected.status !== 0) {
|
|
93
|
+
return unknown(`exact container inspection exited with ${inspected.status ?? 'unknown status'}`);
|
|
94
|
+
}
|
|
95
|
+
return parseExactInspect(outputText(inspected.stdout).trim(), id);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=docker-exact-discovery.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PUBLIC_CLI_ROUTE_SELECTORS } from '../internal/cli-route-inventory.js';
|
|
1
2
|
const USAGE = `Usage: ai sandbox <command> [options]
|
|
2
3
|
|
|
3
4
|
Commands:
|
|
@@ -18,14 +19,15 @@ Commands:
|
|
|
18
19
|
rm <branch | TASK-id> | --unbound | --purge
|
|
19
20
|
Remove one sandbox; use a full TASK-id for task-bound
|
|
20
21
|
cleanup and a branch for branch-only cleanup. --unbound
|
|
21
|
-
removes completed task-bound and branch-only sandboxes
|
|
22
|
-
active, blocked, and archive tasks are protected.
|
|
22
|
+
removes completed task-bound and branch-only sandboxes
|
|
23
|
+
plus verified auxiliary state; active, blocked, and archive tasks are protected.
|
|
23
24
|
start [--recreate] <branch | TASK-id | N>
|
|
24
25
|
Verify or recover an existing sandbox container;
|
|
25
26
|
optionally replace only the container on failure
|
|
26
27
|
vm status|start|stop Manage the sandbox VM (macOS) or check the backend (Windows)
|
|
27
28
|
|
|
28
29
|
Run 'ai sandbox <command> --help' for details.`;
|
|
30
|
+
const SANDBOX_OPERATIONS = PUBLIC_CLI_ROUTE_SELECTORS.sandbox;
|
|
29
31
|
export async function runSandbox(args) {
|
|
30
32
|
const [subcommand, ...rest] = args;
|
|
31
33
|
if (!subcommand) {
|
|
@@ -37,6 +39,9 @@ export async function runSandbox(args) {
|
|
|
37
39
|
process.stdout.write(`${USAGE}\n`);
|
|
38
40
|
return;
|
|
39
41
|
}
|
|
42
|
+
if (!SANDBOX_OPERATIONS.includes(subcommand)) {
|
|
43
|
+
throw new Error(`Unknown sandbox command: ${subcommand}`);
|
|
44
|
+
}
|
|
40
45
|
switch (subcommand) {
|
|
41
46
|
case 'create': {
|
|
42
47
|
const { create } = await import('./commands/create.js');
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { prepareCompletedReentry, publishCompletedReentry, waitForCompletedReentry } from './control/completed-reentry.js';
|
|
1
2
|
import fs from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { spawn } from 'node:child_process';
|
|
@@ -17,7 +18,9 @@ import { declaredTmpfsSeedEntries, resolveTools, toolConfigDirCandidates } from
|
|
|
17
18
|
import { fetchSandboxRows, selectSandboxContainer, startSandboxContainer } from './commands/list-running.js';
|
|
18
19
|
import { getProcessIdentityState, getProcessStartTime, removePidFileIfMatches } from '../server/process-state.js';
|
|
19
20
|
import { acquireSandboxControlBrokerStartup, garbageCollectSandboxControlRoot, isSandboxControlRootQuiescing, readSandboxControlManifest } from './control/lifecycle.js';
|
|
20
|
-
import {
|
|
21
|
+
import { readSandboxControlStatus } from './control/state.js';
|
|
22
|
+
import { validateSandboxControlIdentity } from './control/identity-sentinel.js';
|
|
23
|
+
import { appendDiagnosticAudit as appendControlDiagnosticAudit } from './control/audit.js';
|
|
21
24
|
import { inspectSandboxControlContainer } from './control/container-identity.js';
|
|
22
25
|
import { SANDBOX_CONTROL_FUTURE_SKEW_MS, SANDBOX_CONTROL_STATUS_STALE_MS } from './control/protocol.js';
|
|
23
26
|
export function worktreeProbeForEngine(engine, probe = runProbe) {
|
|
@@ -60,6 +63,17 @@ export async function startSandboxControlBroker(repoRoot, manifestPath) {
|
|
|
60
63
|
const internalCli = path.resolve(directory, '..', '..', 'bin', `internal-cli${extension}`);
|
|
61
64
|
const manifest = readSandboxControlManifest(manifestPath);
|
|
62
65
|
const root = path.dirname(manifestPath);
|
|
66
|
+
const identity = validateSandboxControlIdentity({
|
|
67
|
+
publicStatusDir: manifest.publicStatusDir,
|
|
68
|
+
root,
|
|
69
|
+
mode: manifest.mode,
|
|
70
|
+
taskId: manifest.taskId,
|
|
71
|
+
generation: manifest.generation,
|
|
72
|
+
controlRootId: manifest.controlRootId
|
|
73
|
+
});
|
|
74
|
+
if (identity.state !== 'valid') {
|
|
75
|
+
throw new Error(`SANDBOX_CONTROL_IDENTITY_${identity.state.replaceAll('-', '_').toUpperCase()}`);
|
|
76
|
+
}
|
|
63
77
|
if (isSandboxControlRootQuiescing(root))
|
|
64
78
|
throw new Error('SANDBOX_CONTROL_QUIESCING');
|
|
65
79
|
const brokerPath = path.join(root, 'broker.json');
|
|
@@ -129,8 +143,8 @@ export async function startSandboxControlBroker(repoRoot, manifestPath) {
|
|
|
129
143
|
}
|
|
130
144
|
}
|
|
131
145
|
if (replacedBrokerRecord) {
|
|
132
|
-
|
|
133
|
-
|
|
146
|
+
appendControlDiagnosticAudit(manifest, 'broker-observed-crash');
|
|
147
|
+
appendControlDiagnosticAudit(manifest, 'broker-restart');
|
|
134
148
|
}
|
|
135
149
|
child = spawn(process.execPath, nodeEntryArgs(internalCli, ['sandbox-control', 'serve', '--manifest', manifestPath]), { cwd: repoRoot, detached: true, stdio: 'ignore' });
|
|
136
150
|
}
|
|
@@ -167,6 +181,17 @@ async function ensureSandboxControlBroker(params) {
|
|
|
167
181
|
if (!fs.existsSync(control.manifestPath))
|
|
168
182
|
return;
|
|
169
183
|
const validatedManifest = readSandboxControlManifest(control.manifestPath);
|
|
184
|
+
const identity = validateSandboxControlIdentity({
|
|
185
|
+
publicStatusDir: validatedManifest.publicStatusDir,
|
|
186
|
+
root: control.root,
|
|
187
|
+
mode: validatedManifest.mode,
|
|
188
|
+
taskId: validatedManifest.taskId,
|
|
189
|
+
generation: validatedManifest.generation,
|
|
190
|
+
controlRootId: validatedManifest.controlRootId
|
|
191
|
+
});
|
|
192
|
+
if (identity.state !== 'valid') {
|
|
193
|
+
throw new Error(`SANDBOX_CONTROL_IDENTITY_${identity.state.replaceAll('-', '_').toUpperCase()}`);
|
|
194
|
+
}
|
|
170
195
|
const containerObservation = await inspectSandboxControlContainer(validatedManifest);
|
|
171
196
|
if (containerObservation.state === 'unknown') {
|
|
172
197
|
throw new Error(`SANDBOX_CONTROL_CONTAINER_UNKNOWN: ${containerObservation.reason}`);
|
|
@@ -441,7 +466,7 @@ function recoveryTaskSources(repoRoot, taskId) {
|
|
|
441
466
|
}
|
|
442
467
|
return { mountPaths, accessiblePaths: [completedSource] };
|
|
443
468
|
}
|
|
444
|
-
function startCompletedSandboxContainer(params) {
|
|
469
|
+
export function startCompletedSandboxContainer(params) {
|
|
445
470
|
const taskSources = recoveryTaskSources(params.config.repoRoot, params.taskId);
|
|
446
471
|
const completedSource = taskSources.accessiblePaths[0];
|
|
447
472
|
const activeRoot = path.join(params.config.repoRoot, '.agents', 'workspace', 'active');
|
|
@@ -513,7 +538,7 @@ function expectedMounts(params) {
|
|
|
513
538
|
? {}
|
|
514
539
|
: {
|
|
515
540
|
runtimeDir: control.runtimeDir,
|
|
516
|
-
taskSources: taskSources.
|
|
541
|
+
taskSources: taskSources.accessiblePaths,
|
|
517
542
|
taskId: taskId
|
|
518
543
|
})
|
|
519
544
|
}).map((mount) => ({
|
|
@@ -879,7 +904,17 @@ export async function ensureSandboxReady(params) {
|
|
|
879
904
|
throw new Error('Explicit container recreation requested.');
|
|
880
905
|
}
|
|
881
906
|
if (!params.row.running) {
|
|
907
|
+
let completedReentry = null;
|
|
882
908
|
if (params.reentry === 'completed' && params.workspace?.mode === 'task-bound') {
|
|
909
|
+
const control = sandboxControlPaths({
|
|
910
|
+
base: params.config.controlBase, project: params.config.project,
|
|
911
|
+
container: params.row.name, identity: params.workspace
|
|
912
|
+
});
|
|
913
|
+
const manifest = readSandboxControlManifest(control.manifestPath);
|
|
914
|
+
if (manifest.taskId !== params.workspace.taskId || manifest.branch !== params.branch) {
|
|
915
|
+
throw new Error('SANDBOX_COMPLETED_REENTRY_EVIDENCE_INVALID');
|
|
916
|
+
}
|
|
917
|
+
completedReentry = { manifest, evidence: await prepareCompletedReentry(manifest) };
|
|
883
918
|
startCompletedSandboxContainer({
|
|
884
919
|
config: params.config,
|
|
885
920
|
engine: params.engine,
|
|
@@ -943,6 +978,15 @@ export async function ensureSandboxReady(params) {
|
|
|
943
978
|
if (final.findings.length > 0) {
|
|
944
979
|
throw new Error(describeFindings(final.findings));
|
|
945
980
|
}
|
|
981
|
+
if (completedReentry) {
|
|
982
|
+
const { manifest, evidence } = completedReentry;
|
|
983
|
+
const current = await prepareCompletedReentry(manifest);
|
|
984
|
+
if (JSON.stringify(current) !== JSON.stringify(evidence)) {
|
|
985
|
+
throw new Error('SANDBOX_COMPLETED_REENTRY_EVIDENCE_INVALID');
|
|
986
|
+
}
|
|
987
|
+
publishCompletedReentry(manifest, evidence);
|
|
988
|
+
await waitForCompletedReentry(manifest, evidence);
|
|
989
|
+
}
|
|
946
990
|
return { container: params.row.name, path: 'recovered', warnings };
|
|
947
991
|
}
|
|
948
992
|
const initial = assess({
|