@fitlab-ai/agent-infra 0.9.14 → 0.10.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/README.md +10 -0
- package/README.zh-CN.md +10 -0
- package/bin/internal-cli.sh +45 -0
- package/dist/bin/internal-cli.js +93 -30
- package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +9 -4
- package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +43 -3
- package/dist/lib/defaults.json +103 -103
- package/dist/lib/fs/durable-write.js +39 -0
- package/dist/lib/fs/file-lock.js +111 -0
- package/dist/lib/host-control/audit.js +19 -0
- package/dist/lib/host-control/client.js +142 -0
- package/dist/lib/host-control/command.js +49 -0
- package/dist/lib/host-control/path.js +160 -0
- package/dist/lib/host-control/secure-fs.js +140 -0
- package/dist/lib/host-control/server.js +159 -0
- package/dist/lib/host-control/service.js +112 -0
- package/dist/lib/init.js +11 -2
- package/dist/lib/internal/cli-route-inventory.js +4 -2
- package/dist/lib/internal/codex-lifecycle.js +6 -6
- package/dist/lib/internal/demo-promotion.js +322 -0
- package/dist/lib/internal/demo-transcript.js +454 -0
- package/dist/lib/internal/host-control.js +28 -0
- package/dist/lib/internal/manual-validation.js +331 -0
- package/dist/lib/internal/platform-pr.js +18 -4
- package/dist/lib/internal/release-workflow.js +63 -84
- package/dist/lib/internal/sandbox-control.js +149 -2
- package/dist/lib/internal/task-artifact.js +16 -263
- package/dist/lib/internal/task-create.js +6 -5
- package/dist/lib/internal/task-event.js +37 -37
- package/dist/lib/internal/task-lifecycle.js +2 -2
- package/dist/lib/internal/task-operation-registry.js +101 -4
- package/dist/lib/internal/task-review.js +11 -56
- package/dist/lib/internal/task-validate.js +30 -10
- package/dist/lib/owned-path.js +33 -0
- package/dist/lib/platform/check-status.js +11 -0
- package/dist/lib/platform/comment-safety.js +4 -1
- package/dist/lib/platform/completion-backfill.js +1 -1
- package/dist/lib/platform/github-data.js +241 -0
- package/dist/lib/platform/github-provider.js +15 -20
- package/dist/lib/platform/issue-comments.js +18 -12
- package/dist/lib/platform/issues.js +2 -180
- package/dist/lib/platform/pr-change-report.js +5 -4
- package/dist/lib/platform/pr-checks.js +12 -65
- package/dist/lib/platform/pr-summary.js +117 -33
- package/dist/lib/platform/pull-requests.js +5 -108
- package/dist/lib/platform/snapshots.js +2 -0
- package/dist/lib/platform/task-identities.js +2 -9
- package/dist/lib/platform/verification-sync.js +132 -143
- package/dist/lib/pr-review/evidence-grading.js +4 -8
- package/dist/lib/release/workflow.js +1 -1
- package/dist/lib/sandbox/commands/create.js +7 -2
- package/dist/lib/sandbox/commands/rm.js +19 -1511
- package/dist/lib/sandbox/control/audit.js +203 -0
- package/dist/lib/sandbox/control/client.js +93 -54
- package/dist/lib/sandbox/control/executor.js +129 -65
- package/dist/lib/sandbox/control/finalization-response.js +27 -0
- package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
- package/dist/lib/sandbox/control/lifecycle.js +36 -2
- package/dist/lib/sandbox/control/native-file-lock.js +6 -98
- package/dist/lib/sandbox/control/protocol.js +55 -4
- package/dist/lib/sandbox/control/server.js +518 -127
- package/dist/lib/sandbox/control/state.js +64 -0
- package/dist/lib/sandbox/control/task-workflow.js +74 -0
- package/dist/lib/sandbox/control/workflow-executor.js +89 -0
- package/dist/lib/sandbox/index.js +1 -2
- package/dist/lib/sandbox/recovery.js +28 -4
- package/dist/lib/sandbox/removal.js +822 -0
- package/dist/lib/sandbox/task-cleanup.js +217 -0
- package/dist/lib/sandbox/workspace-identity.js +17 -1
- package/dist/lib/sandbox/workspace-view.js +13 -14
- package/dist/lib/task/activity-intent.js +2 -1
- package/dist/lib/task/activity-log.js +30 -24
- package/dist/lib/task/artifact-command.js +79 -0
- package/dist/lib/task/artifact-lifecycle.js +30 -28
- package/dist/lib/task/artifact-name.js +36 -0
- package/dist/lib/task/artifact-operations.js +29 -289
- package/dist/lib/task/artifact-receipts.js +3 -15
- package/dist/lib/task/artifact-recovery.js +430 -0
- package/dist/lib/task/artifact-repair-intent.js +134 -29
- package/dist/lib/task/artifact-schema.js +6 -14
- package/dist/lib/task/capabilities.js +12 -19
- package/dist/lib/task/codex-orchestration.js +71 -25
- package/dist/lib/task/commit-identity.js +28 -0
- package/dist/lib/task/commit-operation.js +33 -20
- package/dist/lib/task/control-authority.js +403 -6
- package/dist/lib/task/control-recovery.js +140 -0
- package/dist/lib/task/create-service.js +1 -8
- package/dist/lib/task/create.js +62 -9
- package/dist/lib/task/decision-details.js +2 -46
- package/dist/lib/task/delegation-receipts.js +64 -3
- package/dist/lib/task/events.js +275 -22
- package/dist/lib/task/finalization-state.js +9 -0
- package/dist/lib/task/human-override.js +8 -14
- package/dist/lib/task/implementation-inputs.js +3 -3
- package/dist/lib/task/intermediate-cleanup.js +441 -0
- package/dist/lib/task/invalidation.js +18 -65
- package/dist/lib/task/ledger-intents.js +7 -22
- package/dist/lib/task/ledger.js +1 -3
- package/dist/lib/task/lifecycle-recovery.js +549 -0
- package/dist/lib/task/lifecycle.js +31 -4
- package/dist/lib/task/local-artifact-finalization.js +197 -197
- package/dist/lib/task/manual-validation-completion.js +26 -0
- package/dist/lib/task/manual-validation-evidence.js +130 -0
- package/dist/lib/task/manual-validation-receipt.js +105 -0
- package/dist/lib/task/manual-validation-shared.js +40 -0
- package/dist/lib/task/manual-validation-transaction.js +243 -0
- package/dist/lib/task/markdown.js +47 -0
- package/dist/lib/task/orchestration.js +66 -19
- package/dist/lib/task/pr-delivery-fact.js +12 -56
- package/dist/lib/task/qualification-audit.js +20 -34
- package/dist/lib/task/recovery-warning.js +19 -0
- package/dist/lib/task/review-artifacts.js +2 -18
- package/dist/lib/task/review-command.js +26 -0
- package/dist/lib/task/review-finalization.js +175 -216
- package/dist/lib/task/review-fingerprint.js +2 -2
- package/dist/lib/task/sections.js +34 -56
- package/dist/lib/task/short-id.js +15 -7
- package/dist/lib/task/task-execution-lock.js +1 -1
- package/dist/lib/task/verification-engine.js +119 -337
- package/dist/lib/task/verification.js +1 -1
- package/dist/lib/task/workflow-command.js +16 -0
- package/dist/lib/task/workflow-warning-intents.js +0 -16
- package/dist/lib/task/workflow-warnings.js +28 -2
- package/dist/lib/update.js +2 -0
- package/dist/lib/version.js +1 -11
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +10 -4
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +55 -3
- package/lib/fs/durable-write.ts +30 -0
- package/lib/fs/file-lock.ts +113 -0
- package/lib/host-control/audit.ts +22 -0
- package/lib/host-control/client.ts +172 -0
- package/lib/host-control/command.ts +60 -0
- package/lib/host-control/path.ts +167 -0
- package/lib/host-control/secure-fs.ts +135 -0
- package/lib/host-control/server.ts +180 -0
- package/lib/host-control/service.ts +133 -0
- package/lib/init.ts +15 -2
- package/lib/internal/cli-route-inventory.ts +4 -2
- package/lib/internal/codex-lifecycle.ts +6 -6
- package/lib/internal/demo-promotion.ts +354 -0
- package/lib/internal/demo-transcript.ts +419 -0
- package/lib/internal/host-control.ts +28 -0
- package/lib/internal/manual-validation.ts +315 -0
- package/lib/internal/platform-pr.ts +15 -4
- package/lib/internal/release-workflow.ts +74 -82
- package/lib/internal/sandbox-control.ts +162 -1
- package/lib/internal/task-artifact.ts +14 -217
- package/lib/internal/task-create.ts +5 -5
- package/lib/internal/task-event.ts +20 -11
- package/lib/internal/task-lifecycle.ts +4 -3
- package/lib/internal/task-operation-registry.ts +111 -4
- package/lib/internal/task-review.ts +9 -54
- package/lib/internal/task-validate.ts +26 -10
- package/lib/owned-path.ts +26 -0
- package/lib/platform/check-status.ts +9 -0
- package/lib/platform/comment-safety.ts +5 -0
- package/lib/platform/completion-backfill.ts +1 -1
- package/lib/platform/github-data.ts +322 -0
- package/lib/platform/github-provider.ts +15 -20
- package/lib/platform/issue-comments.ts +21 -14
- package/lib/platform/issues.ts +5 -246
- package/lib/platform/pr-change-report.ts +7 -5
- package/lib/platform/pr-checks.ts +13 -77
- package/lib/platform/pr-summary.ts +123 -35
- package/lib/platform/pull-requests.ts +6 -173
- package/lib/platform/snapshots.ts +53 -0
- package/lib/platform/task-identities.ts +3 -14
- package/lib/platform/verification-sync.ts +150 -156
- package/lib/pr-review/evidence-grading.ts +4 -9
- package/lib/release/workflow.ts +3 -3
- package/lib/sandbox/commands/create.ts +7 -6
- package/lib/sandbox/commands/rm.ts +21 -1895
- package/lib/sandbox/control/audit.ts +253 -0
- package/lib/sandbox/control/client.ts +109 -66
- package/lib/sandbox/control/executor.ts +134 -74
- package/lib/sandbox/control/finalization-response.ts +29 -0
- package/lib/sandbox/control/identity-sentinel.ts +137 -0
- package/lib/sandbox/control/lifecycle.ts +45 -3
- package/lib/sandbox/control/native-file-lock.ts +6 -107
- package/lib/sandbox/control/protocol.ts +80 -6
- package/lib/sandbox/control/server.ts +567 -132
- package/lib/sandbox/control/state.ts +86 -0
- package/lib/sandbox/control/task-workflow.ts +95 -0
- package/lib/sandbox/control/workflow-executor.ts +92 -0
- package/lib/sandbox/index.ts +1 -2
- package/lib/sandbox/recovery.ts +28 -5
- package/lib/sandbox/removal.ts +1142 -0
- package/lib/sandbox/task-cleanup.ts +209 -0
- package/lib/sandbox/workspace-identity.ts +19 -3
- package/lib/sandbox/workspace-view.ts +17 -15
- package/lib/task/activity-intent.ts +2 -2
- package/lib/task/activity-log.ts +27 -19
- package/lib/task/artifact-command.ts +85 -0
- package/lib/task/artifact-lifecycle.ts +31 -26
- package/lib/task/artifact-name.ts +55 -0
- package/lib/task/artifact-operations.ts +34 -310
- package/lib/task/artifact-receipts.ts +3 -14
- package/lib/task/artifact-recovery.ts +519 -0
- package/lib/task/artifact-repair-intent.ts +162 -33
- package/lib/task/artifact-schema.ts +5 -34
- package/lib/task/capabilities.ts +13 -22
- package/lib/task/codex-orchestration.ts +85 -24
- package/lib/task/commit-identity.ts +31 -0
- package/lib/task/commit-operation.ts +37 -20
- package/lib/task/control-authority.ts +540 -10
- package/lib/task/control-recovery.ts +186 -0
- package/lib/task/create-service.ts +1 -10
- package/lib/task/create.ts +63 -8
- package/lib/task/decision-details.ts +3 -71
- package/lib/task/delegation-receipts.ts +73 -2
- package/lib/task/events.ts +309 -24
- package/lib/task/finalization-state.ts +11 -0
- package/lib/task/human-override.ts +8 -16
- package/lib/task/implementation-inputs.ts +3 -3
- package/lib/task/intermediate-cleanup.ts +493 -0
- package/lib/task/invalidation.ts +18 -62
- package/lib/task/ledger-intents.ts +7 -24
- package/lib/task/ledger.ts +1 -3
- package/lib/task/lifecycle-recovery.ts +691 -0
- package/lib/task/lifecycle.ts +30 -5
- package/lib/task/local-artifact-finalization.ts +244 -234
- package/lib/task/manual-validation-completion.ts +40 -0
- package/lib/task/manual-validation-evidence.ts +209 -0
- package/lib/task/manual-validation-receipt.ts +156 -0
- package/lib/task/manual-validation-shared.ts +50 -0
- package/lib/task/manual-validation-transaction.ts +304 -0
- package/lib/task/markdown.ts +70 -0
- package/lib/task/orchestration.ts +84 -19
- package/lib/task/pr-delivery-fact.ts +15 -62
- package/lib/task/qualification-audit.ts +22 -33
- package/lib/task/recovery-warning.ts +21 -0
- package/lib/task/review-artifacts.ts +1 -20
- package/lib/task/review-command.ts +24 -0
- package/lib/task/review-finalization.ts +183 -292
- package/lib/task/review-fingerprint.ts +2 -2
- package/lib/task/sections.ts +33 -54
- package/lib/task/short-id.ts +27 -5
- package/lib/task/task-execution-lock.ts +1 -1
- package/lib/task/verification-engine.ts +113 -383
- package/lib/task/verification-types.ts +15 -0
- package/lib/task/verification.ts +1 -1
- package/lib/task/workflow-command.ts +17 -0
- package/lib/task/workflow-warning-intents.ts +0 -13
- package/lib/task/workflow-warnings.ts +21 -2
- package/lib/update.ts +6 -0
- package/lib/version.ts +1 -15
- package/package.json +6 -6
- package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
- package/templates/.agents/rules/create-issue.en.md +1 -1
- package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.en.md +4 -2
- package/templates/.agents/rules/issue-sync.zh-CN.md +4 -3
- package/templates/.agents/rules/local-artifact-repair.en.md +46 -39
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +43 -36
- package/templates/.agents/rules/testing-discipline.en.md +2 -0
- package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
- package/templates/.agents/scripts/package.json +3 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +6 -6
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +6 -6
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -1
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/block-task/config/verify.json +1 -1
- package/templates/.agents/skills/cancel-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/cancel-task/config/verify.json +1 -1
- package/templates/.agents/skills/code-task/SKILL.en.md +7 -7
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +7 -7
- package/templates/.agents/skills/code-task/config/verify.en.json +1 -1
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +33 -21
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +33 -21
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
- package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +1 -1
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/config/verify.json +1 -1
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +2 -2
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +2 -2
- package/templates/.agents/skills/create-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/create-task/config/verify.json +1 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +8 -8
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/import-issue/config/verify.json +2 -2
- package/templates/.agents/skills/plan-task/SKILL.en.md +4 -4
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/plan-task/config/verify.en.json +1 -1
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/release/SKILL.en.md +7 -3
- package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
- package/templates/.agents/skills/restore-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/restore-task/config/verify.json +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +2 -2
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +7 -7
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +6 -6
- package/templates/.agents/skills/review-code/SKILL.en.md +2 -2
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-code/reference/report-template.en.md +12 -12
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +12 -12
- package/templates/.agents/skills/review-plan/SKILL.en.md +2 -2
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +7 -7
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +7 -7
- package/templates/.agents/skills/review-pr/config/verify.en.json +1 -1
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +3 -3
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +3 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +20 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +20 -3
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +1 -1
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/test/SKILL.en.md +17 -6
- package/templates/.agents/skills/test/SKILL.zh-CN.md +17 -6
- package/templates/.agents/templates/task.en.md +1 -1
- package/templates/.agents/templates/task.zh-CN.md +1 -1
- package/templates/.claude/commands/import-issue.en.md +1 -1
- package/templates/.claude/commands/import-issue.zh-CN.md +1 -1
- package/templates/.claude/commands/restore-task.en.md +1 -1
- package/templates/.claude/commands/restore-task.zh-CN.md +1 -1
- package/templates/.claude/commands/run-manual-validation.en.md +1 -1
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
- package/dist/lib/platform/adapters.js +0 -56
- package/lib/platform/adapters.ts +0 -197
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { isCompletionEvidence } from '../../task/orchestration.js';
|
|
2
|
+
import { parseControlOutput } from '../../task/control-recovery.js';
|
|
3
|
+
import { isRecoveryWarning } from '../../task/recovery-warning.js';
|
|
1
4
|
import { execFileSync } from 'node:child_process';
|
|
2
5
|
import fs from 'node:fs';
|
|
3
6
|
import path from 'node:path';
|
|
@@ -70,6 +73,67 @@ export function reservationPath(manifest, requestId) {
|
|
|
70
73
|
throw new Error('SANDBOX_CONTROL_RESERVATION_INVALID');
|
|
71
74
|
return path.join(manifest.processingDir, requestId, 'reservation.json');
|
|
72
75
|
}
|
|
76
|
+
export function terminalResultPath(manifest, requestId) {
|
|
77
|
+
if (!/^[a-f0-9-]{16,64}$/u.test(requestId))
|
|
78
|
+
throw new Error('SANDBOX_CONTROL_TERMINAL_RESULT_INVALID');
|
|
79
|
+
return path.join(manifest.processingDir, requestId, 'terminal-result.json');
|
|
80
|
+
}
|
|
81
|
+
export function createSandboxControlTerminalResult(manifest, request, output) {
|
|
82
|
+
const nested = parseControlOutput(output) ?? {};
|
|
83
|
+
const run = nested.run && typeof nested.run === 'object' && !Array.isArray(nested.run)
|
|
84
|
+
? nested.run : null;
|
|
85
|
+
const rawCompletion = nested.completionEvidence ?? run?.completionEvidence;
|
|
86
|
+
const operation = request.operation ?? (typeof nested.intent === 'string' ? nested.intent : null) ?? '';
|
|
87
|
+
const warning = isRecoveryWarning(nested.warning) ? nested.warning : null;
|
|
88
|
+
return {
|
|
89
|
+
version: 1,
|
|
90
|
+
requestId: request.id,
|
|
91
|
+
generation: manifest.generation,
|
|
92
|
+
taskId: manifest.taskId,
|
|
93
|
+
intentDigest: createHash('sha256').update(`${request.family}\0${operation}`, 'utf8').digest('hex'),
|
|
94
|
+
targetState: typeof nested.targetState === 'string' ? nested.targetState : null,
|
|
95
|
+
status: typeof nested.status === 'string' ? nested.status : 'completed',
|
|
96
|
+
changed: typeof nested.changed === 'boolean' ? nested.changed : null,
|
|
97
|
+
completionEvidence: isCompletionEvidence(rawCompletion) ? rawCompletion : null,
|
|
98
|
+
...(warning ? { warning } : {})
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export function writeSandboxControlTerminalResult(manifest, request, output) {
|
|
102
|
+
const result = createSandboxControlTerminalResult(manifest, request, output);
|
|
103
|
+
const filePath = terminalResultPath(manifest, request.id);
|
|
104
|
+
try {
|
|
105
|
+
atomicWriteJsonNoReplace(filePath, result);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (!(error instanceof Error) || error.message !== 'SANDBOX_CONTROL_TERMINAL_ALREADY_EXISTS')
|
|
109
|
+
throw error;
|
|
110
|
+
const existing = readSandboxControlTerminalResult(filePath);
|
|
111
|
+
if (JSON.stringify(existing) !== JSON.stringify(result))
|
|
112
|
+
throw new Error('SANDBOX_CONTROL_TERMINAL_RESULT_CONFLICT');
|
|
113
|
+
}
|
|
114
|
+
return readSandboxControlTerminalResult(filePath);
|
|
115
|
+
}
|
|
116
|
+
export function readSandboxControlTerminalResult(filePath) {
|
|
117
|
+
const value = readJsonFile(filePath);
|
|
118
|
+
if (!value || value.version !== 1 || typeof value.requestId !== 'string'
|
|
119
|
+
|| typeof value.generation !== 'string' || (value.taskId !== null && typeof value.taskId !== 'string')
|
|
120
|
+
|| typeof value.intentDigest !== 'string' || !/^[a-f0-9]{64}$/u.test(value.intentDigest)
|
|
121
|
+
|| (value.targetState !== null && typeof value.targetState !== 'string')
|
|
122
|
+
|| typeof value.status !== 'string'
|
|
123
|
+
|| (value.changed !== null && typeof value.changed !== 'boolean')) {
|
|
124
|
+
throw new Error('SANDBOX_CONTROL_TERMINAL_RESULT_INVALID');
|
|
125
|
+
}
|
|
126
|
+
if (value.completionEvidence !== null && !isCompletionEvidence(value.completionEvidence)) {
|
|
127
|
+
throw new Error('SANDBOX_CONTROL_TERMINAL_RESULT_INVALID');
|
|
128
|
+
}
|
|
129
|
+
if (value.warning !== undefined && value.warning !== null && !isRecoveryWarning(value.warning)) {
|
|
130
|
+
throw new Error('SANDBOX_CONTROL_TERMINAL_RESULT_INVALID');
|
|
131
|
+
}
|
|
132
|
+
if (value.changed === undefined) {
|
|
133
|
+
throw new Error('SANDBOX_CONTROL_TERMINAL_RESULT_INVALID');
|
|
134
|
+
}
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
73
137
|
export function readSandboxControlResultEvidence(filePath) {
|
|
74
138
|
assertRegularFile(filePath);
|
|
75
139
|
const raw = fs.readFileSync(filePath, 'utf8');
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
4
|
+
import { readStableFile, SecureFileError, writeAtomicFile } from '../../host-control/secure-fs.js';
|
|
5
|
+
import { TASK_WORKFLOW_COMMANDS, TASK_WORKFLOW_OPERATIONS } from '../../task/workflow-command.js';
|
|
6
|
+
export function validateTaskWorkflowRequest(value) {
|
|
7
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
8
|
+
throw new Error('TASK_WORKFLOW_REQUEST_INVALID');
|
|
9
|
+
const request = value;
|
|
10
|
+
if (Object.keys(request).sort().join(',') !== 'args,generation,id,operation,taskId,version'
|
|
11
|
+
|| request.version !== 1 || typeof request.id !== 'string' || !/^[a-f0-9-]{16,64}$/u.test(request.id)
|
|
12
|
+
|| typeof request.taskId !== 'string' || !/^TASK-\d{8}-\d{6}$/u.test(request.taskId)
|
|
13
|
+
|| typeof request.generation !== 'string' || !request.generation
|
|
14
|
+
|| !Object.hasOwn(TASK_WORKFLOW_COMMANDS, request.operation)
|
|
15
|
+
|| !Array.isArray(request.args) || request.args.length < 2 || request.args.length > 128
|
|
16
|
+
|| !request.args.every((arg) => typeof arg === 'string' && !/[\r\n]/u.test(arg))
|
|
17
|
+
|| request.args[0] !== request.taskId)
|
|
18
|
+
throw new Error('TASK_WORKFLOW_REQUEST_INVALID');
|
|
19
|
+
const [, selector] = TASK_WORKFLOW_COMMANDS[request.operation];
|
|
20
|
+
if (selector !== null && request.args[1] !== selector)
|
|
21
|
+
throw new Error('TASK_WORKFLOW_REQUEST_INVALID');
|
|
22
|
+
return request;
|
|
23
|
+
}
|
|
24
|
+
/** Preserve argv verbatim; the domain command owns option parsing and validation. */
|
|
25
|
+
export function createTaskWorkflowRequest(command, args, taskId, generation) {
|
|
26
|
+
const operation = TASK_WORKFLOW_OPERATIONS.find((key) => {
|
|
27
|
+
const [name, selector] = TASK_WORKFLOW_COMMANDS[key];
|
|
28
|
+
return name === command && (selector === null || selector === args[1]);
|
|
29
|
+
});
|
|
30
|
+
if (!operation)
|
|
31
|
+
throw new Error('TASK_WORKFLOW_OPERATION_UNSUPPORTED');
|
|
32
|
+
return validateTaskWorkflowRequest({ version: 1, id: randomUUID(), taskId, generation, operation, args: [...args] });
|
|
33
|
+
}
|
|
34
|
+
export function canonicalArtifactName(value) {
|
|
35
|
+
return /^(?:analysis|plan|code|review-analysis|review-plan|review-code)(?:-r[1-9]\d*)?\.md$/u.test(value)
|
|
36
|
+
&& path.basename(value) === value;
|
|
37
|
+
}
|
|
38
|
+
function assertTaskArtifactDirectory(directory) {
|
|
39
|
+
const resolved = path.resolve(directory);
|
|
40
|
+
let stat;
|
|
41
|
+
try {
|
|
42
|
+
stat = fs.lstatSync(resolved);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
throw new SecureFileError('TASK_ARTIFACT_WRITE_DENIED', 'task directory is unavailable');
|
|
46
|
+
}
|
|
47
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
48
|
+
throw new SecureFileError('TASK_ARTIFACT_WRITE_DENIED', 'task directory must be a real directory');
|
|
49
|
+
}
|
|
50
|
+
return resolved;
|
|
51
|
+
}
|
|
52
|
+
export async function readTaskArtifact(taskDir, input) {
|
|
53
|
+
if (!canonicalArtifactName(input.artifact))
|
|
54
|
+
throw new SecureFileError('TASK_ARTIFACT_WRITE_DENIED', 'artifact must be a canonical top-level basename');
|
|
55
|
+
const root = assertTaskArtifactDirectory(taskDir);
|
|
56
|
+
const candidate = path.join(root, input.artifact);
|
|
57
|
+
if (path.dirname(candidate) !== root)
|
|
58
|
+
throw new SecureFileError('TASK_ARTIFACT_WRITE_DENIED', 'artifact escapes task directory');
|
|
59
|
+
const stable = await readStableFile(candidate, {
|
|
60
|
+
maxBytes: 1024 * 1024,
|
|
61
|
+
...(input.expectedSha256 ? { expectedSha256: input.expectedSha256 } : {})
|
|
62
|
+
});
|
|
63
|
+
return { artifact: input.artifact, bytes: stable.bytes, sha256: stable.sha256 };
|
|
64
|
+
}
|
|
65
|
+
export async function writeTaskArtifact(taskDir, artifact) {
|
|
66
|
+
if (!canonicalArtifactName(artifact.artifact))
|
|
67
|
+
throw new SecureFileError('TASK_ARTIFACT_WRITE_DENIED', 'artifact must be a canonical top-level basename');
|
|
68
|
+
const root = assertTaskArtifactDirectory(taskDir);
|
|
69
|
+
const target = path.join(root, artifact.artifact);
|
|
70
|
+
if (path.dirname(target) !== root)
|
|
71
|
+
throw new SecureFileError('TASK_ARTIFACT_WRITE_DENIED', 'artifact escapes task directory');
|
|
72
|
+
await writeAtomicFile(target, artifact.bytes, 0o600, artifact.expectedSha256);
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=task-workflow.js.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { TASK_WORKFLOW_COMMANDS } from '../../task/workflow-command.js';
|
|
2
|
+
import { parseArtifactCommand, executeArtifactCommand } from '../../task/artifact-command.js';
|
|
3
|
+
import { parseReviewCommand } from '../../task/review-command.js';
|
|
4
|
+
import { prepareLocalArtifact, commitLocalArtifactProvenance } from '../../task/local-artifact-finalization.js';
|
|
5
|
+
import { prepareReviewSummaryCandidate, commitReviewSummaryProvenance } from '../../task/review-finalization.js';
|
|
6
|
+
import { withTaskExecutionLock } from '../../task/task-execution-lock.js';
|
|
7
|
+
import { dispatchHostControlCommand } from '../../host-control/command.js';
|
|
8
|
+
import { assertSandboxTaskSource } from '../workspace-view.js';
|
|
9
|
+
import { appendDiagnosticAudit } from './audit.js';
|
|
10
|
+
import { readTaskArtifact } from './task-workflow.js';
|
|
11
|
+
import { applyTaskEvent } from '../../task/events.js';
|
|
12
|
+
import { parseTaskEventRequest } from '../../internal/task-event.js';
|
|
13
|
+
function executionResult(result) {
|
|
14
|
+
return { exitCode: result.status === 'failed' || result.status === 'refused' ? 1 : 0, stdout: `${JSON.stringify(result)}\n`, stderr: '' };
|
|
15
|
+
}
|
|
16
|
+
/** The broker already authorized this host executor; domain operations own validation. */
|
|
17
|
+
export async function executeTaskWorkflow(manifest, request, lifecycleRecoveryAttestation = null) {
|
|
18
|
+
let publicationStarted = false;
|
|
19
|
+
try {
|
|
20
|
+
const taskDir = assertSandboxTaskSource(manifest.repoRoot, request.taskId);
|
|
21
|
+
const [command] = TASK_WORKFLOW_COMMANDS[request.operation];
|
|
22
|
+
if (request.operation === 'event') {
|
|
23
|
+
const eventRequest = parseTaskEventRequest(request.args);
|
|
24
|
+
const boundEventRequest = lifecycleRecoveryAttestation && eventRequest.requestId === undefined
|
|
25
|
+
? { ...eventRequest, requestId: lifecycleRecoveryAttestation.lifecycleRequestId }
|
|
26
|
+
: eventRequest;
|
|
27
|
+
const result = applyTaskEvent(boundEventRequest, {
|
|
28
|
+
repoRoot: manifest.repoRoot,
|
|
29
|
+
lifecycleRecoveryAttestation,
|
|
30
|
+
deferLifecycleRecoveryConsumption: true
|
|
31
|
+
});
|
|
32
|
+
return executionResult(result);
|
|
33
|
+
}
|
|
34
|
+
if (command !== 'task-artifact' && command !== 'task-review') {
|
|
35
|
+
publicationStarted = true;
|
|
36
|
+
// Inherit this executor's process group so its existing recovery owns the worker too.
|
|
37
|
+
const result = await dispatchHostControlCommand({
|
|
38
|
+
operation: command, payload: { workingDirectory: manifest.repoRoot, args: request.args }
|
|
39
|
+
});
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
const input = command === 'task-artifact' ? parseArtifactCommand(request.args) : parseReviewCommand(request.args);
|
|
43
|
+
if (command === 'task-artifact' && 'operation' in input && input.operation === 'inspect') {
|
|
44
|
+
return executionResult(executeArtifactCommand(input, { repoRoot: manifest.repoRoot }));
|
|
45
|
+
}
|
|
46
|
+
if ('operation' in input && input.operation === 'init') {
|
|
47
|
+
return executionResult(executeArtifactCommand(input, { repoRoot: manifest.repoRoot, artifactDir: taskDir }));
|
|
48
|
+
}
|
|
49
|
+
return await withTaskExecutionLock(manifest.repoRoot, request.taskId, `sandbox-control.${request.operation}`, async () => {
|
|
50
|
+
const artifact = await readTaskArtifact(taskDir, { artifact: input.artifact });
|
|
51
|
+
const content = artifact.bytes.toString('utf8');
|
|
52
|
+
let result;
|
|
53
|
+
if ('operation' in input) {
|
|
54
|
+
const { family } = input;
|
|
55
|
+
if (family !== 'analysis' && family !== 'plan' && family !== 'code')
|
|
56
|
+
throw new Error('ARTIFACT_IDENTITY_INVALID');
|
|
57
|
+
const local = { taskRef: request.taskId, family, artifact: input.artifact, repoRoot: manifest.repoRoot, recoveryId: input.recoveryId, lockAlreadyHeld: true };
|
|
58
|
+
const prepared = prepareLocalArtifact(local, content, lifecycleRecoveryAttestation ?? undefined);
|
|
59
|
+
if (prepared.result.status === 'failed')
|
|
60
|
+
return executionResult(commitLocalArtifactProvenance(prepared));
|
|
61
|
+
publicationStarted = true;
|
|
62
|
+
result = commitLocalArtifactProvenance(prepared);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
if (input.overrideTicket)
|
|
66
|
+
throw new Error('TASK_WORKFLOW_OVERRIDE_UNSUPPORTED');
|
|
67
|
+
const prepared = prepareReviewSummaryCandidate(input, content, { repoRoot: manifest.repoRoot, lockAlreadyHeld: true, startRecovery: true });
|
|
68
|
+
if (input.dryRun || prepared.result.status === 'planned')
|
|
69
|
+
return executionResult(prepared.result);
|
|
70
|
+
if (prepared.result.status === 'failed')
|
|
71
|
+
return executionResult(commitReviewSummaryProvenance(prepared, manifest.repoRoot));
|
|
72
|
+
publicationStarted = true;
|
|
73
|
+
result = commitReviewSummaryProvenance(prepared, manifest.repoRoot);
|
|
74
|
+
}
|
|
75
|
+
if (result.status !== 'failed')
|
|
76
|
+
appendDiagnosticAudit(manifest, 'task-workflow-artifact-finalized', {
|
|
77
|
+
requestId: request.id, sandboxTaskId: request.taskId, workflowOperation: request.operation,
|
|
78
|
+
artifact: input.artifact, sha256: result.artifactSha256, semanticDigest: result.semanticDigest
|
|
79
|
+
});
|
|
80
|
+
return executionResult({ ...result, changed: true });
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
85
|
+
const code = error?.code ?? /^([A-Z][A-Z0-9_]+)/u.exec(message)?.[1] ?? 'TASK_WORKFLOW_REQUEST_INVALID';
|
|
86
|
+
return executionResult({ status: 'failed', changed: publicationStarted ? null : false, error: { code, message } });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=workflow-executor.js.map
|
|
@@ -19,8 +19,7 @@ Commands:
|
|
|
19
19
|
rm <branch | TASK-id> | --unbound | --purge
|
|
20
20
|
Remove one sandbox; use a full TASK-id for task-bound
|
|
21
21
|
cleanup and a branch for branch-only cleanup. --unbound
|
|
22
|
-
removes
|
|
23
|
-
active, blocked, and archive tasks are protected.
|
|
22
|
+
removes discovered task-bound and branch-only sandboxes.
|
|
24
23
|
start [--recreate] <branch | TASK-id | N>
|
|
25
24
|
Verify or recover an existing sandbox container;
|
|
26
25
|
optionally replace only the container on failure
|
|
@@ -18,7 +18,9 @@ import { declaredTmpfsSeedEntries, resolveTools, toolConfigDirCandidates } from
|
|
|
18
18
|
import { fetchSandboxRows, selectSandboxContainer, startSandboxContainer } from './commands/list-running.js';
|
|
19
19
|
import { getProcessIdentityState, getProcessStartTime, removePidFileIfMatches } from '../server/process-state.js';
|
|
20
20
|
import { acquireSandboxControlBrokerStartup, garbageCollectSandboxControlRoot, isSandboxControlRootQuiescing, readSandboxControlManifest } from './control/lifecycle.js';
|
|
21
|
-
import {
|
|
21
|
+
import { readSandboxControlStatus } from './control/state.js';
|
|
22
|
+
import { validateSandboxControlIdentity } from './control/identity-sentinel.js';
|
|
23
|
+
import { appendDiagnosticAudit as appendControlDiagnosticAudit } from './control/audit.js';
|
|
22
24
|
import { inspectSandboxControlContainer } from './control/container-identity.js';
|
|
23
25
|
import { SANDBOX_CONTROL_FUTURE_SKEW_MS, SANDBOX_CONTROL_STATUS_STALE_MS } from './control/protocol.js';
|
|
24
26
|
export function worktreeProbeForEngine(engine, probe = runProbe) {
|
|
@@ -61,6 +63,17 @@ export async function startSandboxControlBroker(repoRoot, manifestPath) {
|
|
|
61
63
|
const internalCli = path.resolve(directory, '..', '..', 'bin', `internal-cli${extension}`);
|
|
62
64
|
const manifest = readSandboxControlManifest(manifestPath);
|
|
63
65
|
const root = path.dirname(manifestPath);
|
|
66
|
+
const identity = validateSandboxControlIdentity({
|
|
67
|
+
publicStatusDir: manifest.publicStatusDir,
|
|
68
|
+
root,
|
|
69
|
+
mode: manifest.mode,
|
|
70
|
+
taskId: manifest.taskId,
|
|
71
|
+
generation: manifest.generation,
|
|
72
|
+
controlRootId: manifest.controlRootId
|
|
73
|
+
});
|
|
74
|
+
if (identity.state !== 'valid') {
|
|
75
|
+
throw new Error(`SANDBOX_CONTROL_IDENTITY_${identity.state.replaceAll('-', '_').toUpperCase()}`);
|
|
76
|
+
}
|
|
64
77
|
if (isSandboxControlRootQuiescing(root))
|
|
65
78
|
throw new Error('SANDBOX_CONTROL_QUIESCING');
|
|
66
79
|
const brokerPath = path.join(root, 'broker.json');
|
|
@@ -130,8 +143,8 @@ export async function startSandboxControlBroker(repoRoot, manifestPath) {
|
|
|
130
143
|
}
|
|
131
144
|
}
|
|
132
145
|
if (replacedBrokerRecord) {
|
|
133
|
-
|
|
134
|
-
|
|
146
|
+
appendControlDiagnosticAudit(manifest, 'broker-observed-crash');
|
|
147
|
+
appendControlDiagnosticAudit(manifest, 'broker-restart');
|
|
135
148
|
}
|
|
136
149
|
child = spawn(process.execPath, nodeEntryArgs(internalCli, ['sandbox-control', 'serve', '--manifest', manifestPath]), { cwd: repoRoot, detached: true, stdio: 'ignore' });
|
|
137
150
|
}
|
|
@@ -168,6 +181,17 @@ async function ensureSandboxControlBroker(params) {
|
|
|
168
181
|
if (!fs.existsSync(control.manifestPath))
|
|
169
182
|
return;
|
|
170
183
|
const validatedManifest = readSandboxControlManifest(control.manifestPath);
|
|
184
|
+
const identity = validateSandboxControlIdentity({
|
|
185
|
+
publicStatusDir: validatedManifest.publicStatusDir,
|
|
186
|
+
root: control.root,
|
|
187
|
+
mode: validatedManifest.mode,
|
|
188
|
+
taskId: validatedManifest.taskId,
|
|
189
|
+
generation: validatedManifest.generation,
|
|
190
|
+
controlRootId: validatedManifest.controlRootId
|
|
191
|
+
});
|
|
192
|
+
if (identity.state !== 'valid') {
|
|
193
|
+
throw new Error(`SANDBOX_CONTROL_IDENTITY_${identity.state.replaceAll('-', '_').toUpperCase()}`);
|
|
194
|
+
}
|
|
171
195
|
const containerObservation = await inspectSandboxControlContainer(validatedManifest);
|
|
172
196
|
if (containerObservation.state === 'unknown') {
|
|
173
197
|
throw new Error(`SANDBOX_CONTROL_CONTAINER_UNKNOWN: ${containerObservation.reason}`);
|
|
@@ -514,7 +538,7 @@ function expectedMounts(params) {
|
|
|
514
538
|
? {}
|
|
515
539
|
: {
|
|
516
540
|
runtimeDir: control.runtimeDir,
|
|
517
|
-
taskSources: taskSources.
|
|
541
|
+
taskSources: taskSources.accessiblePaths,
|
|
518
542
|
taskId: taskId
|
|
519
543
|
})
|
|
520
544
|
}).map((mount) => ({
|