@fitlab-ai/agent-infra 0.8.5 → 0.9.0
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/bin/cli.ts +2 -2
- package/dist/bin/cli.js +2 -2
- package/dist/bin/internal-cli.js +98 -0
- package/dist/lib/decide.js +81 -90
- package/dist/lib/defaults.json +1 -0
- package/dist/lib/git/review-snapshot.js +79 -0
- package/dist/lib/git/workflow.js +101 -0
- package/dist/lib/internal/git-workflow.js +42 -0
- package/dist/lib/internal/platform-checks.js +119 -0
- package/dist/lib/internal/platform-comment.js +129 -0
- package/dist/lib/internal/platform-context.js +46 -0
- package/dist/lib/internal/platform-issue.js +142 -0
- package/dist/lib/internal/platform-pr.js +146 -0
- package/dist/lib/internal/release-workflow.js +217 -0
- package/dist/lib/internal/task-artifact.js +67 -0
- package/dist/lib/internal/task-context.js +43 -0
- package/dist/lib/internal/task-event.js +70 -0
- package/dist/lib/internal/task-ledger.js +114 -0
- package/dist/lib/internal/task-lifecycle.js +58 -0
- package/dist/lib/internal/task-short-id.js +83 -0
- package/dist/lib/internal/task-snapshot.js +47 -0
- package/dist/lib/internal/task-verify.js +50 -0
- package/dist/lib/internal/task-warning.js +74 -0
- package/dist/lib/platform/adapters.js +14 -0
- package/dist/lib/platform/context.js +146 -0
- package/dist/lib/platform/github-client.js +124 -0
- package/dist/lib/platform/issue-comments.js +409 -0
- package/dist/lib/platform/issue-metadata.js +183 -0
- package/dist/lib/platform/issues.js +617 -0
- package/dist/lib/platform/metadata-labels.js +28 -0
- package/dist/lib/platform/pr-checks.js +216 -0
- package/dist/lib/platform/pr-summary.js +88 -0
- package/dist/lib/platform/pull-request-metadata.js +38 -0
- package/dist/lib/platform/pull-requests.js +338 -0
- package/dist/lib/platform/releases.js +82 -0
- package/dist/lib/platform/types.js +22 -0
- package/dist/lib/platform/verification-required.js +78 -0
- package/dist/lib/platform/verification-sync.js +1014 -0
- package/dist/lib/platform/verification.js +6 -0
- package/dist/lib/release/channels.js +31 -0
- package/dist/lib/release/workflow.js +32 -0
- package/dist/lib/render.js +3 -2
- package/dist/lib/run/index.js +24 -7
- package/dist/lib/sandbox/capture.js +25 -3
- package/dist/lib/sandbox/commands/create.js +36 -22
- package/dist/lib/sandbox/commands/enter.js +34 -11
- package/dist/lib/sandbox/commands/list-running.js +10 -8
- package/dist/lib/sandbox/commands/show.js +2 -2
- package/dist/lib/sandbox/commands/start.js +53 -15
- package/dist/lib/sandbox/index.js +6 -6
- package/dist/lib/sandbox/mounts.js +36 -0
- package/dist/lib/sandbox/recovery.js +562 -0
- package/dist/lib/sandbox/task-resolver.js +5 -1
- package/dist/lib/sandbox/tools.js +19 -0
- package/dist/lib/server/protocol.js +5 -5
- package/dist/lib/task/activity-log.js +61 -0
- package/dist/lib/task/artifact-lifecycle.js +427 -0
- package/dist/lib/task/command-options.js +30 -0
- package/dist/lib/task/commands/cat.js +36 -6
- package/dist/lib/task/commands/decisions.js +80 -46
- package/dist/lib/task/commands/files.js +21 -7
- package/dist/lib/task/commands/grep.js +55 -7
- package/dist/lib/task/commands/issue-body.js +23 -14
- package/dist/lib/task/commands/log.js +27 -70
- package/dist/lib/task/commands/show.js +20 -7
- package/dist/lib/task/commands/status.js +18 -8
- package/dist/lib/task/decision-intents.js +154 -0
- package/dist/lib/task/decision-items.js +53 -0
- package/dist/lib/task/events.js +318 -0
- package/dist/lib/task/frontmatter.js +159 -1
- package/dist/lib/task/implementation-inputs.js +117 -0
- package/dist/lib/task/index.js +12 -9
- package/dist/lib/task/issue-form.js +19 -6
- package/dist/lib/task/ledger-intents.js +185 -0
- package/dist/lib/task/ledger.js +65 -35
- package/dist/lib/task/lifecycle.js +484 -0
- package/dist/lib/task/resolve-ref.js +152 -32
- package/dist/lib/task/review-artifacts.js +101 -0
- package/dist/lib/task/review-fingerprint.js +46 -0
- package/dist/lib/task/sections.js +358 -4
- package/dist/lib/task/short-id.js +292 -7
- package/dist/lib/task/snapshot.js +95 -0
- package/dist/lib/task/verification-checks.js +8 -0
- package/dist/lib/task/verification-config.js +14 -0
- package/dist/lib/task/verification-engine.js +906 -0
- package/dist/lib/task/verification-review.js +3 -0
- package/dist/lib/task/verification-types.js +2 -0
- package/dist/lib/task/verification.js +113 -0
- package/dist/lib/task/workflow-warning-intents.js +131 -0
- package/dist/lib/task/workflow-warnings.js +10 -78
- package/dist/lib/task/write.js +241 -0
- package/lib/decide.ts +57 -97
- package/lib/defaults.json +1 -0
- package/lib/git/review-snapshot.ts +73 -0
- package/lib/git/workflow.ts +101 -0
- package/lib/internal/git-workflow.ts +37 -0
- package/lib/internal/platform-checks.ts +101 -0
- package/lib/internal/platform-comment.ts +99 -0
- package/lib/internal/platform-context.ts +33 -0
- package/lib/internal/platform-issue.ts +116 -0
- package/lib/internal/platform-pr.ts +119 -0
- package/lib/internal/release-workflow.ts +186 -0
- package/lib/internal/task-artifact.ts +47 -0
- package/lib/internal/task-context.ts +35 -0
- package/lib/internal/task-event.ts +51 -0
- package/lib/internal/task-ledger.ts +86 -0
- package/lib/internal/task-lifecycle.ts +41 -0
- package/lib/internal/task-short-id.ts +55 -0
- package/lib/internal/task-snapshot.ts +32 -0
- package/lib/internal/task-verify.ts +33 -0
- package/lib/internal/task-warning.ts +50 -0
- package/lib/platform/adapters.ts +30 -0
- package/lib/platform/context.ts +164 -0
- package/lib/platform/github-client.ts +146 -0
- package/lib/platform/issue-comments.ts +479 -0
- package/lib/platform/issue-metadata.ts +250 -0
- package/lib/platform/issues.ts +691 -0
- package/lib/platform/metadata-labels.ts +33 -0
- package/lib/platform/pr-checks.ts +246 -0
- package/lib/platform/pr-summary.ts +90 -0
- package/lib/platform/pull-request-metadata.ts +69 -0
- package/lib/platform/pull-requests.ts +380 -0
- package/lib/platform/releases.ts +71 -0
- package/lib/platform/types.ts +74 -0
- package/lib/platform/verification-required.ts +83 -0
- package/{runtime/platform-adapters/platform-sync.github.js → lib/platform/verification-sync.ts} +198 -367
- package/lib/platform/verification.ts +11 -0
- package/lib/release/channels.ts +30 -0
- package/lib/release/workflow.ts +31 -0
- package/lib/render.ts +3 -2
- package/lib/run/index.ts +25 -7
- package/lib/sandbox/capture.ts +29 -3
- package/lib/sandbox/commands/create.ts +43 -25
- package/lib/sandbox/commands/enter.ts +38 -11
- package/lib/sandbox/commands/list-running.ts +10 -8
- package/lib/sandbox/commands/show.ts +2 -2
- package/lib/sandbox/commands/start.ts +50 -16
- package/lib/sandbox/index.ts +6 -6
- package/lib/sandbox/mounts.ts +55 -0
- package/lib/sandbox/recovery.ts +828 -0
- package/lib/sandbox/task-resolver.ts +5 -1
- package/lib/sandbox/tools.ts +31 -0
- package/lib/server/protocol.ts +5 -5
- package/lib/task/activity-log.ts +62 -0
- package/lib/task/artifact-lifecycle.ts +484 -0
- package/lib/task/command-options.ts +32 -0
- package/lib/task/commands/cat.ts +22 -9
- package/lib/task/commands/decisions.ts +49 -47
- package/lib/task/commands/files.ts +14 -6
- package/lib/task/commands/grep.ts +34 -7
- package/lib/task/commands/issue-body.ts +16 -16
- package/lib/task/commands/log.ts +17 -70
- package/lib/task/commands/show.ts +14 -6
- package/lib/task/commands/status.ts +17 -7
- package/lib/task/decision-intents.ts +163 -0
- package/lib/task/decision-items.ts +64 -0
- package/lib/task/events.ts +320 -0
- package/lib/task/frontmatter.ts +202 -2
- package/lib/task/implementation-inputs.ts +137 -0
- package/lib/task/index.ts +12 -9
- package/lib/task/issue-form.ts +20 -6
- package/lib/task/ledger-intents.ts +201 -0
- package/lib/task/ledger.ts +77 -31
- package/lib/task/lifecycle.ts +458 -0
- package/lib/task/resolve-ref.ts +197 -36
- package/{templates/.agents/scripts/lib/review-artifacts.js → lib/task/review-artifacts.ts} +11 -12
- package/{templates/.agents/scripts/lib/post-review-commit.js → lib/task/review-fingerprint.ts} +17 -12
- package/lib/task/sections.ts +486 -4
- package/lib/task/short-id.ts +403 -9
- package/lib/task/snapshot.ts +143 -0
- package/lib/task/verification-checks.ts +9 -0
- package/lib/task/verification-config.ts +20 -0
- package/{templates/.agents/scripts/validate-artifact.js → lib/task/verification-engine.ts} +199 -406
- package/lib/task/verification-review.ts +9 -0
- package/lib/task/verification-types.ts +29 -0
- package/lib/task/verification.ts +156 -0
- package/lib/task/workflow-warning-intents.ts +142 -0
- package/lib/task/workflow-warnings.ts +10 -78
- package/lib/task/write.ts +468 -0
- package/package.json +4 -2
- package/templates/.agents/README.en.md +4 -3
- package/templates/.agents/README.zh-CN.md +4 -3
- package/templates/.agents/rules/README.en.md +6 -5
- package/templates/.agents/rules/README.zh-CN.md +6 -5
- package/templates/.agents/rules/create-issue.en.md +1 -1
- package/templates/.agents/rules/create-issue.github.en.md +5 -184
- package/templates/.agents/rules/create-issue.github.zh-CN.md +12 -178
- package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
- package/templates/.agents/rules/human-decision-context.en.md +36 -0
- package/templates/.agents/rules/human-decision-context.zh-CN.md +36 -0
- package/templates/.agents/rules/issue-fields.github.en.md +4 -148
- package/templates/.agents/rules/issue-fields.github.zh-CN.md +9 -144
- package/templates/.agents/rules/issue-pr-commands.en.md +43 -3
- package/templates/.agents/rules/issue-pr-commands.github.en.md +15 -220
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +23 -213
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +45 -3
- package/templates/.agents/rules/issue-sync.en.md +1 -1
- package/templates/.agents/rules/issue-sync.github.en.md +14 -301
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +36 -287
- package/templates/.agents/rules/issue-sync.zh-CN.md +1 -1
- package/templates/.agents/rules/milestone-inference.en.md +1 -1
- package/templates/.agents/rules/milestone-inference.github.en.md +7 -119
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +8 -108
- package/templates/.agents/rules/milestone-inference.zh-CN.md +1 -1
- package/templates/.agents/rules/next-step-output.en.md +12 -11
- package/templates/.agents/rules/next-step-output.zh-CN.md +12 -11
- package/templates/.agents/rules/no-mid-flow-questions.en.md +3 -3
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +3 -3
- package/templates/.agents/rules/pr-checks-commands.en.md +16 -3
- package/templates/.agents/rules/pr-checks-commands.github.en.md +10 -54
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +19 -47
- package/templates/.agents/rules/pr-checks-commands.zh-CN.md +30 -3
- package/templates/.agents/rules/pr-sync.en.md +30 -3
- package/templates/.agents/rules/pr-sync.github.en.md +12 -115
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +26 -104
- package/templates/.agents/rules/pr-sync.zh-CN.md +43 -3
- package/templates/.agents/rules/review-handshake.en.md +8 -5
- package/templates/.agents/rules/review-handshake.zh-CN.md +8 -5
- package/templates/.agents/rules/task-management.en.md +11 -2
- package/templates/.agents/rules/task-management.zh-CN.md +11 -3
- package/templates/.agents/rules/task-short-id.en.md +25 -29
- package/templates/.agents/rules/task-short-id.zh-CN.md +20 -23
- package/templates/.agents/scripts/lib/agent-infra-package.js +1 -9
- package/templates/.agents/scripts/task-short-id.js +71 -533
- package/templates/.agents/skills/analyze-task/SKILL.en.md +22 -55
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +26 -59
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -3
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -3
- package/templates/.agents/skills/block-task/SKILL.en.md +21 -47
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +23 -47
- package/templates/.agents/skills/block-task/config/verify.json +1 -2
- package/templates/.agents/skills/cancel-task/SKILL.en.md +16 -45
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +16 -45
- package/templates/.agents/skills/cancel-task/config/verify.json +1 -2
- package/templates/.agents/skills/check-task/SKILL.en.md +6 -3
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +6 -3
- package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -24
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -24
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -24
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -24
- package/templates/.agents/skills/code-task/SKILL.en.md +22 -35
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +28 -44
- package/templates/.agents/skills/code-task/config/verify.en.json +3 -3
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +3 -3
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +13 -9
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +13 -9
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +11 -1
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +11 -1
- package/templates/.agents/skills/commit/SKILL.en.md +13 -11
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +13 -11
- package/templates/.agents/skills/commit/config/verify.json +1 -2
- package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -11
- package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -11
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +4 -8
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +4 -8
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +6 -18
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +5 -17
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +13 -0
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +13 -0
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +13 -36
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +13 -36
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -3
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -3
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +10 -54
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +10 -79
- package/templates/.agents/skills/complete-task/SKILL.en.md +59 -63
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +59 -63
- package/templates/.agents/skills/complete-task/config/verify.en.json +11 -7
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +11 -7
- package/templates/.agents/skills/create-pr/SKILL.en.md +19 -44
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +19 -43
- package/templates/.agents/skills/create-pr/config/verify.json +1 -2
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +8 -12
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +7 -11
- package/templates/.agents/skills/create-task/SKILL.en.md +12 -13
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +12 -13
- package/templates/.agents/skills/create-task/config/verify.json +1 -2
- package/templates/.agents/skills/import-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/import-codescan/config/verify.json +1 -2
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/import-dependabot/config/verify.json +1 -2
- package/templates/.agents/skills/import-issue/SKILL.en.md +9 -13
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -14
- package/templates/.agents/skills/import-issue/config/verify.json +1 -2
- package/templates/.agents/skills/plan-task/SKILL.en.md +17 -42
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +22 -49
- package/templates/.agents/skills/plan-task/config/verify.en.json +1 -3
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -3
- package/templates/.agents/skills/post-release/SKILL.en.md +11 -81
- package/templates/.agents/skills/post-release/SKILL.zh-CN.md +8 -78
- package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
- package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/release/SKILL.en.md +16 -163
- package/templates/.agents/skills/release/SKILL.zh-CN.md +15 -162
- package/templates/.agents/skills/restore-task/SKILL.en.md +11 -29
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +11 -29
- package/templates/.agents/skills/restore-task/config/verify.json +1 -2
- package/templates/.agents/skills/review-analysis/SKILL.en.md +13 -25
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +13 -33
- package/templates/.agents/skills/review-analysis/config/verify.en.json +3 -4
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +3 -4
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +9 -12
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +9 -12
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +9 -2
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +9 -2
- package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +7 -0
- package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +7 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +22 -36
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +23 -41
- package/templates/.agents/skills/review-code/config/verify.en.json +3 -4
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +3 -4
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +56 -18
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +56 -18
- package/templates/.agents/skills/review-code/reference/report-template.en.md +11 -4
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +11 -4
- package/templates/.agents/skills/review-code/reference/review-criteria.en.md +7 -0
- package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +7 -0
- package/templates/.agents/skills/review-plan/SKILL.en.md +13 -25
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +13 -33
- package/templates/.agents/skills/review-plan/config/verify.en.json +3 -4
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +3 -4
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +9 -12
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +9 -12
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +9 -2
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +9 -2
- package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +7 -0
- package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +7 -0
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +1 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +1 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -15
- package/templates/.agents/skills/watch-pr/SKILL.en.md +24 -14
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +25 -15
- package/templates/.agents/skills/watch-pr/config/verify.json +1 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +2 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +2 -2
- package/templates/.agents/templates/task.en.md +6 -1
- package/templates/.agents/templates/task.zh-CN.md +6 -1
- 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 -0
- package/templates/.claude/commands/commit.zh-CN.md +1 -0
- 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/watch-pr.en.md +1 -1
- package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
- package/templates/.gemini/commands/_project_/analyze-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/block-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/cancel-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/check-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/code-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/commit.en.toml +4 -0
- package/templates/.gemini/commands/_project_/commit.zh-CN.toml +4 -0
- package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +2 -0
- package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/complete-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/create-pr.en.toml +2 -0
- package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/plan-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/review-analysis.en.toml +2 -0
- package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/review-code.en.toml +2 -0
- package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/review-plan.en.toml +2 -0
- package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/watch-pr.en.toml +2 -0
- package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +2 -0
- package/templates/.git-hooks/check-large-files.cjs +92 -0
- package/templates/.git-hooks/check-version-format.sh +5 -1
- package/templates/.git-hooks/pre-commit +1 -0
- package/templates/.opencode/commands/analyze-task.en.md +1 -1
- package/templates/.opencode/commands/analyze-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/check-task.en.md +1 -1
- package/templates/.opencode/commands/check-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/code-task.en.md +1 -1
- package/templates/.opencode/commands/code-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/commit.en.md +2 -0
- package/templates/.opencode/commands/commit.zh-CN.md +2 -0
- package/templates/.opencode/commands/complete-task.en.md +1 -1
- package/templates/.opencode/commands/complete-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/plan-task.en.md +1 -1
- package/templates/.opencode/commands/plan-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/review-analysis.en.md +1 -1
- package/templates/.opencode/commands/review-analysis.zh-CN.md +1 -1
- package/templates/.opencode/commands/review-code.en.md +1 -1
- package/templates/.opencode/commands/review-code.zh-CN.md +1 -1
- package/templates/.opencode/commands/review-plan.en.md +1 -1
- package/templates/.opencode/commands/review-plan.zh-CN.md +1 -1
- package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +0 -40
- package/templates/.agents/scripts/platform-adapters/platform-sync.js +0 -13
- package/templates/.agents/scripts/review-diff-fingerprint.js +0 -170
- package/templates/.agents/scripts/workflow-warnings.js +0 -290
- package/templates/.agents/skills/code-task/scripts/detect-mode.js +0 -257
- package/templates/.agents/skills/release/scripts/manage-milestones.github.sh +0 -80
- package/templates/.agents/skills/release/scripts/manage-milestones.sh +0 -6
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { inspectRequiredChecks } from './pr-checks.js';
|
|
2
|
+
function verificationCheck(type, status, message, failType) {
|
|
3
|
+
return { type, status, message, ...(failType ? { fail_type: failType } : {}) };
|
|
4
|
+
}
|
|
5
|
+
export { inspectRequiredChecks, verificationCheck };
|
|
6
|
+
//# sourceMappingURL=verification.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
async function inspectNpmChannel(name, version, fetcher = fetch) {
|
|
2
|
+
try {
|
|
3
|
+
const response = await fetcher(`https://registry.npmjs.org/${encodeURIComponent(name)}/${encodeURIComponent(version)}`);
|
|
4
|
+
if (response.status === 404)
|
|
5
|
+
return { status: 'no-op', published: false, version, error: null };
|
|
6
|
+
if (!response.ok)
|
|
7
|
+
return { status: 'blocked', published: null, version, error: { code: 'NPM_REGISTRY_UNAVAILABLE', message: `npm registry returned ${response.status}` } };
|
|
8
|
+
const body = await response.json();
|
|
9
|
+
return { status: 'no-op', published: body.version === version, version, error: null };
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
return { status: 'blocked', published: null, version, error: { code: 'NPM_REGISTRY_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) } };
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async function inspectHomebrewChannel(url, version, fetcher = fetch) {
|
|
16
|
+
try {
|
|
17
|
+
const response = await fetcher(url);
|
|
18
|
+
if (response.status === 404)
|
|
19
|
+
return { status: 'no-op', published: false, version, error: null };
|
|
20
|
+
if (!response.ok)
|
|
21
|
+
return { status: 'blocked', published: null, version, error: { code: 'HOMEBREW_UNAVAILABLE', message: `formula endpoint returned ${response.status}` } };
|
|
22
|
+
const formula = await response.text();
|
|
23
|
+
const escaped = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
24
|
+
return { status: 'no-op', published: new RegExp(`(?:version\\s+["']${escaped}["']|/v?${escaped}\\.)`).test(formula), version, error: null };
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
return { status: 'blocked', published: null, version, error: { code: 'HOMEBREW_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) } };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export { inspectHomebrewChannel, inspectNpmChannel };
|
|
31
|
+
//# sourceMappingURL=channels.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
function deriveReleasePhase(facts) {
|
|
2
|
+
if (!facts.localTag)
|
|
3
|
+
return 'unprepared';
|
|
4
|
+
if (!facts.remoteBranch && !facts.remoteTag)
|
|
5
|
+
return 'prepared';
|
|
6
|
+
if (!facts.remoteBranch || !facts.remoteTag)
|
|
7
|
+
return 'partially-published';
|
|
8
|
+
if (facts.githubRelease !== true || facts.npm !== true || facts.homebrew !== true)
|
|
9
|
+
return 'published';
|
|
10
|
+
if (facts.smoke !== 'success' || !facts.postCommit)
|
|
11
|
+
return 'post-pending';
|
|
12
|
+
return 'complete';
|
|
13
|
+
}
|
|
14
|
+
function releaseSnapshot(version, facts) {
|
|
15
|
+
return { version, tag: `v${version.replace(/^v/, '')}`, phase: deriveReleasePhase(facts), facts };
|
|
16
|
+
}
|
|
17
|
+
async function runReleaseAction(input) {
|
|
18
|
+
const before = releaseSnapshot(input.version, await input.inspect());
|
|
19
|
+
if (input.action === 'inspect')
|
|
20
|
+
return { status: 'no-op', changed: false, before, snapshot: before, error: null };
|
|
21
|
+
const allowed = input.action === 'prepare' ? before.phase === 'unprepared'
|
|
22
|
+
: input.action === 'publish' ? ['prepared', 'partially-published'].includes(before.phase)
|
|
23
|
+
: ['published', 'post-pending'].includes(before.phase);
|
|
24
|
+
if (!allowed)
|
|
25
|
+
return { status: before.phase === 'complete' ? 'no-op' : 'failed', changed: false, before, snapshot: before, error: before.phase === 'complete' ? null : { code: 'RELEASE_PHASE_INVALID', message: `Cannot ${input.action} from ${before.phase}` } };
|
|
26
|
+
await input[input.action]?.();
|
|
27
|
+
const snapshot = releaseSnapshot(input.version, await input.inspect());
|
|
28
|
+
const progressed = snapshot.phase !== before.phase;
|
|
29
|
+
return { status: progressed ? 'applied' : 'blocked', changed: progressed, before, snapshot, error: progressed ? null : { code: 'RELEASE_PROGRESS_PENDING', message: `${input.action} has not reached the next observable phase` } };
|
|
30
|
+
}
|
|
31
|
+
export { deriveReleasePhase, releaseSnapshot, runReleaseAction };
|
|
32
|
+
//# sourceMappingURL=workflow.js.map
|
package/dist/lib/render.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
//
|
|
4
|
-
|
|
3
|
+
// Built-in platform strategies. "none" deliberately selects generic templates
|
|
4
|
+
// and the no-op runtime adapter instead of requiring .none.* variants.
|
|
5
|
+
const KNOWN_PLATFORMS = new Set(['github', 'none']);
|
|
5
6
|
const KNOWN_LANGUAGES = new Set(['en', 'zh-CN']);
|
|
6
7
|
function renderFile(src, dst, replacements) {
|
|
7
8
|
if (!fs.existsSync(src)) {
|
package/dist/lib/run/index.js
CHANGED
|
@@ -7,14 +7,15 @@ import { loadShortIdByTaskId, normalizeShortIdInput } from '../task/short-id.js'
|
|
|
7
7
|
import { buildTuiCommand, renderPrompt, selectTui } from './tui.js';
|
|
8
8
|
import { getSkillRunSpec } from './skills.js';
|
|
9
9
|
import { runHostCommand } from './host.js';
|
|
10
|
-
const USAGE = `Usage: ai run <skill> [task-ref] [args...] [--tui <name>]
|
|
10
|
+
const USAGE = `Usage: ai run <skill> [task-ref] [args...] [--tui <name>] [--recreate]
|
|
11
11
|
|
|
12
12
|
Task skills are scheduled inside the sandbox tmux session; ai run returns once
|
|
13
|
-
the tmux window is created.
|
|
13
|
+
the tmux window is created. --recreate authorizes container-only replacement
|
|
14
|
+
when in-place sandbox recovery fails; it is not included in the TUI prompt.
|
|
14
15
|
|
|
15
16
|
Examples:
|
|
16
17
|
ai run create-task "describe the task" --tui codex
|
|
17
|
-
ai run code-task #7 --tui codex`;
|
|
18
|
+
ai run code-task #7 --tui codex --recreate`;
|
|
18
19
|
function extractTui(args) {
|
|
19
20
|
const rest = [];
|
|
20
21
|
let tui = null;
|
|
@@ -36,12 +37,16 @@ export function parseRunArgs(args) {
|
|
|
36
37
|
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
37
38
|
throw new Error(USAGE);
|
|
38
39
|
}
|
|
39
|
-
const { rest, tui } = extractTui(args);
|
|
40
|
+
const { rest: withRecoveryFlags, tui } = extractTui(args);
|
|
41
|
+
const recreate = withRecoveryFlags.includes('--recreate');
|
|
42
|
+
const rest = withRecoveryFlags.filter((arg) => arg !== '--recreate');
|
|
40
43
|
const [skill = '', maybeTaskRef, ...remaining] = rest;
|
|
41
44
|
const spec = getSkillRunSpec(skill);
|
|
42
45
|
if (!spec)
|
|
43
46
|
throw new Error(`Unknown skill '${skill}'`);
|
|
44
47
|
if (spec.kind === 'create') {
|
|
48
|
+
if (recreate)
|
|
49
|
+
throw new Error('--recreate is only valid for sandbox task runs');
|
|
45
50
|
const createArgs = rest.slice(1);
|
|
46
51
|
if (createArgs.length === 0)
|
|
47
52
|
throw new Error('create-task requires a description');
|
|
@@ -49,7 +54,13 @@ export function parseRunArgs(args) {
|
|
|
49
54
|
}
|
|
50
55
|
if (!maybeTaskRef)
|
|
51
56
|
throw new Error(`${skill} requires a task-ref`);
|
|
52
|
-
return {
|
|
57
|
+
return {
|
|
58
|
+
skill,
|
|
59
|
+
taskRef: maybeTaskRef,
|
|
60
|
+
args: remaining,
|
|
61
|
+
tui,
|
|
62
|
+
...(recreate ? { recreate: true } : {})
|
|
63
|
+
};
|
|
53
64
|
}
|
|
54
65
|
function assertAllowedByConfig(skill, commandConfig) {
|
|
55
66
|
const allowed = commandConfig.allowedSkills;
|
|
@@ -97,7 +108,7 @@ function resolveActiveTaskIdentity(taskRef, repoRoot) {
|
|
|
97
108
|
if (normalized.kind !== 'shortId')
|
|
98
109
|
return null;
|
|
99
110
|
resolvedTaskRef = normalized.value;
|
|
100
|
-
taskId = readActiveShortIdRegistry(repoRoot)[normalized.value
|
|
111
|
+
taskId = readActiveShortIdRegistry(repoRoot)[normalized.value] ?? null;
|
|
101
112
|
}
|
|
102
113
|
if (!taskId)
|
|
103
114
|
return null;
|
|
@@ -161,7 +172,13 @@ export async function runSkill(args, options = {}) {
|
|
|
161
172
|
const writeStderr = options.writeStderr ?? ((chunk) => process.stderr.write(chunk));
|
|
162
173
|
const runSandbox = options.runSandbox ??
|
|
163
174
|
((request) => runInSandbox(request));
|
|
164
|
-
const result = await runSandbox({
|
|
175
|
+
const result = await runSandbox({
|
|
176
|
+
taskRef: parsed.taskRef,
|
|
177
|
+
branch,
|
|
178
|
+
command,
|
|
179
|
+
runId,
|
|
180
|
+
recreate: parsed.recreate
|
|
181
|
+
});
|
|
165
182
|
if (result.stdout) {
|
|
166
183
|
writeStdout(result.stdout);
|
|
167
184
|
}
|
|
@@ -3,6 +3,7 @@ import { loadConfig } from './config.js';
|
|
|
3
3
|
import { containerNameCandidates, sandboxBranchLabel, sandboxLabel } from './constants.js';
|
|
4
4
|
import { detectEngine } from './engine.js';
|
|
5
5
|
import { commandForEngine } from './shell.js';
|
|
6
|
+
import { ensureSandboxReady } from './recovery.js';
|
|
6
7
|
import { hostTimezoneEnvFlags, terminalEnvFlags } from './commands/enter.js';
|
|
7
8
|
import { fetchSandboxRows, selectSandboxContainer, startSandboxContainer } from './commands/list-running.js';
|
|
8
9
|
async function spawnCapture(file, args) {
|
|
@@ -131,7 +132,28 @@ export async function runInSandbox(request, options = {}) {
|
|
|
131
132
|
if (!found) {
|
|
132
133
|
throw new Error(`Sandbox for ${request.branch} not found. Create it first with ai sandbox create ${request.taskRef}.`);
|
|
133
134
|
}
|
|
134
|
-
|
|
135
|
+
let container = found.name;
|
|
136
|
+
if (options.ensureReady) {
|
|
137
|
+
container = (await options.ensureReady({
|
|
138
|
+
branch: request.branch,
|
|
139
|
+
row: found,
|
|
140
|
+
allowRecreate: request.recreate ?? false
|
|
141
|
+
})).container;
|
|
142
|
+
}
|
|
143
|
+
else if (config) {
|
|
144
|
+
container = (await ensureSandboxReady({
|
|
145
|
+
config,
|
|
146
|
+
engine,
|
|
147
|
+
branch: request.branch,
|
|
148
|
+
row: found,
|
|
149
|
+
allowRecreate: request.recreate,
|
|
150
|
+
recreate: async (targetBranch) => {
|
|
151
|
+
const { create } = await import('./commands/create.js');
|
|
152
|
+
await create([targetBranch, '--no-refresh']);
|
|
153
|
+
}
|
|
154
|
+
})).container;
|
|
155
|
+
}
|
|
156
|
+
else if (!found.running) {
|
|
135
157
|
(options.startContainer ?? ((name) => startSandboxContainer(engine, name)))(found.name);
|
|
136
158
|
}
|
|
137
159
|
const runId = options.runId ?? createRunId();
|
|
@@ -140,7 +162,7 @@ export async function runInSandbox(request, options = {}) {
|
|
|
140
162
|
'exec',
|
|
141
163
|
...terminalEnvFlags(),
|
|
142
164
|
...hostTimezoneEnvFlags(),
|
|
143
|
-
|
|
165
|
+
container,
|
|
144
166
|
'bash',
|
|
145
167
|
'-lc',
|
|
146
168
|
buildTmuxLauncher({ request, runId })
|
|
@@ -152,7 +174,7 @@ export async function runInSandbox(request, options = {}) {
|
|
|
152
174
|
run: {
|
|
153
175
|
runId,
|
|
154
176
|
engine,
|
|
155
|
-
container
|
|
177
|
+
container,
|
|
156
178
|
runDir
|
|
157
179
|
}
|
|
158
180
|
};
|
|
@@ -13,8 +13,10 @@ import { prepareDockerfile } from '../dockerfile.js';
|
|
|
13
13
|
import { detectEngine, ensureDocker } from '../engine.js';
|
|
14
14
|
import { commandForEngine, execEngine, run, runEngine, runOk, runOkEngine, runSafe, runSafeEngine, runVerboseEngine } from '../shell.js';
|
|
15
15
|
import { resolveTaskBranch } from '../task-resolver.js';
|
|
16
|
-
import { resolveTools, toolConfigDirCandidates } from '../tools.js';
|
|
16
|
+
import { resolveTools, tmpfsSeedStagingPath, tmpfsSeedTargetPath, toolConfigDirCandidates } from '../tools.js';
|
|
17
|
+
import { assertFreshSandboxReady, hydrateTmpfsSeedEntries, prepareTmpfsMounts } from '../recovery.js';
|
|
17
18
|
import { hostJoin, toEnginePath, volumeArg } from '../engines/wsl2-paths.js';
|
|
19
|
+
import { sandboxCoreBindMounts } from '../mounts.js';
|
|
18
20
|
import { clipboardHostDir, CONTAINER_CLIPBOARD_MOUNT } from '../clipboard/paths.js';
|
|
19
21
|
import { validateSelinuxDisableEnv } from '../engines/selinux.js';
|
|
20
22
|
import { dotfilesCacheDir, materializeDotfiles } from '../dotfiles.js';
|
|
@@ -999,6 +1001,7 @@ export async function create(args) {
|
|
|
999
1001
|
const baseBranch = base ?? runSafe('git', ['-C', effectiveConfig.repoRoot, 'branch', '--show-current']);
|
|
1000
1002
|
const expectedImageSignature = buildImageSignature(preparedDockerfile, tools);
|
|
1001
1003
|
const engine = detectEngine(effectiveConfig);
|
|
1004
|
+
let createdTmpfsSeedPlan = [];
|
|
1002
1005
|
p.intro(pc.cyan('AI Sandbox'));
|
|
1003
1006
|
p.log.info(`Project: ${pc.bold(effectiveConfig.project)} | Branch: ${pc.bold(branch)} | Base: ${pc.bold(baseBranch || 'HEAD')}`);
|
|
1004
1007
|
if (credentialOutcome.status === 'SKIPPED') {
|
|
@@ -1209,9 +1212,12 @@ export async function create(args) {
|
|
|
1209
1212
|
branch,
|
|
1210
1213
|
repoRoot: effectiveConfig.repoRoot
|
|
1211
1214
|
});
|
|
1212
|
-
const
|
|
1215
|
+
const coreVolumes = sandboxCoreBindMounts(effectiveConfig, branch, {
|
|
1216
|
+
worktree,
|
|
1217
|
+
shellConfigHostDir: hostShellConfig.hostDir
|
|
1218
|
+
}).flatMap(({ hostPaths, containerPath, readOnly }) => [
|
|
1213
1219
|
'-v',
|
|
1214
|
-
volumeArg(engine,
|
|
1220
|
+
volumeArg(engine, hostPaths[0], containerPath, readOnly ? ':ro' : '')
|
|
1215
1221
|
]);
|
|
1216
1222
|
// Mount each declared seed read-only at an isolated staging path.
|
|
1217
1223
|
// After docker run mounts the empty tmpfs, the container's default
|
|
@@ -1220,14 +1226,17 @@ export async function create(args) {
|
|
|
1220
1226
|
// stale runtime files (logs_2.sqlite, sessions, etc.) on the host from
|
|
1221
1227
|
// being exposed or written through.
|
|
1222
1228
|
tmpfsSeedPlan = effectiveResolvedTools.flatMap(({ tool, dir }) => (tool.tmpfs?.seed ?? []).flatMap((entry, index) => {
|
|
1229
|
+
const targetPath = tmpfsSeedTargetPath(tool.containerMount, entry);
|
|
1223
1230
|
const hostPath = path.join(dir, entry);
|
|
1224
1231
|
if (!fs.existsSync(hostPath)) {
|
|
1225
1232
|
return [];
|
|
1226
1233
|
}
|
|
1227
|
-
const stagingPath =
|
|
1234
|
+
const stagingPath = tmpfsSeedStagingPath(tool.id, index);
|
|
1228
1235
|
return [{
|
|
1236
|
+
toolId: tool.id,
|
|
1237
|
+
containerMount: tool.containerMount,
|
|
1229
1238
|
stagingPath,
|
|
1230
|
-
targetPath
|
|
1239
|
+
targetPath,
|
|
1231
1240
|
volumeArgs: ['-v', volumeArg(engine, hostPath, stagingPath, ':ro')]
|
|
1232
1241
|
}];
|
|
1233
1242
|
}));
|
|
@@ -1258,14 +1267,7 @@ export async function create(args) {
|
|
|
1258
1267
|
sandboxLabel(effectiveConfig),
|
|
1259
1268
|
'--label',
|
|
1260
1269
|
`${sandboxBranchLabel(effectiveConfig)}=${branch}`,
|
|
1261
|
-
|
|
1262
|
-
volumeArg(engine, worktree, '/workspace'),
|
|
1263
|
-
'-v',
|
|
1264
|
-
volumeArg(engine, workspaceDir, '/workspace/.agents/workspace'),
|
|
1265
|
-
'-v',
|
|
1266
|
-
volumeArg(engine, shareCommon, '/share/common'),
|
|
1267
|
-
'-v',
|
|
1268
|
-
volumeArg(engine, shareBranch, '/share/branch'),
|
|
1270
|
+
...coreVolumes,
|
|
1269
1271
|
...buildClipboardVolumeArgs(engine, effectiveConfig.home),
|
|
1270
1272
|
'-v',
|
|
1271
1273
|
volumeArg(engine, path.join(effectiveConfig.repoRoot, '.git'), `${toEnginePath(engine, effectiveConfig.repoRoot)}/.git`),
|
|
@@ -1274,25 +1276,30 @@ export async function create(args) {
|
|
|
1274
1276
|
...tmpfsArgs,
|
|
1275
1277
|
...tmpfsSeedPlan.flatMap(({ volumeArgs }) => volumeArgs),
|
|
1276
1278
|
...liveMountVolumes,
|
|
1277
|
-
...shellConfigVolumes,
|
|
1278
1279
|
...envFile.dockerArgs,
|
|
1279
1280
|
...tzFlags,
|
|
1280
1281
|
'-w',
|
|
1281
1282
|
'/workspace',
|
|
1282
1283
|
effectiveConfig.imageName
|
|
1283
1284
|
]);
|
|
1285
|
+
createdTmpfsSeedPlan = tmpfsSeedPlan;
|
|
1284
1286
|
}
|
|
1285
1287
|
finally {
|
|
1286
1288
|
envFile.cleanup();
|
|
1287
1289
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1290
|
+
prepareTmpfsMounts({
|
|
1291
|
+
engine,
|
|
1292
|
+
container,
|
|
1293
|
+
mountPaths: effectiveResolvedTools
|
|
1294
|
+
.filter(({ tool }) => tool.tmpfs)
|
|
1295
|
+
.map(({ tool }) => tool.containerMount)
|
|
1296
|
+
});
|
|
1297
|
+
hydrateTmpfsSeedEntries({
|
|
1298
|
+
engine,
|
|
1299
|
+
container,
|
|
1300
|
+
entries: tmpfsSeedPlan,
|
|
1301
|
+
replace: true
|
|
1302
|
+
});
|
|
1296
1303
|
// Belt-and-suspenders: re-create the four shell-config symlinks at
|
|
1297
1304
|
// runtime so users with a custom `sandbox.dockerfile` (which won't
|
|
1298
1305
|
// include the ai-tools.dockerfile symlink fragment) still get
|
|
@@ -1346,6 +1353,13 @@ export async function create(args) {
|
|
|
1346
1353
|
preparedDockerfile.cleanup();
|
|
1347
1354
|
}
|
|
1348
1355
|
p.log.step('Verifying setup...');
|
|
1356
|
+
assertFreshSandboxReady({
|
|
1357
|
+
config: effectiveConfig,
|
|
1358
|
+
engine,
|
|
1359
|
+
branch,
|
|
1360
|
+
container,
|
|
1361
|
+
copiedEntries: createdTmpfsSeedPlan
|
|
1362
|
+
});
|
|
1349
1363
|
const runningContainers = runSafeEngine(engine, 'docker', ['ps', '--format', '{{.Names}}']).split('\n');
|
|
1350
1364
|
const checks = [
|
|
1351
1365
|
{ name: 'Container running', ok: runningContainers.includes(container) },
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { loadConfig } from '../config.js';
|
|
2
2
|
import { assertValidBranchName, containerNameCandidates, sandboxBranchLabel, sandboxLabel } from '../constants.js';
|
|
3
3
|
import { detectEngine } from '../engine.js';
|
|
4
|
+
import { ensureSandboxReady } from '../recovery.js';
|
|
4
5
|
import { formatCredentialWarnings, formatRemaining, hasClaudeProviderAuth, reconcileClaudeCredentials, redactCommandError, validateClaudeCredentialsEnvOverride } from '../credentials.js';
|
|
5
6
|
import { runInteractiveEngine } from '../shell.js';
|
|
6
7
|
import { dotfilesCacheDir, materializeDotfiles } from '../dotfiles.js';
|
|
7
8
|
import { runInteractiveWithClipboardBridge } from '../clipboard/bridge.js';
|
|
8
9
|
import { detectHostTimezone } from '../host-timezone.js';
|
|
9
|
-
import { fetchSandboxRows, resolveBranchArg, selectSandboxContainer,
|
|
10
|
-
const USAGE = `Usage: ai sandbox exec <branch | TASK-id | N
|
|
10
|
+
import { fetchSandboxRows, resolveBranchArg, selectSandboxContainer, } from './list-running.js';
|
|
11
|
+
const USAGE = `Usage: ai sandbox exec [--recreate] <branch | TASK-id | N> [cmd...]
|
|
11
12
|
|
|
12
|
-
N
|
|
13
|
+
N references an active task short id from
|
|
13
14
|
.agents/workspace/active/.short-ids.json. They resolve only via that
|
|
14
15
|
registry — they do not reference a container's row position in
|
|
15
|
-
'ai sandbox ls' output
|
|
16
|
+
'ai sandbox ls' output. --recreate is a host recovery flag only before the
|
|
17
|
+
target; the same token after the target is passed to the container command.`;
|
|
16
18
|
const TMUX_ENTRY_PATH = '/usr/local/bin/sandbox-tmux-entry';
|
|
17
19
|
// Terminal-detection variables that interactive TUIs (e.g. claude-code)
|
|
18
20
|
// inspect to enable progressive enhancements such as the kitty keyboard
|
|
@@ -76,6 +78,19 @@ export function formatCredentialSyncStatus(result, isTTY = process.stderr.isTTY,
|
|
|
76
78
|
}
|
|
77
79
|
return null;
|
|
78
80
|
}
|
|
81
|
+
export function parseEnterArgs(args) {
|
|
82
|
+
let recreate = false;
|
|
83
|
+
let index = 0;
|
|
84
|
+
while (args[index] === '--recreate') {
|
|
85
|
+
recreate = true;
|
|
86
|
+
index += 1;
|
|
87
|
+
}
|
|
88
|
+
const target = args[index] ?? '';
|
|
89
|
+
if (!target) {
|
|
90
|
+
throw new Error(USAGE);
|
|
91
|
+
}
|
|
92
|
+
return { target, command: args.slice(index + 1), recreate };
|
|
93
|
+
}
|
|
79
94
|
export async function enter(args) {
|
|
80
95
|
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
81
96
|
process.stdout.write(`${USAGE}\n`);
|
|
@@ -87,19 +102,27 @@ export async function enter(args) {
|
|
|
87
102
|
const config = loadConfig();
|
|
88
103
|
validateClaudeCredentialsEnvOverride();
|
|
89
104
|
const engine = detectEngine(config);
|
|
90
|
-
const
|
|
91
|
-
const branch = resolveBranchArg(
|
|
105
|
+
const parsed = parseEnterArgs(args);
|
|
106
|
+
const branch = resolveBranchArg(parsed.target, { repoRoot: config.repoRoot });
|
|
92
107
|
assertValidBranchName(branch);
|
|
93
108
|
const { running, nonRunning } = fetchSandboxRows(engine, sandboxLabel(config), sandboxBranchLabel(config));
|
|
94
109
|
const found = selectSandboxContainer([...running, ...nonRunning], containerNameCandidates(config, branch));
|
|
95
110
|
if (!found) {
|
|
96
111
|
throw new Error(`No sandbox found for branch '${branch}'. Run 'ai sandbox create ${branch}' to create one.`);
|
|
97
112
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
113
|
+
const ready = await ensureSandboxReady({
|
|
114
|
+
config,
|
|
115
|
+
engine,
|
|
116
|
+
branch,
|
|
117
|
+
row: found,
|
|
118
|
+
allowRecreate: parsed.recreate,
|
|
119
|
+
recreate: async (targetBranch) => {
|
|
120
|
+
const { create } = await import('./create.js');
|
|
121
|
+
await create([targetBranch, '--no-refresh']);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const container = ready.container;
|
|
125
|
+
const cmd = parsed.command;
|
|
103
126
|
if (config.tools.includes('claude-code')) {
|
|
104
127
|
try {
|
|
105
128
|
// Scan all projects so a refresh from a neighbouring sandbox can still flow back to the host.
|
|
@@ -3,6 +3,7 @@ import fs from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { runSafeEngine, runVerboseEngine } from '../shell.js';
|
|
5
5
|
import { resolveTaskBranch } from '../task-resolver.js';
|
|
6
|
+
import { isRemovedHashShortIdInput } from '../../task/short-id.js';
|
|
6
7
|
export function containerListFormat() {
|
|
7
8
|
return '{{.Names}}\t{{.Status}}\t{{.Labels}}';
|
|
8
9
|
}
|
|
@@ -70,13 +71,13 @@ export function fetchSandboxRows(engine, label, branchKey) {
|
|
|
70
71
|
}
|
|
71
72
|
/**
|
|
72
73
|
* Returns true iff `arg` is a syntactically valid task short reference.
|
|
73
|
-
* Accepts
|
|
74
|
+
* Accepts bare numeric ('11') task short ids.
|
|
74
75
|
* Zero IO. Callers MUST use this as the gate before constructing any context
|
|
75
76
|
* for resolveTaskShortRef — that way non-matching arguments (e.g. '#abc',
|
|
76
77
|
* '#1.5', '#') never trigger sandbox list IO.
|
|
77
78
|
*/
|
|
78
79
|
export function isTaskShortRef(arg) {
|
|
79
|
-
return
|
|
80
|
+
return /^\d+$/.test(arg);
|
|
80
81
|
}
|
|
81
82
|
/**
|
|
82
83
|
* Try to resolve a short ref against the global task-short-id registry.
|
|
@@ -91,9 +92,7 @@ function tryResolveFromRegistry(arg, repoRoot) {
|
|
|
91
92
|
const scriptPath = path.join(repoRoot, '.agents', 'scripts', 'task-short-id.js');
|
|
92
93
|
if (!fs.existsSync(scriptPath))
|
|
93
94
|
return { status: 'miss' };
|
|
94
|
-
//
|
|
95
|
-
// (Script accepts both forms, but this avoids shell quoting confusion in error
|
|
96
|
-
// messages echoed back to the user.)
|
|
95
|
+
// Forward the bare-numeric short ref to the registry script for ID resolution.
|
|
97
96
|
const result = spawnSync('node', [scriptPath, 'resolve', arg], { encoding: 'utf8', cwd: repoRoot });
|
|
98
97
|
if (result.status !== 0)
|
|
99
98
|
return { status: 'miss' };
|
|
@@ -120,7 +119,7 @@ function tryResolveFromRegistry(arg, repoRoot) {
|
|
|
120
119
|
}
|
|
121
120
|
/**
|
|
122
121
|
/**
|
|
123
|
-
* Resolve a task short reference
|
|
122
|
+
* Resolve a bare task short reference to a branch name for the
|
|
124
123
|
* sandbox entrypoint.
|
|
125
124
|
*
|
|
126
125
|
* Resolution: registry-only. Look up the short id in the global task-short-id
|
|
@@ -137,11 +136,11 @@ export function resolveTaskShortRef(arg, ctx) {
|
|
|
137
136
|
if (lookup.status === 'hit')
|
|
138
137
|
return lookup.branch;
|
|
139
138
|
throw new Error(`short ref '${arg}' is not in the active task registry. ` +
|
|
140
|
-
`
|
|
139
|
+
`bare N resolves only via the registry (not by row position in 'ai sandbox ls'); ` +
|
|
141
140
|
`use a task short id (e.g. 'ai sandbox exec 11'), a TASK-id, or a branch name.`);
|
|
142
141
|
}
|
|
143
142
|
/**
|
|
144
|
-
* Resolve a sandbox command argument (`<branch | TASK-id | N
|
|
143
|
+
* Resolve a sandbox command argument (`<branch | TASK-id | N>`) to a
|
|
145
144
|
* branch name, mirroring `ai sandbox exec` so that `start` and `exec` share one
|
|
146
145
|
* input contract. Short refs go through the registry-only resolver (which throws
|
|
147
146
|
* an actionable error on a miss); everything else flows through resolveTaskBranch
|
|
@@ -149,6 +148,9 @@ export function resolveTaskShortRef(arg, ctx) {
|
|
|
149
148
|
* Callers still run assertValidBranchName on the result.
|
|
150
149
|
*/
|
|
151
150
|
export function resolveBranchArg(arg, ctx) {
|
|
151
|
+
if (isRemovedHashShortIdInput(arg)) {
|
|
152
|
+
throw new Error(`Invalid task short id '${arg}': task short ids must use bare digits`);
|
|
153
|
+
}
|
|
152
154
|
return isTaskShortRef(arg)
|
|
153
155
|
? resolveTaskShortRef(arg, ctx)
|
|
154
156
|
: resolveTaskBranch(arg, ctx.repoRoot);
|
|
@@ -5,12 +5,12 @@ import { loadConfig } from '../config.js';
|
|
|
5
5
|
import { assertValidBranchName, worktreeDirCandidates } from '../constants.js';
|
|
6
6
|
import { resolveBranchArg } from './list-running.js';
|
|
7
7
|
import { resolveTools, toolConfigDirCandidates } from '../tools.js';
|
|
8
|
-
const USAGE = `Usage: ai sandbox show <branch | TASK-id | N
|
|
8
|
+
const USAGE = `Usage: ai sandbox show <branch | TASK-id | N>
|
|
9
9
|
|
|
10
10
|
Shows one sandbox's worktree path and per-tool state paths (Claude Code,
|
|
11
11
|
Codex, Gemini CLI, OpenCode). The argument follows the same contract as
|
|
12
12
|
'ai sandbox exec' and 'ai sandbox start': N (bare) is the recommended form
|
|
13
|
-
for task short ids (e.g. 'ai sandbox show 11');
|
|
13
|
+
for task short ids (e.g. 'ai sandbox show 11'); a TASK-id or a plain
|
|
14
14
|
branch name are also accepted. Use 'ai sandbox ls' for the container list.`;
|
|
15
15
|
function existingDirs(candidates) {
|
|
16
16
|
const seen = new Set();
|
|
@@ -1,36 +1,74 @@
|
|
|
1
1
|
import { loadConfig } from '../config.js';
|
|
2
2
|
import { assertValidBranchName, containerNameCandidates, sandboxBranchLabel, sandboxLabel } from '../constants.js';
|
|
3
3
|
import { detectEngine } from '../engine.js';
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import { ensureSandboxReady } from '../recovery.js';
|
|
5
|
+
import { fetchSandboxRows, resolveBranchArg, selectSandboxContainer, } from './list-running.js';
|
|
6
|
+
const USAGE = `Usage: ai sandbox start [--recreate] <branch | TASK-id | N>
|
|
6
7
|
|
|
7
8
|
Start an existing sandbox container that has stopped (for example after the
|
|
8
9
|
Docker daemon was restarted or replaced). The container must already exist:
|
|
9
10
|
if none is found, run 'ai sandbox create <branch>' first. A container that is
|
|
10
|
-
already running is
|
|
11
|
+
already running is checked without modifying healthy runtime state. --recreate
|
|
12
|
+
allows container-only replacement after in-place recovery fails.`;
|
|
13
|
+
export function parseStartArgs(args) {
|
|
14
|
+
let recreate = false;
|
|
15
|
+
let help = false;
|
|
16
|
+
const positionals = [];
|
|
17
|
+
for (const arg of args) {
|
|
18
|
+
if (arg === '--recreate') {
|
|
19
|
+
recreate = true;
|
|
20
|
+
}
|
|
21
|
+
else if (arg === '--help' || arg === '-h') {
|
|
22
|
+
help = true;
|
|
23
|
+
}
|
|
24
|
+
else if (arg.startsWith('-')) {
|
|
25
|
+
throw new Error(`Unknown option: ${arg}\n${USAGE}`);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
positionals.push(arg);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (!help && positionals.length !== 1) {
|
|
32
|
+
throw new Error(USAGE);
|
|
33
|
+
}
|
|
34
|
+
return { target: positionals[0] ?? '', recreate, help };
|
|
35
|
+
}
|
|
11
36
|
export async function start(args) {
|
|
12
|
-
if (args.length === 0
|
|
37
|
+
if (args.length === 0) {
|
|
38
|
+
process.stdout.write(`${USAGE}\n`);
|
|
39
|
+
process.exitCode = 1;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const parsed = parseStartArgs(args);
|
|
43
|
+
if (parsed.help) {
|
|
13
44
|
process.stdout.write(`${USAGE}\n`);
|
|
14
|
-
if (args.length === 0) {
|
|
15
|
-
process.exitCode = 1;
|
|
16
|
-
}
|
|
17
45
|
return;
|
|
18
46
|
}
|
|
19
|
-
const [firstArg = ''] = args;
|
|
20
47
|
const config = loadConfig();
|
|
21
48
|
const engine = detectEngine(config);
|
|
22
|
-
const branch = resolveBranchArg(
|
|
49
|
+
const branch = resolveBranchArg(parsed.target, { repoRoot: config.repoRoot });
|
|
23
50
|
assertValidBranchName(branch);
|
|
24
51
|
const { running, nonRunning } = fetchSandboxRows(engine, sandboxLabel(config), sandboxBranchLabel(config));
|
|
25
52
|
const found = selectSandboxContainer([...running, ...nonRunning], containerNameCandidates(config, branch));
|
|
26
53
|
if (!found) {
|
|
27
54
|
throw new Error(`No sandbox container for branch '${branch}'. Run 'ai sandbox create ${branch}' to create one.`);
|
|
28
55
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
56
|
+
const ready = await ensureSandboxReady({
|
|
57
|
+
config,
|
|
58
|
+
engine,
|
|
59
|
+
branch,
|
|
60
|
+
row: found,
|
|
61
|
+
allowRecreate: parsed.recreate,
|
|
62
|
+
recreate: async (targetBranch) => {
|
|
63
|
+
const { create } = await import('./create.js');
|
|
64
|
+
await create([targetBranch, '--no-refresh']);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
const message = ready.path === 'healthy'
|
|
68
|
+
? `Sandbox '${ready.container}' is already running and healthy.`
|
|
69
|
+
: ready.path === 'recreated'
|
|
70
|
+
? `Recreated sandbox '${ready.container}' and verified readiness.`
|
|
71
|
+
: `Recovered sandbox '${ready.container}' and verified readiness.`;
|
|
72
|
+
process.stdout.write(`${message}\n`);
|
|
35
73
|
}
|
|
36
74
|
//# sourceMappingURL=start.js.map
|
|
@@ -2,14 +2,14 @@ const USAGE = `Usage: ai sandbox <command> [options]
|
|
|
2
2
|
|
|
3
3
|
Commands:
|
|
4
4
|
create <branch> [base] Create a sandbox (VM + image + worktree + container)
|
|
5
|
-
exec <branch | TASK-id | N
|
|
5
|
+
exec [--recreate] <branch | TASK-id | N> [cmd...]
|
|
6
6
|
Enter sandbox or run a command. N (bare) is the
|
|
7
7
|
recommended form for task short ids (e.g.
|
|
8
|
-
'ai sandbox exec 11')
|
|
8
|
+
'ai sandbox exec 11').
|
|
9
9
|
ls List sandboxes for the current project (the '#'
|
|
10
10
|
column is a display-only row number; the 'SHORT'
|
|
11
11
|
column shows the active task short id, '-' if none)
|
|
12
|
-
show <branch | TASK-id | N
|
|
12
|
+
show <branch | TASK-id | N>
|
|
13
13
|
Show one sandbox's worktree and per-tool state paths
|
|
14
14
|
prune [--dry-run] Remove orphaned per-branch state dirs
|
|
15
15
|
rebuild [--quiet] [--refresh]
|
|
@@ -18,9 +18,9 @@ Commands:
|
|
|
18
18
|
rm <branch> | --all | --purge
|
|
19
19
|
Remove one sandbox, all sandboxes not bound to an
|
|
20
20
|
active task (--all), or tear down everything (--purge)
|
|
21
|
-
start <branch | TASK-id | N
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
start [--recreate] <branch | TASK-id | N>
|
|
22
|
+
Verify or recover an existing sandbox container;
|
|
23
|
+
optionally replace only the container on failure
|
|
24
24
|
vm status|start|stop Manage the sandbox VM (macOS) or check the backend (Windows)
|
|
25
25
|
|
|
26
26
|
Run 'ai sandbox <command> --help' for details.`;
|