@fitlab-ai/agent-infra 0.9.10 → 0.9.12
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 +19 -9
- package/README.zh-CN.md +19 -9
- package/bin/cli.ts +17 -4
- package/dist/bin/cli.js +19 -4
- package/dist/bin/internal-cli.js +55 -4
- package/dist/lib/agent-client.js +0 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
- package/dist/lib/agent-clients/adapters/opencode-sandbox.js +0 -4
- package/dist/lib/agent-clients/adapters/traecli.js +7 -8
- package/dist/lib/agent-clients/config.js +14 -99
- package/dist/lib/agent-clients/reconcile.js +1 -11
- package/dist/lib/agent-clients/schema.js +5 -4
- package/dist/lib/agent-clients/tokens.js +5 -15
- package/dist/lib/decide.js +14 -30
- package/dist/lib/defaults.json +8 -0
- package/dist/lib/git/workflow.js +43 -1
- package/dist/lib/init.js +3 -2
- package/dist/lib/internal/git-workflow.js +8 -1
- package/dist/lib/internal/platform-pr.js +8 -2
- package/dist/lib/internal/release-workflow.js +0 -1
- package/dist/lib/internal/task-delivery.js +59 -0
- package/dist/lib/internal/task-finalization.js +19 -9
- package/dist/lib/internal/task-ledger.js +8 -2
- package/dist/lib/internal/task-lifecycle.js +17 -93
- package/dist/lib/internal/task-orchestration.js +30 -216
- package/dist/lib/internal/task-validate.js +2 -1
- package/dist/lib/merge.js +205 -103
- package/dist/lib/platform/github-client.js +7 -1
- package/dist/lib/platform/pr-checks.js +8 -5
- package/dist/lib/platform/pr-summary.js +12 -8
- package/dist/lib/platform/pull-requests.js +393 -91
- package/dist/lib/platform/verification-required.js +13 -2
- package/dist/lib/platform/verification-sync.js +9 -4
- package/dist/lib/pr-review/evidence-grading.js +12 -4
- package/dist/lib/process-data/normalize.js +2 -9
- package/dist/lib/run/host.js +46 -16
- package/dist/lib/sandbox/agent-client-reconciler.js +4 -12
- package/dist/lib/sandbox/commands/create.js +3 -3
- package/dist/lib/sandbox/commands/enter.js +18 -4
- package/dist/lib/sandbox/config.js +8 -12
- package/dist/lib/sandbox/control/executor.js +131 -39
- package/dist/lib/sandbox/control/lifecycle.js +55 -24
- package/dist/lib/sandbox/control/server.js +18 -16
- package/dist/lib/sandbox/mounts.js +3 -2
- package/dist/lib/sandbox/recovery.js +123 -22
- package/dist/lib/sandbox/workspace-identity.js +14 -0
- package/dist/lib/sandbox/workspace-view.js +8 -9
- package/dist/lib/self-update.js +278 -0
- package/dist/lib/server/process-state.js +2 -2
- package/dist/lib/server/protocol.js +5 -5
- package/dist/lib/task/activity-log.js +4 -1
- package/dist/lib/task/artifact-lifecycle.js +6 -4
- package/dist/lib/task/codex-orchestration.js +1 -1
- package/dist/lib/task/command-options.js +1 -3
- package/dist/lib/task/commands/cat.js +0 -5
- package/dist/lib/task/commands/decisions.js +76 -92
- package/dist/lib/task/commands/files.js +6 -6
- package/dist/lib/task/commands/grep.js +25 -61
- package/dist/lib/task/commands/issue-body.js +6 -6
- package/dist/lib/task/commands/log.js +25 -10
- package/dist/lib/task/commands/show.js +5 -6
- package/dist/lib/task/commands/status.js +8 -8
- package/dist/lib/task/commit-intent.js +100 -0
- package/dist/lib/task/commit-operation.js +181 -91
- package/dist/lib/task/commit-policy.js +1 -1
- package/dist/lib/task/control-authority.js +431 -0
- package/dist/lib/task/create.js +39 -8
- package/dist/lib/task/current-contract.js +35 -0
- package/dist/lib/task/decision-details.js +218 -0
- package/dist/lib/task/decision-intents.js +5 -2
- package/dist/lib/task/delivery-target.js +97 -0
- package/dist/lib/task/delivery.js +153 -0
- package/dist/lib/task/events.js +11 -5
- package/dist/lib/task/human-override.js +5 -2
- package/dist/lib/task/index.js +19 -20
- package/dist/lib/task/ledger-intents.js +8 -9
- package/dist/lib/task/ledger.js +13 -6
- package/dist/lib/task/lifecycle.js +122 -9
- package/dist/lib/task/orchestration.js +105 -75
- package/dist/lib/task/pr-delivery-fact.js +182 -0
- package/dist/lib/task/review-artifacts.js +31 -12
- package/dist/lib/task/review-finalization.js +13 -4
- package/dist/lib/task/review-fingerprint.js +8 -0
- package/dist/lib/task/verification-engine.js +86 -39
- package/dist/lib/task/verification-review.js +2 -2
- package/dist/lib/task/workspace-snapshot.js +5 -11
- package/dist/lib/task/write.js +11 -1
- package/dist/lib/update.js +13 -35
- package/dist/lib/version.js +5 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +0 -1
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
- package/lib/agent-clients/adapters/opencode-sandbox.ts +0 -5
- package/lib/agent-clients/adapters/traecli.ts +7 -8
- package/lib/agent-clients/config.ts +14 -144
- package/lib/agent-clients/reconcile.ts +1 -12
- package/lib/agent-clients/schema.ts +5 -4
- package/lib/agent-clients/tokens.ts +5 -18
- package/lib/decide.ts +12 -22
- package/lib/defaults.json +8 -0
- package/lib/git/workflow.ts +38 -1
- package/lib/init.ts +5 -2
- package/lib/internal/git-workflow.ts +7 -1
- package/lib/internal/platform-pr.ts +8 -1
- package/lib/internal/release-workflow.ts +0 -1
- package/lib/internal/task-delivery.ts +53 -0
- package/lib/internal/task-finalization.ts +27 -13
- package/lib/internal/task-ledger.ts +8 -2
- package/lib/internal/task-lifecycle.ts +33 -76
- package/lib/internal/task-orchestration.ts +33 -190
- package/lib/internal/task-validate.ts +3 -2
- package/lib/merge.ts +236 -120
- package/lib/platform/github-client.ts +8 -1
- package/lib/platform/pr-checks.ts +7 -5
- package/lib/platform/pr-summary.ts +10 -7
- package/lib/platform/pull-requests.ts +425 -87
- package/lib/platform/verification-required.ts +12 -2
- package/lib/platform/verification-sync.ts +9 -4
- package/lib/pr-review/evidence-grading.ts +7 -4
- package/lib/process-data/normalize.ts +2 -8
- package/lib/run/host.ts +63 -14
- package/lib/sandbox/agent-client-reconciler.ts +5 -15
- package/lib/sandbox/commands/create.ts +4 -4
- package/lib/sandbox/commands/enter.ts +24 -4
- package/lib/sandbox/config.ts +9 -14
- package/lib/sandbox/control/container-identity.ts +2 -2
- package/lib/sandbox/control/executor.ts +148 -51
- package/lib/sandbox/control/lifecycle.ts +59 -31
- package/lib/sandbox/control/protocol.ts +1 -3
- package/lib/sandbox/control/server.ts +15 -12
- package/lib/sandbox/control/state.ts +7 -7
- package/lib/sandbox/mounts.ts +4 -3
- package/lib/sandbox/recovery.ts +162 -34
- package/lib/sandbox/tools.ts +1 -1
- package/lib/sandbox/workspace-identity.ts +28 -0
- package/lib/sandbox/workspace-view.ts +14 -10
- package/lib/self-update.ts +341 -0
- package/lib/server/process-state.ts +2 -2
- package/lib/server/protocol.ts +5 -5
- package/lib/task/activity-log.ts +6 -1
- package/lib/task/artifact-lifecycle.ts +7 -5
- package/lib/task/codex-orchestration.ts +2 -1
- package/lib/task/command-options.ts +1 -2
- package/lib/task/commands/cat.ts +0 -4
- package/lib/task/commands/decisions.ts +80 -75
- package/lib/task/commands/files.ts +6 -6
- package/lib/task/commands/grep.ts +23 -51
- package/lib/task/commands/issue-body.ts +6 -6
- package/lib/task/commands/log.ts +22 -10
- package/lib/task/commands/show.ts +5 -6
- package/lib/task/commands/status.ts +8 -8
- package/lib/task/commit-intent.ts +137 -0
- package/lib/task/commit-operation.ts +161 -79
- package/lib/task/commit-policy.ts +1 -2
- package/lib/task/control-authority.ts +563 -0
- package/lib/task/create.ts +40 -10
- package/lib/task/current-contract.ts +49 -0
- package/lib/task/decision-details.ts +280 -0
- package/lib/task/decision-intents.ts +7 -2
- package/lib/task/delivery-target.ts +130 -0
- package/lib/task/delivery.ts +160 -0
- package/lib/task/events.ts +10 -5
- package/lib/task/human-override.ts +5 -2
- package/lib/task/index.ts +19 -20
- package/lib/task/ledger-intents.ts +6 -8
- package/lib/task/ledger.ts +17 -7
- package/lib/task/lifecycle.ts +113 -4
- package/lib/task/orchestration.ts +102 -80
- package/lib/task/pr-delivery-fact.ts +254 -0
- package/lib/task/review-artifacts.ts +53 -15
- package/lib/task/review-finalization.ts +21 -5
- package/lib/task/review-fingerprint.ts +10 -0
- package/lib/task/verification-engine.ts +78 -46
- package/lib/task/verification-review.ts +3 -1
- package/lib/task/workspace-snapshot.ts +4 -13
- package/lib/task/write.ts +20 -1
- package/lib/update.ts +14 -38
- package/lib/version.ts +6 -1
- package/package.json +1 -1
- package/templates/.agents/README.en.md +5 -3
- package/templates/.agents/README.zh-CN.md +5 -3
- package/templates/.agents/rules/README.en.md +4 -2
- package/templates/.agents/rules/README.zh-CN.md +4 -2
- package/templates/.agents/rules/compatibility-policy.en.md +5 -4
- package/templates/.agents/rules/compatibility-policy.zh-CN.md +5 -4
- package/templates/.agents/rules/create-issue.en.md +11 -2
- package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
- package/templates/.agents/rules/human-decision-context.en.md +9 -7
- package/templates/.agents/rules/human-decision-context.zh-CN.md +9 -7
- package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +1 -1
- package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +1 -1
- package/templates/.agents/rules/issue-pr-commands.en.md +5 -18
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +26 -5
- package/templates/.agents/rules/issue-sync.zh-CN.md +62 -5
- package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
- package/templates/.agents/rules/local-artifact-repair.en.md +46 -0
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +46 -0
- package/templates/.agents/rules/milestone-inference.en.md +12 -2
- package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
- package/templates/.agents/rules/next-step-output.en.md +3 -3
- package/templates/.agents/rules/next-step-output.zh-CN.md +3 -3
- package/templates/.agents/rules/no-mid-flow-questions.en.md +1 -1
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +1 -1
- package/templates/.agents/rules/pr-sync.en.md +23 -14
- package/templates/.agents/rules/pr-sync.zh-CN.md +23 -2
- package/templates/.agents/rules/release-commands.en.md +42 -3
- package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
- package/templates/.agents/rules/review-handshake.en.md +1 -1
- package/templates/.agents/rules/review-handshake.zh-CN.md +1 -1
- package/templates/.agents/rules/security-alerts.en.md +17 -2
- package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
- package/templates/.agents/rules/sync-content-generation.en.md +8 -0
- package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
- package/templates/.agents/rules/task-management.en.md +2 -3
- package/templates/.agents/rules/task-management.zh-CN.md +2 -3
- package/templates/.agents/scripts/security-alerts.github.sh +151 -0
- package/templates/.agents/scripts/security-alerts.sh +31 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +4 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.en.md +3 -3
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +3 -3
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/code-task/SKILL.en.md +8 -5
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +9 -6
- package/templates/.agents/skills/commit/SKILL.en.md +30 -10
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +6 -7
- package/templates/.agents/skills/commit/config/verify.json +1 -1
- package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
- package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +7 -6
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +7 -6
- 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/summary-update.en.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +13 -13
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +13 -13
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.en.md +9 -11
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +9 -11
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +9 -4
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +9 -4
- package/templates/.agents/skills/create-pr/scripts/change-report.mjs +203 -0
- package/templates/.agents/skills/create-release-note/SKILL.en.md +5 -6
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +5 -6
- package/templates/.agents/skills/create-task/SKILL.en.md +2 -1
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +2 -1
- 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/import-issue/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
- package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
- package/templates/.agents/skills/plan-task/SKILL.en.md +4 -3
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/restore-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +8 -5
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +8 -5
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +11 -8
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +11 -8
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.en.md +2 -1
- package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +2 -1
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
- package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
- package/templates/.agents/skills/review-plan/SKILL.en.md +8 -5
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +8 -5
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -0
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -0
- package/templates/.agents/skills/run-task/SKILL.en.md +5 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +2 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +144 -109
- package/templates/.agents/skills/watch-pr/SKILL.en.md +5 -5
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +5 -5
- package/templates/.agents/templates/task.en.md +6 -2
- package/templates/.agents/templates/task.zh-CN.md +6 -2
- package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
- package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/feature-development.en.yaml +9 -8
- package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/refactoring.en.yaml +9 -8
- package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
- package/templates/.claude/commands/analyze-task.en.md +1 -1
- package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
- package/templates/.claude/commands/block-task.en.md +1 -1
- package/templates/.claude/commands/block-task.zh-CN.md +1 -1
- package/templates/.claude/commands/cancel-task.en.md +1 -1
- package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
- package/templates/.claude/commands/check-task.en.md +1 -1
- package/templates/.claude/commands/check-task.zh-CN.md +1 -1
- package/templates/.claude/commands/code-task.en.md +1 -1
- package/templates/.claude/commands/code-task.zh-CN.md +1 -1
- package/templates/.claude/commands/commit.en.md +1 -1
- package/templates/.claude/commands/commit.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-task.en.md +1 -1
- package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
- package/templates/.claude/commands/create-pr.en.md +1 -1
- package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
- package/templates/.claude/commands/plan-task.en.md +1 -1
- package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
- package/templates/.claude/commands/review-analysis.en.md +1 -1
- package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
- package/templates/.claude/commands/review-code.en.md +1 -1
- package/templates/.claude/commands/review-code.zh-CN.md +1 -1
- package/templates/.claude/commands/review-plan.en.md +1 -1
- package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
- package/templates/.claude/commands/run-manual-validation.en.md +1 -1
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/run-task.en.md +1 -1
- package/templates/.claude/commands/run-task.zh-CN.md +1 -1
- package/templates/.claude/commands/watch-pr.en.md +1 -1
- package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
- package/templates/{.trae/skills → .traecli/commands}/update-agent-infra.en.md +0 -1
- package/templates/{.trae/skills → .traecli/commands}/update-agent-infra.zh-CN.md +0 -1
- package/dist/lib/builtin-tuis.js +0 -40
- package/lib/builtin-tuis.ts +0 -56
- package/templates/.agents/rules/create-issue.github.en.md +0 -14
- package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
- package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
- package/templates/.agents/rules/issue-sync.github.en.md +0 -40
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
- package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
- package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
- package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
- package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
- package/templates/.agents/rules/pr-sync.github.en.md +0 -43
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
- package/templates/.agents/rules/release-commands.github.en.md +0 -38
- package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -38
- package/templates/.agents/rules/security-alerts.github.en.md +0 -43
- package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
|
@@ -414,8 +414,6 @@ function readProcessingSnapshot(root) {
|
|
|
414
414
|
export function captureSandboxControlCutoverSnapshot(root) {
|
|
415
415
|
const resolvedRoot = path.resolve(root);
|
|
416
416
|
const manifestPath = path.join(resolvedRoot, 'manifest.json');
|
|
417
|
-
if (fs.existsSync(manifestPath))
|
|
418
|
-
readSandboxControlManifestForTransition(manifestPath);
|
|
419
417
|
return {
|
|
420
418
|
root: resolvedRoot,
|
|
421
419
|
manifestRaw: readOptionalRaw(manifestPath),
|
|
@@ -430,7 +428,7 @@ export function assertSandboxControlCutoverSnapshot(snapshot) {
|
|
|
430
428
|
throw new Error('SANDBOX_CONTROL_OWNER_TRANSITION');
|
|
431
429
|
}
|
|
432
430
|
}
|
|
433
|
-
function readSandboxControlManifestValue(manifestPath
|
|
431
|
+
function readSandboxControlManifestValue(manifestPath) {
|
|
434
432
|
if (!regularFile(manifestPath))
|
|
435
433
|
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
436
434
|
let manifest;
|
|
@@ -445,25 +443,35 @@ function readSandboxControlManifestValue(manifestPath, allowLegacy) {
|
|
|
445
443
|
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
446
444
|
}
|
|
447
445
|
const candidate = manifest;
|
|
448
|
-
|
|
449
|
-
|
|
446
|
+
const expectedKeys = [
|
|
447
|
+
'branch', 'channelDir', 'container', 'containerIdentity', 'engine', 'generation',
|
|
448
|
+
'mode', 'processingDir', 'project', 'publicStatusDir', 'repoRoot', 'runtimeDir',
|
|
449
|
+
'taskId', 'token', 'worktreeRoot'
|
|
450
|
+
];
|
|
451
|
+
if (Object.keys(manifest).sort().join(',') !== expectedKeys.sort().join(',')) {
|
|
452
|
+
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
450
453
|
}
|
|
451
454
|
if (typeof candidate.containerIdentity !== 'object' || candidate.containerIdentity === null
|
|
452
455
|
|| Array.isArray(candidate.containerIdentity))
|
|
453
456
|
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
454
457
|
const containerIdentity = candidate.containerIdentity;
|
|
455
|
-
if (
|
|
458
|
+
if (Object.keys(containerIdentity).sort().join(',') !== 'id,labels'
|
|
459
|
+
|| typeof candidate.engine !== 'string' || candidate.engine.length === 0
|
|
456
460
|
|| typeof candidate.repoRoot !== 'string' || typeof candidate.worktreeRoot !== 'string'
|
|
457
461
|
|| typeof candidate.project !== 'string' || typeof candidate.container !== 'string'
|
|
458
462
|
|| typeof containerIdentity.id !== 'string' || containerIdentity.id.length === 0
|
|
459
463
|
|| typeof containerIdentity.labels !== 'object' || containerIdentity.labels === null
|
|
460
464
|
|| Array.isArray(containerIdentity.labels)
|
|
461
465
|
|| Object.values(containerIdentity.labels).some((value) => typeof value !== 'string')
|
|
462
|
-
|| typeof candidate.branch !== 'string'
|
|
466
|
+
|| typeof candidate.branch !== 'string'
|
|
467
|
+
|| (candidate.mode !== 'task-bound' && candidate.mode !== 'branch-only')
|
|
463
468
|
|| (candidate.taskId !== null && typeof candidate.taskId !== 'string')
|
|
464
469
|
|| typeof candidate.channelDir !== 'string' || typeof candidate.publicStatusDir !== 'string'
|
|
465
|
-
|| typeof candidate.processingDir !== 'string' || typeof candidate.
|
|
466
|
-
|| typeof candidate.
|
|
470
|
+
|| typeof candidate.processingDir !== 'string' || typeof candidate.runtimeDir !== 'string'
|
|
471
|
+
|| typeof candidate.token !== 'string'
|
|
472
|
+
|| typeof candidate.generation !== 'string'
|
|
473
|
+
|| (candidate.mode === 'task-bound' && (typeof candidate.taskId !== 'string' || candidate.taskId.length === 0))
|
|
474
|
+
|| (candidate.mode === 'branch-only' && candidate.taskId !== null))
|
|
467
475
|
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
468
476
|
const root = path.dirname(path.resolve(manifestPath));
|
|
469
477
|
if (path.resolve(candidate.channelDir) !== path.join(root, 'channel')
|
|
@@ -471,22 +479,33 @@ function readSandboxControlManifestValue(manifestPath, allowLegacy) {
|
|
|
471
479
|
|| path.resolve(candidate.processingDir) !== path.join(root, 'processing')) {
|
|
472
480
|
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
473
481
|
}
|
|
474
|
-
if (candidate.
|
|
475
|
-
if (!allowLegacy) {
|
|
476
|
-
throw new Error('SANDBOX_CONTROL_MANIFEST_VERSION_INVALID: expected version 5; container-only recreation is required');
|
|
477
|
-
}
|
|
478
|
-
return candidate;
|
|
479
|
-
}
|
|
480
|
-
if (typeof candidate.runtimeDir !== 'string' || path.resolve(candidate.runtimeDir) !== path.join(root, 'runtime')) {
|
|
482
|
+
if (path.resolve(candidate.runtimeDir) !== path.join(root, 'runtime')) {
|
|
481
483
|
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
482
484
|
}
|
|
483
|
-
|
|
485
|
+
const normalized = {
|
|
486
|
+
engine: candidate.engine,
|
|
487
|
+
repoRoot: candidate.repoRoot,
|
|
488
|
+
worktreeRoot: candidate.worktreeRoot,
|
|
489
|
+
project: candidate.project,
|
|
490
|
+
container: candidate.container,
|
|
491
|
+
containerIdentity: {
|
|
492
|
+
id: containerIdentity.id,
|
|
493
|
+
labels: { ...containerIdentity.labels }
|
|
494
|
+
},
|
|
495
|
+
branch: candidate.branch,
|
|
496
|
+
mode: candidate.mode,
|
|
497
|
+
taskId: candidate.taskId,
|
|
498
|
+
token: candidate.token,
|
|
499
|
+
generation: candidate.generation,
|
|
500
|
+
channelDir: candidate.channelDir,
|
|
501
|
+
publicStatusDir: candidate.publicStatusDir,
|
|
502
|
+
processingDir: candidate.processingDir,
|
|
503
|
+
runtimeDir: candidate.runtimeDir
|
|
504
|
+
};
|
|
505
|
+
return normalized;
|
|
484
506
|
}
|
|
485
507
|
export function readSandboxControlManifest(manifestPath) {
|
|
486
|
-
return readSandboxControlManifestValue(manifestPath
|
|
487
|
-
}
|
|
488
|
-
export function readSandboxControlManifestForTransition(manifestPath) {
|
|
489
|
-
return readSandboxControlManifestValue(manifestPath, true);
|
|
508
|
+
return readSandboxControlManifestValue(manifestPath);
|
|
490
509
|
}
|
|
491
510
|
function readBrokerOwner(filePath) {
|
|
492
511
|
if (!fs.existsSync(filePath))
|
|
@@ -507,6 +526,18 @@ function readBrokerOwner(filePath) {
|
|
|
507
526
|
throw new Error('SANDBOX_CONTROL_OWNER_MISMATCH');
|
|
508
527
|
return owner;
|
|
509
528
|
}
|
|
529
|
+
export function assertSandboxControlBrokerOwner(manifest, options = {}) {
|
|
530
|
+
const root = path.dirname(path.resolve(manifest.publicStatusDir));
|
|
531
|
+
const owner = readBrokerOwner(path.join(root, 'broker.json'));
|
|
532
|
+
if (!owner)
|
|
533
|
+
throw new Error('SANDBOX_CONTROL_OWNER_EVIDENCE_MISSING');
|
|
534
|
+
if (owner.token !== manifest.token || owner.generation !== manifest.generation) {
|
|
535
|
+
throw new Error('SANDBOX_CONTROL_OWNER_MISMATCH');
|
|
536
|
+
}
|
|
537
|
+
if (!ownerLive(owner, options.identityProbe))
|
|
538
|
+
throw new Error('SANDBOX_CONTROL_OWNER_LOST');
|
|
539
|
+
return owner;
|
|
540
|
+
}
|
|
510
541
|
function readStatusOwner(filePath) {
|
|
511
542
|
if (!fs.existsSync(filePath))
|
|
512
543
|
return null;
|
|
@@ -641,7 +672,7 @@ export async function quiesceSandboxControlRoot(root, options = {}) {
|
|
|
641
672
|
markSandboxControlRootQuiescing(resolvedRoot);
|
|
642
673
|
await waitForStartupTransition(resolvedRoot, Math.max(0, forceAt - Date.now()), identityProbe);
|
|
643
674
|
const manifestPath = path.join(resolvedRoot, 'manifest.json');
|
|
644
|
-
const manifest = fs.existsSync(manifestPath) ?
|
|
675
|
+
const manifest = fs.existsSync(manifestPath) ? readSandboxControlManifest(manifestPath) : null;
|
|
645
676
|
const broker = readBrokerOwner(path.join(resolvedRoot, 'broker.json'));
|
|
646
677
|
const status = readStatusOwner(path.join(resolvedRoot, 'public', 'status.json'));
|
|
647
678
|
const statusOwner = status ? status.broker : null;
|
|
@@ -730,7 +761,7 @@ export async function removeSandboxControlRoot(root, options) {
|
|
|
730
761
|
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
731
762
|
throw new Error('SANDBOX_CONTROL_CHANNEL_INVALID');
|
|
732
763
|
const manifestPath = path.join(resolvedRoot, 'manifest.json');
|
|
733
|
-
const manifest =
|
|
764
|
+
const manifest = readSandboxControlManifest(manifestPath);
|
|
734
765
|
const inspectContainer = options.inspectContainer
|
|
735
766
|
?? ((timeoutMs) => inspectSandboxControlContainer(manifest, { timeoutMs }));
|
|
736
767
|
const timeoutMs = options.timeoutMs ?? options.timing?.quiesceDeadlineMs ?? DEFAULT_QUIESCE_TIMEOUT_MS;
|
|
@@ -792,7 +823,7 @@ export async function removeSandboxControlRoot(root, options) {
|
|
|
792
823
|
: 'SANDBOX_CONTROL_CONTAINER_STILL_EXISTS');
|
|
793
824
|
}
|
|
794
825
|
}
|
|
795
|
-
const currentManifest =
|
|
826
|
+
const currentManifest = readSandboxControlManifest(manifestPath);
|
|
796
827
|
if (currentManifest.token !== manifest.token || currentManifest.generation !== manifest.generation
|
|
797
828
|
|| !isSandboxControlRootQuiescing(resolvedRoot)) {
|
|
798
829
|
throw new Error('SANDBOX_CONTROL_OWNER_TRANSITION');
|
|
@@ -197,6 +197,7 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
|
|
|
197
197
|
if (!recoverProcessing(manifest, brokerOwns))
|
|
198
198
|
return;
|
|
199
199
|
while (!signal.aborted) {
|
|
200
|
+
let settledExecution = null;
|
|
200
201
|
if (!brokerOwns())
|
|
201
202
|
break;
|
|
202
203
|
let current;
|
|
@@ -255,22 +256,7 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
|
|
|
255
256
|
if (active?.settled) {
|
|
256
257
|
if (!brokerOwns())
|
|
257
258
|
break;
|
|
258
|
-
|
|
259
|
-
if (!brokerOwns())
|
|
260
|
-
break;
|
|
261
|
-
writeResponse(manifest, {
|
|
262
|
-
version: 2, id: active.request.id, phase: 'completed', exitCode: active.result.exitCode,
|
|
263
|
-
stdout: active.result.stdout, stderr: active.result.stderr, error: null
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
if (!brokerOwns())
|
|
268
|
-
break;
|
|
269
|
-
writeResponse(manifest, unknown(active.request.id));
|
|
270
|
-
}
|
|
271
|
-
if (!brokerOwns())
|
|
272
|
-
break;
|
|
273
|
-
fs.rmSync(path.join(manifest.processingDir, active.request.id), { recursive: true, force: true });
|
|
259
|
+
settledExecution = active;
|
|
274
260
|
active = null;
|
|
275
261
|
}
|
|
276
262
|
let reasonCode = null;
|
|
@@ -313,6 +299,22 @@ export async function serveSandboxControl(manifestPath, signal = new AbortContro
|
|
|
313
299
|
appendSandboxControlAudit(manifest, 'broker-state', { state, reasonCode, requestId: active?.request.id ?? null });
|
|
314
300
|
lastState = stateKey;
|
|
315
301
|
}
|
|
302
|
+
if (settledExecution) {
|
|
303
|
+
if (!brokerOwns())
|
|
304
|
+
break;
|
|
305
|
+
if (settledExecution.result) {
|
|
306
|
+
writeResponse(manifest, {
|
|
307
|
+
version: 2, id: settledExecution.request.id, phase: 'completed', exitCode: settledExecution.result.exitCode,
|
|
308
|
+
stdout: settledExecution.result.stdout, stderr: settledExecution.result.stderr, error: null
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
writeResponse(manifest, unknown(settledExecution.request.id));
|
|
313
|
+
}
|
|
314
|
+
if (!brokerOwns())
|
|
315
|
+
break;
|
|
316
|
+
fs.rmSync(path.join(manifest.processingDir, settledExecution.request.id), { recursive: true, force: true });
|
|
317
|
+
}
|
|
316
318
|
let retiring = false;
|
|
317
319
|
for (const name of fs.readdirSync(requestsDir).sort()) {
|
|
318
320
|
if (!/^[a-f0-9-]{16,64}\.json$/.test(name))
|
|
@@ -2,7 +2,8 @@ import path from 'node:path';
|
|
|
2
2
|
import { shareBranchDir, shareCommonDir, shellConfigDirCandidates, worktreeDirCandidates } from './constants.js';
|
|
3
3
|
import { sandboxWorkspaceViewStatePaths } from './workspace-view.js';
|
|
4
4
|
export function sandboxCoreBindMounts(config, branch, overrides) {
|
|
5
|
-
const
|
|
5
|
+
const taskSources = overrides.taskSources ?? [];
|
|
6
|
+
const taskBound = Boolean(taskSources.length > 0 && overrides.taskId);
|
|
6
7
|
const workspaceMounts = sandboxWorkspaceViewStatePaths(overrides.workspaceViewRoot).map(({ state, hostPath }) => taskBound && state === 'active'
|
|
7
8
|
? {
|
|
8
9
|
hostPaths: [path.join(hostPath, '.short-ids.json')],
|
|
@@ -26,7 +27,7 @@ export function sandboxCoreBindMounts(config, branch, overrides) {
|
|
|
26
27
|
];
|
|
27
28
|
if (taskBound) {
|
|
28
29
|
mounts.push({
|
|
29
|
-
hostPaths:
|
|
30
|
+
hostPaths: taskSources,
|
|
30
31
|
containerPath: path.posix.join('/workspace/.agents/workspace/active', overrides.taskId),
|
|
31
32
|
readOnly: false
|
|
32
33
|
});
|
|
@@ -9,6 +9,7 @@ import { createSandboxCapabilityPlan } from './agent-client-reconciler.js';
|
|
|
9
9
|
import { toEnginePath } from './engines/wsl2-paths.js';
|
|
10
10
|
import { sandboxCoreBindMounts } from './mounts.js';
|
|
11
11
|
import { assertSandboxTaskSource, sandboxControlPaths, sandboxWorkspaceViewPaths } from './workspace-view.js';
|
|
12
|
+
import { resolveTaskWorkspace } from './task-resolver.js';
|
|
12
13
|
import { parseSandboxWorkspaceIdentity, sameSandboxWorkspaceIdentity } from './workspace-identity.js';
|
|
13
14
|
import { inspectWorktree } from './worktree-safety.js';
|
|
14
15
|
import { commandForEngine, runEngine, runOkEngine, runProbe, runVerboseEngine } from './shell.js';
|
|
@@ -407,6 +408,66 @@ function sourceCandidates(engine, hostPath) {
|
|
|
407
408
|
}
|
|
408
409
|
return [...new Set(candidates.map((candidate) => normalizeMountSource(engine, candidate)))];
|
|
409
410
|
}
|
|
411
|
+
function recoveryTaskSources(repoRoot, taskId) {
|
|
412
|
+
const activePath = path.join(repoRoot, '.agents', 'workspace', 'active', taskId);
|
|
413
|
+
const completedPath = path.join(repoRoot, '.agents', 'workspace', 'completed', taskId);
|
|
414
|
+
if (fs.existsSync(activePath) && !fs.existsSync(completedPath)) {
|
|
415
|
+
const source = assertSandboxTaskSource(repoRoot, taskId);
|
|
416
|
+
return { mountPaths: [source], accessiblePaths: [source] };
|
|
417
|
+
}
|
|
418
|
+
const task = resolveTaskWorkspace(taskId, repoRoot);
|
|
419
|
+
if (task.state === 'active') {
|
|
420
|
+
const source = assertSandboxTaskSource(repoRoot, taskId);
|
|
421
|
+
return { mountPaths: [source], accessiblePaths: [source] };
|
|
422
|
+
}
|
|
423
|
+
if (task.state !== 'completed') {
|
|
424
|
+
throw new Error(`SANDBOX_TASK_SOURCE_STATE_UNSUPPORTED: task ${taskId} is ${task.state}`);
|
|
425
|
+
}
|
|
426
|
+
const completedRoot = fs.realpathSync.native(path.join(repoRoot, '.agents', 'workspace', 'completed'));
|
|
427
|
+
const completedSource = fs.realpathSync.native(path.dirname(task.taskMd));
|
|
428
|
+
if (path.dirname(completedSource) !== completedRoot) {
|
|
429
|
+
throw new Error(`SANDBOX_TASK_SOURCE_INVALID: ${completedSource} is not under completed workspace`);
|
|
430
|
+
}
|
|
431
|
+
const historicalActivePath = path.join(repoRoot, '.agents', 'workspace', 'active', taskId);
|
|
432
|
+
const mountPaths = [completedSource, historicalActivePath];
|
|
433
|
+
if (fs.existsSync(historicalActivePath)) {
|
|
434
|
+
try {
|
|
435
|
+
mountPaths[1] = fs.realpathSync.native(historicalActivePath);
|
|
436
|
+
}
|
|
437
|
+
catch {
|
|
438
|
+
// Keep the exact historical path as a candidate; the current completed
|
|
439
|
+
// source remains the only source that must still be accessible.
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return { mountPaths, accessiblePaths: [completedSource] };
|
|
443
|
+
}
|
|
444
|
+
function startCompletedSandboxContainer(params) {
|
|
445
|
+
const taskSources = recoveryTaskSources(params.config.repoRoot, params.taskId);
|
|
446
|
+
const completedSource = taskSources.accessiblePaths[0];
|
|
447
|
+
const activeRoot = path.join(params.config.repoRoot, '.agents', 'workspace', 'active');
|
|
448
|
+
const historicalSource = path.join(activeRoot, params.taskId);
|
|
449
|
+
fs.mkdirSync(activeRoot, { recursive: true });
|
|
450
|
+
try {
|
|
451
|
+
fs.lstatSync(historicalSource);
|
|
452
|
+
throw new Error(`SANDBOX_COMPLETED_SOURCE_CONFLICT: historical task source already exists at ${historicalSource}`);
|
|
453
|
+
}
|
|
454
|
+
catch (error) {
|
|
455
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
|
|
456
|
+
throw error;
|
|
457
|
+
}
|
|
458
|
+
fs.symlinkSync(completedSource, historicalSource, process.platform === 'win32' ? 'junction' : 'dir');
|
|
459
|
+
try {
|
|
460
|
+
params.start(params.engine, params.container);
|
|
461
|
+
}
|
|
462
|
+
finally {
|
|
463
|
+
const temporarySource = fs.lstatSync(historicalSource);
|
|
464
|
+
const resolvedSource = fs.realpathSync.native(historicalSource);
|
|
465
|
+
if (!temporarySource.isSymbolicLink() || resolvedSource !== completedSource) {
|
|
466
|
+
throw new Error(`SANDBOX_COMPLETED_SOURCE_CHANGED: refusing to remove unexpected path at ${historicalSource}`);
|
|
467
|
+
}
|
|
468
|
+
fs.unlinkSync(historicalSource);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
410
471
|
function sameHostSource(left, right) {
|
|
411
472
|
try {
|
|
412
473
|
const leftStat = fs.statSync(left, { bigint: true });
|
|
@@ -440,21 +501,29 @@ function expectedMounts(params) {
|
|
|
440
501
|
container: params.container,
|
|
441
502
|
identity: params.workspace
|
|
442
503
|
});
|
|
504
|
+
const taskSources = params.workspace.mode === 'task-bound'
|
|
505
|
+
? recoveryTaskSources(config.repoRoot, params.workspace.taskId)
|
|
506
|
+
: null;
|
|
507
|
+
const taskId = params.workspace.mode === 'task-bound' ? params.workspace.taskId : null;
|
|
443
508
|
const core = sandboxCoreBindMounts(config, branch, {
|
|
444
509
|
workspaceViewRoot: view.root,
|
|
445
510
|
controlDir: control.channelDir,
|
|
446
511
|
controlStatusDir: control.statusDir,
|
|
447
|
-
...(
|
|
448
|
-
? {
|
|
512
|
+
...(taskSources === null
|
|
513
|
+
? {}
|
|
514
|
+
: {
|
|
449
515
|
runtimeDir: control.runtimeDir,
|
|
450
|
-
|
|
451
|
-
taskId:
|
|
452
|
-
}
|
|
453
|
-
: {})
|
|
516
|
+
taskSources: taskSources.mountPaths,
|
|
517
|
+
taskId: taskId
|
|
518
|
+
})
|
|
454
519
|
}).map((mount) => ({
|
|
455
520
|
path: mount.containerPath,
|
|
456
521
|
expectedType: 'bind',
|
|
457
522
|
hostPaths: mount.hostPaths,
|
|
523
|
+
...(taskSources !== null && taskId !== null
|
|
524
|
+
&& mount.containerPath === `/workspace/.agents/workspace/active/${taskId}`
|
|
525
|
+
? { sourceAccessiblePaths: taskSources.accessiblePaths }
|
|
526
|
+
: {}),
|
|
458
527
|
expectedRW: !mount.readOnly
|
|
459
528
|
}));
|
|
460
529
|
const live = tools.flatMap((tool) => (tool.hostLiveMounts ?? []).flatMap(({ hostPath, containerSubpath }) => {
|
|
@@ -469,9 +538,7 @@ function expectedMounts(params) {
|
|
|
469
538
|
}];
|
|
470
539
|
}));
|
|
471
540
|
const persistentTools = tools
|
|
472
|
-
.filter((tool) => !tool.tmpfs
|
|
473
|
-
&& (config.agentClientSource === 'canonical'
|
|
474
|
-
|| actualMounts.has(tool.containerMount)))
|
|
541
|
+
.filter((tool) => !tool.tmpfs)
|
|
475
542
|
.map((tool) => ({
|
|
476
543
|
path: tool.containerMount,
|
|
477
544
|
expectedType: 'bind',
|
|
@@ -577,13 +644,10 @@ export function collectSandboxRecoverySnapshot(params) {
|
|
|
577
644
|
taskId: sandboxTaskIdLabel(params.config)
|
|
578
645
|
});
|
|
579
646
|
const selectedToolIds = new Set(tools.map((tool) => tool.id));
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
.map((tool) => tool.containerMount)
|
|
585
|
-
.filter((mountPath) => mountsByDestination.has(mountPath))
|
|
586
|
-
: [];
|
|
647
|
+
const unexpectedCapabilityMounts = capabilityPlan.cleanupInventory
|
|
648
|
+
.filter((tool) => isAgentClientId(tool.id) && !selectedToolIds.has(tool.id))
|
|
649
|
+
.map((tool) => tool.containerMount)
|
|
650
|
+
.filter((mountPath) => mountsByDestination.has(mountPath));
|
|
587
651
|
const mountSnapshots = expectedMounts({
|
|
588
652
|
config: params.config,
|
|
589
653
|
branch: params.branch,
|
|
@@ -616,7 +680,7 @@ export function collectSandboxRecoverySnapshot(params) {
|
|
|
616
680
|
sourceAccessible: expected.expectedType === 'tmpfs'
|
|
617
681
|
? true
|
|
618
682
|
: matchedHostPath !== undefined
|
|
619
|
-
&& hostSourceAccessible(
|
|
683
|
+
&& (expected.sourceAccessiblePaths ?? [matchedHostPath]).some((hostPath) => hostSourceAccessible(hostPath, expected.expectedRW))
|
|
620
684
|
};
|
|
621
685
|
});
|
|
622
686
|
return {
|
|
@@ -636,9 +700,7 @@ export function collectSandboxRecoverySnapshot(params) {
|
|
|
636
700
|
identityOk: typeof inspection.Id === 'string' && inspection.Id.length > 0
|
|
637
701
|
&& branchLabel === params.branch
|
|
638
702
|
&& sameSandboxWorkspaceIdentity(containerWorkspace, workspace),
|
|
639
|
-
runtimeCapabilityOk:
|
|
640
|
-
? labels[sandboxRuntimeCapabilityLabel(params.config)] === capabilityPlan.runtimeSignature
|
|
641
|
-
: undefined,
|
|
703
|
+
runtimeCapabilityOk: labels[sandboxRuntimeCapabilityLabel(params.config)] === capabilityPlan.runtimeSignature,
|
|
642
704
|
unexpectedCapabilityMounts,
|
|
643
705
|
mounts: mountSnapshots,
|
|
644
706
|
tmpfs,
|
|
@@ -813,11 +875,22 @@ export async function ensureSandboxReady(params) {
|
|
|
813
875
|
workspace: params.workspace ?? { mode: 'branch-only' }
|
|
814
876
|
});
|
|
815
877
|
}
|
|
816
|
-
if (params.forceRecreate) {
|
|
878
|
+
if (params.forceRecreate || (params.reentry === 'completed' && params.allowRecreate)) {
|
|
817
879
|
throw new Error('Explicit container recreation requested.');
|
|
818
880
|
}
|
|
819
881
|
if (!params.row.running) {
|
|
820
|
-
|
|
882
|
+
if (params.reentry === 'completed' && params.workspace?.mode === 'task-bound') {
|
|
883
|
+
startCompletedSandboxContainer({
|
|
884
|
+
config: params.config,
|
|
885
|
+
engine: params.engine,
|
|
886
|
+
container: params.row.name,
|
|
887
|
+
taskId: params.workspace.taskId,
|
|
888
|
+
start: startFn
|
|
889
|
+
});
|
|
890
|
+
}
|
|
891
|
+
else {
|
|
892
|
+
startFn(params.engine, params.row.name);
|
|
893
|
+
}
|
|
821
894
|
const initial = assess({
|
|
822
895
|
config: params.config,
|
|
823
896
|
engine: params.engine,
|
|
@@ -930,6 +1003,34 @@ export async function ensureSandboxReady(params) {
|
|
|
930
1003
|
catch (error) {
|
|
931
1004
|
failure = error instanceof Error ? error : new Error(String(error));
|
|
932
1005
|
}
|
|
1006
|
+
if (params.reentry === 'completed') {
|
|
1007
|
+
if (params.workspace?.mode !== 'task-bound') {
|
|
1008
|
+
throw new Error('SANDBOX_COMPLETED_REENTRY_INVALID: completed re-entry requires a task-bound workspace');
|
|
1009
|
+
}
|
|
1010
|
+
const taskId = params.workspace.taskId;
|
|
1011
|
+
const commandChain = [
|
|
1012
|
+
`docker exec -it ${params.row.name} bash /usr/local/bin/sandbox-tmux-entry`,
|
|
1013
|
+
`ai sandbox rm ${taskId}`,
|
|
1014
|
+
`ai sandbox create ${params.branch}`
|
|
1015
|
+
];
|
|
1016
|
+
const code = params.allowRecreate || params.forceRecreate
|
|
1017
|
+
? 'SANDBOX_COMPLETED_RECREATE_UNSUPPORTED'
|
|
1018
|
+
: 'SANDBOX_COMPLETED_REENTRY_FAILED';
|
|
1019
|
+
const lead = code === 'SANDBOX_COMPLETED_RECREATE_UNSUPPORTED'
|
|
1020
|
+
? 'Completed sandbox replacement is unsupported; the existing container was not replaced.'
|
|
1021
|
+
: 'Completed sandbox recovery failed; the existing container was not replaced.';
|
|
1022
|
+
throw new Error([
|
|
1023
|
+
`${code}: ${lead}`,
|
|
1024
|
+
`Task: ${taskId}; container: ${params.row.name}; branch: ${params.branch}.`,
|
|
1025
|
+
'To preserve the current container state, enter it manually with:',
|
|
1026
|
+
` ${commandChain[0]}`,
|
|
1027
|
+
'If you intentionally want a replacement, the following is the full interactive sandbox cleanup, not a container-only delete.',
|
|
1028
|
+
'It may remove the worktree, local branch, tool/shell state, and branch share:',
|
|
1029
|
+
` ${commandChain[1]}`,
|
|
1030
|
+
` ${commandChain[2]}`,
|
|
1031
|
+
`Details: ${failure.message}`
|
|
1032
|
+
].join('\n'));
|
|
1033
|
+
}
|
|
933
1034
|
const dataBoundary = 'The existing container writable layer, ordinary /tmp data, processes, tmux sessions, and RAM state may be lost by replacement; worktree and host-managed sandbox data are preserved.';
|
|
934
1035
|
const recoveryTarget = params.workspace?.mode === 'task-bound'
|
|
935
1036
|
? params.workspace.taskId
|
|
@@ -79,6 +79,20 @@ export function resolveSandboxTarget(requestedRef, repoRoot) {
|
|
|
79
79
|
}
|
|
80
80
|
return { requestedRef, branch: requestedRef, workspace: { mode: 'branch-only' } };
|
|
81
81
|
}
|
|
82
|
+
export function resolveSandboxReentryContext(params) {
|
|
83
|
+
if (params.target.workspace.mode !== 'branch-only'
|
|
84
|
+
|| params.containerWorkspace.mode !== 'task-bound') {
|
|
85
|
+
return { workspace: params.target.workspace, reentry: 'standard' };
|
|
86
|
+
}
|
|
87
|
+
const task = resolveTaskWorkspace(params.containerWorkspace.taskId, params.repoRoot);
|
|
88
|
+
if (task.state !== 'completed' || task.branch !== params.target.branch) {
|
|
89
|
+
return { workspace: params.target.workspace, reentry: 'standard' };
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
workspace: { mode: 'task-bound', taskId: task.taskId },
|
|
93
|
+
reentry: 'completed'
|
|
94
|
+
};
|
|
95
|
+
}
|
|
82
96
|
export function resolveSandboxCleanupTarget(requestedRef, repoRoot, options = {}) {
|
|
83
97
|
if (isRemovedHashShortIdInput(requestedRef)) {
|
|
84
98
|
throw new Error(`Invalid task short id '${requestedRef}': task short ids must use bare digits`);
|
|
@@ -171,14 +171,12 @@ export function materializeSandboxControl(params) {
|
|
|
171
171
|
const token = randomBytes(32).toString('hex');
|
|
172
172
|
const generation = randomBytes(16).toString('hex');
|
|
173
173
|
const repoRoot = fs.realpathSync.native(params.repoRoot);
|
|
174
|
-
const
|
|
175
|
-
version: 5,
|
|
174
|
+
const manifestDraft = {
|
|
176
175
|
engine: params.engine ?? 'docker',
|
|
177
176
|
repoRoot,
|
|
178
177
|
worktreeRoot: fs.realpathSync.native(params.worktreeRoot),
|
|
179
178
|
project: params.project,
|
|
180
179
|
container: params.container,
|
|
181
|
-
containerIdentity: { id: '', labels: {} },
|
|
182
180
|
branch: params.branch,
|
|
183
181
|
mode: params.identity.mode,
|
|
184
182
|
taskId: params.identity.mode === 'task-bound' ? params.identity.taskId : null,
|
|
@@ -189,16 +187,16 @@ export function materializeSandboxControl(params) {
|
|
|
189
187
|
processingDir,
|
|
190
188
|
runtimeDir
|
|
191
189
|
};
|
|
192
|
-
|
|
193
|
-
return { root, channelDir, statusDir, runtimeDir, manifestPath, token, generation };
|
|
190
|
+
return { root, channelDir, statusDir, runtimeDir, manifestPath, manifestDraft, token, generation };
|
|
194
191
|
}
|
|
195
192
|
export function finalizeSandboxControlManifest(setup, identity) {
|
|
196
193
|
if (!identity.engine || !identity.id)
|
|
197
194
|
throw new Error('SANDBOX_CONTROL_CONTAINER_ID_INVALID');
|
|
198
|
-
const manifest =
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
195
|
+
const manifest = {
|
|
196
|
+
...setup.manifestDraft,
|
|
197
|
+
engine: identity.engine,
|
|
198
|
+
containerIdentity: { id: identity.id, labels: { ...identity.labels } }
|
|
199
|
+
};
|
|
202
200
|
const temporary = `${setup.manifestPath}.${process.pid}.${randomBytes(8).toString('hex')}.tmp`;
|
|
203
201
|
try {
|
|
204
202
|
fs.writeFileSync(temporary, `${JSON.stringify(manifest)}\n`, { mode: 0o600, flag: 'wx' });
|
|
@@ -207,5 +205,6 @@ export function finalizeSandboxControlManifest(setup, identity) {
|
|
|
207
205
|
finally {
|
|
208
206
|
fs.rmSync(temporary, { force: true });
|
|
209
207
|
}
|
|
208
|
+
return manifest;
|
|
210
209
|
}
|
|
211
210
|
//# sourceMappingURL=workspace-view.js.map
|