@fitlab-ai/agent-infra 0.12.1 → 0.12.2
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 +0 -2
- package/README.zh-CN.md +0 -2
- package/dist/bin/internal-cli.js +2 -17
- package/dist/lib/agent-clients/adapter.js +0 -13
- package/dist/lib/agent-clients/adapters/antigravity-cli.js +0 -5
- package/dist/lib/agent-clients/adapters/claude-code-credentials.js +0 -17
- package/dist/lib/agent-clients/adapters/claude-code.js +0 -9
- package/dist/lib/agent-clients/adapters/codex.js +0 -52
- package/dist/lib/agent-clients/adapters/opencode.js +0 -5
- package/dist/lib/agent-clients/adapters/traecli.js +0 -5
- package/dist/lib/agent-clients/config.js +19 -54
- package/dist/lib/agent-clients/registry.js +1 -12
- package/dist/lib/agent-clients/schema.js +0 -18
- package/dist/lib/agent-clients/tokens.js +1 -2
- package/dist/lib/agent-clients/types.js +0 -1
- package/dist/lib/decide.js +2 -0
- package/dist/lib/git/worktree-identity.js +1 -9
- package/dist/lib/internal/agent-client.js +2 -62
- package/dist/lib/internal/cli-route-inventory.js +1 -5
- package/dist/lib/internal/manual-validation.js +18 -10
- package/dist/lib/internal/task-create.js +1 -1
- package/dist/lib/internal/task-event.js +1 -8
- package/dist/lib/internal/task-finalization.js +0 -1
- package/dist/lib/internal/task-lifecycle.js +2 -2
- package/dist/lib/internal/task-operation-registry.js +4 -20
- package/dist/lib/internal/task-review.js +4 -4
- package/dist/lib/platform/comment-safety.js +1 -7
- package/dist/lib/platform/in-label-sync.js +1 -14
- package/dist/lib/platform/issue-comments.js +1 -16
- package/dist/lib/platform/issues.js +1 -1
- package/dist/lib/platform/operation-coordinator.js +4 -2
- package/dist/lib/platform/pr-change-report.js +1 -4
- package/dist/lib/platform/pr-checks.js +2 -8
- package/dist/lib/platform/provider-validation.js +0 -20
- package/dist/lib/platform/pull-requests.js +73 -84
- package/dist/lib/platform/releases.js +1 -43
- package/dist/lib/platform/verification-required.js +0 -2
- package/dist/lib/platform/verification-sync.js +1 -79
- package/dist/lib/process-data/normalize.js +1 -185
- package/dist/lib/process-data/privacy.js +1 -16
- package/dist/lib/process-data/sources.js +2 -279
- package/dist/lib/render.js +0 -12
- package/dist/lib/run/index.js +15 -10
- package/dist/lib/run/skills.js +0 -3
- package/dist/lib/sandbox/commands/create.js +40 -53
- package/dist/lib/sandbox/commands/list-running.js +0 -18
- package/dist/lib/sandbox/commands/start.js +7 -8
- package/dist/lib/sandbox/constants.js +0 -6
- package/dist/lib/sandbox/control/client.js +0 -1
- package/dist/lib/sandbox/control/container-identity.js +1 -16
- package/dist/lib/sandbox/control/executor.js +0 -4
- package/dist/lib/sandbox/control/identity-sentinel.js +0 -7
- package/dist/lib/sandbox/control/lifecycle.js +21 -37
- package/dist/lib/sandbox/control/native-file-lock.js +0 -3
- package/dist/lib/sandbox/control/server.js +18 -38
- package/dist/lib/sandbox/control/state.js +1 -9
- package/dist/lib/sandbox/dockerfile.js +0 -6
- package/dist/lib/sandbox/engine.js +0 -14
- package/dist/lib/sandbox/engines/docker-exact-discovery.js +1 -4
- package/dist/lib/sandbox/engines/wsl2-paths.js +0 -3
- package/dist/lib/sandbox/recovery.js +24 -26
- package/dist/lib/sandbox/removal.js +11 -519
- package/dist/lib/sandbox/task-resolver.js +0 -41
- package/dist/lib/sandbox/tools.js +1 -4
- package/dist/lib/sandbox/workspace-view.js +1 -2
- package/dist/lib/server/display.js +0 -6
- package/dist/lib/task/activity-intent.js +45 -40
- package/dist/lib/task/activity-log.js +9 -16
- package/dist/lib/task/artifact-command.js +1 -1
- package/dist/lib/task/artifact-lifecycle.js +61 -63
- package/dist/lib/task/artifact-name.js +0 -6
- package/dist/lib/task/artifact-operations.js +3 -3
- package/dist/lib/task/capabilities.js +4 -5
- package/dist/lib/task/commands/log.js +0 -6
- package/dist/lib/task/commands/status.js +17 -60
- package/dist/lib/task/commit-operation.js +28 -39
- package/dist/lib/task/completion-facts.js +56 -43
- package/dist/lib/task/control-authority.js +23 -256
- package/dist/lib/task/control-recovery.js +3 -5
- package/dist/lib/task/create.js +2 -4
- package/dist/lib/task/decision-intents.js +8 -9
- package/dist/lib/task/delivery-target.js +1 -40
- package/dist/lib/task/events.js +84 -107
- package/dist/lib/task/finalization.js +44 -8
- package/dist/lib/task/ledger-intents.js +1 -1
- package/dist/lib/task/lifecycle-execution.js +38 -33
- package/dist/lib/task/lifecycle.js +49 -41
- package/dist/lib/task/local-artifact-finalization.js +1 -4
- package/dist/lib/task/manual-validation-evidence.js +1 -37
- package/dist/lib/task/platform-operation-recovery.js +67 -24
- package/dist/lib/task/pr-delivery-fact.js +2 -5
- package/dist/lib/task/qualification-confirmation.js +5 -7
- package/dist/lib/task/resolve-ref.js +1 -25
- package/dist/lib/task/review-command.js +2 -2
- package/dist/lib/task/review-finalization.js +1 -21
- package/dist/lib/task/review-fingerprint.js +0 -4
- package/dist/lib/task/secure-fs.js +0 -56
- package/dist/lib/task/short-id.js +1 -39
- package/dist/lib/task/skill-scope.js +0 -1
- package/dist/lib/task/verification-engine.js +58 -282
- package/dist/lib/task/verification.js +6 -3
- package/dist/lib/task/write.js +11 -1
- package/lib/agent-clients/adapter.ts +0 -76
- package/lib/agent-clients/adapters/antigravity-cli.ts +0 -5
- package/lib/agent-clients/adapters/claude-code-credentials.ts +0 -19
- package/lib/agent-clients/adapters/claude-code.ts +0 -9
- package/lib/agent-clients/adapters/codex.ts +0 -56
- package/lib/agent-clients/adapters/opencode.ts +0 -5
- package/lib/agent-clients/adapters/traecli.ts +0 -5
- package/lib/agent-clients/config.ts +20 -61
- package/lib/agent-clients/registry.ts +1 -34
- package/lib/agent-clients/schema.ts +0 -18
- package/lib/agent-clients/tokens.ts +1 -2
- package/lib/agent-clients/types.ts +0 -15
- package/lib/decide.ts +1 -0
- package/lib/git/worktree-identity.ts +0 -10
- package/lib/internal/agent-client.ts +2 -70
- package/lib/internal/cli-route-inventory.ts +1 -4
- package/lib/internal/manual-validation.ts +16 -9
- package/lib/internal/task-create.ts +0 -1
- package/lib/internal/task-event.ts +1 -5
- package/lib/internal/task-finalization.ts +0 -1
- package/lib/internal/task-lifecycle.ts +3 -5
- package/lib/internal/task-operation-registry.ts +3 -19
- package/lib/internal/task-review.ts +4 -4
- package/lib/platform/comment-safety.ts +0 -10
- package/lib/platform/github-provider.ts +0 -2
- package/lib/platform/in-label-sync.ts +0 -16
- package/lib/platform/issue-comments.ts +0 -21
- package/lib/platform/issues.ts +0 -2
- package/lib/platform/operation-coordinator.ts +4 -2
- package/lib/platform/pr-change-report.ts +0 -5
- package/lib/platform/pr-checks.ts +1 -10
- package/lib/platform/pr-review.ts +1 -1
- package/lib/platform/provider-bridge.ts +0 -1
- package/lib/platform/provider-loader.ts +1 -5
- package/lib/platform/provider-validation.ts +1 -49
- package/lib/platform/pull-requests.ts +64 -99
- package/lib/platform/releases.ts +1 -40
- package/lib/platform/verification-required.ts +0 -2
- package/lib/platform/verification-sync.ts +0 -94
- package/lib/process-data/normalize.ts +1 -186
- package/lib/process-data/privacy.ts +2 -19
- package/lib/process-data/sources.ts +3 -283
- package/lib/render.ts +0 -15
- package/lib/run/index.ts +13 -7
- package/lib/run/skills.ts +0 -4
- package/lib/sandbox/commands/create.ts +37 -74
- package/lib/sandbox/commands/list-running.ts +0 -19
- package/lib/sandbox/commands/start.ts +7 -10
- package/lib/sandbox/constants.ts +0 -8
- package/lib/sandbox/control/client.ts +0 -1
- package/lib/sandbox/control/container-identity.ts +1 -16
- package/lib/sandbox/control/executor.ts +1 -5
- package/lib/sandbox/control/identity-sentinel.ts +0 -8
- package/lib/sandbox/control/lifecycle.ts +18 -51
- package/lib/sandbox/control/native-file-lock.ts +0 -8
- package/lib/sandbox/control/protocol.ts +0 -2
- package/lib/sandbox/control/server.ts +13 -39
- package/lib/sandbox/control/state.ts +1 -10
- package/lib/sandbox/dockerfile.ts +0 -11
- package/lib/sandbox/engine.ts +0 -17
- package/lib/sandbox/engines/docker-exact-discovery.ts +1 -5
- package/lib/sandbox/engines/wsl2-paths.ts +0 -4
- package/lib/sandbox/recovery.ts +24 -26
- package/lib/sandbox/removal.ts +11 -696
- package/lib/sandbox/shell.ts +1 -1
- package/lib/sandbox/task-resolver.ts +0 -48
- package/lib/sandbox/tools.ts +1 -5
- package/lib/sandbox/workspace-view.ts +2 -4
- package/lib/server/display.ts +0 -14
- package/lib/server/process-control.ts +1 -1
- package/lib/task/activity-intent.ts +36 -44
- package/lib/task/activity-log.ts +9 -22
- package/lib/task/artifact-command.ts +1 -1
- package/lib/task/artifact-lifecycle.ts +58 -67
- package/lib/task/artifact-name.ts +0 -7
- package/lib/task/artifact-operations.ts +3 -3
- package/lib/task/capabilities.ts +5 -6
- package/lib/task/commands/log.ts +0 -7
- package/lib/task/commands/status.ts +14 -79
- package/lib/task/commit-operation.ts +29 -51
- package/lib/task/completion-facts.ts +45 -42
- package/lib/task/control-authority.ts +27 -317
- package/lib/task/control-recovery.ts +2 -5
- package/lib/task/create.ts +2 -5
- package/lib/task/decision-intents.ts +5 -5
- package/lib/task/delivery-target.ts +0 -40
- package/lib/task/events.ts +89 -123
- package/lib/task/finalization.ts +41 -9
- package/lib/task/ledger-intents.ts +1 -1
- package/lib/task/lifecycle-execution.ts +37 -89
- package/lib/task/lifecycle.ts +48 -44
- package/lib/task/local-artifact-finalization.ts +0 -7
- package/lib/task/manual-validation-evidence.ts +1 -47
- package/lib/task/platform-operation-recovery.ts +50 -26
- package/lib/task/pr-delivery-fact.ts +2 -11
- package/lib/task/qualification-confirmation.ts +6 -6
- package/lib/task/resolve-ref.ts +0 -23
- package/lib/task/review-command.ts +2 -2
- package/lib/task/review-finalization.ts +1 -27
- package/lib/task/review-fingerprint.ts +0 -8
- package/lib/task/secure-fs.ts +0 -42
- package/lib/task/short-id.ts +0 -43
- package/lib/task/skill-scope.ts +0 -1
- package/lib/task/verification-engine.ts +56 -287
- package/lib/task/verification.ts +5 -5
- package/lib/task/write.ts +12 -1
- package/package.json +2 -2
- package/templates/.agents/README.en.md +1 -3
- package/templates/.agents/README.zh-CN.md +0 -2
- package/templates/.agents/rules/README.en.md +0 -1
- package/templates/.agents/rules/README.zh-CN.md +0 -1
- package/templates/.agents/rules/commit-and-pr.en.md +1 -1
- package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -1
- package/templates/.agents/rules/no-mid-flow-questions.en.md +0 -10
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +0 -10
- package/templates/.agents/rules/pr-sync.en.md +1 -1
- package/templates/.agents/rules/pr-sync.zh-CN.md +1 -1
- package/templates/.agents/rules/task-management.en.md +3 -3
- package/templates/.agents/rules/task-management.zh-CN.md +3 -3
- package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/commit/SKILL.en.md +2 -2
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +6 -6
- package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +6 -6
- package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-analysis/SKILL.en.md +3 -3
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/review-code/SKILL.en.md +5 -5
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/review-plan/SKILL.en.md +3 -3
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/review-pr/SKILL.en.md +4 -4
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -75
- package/templates/.agents/templates/task.en.md +1 -0
- package/templates/.agents/templates/task.zh-CN.md +1 -0
- package/templates/.claude/settings.json +0 -24
- package/templates/.codex/hooks.json +0 -50
- package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +0 -582
- package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +0 -114
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +0 -237
- package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +0 -443
- package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +0 -236
- package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +0 -292
- package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +0 -267
- package/dist/lib/agent-clients/adapters/codex-orchestration.js +0 -466
- package/dist/lib/internal/task-orchestration.js +0 -71
- package/dist/lib/platform/verification.js +0 -6
- package/dist/lib/run/prompt.js +0 -2
- package/dist/lib/sandbox/engines/authority.js +0 -289
- package/dist/lib/task/delegation-receipts.js +0 -410
- package/dist/lib/task/orchestration.js +0 -1233
- package/dist/lib/task/verification-checks.js +0 -9
- package/dist/lib/task/workspace-snapshot.js +0 -121
- package/dist/lifecycle-build-manifest.json +0 -6
- package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +0 -688
- package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +0 -147
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +0 -349
- package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +0 -506
- package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +0 -385
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -41
- package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +0 -418
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +0 -354
- package/lib/agent-clients/adapters/codex-orchestration.ts +0 -630
- package/lib/internal/task-orchestration.ts +0 -74
- package/lib/platform/verification.ts +0 -11
- package/lib/run/prompt.ts +0 -1
- package/lib/sandbox/engines/authority.ts +0 -365
- package/lib/task/delegation-receipts.ts +0 -547
- package/lib/task/orchestration.ts +0 -1651
- package/lib/task/verification-checks.ts +0 -10
- package/lib/task/workspace-snapshot.ts +0 -144
- package/templates/.agents/hooks/lifecycle-delegation.js +0 -140
- package/templates/.agents/rules/lifecycle-orchestration.en.md +0 -44
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +0 -44
- package/templates/.agents/skills/run-task/SKILL.en.md +0 -29
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +0 -29
- package/templates/.agents/skills/run-task/config/verify.en.json +0 -10
- package/templates/.agents/skills/run-task/config/verify.zh-CN.json +0 -10
- package/templates/.agents/skills/run-task/reference/host-validation.en.md +0 -24
- package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +0 -24
- package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +0 -6
- package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +0 -6
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +0 -6
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +0 -6
- package/templates/.claude/commands/run-task.en.md +0 -8
- package/templates/.claude/commands/run-task.zh-CN.md +0 -8
- package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +0 -3
- package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +0 -3
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +0 -3
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +0 -3
- package/templates/.opencode/commands/run-task.en.md +0 -11
- package/templates/.opencode/commands/run-task.zh-CN.md +0 -11
|
@@ -2,27 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
4
|
import { normalizeAgentToken } from '../agent-clients/tokens.ts';
|
|
5
|
-
import { isAgentClientId } from '../agent-clients/types.ts';
|
|
6
|
-
import type { AgentClientId } from '../agent-clients/types.ts';
|
|
7
5
|
import { sandboxControlPaths } from '../sandbox/workspace-view.ts';
|
|
8
|
-
import { getAgentClientAdapter } from '../agent-clients/registry.ts';
|
|
9
|
-
import {
|
|
10
|
-
activateMatchingOrchestrationDelegation,
|
|
11
|
-
activateOrchestrationDelegation,
|
|
12
|
-
advanceOrchestration,
|
|
13
|
-
awaitOrchestrationDelegationActivation,
|
|
14
|
-
beginOrResumeOrchestration,
|
|
15
|
-
dispatchOrchestrationDelegation,
|
|
16
|
-
OrchestrationStateError,
|
|
17
|
-
pauseOrchestration,
|
|
18
|
-
prepareOrchestrationDelegation,
|
|
19
|
-
recoverPreparedOrchestrationDelegation,
|
|
20
|
-
routeOrchestration,
|
|
21
|
-
sealMatchingOrchestrationDelegation,
|
|
22
|
-
sealOrchestrationDelegation,
|
|
23
|
-
statusOrchestration
|
|
24
|
-
} from './orchestration.ts';
|
|
25
|
-
import type { OrchestrationOptions, OrchestrationResult } from './orchestration.ts';
|
|
26
6
|
import {
|
|
27
7
|
applyTaskFinalization,
|
|
28
8
|
type TaskFinalizationRequest,
|
|
@@ -33,11 +13,7 @@ import {
|
|
|
33
13
|
type TaskLifecycleRequest,
|
|
34
14
|
type TaskLifecycleResult
|
|
35
15
|
} from './lifecycle.ts';
|
|
36
|
-
import
|
|
37
|
-
AgentClientLifecycleRecoveryRequest as LifecycleRecoveryRequest,
|
|
38
|
-
AgentClientLifecycleRecoveryResult as LifecycleRecoveryResult
|
|
39
|
-
} from '../agent-clients/adapter.ts';
|
|
40
|
-
import { resolveTaskContext, resolveTaskRef, TASK_ID_RE } from './resolve-ref.ts';
|
|
16
|
+
import { resolveTaskRef, TASK_ID_RE } from './resolve-ref.ts';
|
|
41
17
|
import { verifyTaskEvent } from './verification.ts';
|
|
42
18
|
import { releaseStaleShortIdRegistry } from './short-id.ts';
|
|
43
19
|
|
|
@@ -62,39 +38,11 @@ export type TaskControlExecutionContext =
|
|
|
62
38
|
requestId: string;
|
|
63
39
|
}>;
|
|
64
40
|
|
|
65
|
-
export type TaskControlOrchestrationIntent =
|
|
66
|
-
| 'begin-or-resume'
|
|
67
|
-
| 'route'
|
|
68
|
-
| 'prepare'
|
|
69
|
-
| 'dispatch'
|
|
70
|
-
| 'await-activation'
|
|
71
|
-
| 'recover-prepared'
|
|
72
|
-
| 'hook-start'
|
|
73
|
-
| 'hook-stop'
|
|
74
|
-
| 'advance'
|
|
75
|
-
| 'pause'
|
|
76
|
-
| 'status';
|
|
77
|
-
|
|
78
41
|
export type TaskControlOperation =
|
|
79
42
|
| Readonly<{ family: 'task-lifecycle'; request: TaskLifecycleControlRequest }>
|
|
80
|
-
| Readonly<{ family: 'task-finalization'; request: TaskFinalizationRequest }
|
|
81
|
-
| Readonly<{
|
|
82
|
-
family: 'task-orchestration';
|
|
83
|
-
taskRef: string;
|
|
84
|
-
intent: TaskControlOrchestrationIntent;
|
|
85
|
-
input: Readonly<Record<string, unknown>>;
|
|
86
|
-
options?: Omit<OrchestrationOptions, 'repoRoot'>;
|
|
87
|
-
}>;
|
|
43
|
+
| Readonly<{ family: 'task-finalization'; request: TaskFinalizationRequest }>;
|
|
88
44
|
|
|
89
|
-
export type TaskControlDispatchResult = TaskLifecycleResult |
|
|
90
|
-
|
|
91
|
-
export function taskControlOperationKey(operation: TaskControlOperation): string {
|
|
92
|
-
if (operation.family === 'task-finalization') return 'complete';
|
|
93
|
-
if (operation.family === 'task-lifecycle') return operation.request.intent;
|
|
94
|
-
return operation.intent === 'route'
|
|
95
|
-
? operation.input && operation.input.completed === true ? 'route.clean-completion' : 'route.read'
|
|
96
|
-
: operation.intent;
|
|
97
|
-
}
|
|
45
|
+
export type TaskControlDispatchResult = TaskLifecycleResult | TaskFinalizationResult;
|
|
98
46
|
|
|
99
47
|
export type TaskLifecycleControlRequest = TaskLifecycleRequest;
|
|
100
48
|
|
|
@@ -178,26 +126,6 @@ function boundTaskRef(context: TaskControlExecutionContext, taskRef: string): st
|
|
|
178
126
|
return context.source === 'sandbox-executor' ? context.taskId : taskRef;
|
|
179
127
|
}
|
|
180
128
|
|
|
181
|
-
function autoTaskOptions(
|
|
182
|
-
context: TaskControlExecutionContext,
|
|
183
|
-
options: OrchestrationOptions
|
|
184
|
-
): OrchestrationOptions {
|
|
185
|
-
if (context.source === 'sandbox-executor') return { ...options, taskId: context.taskId };
|
|
186
|
-
const resolved = resolveTaskContext(undefined, { repoRoot: context.repoRoot });
|
|
187
|
-
if (!resolved.ok) throw new Error(`${resolved.code}: ${resolved.message}`);
|
|
188
|
-
return { ...options, taskId: resolved.taskId };
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function domainOptions(
|
|
192
|
-
context: TaskControlExecutionContext,
|
|
193
|
-
options: Omit<OrchestrationOptions, 'repoRoot'> | undefined
|
|
194
|
-
): OrchestrationOptions {
|
|
195
|
-
return {
|
|
196
|
-
...options,
|
|
197
|
-
repoRoot: context.repoRoot
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
129
|
function lifecycleTaskId(request: TaskLifecycleControlRequest, repoRoot: string): string | null {
|
|
202
130
|
if (request.intent === 'restore') return TASK_ID_RE.test(request.taskRef) ? request.taskRef : null;
|
|
203
131
|
try {
|
|
@@ -211,23 +139,10 @@ function lifecycleTaskId(request: TaskLifecycleControlRequest, repoRoot: string)
|
|
|
211
139
|
async function applyLifecycleWithAuthority(
|
|
212
140
|
context: TaskControlExecutionContext,
|
|
213
141
|
request: TaskLifecycleControlRequest
|
|
214
|
-
): Promise<TaskLifecycleResult
|
|
142
|
+
): Promise<TaskLifecycleResult> {
|
|
215
143
|
const taskId = lifecycleTaskId(request, context.repoRoot);
|
|
216
144
|
const controlRoot = taskId ? controlRootForTask(context, taskId) : undefined;
|
|
217
|
-
const execute = async (): Promise<TaskLifecycleResult
|
|
218
|
-
if (request.intent === 'recover-started') {
|
|
219
|
-
const adapter = isAgentClientId(request.agent)
|
|
220
|
-
? getAgentClientAdapter(request.agent).orchestrationAdapter
|
|
221
|
-
: undefined;
|
|
222
|
-
if (!adapter?.recoverStarted) {
|
|
223
|
-
return {
|
|
224
|
-
status: 'no-op', changed: false, targetState: 'active',
|
|
225
|
-
requestRef: request.taskRef, intent: 'recover-started', taskId: null,
|
|
226
|
-
receiptId: null, childId: null, error: null
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
return adapter.recoverStarted(request as LifecycleRecoveryRequest, { repoRoot: context.repoRoot });
|
|
230
|
-
}
|
|
145
|
+
const execute = async (): Promise<TaskLifecycleResult> => {
|
|
231
146
|
return applyTaskLifecycle(request, {
|
|
232
147
|
repoRoot: context.repoRoot,
|
|
233
148
|
...(controlRoot ? { controlRoot } : {}),
|
|
@@ -248,94 +163,14 @@ function controlRootForTask(context: TaskControlExecutionContext, taskId: string
|
|
|
248
163
|
}).root;
|
|
249
164
|
}
|
|
250
165
|
|
|
251
|
-
function orchestration(
|
|
252
|
-
context: TaskControlExecutionContext,
|
|
253
|
-
operation: Extract<TaskControlOperation, { family: 'task-orchestration' }>
|
|
254
|
-
): OrchestrationResult | Promise<OrchestrationResult> {
|
|
255
|
-
const taskRef = boundTaskRef(context, operation.taskRef);
|
|
256
|
-
const input = operation.input;
|
|
257
|
-
const options = domainOptions(context, operation.options);
|
|
258
|
-
switch (operation.intent) {
|
|
259
|
-
case 'begin-or-resume':
|
|
260
|
-
return beginOrResumeOrchestration(taskRef, {
|
|
261
|
-
...options,
|
|
262
|
-
client: input.client as AgentClientId,
|
|
263
|
-
maxSteps: input.maxSteps as number | undefined,
|
|
264
|
-
modelPolicy: input.modelPolicy as OrchestrationOptions['modelPolicy']
|
|
265
|
-
});
|
|
266
|
-
case 'route': return routeOrchestration(taskRef, options);
|
|
267
|
-
case 'status': return statusOrchestration(taskRef, options);
|
|
268
|
-
case 'prepare': return prepareTaskOrchestration(context, { ...operation, taskRef }, options);
|
|
269
|
-
case 'dispatch': return dispatchOrchestrationDelegation(taskRef, options);
|
|
270
|
-
case 'await-activation':
|
|
271
|
-
return awaitOrchestrationDelegationActivation(taskRef, input.event as never, options);
|
|
272
|
-
case 'recover-prepared': return recoverPreparedOrchestrationDelegation(taskRef, options);
|
|
273
|
-
case 'hook-start':
|
|
274
|
-
return input.auto === true
|
|
275
|
-
? activateMatchingOrchestrationDelegation(
|
|
276
|
-
input.client as AgentClientId, input.event as never, autoTaskOptions(context, options)
|
|
277
|
-
)
|
|
278
|
-
: activateOrchestrationDelegation(taskRef, input.event as never, options);
|
|
279
|
-
case 'hook-stop':
|
|
280
|
-
return input.auto === true
|
|
281
|
-
? sealMatchingOrchestrationDelegation(
|
|
282
|
-
input.client as AgentClientId, input.event as never, autoTaskOptions(context, options)
|
|
283
|
-
)
|
|
284
|
-
: sealOrchestrationDelegation(taskRef, input.event as never, undefined, options);
|
|
285
|
-
case 'advance': return advanceOrchestration(taskRef, options);
|
|
286
|
-
case 'pause':
|
|
287
|
-
return pauseOrchestration(
|
|
288
|
-
taskRef,
|
|
289
|
-
input.code as string,
|
|
290
|
-
input.message as string,
|
|
291
|
-
input.recoverable as boolean,
|
|
292
|
-
options
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function prepareTaskOrchestration(
|
|
298
|
-
context: TaskControlExecutionContext,
|
|
299
|
-
operation: Extract<TaskControlOperation, { family: 'task-orchestration' }>,
|
|
300
|
-
options: OrchestrationOptions
|
|
301
|
-
): OrchestrationResult | Promise<OrchestrationResult> {
|
|
302
|
-
const input = operation.input;
|
|
303
|
-
const prepareInput = {
|
|
304
|
-
client: input.client as AgentClientId,
|
|
305
|
-
requestedModel: input.requestedModel as string | undefined,
|
|
306
|
-
requestedReasoningEffort: input.requestedReasoningEffort as string | undefined,
|
|
307
|
-
};
|
|
308
|
-
const prepareDelegation = getAgentClientAdapter(prepareInput.client).orchestrationAdapter?.prepareDelegation;
|
|
309
|
-
return prepareDelegation
|
|
310
|
-
? prepareDelegation(operation.taskRef, prepareInput, {
|
|
311
|
-
repoRoot: context.repoRoot,
|
|
312
|
-
orchestrationOptions: options,
|
|
313
|
-
})
|
|
314
|
-
: prepareOrchestrationDelegation(operation.taskRef, prepareInput, options);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function orchestrationFailure(error: unknown): OrchestrationResult {
|
|
318
|
-
if (error instanceof OrchestrationStateError) {
|
|
319
|
-
return {
|
|
320
|
-
status: 'failed', changed: false, taskId: error.taskId, run: null, next: null,
|
|
321
|
-
error: { code: error.code, message: error.message }
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
throw error;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
166
|
export function dispatchTaskControlOperation(
|
|
328
167
|
context: TaskControlExecutionContext,
|
|
329
168
|
operation: Extract<TaskControlOperation, { family: 'task-lifecycle' }>
|
|
330
|
-
): Promise<TaskLifecycleResult
|
|
169
|
+
): Promise<TaskLifecycleResult>;
|
|
331
170
|
export function dispatchTaskControlOperation(
|
|
332
171
|
context: TaskControlExecutionContext,
|
|
333
172
|
operation: Extract<TaskControlOperation, { family: 'task-finalization' }>
|
|
334
173
|
): Promise<TaskFinalizationResult>;
|
|
335
|
-
export function dispatchTaskControlOperation(
|
|
336
|
-
context: TaskControlExecutionContext,
|
|
337
|
-
operation: Extract<TaskControlOperation, { family: 'task-orchestration' }>
|
|
338
|
-
): OrchestrationResult | Promise<OrchestrationResult>;
|
|
339
174
|
export function dispatchTaskControlOperation(
|
|
340
175
|
context: TaskControlExecutionContext,
|
|
341
176
|
operation: TaskControlOperation
|
|
@@ -389,12 +224,7 @@ export function dispatchTaskControlOperation(
|
|
|
389
224
|
}
|
|
390
225
|
});
|
|
391
226
|
}
|
|
392
|
-
|
|
393
|
-
const result = orchestration(context, operation);
|
|
394
|
-
return result instanceof Promise ? result.catch(orchestrationFailure) : result;
|
|
395
|
-
} catch (error) {
|
|
396
|
-
return orchestrationFailure(error);
|
|
397
|
-
}
|
|
227
|
+
throw new Error('TASK_CONTROL_OPERATION_INVALID: unsupported operation family');
|
|
398
228
|
}
|
|
399
229
|
|
|
400
230
|
export function assertTaskControlOperation(operation: TaskControlOperation): void {
|
|
@@ -410,9 +240,6 @@ export function assertTaskControlOperation(operation: TaskControlOperation): voi
|
|
|
410
240
|
}
|
|
411
241
|
return;
|
|
412
242
|
}
|
|
413
|
-
if (!operation.taskRef || !operation.intent || !operation.input || typeof operation.input !== 'object' || Array.isArray(operation.input)) {
|
|
414
|
-
throw new Error('TASK_CONTROL_OPERATION_INVALID: orchestration operation is invalid');
|
|
415
|
-
}
|
|
416
243
|
}
|
|
417
244
|
|
|
418
245
|
function operationInvalid(message: string): never {
|
|
@@ -421,20 +248,11 @@ function operationInvalid(message: string): never {
|
|
|
421
248
|
|
|
422
249
|
const LIFECYCLE_FLAGS = new Set([
|
|
423
250
|
'--agent', '--reason', '--unblock-condition', '--note', '--alert-number', '--staging-dir', '--issue-number',
|
|
424
|
-
'--
|
|
251
|
+
'--dry-run'
|
|
425
252
|
]);
|
|
426
253
|
|
|
427
254
|
const FINALIZATION_FLAGS = new Set(['--agent']);
|
|
428
255
|
|
|
429
|
-
const ORCHESTRATION_FLAGS = new Set([
|
|
430
|
-
'--agent', '--max-steps', '--executor-model', '--executor-reasoning-effort', '--reviewer-model',
|
|
431
|
-
'--reviewer-reasoning-effort', '--client', '--requested-model', '--requested-reasoning-effort',
|
|
432
|
-
'--parent-id', '--before-fingerprint', '--stage', '--round', '--artifact', '--role',
|
|
433
|
-
'--native-agent', '--child-id', '--spawn-mode', '--actual-model', '--actual-reasoning-effort',
|
|
434
|
-
'--model-fallback-reason', '--reasoning-effort-fallback-reason', '--exit-code', '--after-fingerprint',
|
|
435
|
-
'--changed-paths', '--code', '--message', '--recoverable'
|
|
436
|
-
]);
|
|
437
|
-
|
|
438
256
|
function parseValues(
|
|
439
257
|
args: readonly string[],
|
|
440
258
|
start: number,
|
|
@@ -443,7 +261,7 @@ function parseValues(
|
|
|
443
261
|
const values: Record<string, string | boolean> = {};
|
|
444
262
|
for (let index = start; index < args.length; index += 1) {
|
|
445
263
|
const flag = args[index]!;
|
|
446
|
-
if (flag === '--dry-run'
|
|
264
|
+
if (flag === '--dry-run') {
|
|
447
265
|
if (!flags.has(flag)) operationInvalid(`unknown option '${flag}'`);
|
|
448
266
|
if (values[flag] !== undefined) operationInvalid(`duplicate option '${flag}'`);
|
|
449
267
|
values[flag] = true;
|
|
@@ -463,13 +281,8 @@ function value(values: Record<string, string | boolean>, flag: string): string |
|
|
|
463
281
|
return typeof current === 'string' ? current : undefined;
|
|
464
282
|
}
|
|
465
283
|
|
|
466
|
-
function required(values: Record<string, string | boolean>, flags: readonly string[]): void {
|
|
467
|
-
const missing = flags.find((flag) => value(values, flag) === undefined);
|
|
468
|
-
if (missing) operationInvalid(`option '${missing}' is required`);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
284
|
export function parseTaskControlOperation(
|
|
472
|
-
family: 'task-lifecycle' | 'task-
|
|
285
|
+
family: 'task-lifecycle' | 'task-finalization',
|
|
473
286
|
args: readonly string[]
|
|
474
287
|
): TaskControlOperation {
|
|
475
288
|
if (family === 'task-finalization') {
|
|
@@ -484,124 +297,21 @@ export function parseTaskControlOperation(
|
|
|
484
297
|
if (args.length < 2) operationInvalid('task ref and intent are required');
|
|
485
298
|
const taskRef = args[0]!;
|
|
486
299
|
const intent = args[1]!;
|
|
487
|
-
if (
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
};
|
|
505
|
-
if (intent === 'recover-started') {
|
|
506
|
-
const recoveryFlags = new Set(['--agent', '--auto']);
|
|
507
|
-
for (const flag of Object.keys(values)) {
|
|
508
|
-
if (!recoveryFlags.has(flag)) operationInvalid(`option '${flag}' is not supported for recover-started`);
|
|
509
|
-
}
|
|
510
|
-
if (values['--auto'] !== true) operationInvalid('--auto is required for recover-started');
|
|
511
|
-
return { family, request: input as unknown as TaskLifecycleControlRequest };
|
|
512
|
-
} else if (values['--auto'] !== undefined) {
|
|
513
|
-
operationInvalid('--auto is only supported for recover-started');
|
|
514
|
-
}
|
|
515
|
-
return { family, request: input as unknown as TaskLifecycleControlRequest };
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
const values = parseValues(args, 2, ORCHESTRATION_FLAGS);
|
|
519
|
-
const orchestrationIntents = new Set<TaskControlOrchestrationIntent>([
|
|
520
|
-
'begin-or-resume', 'route', 'prepare', 'dispatch', 'await-activation', 'recover-prepared',
|
|
521
|
-
'hook-start', 'hook-stop', 'advance', 'pause', 'status'
|
|
522
|
-
]);
|
|
523
|
-
if (!orchestrationIntents.has(intent as TaskControlOrchestrationIntent)) {
|
|
524
|
-
operationInvalid(`unknown orchestration intent '${intent}'`);
|
|
525
|
-
}
|
|
526
|
-
const client = value(values, '--client');
|
|
527
|
-
if (client !== undefined && !isAgentClientId(client)) operationInvalid(`unknown client '${client}'`);
|
|
528
|
-
const parsedIntent = intent as TaskControlOrchestrationIntent;
|
|
529
|
-
const input: Record<string, unknown> = {};
|
|
530
|
-
if (parsedIntent === 'begin-or-resume' || parsedIntent === 'prepare') {
|
|
531
|
-
required(values, ['--client']);
|
|
532
|
-
if (!client || !isAgentClientId(client)) operationInvalid(`unknown client '${client ?? ''}'`);
|
|
533
|
-
input.client = client;
|
|
534
|
-
}
|
|
535
|
-
if (parsedIntent === 'begin-or-resume') {
|
|
536
|
-
const maxSteps = value(values, '--max-steps');
|
|
537
|
-
if (maxSteps !== undefined) {
|
|
538
|
-
const parsed = Number(maxSteps);
|
|
539
|
-
if (!Number.isInteger(parsed) || parsed < 1) operationInvalid('--max-steps must be a positive integer');
|
|
540
|
-
input.maxSteps = parsed;
|
|
541
|
-
}
|
|
542
|
-
const policyFlags = ['--executor-model', '--executor-reasoning-effort', '--reviewer-model', '--reviewer-reasoning-effort'];
|
|
543
|
-
const hasPolicy = policyFlags.some((flag) => value(values, flag) !== undefined);
|
|
544
|
-
if (hasPolicy && policyFlags.some((flag) => value(values, flag) === undefined)) {
|
|
545
|
-
operationInvalid('explicit model policy requires executor/reviewer model and reasoning effort');
|
|
546
|
-
}
|
|
547
|
-
if (hasPolicy) {
|
|
548
|
-
input.modelPolicy = {
|
|
549
|
-
executor: { model: value(values, '--executor-model'), reasoningEffort: value(values, '--executor-reasoning-effort') },
|
|
550
|
-
reviewer: { model: value(values, '--reviewer-model'), reasoningEffort: value(values, '--reviewer-reasoning-effort') }
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
if (parsedIntent === 'prepare') {
|
|
555
|
-
input.requestedModel = value(values, '--requested-model');
|
|
556
|
-
input.requestedReasoningEffort = value(values, '--requested-reasoning-effort');
|
|
557
|
-
}
|
|
558
|
-
if (parsedIntent === 'await-activation') {
|
|
559
|
-
required(values, ['--stage', '--round', '--artifact', '--role']);
|
|
560
|
-
const round = Number(value(values, '--round'));
|
|
561
|
-
if (!Number.isSafeInteger(round) || round < 1) operationInvalid('--round must be a positive integer');
|
|
562
|
-
const role = value(values, '--role');
|
|
563
|
-
if (role !== 'executor' && role !== 'reviewer') operationInvalid('--role must be executor or reviewer');
|
|
564
|
-
input.event = { stage: value(values, '--stage'), round, artifact: value(values, '--artifact'), role };
|
|
565
|
-
}
|
|
566
|
-
if (parsedIntent === 'hook-start') {
|
|
567
|
-
required(values, ['--native-agent', '--child-id', '--parent-id']);
|
|
568
|
-
if (taskRef === 'auto') required(values, ['--client']);
|
|
569
|
-
input.auto = taskRef === 'auto';
|
|
570
|
-
input.client = value(values, '--client');
|
|
571
|
-
input.event = {
|
|
572
|
-
nativeAgent: value(values, '--native-agent'), childId: value(values, '--child-id'), parentId: value(values, '--parent-id'),
|
|
573
|
-
spawnMode: value(values, '--spawn-mode'), actualModel: value(values, '--actual-model'),
|
|
574
|
-
actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
|
|
575
|
-
reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
|
|
576
|
-
};
|
|
577
|
-
}
|
|
578
|
-
if (parsedIntent === 'hook-stop') {
|
|
579
|
-
input.auto = taskRef === 'auto';
|
|
580
|
-
if (input.auto) {
|
|
581
|
-
required(values, ['--client', '--native-agent', '--child-id']);
|
|
582
|
-
input.client = value(values, '--client');
|
|
583
|
-
input.event = {
|
|
584
|
-
nativeAgent: value(values, '--native-agent'), childId: value(values, '--child-id'), actualModel: value(values, '--actual-model'),
|
|
585
|
-
actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
|
|
586
|
-
reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
|
|
587
|
-
};
|
|
588
|
-
} else {
|
|
589
|
-
required(values, ['--child-id', '--exit-code', '--after-fingerprint']);
|
|
590
|
-
const exitCode = Number(value(values, '--exit-code'));
|
|
591
|
-
if (!Number.isInteger(exitCode)) operationInvalid('--exit-code must be an integer');
|
|
592
|
-
input.event = {
|
|
593
|
-
childId: value(values, '--child-id'), exitCode, afterFingerprint: value(values, '--after-fingerprint'),
|
|
594
|
-
changedPaths: value(values, '--changed-paths')?.split(',').filter(Boolean) ?? [], actualModel: value(values, '--actual-model'),
|
|
595
|
-
actualReasoningEffort: value(values, '--actual-reasoning-effort'), modelFallbackReason: value(values, '--model-fallback-reason'),
|
|
596
|
-
reasoningEffortFallbackReason: value(values, '--reasoning-effort-fallback-reason')
|
|
597
|
-
};
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
if (parsedIntent === 'pause') {
|
|
601
|
-
required(values, ['--code', '--message', '--recoverable']);
|
|
602
|
-
const recoverable = value(values, '--recoverable');
|
|
603
|
-
if (recoverable !== 'true' && recoverable !== 'false') operationInvalid('--recoverable must be true or false');
|
|
604
|
-
input.code = value(values, '--code'); input.message = value(values, '--message'); input.recoverable = recoverable === 'true';
|
|
605
|
-
}
|
|
606
|
-
return { family, taskRef, intent: parsedIntent, input };
|
|
300
|
+
if (intent === 'complete') operationInvalid('complete must use task-finalization');
|
|
301
|
+
const values = parseValues(args, 2, LIFECYCLE_FLAGS);
|
|
302
|
+
const agent = normalizeAgentToken(value(values, '--agent') ?? '');
|
|
303
|
+
if (!agent) operationInvalid('lifecycle agent is invalid');
|
|
304
|
+
const request: Record<string, unknown> = {
|
|
305
|
+
taskRef,
|
|
306
|
+
intent,
|
|
307
|
+
agent,
|
|
308
|
+
...(value(values, '--reason') ? { reason: value(values, '--reason') } : {}),
|
|
309
|
+
...(value(values, '--unblock-condition') ? { unblockCondition: value(values, '--unblock-condition') } : {}),
|
|
310
|
+
...(value(values, '--note') ? { note: value(values, '--note') } : {}),
|
|
311
|
+
...(value(values, '--staging-dir') ? { stagingDir: value(values, '--staging-dir') } : {}),
|
|
312
|
+
...(value(values, '--alert-number') ? { alertNumber: Number(value(values, '--alert-number')) } : {}),
|
|
313
|
+
...(value(values, '--issue-number') ? { issueNumber: Number(value(values, '--issue-number')) } : {}),
|
|
314
|
+
...(values['--dry-run'] === true ? { dryRun: true } : {})
|
|
315
|
+
};
|
|
316
|
+
return { family, request: request as unknown as TaskLifecycleControlRequest };
|
|
607
317
|
}
|
|
@@ -51,7 +51,7 @@ export type ControlRecoveryDecision = Readonly<{
|
|
|
51
51
|
reasonCode: string;
|
|
52
52
|
}>;
|
|
53
53
|
|
|
54
|
-
const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'close-codescan', 'close-dependabot', 'restore'
|
|
54
|
+
const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'close-codescan', 'close-dependabot', 'restore'] as const;
|
|
55
55
|
export const SANDBOX_CONTROL_RECOVERY_OPERATIONS: readonly ControlRecoveryOperation[] = Object.freeze([
|
|
56
56
|
...LIFECYCLE_INTENTS.map((intent) => ({ family: 'task-lifecycle' as const, intent, class: 'lifecycle-mutation' })),
|
|
57
57
|
{ family: 'task-create', intent: 'create', class: 'task-create' }
|
|
@@ -73,13 +73,10 @@ function bindingMatchesResult(binding: ControlRecoveryBinding, result: Readonly<
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
function domainEvidenceMatches(
|
|
76
|
-
operation: ControlRecoveryOperation,
|
|
77
|
-
result: Readonly<Record<string, unknown>>,
|
|
78
76
|
domain: Readonly<Record<string, unknown>> | null | undefined
|
|
79
77
|
): boolean {
|
|
80
78
|
if (!domain) return false;
|
|
81
79
|
if (domain.consistent !== true) return false;
|
|
82
|
-
if (operation.family === 'task-lifecycle' && operation.intent === 'recover-started') return false;
|
|
83
80
|
return true;
|
|
84
81
|
}
|
|
85
82
|
|
|
@@ -110,7 +107,7 @@ export function classifySandboxControlRecovery(input: ControlRecoveryInput): Con
|
|
|
110
107
|
if (result.changed === null) {
|
|
111
108
|
return { outcome: 'unknown', responseReconstructable: false, reasonCode: 'RECOVERY_RESULT_CHANGE_FLAG_MISSING' };
|
|
112
109
|
}
|
|
113
|
-
if (!domainEvidenceMatches(input.
|
|
110
|
+
if (!domainEvidenceMatches(input.domain)) {
|
|
114
111
|
if (input.journal?.exists && (input.journal.completedSteps?.length ?? 0) > 0) {
|
|
115
112
|
return { outcome: 'in-progress', responseReconstructable: false, reasonCode: 'RECOVERY_DOMAIN_EVIDENCE_INCOMPLETE' };
|
|
116
113
|
}
|
package/lib/task/create.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { readDeliveryDefaults, validateBaseRef, validateRemote } from './deliver
|
|
|
9
9
|
import { buildUnboundFact, encodePrDeliveryFact } from './pr-delivery-fact.ts';
|
|
10
10
|
import { CANDIDATE_COLUMNS, CONSTRAINT_COLUMNS, parseTaskQualification } from './qualification-audit.ts';
|
|
11
11
|
import { enumerateAllTaskDirs } from './resolve-ref.ts';
|
|
12
|
+
import { serializeLifecycleExecution } from './lifecycle-execution.ts';
|
|
12
13
|
import { parseTaskFrontmatter } from './frontmatter.ts';
|
|
13
14
|
import { AGENT_TOKEN_VALUES, type AgentToken } from '../agent-clients/tokens.ts';
|
|
14
15
|
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.ts';
|
|
@@ -59,7 +60,6 @@ function payloadError(message: string): never {
|
|
|
59
60
|
|
|
60
61
|
function exactKeys(value: Record<string, unknown>, expected: readonly string[], label: string, optional: readonly string[] = []): void {
|
|
61
62
|
const actual = Object.keys(value).sort();
|
|
62
|
-
const wanted = [...expected].sort();
|
|
63
63
|
const allowed = new Set([...expected, ...optional]);
|
|
64
64
|
if (actual.some((key) => !allowed.has(key))) {
|
|
65
65
|
payloadError(`${label} has unknown or missing fields`);
|
|
@@ -170,10 +170,6 @@ function taskIdFor(date: Date): string {
|
|
|
170
170
|
return `TASK-${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
function yamlString(value: string): string {
|
|
174
|
-
return JSON.stringify(value);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
173
|
function markdownBlock(value: string): string {
|
|
178
174
|
return value.split(/\r?\n/).map((line) => /^(?:#{1,6}\s|```)/.test(line) ? `\\${line}` : line).join('\n');
|
|
179
175
|
}
|
|
@@ -289,6 +285,7 @@ function renderTask(params: Readonly<{
|
|
|
289
285
|
'target_date:',
|
|
290
286
|
'current_step: requirement-analysis',
|
|
291
287
|
`assigned_to: ${candidate.agent}`,
|
|
288
|
+
`lifecycle_execution: ${JSON.stringify(serializeLifecycleExecution([]))}`,
|
|
292
289
|
`pr_delivery_fact: ${JSON.stringify(encodePrDeliveryFact(buildUnboundFact()))}`,
|
|
293
290
|
`delivery_remote: ${candidate.deliveryRemote ?? params.delivery.remote}`,
|
|
294
291
|
`delivery_base_ref: ${candidate.deliveryBaseRef ?? params.delivery.baseRef}`,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
|
|
3
|
-
import { appendActivityEntry, locateActivityLog } from './activity-log.ts';
|
|
3
|
+
import { activityWarnings, appendActivityEntry, locateActivityLog } from './activity-log.ts';
|
|
4
4
|
import { isDecisionItem, listDecisionItems, selectDecisionItem } from './decision-items.ts';
|
|
5
5
|
import {
|
|
6
6
|
createImplementationInput,
|
|
@@ -31,6 +31,7 @@ type HumanDecisionResult = {
|
|
|
31
31
|
taskId: string | null; ledgerId: string | null; recordId: string | null;
|
|
32
32
|
implementationInputId: string | null; operations: readonly TaskOperationSummary[];
|
|
33
33
|
error: { code: string; message: string } | null;
|
|
34
|
+
warnings?: readonly { code: string; message: string }[];
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
const DECISION_ALIASES = ['人工裁决', 'Human Rulings', 'Human Decisions', 'Human Decision'] as const;
|
|
@@ -102,7 +103,7 @@ function applyHumanDecision(request: HumanDecisionRequest, options: TaskWriteOpt
|
|
|
102
103
|
try {
|
|
103
104
|
const replay = existingDecision(content, direct[0]!, request.decision.trim(), request.needsImplementation);
|
|
104
105
|
if ('conflict' in replay) return failed('DECISION_CONFLICT', replay.conflict, resolved.taskId, direct[0]!.id);
|
|
105
|
-
return { status: 'no-op', changed: false, taskId: resolved.taskId, ledgerId: direct[0]!.id, recordId: replay.recordId, implementationInputId: replay.implementationInputId, operations: [], error: null };
|
|
106
|
+
return { status: 'no-op', changed: false, taskId: resolved.taskId, ledgerId: direct[0]!.id, recordId: replay.recordId, implementationInputId: replay.implementationInputId, operations: [], error: null, warnings: activityWarnings(content) };
|
|
106
107
|
} catch (error) { return failed('DECISION_DOCUMENT_INVALID', error instanceof Error ? error.message : String(error), resolved.taskId, direct[0]!.id); }
|
|
107
108
|
}
|
|
108
109
|
|
|
@@ -144,7 +145,6 @@ function applyHumanDecision(request: HumanDecisionRequest, options: TaskWriteOpt
|
|
|
144
145
|
const decision = request.decision.trim();
|
|
145
146
|
const record = `### ${recordId}\n\n- **原账本 ID**:${row.id}\n- **裁决时间**:${metadata.timestamp}\n- **裁决结果**:${decision}`;
|
|
146
147
|
const activity = locateActivityLog(content);
|
|
147
|
-
if (!activity) return failed('DECISION_ACTIVITY_MISSING', 'activity log section is missing or ambiguous', resolved.taskId, row.id);
|
|
148
148
|
const mutations: TaskMutation[] = [
|
|
149
149
|
{
|
|
150
150
|
kind: 'table-row', action: 'upsert', sectionAliases: LEDGER_HEADINGS, columns: LEDGER_COLUMNS,
|
|
@@ -172,7 +172,7 @@ function applyHumanDecision(request: HumanDecisionRequest, options: TaskWriteOpt
|
|
|
172
172
|
body: renderImplementationInputs(nextInputs)
|
|
173
173
|
});
|
|
174
174
|
}
|
|
175
|
-
mutations.push({
|
|
175
|
+
if (activity) mutations.push({
|
|
176
176
|
kind: 'section', aliases: ACTIVITY_ALIASES, heading: activity.heading,
|
|
177
177
|
body: appendActivityEntry(activity, { time: metadata.timestamp, step: 'Human Decision', agent: 'human', note: `${row.id} decided → ${recordId}` })
|
|
178
178
|
});
|
|
@@ -190,7 +190,7 @@ function applyHumanDecision(request: HumanDecisionRequest, options: TaskWriteOpt
|
|
|
190
190
|
metadataProvider: () => metadata
|
|
191
191
|
});
|
|
192
192
|
if (writeResult.status === 'failed') return failed(writeResult.error.code, writeResult.error.message, writeResult.taskId, row.id);
|
|
193
|
-
return { status: writeResult.status, changed: writeResult.changed, taskId: writeResult.taskId, ledgerId: row.id, recordId, implementationInputId, operations: writeResult.operations, error: null };
|
|
193
|
+
return { status: writeResult.status, changed: writeResult.changed, taskId: writeResult.taskId, ledgerId: row.id, recordId, implementationInputId, operations: writeResult.operations, error: null, warnings: activityWarnings(content) };
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
export { applyHumanDecision };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { execFileSync } from 'node:child_process';
|
|
4
3
|
|
|
5
4
|
export type DeliveryTarget = Readonly<{
|
|
6
5
|
remote: string;
|
|
@@ -82,49 +81,10 @@ function resolveDeliveryTarget(
|
|
|
82
81
|
return bindDeliveryTarget({ defaults: defaults.value, existing, explicit });
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
function gitText(repoRoot: string, args: readonly string[]): string {
|
|
86
|
-
return execFileSync('git', [...args], {
|
|
87
|
-
cwd: repoRoot,
|
|
88
|
-
encoding: 'utf8',
|
|
89
|
-
stdio: ['ignore', 'pipe', 'pipe']
|
|
90
|
-
}).trim();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function resolveTargetHead(repoRoot: string, target: DeliveryTarget): DeliveryTargetResult & { head?: string } {
|
|
94
|
-
try {
|
|
95
|
-
const output = gitText(repoRoot, ['ls-remote', '--refs', target.remote, `refs/heads/${target.baseRef}`]);
|
|
96
|
-
const head = output.split(/\s+/)[0] ?? '';
|
|
97
|
-
if (!/^[a-f0-9]{40}$/i.test(head)) {
|
|
98
|
-
return { ok: false, code: 'DELIVERY_TARGET_UNAVAILABLE', message: `Delivery target ${target.remote}/${target.baseRef} is unavailable` };
|
|
99
|
-
}
|
|
100
|
-
try { gitText(repoRoot, ['cat-file', '-e', `${head}^{commit}`]); }
|
|
101
|
-
catch {
|
|
102
|
-
return { ok: false, code: 'DELIVERY_TARGET_OBJECT_MISSING', message: `Delivery target commit ${head} is not available locally` };
|
|
103
|
-
}
|
|
104
|
-
return { ok: true, value: target, head };
|
|
105
|
-
} catch (error) {
|
|
106
|
-
return { ok: false, code: 'DELIVERY_TARGET_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) };
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function resolveDiffBase(repoRoot: string, reviewedHead: string, targetHead: string): DiffBaseResult {
|
|
111
|
-
try {
|
|
112
|
-
const diffBase = gitText(repoRoot, ['merge-base', reviewedHead, targetHead]);
|
|
113
|
-
if (!/^[a-f0-9]{40}$/i.test(diffBase)) {
|
|
114
|
-
return { ok: false, code: 'DELIVERY_DIFF_BASE_UNAVAILABLE', message: 'Git returned an invalid diff base' };
|
|
115
|
-
}
|
|
116
|
-
return { ok: true, diffBase };
|
|
117
|
-
} catch (error) {
|
|
118
|
-
return { ok: false, code: 'DELIVERY_DIFF_BASE_UNAVAILABLE', message: error instanceof Error ? error.message : String(error) };
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
84
|
export {
|
|
123
85
|
bindDeliveryTarget,
|
|
124
86
|
readDeliveryDefaults,
|
|
125
87
|
resolveDeliveryTarget,
|
|
126
|
-
resolveTargetHead,
|
|
127
|
-
resolveDiffBase,
|
|
128
88
|
validateBaseRef,
|
|
129
89
|
validateRemote
|
|
130
90
|
};
|