@fitlab-ai/agent-infra 0.8.4 → 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 +9 -0
- package/dist/lib/git/review-snapshot.js +79 -0
- package/dist/lib/git/workflow.js +101 -0
- package/dist/lib/init.js +5 -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 +66 -26
- 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/engine.js +33 -3
- package/dist/lib/sandbox/engines/colima.js +2 -2
- 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/runtimes/base.dockerfile +4 -0
- package/dist/lib/sandbox/task-resolver.js +5 -1
- package/dist/lib/sandbox/tools.js +19 -0
- package/dist/lib/server/daemon.js +9 -0
- package/dist/lib/server/process-control.js +66 -73
- package/dist/lib/server/process-state.js +168 -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/dist/lib/update.js +2 -0
- package/lib/decide.ts +57 -97
- package/lib/defaults.json +9 -0
- package/lib/git/review-snapshot.ts +73 -0
- package/lib/git/workflow.ts +101 -0
- package/lib/init.ts +9 -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/{templates/.agents/scripts/platform-adapters/platform-sync.github.js → lib/platform/verification-sync.ts} +221 -363
- 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 +75 -28
- 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/engine.ts +37 -3
- package/lib/sandbox/engines/colima.ts +2 -2
- package/lib/sandbox/index.ts +6 -6
- package/lib/sandbox/mounts.ts +55 -0
- package/lib/sandbox/recovery.ts +828 -0
- package/lib/sandbox/runtimes/base.dockerfile +4 -0
- package/lib/sandbox/task-resolver.ts +5 -1
- package/lib/sandbox/tools.ts +31 -0
- package/lib/server/daemon.ts +9 -0
- package/lib/server/process-control.ts +70 -71
- package/lib/server/process-state.ts +183 -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} +20 -10
- 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} +257 -451
- 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/lib/update.ts +6 -0
- package/package.json +5 -2
- package/templates/.agents/README.en.md +6 -3
- package/templates/.agents/README.zh-CN.md +6 -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 +13 -9
- package/templates/.agents/rules/review-handshake.zh-CN.md +13 -9
- 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 +141 -0
- 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 +18 -14
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +18 -14
- 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 +42 -2
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +42 -2
- 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 -6
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +11 -6
- 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/init-milestones/SKILL.en.md +2 -2
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +5 -4
- 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 +5 -5
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +5 -5
- 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 +12 -4
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +12 -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 +6 -3
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +6 -3
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +177 -151
- 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.js +0 -13
- package/templates/.agents/scripts/review-diff-fingerprint.js +0 -99
- 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';
|
|
@@ -47,13 +49,27 @@ alias gy='gemini --yolo; tput ed'
|
|
|
47
49
|
`;
|
|
48
50
|
const CONTAINER_HOME = '/home/devuser';
|
|
49
51
|
const CONTAINER_SHELL_CONFIG_MOUNT = `${CONTAINER_HOME}/.host-shell-config`;
|
|
50
|
-
const USAGE = `Usage: ai sandbox create <branch> [base] [--cpu <n>] [--memory <n>] [--no-refresh]
|
|
52
|
+
const USAGE = `Usage: ai sandbox create <branch> [base] [--cpu <n>] [--memory <n>] [--no-refresh] [--inherit-proxy|-P]
|
|
51
53
|
|
|
52
54
|
Host aliases:
|
|
53
55
|
${'~'}/.agent-infra/aliases/sandbox.sh is auto-created on first run and exposed
|
|
54
56
|
as ${CONTAINER_HOME}/.bash_aliases inside the sandbox container (the host
|
|
55
57
|
shell-config directory is bind-mounted at ${CONTAINER_SHELL_CONFIG_MOUNT} and
|
|
56
|
-
symlinked into $HOME)
|
|
58
|
+
symlinked into $HOME).
|
|
59
|
+
|
|
60
|
+
Proxy:
|
|
61
|
+
--inherit-proxy, -P Copy non-empty standard host proxy variables into the
|
|
62
|
+
container environment through the private env file.`;
|
|
63
|
+
const HOST_PROXY_ENV_KEYS = [
|
|
64
|
+
'http_proxy',
|
|
65
|
+
'HTTP_PROXY',
|
|
66
|
+
'https_proxy',
|
|
67
|
+
'HTTPS_PROXY',
|
|
68
|
+
'all_proxy',
|
|
69
|
+
'ALL_PROXY',
|
|
70
|
+
'no_proxy',
|
|
71
|
+
'NO_PROXY'
|
|
72
|
+
];
|
|
57
73
|
function resolveToolDirs(config, tools, branch) {
|
|
58
74
|
return tools.map((tool) => {
|
|
59
75
|
const candidates = toolConfigDirCandidates(tool, config.project, branch);
|
|
@@ -425,9 +441,17 @@ function formatEnvFileEntry(key, value) {
|
|
|
425
441
|
}
|
|
426
442
|
return `${key}=${value}`;
|
|
427
443
|
}
|
|
444
|
+
export function collectHostProxyEntries(env) {
|
|
445
|
+
const entriesByExactKey = new Map(Object.entries(env));
|
|
446
|
+
return HOST_PROXY_ENV_KEYS.flatMap((key) => {
|
|
447
|
+
const value = entriesByExactKey.get(key);
|
|
448
|
+
return typeof value === 'string' && value !== '' ? [[key, value]] : [];
|
|
449
|
+
});
|
|
450
|
+
}
|
|
428
451
|
export function buildContainerEnvFile(resolvedTools, engine, runSafeEngineFn = runSafeEngine, options = {}) {
|
|
429
|
-
const { mkdtempFn = fs.mkdtempSync, writeFileFn = fs.writeFileSync, chmodFn = fs.chmodSync, rmFn = fs.rmSync, tmpDir = os.tmpdir(), runSafeFn = runSafe } = options;
|
|
452
|
+
const { additionalEntries = [], mkdtempFn = fs.mkdtempSync, writeFileFn = fs.writeFileSync, chmodFn = fs.chmodSync, rmFn = fs.rmSync, tmpDir = os.tmpdir(), runSafeFn = runSafe } = options;
|
|
430
453
|
const entries = resolvedTools.flatMap(({ tool }) => Object.entries(tool.envVars ?? {}));
|
|
454
|
+
entries.push(...additionalEntries);
|
|
431
455
|
let ghToken = runSafeEngineFn(engine, 'gh', ['auth', 'token']);
|
|
432
456
|
if (!ghToken && engine === 'wsl2') {
|
|
433
457
|
ghToken = runSafeFn('gh', ['auth', 'token']);
|
|
@@ -933,6 +957,7 @@ export async function create(args) {
|
|
|
933
957
|
cpu: { type: 'string' },
|
|
934
958
|
memory: { type: 'string' },
|
|
935
959
|
'no-refresh': { type: 'boolean' },
|
|
960
|
+
'inherit-proxy': { type: 'boolean', short: 'P' },
|
|
936
961
|
help: { type: 'boolean', short: 'h' }
|
|
937
962
|
}
|
|
938
963
|
});
|
|
@@ -976,6 +1001,7 @@ export async function create(args) {
|
|
|
976
1001
|
const baseBranch = base ?? runSafe('git', ['-C', effectiveConfig.repoRoot, 'branch', '--show-current']);
|
|
977
1002
|
const expectedImageSignature = buildImageSignature(preparedDockerfile, tools);
|
|
978
1003
|
const engine = detectEngine(effectiveConfig);
|
|
1004
|
+
let createdTmpfsSeedPlan = [];
|
|
979
1005
|
p.intro(pc.cyan('AI Sandbox'));
|
|
980
1006
|
p.log.info(`Project: ${pc.bold(effectiveConfig.project)} | Branch: ${pc.bold(branch)} | Base: ${pc.bold(baseBranch || 'HEAD')}`);
|
|
981
1007
|
if (credentialOutcome.status === 'SKIPPED') {
|
|
@@ -1148,7 +1174,10 @@ export async function create(args) {
|
|
|
1148
1174
|
const cachedGpg = needsGpg
|
|
1149
1175
|
? readGpgCache(effectiveConfig.home, effectiveConfig.project, undefined, signingKey)
|
|
1150
1176
|
: null;
|
|
1151
|
-
const
|
|
1177
|
+
const proxyEntries = values['inherit-proxy'] ? collectHostProxyEntries(process.env) : [];
|
|
1178
|
+
const envFile = buildContainerEnvFile(effectiveResolvedTools, engine, undefined, {
|
|
1179
|
+
additionalEntries: proxyEntries
|
|
1180
|
+
});
|
|
1152
1181
|
let hostShellConfig;
|
|
1153
1182
|
let tmpfsSeedPlan = [];
|
|
1154
1183
|
try {
|
|
@@ -1183,9 +1212,12 @@ export async function create(args) {
|
|
|
1183
1212
|
branch,
|
|
1184
1213
|
repoRoot: effectiveConfig.repoRoot
|
|
1185
1214
|
});
|
|
1186
|
-
const
|
|
1215
|
+
const coreVolumes = sandboxCoreBindMounts(effectiveConfig, branch, {
|
|
1216
|
+
worktree,
|
|
1217
|
+
shellConfigHostDir: hostShellConfig.hostDir
|
|
1218
|
+
}).flatMap(({ hostPaths, containerPath, readOnly }) => [
|
|
1187
1219
|
'-v',
|
|
1188
|
-
volumeArg(engine,
|
|
1220
|
+
volumeArg(engine, hostPaths[0], containerPath, readOnly ? ':ro' : '')
|
|
1189
1221
|
]);
|
|
1190
1222
|
// Mount each declared seed read-only at an isolated staging path.
|
|
1191
1223
|
// After docker run mounts the empty tmpfs, the container's default
|
|
@@ -1194,14 +1226,17 @@ export async function create(args) {
|
|
|
1194
1226
|
// stale runtime files (logs_2.sqlite, sessions, etc.) on the host from
|
|
1195
1227
|
// being exposed or written through.
|
|
1196
1228
|
tmpfsSeedPlan = effectiveResolvedTools.flatMap(({ tool, dir }) => (tool.tmpfs?.seed ?? []).flatMap((entry, index) => {
|
|
1229
|
+
const targetPath = tmpfsSeedTargetPath(tool.containerMount, entry);
|
|
1197
1230
|
const hostPath = path.join(dir, entry);
|
|
1198
1231
|
if (!fs.existsSync(hostPath)) {
|
|
1199
1232
|
return [];
|
|
1200
1233
|
}
|
|
1201
|
-
const stagingPath =
|
|
1234
|
+
const stagingPath = tmpfsSeedStagingPath(tool.id, index);
|
|
1202
1235
|
return [{
|
|
1236
|
+
toolId: tool.id,
|
|
1237
|
+
containerMount: tool.containerMount,
|
|
1203
1238
|
stagingPath,
|
|
1204
|
-
targetPath
|
|
1239
|
+
targetPath,
|
|
1205
1240
|
volumeArgs: ['-v', volumeArg(engine, hostPath, stagingPath, ':ro')]
|
|
1206
1241
|
}];
|
|
1207
1242
|
}));
|
|
@@ -1232,14 +1267,7 @@ export async function create(args) {
|
|
|
1232
1267
|
sandboxLabel(effectiveConfig),
|
|
1233
1268
|
'--label',
|
|
1234
1269
|
`${sandboxBranchLabel(effectiveConfig)}=${branch}`,
|
|
1235
|
-
|
|
1236
|
-
volumeArg(engine, worktree, '/workspace'),
|
|
1237
|
-
'-v',
|
|
1238
|
-
volumeArg(engine, workspaceDir, '/workspace/.agents/workspace'),
|
|
1239
|
-
'-v',
|
|
1240
|
-
volumeArg(engine, shareCommon, '/share/common'),
|
|
1241
|
-
'-v',
|
|
1242
|
-
volumeArg(engine, shareBranch, '/share/branch'),
|
|
1270
|
+
...coreVolumes,
|
|
1243
1271
|
...buildClipboardVolumeArgs(engine, effectiveConfig.home),
|
|
1244
1272
|
'-v',
|
|
1245
1273
|
volumeArg(engine, path.join(effectiveConfig.repoRoot, '.git'), `${toEnginePath(engine, effectiveConfig.repoRoot)}/.git`),
|
|
@@ -1248,25 +1276,30 @@ export async function create(args) {
|
|
|
1248
1276
|
...tmpfsArgs,
|
|
1249
1277
|
...tmpfsSeedPlan.flatMap(({ volumeArgs }) => volumeArgs),
|
|
1250
1278
|
...liveMountVolumes,
|
|
1251
|
-
...shellConfigVolumes,
|
|
1252
1279
|
...envFile.dockerArgs,
|
|
1253
1280
|
...tzFlags,
|
|
1254
1281
|
'-w',
|
|
1255
1282
|
'/workspace',
|
|
1256
1283
|
effectiveConfig.imageName
|
|
1257
1284
|
]);
|
|
1285
|
+
createdTmpfsSeedPlan = tmpfsSeedPlan;
|
|
1258
1286
|
}
|
|
1259
1287
|
finally {
|
|
1260
1288
|
envFile.cleanup();
|
|
1261
1289
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
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
|
+
});
|
|
1270
1303
|
// Belt-and-suspenders: re-create the four shell-config symlinks at
|
|
1271
1304
|
// runtime so users with a custom `sandbox.dockerfile` (which won't
|
|
1272
1305
|
// include the ai-tools.dockerfile symlink fragment) still get
|
|
@@ -1320,6 +1353,13 @@ export async function create(args) {
|
|
|
1320
1353
|
preparedDockerfile.cleanup();
|
|
1321
1354
|
}
|
|
1322
1355
|
p.log.step('Verifying setup...');
|
|
1356
|
+
assertFreshSandboxReady({
|
|
1357
|
+
config: effectiveConfig,
|
|
1358
|
+
engine,
|
|
1359
|
+
branch,
|
|
1360
|
+
container,
|
|
1361
|
+
copiedEntries: createdTmpfsSeedPlan
|
|
1362
|
+
});
|
|
1323
1363
|
const runningContainers = runSafeEngine(engine, 'docker', ['ps', '--format', '{{.Names}}']).split('\n');
|
|
1324
1364
|
const checks = [
|
|
1325
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();
|