@fitlab-ai/agent-infra 0.11.14 → 0.12.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 +1 -1
- package/dist/bin/cli.js +1 -1
- package/dist/bin/internal-cli.js +6 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +6 -6
- package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +8 -18
- package/dist/lib/agent-clients/adapters/codex-orchestration.js +1 -1
- package/dist/lib/decide.js +2 -7
- package/dist/lib/internal/cli-route-inventory.js +3 -0
- package/dist/lib/internal/manual-validation.js +8 -16
- package/dist/lib/internal/platform-comment.js +3 -2
- package/dist/lib/internal/task-activity.js +1 -12
- package/dist/lib/internal/task-event.js +1 -12
- package/dist/lib/internal/task-finalization.js +2 -2
- package/dist/lib/internal/task-ledger.js +1 -12
- package/dist/lib/internal/task-operation-registry.js +2 -1
- package/dist/lib/internal/task-qualification.js +6 -15
- package/dist/lib/internal/task-review.js +3 -16
- package/dist/lib/internal/task-short-id.js +2 -1
- package/dist/lib/internal/task-verify.js +1 -11
- package/dist/lib/internal/task-warning.js +1 -12
- package/dist/lib/internal/task-workspace.js +43 -0
- package/dist/lib/merge.js +4 -3
- package/dist/lib/platform/pr-change-report.js +10 -3
- package/dist/lib/platform/pr-summary.js +6 -15
- package/dist/lib/platform/pull-requests.js +3 -15
- package/dist/lib/pr-review/evidence-grading.js +3 -2
- package/dist/lib/process-data/index.js +18 -6
- package/dist/lib/process-data/sources.js +6 -0
- package/dist/lib/run/index.js +3 -2
- package/dist/lib/sandbox/commands/create.js +5 -1
- package/dist/lib/sandbox/commands/enter.js +1 -1
- package/dist/lib/sandbox/commands/list-running.js +2 -1
- package/dist/lib/sandbox/control/client.js +8 -13
- package/dist/lib/sandbox/control/completed-reentry.js +2 -1
- package/dist/lib/sandbox/control/lifecycle.js +2 -21
- package/dist/lib/sandbox/control/task-view.js +4 -2
- package/dist/lib/sandbox/mounts.js +4 -4
- package/dist/lib/sandbox/recovery.js +26 -16
- package/dist/lib/sandbox/removal.js +3 -10
- package/dist/lib/sandbox/task-resolver.js +9 -6
- package/dist/lib/sandbox/workspace-identity.js +36 -20
- package/dist/lib/sandbox/workspace-view.js +29 -22
- package/dist/lib/task/activity-intent.js +2 -12
- package/dist/lib/task/artifact-lifecycle.js +17 -11
- package/dist/lib/task/artifact-operations.js +41 -49
- package/dist/lib/task/capabilities.js +2 -2
- package/dist/lib/task/commands/ls.js +4 -3
- package/dist/lib/task/commands/status.js +1 -1
- package/dist/lib/task/commit-operation.js +6 -6
- package/dist/lib/task/control-authority.js +32 -32
- package/dist/lib/task/create-service.js +2 -4
- package/dist/lib/task/create.js +12 -65
- package/dist/lib/task/delegation-receipts.js +1 -1
- package/dist/lib/task/delivery.js +2 -8
- package/dist/lib/task/events.js +5 -31
- package/dist/lib/task/finalization.js +17 -22
- package/dist/lib/task/lifecycle.js +38 -49
- package/dist/lib/task/local-artifact-finalization.js +1 -2
- package/dist/lib/task/orchestration.js +24 -57
- package/dist/lib/task/platform-operation-recovery.js +1 -2
- package/dist/lib/task/resolve-ref.js +17 -12
- package/dist/lib/task/review-finalization.js +2 -35
- package/dist/lib/task/review-identity.js +3 -1
- package/dist/lib/task/short-id.js +12 -10
- package/dist/lib/task/verification-engine.js +19 -58
- package/dist/lib/task/workspace-root.js +59 -0
- package/dist/lib/task/workspace-snapshot.js +4 -3
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +6 -6
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +8 -34
- package/lib/agent-clients/adapters/codex-orchestration.ts +1 -1
- package/lib/decide.ts +2 -7
- package/lib/internal/cli-route-inventory.ts +2 -0
- package/lib/internal/manual-validation.ts +8 -19
- package/lib/internal/platform-comment.ts +3 -2
- package/lib/internal/task-activity.ts +1 -10
- package/lib/internal/task-event.ts +1 -10
- package/lib/internal/task-finalization.ts +2 -2
- package/lib/internal/task-ledger.ts +1 -10
- package/lib/internal/task-operation-registry.ts +2 -1
- package/lib/internal/task-qualification.ts +5 -11
- package/lib/internal/task-review.ts +3 -14
- package/lib/internal/task-short-id.ts +2 -1
- package/lib/internal/task-verify.ts +1 -9
- package/lib/internal/task-warning.ts +1 -10
- package/lib/internal/task-workspace.ts +39 -0
- package/lib/merge.ts +4 -3
- package/lib/platform/pr-change-report.ts +9 -3
- package/lib/platform/pr-summary.ts +7 -16
- package/lib/platform/pull-requests.ts +3 -24
- package/lib/pr-review/evidence-grading.ts +3 -2
- package/lib/process-data/index.ts +17 -5
- package/lib/process-data/sources.ts +6 -0
- package/lib/run/index.ts +3 -2
- package/lib/sandbox/commands/create.ts +5 -1
- package/lib/sandbox/commands/enter.ts +1 -1
- package/lib/sandbox/commands/list-running.ts +2 -1
- package/lib/sandbox/control/client.ts +7 -12
- package/lib/sandbox/control/completed-reentry.ts +2 -1
- package/lib/sandbox/control/lifecycle.ts +4 -21
- package/lib/sandbox/control/task-view.ts +4 -2
- package/lib/sandbox/mounts.ts +4 -4
- package/lib/sandbox/recovery.ts +26 -18
- package/lib/sandbox/removal.ts +3 -26
- package/lib/sandbox/task-resolver.ts +9 -6
- package/lib/sandbox/workspace-identity.ts +42 -18
- package/lib/sandbox/workspace-view.ts +28 -20
- package/lib/task/activity-intent.ts +3 -17
- package/lib/task/artifact-lifecycle.ts +39 -11
- package/lib/task/artifact-operations.ts +28 -35
- package/lib/task/capabilities.ts +2 -2
- package/lib/task/commands/ls.ts +4 -3
- package/lib/task/commands/status.ts +1 -1
- package/lib/task/commit-operation.ts +5 -6
- package/lib/task/control-authority.ts +29 -35
- package/lib/task/create-service.ts +2 -4
- package/lib/task/create.ts +10 -51
- package/lib/task/delegation-receipts.ts +1 -1
- package/lib/task/delivery.ts +2 -10
- package/lib/task/events.ts +5 -32
- package/lib/task/finalization.ts +16 -24
- package/lib/task/lifecycle.ts +40 -51
- package/lib/task/local-artifact-finalization.ts +1 -4
- package/lib/task/orchestration.ts +31 -80
- package/lib/task/platform-operation-recovery.ts +1 -2
- package/lib/task/resolve-ref.ts +18 -12
- package/lib/task/review-finalization.ts +2 -52
- package/lib/task/review-identity.ts +3 -1
- package/lib/task/short-id.ts +15 -10
- package/lib/task/verification-engine.ts +20 -62
- package/lib/task/workspace-root.ts +78 -0
- package/lib/task/workspace-snapshot.ts +4 -3
- package/package.json +1 -1
- package/templates/.agents/QUICKSTART.en.md +19 -8
- package/templates/.agents/QUICKSTART.zh-CN.md +19 -8
- package/templates/.agents/README.en.md +10 -15
- package/templates/.agents/README.zh-CN.md +9 -13
- package/templates/.agents/rules/issue-sync.en.md +1 -1
- package/templates/.agents/rules/issue-sync.zh-CN.md +1 -1
- package/templates/.agents/rules/lifecycle-orchestration.en.md +1 -1
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +1 -1
- package/templates/.agents/rules/next-step-output.en.md +2 -2
- package/templates/.agents/rules/next-step-output.zh-CN.md +2 -2
- 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/release-commands.en.md +3 -0
- package/templates/.agents/rules/release-commands.zh-CN.md +3 -0
- package/templates/.agents/rules/task-management.en.md +0 -2
- package/templates/.agents/rules/task-management.zh-CN.md +0 -2
- package/templates/.agents/rules/task-short-id.en.md +2 -2
- package/templates/.agents/rules/task-short-id.zh-CN.md +2 -2
- package/templates/.agents/scripts/task-short-id.js +2 -8
- 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 +0 -1
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/archive-tasks/SKILL.en.md +5 -5
- package/templates/.agents/skills/archive-tasks/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/archive-tasks/scripts/archive-tasks.sh +10 -2
- package/templates/.agents/skills/block-task/SKILL.en.md +4 -4
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/block-task/config/verify.json +0 -1
- package/templates/.agents/skills/cancel-task/SKILL.en.md +6 -6
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +6 -6
- package/templates/.agents/skills/cancel-task/config/verify.json +0 -1
- package/templates/.agents/skills/code-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/code-task/config/verify.en.json +0 -1
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/code-task/reference/output-template.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/SKILL.en.md +1 -1
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/config/verify.json +0 -1
- package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +2 -2
- package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +2 -2
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +2 -2
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +0 -1
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +17 -9
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +18 -10
- package/templates/.agents/skills/complete-task/config/verify.en.json +0 -1
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/create-pr/SKILL.en.md +3 -3
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/create-pr/config/verify.json +0 -1
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +13 -3
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +13 -3
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
- package/templates/.agents/skills/create-release-note/SKILL.en.md +2 -2
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/create-task/SKILL.en.md +4 -4
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/create-task/config/verify.json +0 -1
- package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-codescan/config/verify.json +0 -1
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +3 -3
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/import-dependabot/config/verify.json +0 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +5 -5
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/import-issue/config/verify.json +0 -1
- package/templates/.agents/skills/plan-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/plan-task/config/verify.en.json +0 -1
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/restore-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/restore-task/config/verify.json +0 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-analysis/config/verify.en.json +0 -1
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +5 -5
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +5 -5
- 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/reference/output-templates.en.md +4 -4
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +4 -4
- package/templates/.agents/skills/review-plan/SKILL.en.md +1 -1
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-plan/config/verify.en.json +0 -1
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +5 -5
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +5 -5
- package/templates/.agents/skills/review-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/review-pr/config/verify.en.json +0 -1
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +1 -1
- package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +1 -1
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -5
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +0 -1
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +0 -1
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +13 -2
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +13 -2
- 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 +0 -3
- package/templates/.agents/skills/test/SKILL.zh-CN.md +0 -3
- package/templates/.agents/skills/test-integration/SKILL.en.md +0 -3
- package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +0 -3
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +13 -6
- package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +0 -3
- package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +0 -3
- package/templates/.agents/skills/watch-pr/SKILL.en.md +21 -4
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +22 -5
- package/templates/.agents/skills/watch-pr/config/verify.json +0 -1
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +14 -0
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +15 -1
- package/templates/.agents/templates/handoff.en.md +1 -1
- package/templates/.agents/templates/handoff.zh-CN.md +1 -1
- package/templates/.agents/workflows/bug-fix.en.yaml +1 -1
- package/templates/.agents/workflows/feature-development.en.yaml +1 -1
- package/templates/.agents/workflows/refactoring.en.yaml +1 -1
- package/dist/lib/runtime/agent-runtime.js +0 -33
- package/dist/lib/task/runtime-paths.js +0 -10
- package/dist/lib/task/task-execution-lock.js +0 -250
- package/lib/runtime/agent-runtime.ts +0 -41
- package/lib/task/runtime-paths.ts +0 -12
- package/lib/task/task-execution-lock.ts +0 -320
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
2
3
|
import { execFileSync } from 'node:child_process';
|
|
3
4
|
import { commitExplicitPaths, inspectGitWorkflow, pushGitRefs } from '../git/workflow.js';
|
|
4
5
|
import { parseTaskFrontmatter } from './frontmatter.js';
|
|
@@ -6,7 +7,6 @@ import { checkpointCommitMatches } from './commit-identity.js';
|
|
|
6
7
|
import { resolveTaskContext, resolveTaskRef } from './resolve-ref.js';
|
|
7
8
|
import { commitPushDecision } from './commit-policy.js';
|
|
8
9
|
import { mergeOperationWarnings } from './operation-outcome.js';
|
|
9
|
-
import { TaskExecutionLockError, withRepositoryMutationLock, withTaskExecutionLock } from './task-execution-lock.js';
|
|
10
10
|
import { appendActivityEntry, locateActivityLog } from './activity-log.js';
|
|
11
11
|
import { captureTaskWriteMetadata, writeTask } from './write.js';
|
|
12
12
|
import { checkpointIntentDigest, readCheckpointIntent, removeCheckpointIntent, sameCheckpointIntent, updateCheckpointIntent, writeCheckpointIntent } from './commit-intent.js';
|
|
@@ -58,6 +58,8 @@ function resolveBoundTask(input) {
|
|
|
58
58
|
};
|
|
59
59
|
return boundTask(input, resolved.taskId, resolved.taskDir, resolved.taskMdPath, resolved.repoRoot, resolved.state);
|
|
60
60
|
}
|
|
61
|
+
if (!fs.existsSync(path.join(input.cwd, '.agents', '.airc.json')))
|
|
62
|
+
return { kind: 'none' };
|
|
61
63
|
const context = resolveTaskContext(undefined, { repoRoot: input.cwd });
|
|
62
64
|
if (context.ok)
|
|
63
65
|
return boundTask(input, context.taskId, context.taskDir, context.taskMdPath, context.repoRoot, context.state);
|
|
@@ -181,7 +183,7 @@ function checkpointIdentity(input, task, delivery) {
|
|
|
181
183
|
function checkpointTimestamp() {
|
|
182
184
|
return new Date().toISOString();
|
|
183
185
|
}
|
|
184
|
-
function
|
|
186
|
+
function executeCommitOperationCore(input, task, mode) {
|
|
185
187
|
const inspected = inspectGitWorkflow(input.cwd);
|
|
186
188
|
if (!inspected.snapshot)
|
|
187
189
|
return failure(input, mode, task?.taskId ?? null, 'GIT_INSPECT_FAILED', 'Unable to inspect Git repository');
|
|
@@ -432,12 +434,10 @@ function executeCommitOperation(input) {
|
|
|
432
434
|
if (mode === 'orchestrated' && !task)
|
|
433
435
|
return failure(normalizedInput, mode, null, 'ORCHESTRATION_TASK_REQUIRED', 'orchestrated commit requires a task context', 'blocked');
|
|
434
436
|
try {
|
|
435
|
-
return task
|
|
436
|
-
? withRepositoryMutationLock(normalizedInput.cwd, () => withTaskExecutionLock(normalizedInput.cwd, task.taskId, 'commit-operation', () => executeUnlocked(normalizedInput, task, mode)))
|
|
437
|
-
: withRepositoryMutationLock(normalizedInput.cwd, () => executeUnlocked(normalizedInput, null, mode));
|
|
437
|
+
return executeCommitOperationCore(normalizedInput, task, mode);
|
|
438
438
|
}
|
|
439
439
|
catch (error) {
|
|
440
|
-
const code =
|
|
440
|
+
const code = 'COMMIT_OPERATION_FAILED';
|
|
441
441
|
return failure(normalizedInput, mode, task?.taskId ?? null, code, error instanceof Error ? error.message : String(error), 'blocked');
|
|
442
442
|
}
|
|
443
443
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
1
2
|
import path from 'node:path';
|
|
2
3
|
import { normalizeAgentToken } from '../agent-clients/tokens.js';
|
|
3
4
|
import { isAgentClientId } from '../agent-clients/types.js';
|
|
@@ -5,10 +6,10 @@ import { sandboxControlPaths } from '../sandbox/workspace-view.js';
|
|
|
5
6
|
import { getAgentClientAdapter } from '../agent-clients/registry.js';
|
|
6
7
|
import { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, advanceOrchestration, awaitOrchestrationDelegationActivation, beginOrResumeOrchestration, dispatchOrchestrationDelegation, OrchestrationStateError, pauseOrchestration, prepareOrchestrationDelegation, recoverPreparedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealOrchestrationDelegation, statusOrchestration } from './orchestration.js';
|
|
7
8
|
import { applyTaskFinalization } from './finalization.js';
|
|
8
|
-
import { applyTaskLifecycle
|
|
9
|
+
import { applyTaskLifecycle } from './lifecycle.js';
|
|
9
10
|
import { resolveTaskContext, resolveTaskRef, TASK_ID_RE } from './resolve-ref.js';
|
|
10
|
-
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
|
|
11
11
|
import { verifyTaskEvent } from './verification.js';
|
|
12
|
+
import { releaseStaleShortIdRegistry } from './short-id.js';
|
|
12
13
|
export function taskControlOperationKey(operation) {
|
|
13
14
|
if (operation.family === 'task-finalization')
|
|
14
15
|
return 'complete';
|
|
@@ -112,7 +113,7 @@ function lifecycleTaskId(request, repoRoot) {
|
|
|
112
113
|
async function applyLifecycleWithAuthority(context, request) {
|
|
113
114
|
const taskId = lifecycleTaskId(request, context.repoRoot);
|
|
114
115
|
const controlRoot = taskId ? controlRootForTask(context, taskId) : undefined;
|
|
115
|
-
const execute = async (
|
|
116
|
+
const execute = async () => {
|
|
116
117
|
if (request.intent === 'recover-started') {
|
|
117
118
|
const adapter = isAgentClientId(request.agent)
|
|
118
119
|
? getAgentClientAdapter(request.agent).orchestrationAdapter
|
|
@@ -126,36 +127,13 @@ async function applyLifecycleWithAuthority(context, request) {
|
|
|
126
127
|
}
|
|
127
128
|
return adapter.recoverStarted(request, { repoRoot: context.repoRoot });
|
|
128
129
|
}
|
|
129
|
-
return
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}, taskId)
|
|
135
|
-
: applyTaskLifecycle(request, {
|
|
136
|
-
repoRoot: context.repoRoot,
|
|
137
|
-
...(controlRoot ? { controlRoot } : {}),
|
|
138
|
-
...(context.source === 'direct-host' && context.project ? { controlProject: context.project } : {})
|
|
139
|
-
});
|
|
130
|
+
return applyTaskLifecycle(request, {
|
|
131
|
+
repoRoot: context.repoRoot,
|
|
132
|
+
...(controlRoot ? { controlRoot } : {}),
|
|
133
|
+
...(context.source === 'direct-host' && context.project ? { controlProject: context.project } : {})
|
|
134
|
+
});
|
|
140
135
|
};
|
|
141
|
-
|
|
142
|
-
return await execute();
|
|
143
|
-
try {
|
|
144
|
-
return await withTaskExecutionLock(context.repoRoot, taskId, `task-lifecycle.${request.intent}`, () => execute(true));
|
|
145
|
-
}
|
|
146
|
-
catch (error) {
|
|
147
|
-
if (!(error instanceof TaskExecutionLockError))
|
|
148
|
-
throw error;
|
|
149
|
-
if (request.intent === 'recover-started') {
|
|
150
|
-
return {
|
|
151
|
-
status: 'owner-unknown', changed: false, targetState: 'active',
|
|
152
|
-
requestRef: request.taskRef, intent: 'recover-started', taskId,
|
|
153
|
-
receiptId: null, childId: null,
|
|
154
|
-
error: { code: error.code, message: error.message }
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
return taskLifecycleFailure(request, { code: error.code, message: error.message }, taskId);
|
|
158
|
-
}
|
|
136
|
+
return await execute();
|
|
159
137
|
}
|
|
160
138
|
function controlRootForTask(context, taskId) {
|
|
161
139
|
if (context.source === 'sandbox-executor')
|
|
@@ -251,6 +229,28 @@ export function dispatchTaskControlOperation(context, operation) {
|
|
|
251
229
|
...(controlRoot ? { controlRoot } : {}),
|
|
252
230
|
...(context.source === 'direct-host' && context.project ? { controlProject: context.project } : {}),
|
|
253
231
|
preflight: (request, options) => verifyTaskEvent({ ...request, event: 'complete-task.hard-preflight' }, options)
|
|
232
|
+
}).then((result) => {
|
|
233
|
+
if (context.source !== 'direct-host' || !controlRoot || result.status !== 'completed' || !result.taskId)
|
|
234
|
+
return result;
|
|
235
|
+
try {
|
|
236
|
+
if (fs.lstatSync(controlRoot, { throwIfNoEntry: false }) === undefined) {
|
|
237
|
+
const released = releaseStaleShortIdRegistry(context.repoRoot, result.taskId);
|
|
238
|
+
return { ...result, changed: result.changed || released.changed };
|
|
239
|
+
}
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
return {
|
|
244
|
+
...result,
|
|
245
|
+
status: 'blocked',
|
|
246
|
+
result: 'blocked',
|
|
247
|
+
error: {
|
|
248
|
+
code: 'TASK_FINALIZATION_SHORT_ID_RELEASE_FAILED',
|
|
249
|
+
message: error instanceof Error ? error.message : String(error),
|
|
250
|
+
retryable: true
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
254
|
});
|
|
255
255
|
}
|
|
256
256
|
try {
|
|
@@ -3,7 +3,6 @@ import { createPlatformIssue, syncPlatformIssue } from '../platform/issues.js';
|
|
|
3
3
|
import { VERSION } from '../version.js';
|
|
4
4
|
import { applyWorkflowWarningIntent } from './workflow-warning-intents.js';
|
|
5
5
|
import { createLocalTask } from './create.js';
|
|
6
|
-
import { TaskExecutionLockError } from './task-execution-lock.js';
|
|
7
6
|
import { verifyTaskEvent } from './verification.js';
|
|
8
7
|
const DEFAULT_DEPENDENCIES = {
|
|
9
8
|
createIssue: createPlatformIssue,
|
|
@@ -152,9 +151,8 @@ async function createTask(value, options) {
|
|
|
152
151
|
}
|
|
153
152
|
catch (error) {
|
|
154
153
|
const message = error instanceof Error ? error.message : String(error);
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
return taskCreateFailure({ code, message, retryable: lockBusy || code === 'TASK_CREATE_LOCK_TIMEOUT' });
|
|
154
|
+
const code = /^([A-Z][A-Z0-9_]+)/.exec(message)?.[1] ?? 'TASK_CREATE_FAILED';
|
|
155
|
+
return taskCreateFailure({ code, message, retryable: false });
|
|
158
156
|
}
|
|
159
157
|
const operations = [{
|
|
160
158
|
name: 'task:local', status: local.status, reasonCode: null
|
package/dist/lib/task/create.js
CHANGED
|
@@ -4,13 +4,13 @@ import os from 'node:os';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { isValidAgentInfraVersion, VERSION } from '../version.js';
|
|
6
6
|
import { loadShortIdByTaskId, mutateShortIdRegistry } from './short-id.js';
|
|
7
|
-
import { TaskExecutionLockError, withRepositoryMutationLock, withTaskExecutionLock } from './task-execution-lock.js';
|
|
8
7
|
import { readDeliveryDefaults, validateBaseRef, validateRemote } from './delivery-target.js';
|
|
9
8
|
import { buildUnboundFact, encodePrDeliveryFact } from './pr-delivery-fact.js';
|
|
10
9
|
import { CANDIDATE_COLUMNS, CONSTRAINT_COLUMNS, parseTaskQualification } from './qualification-audit.js';
|
|
11
10
|
import { enumerateAllTaskDirs } from './resolve-ref.js';
|
|
12
11
|
import { parseTaskFrontmatter } from './frontmatter.js';
|
|
13
12
|
import { AGENT_TOKEN_VALUES } from '../agent-clients/tokens.js';
|
|
13
|
+
import { resolveProjectTaskWorkspaceRoot } from './workspace-root.js';
|
|
14
14
|
const TYPES = ['feature', 'bugfix', 'refactor', 'docs', 'chore'];
|
|
15
15
|
const PRIORITIES = ['Urgent', 'High', 'Medium', 'Low'];
|
|
16
16
|
const EFFORTS = ['High', 'Medium', 'Low'];
|
|
@@ -295,49 +295,6 @@ function ensureRealDirectory(directory, code) {
|
|
|
295
295
|
}
|
|
296
296
|
fs.mkdirSync(directory, { mode: 0o700 });
|
|
297
297
|
}
|
|
298
|
-
function createLockRoot(project) {
|
|
299
|
-
const root = path.join(os.homedir(), '.agent-infra');
|
|
300
|
-
const directories = [root, path.join(root, 'run'), path.join(root, 'run', project), path.join(root, 'run', project, 'task-create-locks')];
|
|
301
|
-
for (const directory of directories) {
|
|
302
|
-
if (fs.existsSync(directory)) {
|
|
303
|
-
assertRealDirectory(directory, 'TASK_CREATE_LOCK_FAILED');
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
try {
|
|
307
|
-
fs.mkdirSync(directory, { mode: 0o700 });
|
|
308
|
-
}
|
|
309
|
-
catch (error) {
|
|
310
|
-
if (error.code !== 'EEXIST')
|
|
311
|
-
throw error;
|
|
312
|
-
assertRealDirectory(directory, 'TASK_CREATE_LOCK_FAILED');
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
return directories.at(-1);
|
|
316
|
-
}
|
|
317
|
-
function withCreateLock(repoRoot, project, operation) {
|
|
318
|
-
const lockRoot = createLockRoot(project);
|
|
319
|
-
let callbackError;
|
|
320
|
-
try {
|
|
321
|
-
return withTaskExecutionLock(repoRoot, 'task-create', 'task-create', () => {
|
|
322
|
-
try {
|
|
323
|
-
return operation();
|
|
324
|
-
}
|
|
325
|
-
catch (error) {
|
|
326
|
-
callbackError = error;
|
|
327
|
-
throw error;
|
|
328
|
-
}
|
|
329
|
-
}, { lockRoot, identityScope: `task-create\0${project}` });
|
|
330
|
-
}
|
|
331
|
-
catch (error) {
|
|
332
|
-
if (callbackError !== undefined)
|
|
333
|
-
throw callbackError;
|
|
334
|
-
if (error instanceof TaskExecutionLockError && error.code === 'ORCHESTRATION_LOCK_BUSY') {
|
|
335
|
-
throw new Error('TASK_CREATE_LOCK_TIMEOUT');
|
|
336
|
-
}
|
|
337
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
338
|
-
throw new Error(`TASK_CREATE_LOCK_FAILED: ${message}`);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
298
|
function recoverPublishedTask(repoRoot, keyDigest, candidateDigest) {
|
|
342
299
|
for (const task of enumerateAllTaskDirs(repoRoot)) {
|
|
343
300
|
const taskMd = path.join(task.taskDir, 'task.md');
|
|
@@ -366,16 +323,24 @@ function createLocalTask(value, options) {
|
|
|
366
323
|
throw new Error('TASK_CREATE_VERSION_INVALID: agentInfraVersion must be a valid v-prefixed semver');
|
|
367
324
|
}
|
|
368
325
|
const repoRoot = fs.realpathSync.native(options.repoRoot);
|
|
369
|
-
const workspaceRoot =
|
|
326
|
+
const workspaceRoot = resolveProjectTaskWorkspaceRoot(repoRoot);
|
|
370
327
|
const activeRoot = path.join(workspaceRoot, 'active');
|
|
371
328
|
ensureRealDirectory(path.join(repoRoot, '.agents'), 'TASK_CREATE_WORKSPACE_INVALID');
|
|
329
|
+
const home = path.resolve(process.env.HOME || os.homedir());
|
|
330
|
+
const managedRoots = [path.join(home, '.agent-infra'), path.join(home, '.agent-infra', 'task-workspaces')];
|
|
331
|
+
for (const root of managedRoots) {
|
|
332
|
+
if (fs.existsSync(root))
|
|
333
|
+
assertRealDirectory(root, 'TASK_CREATE_WORKSPACE_INVALID');
|
|
334
|
+
else
|
|
335
|
+
fs.mkdirSync(root, { mode: 0o700 });
|
|
336
|
+
}
|
|
372
337
|
ensureRealDirectory(workspaceRoot, 'TASK_CREATE_WORKSPACE_INVALID');
|
|
373
338
|
ensureRealDirectory(activeRoot, 'TASK_CREATE_WORKSPACE_INVALID');
|
|
374
339
|
const projectConfig = readProject(repoRoot);
|
|
375
340
|
const canonical = canonicalTaskCreateCandidate(candidate);
|
|
376
341
|
const candidateDigest = sha256(canonical);
|
|
377
342
|
const keyDigest = sha256(candidate.idempotencyKey);
|
|
378
|
-
function
|
|
343
|
+
function createOnce() {
|
|
379
344
|
const recovered = recoverPublishedTask(repoRoot, keyDigest, candidateDigest);
|
|
380
345
|
if (recovered) {
|
|
381
346
|
return { status: 'no-op', changed: false, task: { id: recovered.taskId, shortId: recovered.shortId, state: recovered.state } };
|
|
@@ -407,25 +372,7 @@ function createLocalTask(value, options) {
|
|
|
407
372
|
throw new Error('TASK_CREATE_SHORT_ID_FAILED');
|
|
408
373
|
return { status: 'applied', changed: true, task: { id: taskId, shortId: allocated.shortId, state: 'active' } };
|
|
409
374
|
}
|
|
410
|
-
return
|
|
411
|
-
let callbackError;
|
|
412
|
-
try {
|
|
413
|
-
return withRepositoryMutationLock(repoRoot, () => {
|
|
414
|
-
try {
|
|
415
|
-
return createUnderRepositoryLock();
|
|
416
|
-
}
|
|
417
|
-
catch (error) {
|
|
418
|
-
callbackError = error;
|
|
419
|
-
throw error;
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
catch (error) {
|
|
424
|
-
if (callbackError !== undefined)
|
|
425
|
-
throw callbackError;
|
|
426
|
-
throw error;
|
|
427
|
-
}
|
|
428
|
-
});
|
|
375
|
+
return createOnce();
|
|
429
376
|
}
|
|
430
377
|
export { canonicalTaskCreateCandidate, createLocalTask, validateTaskCreateCandidate };
|
|
431
378
|
//# sourceMappingURL=create.js.map
|
|
@@ -195,7 +195,7 @@ function validateSealRequest(receipt, event) {
|
|
|
195
195
|
function validateReviewerSealPaths(receipt, changedPaths) {
|
|
196
196
|
if (receipt.role !== 'reviewer')
|
|
197
197
|
return null;
|
|
198
|
-
const taskRoot =
|
|
198
|
+
const taskRoot = `task-workspace/active/${receipt.taskId}/`;
|
|
199
199
|
const allowed = new Set([
|
|
200
200
|
`${taskRoot}${receipt.artifact}`,
|
|
201
201
|
`${taskRoot}task.md`,
|
|
@@ -5,7 +5,6 @@ import { parseTaskFrontmatter } from './frontmatter.js';
|
|
|
5
5
|
import { resolveTaskRef } from './resolve-ref.js';
|
|
6
6
|
import { resolveDeliveryTarget, validateBaseRef, validateRemote } from './delivery-target.js';
|
|
7
7
|
import { captureTaskWriteMetadata, writeTask } from './write.js';
|
|
8
|
-
import { withRepositoryMutationLock, withTaskExecutionLock } from './task-execution-lock.js';
|
|
9
8
|
function classifyDeliveryState(localHead, remoteHead, lastDelivered) {
|
|
10
9
|
if (remoteHead === null)
|
|
11
10
|
return { state: 'absent', shouldPush: true };
|
|
@@ -29,7 +28,7 @@ function validateBranch(cwd, branch) {
|
|
|
29
28
|
function failure(taskId, code, message, retryable = false, status = retryable ? 'blocked' : 'failed') {
|
|
30
29
|
return { status, changed: false, taskId, remoteHead: null, localHead: null, state: null, error: { code, message, retryable } };
|
|
31
30
|
}
|
|
32
|
-
function
|
|
31
|
+
function deliverTaskBranchCore(taskId, taskDir, repoRoot, options) {
|
|
33
32
|
let frontmatter;
|
|
34
33
|
try {
|
|
35
34
|
frontmatter = parseTaskFrontmatter(fs.readFileSync(path.join(taskDir, 'task.md'), 'utf8'));
|
|
@@ -100,12 +99,7 @@ function deliverTaskBranch(taskRef, options) {
|
|
|
100
99
|
const resolved = resolveTaskRef(taskRef, { repoRoot: options.repoRoot });
|
|
101
100
|
if (!resolved.ok)
|
|
102
101
|
return failure(resolved.taskId, resolved.code, resolved.message);
|
|
103
|
-
|
|
104
|
-
return withRepositoryMutationLock(resolved.repoRoot, () => withTaskExecutionLock(resolved.repoRoot, resolved.taskId, 'task-delivery', () => deliverUnlocked(resolved.taskId, resolved.taskDir, resolved.repoRoot, options)));
|
|
105
|
-
}
|
|
106
|
-
catch (error) {
|
|
107
|
-
return failure(resolved.taskId, 'DELIVERY_LOCK_FAILED', error instanceof Error ? error.message : String(error), true, 'blocked');
|
|
108
|
-
}
|
|
102
|
+
return deliverTaskBranchCore(resolved.taskId, resolved.taskDir, resolved.repoRoot, options);
|
|
109
103
|
}
|
|
110
104
|
export { classifyDeliveryState, deliverTaskBranch };
|
|
111
105
|
//# sourceMappingURL=delivery.js.map
|
package/dist/lib/task/events.js
CHANGED
|
@@ -15,7 +15,6 @@ import { resolveTaskRef } from './resolve-ref.js';
|
|
|
15
15
|
import { findSectionHeading } from './sections.js';
|
|
16
16
|
import { validateLifecycleExecution } from './lifecycle-execution.js';
|
|
17
17
|
import { commitOrchestrationStageCompletion } from './orchestration.js';
|
|
18
|
-
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
|
|
19
18
|
import { captureTaskWriteMetadata, writeTask } from './write.js';
|
|
20
19
|
import { validateLocalArtifact } from './local-artifact-finalization.js';
|
|
21
20
|
import { buildLifecycleFacts, canStart, effectiveReworkTarget } from './capabilities.js';
|
|
@@ -456,11 +455,11 @@ function reworkIntentMutationForCompletion(content, taskDir, family, artifact, t
|
|
|
456
455
|
}
|
|
457
456
|
return { mutation: JSON.stringify(next) === JSON.stringify(parsed.intents) ? null : reworkIntentMutation(content, next) };
|
|
458
457
|
}
|
|
459
|
-
function buildCompletionReceipt(content, taskDir, family, artifact, completedAt, frontmatter, request) {
|
|
458
|
+
function buildCompletionReceipt(content, taskDir, repositoryRoot, family, artifact, completedAt, frontmatter, request) {
|
|
460
459
|
if (!['analyze', 'plan', 'code'].includes(family) && !family.startsWith('review-'))
|
|
461
460
|
return null;
|
|
462
461
|
if (family === 'review-code') {
|
|
463
|
-
const identity = inspectReviewIdentity(taskDir, fs.readFileSync(artifact.path, 'utf8'));
|
|
462
|
+
const identity = inspectReviewIdentity(taskDir, fs.readFileSync(artifact.path, 'utf8'), repositoryRoot);
|
|
464
463
|
if (identity.status !== 'matched')
|
|
465
464
|
return { ok: false, message: `review-code identity is ${identity.status}: ${identity.message}` };
|
|
466
465
|
}
|
|
@@ -566,7 +565,7 @@ function sameCompletionFact(left, right) {
|
|
|
566
565
|
function replaceCompletionFact(facts, next) {
|
|
567
566
|
return [...facts.filter((fact) => !(fact.event === next.event && fact.output === next.output)), next];
|
|
568
567
|
}
|
|
569
|
-
function
|
|
568
|
+
function applyTaskEvent(request, options = {}) {
|
|
570
569
|
const invalid = validateTaskEventRequest(request);
|
|
571
570
|
if (invalid)
|
|
572
571
|
return failed(request, invalid);
|
|
@@ -718,7 +717,7 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
718
717
|
}
|
|
719
718
|
if (eventIdentity.phase === 'started') {
|
|
720
719
|
const trigger = eventTrigger(normalized, eventIdentity.family);
|
|
721
|
-
const facts = buildLifecycleFacts(resolved.taskDir, content, resolved.state);
|
|
720
|
+
const facts = buildLifecycleFacts(resolved.taskDir, content, resolved.state, false, resolved.repoRoot);
|
|
722
721
|
if (!facts.ok)
|
|
723
722
|
return failed(normalized, { code: 'EVENT_TRANSITION_INVALID', message: `${facts.code}: ${facts.message}` }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
724
723
|
const capability = canStart(lifecycleAction(eventIdentity.family), facts.facts, trigger);
|
|
@@ -766,7 +765,7 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
766
765
|
let currentFact = null;
|
|
767
766
|
let completionRework = null;
|
|
768
767
|
if (eventIdentity.phase === 'completed' && completedArtifact) {
|
|
769
|
-
const receipt = buildCompletionReceipt(content, resolved.taskDir, eventIdentity.family, completedArtifact, metadata.timestamp, frontmatter, normalized);
|
|
768
|
+
const receipt = buildCompletionReceipt(content, resolved.taskDir, resolved.repoRoot, eventIdentity.family, completedArtifact, metadata.timestamp, frontmatter, normalized);
|
|
770
769
|
if (receipt && !receipt.ok) {
|
|
771
770
|
return failed(normalized, { code: 'EVENT_ARTIFACT_CONFLICT', message: receipt.message }, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, fromStep: currentStep, toStep: currentStep, action: eventIdentity.action, phase: eventIdentity.phase });
|
|
772
771
|
}
|
|
@@ -938,31 +937,6 @@ function applyTaskEventUnlocked(request, options = {}) {
|
|
|
938
937
|
agentInfraVersion: result.agentInfraVersion, operations: result.operations, error: null
|
|
939
938
|
};
|
|
940
939
|
}
|
|
941
|
-
function applyTaskEvent(request, options = {}) {
|
|
942
|
-
const invalid = validateTaskEventRequest(request);
|
|
943
|
-
if (invalid)
|
|
944
|
-
return failed(request, invalid);
|
|
945
|
-
const parts = eventParts(request.event);
|
|
946
|
-
if (options.lockAlreadyHeld)
|
|
947
|
-
return applyTaskEventUnlocked(request, options);
|
|
948
|
-
if (request.dryRun || !['started', 'completed'].includes(parts.phase)) {
|
|
949
|
-
return applyTaskEventUnlocked(request, options);
|
|
950
|
-
}
|
|
951
|
-
const resolved = resolveTaskRef(request.taskRef, { repoRoot: options.repoRoot });
|
|
952
|
-
if (!resolved.ok)
|
|
953
|
-
return applyTaskEventUnlocked(request, options);
|
|
954
|
-
try {
|
|
955
|
-
return withTaskExecutionLock(resolved.repoRoot, resolved.taskId, `task-event.${request.event}`, () => applyTaskEventUnlocked(request, { ...options, lockAlreadyHeld: true }));
|
|
956
|
-
}
|
|
957
|
-
catch (error) {
|
|
958
|
-
if (!(error instanceof TaskExecutionLockError))
|
|
959
|
-
throw error;
|
|
960
|
-
return failed(request, {
|
|
961
|
-
code: 'EVENT_TRANSITION_INVALID',
|
|
962
|
-
message: `${error.code}: ${error.message}`
|
|
963
|
-
}, { taskId: resolved.taskId, taskMdPath: resolved.taskMdPath });
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
940
|
function successNoOp(request, taskId, taskMdPath, currentStep, eventIdentity, timestamp, frontmatter, artifactContext) {
|
|
967
941
|
return {
|
|
968
942
|
...failed(request, { code: 'EVENT_LOG_CONFLICT', message: '' }), status: 'no-op', error: null,
|
|
@@ -9,10 +9,9 @@ import { inspectPlatformIssue, syncPlatformIssue } from '../platform/issues.js';
|
|
|
9
9
|
import { resourceIdentityEquals } from '../platform/resource-identity.js';
|
|
10
10
|
import { parseTaskFrontmatter } from './frontmatter.js';
|
|
11
11
|
import { recoverPlatformOperations } from './platform-operation-recovery.js';
|
|
12
|
-
import { applyTaskLifecycle,
|
|
12
|
+
import { applyTaskLifecycle, inspectTaskLifecycleProgress, previewTaskCompletion } from './lifecycle.js';
|
|
13
13
|
import { enumerateAllTaskDirs, resolveTaskRef } from './resolve-ref.js';
|
|
14
14
|
import { inspectShortIdRegistry } from './short-id.js';
|
|
15
|
-
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
|
|
16
15
|
import { verifyTaskEvent } from './verification.js';
|
|
17
16
|
import { projectFinalizationWarning } from './workflow-warning-intents.js';
|
|
18
17
|
import { mergeOperationWarnings } from './operation-outcome.js';
|
|
@@ -442,7 +441,7 @@ function mutationPatch(current, mutation) {
|
|
|
442
441
|
? { warningProjection: 'done', lastError: null }
|
|
443
442
|
: { warningProjection: 'pending', lastError: mutation.error };
|
|
444
443
|
}
|
|
445
|
-
function
|
|
444
|
+
function mutateFinalizationReceipt(repoRoot, receipt, capability, mutation, consumed) {
|
|
446
445
|
if (!hasFinalizationTaskDocument(repoRoot, receipt.taskId)) {
|
|
447
446
|
throw capabilityError('FINALIZATION_SCOPE_INVALID', 'finalization capability requires an active task or a completed task');
|
|
448
447
|
}
|
|
@@ -459,7 +458,7 @@ function applyFinalizationReceiptMutation(repoRoot, receipt, capability, mutatio
|
|
|
459
458
|
if (!hasFinalizationTaskDocument(repoRoot, receipt.taskId)) {
|
|
460
459
|
throw capabilityError('FINALIZATION_SCOPE_INVALID', 'finalization capability requires an active task or a completed task');
|
|
461
460
|
}
|
|
462
|
-
return
|
|
461
|
+
return mutateFinalizationReceipt(repoRoot, receipt, capability, mutation, new Set());
|
|
463
462
|
}
|
|
464
463
|
function warningKey(warning) {
|
|
465
464
|
return `${warning.step}\0${warning.code}\0${warning.target}`;
|
|
@@ -479,14 +478,14 @@ function reconcileWarningProjection(repoRoot, taskId, receipt, consumed) {
|
|
|
479
478
|
retryable: true
|
|
480
479
|
};
|
|
481
480
|
const capability = issueCapability(receipt, 'warning-projection');
|
|
482
|
-
return
|
|
481
|
+
return mutateFinalizationReceipt(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'failed', error: detail }, consumed);
|
|
483
482
|
}
|
|
484
483
|
}
|
|
485
484
|
catch (error) {
|
|
486
485
|
const detail = errorOf(error, 'FINALIZATION_WARNING_PROJECTION_FAILED', true);
|
|
487
486
|
try {
|
|
488
487
|
const capability = issueCapability(receipt, 'warning-projection');
|
|
489
|
-
return
|
|
488
|
+
return mutateFinalizationReceipt(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'failed', error: detail }, consumed);
|
|
490
489
|
}
|
|
491
490
|
catch {
|
|
492
491
|
return receipt;
|
|
@@ -495,7 +494,7 @@ function reconcileWarningProjection(repoRoot, taskId, receipt, consumed) {
|
|
|
495
494
|
}
|
|
496
495
|
try {
|
|
497
496
|
const capability = issueCapability(receipt, 'warning-projection');
|
|
498
|
-
return
|
|
497
|
+
return mutateFinalizationReceipt(repoRoot, receipt, capability, { scope: 'warning-projection', operation: 'succeeded' }, consumed);
|
|
499
498
|
}
|
|
500
499
|
catch {
|
|
501
500
|
return receipt;
|
|
@@ -526,7 +525,7 @@ async function syncPendingTaskComment(input) {
|
|
|
526
525
|
if (result.status === 'applied' || result.status === 'no-op') {
|
|
527
526
|
const skipped = result.error?.code === 'ISSUE_NOT_LINKED';
|
|
528
527
|
const capability = issueCapability(receipt, 'task-comment');
|
|
529
|
-
receipt =
|
|
528
|
+
receipt = mutateFinalizationReceipt(repoRoot, receipt, capability, {
|
|
530
529
|
scope: 'task-comment', operation: 'succeeded', state: skipped ? 'skipped' : 'done'
|
|
531
530
|
}, consumedCapabilities);
|
|
532
531
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
@@ -542,7 +541,7 @@ async function syncPendingTaskComment(input) {
|
|
|
542
541
|
}
|
|
543
542
|
const detail = step.error ?? { code: 'COMMENT_SYNC_FAILED', message: 'task comment synchronization failed', retryable: true };
|
|
544
543
|
const capability = issueCapability(receipt, 'task-comment');
|
|
545
|
-
receipt =
|
|
544
|
+
receipt = mutateFinalizationReceipt(repoRoot, receipt, capability, {
|
|
546
545
|
scope: 'task-comment', operation: 'failed', error: detail
|
|
547
546
|
}, consumedCapabilities);
|
|
548
547
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
@@ -552,7 +551,7 @@ async function syncPendingTaskComment(input) {
|
|
|
552
551
|
const detail = errorOf(error, 'COMMENT_SYNC_FAILED', true);
|
|
553
552
|
try {
|
|
554
553
|
const capability = issueCapability(receipt, 'task-comment');
|
|
555
|
-
receipt =
|
|
554
|
+
receipt = mutateFinalizationReceipt(repoRoot, receipt, capability, {
|
|
556
555
|
scope: 'task-comment', operation: 'failed', error: detail
|
|
557
556
|
}, consumedCapabilities);
|
|
558
557
|
receipt = reconcileWarningProjection(repoRoot, taskId, receipt, consumedCapabilities);
|
|
@@ -682,9 +681,9 @@ function preparedResult(taskId, receipt, steps, changed) {
|
|
|
682
681
|
result: 'prepared', warnings: openWarnings(receipt), error: null
|
|
683
682
|
};
|
|
684
683
|
}
|
|
685
|
-
async function
|
|
684
|
+
async function prepareTaskFinalizationCore(request, taskId, options) {
|
|
686
685
|
const repoRoot = path.resolve(options.repoRoot);
|
|
687
|
-
const lifecycle = options.lifecycle ?? ((lifecycleRequest, lifecycleOptions) => (
|
|
686
|
+
const lifecycle = options.lifecycle ?? ((lifecycleRequest, lifecycleOptions) => (applyTaskLifecycle(lifecycleRequest, lifecycleOptions ?? { repoRoot })));
|
|
688
687
|
const backfill = options.backfill ?? backfillCompletionComments;
|
|
689
688
|
const commentSync = options.commentSync ?? syncPlatformComment;
|
|
690
689
|
const issueSync = options.issueSync ?? syncPlatformIssue;
|
|
@@ -966,12 +965,10 @@ async function prepareTaskFinalization(request, options) {
|
|
|
966
965
|
if (!resolved.ok)
|
|
967
966
|
return failed(resolved.taskId, { code: resolved.code, message: resolved.message, retryable: false });
|
|
968
967
|
try {
|
|
969
|
-
return await
|
|
968
|
+
return await prepareTaskFinalizationCore(request, resolved.taskId, options);
|
|
970
969
|
}
|
|
971
970
|
catch (error) {
|
|
972
|
-
const detail = error
|
|
973
|
-
? { code: error.code, message: error.message, retryable: error.code === 'ORCHESTRATION_LOCK_BUSY' }
|
|
974
|
-
: errorOf(error, 'TASK_FINALIZATION_FAILED');
|
|
971
|
+
const detail = errorOf(error, 'TASK_FINALIZATION_FAILED');
|
|
975
972
|
return failed(resolved.taskId, detail);
|
|
976
973
|
}
|
|
977
974
|
}
|
|
@@ -984,7 +981,7 @@ async function commitPreparedTaskFinalization(request, options) {
|
|
|
984
981
|
if (!resolved.ok)
|
|
985
982
|
return failed(resolved.taskId, { code: resolved.code, message: resolved.message, retryable: false });
|
|
986
983
|
try {
|
|
987
|
-
return await
|
|
984
|
+
return await (async () => {
|
|
988
985
|
if (options.controlBinding && options.manifestPath) {
|
|
989
986
|
try {
|
|
990
987
|
const manifest = readSandboxControlManifest(options.manifestPath);
|
|
@@ -1051,7 +1048,7 @@ async function commitPreparedTaskFinalization(request, options) {
|
|
|
1051
1048
|
};
|
|
1052
1049
|
const result = options.lifecycle
|
|
1053
1050
|
? options.lifecycle(lifecycleRequest, lifecycleOptions)
|
|
1054
|
-
:
|
|
1051
|
+
: applyTaskLifecycle(lifecycleRequest, lifecycleOptions);
|
|
1055
1052
|
const step = lifecycleStep(result);
|
|
1056
1053
|
if (result.status !== 'applied' && result.status !== 'no-op') {
|
|
1057
1054
|
const updated = updateReceipt(repoRoot, receipt, { lifecycle: 'pending', lastError: step.error });
|
|
@@ -1131,12 +1128,10 @@ async function commitPreparedTaskFinalization(request, options) {
|
|
|
1131
1128
|
});
|
|
1132
1129
|
}
|
|
1133
1130
|
return terminalResult(resolved.taskId, updated, { lifecycle: step, verification }, result.changed, detail);
|
|
1134
|
-
});
|
|
1131
|
+
})();
|
|
1135
1132
|
}
|
|
1136
1133
|
catch (error) {
|
|
1137
|
-
const detail = error
|
|
1138
|
-
? { code: error.code, message: error.message, retryable: error.code === 'ORCHESTRATION_LOCK_BUSY' }
|
|
1139
|
-
: errorOf(error, 'TASK_FINALIZATION_FAILED');
|
|
1134
|
+
const detail = errorOf(error, 'TASK_FINALIZATION_FAILED');
|
|
1140
1135
|
return failed(resolved.taskId, detail);
|
|
1141
1136
|
}
|
|
1142
1137
|
}
|